@remotion/studio 4.0.520 → 4.0.522

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (117) hide show
  1. package/dist/api/shut-down-studio.d.ts +6 -0
  2. package/dist/api/shut-down-studio.js +23 -0
  3. package/dist/components/AudioWaveform.js +10 -6
  4. package/dist/components/Canvas.js +84 -12
  5. package/dist/components/CanvasIfSizeIsAvailable.js +7 -0
  6. package/dist/components/CaptionInspector.d.ts +1 -0
  7. package/dist/components/CaptionInspector.js +43 -2
  8. package/dist/components/CaptionTextEditor.js +1 -1
  9. package/dist/components/CompositionSelector.js +41 -30
  10. package/dist/components/CompositionSelectorItem.d.ts +7 -0
  11. package/dist/components/CompositionSelectorItem.js +343 -67
  12. package/dist/components/CopyButton.js +7 -14
  13. package/dist/components/Editor.js +6 -5
  14. package/dist/components/EditorContent.js +1 -1
  15. package/dist/components/ElementInstallConfirmation.js +77 -65
  16. package/dist/components/ElementLibraryModal.js +3 -1
  17. package/dist/components/FixComputedValueModal.js +20 -10
  18. package/dist/components/InlineCaptionInspector.js +37 -1
  19. package/dist/components/InspectorLocationCopy.js +10 -5
  20. package/dist/components/InspectorPanel/ElementLibraryButton.js +3 -18
  21. package/dist/components/InspectorSequenceSection.js +1 -4
  22. package/dist/components/Menu/MenuSubItem.js +1 -1
  23. package/dist/components/MenuBuildIndicator.js +7 -2
  24. package/dist/components/MenuCompositionName.js +62 -6
  25. package/dist/components/ModalContainer.d.ts +1 -0
  26. package/dist/components/ModalContainer.js +2 -2
  27. package/dist/components/ModalHeader.js +5 -1
  28. package/dist/components/QuickSwitcher/asset-search.d.ts +0 -1
  29. package/dist/components/QuickSwitcher/asset-search.js +1 -16
  30. package/dist/components/RenderButton.js +2 -2
  31. package/dist/components/RenderModal/CliCopyButton.js +13 -27
  32. package/dist/components/RenderModal/RenderStatusModal.js +7 -1
  33. package/dist/components/RenderModal/ServerRenderModal.js +1 -1
  34. package/dist/components/RenderModal/WebRenderModal.js +1 -1
  35. package/dist/components/RenderQueue/ClientRenderQueueProcessor.js +1 -1
  36. package/dist/components/RenderQueue/RenderQueueCopyToClipboard.js +7 -4
  37. package/dist/components/SettingsModal.js +8 -5
  38. package/dist/components/SidebarCollapserControls.js +11 -5
  39. package/dist/components/SkillsSettings.js +9 -5
  40. package/dist/components/Splitter/SplitterContainer.js +63 -10
  41. package/dist/components/Splitter/SplitterContext.d.ts +3 -0
  42. package/dist/components/Splitter/SplitterContext.js +5 -1
  43. package/dist/components/Splitter/SplitterElement.js +11 -2
  44. package/dist/components/Splitter/SplitterHandle.d.ts +1 -0
  45. package/dist/components/Splitter/SplitterHandle.js +55 -25
  46. package/dist/components/TimeValue.js +36 -7
  47. package/dist/components/Timeline/SubscribeToNodePaths.d.ts +2 -1
  48. package/dist/components/Timeline/SubscribeToNodePaths.js +2 -1
  49. package/dist/components/Timeline/Timeline.d.ts +1 -1
  50. package/dist/components/Timeline/Timeline.js +45 -22
  51. package/dist/components/Timeline/TimelineAssetField.d.ts +0 -1
  52. package/dist/components/Timeline/TimelineAssetField.js +16 -9
  53. package/dist/components/Timeline/TimelineCollapseToggle.js +1 -1
  54. package/dist/components/Timeline/TimelineDragHandler.js +9 -4
  55. package/dist/components/Timeline/TimelineFontWeightField.d.ts +11 -0
  56. package/dist/components/Timeline/TimelineFontWeightField.js +65 -0
  57. package/dist/components/Timeline/TimelineLayerChildren.d.ts +21 -0
  58. package/dist/components/Timeline/TimelineLayerChildren.js +129 -0
  59. package/dist/components/Timeline/TimelineNumberField.js +13 -5
  60. package/dist/components/Timeline/TimelinePinchZoom.js +6 -30
  61. package/dist/components/Timeline/TimelinePlayCursorSyncer.js +1 -7
  62. package/dist/components/Timeline/TimelinePrimitiveFieldValue.js +4 -0
  63. package/dist/components/Timeline/TimelineSequence.js +113 -42
  64. package/dist/components/Timeline/TimelineSequenceItem.js +14 -2
  65. package/dist/components/Timeline/TimelineSequenceRightEdgeDragHandle.d.ts +13 -3
  66. package/dist/components/Timeline/TimelineSequenceRightEdgeDragHandle.js +185 -126
  67. package/dist/components/Timeline/TimelineSlider.js +1 -4
  68. package/dist/components/Timeline/TimelineTickFormatProvider.d.ts +8 -0
  69. package/dist/components/Timeline/TimelineTickFormatProvider.js +16 -0
  70. package/dist/components/Timeline/TimelineTimeIndicators.js +7 -3
  71. package/dist/components/Timeline/TimelineVideoInfo.js +7 -3
  72. package/dist/components/Timeline/TimelineWidthProvider.js +2 -5
  73. package/dist/components/Timeline/TimelineZoomControls.js +20 -20
  74. package/dist/components/Timeline/get-sequence-split-menu-item.d.ts +11 -0
  75. package/dist/components/Timeline/get-sequence-split-menu-item.js +55 -0
  76. package/dist/components/Timeline/timeline-field-display-utils.js +1 -0
  77. package/dist/components/Timeline/use-sequence-props-subscription.d.ts +3 -2
  78. package/dist/components/Timeline/use-sequence-props-subscription.js +4 -10
  79. package/dist/components/TopPanel.js +3 -19
  80. package/dist/components/UpdateStatusContext.d.ts +5 -0
  81. package/dist/components/UpdateStatusContext.js +53 -2
  82. package/dist/components/UpdatesSettings.js +34 -9
  83. package/dist/components/WebMcp.js +26 -0
  84. package/dist/components/ZoomPersistor.js +6 -3
  85. package/dist/components/composition-menu-items.js +1 -1
  86. package/dist/components/composition-selector-drag-data.d.ts +27 -0
  87. package/dist/components/composition-selector-drag-data.js +80 -0
  88. package/dist/components/import-assets.d.ts +2 -1
  89. package/dist/components/import-assets.js +11 -1
  90. package/dist/components/parse-caption-file.d.ts +5 -0
  91. package/dist/components/parse-caption-file.js +63 -0
  92. package/dist/esm/{chunk-np6q13k5.js → chunk-3netyjd9.js} +7943 -6314
  93. package/dist/esm/index.mjs +23 -8
  94. package/dist/esm/internals.mjs +7965 -6336
  95. package/dist/esm/previewEntry.mjs +8007 -6378
  96. package/dist/esm/renderEntry.mjs +1 -1
  97. package/dist/helpers/copy-text.js +1 -2
  98. package/dist/helpers/get-preview-file-type.js +22 -3
  99. package/dist/helpers/inserted-element-selection.d.ts +2 -1
  100. package/dist/helpers/use-copy-feedback.d.ts +4 -0
  101. package/dist/helpers/use-copy-feedback.js +19 -0
  102. package/dist/helpers/use-menu-structure.js +2 -2
  103. package/dist/icons/copy.d.ts +5 -0
  104. package/dist/icons/copy.js +12 -0
  105. package/dist/index.d.ts +1 -0
  106. package/dist/index.js +3 -1
  107. package/dist/state/canvas-ref.d.ts +1 -0
  108. package/dist/state/canvas-ref.js +2 -1
  109. package/dist/state/modals.d.ts +0 -2
  110. package/dist/state/sidebar.d.ts +3 -0
  111. package/dist/state/sidebar.js +6 -1
  112. package/dist/state/timeline-zoom.d.ts +1 -1
  113. package/dist/state/timeline-zoom.js +3 -3
  114. package/dist/visual-controls/VisualControls.js +4 -0
  115. package/package.json +16 -16
  116. package/dist/helpers/use-max-media-duration.d.ts +0 -2
  117. package/dist/helpers/use-max-media-duration.js +0 -61
@@ -44,6 +44,7 @@ const TimeValue_1 = require("../TimeValue");
44
44
  const timeline_refs_1 = require("./timeline-refs");
45
45
  const timeline_scroll_logic_1 = require("./timeline-scroll-logic");
46
46
  const TimelineSelection_1 = require("./TimelineSelection");
47
+ const TimelineTickFormatProvider_1 = require("./TimelineTickFormatProvider");
47
48
  const TimelineWidthProvider_1 = require("./TimelineWidthProvider");
48
49
  exports.TIMELINE_TIME_INDICATOR_HEIGHT = 39;
49
50
  const container = {
@@ -190,6 +191,7 @@ const TimelineTimeIndicators = () => {
190
191
  exports.TimelineTimeIndicators = TimelineTimeIndicators;
191
192
  const TimelineTimeIndicatorsInner = react_1.default.memo(({ windowWidth, durationInFrames, fps }) => {
192
193
  const canvasRef = (0, react_1.useRef)(null);
194
+ const { showFrames } = (0, react_1.useContext)(TimelineTickFormatProvider_1.TimelineTickFormatContext);
193
195
  (0, react_1.useLayoutEffect)(() => {
194
196
  const canvas = canvasRef.current;
195
197
  const scrollable = timeline_refs_1.scrollableRef.current;
@@ -201,7 +203,9 @@ const TimelineTimeIndicatorsInner = react_1.default.memo(({ windowWidth, duratio
201
203
  return;
202
204
  }
203
205
  const frameInterval = (0, timeline_scroll_logic_1.getFrameIncrementFromWidth)(durationInFrames, windowWidth);
204
- const maxTickLabelWidth = (0, render_frame_1.renderFrame)(durationInFrames - 1, fps).length *
206
+ const maxTickLabelWidth = (showFrames
207
+ ? `${durationInFrames - 1}f`
208
+ : (0, render_frame_1.renderFrame)(durationInFrames - 1, fps)).length *
205
209
  TICK_LABEL_FONT_SIZE *
206
210
  0.6;
207
211
  const tickScale = (0, exports.getTimelineTickScale)({
@@ -242,7 +246,7 @@ const TimelineTimeIndicatorsInner = react_1.default.memo(({ windowWidth, duratio
242
246
  context.fillStyle = colors_1.LIGHT_TEXT;
243
247
  context.font = `${TICK_LABEL_FONT_SIZE}px ${getComputedStyle(canvas).fontFamily}`;
244
248
  context.textBaseline = 'top';
245
- context.fillText((0, render_frame_1.renderFrame)(frame, fps), xForFrame(frame) + TICK_LABEL_MARGIN_LEFT, 7);
249
+ context.fillText(showFrames ? `${Math.round(frame)}f` : (0, render_frame_1.renderFrame)(frame, fps), xForFrame(frame) + TICK_LABEL_MARGIN_LEFT, 7);
246
250
  context.fillStyle = colors_1.WHITE_ALPHA_15;
247
251
  }
248
252
  }
@@ -286,7 +290,7 @@ const TimelineTimeIndicatorsInner = react_1.default.memo(({ windowWidth, duratio
286
290
  scrollable.removeEventListener('scroll', onScroll);
287
291
  resizeObserver.disconnect();
288
292
  };
289
- }, [durationInFrames, fps, windowWidth]);
293
+ }, [durationInFrames, fps, showFrames, windowWidth]);
290
294
  const style = (0, react_1.useMemo)(() => {
291
295
  return {
292
296
  ...container,
@@ -53,6 +53,7 @@ const filmstripContainerStyle = {
53
53
  height: timeline_layout_1.TIMELINE_LAYER_FILMSTRIP_HEIGHT,
54
54
  backgroundColor: colors_1.BLACK_ALPHA_30,
55
55
  display: 'flex',
56
+ overflow: 'hidden',
56
57
  borderTopLeftRadius: 2,
57
58
  fontSize: 10,
58
59
  fontFamily: 'Arial, Helvetica',
@@ -86,8 +87,8 @@ const TimelineVideoInfoSegment = ({ src, visualizationWidth, startMediaFrom, med
86
87
  const canvas = document.createElement('canvas');
87
88
  canvas.width = Math.ceil(visualizationWidth * pixelRatio);
88
89
  canvas.height = Math.ceil(timeline_layout_1.TIMELINE_LAYER_FILMSTRIP_HEIGHT * pixelRatio);
89
- canvas.style.width = visualizationWidth + 'px';
90
- canvas.style.height = timeline_layout_1.TIMELINE_LAYER_FILMSTRIP_HEIGHT + 'px';
90
+ canvas.style.width = canvas.width / pixelRatio + 'px';
91
+ canvas.style.height = canvas.height / pixelRatio + 'px';
91
92
  const ctx = canvas.getContext('2d');
92
93
  if (!ctx) {
93
94
  return;
@@ -194,7 +195,10 @@ const TimelineVideoInfoSegment = ({ src, visualizationWidth, startMediaFrom, med
194
195
  // desired-timestamp -> filled-timestamp
195
196
  const filledSlots = new Map();
196
197
  const { fromSeconds, toSeconds } = times;
197
- const targetWidth = targetCanvas.width;
198
+ // Keep the time-to-pixel scale independent of the integer canvas backing size.
199
+ const targetWidth = tiledLoop
200
+ ? tiledLoop.loopWidth * pixelRatio
201
+ : visualizationWidth * pixelRatio;
198
202
  const repeatTarget = () => {
199
203
  if (!tiledLoop) {
200
204
  return;
@@ -15,7 +15,6 @@ const TimelineWidthProvider = ({ children }) => {
15
15
  shouldApplyCssTransforms: true,
16
16
  });
17
17
  const { zoom: zoomMap } = (0, react_1.useContext)(timeline_zoom_1.TimelineZoomCtx);
18
- const { canvasContent } = (0, react_1.useContext)(remotion_1.Internals.CompositionManager);
19
18
  const videoConfig = remotion_1.Internals.useUnsafeVideoConfig();
20
19
  const width = (0, react_1.useMemo)(() => {
21
20
  var _a, _b;
@@ -28,12 +27,10 @@ const TimelineWidthProvider = ({ children }) => {
28
27
  const zoom = (0, get_timeline_max_zoom_1.getTimelineZoom)({
29
28
  durationInFrames,
30
29
  timelineViewportWidth: scrollableWidth,
31
- zoom: (canvasContent === null || canvasContent === void 0 ? void 0 : canvasContent.type) === 'composition'
32
- ? ((_f = zoomMap[canvasContent.compositionId]) !== null && _f !== void 0 ? _f : null)
33
- : null,
30
+ zoom: videoConfig ? ((_f = zoomMap[videoConfig.id]) !== null && _f !== void 0 ? _f : null) : null,
34
31
  });
35
32
  return (0, get_timeline_max_zoom_1.getTimelineWidth)({ durationInFrames, zoom });
36
- }, [canvasContent, size === null || size === void 0 ? void 0 : size.width, videoConfig === null || videoConfig === void 0 ? void 0 : videoConfig.durationInFrames, zoomMap]);
33
+ }, [size === null || size === void 0 ? void 0 : size.width, videoConfig, zoomMap]);
37
34
  return (jsx_runtime_1.jsx(exports.TimelineWidthContext.Provider, { value: width, children: children }));
38
35
  };
39
36
  exports.TimelineWidthProvider = TimelineWidthProvider;
@@ -59,32 +59,29 @@ const buttonStyle = {
59
59
  };
60
60
  const TimelineZoomSlider = ({ maxWidth, minZoom, timelineViewportWidth }) => {
61
61
  var _a, _b;
62
- const { canvasContent } = (0, react_1.useContext)(remotion_1.Internals.CompositionManager);
63
62
  const { setZoom, zoom: zoomMap } = (0, react_1.useContext)(timeline_zoom_1.TimelineZoomCtx);
64
63
  const videoConfig = remotion_1.Internals.useUnsafeVideoConfig();
65
64
  const { tabIndex } = (0, z_index_1.useZIndex)();
66
- const isStill = (0, is_current_selected_still_1.useIsStill)();
65
+ const isVideoComposition = (0, is_current_selected_still_1.useIsVideoComposition)();
67
66
  const onChange = (0, react_1.useCallback)((e) => {
68
- if (canvasContent === null || canvasContent.type !== 'composition') {
67
+ if (videoConfig === null) {
69
68
  return;
70
69
  }
71
- setZoom(canvasContent.compositionId, () => (0, get_timeline_max_zoom_1.sliderValueToTimelineZoom)({
70
+ setZoom(videoConfig.id, () => (0, get_timeline_max_zoom_1.sliderValueToTimelineZoom)({
72
71
  sliderValue: Number(e.target.value),
73
72
  minZoom,
74
73
  }), {
75
74
  anchorFrame: null,
76
75
  anchorContentX: null,
77
76
  });
78
- }, [canvasContent, minZoom, setZoom]);
79
- if (isStill ||
80
- canvasContent === null ||
81
- canvasContent.type !== 'composition') {
77
+ }, [minZoom, setZoom, videoConfig]);
78
+ if (!isVideoComposition || videoConfig === null) {
82
79
  return null;
83
80
  }
84
81
  const zoom = (0, get_timeline_max_zoom_1.getTimelineZoom)({
85
82
  durationInFrames: (_a = videoConfig === null || videoConfig === void 0 ? void 0 : videoConfig.durationInFrames) !== null && _a !== void 0 ? _a : 1,
86
83
  timelineViewportWidth,
87
- zoom: (_b = zoomMap[canvasContent.compositionId]) !== null && _b !== void 0 ? _b : null,
84
+ zoom: (_b = zoomMap[videoConfig.id]) !== null && _b !== void 0 ? _b : null,
88
85
  });
89
86
  const roundedZoom = Math.round(zoom * 100) / 100;
90
87
  return (jsx_runtime_1.jsx("input", { style: maxWidth === undefined ? undefined : { maxWidth }, title: `Timeline zoom (${roundedZoom}px/frame)`, alt: `Timeline zoom (${roundedZoom}px/frame)`, type: "range", min: get_timeline_max_zoom_1.TIMELINE_ZOOM_SLIDER_PROPS.min, max: get_timeline_max_zoom_1.TIMELINE_ZOOM_SLIDER_PROPS.max, step: get_timeline_max_zoom_1.TIMELINE_ZOOM_SLIDER_PROPS.step, value: (0, get_timeline_max_zoom_1.timelineZoomToSliderValue)({ zoom, minZoom }), onChange: onChange, className: "__remotion-timeline-slider", tabIndex: tabIndex }));
@@ -92,7 +89,6 @@ const TimelineZoomSlider = ({ maxWidth, minZoom, timelineViewportWidth }) => {
92
89
  const TimelineZoomControlsInner = ({ sliderMaxWidth }) => {
93
90
  var _a;
94
91
  var _b, _c, _d;
95
- const { canvasContent } = (0, react_1.useContext)(remotion_1.Internals.CompositionManager);
96
92
  const { setZoom } = (0, react_1.useContext)(timeline_zoom_1.TimelineZoomCtx);
97
93
  const videoConfig = remotion_1.Internals.useUnsafeVideoConfig();
98
94
  const timelineSize = player_1.PlayerInternals.useElementSize(timeline_refs_1.scrollableRef, {
@@ -105,21 +101,25 @@ const TimelineZoomControlsInner = ({ sliderMaxWidth }) => {
105
101
  timelineViewportWidth,
106
102
  });
107
103
  const onMinusClicked = (0, react_1.useCallback)(() => {
108
- if (canvasContent === null || canvasContent.type !== 'composition') {
104
+ if (videoConfig === null) {
109
105
  return;
110
106
  }
111
- setZoom(canvasContent.compositionId, (z) => z / TIMELINE_ZOOM_BUTTON_FACTOR, { anchorFrame: null, anchorContentX: null });
112
- }, [canvasContent, setZoom]);
107
+ setZoom(videoConfig.id, (z) => z / TIMELINE_ZOOM_BUTTON_FACTOR, {
108
+ anchorFrame: null,
109
+ anchorContentX: null,
110
+ });
111
+ }, [setZoom, videoConfig]);
113
112
  const onPlusClicked = (0, react_1.useCallback)(() => {
114
- if (canvasContent === null || canvasContent.type !== 'composition') {
113
+ if (videoConfig === null) {
115
114
  return;
116
115
  }
117
- setZoom(canvasContent.compositionId, (z) => z * TIMELINE_ZOOM_BUTTON_FACTOR, { anchorFrame: null, anchorContentX: null });
118
- }, [canvasContent, setZoom]);
119
- const isStill = (0, is_current_selected_still_1.useIsStill)();
120
- if (isStill ||
121
- canvasContent === null ||
122
- canvasContent.type !== 'composition') {
116
+ setZoom(videoConfig.id, (z) => z * TIMELINE_ZOOM_BUTTON_FACTOR, {
117
+ anchorFrame: null,
118
+ anchorContentX: null,
119
+ });
120
+ }, [setZoom, videoConfig]);
121
+ const isVideoComposition = (0, is_current_selected_still_1.useIsVideoComposition)();
122
+ if (!isVideoComposition || videoConfig === null) {
123
123
  return null;
124
124
  }
125
125
  return (jsx_runtime_1.jsxs("div", { style: container, children: [
@@ -0,0 +1,11 @@
1
+ import type { CanUpdateSequencePropStatus, TSequence } from 'remotion';
2
+ import type { SequenceNodePathInfo } from '../../helpers/get-timeline-sequence-sort-key';
3
+ import type { ComboboxValue } from '../NewComposition/ComboBox';
4
+ export declare const getSequenceSplitMenuItem: ({ nodePathInfo, sequence, propStatuses, splitFrame, canEditSource, hasMultipleSelection, }: {
5
+ readonly nodePathInfo: SequenceNodePathInfo | null;
6
+ readonly sequence: TSequence;
7
+ readonly propStatuses: Record<string, CanUpdateSequencePropStatus> | undefined;
8
+ readonly splitFrame: number;
9
+ readonly canEditSource: boolean;
10
+ readonly hasMultipleSelection: boolean;
11
+ }) => ComboboxValue | null;
@@ -0,0 +1,55 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.getSequenceSplitMenuItem = void 0;
4
+ const jsx_runtime_1 = require("react/jsx-runtime");
5
+ const split_selected_timeline_item_1 = require("./split-selected-timeline-item");
6
+ const getSequenceSplitMenuItem = ({ nodePathInfo, sequence, propStatuses, splitFrame, canEditSource, hasMultipleSelection, }) => {
7
+ if (hasMultipleSelection) {
8
+ return null;
9
+ }
10
+ const eligibility = nodePathInfo
11
+ ? (0, split_selected_timeline_item_1.getTimelineSequenceSplitEligibility)({
12
+ selection: { type: 'sequence', nodePathInfo },
13
+ sequence,
14
+ propStatuses,
15
+ splitFrame,
16
+ })
17
+ : {
18
+ canSplit: false,
19
+ reason: 'Sequence has no editable source node',
20
+ };
21
+ const disabledReason = !canEditSource
22
+ ? 'Sequence source is unavailable'
23
+ : propStatuses === undefined
24
+ ? 'Waiting for sequence prop status'
25
+ : eligibility.canSplit
26
+ ? null
27
+ : eligibility.reason;
28
+ return {
29
+ type: 'item',
30
+ id: 'split-sequence',
31
+ label: (jsx_runtime_1.jsx("span", { style: {
32
+ fontFamily: 'inherit',
33
+ fontSize: 'inherit',
34
+ lineHeight: 'inherit',
35
+ color: 'inherit',
36
+ }, title: disabledReason !== null && disabledReason !== void 0 ? disabledReason : 'Split at the playhead', children: "Split clip" })),
37
+ value: 'split-sequence',
38
+ keyHint: null,
39
+ leftItem: null,
40
+ quickSwitcherLabel: null,
41
+ subMenu: null,
42
+ disabled: disabledReason !== null,
43
+ onClick: () => {
44
+ if (disabledReason !== null || !eligibility.canSplit) {
45
+ return;
46
+ }
47
+ // Keep the frame used to enable the menu item, even during playback.
48
+ (0, split_selected_timeline_item_1.splitTimelineSequenceFromSource)({
49
+ nodePathInfo: eligibility.nodePathInfo,
50
+ splitFrame,
51
+ }).catch(() => undefined);
52
+ },
53
+ };
54
+ };
55
+ exports.getSequenceSplitMenuItem = getSequenceSplitMenuItem;
@@ -243,6 +243,7 @@ const formatTimelineFieldValueForDisplay = ({ fieldSchema, value, }) => {
243
243
  case 'color':
244
244
  case 'enum':
245
245
  case 'font-family':
246
+ case 'font-weight':
246
247
  case 'hidden':
247
248
  return formatUnknownTimelineValueForDisplay(value);
248
249
  default:
@@ -1,6 +1,6 @@
1
- import type { InteractivitySchema } from 'remotion';
1
+ import type { InteractivitySchema, VideoConfigValues } from 'remotion';
2
2
  import type { OriginalPosition } from '../../error-overlay/react-overlay/utils/get-source-map';
3
- export declare const useSequencePropsSubscription: ({ originalLocation, overrideId, componentIdentity, schema, effects, preferMappedNodePath, stack, }: {
3
+ export declare const useSequencePropsSubscription: ({ originalLocation, overrideId, componentIdentity, schema, effects, preferMappedNodePath, stack, videoConfigValues, }: {
4
4
  overrideId: string;
5
5
  componentIdentity: string | null;
6
6
  schema: InteractivitySchema;
@@ -8,4 +8,5 @@ export declare const useSequencePropsSubscription: ({ originalLocation, override
8
8
  originalLocation: OriginalPosition | null;
9
9
  preferMappedNodePath: boolean;
10
10
  stack: string | null;
11
+ videoConfigValues: VideoConfigValues | null;
11
12
  }) => void;
@@ -8,7 +8,7 @@ const client_id_1 = require("../../helpers/client-id");
8
8
  const ExpandedTracksProvider_1 = require("../ExpandedTracksProvider");
9
9
  const sequence_props_subscription_store_1 = require("./sequence-props-subscription-store");
10
10
  const should_subscribe_to_source_file_1 = require("./should-subscribe-to-source-file");
11
- const useSequencePropsSubscription = ({ originalLocation, overrideId, componentIdentity, schema, effects, preferMappedNodePath, stack, }) => {
11
+ const useSequencePropsSubscription = ({ originalLocation, overrideId, componentIdentity, schema, effects, preferMappedNodePath, stack, videoConfigValues, }) => {
12
12
  var _a, _b, _c;
13
13
  const { setPropStatuses } = (0, react_1.useContext)(remotion_1.Internals.VisualModeSettersContext);
14
14
  const { setOverrideIdToNodePath } = (0, react_1.useContext)(remotion_1.Internals.OverrideIdsToNodePathsSettersContext);
@@ -20,7 +20,6 @@ const useSequencePropsSubscription = ({ originalLocation, overrideId, componentI
20
20
  const overrideIdToNodePathMappingsRef = (0, react_1.useRef)(overrideIdToNodePathMappings);
21
21
  overrideIdToNodePathMappingsRef.current = overrideIdToNodePathMappings;
22
22
  const clientId = state.type === 'connected' ? state.clientId : undefined;
23
- const videoConfig = remotion_1.Internals.useUnsafeVideoConfig();
24
23
  const effectsSignature = (0, react_1.useMemo)(() => effects.map((effect) => (0, studio_shared_1.getAllSchemaKeys)(effect).join('\0')).join('\0\0'), [effects]);
25
24
  const validatedLocation = (0, react_1.useMemo)(() => {
26
25
  var _a;
@@ -51,7 +50,7 @@ const useSequencePropsSubscription = ({ originalLocation, overrideId, componentI
51
50
  !locationLine ||
52
51
  locationColumn === null ||
53
52
  !schema ||
54
- videoConfig === null) {
53
+ videoConfigValues === null) {
55
54
  return;
56
55
  }
57
56
  const nodePathAtResubscribe = (_a = overrideIdToNodePathMappingsRef.current[overrideId]) !== null && _a !== void 0 ? _a : null;
@@ -67,12 +66,7 @@ const useSequencePropsSubscription = ({ originalLocation, overrideId, componentI
67
66
  : null,
68
67
  clientId,
69
68
  stack,
70
- videoConfigValues: {
71
- durationInFrames: videoConfig.durationInFrames,
72
- fps: videoConfig.fps,
73
- height: videoConfig.height,
74
- width: videoConfig.width,
75
- },
69
+ videoConfigValues,
76
70
  applyOnce: (result) => {
77
71
  if (!result.success) {
78
72
  return;
@@ -119,7 +113,7 @@ const useSequencePropsSubscription = ({ originalLocation, overrideId, componentI
119
113
  setPropStatuses,
120
114
  setOverrideIdToNodePath,
121
115
  stack,
122
- videoConfig,
116
+ videoConfigValues,
123
117
  ]);
124
118
  };
125
119
  exports.useSequencePropsSubscription = useSequencePropsSubscription;
@@ -35,7 +35,6 @@ var __importStar = (this && this.__importStar) || (function () {
35
35
  Object.defineProperty(exports, "__esModule", { value: true });
36
36
  exports.TopPanel = exports.useResponsiveSidebarStatus = void 0;
37
37
  const jsx_runtime_1 = require("react/jsx-runtime");
38
- const player_1 = require("@remotion/player");
39
38
  const react_1 = __importStar(require("react"));
40
39
  const remotion_1 = require("remotion");
41
40
  const mobile_layout_1 = require("../helpers/mobile-layout");
@@ -87,7 +86,7 @@ const useResponsiveSidebarStatus = () => {
87
86
  };
88
87
  exports.useResponsiveSidebarStatus = useResponsiveSidebarStatus;
89
88
  const TopPanelInner = ({ readOnlyStudio, onMounted, drawRef, bufferStateDelayInMilliseconds }) => {
90
- const { setSidebarCollapsedState, sidebarCollapsedStateRight } = (0, react_1.useContext)(sidebar_1.SidebarContext);
89
+ const { setSidebarCollapsedState, sidebarCollapsedStateRight, setSidebarCollapsedDuringDrag, } = (0, react_1.useContext)(sidebar_1.SidebarContext);
91
90
  const rulersAreVisible = (0, use_is_ruler_visible_1.useIsRulerVisible)();
92
91
  const { canvasContent } = (0, react_1.useContext)(remotion_1.Internals.CompositionManager);
93
92
  const actualStateLeft = (0, exports.useResponsiveSidebarStatus)();
@@ -97,21 +96,6 @@ const TopPanelInner = ({ readOnlyStudio, onMounted, drawRef, bufferStateDelayInM
97
96
  }
98
97
  return 'expanded';
99
98
  }, [sidebarCollapsedStateRight]);
100
- const previousSidebarState = (0, react_1.useRef)({
101
- left: actualStateLeft,
102
- right: actualStateRight,
103
- });
104
- (0, react_1.useLayoutEffect)(() => {
105
- if (previousSidebarState.current.left === actualStateLeft &&
106
- previousSidebarState.current.right === actualStateRight) {
107
- return;
108
- }
109
- previousSidebarState.current = {
110
- left: actualStateLeft,
111
- right: actualStateRight,
112
- };
113
- player_1.PlayerInternals.updateAllElementsSizes();
114
- }, [actualStateLeft, actualStateRight]);
115
99
  (0, react_1.useEffect)(() => {
116
100
  onMounted();
117
101
  }, [onMounted]);
@@ -130,8 +114,8 @@ const TopPanelInner = ({ readOnlyStudio, onMounted, drawRef, bufferStateDelayInM
130
114
  return (jsx_runtime_1.jsx(ObserveDefaultPropsContext_1.ObserveDefaultProps, { compositionId: (canvasContent === null || canvasContent === void 0 ? void 0 : canvasContent.type) === 'composition'
131
115
  ? canvasContent.compositionId
132
116
  : null, readOnlyStudio: readOnlyStudio, children: jsx_runtime_1.jsxs("div", { style: container, children: [
133
- jsx_runtime_1.jsx("div", { style: row, children: jsx_runtime_1.jsxs(SplitterContainer_1.SplitterContainer, { minFlex: 0.15, maxFlex: 0.4, defaultFlex: 0.2, maxFlexerSize: MAX_SIDEBAR_WIDTH, minFlexerSize: null, maxAntiFlexerSize: null, minAntiFlexerSize: null, id: "sidebar-to-preview", orientation: "vertical", children: [actualStateLeft === 'expanded' ? (jsx_runtime_1.jsx(SplitterElement_1.SplitterElement, { sticky: null, type: "flexer", children: jsx_runtime_1.jsx(ExplorerPanel_1.ExplorerPanel, { readOnlyStudio: readOnlyStudio }) })) : null, actualStateLeft === 'expanded' ? (jsx_runtime_1.jsx(SplitterHandle_1.SplitterHandle, { allowToCollapse: "left", onCollapse: onCollapseLeft })) : null, jsx_runtime_1.jsx(SplitterElement_1.SplitterElement, { sticky: null, type: "anti-flexer", children: jsx_runtime_1.jsxs(SplitterContainer_1.SplitterContainer, { minFlex: 0.5, maxFlex: 0.8, defaultFlex: 0.7, maxFlexerSize: null, minFlexerSize: null, maxAntiFlexerSize: MAX_SIDEBAR_WIDTH, minAntiFlexerSize: MIN_SIDEBAR_WIDTH, id: "canvas-to-right-sidebar", orientation: "vertical", children: [
134
- jsx_runtime_1.jsx(SplitterElement_1.SplitterElement, { sticky: null, type: "flexer", children: jsx_runtime_1.jsx("div", { ref: drawRef, style: canvasContainerStyle, children: jsx_runtime_1.jsx(CanvasIfSizeIsAvailable_1.CanvasIfSizeIsAvailable, {}) }) }), actualStateRight === 'expanded' ? (jsx_runtime_1.jsx(SplitterHandle_1.SplitterHandle, { allowToCollapse: "right", onCollapse: onCollapseRight })) : null, actualStateRight === 'expanded' ? (jsx_runtime_1.jsx(SplitterElement_1.SplitterElement, { sticky: null, type: "anti-flexer", children: jsx_runtime_1.jsx(OptionsPanel_1.OptionsPanel, { readOnlyStudio: readOnlyStudio }) })) : null] }) })
117
+ jsx_runtime_1.jsx("div", { style: row, children: jsx_runtime_1.jsxs(SplitterContainer_1.SplitterContainer, { minFlex: 0.15, maxFlex: 0.4, defaultFlex: 0.2, maxFlexerSize: MAX_SIDEBAR_WIDTH, minFlexerSize: null, maxAntiFlexerSize: null, minAntiFlexerSize: null, id: "sidebar-to-preview", orientation: "vertical", children: [actualStateLeft === 'expanded' ? (jsx_runtime_1.jsx(SplitterElement_1.SplitterElement, { sticky: null, type: "flexer", children: jsx_runtime_1.jsx(ExplorerPanel_1.ExplorerPanel, { readOnlyStudio: readOnlyStudio }) })) : null, actualStateLeft === 'expanded' ? (jsx_runtime_1.jsx(SplitterHandle_1.SplitterHandle, { allowToCollapse: "left", onCollapse: onCollapseLeft, onCollapseDuringDrag: setSidebarCollapsedDuringDrag })) : null, jsx_runtime_1.jsx(SplitterElement_1.SplitterElement, { sticky: null, type: "anti-flexer", children: jsx_runtime_1.jsxs(SplitterContainer_1.SplitterContainer, { minFlex: 0.5, maxFlex: 0.8, defaultFlex: 0.7, maxFlexerSize: null, minFlexerSize: null, maxAntiFlexerSize: MAX_SIDEBAR_WIDTH, minAntiFlexerSize: MIN_SIDEBAR_WIDTH, id: "canvas-to-right-sidebar", orientation: "vertical", children: [
118
+ jsx_runtime_1.jsx(SplitterElement_1.SplitterElement, { sticky: null, type: "flexer", children: jsx_runtime_1.jsx("div", { ref: drawRef, style: canvasContainerStyle, children: jsx_runtime_1.jsx(CanvasIfSizeIsAvailable_1.CanvasIfSizeIsAvailable, {}) }) }), actualStateRight === 'expanded' ? (jsx_runtime_1.jsx(SplitterHandle_1.SplitterHandle, { allowToCollapse: "right", onCollapse: onCollapseRight, onCollapseDuringDrag: setSidebarCollapsedDuringDrag })) : null, actualStateRight === 'expanded' ? (jsx_runtime_1.jsx(SplitterElement_1.SplitterElement, { sticky: null, type: "anti-flexer", children: jsx_runtime_1.jsx(OptionsPanel_1.OptionsPanel, { readOnlyStudio: readOnlyStudio }) })) : null] }) })
135
119
  ] }) }), jsx_runtime_1.jsx(PreviewToolbar_1.PreviewToolbar, { bufferStateDelayInMilliseconds: bufferStateDelayInMilliseconds, readOnlyStudio: readOnlyStudio }), jsx_runtime_1.jsx(CurrentCompositionSideEffects_1.TitleUpdater, {})
136
120
  ] }) }));
137
121
  };
@@ -6,7 +6,12 @@ export type Bug = {
6
6
  link: string;
7
7
  versions: string[];
8
8
  };
9
+ type UpgradeState = 'idle' | 'upgrading' | 'upgraded' | 'shutting-down' | 'shutdown';
9
10
  type UpdateStatusContextValue = {
11
+ readonly upgradeState: UpgradeState;
12
+ readonly upgradeError: string | null;
13
+ readonly upgrade: (version: string) => Promise<void>;
14
+ readonly shutdown: () => Promise<void>;
10
15
  readonly error: string | null;
11
16
  readonly info: UpdateAvailableResponse | null;
12
17
  readonly knownBugs: Bug[] | null;
@@ -4,13 +4,56 @@ exports.useUpdateStatus = exports.UpdateStatusProvider = void 0;
4
4
  const jsx_runtime_1 = require("react/jsx-runtime");
5
5
  const react_1 = require("react");
6
6
  const remotion_1 = require("remotion");
7
+ const shut_down_studio_1 = require("../api/shut-down-studio");
7
8
  const browser_studio_operations_1 = require("../helpers/browser-studio-operations");
8
9
  const can_show_updates_1 = require("../helpers/can-show-updates");
9
10
  const client_id_1 = require("../helpers/client-id");
11
+ const call_api_1 = require("./call-api");
10
12
  const actions_1 = require("./RenderQueue/actions");
11
13
  const UpdateStatusContext = (0, react_1.createContext)(null);
12
14
  const UpdateStatusProvider = ({ children }) => {
13
15
  const { previewServerState } = (0, react_1.useContext)(client_id_1.StudioServerConnectionCtx);
16
+ const [upgradeState, setUpgradeState] = (0, react_1.useState)('idle');
17
+ const [upgradeError, setUpgradeError] = (0, react_1.useState)(null);
18
+ const busy = (0, react_1.useRef)(false);
19
+ const upgrade = (0, react_1.useCallback)(async (version) => {
20
+ if (busy.current) {
21
+ return;
22
+ }
23
+ busy.current = true;
24
+ setUpgradeState('upgrading');
25
+ setUpgradeError(null);
26
+ try {
27
+ await (0, call_api_1.callApi)('/api/upgrade-remotion', { version });
28
+ setUpgradeState('upgraded');
29
+ }
30
+ catch (err) {
31
+ setUpgradeError(err.message);
32
+ setUpgradeState('idle');
33
+ }
34
+ finally {
35
+ busy.current = false;
36
+ }
37
+ }, []);
38
+ const shutdown = (0, react_1.useCallback)(async () => {
39
+ if (busy.current) {
40
+ return;
41
+ }
42
+ busy.current = true;
43
+ setUpgradeState('shutting-down');
44
+ setUpgradeError(null);
45
+ try {
46
+ await (0, shut_down_studio_1.shutDownStudio)();
47
+ setUpgradeState('shutdown');
48
+ }
49
+ catch (err) {
50
+ setUpgradeError(err.message);
51
+ setUpgradeState('upgraded');
52
+ }
53
+ finally {
54
+ busy.current = false;
55
+ }
56
+ }, []);
14
57
  const [info, setInfo] = (0, react_1.useState)(null);
15
58
  const [knownBugs, setKnownBugs] = (0, react_1.useState)(null);
16
59
  const [error, setError] = (0, react_1.useState)(null);
@@ -59,8 +102,16 @@ const UpdateStatusProvider = ({ children }) => {
59
102
  };
60
103
  }, [showUpdates]);
61
104
  const value = (0, react_1.useMemo)(() => {
62
- return { error, info, knownBugs };
63
- }, [error, info, knownBugs]);
105
+ return {
106
+ error,
107
+ info,
108
+ knownBugs,
109
+ upgradeState,
110
+ upgradeError,
111
+ upgrade,
112
+ shutdown,
113
+ };
114
+ }, [error, info, knownBugs, upgradeState, upgradeError, upgrade, shutdown]);
64
115
  return (jsx_runtime_1.jsx(UpdateStatusContext.Provider, { value: value, children: children }));
65
116
  };
66
117
  exports.UpdateStatusProvider = UpdateStatusProvider;
@@ -5,9 +5,11 @@ const jsx_runtime_1 = require("react/jsx-runtime");
5
5
  const react_1 = require("react");
6
6
  const colors_1 = require("../helpers/colors");
7
7
  const copy_text_1 = require("../helpers/copy-text");
8
- const clipboard_1 = require("../icons/clipboard");
8
+ const use_copy_feedback_1 = require("../helpers/use-copy-feedback");
9
+ const copy_1 = require("../icons/copy");
9
10
  const InlineAction_1 = require("./InlineAction");
10
11
  const KnownBugs_1 = require("./KnownBugs");
12
+ const ModalButton_1 = require("./ModalButton");
11
13
  const ValidationMessage_1 = require("./NewComposition/ValidationMessage");
12
14
  const NotificationCenter_1 = require("./Notifications/NotificationCenter");
13
15
  const actions_1 = require("./RenderQueue/actions");
@@ -86,6 +88,7 @@ const commands = {
86
88
  yarn: 'yarn remotion upgrade',
87
89
  pnpm: 'pnpm exec remotion upgrade',
88
90
  bun: 'bun remotion upgrade',
91
+ nub: 'nubx remotion upgrade',
89
92
  unknown: 'npx remotion upgrade',
90
93
  };
91
94
  const skillsUpdateCommand = 'npx remotion skills update';
@@ -170,7 +173,7 @@ const RenderedReleaseNotes = ({ release }) => {
170
173
  };
171
174
  const UpdatesSettings = () => {
172
175
  const { remotionSkillsInfo } = (0, SettingsContext_1.useSettings)();
173
- const { error, info, knownBugs } = (0, UpdateStatusContext_1.useUpdateStatus)();
176
+ const { error, info, knownBugs, upgradeState, upgradeError, upgrade, shutdown, } = (0, UpdateStatusContext_1.useUpdateStatus)();
174
177
  const [releaseNotes, setReleaseNotes] = (0, react_1.useState)(null);
175
178
  (0, react_1.useEffect)(() => {
176
179
  if (!(info === null || info === void 0 ? void 0 : info.updateAvailable)) {
@@ -211,17 +214,37 @@ const UpdatesSettings = () => {
211
214
  const updateActionType = (remotionSkillsInfo === null || remotionSkillsInfo === void 0 ? void 0 : remotionSkillsInfo.remotionUpgradeSkillAvailable)
212
215
  ? 'skill'
213
216
  : 'command';
217
+ const { copied, markCopied } = (0, use_copy_feedback_1.useCopyFeedback)();
214
218
  const onClick = (0, react_1.useCallback)(() => {
215
219
  if (updateAction === null) {
216
220
  return;
217
221
  }
218
- (0, copy_text_1.copyText)(updateAction).catch((err) => {
222
+ (0, copy_text_1.copyText)(updateAction)
223
+ .then(markCopied)
224
+ .catch((err) => {
219
225
  (0, NotificationCenter_1.showNotification)('Could not copy: ' + err.message, 2000);
220
226
  });
221
- }, [updateAction]);
227
+ }, [markCopied, updateAction]);
222
228
  const renderCopyAction = (0, react_1.useCallback)((color) => {
223
- return jsx_runtime_1.jsx(clipboard_1.ClipboardIcon, { color: color, style: copyIcon });
224
- }, []);
229
+ return jsx_runtime_1.jsx(copy_1.CopyIcon, { copied: copied, color: color, style: copyIcon });
230
+ }, [copied]);
231
+ const onUpgrade = (0, react_1.useCallback)(() => {
232
+ if (info) {
233
+ upgrade(info.latestVersion);
234
+ }
235
+ }, [info, upgrade]);
236
+ if (upgradeState !== 'idle') {
237
+ return (jsx_runtime_1.jsxs("div", { style: container, children: [
238
+ jsx_runtime_1.jsx("div", { style: title, children: upgradeState === 'upgrading'
239
+ ? 'Upgrading Remotion...'
240
+ : 'Remotion has been upgraded.' }), jsx_runtime_1.jsx("div", { style: text, children: upgradeState === 'upgrading'
241
+ ? 'This may take a few minutes. You can follow the progress in your terminal.'
242
+ : upgradeState === 'shutdown'
243
+ ? 'Studio is shutting down. Run your Studio start command again in the terminal to use the new version.'
244
+ : 'Restart Studio to use the new version. Shut down the server below, then run your Studio start command again in the terminal.' }), upgradeState === 'upgraded' || upgradeState === 'shutting-down' ? (jsx_runtime_1.jsx("div", { style: { marginTop: 12 }, children: jsx_runtime_1.jsx(ModalButton_1.ModalButton, { onClick: shutdown, disabled: upgradeState === 'shutting-down', children: upgradeState === 'shutting-down'
245
+ ? 'Shutting down...'
246
+ : 'Shut down Studio' }) })) : null, upgradeError ? (jsx_runtime_1.jsx(ValidationMessage_1.ValidationMessage, { message: upgradeError, type: "error", align: "flex-start" })) : null] }));
247
+ }
225
248
  if (info === null) {
226
249
  return (jsx_runtime_1.jsx("div", { style: container, children: error ? (jsx_runtime_1.jsx("div", { style: { paddingTop: 12 }, children: jsx_runtime_1.jsx(ValidationMessage_1.ValidationMessage, { message: 'Could not check for updates: ' + error, align: "flex-start", type: "error" }) })) : (jsx_runtime_1.jsx("div", { style: title, children: "Checking for updates..." })) }));
227
250
  }
@@ -235,9 +258,11 @@ const UpdatesSettings = () => {
235
258
  jsx_runtime_1.jsxs("div", { style: title, children: ["You", "'re", " up to date."] }), jsx_runtime_1.jsxs("div", { style: text, children: ["Remotion ", info.currentVersion, " and your Remotion Agent Skills are up to date."] })
236
259
  ] }));
237
260
  }
238
- return (jsx_runtime_1.jsxs("div", { style: container, children: [hasKnownBugs && info.updateAvailable ? (jsx_runtime_1.jsxs(jsx_runtime_1.Fragment, { children: [
239
- jsx_runtime_1.jsxs("div", { style: title, children: ["The currently installed version ", info.currentVersion, " has the following known bugs:"] }), jsx_runtime_1.jsx(KnownBugs_1.KnownBugs, { bugs: knownBugs !== null && knownBugs !== void 0 ? knownBugs : [] }), jsx_runtime_1.jsx("div", { style: { height: '20px' } }), jsx_runtime_1.jsxs("div", { style: text, children: ["To update, run the following ", updateActionType, ":"] })
240
- ] })) : info.updateAvailable ? (jsx_runtime_1.jsxs("div", { style: titleBeforeCommand, children: ["A new Remotion update is available. Run the following", ' ', updateActionType, ":"] })) : (jsx_runtime_1.jsxs("div", { style: titleBeforeCommand, children: ["Your Remotion Agent Skills are out of date. Run the following", ' ', updateActionType, ":"] })), jsx_runtime_1.jsxs("div", { style: commandField, children: [
261
+ return (jsx_runtime_1.jsxs("div", { style: container, children: [info.updateAvailable && info.packageManager !== 'unknown' ? (jsx_runtime_1.jsxs("div", { style: { paddingTop: 12 }, children: [
262
+ jsx_runtime_1.jsxs(ModalButton_1.ModalButton, { onClick: onUpgrade, children: ["Upgrade to ", info.latestVersion] }), jsx_runtime_1.jsx("div", { style: { ...text, marginTop: 8 }, children: "You will need to restart Studio after upgrading." })
263
+ ] })) : null, upgradeError ? (jsx_runtime_1.jsx(ValidationMessage_1.ValidationMessage, { message: upgradeError, type: "error", align: "flex-start" })) : null, hasKnownBugs && info.updateAvailable ? (jsx_runtime_1.jsxs(jsx_runtime_1.Fragment, { children: [
264
+ jsx_runtime_1.jsxs("div", { style: title, children: ["The currently installed version ", info.currentVersion, " has the following known bugs:"] }), jsx_runtime_1.jsx(KnownBugs_1.KnownBugs, { bugs: knownBugs !== null && knownBugs !== void 0 ? knownBugs : [] }), jsx_runtime_1.jsx("div", { style: { height: '20px' } }), jsx_runtime_1.jsxs("div", { style: text, children: ["Or run the following ", updateActionType, ":"] })
265
+ ] })) : info.updateAvailable ? (jsx_runtime_1.jsxs("div", { style: titleBeforeCommand, children: ["A new Remotion update is available. You can also run the following", ' ', updateActionType, ":"] })) : (jsx_runtime_1.jsxs("div", { style: titleBeforeCommand, children: ["Your Remotion Agent Skills are out of date. Run the following", ' ', updateActionType, ":"] })), jsx_runtime_1.jsxs("div", { style: commandField, children: [
241
266
  jsx_runtime_1.jsx("pre", { style: code, children: updateAction }), jsx_runtime_1.jsx(InlineAction_1.InlineAction, { variant: null, onClick: onClick, renderAction: renderCopyAction, title: "Copy command" })
242
267
  ] }), info.updateAvailable ? (jsx_runtime_1.jsxs("div", { style: text, children: ["This will update Remotion from ", info.currentVersion, " to", ' ', info.latestVersion, info.skillsUpdateAvailable
243
268
  ? ' and update your project Remotion Agent Skills.'
@@ -5,7 +5,9 @@ const react_1 = require("react");
5
5
  const remotion_1 = require("remotion");
6
6
  const pause_1 = require("../api/pause");
7
7
  const play_1 = require("../api/play");
8
+ const restart_studio_1 = require("../api/restart-studio");
8
9
  const seek_1 = require("../api/seek");
10
+ const shut_down_studio_1 = require("../api/shut-down-studio");
9
11
  const current_error_1 = require("../error-overlay/current-error");
10
12
  const calculate_timeline_1 = require("../helpers/calculate-timeline");
11
13
  const create_folder_tree_1 = require("../helpers/create-folder-tree");
@@ -203,6 +205,30 @@ const WebMcp = () => {
203
205
  }).filter((timelineTrack) => (0, should_show_track_in_timeline_1.shouldShowTrackInTimeline)(timelineTrack, durationInFrames));
204
206
  };
205
207
  Promise.all([
208
+ modelContext.registerTool({
209
+ name: 'restart_studio',
210
+ title: 'Restart Studio',
211
+ description: 'Restart the Studio server. The browser temporarily disconnects and reconnects when Studio is ready. Only available in a writable Studio with a server backend.',
212
+ inputSchema: {
213
+ type: 'object',
214
+ properties: {},
215
+ additionalProperties: false,
216
+ },
217
+ annotations: { readOnlyHint: false },
218
+ execute: () => (0, restart_studio_1.restartStudio)(),
219
+ }, { signal: controller.signal }),
220
+ modelContext.registerTool({
221
+ name: 'shut_down_studio',
222
+ title: 'Shut down Studio',
223
+ description: 'Gracefully shut down the Studio server. The browser disconnects. Start Studio again from the terminal to reconnect. Only available in a writable Studio with a server backend.',
224
+ inputSchema: {
225
+ type: 'object',
226
+ properties: {},
227
+ additionalProperties: false,
228
+ },
229
+ annotations: { readOnlyHint: false },
230
+ execute: () => (0, shut_down_studio_1.shutDownStudio)(),
231
+ }, { signal: controller.signal }),
206
232
  modelContext.registerTool({
207
233
  name: 'get_current_error',
208
234
  title: 'Get current Studio error',
@@ -22,10 +22,13 @@ const ZoomPersistor = () => {
22
22
  const { canvasContent } = (0, react_1.useContext)(remotion_1.Internals.CompositionManager);
23
23
  const urlState = (0, load_canvas_content_from_url_1.deriveCanvasContentFromUrl)();
24
24
  const isActive = urlState &&
25
- urlState.type === 'composition' &&
26
25
  canvasContent &&
27
- canvasContent.type === 'composition' &&
28
- urlState.compositionId === canvasContent.compositionId;
26
+ ((urlState.type === 'composition' &&
27
+ canvasContent.type === 'composition' &&
28
+ urlState.compositionId === canvasContent.compositionId) ||
29
+ (urlState.type === 'asset' &&
30
+ canvasContent.type === 'asset' &&
31
+ urlState.asset === canvasContent.asset));
29
32
  (0, react_1.useEffect)(() => {
30
33
  if (!isActive) {
31
34
  return;
@@ -218,7 +218,7 @@ const getCompositionMenuItems = ({ composition, connectionStatus, resolvedLocati
218
218
  navigator.clipboard
219
219
  .writeText(composition.id)
220
220
  .then(() => {
221
- (0, NotificationCenter_1.showNotification)('Copied to clipboard', 1000);
221
+ (0, NotificationCenter_1.showNotification)('Copied composition name', 1000);
222
222
  })
223
223
  .catch((err) => {
224
224
  (0, NotificationCenter_1.showNotification)(`Could not copy to clipboard: ${err.message}`, 1000);