@remotion/studio 4.0.514 → 4.0.515

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 (58) hide show
  1. package/dist/api/install-package.js +14 -1
  2. package/dist/components/AssetSelectorItem.d.ts +2 -1
  3. package/dist/components/AssetSelectorItem.js +18 -14
  4. package/dist/components/AudioWaveform.js +17 -139
  5. package/dist/components/InspectorPanel/CompositionInspector.js +27 -5
  6. package/dist/components/InstallPackage.d.ts +1 -1
  7. package/dist/components/InstallPackage.js +38 -6
  8. package/dist/components/Menu/MenuDivider.js +1 -1
  9. package/dist/components/Modals.js +9 -2
  10. package/dist/components/RenderModal/GuiRenderStatus.js +3 -1
  11. package/dist/components/RenderModal/RenderModalOutputName.js +3 -3
  12. package/dist/components/RenderModal/WebRenderModal.js +4 -2
  13. package/dist/components/RenderQueue/RenderQueueItem.js +3 -1
  14. package/dist/components/RenderQueue/RenderQueueOpenInFolder.js +3 -1
  15. package/dist/components/RenderQueue/RenderQueueRemoveItem.js +1 -1
  16. package/dist/components/SelectedOutlineCanvasRotation.d.ts +1 -0
  17. package/dist/components/SelectedOutlineCanvasRotation.js +11 -4
  18. package/dist/components/SelectedOutlineElement.js +1 -1
  19. package/dist/components/SelectedOutlinePolygon.d.ts +1 -0
  20. package/dist/components/SelectedOutlinePolygon.js +3 -2
  21. package/dist/components/Timeline/TimelineClipboardKeybindings.js +6 -2
  22. package/dist/components/Timeline/TimelineEffectItem.js +23 -6
  23. package/dist/components/Timeline/TimelineEffectPropItem.js +6 -2
  24. package/dist/components/Timeline/TimelineExpandArrowButton.js +10 -7
  25. package/dist/components/Timeline/TimelineExpandedKeyframeRow.js +4 -1
  26. package/dist/components/Timeline/TimelineExpandedSection.js +8 -5
  27. package/dist/components/Timeline/TimelineRowChrome.d.ts +1 -0
  28. package/dist/components/Timeline/TimelineRowChrome.js +38 -2
  29. package/dist/components/Timeline/TimelineSelection.d.ts +8 -3
  30. package/dist/components/Timeline/TimelineSelection.js +6 -4
  31. package/dist/components/Timeline/TimelineSequenceItem.js +7 -4
  32. package/dist/components/Timeline/TimelineSequenceName.js +1 -1
  33. package/dist/components/Timeline/TimelineTrack.js +4 -1
  34. package/dist/components/Timeline/TimelineVideoInfo.js +4 -2
  35. package/dist/components/Timeline/delete-selected-timeline-item.js +6 -2
  36. package/dist/components/Timeline/duplicate-selected-timeline-item.js +4 -2
  37. package/dist/components/Timeline/save-effect-prop.js +3 -3
  38. package/dist/components/effect-drag-and-drop.js +6 -3
  39. package/dist/components/effect-operations-api.d.ts +8 -0
  40. package/dist/components/effect-operations-api.js +52 -0
  41. package/dist/error-overlay/remotion-overlay/log-studio-error.js +4 -0
  42. package/dist/esm/{chunk-r46yxrjr.js → chunk-s6k99gh2.js} +1 -1
  43. package/dist/esm/{chunk-xn2q7eem.js → chunk-v5a8vpv4.js} +3525 -3475
  44. package/dist/esm/internals.mjs +3525 -3475
  45. package/dist/esm/previewEntry.mjs +3533 -3483
  46. package/dist/esm/renderEntry.mjs +2 -2
  47. package/dist/helpers/browser-studio-operations.d.ts +3 -0
  48. package/dist/helpers/browser-studio-operations.js +18 -1
  49. package/dist/helpers/colors.d.ts +1 -1
  50. package/dist/helpers/colors.js +1 -1
  51. package/dist/helpers/inject-css.js +5 -3
  52. package/dist/helpers/use-max-media-duration.js +5 -3
  53. package/dist/helpers/use-media-metadata.js +37 -20
  54. package/dist/helpers/use-menu-structure.js +67 -80
  55. package/dist/icons/cloud-download.d.ts +4 -0
  56. package/dist/icons/cloud-download.js +8 -0
  57. package/dist/state/modals.d.ts +1 -1
  58. package/package.json +12 -12
@@ -3,10 +3,23 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.installPackages = void 0;
4
4
  const remotion_1 = require("remotion");
5
5
  const call_api_1 = require("../components/call-api");
6
- const installPackages = (dependencies) => {
6
+ const browser_studio_operations_1 = require("../helpers/browser-studio-operations");
7
+ const installPackages = async (dependencies) => {
7
8
  if (!(0, remotion_1.getRemotionEnvironment)().isStudio) {
8
9
  throw new Error('installPackages() is only available in the Studio');
9
10
  }
11
+ const browserStudioOperations = (0, browser_studio_operations_1.getBrowserStudioOperations)();
12
+ if (browserStudioOperations !== null) {
13
+ const response = await browserStudioOperations.packageInstallation.installPackages({
14
+ dependencies: [...dependencies],
15
+ });
16
+ if (!response.success) {
17
+ const error = new Error(response.reason);
18
+ error.stack = response.stack;
19
+ throw error;
20
+ }
21
+ return {};
22
+ }
10
23
  if (window.remotion_isReadOnlyStudio) {
11
24
  throw new Error('installPackages() is not available in Read-Only Studio');
12
25
  }
@@ -14,7 +14,7 @@ export declare const getCanDragAsset: ({ readOnlyStudio, relativePath, }: {
14
14
  readOnlyStudio: boolean;
15
15
  relativePath: string;
16
16
  }) => boolean;
17
- export declare const getAssetContextMenuItems: ({ relativePath, fileManagerName, copyFileName, copyStaticFilePath, openAssetInExplorer, renameAsset, deleteAsset, fileExplorerDisabled, mutationsDisabled, }: {
17
+ export declare const getAssetContextMenuItems: ({ relativePath, fileManagerName, copyFileName, copyStaticFilePath, openAssetInExplorer, renameAsset, deleteAsset, fileExplorerAvailable, fileExplorerDisabled, mutationsDisabled, }: {
18
18
  relativePath: string;
19
19
  fileManagerName: string;
20
20
  copyFileName: () => void;
@@ -22,6 +22,7 @@ export declare const getAssetContextMenuItems: ({ relativePath, fileManagerName,
22
22
  openAssetInExplorer: () => void;
23
23
  renameAsset: () => void;
24
24
  deleteAsset: () => void;
25
+ fileExplorerAvailable: boolean;
25
26
  fileExplorerDisabled: boolean;
26
27
  mutationsDisabled: boolean;
27
28
  }) => ComboboxValue[];
@@ -117,8 +117,8 @@ const getCanDragAsset = ({ readOnlyStudio, relativePath, }) => {
117
117
  return !readOnlyStudio && (0, import_assets_1.getAssetElementFromPath)(relativePath) !== null;
118
118
  };
119
119
  exports.getCanDragAsset = getCanDragAsset;
120
- const getAssetContextMenuItems = ({ relativePath, fileManagerName, copyFileName, copyStaticFilePath, openAssetInExplorer, renameAsset, deleteAsset, fileExplorerDisabled, mutationsDisabled, }) => {
121
- return [
120
+ const getAssetContextMenuItems = ({ relativePath, fileManagerName, copyFileName, copyStaticFilePath, openAssetInExplorer, renameAsset, deleteAsset, fileExplorerAvailable, fileExplorerDisabled, mutationsDisabled, }) => {
121
+ const items = [
122
122
  (0, open_in_new_window_1.getOpenInNewWindowMenuItem)(`/assets/${relativePath}`),
123
123
  {
124
124
  type: 'divider',
@@ -150,18 +150,20 @@ const getAssetContextMenuItems = ({ relativePath, fileManagerName, copyFileName,
150
150
  type: 'divider',
151
151
  id: 'asset-file-actions-divider',
152
152
  },
153
- {
154
- id: 'open-asset-in-explorer',
155
- keyHint: null,
156
- label: `Show in ${fileManagerName}`,
157
- leftItem: null,
158
- onClick: openAssetInExplorer,
159
- quickSwitcherLabel: `Show asset in ${fileManagerName}`,
160
- subMenu: null,
161
- type: 'item',
162
- value: 'open-asset-in-explorer',
163
- disabled: fileExplorerDisabled,
164
- },
153
+ fileExplorerAvailable
154
+ ? {
155
+ id: 'open-asset-in-explorer',
156
+ keyHint: null,
157
+ label: `Show in ${fileManagerName}`,
158
+ leftItem: null,
159
+ onClick: openAssetInExplorer,
160
+ quickSwitcherLabel: `Show asset in ${fileManagerName}`,
161
+ subMenu: null,
162
+ type: 'item',
163
+ value: 'open-asset-in-explorer',
164
+ disabled: fileExplorerDisabled,
165
+ }
166
+ : null,
165
167
  {
166
168
  id: 'rename-asset',
167
169
  keyHint: null,
@@ -187,6 +189,7 @@ const getAssetContextMenuItems = ({ relativePath, fileManagerName, copyFileName,
187
189
  disabled: mutationsDisabled,
188
190
  },
189
191
  ];
192
+ return items.filter(no_react_1.NoReactInternals.truthy);
190
193
  };
191
194
  exports.getAssetContextMenuItems = getAssetContextMenuItems;
192
195
  const AssetFolderItem = ({ tabIndex, item, level, parentFolder, toggleFolder, dropLocation, setDropLocation, readOnlyStudio, }) => {
@@ -432,6 +435,7 @@ const AssetSelectorItem = ({ item, tabIndex, level, parentFolder, readOnlyStudio
432
435
  openAssetInExplorer,
433
436
  renameAsset,
434
437
  deleteAsset,
438
+ fileExplorerAvailable: (0, browser_studio_operations_1.getBrowserStudioOperations)() === null,
435
439
  fileExplorerDisabled,
436
440
  mutationsDisabled,
437
441
  });
@@ -41,19 +41,6 @@ const remotion_1 = require("remotion");
41
41
  const colors_1 = require("../helpers/colors");
42
42
  const timeline_layout_1 = require("../helpers/timeline-layout");
43
43
  const EMPTY_PEAKS = new Float32Array(0);
44
- // Recreate the canvas after Fast Refresh because an already transferred canvas
45
- // cannot be handed to OffscreenCanvas again.
46
- const canRetryCanvasTransfer = (err) => {
47
- return err instanceof DOMException && err.name === 'InvalidStateError';
48
- };
49
- const canUseAudioWaveformWorker = () => {
50
- if (typeof Worker === 'undefined' ||
51
- typeof OffscreenCanvas === 'undefined' ||
52
- typeof HTMLCanvasElement === 'undefined') {
53
- return false;
54
- }
55
- return 'transferControlToOffscreen' in HTMLCanvasElement.prototype;
56
- };
57
44
  const getContainerStyle = (height) => {
58
45
  return {
59
46
  display: 'flex',
@@ -64,9 +51,6 @@ const getContainerStyle = (height) => {
64
51
  height,
65
52
  };
66
53
  };
67
- const getWaveformErrorMessage = () => {
68
- return new Error('No waveform available. The audio could not be decoded or may not support CORS.');
69
- };
70
54
  const waveformCanvasStyle = {
71
55
  pointerEvents: 'none',
72
56
  width: '100%',
@@ -86,17 +70,12 @@ const parseVolume = (volume) => {
86
70
  const AudioWaveformInner = ({ src, height, startFrom, durationInFrames, displayOffsetInFrames, displayDurationInFrames, visualizationWidth, volume, doesVolumeChange, muted, playbackRate, loopDisplay, }) => {
87
71
  const [peaks, setPeaks] = (0, react_1.useState)(null);
88
72
  const [error, setError] = (0, react_1.useState)(null);
89
- const [waveformCanvasKey, setWaveformCanvasKey] = (0, react_1.useState)(0);
90
- const canUseWorkerPath = (0, react_1.useMemo)(() => canUseAudioWaveformWorker(), []);
91
73
  const vidConf = remotion_1.Internals.useUnsafeVideoConfig();
92
74
  if (vidConf === null) {
93
75
  throw new Error('Expected video config');
94
76
  }
95
77
  const waveformCanvas = (0, react_1.useRef)(null);
96
78
  const volumeCanvas = (0, react_1.useRef)(null);
97
- const waveformWorker = (0, react_1.useRef)(null);
98
- const hasTransferredCanvas = (0, react_1.useRef)(false);
99
- const latestRequestId = (0, react_1.useRef)(0);
100
79
  const shouldRenderVolumeOverlay = doesVolumeChange && typeof volume === 'string';
101
80
  const parsedVolume = (0, react_1.useMemo)(() => parseVolume(volume), [volume]);
102
81
  const visibleVolume = (0, react_1.useMemo)(() => {
@@ -116,82 +95,19 @@ const AudioWaveformInner = ({ src, height, startFrom, durationInFrames, displayO
116
95
  muted,
117
96
  parsedVolume,
118
97
  ]);
119
- (0, react_1.useEffect)(() => {
120
- if (canUseWorkerPath) {
121
- return;
122
- }
123
- const controller = new AbortController();
98
+ // Layout effect so that a cache hit sets the peaks synchronously and the
99
+ // waveform is painted on the very first frame after mounting.
100
+ (0, react_1.useLayoutEffect)(() => {
124
101
  setPeaks(null);
125
102
  setError(null);
126
- (0, timeline_utils_1.loadWaveformPeaks)(src, controller.signal)
127
- .then((p) => {
128
- if (!controller.signal.aborted) {
129
- setPeaks(p);
130
- }
131
- })
132
- .catch((err) => {
133
- if (!controller.signal.aborted) {
134
- setError(err);
135
- }
103
+ return (0, timeline_utils_1.subscribeToWaveformPeaks)({
104
+ src,
105
+ onPeaks: (p) => setPeaks(p),
106
+ onError: (err) => setError(err),
136
107
  });
137
- return () => controller.abort();
138
- }, [canUseWorkerPath, src]);
139
- (0, react_1.useEffect)(() => {
140
- if (!canUseWorkerPath) {
141
- return;
142
- }
143
- const canvasElement = waveformCanvas.current;
144
- if (!canvasElement || hasTransferredCanvas.current) {
145
- return;
146
- }
147
- const worker = (0, timeline_utils_1.makeAudioWaveformWorker)();
148
- let workerFailed = false;
149
- waveformWorker.current = worker;
150
- worker.addEventListener('message', (event) => {
151
- if (event.data.type === 'error') {
152
- if (event.data.requestId !== latestRequestId.current) {
153
- return;
154
- }
155
- setError(new Error(event.data.message));
156
- }
157
- });
158
- worker.addEventListener('error', (event) => {
159
- event.preventDefault();
160
- workerFailed = true;
161
- if (worker !== waveformWorker.current) {
162
- return;
163
- }
164
- worker.terminate();
165
- waveformWorker.current = null;
166
- hasTransferredCanvas.current = false;
167
- setError(getWaveformErrorMessage());
168
- });
169
- let offscreen;
170
- try {
171
- offscreen = canvasElement.transferControlToOffscreen();
172
- }
173
- catch (err) {
174
- worker.terminate();
175
- waveformWorker.current = null;
176
- if (canRetryCanvasTransfer(err)) {
177
- setWaveformCanvasKey((key) => key + 1);
178
- return;
179
- }
180
- throw err;
181
- }
182
- hasTransferredCanvas.current = true;
183
- worker.postMessage({ type: 'init', canvas: offscreen }, [offscreen]);
184
- return () => {
185
- if (!workerFailed) {
186
- worker.postMessage({ type: 'dispose' });
187
- }
188
- worker.terminate();
189
- waveformWorker.current = null;
190
- hasTransferredCanvas.current = false;
191
- };
192
- }, [canUseWorkerPath, waveformCanvasKey]);
108
+ }, [src]);
193
109
  const portionPeaks = (0, react_1.useMemo)(() => {
194
- if (canUseWorkerPath || !peaks) {
110
+ if (!peaks) {
195
111
  return null;
196
112
  }
197
113
  return (0, timeline_utils_1.sliceVisibleWaveformPeaks)({
@@ -205,7 +121,6 @@ const AudioWaveformInner = ({ src, height, startFrom, durationInFrames, displayO
205
121
  startFrom,
206
122
  });
207
123
  }, [
208
- canUseWorkerPath,
209
124
  displayDurationInFrames,
210
125
  displayOffsetInFrames,
211
126
  durationInFrames,
@@ -215,7 +130,10 @@ const AudioWaveformInner = ({ src, height, startFrom, durationInFrames, displayO
215
130
  startFrom,
216
131
  vidConf.fps,
217
132
  ]);
218
- (0, react_1.useEffect)(() => {
133
+ // Drawing must happen in a layout effect: when the timeline zooms, the
134
+ // canvas CSS box resizes in the same commit, and painting the bitmap
135
+ // before the browser paints avoids showing a stretched stale waveform.
136
+ (0, react_1.useLayoutEffect)(() => {
219
137
  const { current: canvasElement } = waveformCanvas;
220
138
  if (!canvasElement) {
221
139
  return;
@@ -223,31 +141,6 @@ const AudioWaveformInner = ({ src, height, startFrom, durationInFrames, displayO
223
141
  const pixelRatio = window.devicePixelRatio;
224
142
  const h = Math.ceil(height * pixelRatio);
225
143
  const w = Math.ceil(visualizationWidth * pixelRatio);
226
- if (canUseWorkerPath) {
227
- const worker = waveformWorker.current;
228
- if (!worker || !hasTransferredCanvas.current) {
229
- return;
230
- }
231
- latestRequestId.current += 1;
232
- setError(null);
233
- const message = {
234
- type: 'render',
235
- requestId: latestRequestId.current,
236
- src,
237
- width: w,
238
- height: h,
239
- volume: visibleVolume,
240
- startFrom,
241
- durationInFrames,
242
- displayOffsetInFrames,
243
- displayDurationInFrames,
244
- fps: vidConf.fps,
245
- playbackRate,
246
- loopDisplay,
247
- };
248
- worker.postMessage(message);
249
- return;
250
- }
251
144
  canvasElement.width = w;
252
145
  canvasElement.height = h;
253
146
  (0, timeline_utils_1.drawBars)({
@@ -257,23 +150,8 @@ const AudioWaveformInner = ({ src, height, startFrom, durationInFrames, displayO
257
150
  volume: visibleVolume,
258
151
  width: w,
259
152
  });
260
- }, [
261
- canUseWorkerPath,
262
- displayDurationInFrames,
263
- displayOffsetInFrames,
264
- durationInFrames,
265
- height,
266
- loopDisplay,
267
- playbackRate,
268
- portionPeaks,
269
- src,
270
- startFrom,
271
- vidConf.fps,
272
- visualizationWidth,
273
- visibleVolume,
274
- waveformCanvasKey,
275
- ]);
276
- (0, react_1.useEffect)(() => {
153
+ }, [height, portionPeaks, visibleVolume, visualizationWidth]);
154
+ (0, react_1.useLayoutEffect)(() => {
277
155
  if (!shouldRenderVolumeOverlay) {
278
156
  return;
279
157
  }
@@ -315,10 +193,10 @@ const AudioWaveformInner = ({ src, height, startFrom, durationInFrames, displayO
315
193
  if (error) {
316
194
  return null;
317
195
  }
318
- if (!canUseWorkerPath && !peaks) {
196
+ if (!peaks) {
319
197
  return null;
320
198
  }
321
199
  return (jsx_runtime_1.jsxs("div", { style: getContainerStyle(height), children: [
322
- jsx_runtime_1.jsx("canvas", { ref: waveformCanvas, style: waveformCanvasStyle }, waveformCanvasKey), shouldRenderVolumeOverlay ? (jsx_runtime_1.jsx("canvas", { ref: volumeCanvas, style: volumeCanvasStyle })) : null] }));
200
+ jsx_runtime_1.jsx("canvas", { ref: waveformCanvas, style: waveformCanvasStyle }), shouldRenderVolumeOverlay ? (jsx_runtime_1.jsx("canvas", { ref: volumeCanvas, style: volumeCanvasStyle })) : null] }));
323
201
  };
324
202
  exports.AudioWaveform = react_1.default.memo(AudioWaveformInner);
@@ -3,10 +3,13 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.CompositionInspector = void 0;
4
4
  const jsx_runtime_1 = require("react/jsx-runtime");
5
5
  const react_1 = require("react");
6
+ const browser_studio_operations_1 = require("../../helpers/browser-studio-operations");
6
7
  const client_id_1 = require("../../helpers/client-id");
7
8
  const colors_1 = require("../../helpers/colors");
9
+ const download_blob_1 = require("../../helpers/download-blob");
8
10
  const interactivity_enabled_1 = require("../../helpers/interactivity-enabled");
9
11
  const browse_elements_1 = require("../../icons/browse-elements");
12
+ const cloud_download_1 = require("../../icons/cloud-download");
10
13
  const frame_1 = require("../../icons/frame");
11
14
  const solid_1 = require("../../icons/solid");
12
15
  const video_1 = require("../../icons/video");
@@ -14,6 +17,7 @@ const VisualControls_1 = require("../../visual-controls/VisualControls");
14
17
  const DefaultPropsEditor_1 = require("../DefaultPropsEditor");
15
18
  const get_zod_if_possible_1 = require("../get-zod-if-possible");
16
19
  const is_menu_item_1 = require("../Menu/is-menu-item");
20
+ const NotificationCenter_1 = require("../Notifications/NotificationCenter");
17
21
  const ObserveDefaultPropsContext_1 = require("../ObserveDefaultPropsContext");
18
22
  const DataEditor_1 = require("../RenderModal/DataEditor");
19
23
  const zod_schema_type_1 = require("../RenderModal/SchemaEditor/zod-schema-type");
@@ -46,18 +50,36 @@ const browseElementsArrowStyle = {
46
50
  verticalAlign: -2,
47
51
  width: 12,
48
52
  };
49
- const CompositionActions = ({ readOnlyStudio }) => {
53
+ const CompositionActions = () => {
54
+ var _a;
55
+ var _b;
50
56
  const { canInsertAsset, canInsertComposition, canInsertSolid, canShowInsertAsset, canShowInsertComposition, canShowInsertSolid, insertAsset, insertComposition, insertSolid, } = (0, use_composition_actions_1.useCompositionActions)();
57
+ const downloadProject = (_b = (_a = (0, browser_studio_operations_1.getBrowserStudioOperations)()) === null || _a === void 0 ? void 0 : _a.downloadProject) !== null && _b !== void 0 ? _b : null;
58
+ const onDownloadProject = (0, react_1.useCallback)(async () => {
59
+ if (downloadProject === null) {
60
+ return;
61
+ }
62
+ try {
63
+ const { data, fileName } = await downloadProject();
64
+ const arrayBuffer = data.buffer.slice(data.byteOffset, data.byteOffset + data.byteLength);
65
+ (0, download_blob_1.downloadBlob)(new Blob([arrayBuffer], { type: 'application/zip' }), fileName);
66
+ }
67
+ catch (error) {
68
+ (0, NotificationCenter_1.showNotification)(`Could not download project: ${error instanceof Error ? error.message : String(error)}`, 2000);
69
+ }
70
+ }, [downloadProject]);
51
71
  const openElementsLibrary = (0, react_1.useCallback)(() => {
52
72
  window.open('https://www.remotion.dev/elements', '_blank', 'noopener,noreferrer');
53
73
  }, []);
54
- if ((readOnlyStudio && !canShowInsertSolid) ||
55
- (!canShowInsertAsset && !canShowInsertComposition && !canShowInsertSolid)) {
74
+ if (!canShowInsertAsset &&
75
+ !canShowInsertComposition &&
76
+ !canShowInsertSolid &&
77
+ downloadProject === null) {
56
78
  return null;
57
79
  }
58
80
  return (jsx_runtime_1.jsxs(common_1.InspectorQuickActionsSection, { children: [canShowInsertSolid ? (jsx_runtime_1.jsx(common_1.InspectorQuickAction, { disabled: !canInsertSolid, onClick: insertSolid, renderIcon: (color) => (jsx_runtime_1.jsx(solid_1.SolidIcon, { color: color, style: actionIconStyle })), children: "Add Solid" })) : null, canShowInsertAsset ? (jsx_runtime_1.jsx(common_1.InspectorQuickAction, { disabled: !canInsertAsset, onClick: insertAsset, renderIcon: (color) => (jsx_runtime_1.jsx(frame_1.PicIcon, { color: color, style: actionIconStyle })), children: "Add asset..." })) : null, canShowInsertComposition ? (jsx_runtime_1.jsx(common_1.InspectorQuickAction, { disabled: !canInsertComposition, onClick: insertComposition, renderIcon: (color) => (jsx_runtime_1.jsx(video_1.FilmIcon, { color: color, style: actionIconStyle })), children: "Add composition..." })) : null, canShowInsertAsset ? (jsx_runtime_1.jsxs(common_1.InspectorQuickAction, { disabled: false, iconContainerStyle: browseElementsIconContainerStyle, onClick: openElementsLibrary, renderIcon: (color) => (jsx_runtime_1.jsx(browse_elements_1.BrowseElementsIcon, { color: color, style: browseElementsIconStyle })), title: "Open the Remotion Elements library in a new tab. Install an Element there to send it to this composition.", children: ["Browse Elements",
59
81
  jsx_runtime_1.jsx("svg", { "aria-hidden": "true", viewBox: "0 0 16 16", style: browseElementsArrowStyle, children: jsx_runtime_1.jsx("path", { d: "M4 12 12 4M6 4h6v6", fill: "none", stroke: colors_1.CURRENT_COLOR, strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: "1.5" }) })
60
- ] })) : null] }));
82
+ ] })) : null, downloadProject ? (jsx_runtime_1.jsx(common_1.InspectorQuickAction, { disabled: false, onClick: onDownloadProject, renderIcon: (color) => (jsx_runtime_1.jsx(cloud_download_1.CloudDownloadIcon, { color: color, style: actionIconStyle })), children: "Download project" })) : null] }));
61
83
  };
62
84
  const CompositionDefaultPropsSection = ({ composition, currentDefaultProps, readOnlyStudio, setDefaultProps }) => {
63
85
  var _a;
@@ -138,7 +160,7 @@ const CompositionInspector = ({ composition, currentDefaultProps, readOnlyStudio
138
160
  return (jsx_runtime_1.jsxs("div", { style: styles_1.scrollableContainer, className: is_menu_item_1.VERTICAL_SCROLLBAR_CLASSNAME, children: [
139
161
  jsx_runtime_1.jsxs("div", { style: styles_1.inspectorOverviewSection, children: [
140
162
  jsx_runtime_1.jsx(CompositionInspectorHeader_1.CompositionInspectorHeader, {}), jsx_runtime_1.jsx(common_1.InspectorSectionDivider, {}), jsx_runtime_1.jsx(CompositionMetadata_1.CompositionMetadata, { compositionId: composition.id, disabled: readOnlyStudio || previewServerState.type !== 'connected', stack: composition.stack })
141
- ] }), jsx_runtime_1.jsx(CompositionDefaultPropsSection, { composition: composition, currentDefaultProps: currentDefaultProps, readOnlyStudio: readOnlyStudio, setDefaultProps: setDefaultProps }), jsx_runtime_1.jsx(CompositionVisualControlsSection, { readOnlyStudio: readOnlyStudio }), jsx_runtime_1.jsx(CompositionActions, { readOnlyStudio: readOnlyStudio })
163
+ ] }), jsx_runtime_1.jsx(CompositionDefaultPropsSection, { composition: composition, currentDefaultProps: currentDefaultProps, readOnlyStudio: readOnlyStudio, setDefaultProps: setDefaultProps }), jsx_runtime_1.jsx(CompositionVisualControlsSection, { readOnlyStudio: readOnlyStudio }), jsx_runtime_1.jsx(CompositionActions, {})
142
164
  ] }));
143
165
  };
144
166
  exports.CompositionInspector = CompositionInspector;
@@ -1,5 +1,5 @@
1
1
  import type { PackageManager } from '@remotion/studio-shared';
2
2
  import React from 'react';
3
3
  export declare const InstallPackageModal: React.FC<{
4
- readonly packageManager: PackageManager;
4
+ readonly packageManager: PackageManager | null;
5
5
  }>;
@@ -44,6 +44,7 @@ const ShortcutHint_1 = require("../error-overlay/remotion-overlay/ShortcutHint")
44
44
  const client_id_1 = require("../helpers/client-id");
45
45
  const colors_1 = require("../helpers/colors");
46
46
  const use_keybinding_1 = require("../helpers/use-keybinding");
47
+ const modals_1 = require("../state/modals");
47
48
  const Checkbox_1 = require("./Checkbox");
48
49
  const InstallablePackage_1 = require("./InstallablePackage");
49
50
  const layout_1 = require("./layout");
@@ -64,22 +65,46 @@ const InstallPackageModal = ({ packageManager }) => {
64
65
  const [state, setState] = react_1.default.useState({ type: 'idle' });
65
66
  const [map, setMap] = react_1.default.useState({});
66
67
  const { previewServerState: ctx } = (0, react_1.useContext)(client_id_1.StudioServerConnectionCtx);
68
+ const { setSelectedModal } = (0, react_1.useContext)(modals_1.SetSelectedModalContext);
67
69
  const selectedPackages = Object.keys(map).filter((pkg) => map[pkg]);
70
+ const selectedPackageSpecs = selectedPackages.map((name) => {
71
+ var _a;
72
+ var _b;
73
+ return ({
74
+ name,
75
+ version: (_b = (_a = studio_shared_1.extraPackages.find((pkg) => pkg.name === name)) === null || _a === void 0 ? void 0 : _a.version) !== null && _b !== void 0 ? _b : null,
76
+ });
77
+ });
68
78
  const onClick = (0, react_1.useCallback)(async () => {
79
+ var _a;
69
80
  if (state.type === 'done') {
81
+ if (packageManager === null) {
82
+ setSelectedModal(null);
83
+ return;
84
+ }
70
85
  setState({ type: 'restarting' });
71
86
  (0, restart_studio_1.restartStudio)();
72
87
  return;
73
88
  }
74
89
  setState({ type: 'installing' });
75
90
  try {
76
- await (0, install_package_1.installPackages)(selectedPackages.map((name) => ({ name, version: null })));
91
+ await (0, install_package_1.installPackages)(selectedPackageSpecs);
92
+ window.remotion_installedPackages = Array.from(new Set([
93
+ ...((_a = window.remotion_installedPackages) !== null && _a !== void 0 ? _a : []),
94
+ ...selectedPackages,
95
+ ]));
77
96
  setState({ type: 'done' });
78
97
  }
79
98
  catch (err) {
80
99
  setState({ type: 'error', error: err });
81
100
  }
82
- }, [selectedPackages, state.type]);
101
+ }, [
102
+ packageManager,
103
+ selectedPackageSpecs,
104
+ selectedPackages,
105
+ setSelectedModal,
106
+ state.type,
107
+ ]);
83
108
  const canSelectPackages = state.type === 'idle' && ctx.type === 'connected';
84
109
  const disabled = !(canSelectPackages || state.type === 'done') ||
85
110
  selectedPackages.length === 0;
@@ -104,7 +129,11 @@ const InstallPackageModal = ({ packageManager }) => {
104
129
  };
105
130
  }, [disabled, onClick, registerKeybinding]);
106
131
  return (jsx_runtime_1.jsxs(DismissableModal_1.DismissableModal, { children: [
107
- jsx_runtime_1.jsx(ModalHeader_1.ModalHeader, { title: "Install packages" }), jsx_runtime_1.jsx("div", { style: container, className: is_menu_item_1.VERTICAL_SCROLLBAR_CLASSNAME, children: state.type === 'done' ? (jsx_runtime_1.jsxs("div", { style: text, children: ["Installed package", selectedPackages.length === 1 ? '' : 's', ' ', "successfully. Restart the server to complete."] })) : state.type === 'restarting' ? (jsx_runtime_1.jsx("div", { style: text, children: "Restarting the Studio server..." })) : state.type === 'installing' ? (jsx_runtime_1.jsxs("div", { style: text, children: ["Installing package", selectedPackages.length === 1 ? '' : 's', ". Check your terminal for progress."] })) : (jsx_runtime_1.jsxs("div", { style: text, children: [Object.entries(studio_shared_1.installableMap)
132
+ jsx_runtime_1.jsx(ModalHeader_1.ModalHeader, { title: "Install packages" }), jsx_runtime_1.jsx("div", { style: container, className: is_menu_item_1.VERTICAL_SCROLLBAR_CLASSNAME, children: state.type === 'done' ? (jsx_runtime_1.jsxs("div", { style: text, children: ["Installed package", selectedPackages.length === 1 ? '' : 's', ' ', "successfully.", packageManager === null
133
+ ? null
134
+ : ' Restart the server to complete.'] })) : state.type === 'restarting' ? (jsx_runtime_1.jsx("div", { style: text, children: "Restarting the Studio server..." })) : state.type === 'installing' ? (jsx_runtime_1.jsxs("div", { style: text, children: ["Installing package", selectedPackages.length === 1 ? '' : 's', packageManager === null
135
+ ? '.'
136
+ : '. Check your terminal for progress.'] })) : (jsx_runtime_1.jsxs("div", { style: text, children: [Object.entries(studio_shared_1.installableMap)
108
137
  .filter(([, install]) => install)
109
138
  .map(([pkgShort]) => {
110
139
  var _a;
@@ -136,13 +165,16 @@ const InstallPackageModal = ({ packageManager }) => {
136
165
  }));
137
166
  }, disabled: !canSelectPackages || isInstalled }), jsx_runtime_1.jsx(layout_1.Spacing, { x: 1.5 }), jsx_runtime_1.jsx(InstallablePackage_1.InstallablePackageComp, { description: extraPkg.description, isInstalled: isInstalled, link: extraPkg.docsUrl, pkg: `${extraPkg.name}@${extraPkg.version}` })
138
167
  ] }, extraPkg.name));
139
- })] })) }), jsx_runtime_1.jsx(ModalFooter_1.ModalFooterContainer, { children: jsx_runtime_1.jsxs(layout_1.Row, { align: "center", children: [state.type === 'idle' ? (jsx_runtime_1.jsxs("span", { style: { color: colors_1.LIGHT_TEXT, fontSize: 13, lineHeight: 1.2 }, children: ["This will install ", selectedPackages.length, " package", selectedPackages.length === 1 ? '' : 's', jsx_runtime_1.jsx("br", {}),
140
- "using ", packageManager, ", Remotion v", remotion_1.VERSION] })) : null, jsx_runtime_1.jsx(layout_1.Flex, {}), jsx_runtime_1.jsxs(ModalButton_1.ModalButton, { onClick: onClick, disabled: disabled, children: [state.type === 'restarting'
168
+ })] })) }), jsx_runtime_1.jsx(ModalFooter_1.ModalFooterContainer, { children: jsx_runtime_1.jsxs(layout_1.Row, { align: "center", children: [state.type === 'idle' ? (jsx_runtime_1.jsxs("span", { style: { color: colors_1.LIGHT_TEXT, fontSize: 13, lineHeight: 1.2 }, children: ["This will install ", selectedPackages.length, " package", selectedPackages.length === 1 ? '' : 's', jsx_runtime_1.jsx("br", {}), packageManager === null
169
+ ? `in this project, Remotion v${remotion_1.VERSION}`
170
+ : `using ${packageManager}, Remotion v${remotion_1.VERSION}`] })) : null, jsx_runtime_1.jsx(layout_1.Flex, {}), jsx_runtime_1.jsxs(ModalButton_1.ModalButton, { onClick: onClick, disabled: disabled, children: [state.type === 'restarting'
141
171
  ? 'Restarting...'
142
172
  : state.type === 'installing'
143
173
  ? 'Installing...'
144
174
  : state.type === 'done'
145
- ? 'Restart Server'
175
+ ? packageManager === null
176
+ ? 'Done'
177
+ : 'Restart Server'
146
178
  : 'Install', disabled ? null : jsx_runtime_1.jsx(ShortcutHint_1.ShortcutHint, { keyToPress: "\u21B5", cmdOrCtrl: true })] })
147
179
  ] }) })
148
180
  ] }));
@@ -10,6 +10,6 @@ const menuDivider = {
10
10
  backgroundColor: colors_1.WHITE_ALPHA_05,
11
11
  };
12
12
  const MenuDivider = () => {
13
- return jsx_runtime_1.jsx("div", { style: menuDivider });
13
+ return jsx_runtime_1.jsx("div", { role: "separator", style: menuDivider });
14
14
  };
15
15
  exports.MenuDivider = MenuDivider;
@@ -6,6 +6,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.Modals = void 0;
7
7
  const jsx_runtime_1 = require("react/jsx-runtime");
8
8
  const react_1 = require("react");
9
+ const browser_studio_operations_1 = require("../helpers/browser-studio-operations");
9
10
  const client_id_1 = require("../helpers/client-id");
10
11
  const studio_runtime_config_1 = require("../helpers/studio-runtime-config");
11
12
  const modals_1 = require("../state/modals");
@@ -36,7 +37,11 @@ const Modals = ({ readOnlyStudio }) => {
36
37
  const { setSelectedModal } = (0, react_1.useContext)(modals_1.SetSelectedModalContext);
37
38
  const { previewServerState, subscribeToEvent } = (0, react_1.useContext)(client_id_1.StudioServerConnectionCtx);
38
39
  const canRender = previewServerState.type === 'connected';
40
+ const isBrowserStudio = (0, browser_studio_operations_1.getBrowserStudioOperations)() !== null;
39
41
  (0, react_1.useEffect)(() => {
42
+ if (isBrowserStudio) {
43
+ return;
44
+ }
40
45
  return subscribeToEvent('license-key-install-request', (event) => {
41
46
  if (event.type !== 'license-key-install-request') {
42
47
  return;
@@ -47,8 +52,10 @@ const Modals = ({ readOnlyStudio }) => {
47
52
  initialPublicLicenseKey: event.licenseKey,
48
53
  });
49
54
  });
50
- }, [setSelectedModal, subscribeToEvent]);
51
- return (jsx_runtime_1.jsxs(jsx_runtime_1.Fragment, { children: [modalContextType && modalContextType.type === 'new-comp' && (jsx_runtime_1.jsx(NewComposition_1.NewComposition, { folderName: modalContextType.folderName, parentName: modalContextType.parentName, stack: modalContextType.stack, canvasCapture: modalContextType.canvasCapture })), modalContextType && modalContextType.type === 'new-folder' && (jsx_runtime_1.jsx(NewFolder_1.NewFolder, { parentName: modalContextType.parentName, stack: modalContextType.stack })), modalContextType && modalContextType.type === 'duplicate-comp' && (jsx_runtime_1.jsx(DuplicateComposition_1.DuplicateComposition, { compositionType: modalContextType.compositionType, compositionId: modalContextType.compositionId })), modalContextType && modalContextType.type === 'delete-comp' && (jsx_runtime_1.jsx(DeleteComposition_1.DeleteComposition, { compositionId: modalContextType.compositionId })), modalContextType && modalContextType.type === 'rename-comp' && (jsx_runtime_1.jsx(RenameComposition_1.RenameComposition, { compositionId: modalContextType.compositionId })), modalContextType && modalContextType.type === 'delete-folder' && (jsx_runtime_1.jsx(DeleteFolder_1.DeleteFolder, { folderName: modalContextType.folderName, parentName: modalContextType.parentName, stack: modalContextType.stack })), modalContextType && modalContextType.type === 'rename-folder' && (jsx_runtime_1.jsx(RenameFolder_1.RenameFolder, { folderName: modalContextType.folderName, parentName: modalContextType.parentName, stack: modalContextType.stack })), modalContextType && modalContextType.type === 'rename-static-file' && (jsx_runtime_1.jsx(RenameStaticFile_1.RenameStaticFileModal, { relativePath: modalContextType.relativePath })), modalContextType && modalContextType.type === 'input-props-override' && (jsx_runtime_1.jsx(OverrideInputProps_1.OverrideInputPropsModal, {})), modalContextType && modalContextType.type === 'settings' && (jsx_runtime_1.jsx(SettingsModal_1.SettingsModal, { initialTab: modalContextType.initialTab, initialPublicLicenseKey: modalContextType.initialPublicLicenseKey }, `${modalContextType.initialTab}-${modalContextType.initialPublicLicenseKey}`)), modalContextType && modalContextType.type === 'web-render' && (jsx_runtime_1.jsx(WebRenderModal_1.WebRenderModalWithLoader, { ...modalContextType })), modalContextType &&
55
+ }, [isBrowserStudio, setSelectedModal, subscribeToEvent]);
56
+ return (jsx_runtime_1.jsxs(jsx_runtime_1.Fragment, { children: [modalContextType && modalContextType.type === 'new-comp' && (jsx_runtime_1.jsx(NewComposition_1.NewComposition, { folderName: modalContextType.folderName, parentName: modalContextType.parentName, stack: modalContextType.stack, canvasCapture: modalContextType.canvasCapture })), modalContextType && modalContextType.type === 'new-folder' && (jsx_runtime_1.jsx(NewFolder_1.NewFolder, { parentName: modalContextType.parentName, stack: modalContextType.stack })), modalContextType && modalContextType.type === 'duplicate-comp' && (jsx_runtime_1.jsx(DuplicateComposition_1.DuplicateComposition, { compositionType: modalContextType.compositionType, compositionId: modalContextType.compositionId })), modalContextType && modalContextType.type === 'delete-comp' && (jsx_runtime_1.jsx(DeleteComposition_1.DeleteComposition, { compositionId: modalContextType.compositionId })), modalContextType && modalContextType.type === 'rename-comp' && (jsx_runtime_1.jsx(RenameComposition_1.RenameComposition, { compositionId: modalContextType.compositionId })), modalContextType && modalContextType.type === 'delete-folder' && (jsx_runtime_1.jsx(DeleteFolder_1.DeleteFolder, { folderName: modalContextType.folderName, parentName: modalContextType.parentName, stack: modalContextType.stack })), modalContextType && modalContextType.type === 'rename-folder' && (jsx_runtime_1.jsx(RenameFolder_1.RenameFolder, { folderName: modalContextType.folderName, parentName: modalContextType.parentName, stack: modalContextType.stack })), modalContextType && modalContextType.type === 'rename-static-file' && (jsx_runtime_1.jsx(RenameStaticFile_1.RenameStaticFileModal, { relativePath: modalContextType.relativePath })), modalContextType && modalContextType.type === 'input-props-override' && (jsx_runtime_1.jsx(OverrideInputProps_1.OverrideInputPropsModal, {})), !isBrowserStudio &&
57
+ modalContextType &&
58
+ modalContextType.type === 'settings' && (jsx_runtime_1.jsx(SettingsModal_1.SettingsModal, { initialTab: modalContextType.initialTab, initialPublicLicenseKey: modalContextType.initialPublicLicenseKey }, `${modalContextType.initialTab}-${modalContextType.initialPublicLicenseKey}`)), modalContextType && modalContextType.type === 'web-render' && (jsx_runtime_1.jsx(WebRenderModal_1.WebRenderModalWithLoader, { ...modalContextType })), modalContextType &&
52
59
  modalContextType.type === 'server-render' &&
53
60
  (canRender || modalContextType.readOnlyStudio) ? (jsx_runtime_1.jsx(ServerRenderModal_1.RenderModalWithLoader, { readOnlyStudio: (_a = modalContextType.readOnlyStudio) !== null && _a !== void 0 ? _a : false, initialFrame: modalContextType.initialFrame, initialDarkMode: modalContextType.initialDarkMode, compositionId: modalContextType.compositionId, initialVideoImageFormat: modalContextType.initialVideoImageFormat, initialJpegQuality: modalContextType.initialJpegQuality, initialScale: modalContextType.initialScale, initialLogLevel: modalContextType.initialLogLevel, initialOffthreadVideoCacheSizeInBytes: modalContextType.initialOffthreadVideoCacheSizeInBytes, initialOffthreadVideoThreads: modalContextType.initialOffthreadVideoThreads, initialMediaCacheSizeInBytes: modalContextType.initialMediaCacheSizeInBytes, initialConcurrency: modalContextType.initialConcurrency, maxConcurrency: modalContextType.maxConcurrency, minConcurrency: modalContextType.minConcurrency, initialStillImageFormat: modalContextType.initialStillImageFormat, initialMuted: modalContextType.initialMuted, initialEnforceAudioTrack: modalContextType.initialEnforceAudioTrack, initialProResProfile: modalContextType.initialProResProfile, initialx264Preset: modalContextType.initialx264Preset, initialGopSize: modalContextType.initialGopSize, initialPixelFormat: modalContextType.initialPixelFormat, initialAudioBitrate: modalContextType.initialAudioBitrate, initialVideoBitrate: modalContextType.initialVideoBitrate, initialEveryNthFrame: modalContextType.initialEveryNthFrame, initialNumberOfGifLoops: modalContextType.initialNumberOfGifLoops, initialDelayRenderTimeout: modalContextType.initialDelayRenderTimeout, initialEnvVariables: modalContextType.initialEnvVariables, initialDisableWebSecurity: modalContextType.initialDisableWebSecurity, initialGl: modalContextType.initialOpenGlRenderer, initialHeadless: modalContextType.initialHeadless, initialIgnoreCertificateErrors: modalContextType.initialIgnoreCertificateErrors, initialEncodingBufferSize: modalContextType.initialEncodingBufferSize, initialEncodingMaxRate: modalContextType.initialEncodingMaxRate, initialUserAgent: modalContextType.initialUserAgent, initialColorSpace: modalContextType.initialColorSpace, initialMultiProcessOnLinux: modalContextType.initialMultiProcessOnLinux, initialRepro: modalContextType.initialRepro, initialBeep: modalContextType.initialBeep, initialForSeamlessAacConcatenation: modalContextType.initialForSeamlessAacConcatenation, defaultProps: modalContextType.defaultProps, inFrameMark: modalContextType.inFrameMark, outFrameMark: modalContextType.outFrameMark, defaultConfigurationAudioCodec: modalContextType.defaultConfigurationAudioCodec, defaultConfigurationVideoCodec: modalContextType.defaultConfigurationVideoCodec, renderTypeOfLastRender: modalContextType.renderTypeOfLastRender, defaultMetadata: modalContextType.defaulMetadata, initialHardwareAcceleration: modalContextType.initialHardwareAcceleration, initialSampleRate: modalContextType.initialSampleRate, initialChromeMode: modalContextType.initialChromeMode, renderDefaults: modalContextType.renderDefaults })) : null, modalContextType && modalContextType.type === 'render-progress' && (jsx_runtime_1.jsx(RenderStatusModal_1.RenderStatusModal, { jobId: modalContextType.jobId })), modalContextType && modalContextType.type === 'update' && (jsx_runtime_1.jsx(UpdateModal_1.UpdateModal, { info: modalContextType.info, knownBugs: modalContextType.knownBugs })), modalContextType && modalContextType.type === 'fix-computed-value' && (jsx_runtime_1.jsx(FixComputedValueModal_1.FixComputedValueModal, { state: modalContextType })), modalContextType && modalContextType.type === 'install-packages' && (jsx_runtime_1.jsx(InstallPackage_1.InstallPackageModal, { packageManager: modalContextType.packageManager })), modalContextType && modalContextType.type === 'quick-switcher' && (jsx_runtime_1.jsx(QuickSwitcher_1.default, { readOnlyStudio: readOnlyStudio, invocationTimestamp: modalContextType.invocationTimestamp, initialMode: modalContextType.mode, assetSelection: modalContextType.assetSelection, compositionSelection: modalContextType.compositionSelection })), modalContextType && modalContextType.type === 'add-effect' && (jsx_runtime_1.jsx(EffectPickerModal_1.EffectPickerModal, { state: modalContextType })), modalContextType && modalContextType.type === 'confirmation-dialog' && (jsx_runtime_1.jsx(ConfirmationDialog_1.ConfirmationDialog, { state: modalContextType })), modalContextType && modalContextType.type === 'svg-import-dialog' && (jsx_runtime_1.jsx(SvgImportDialog_1.SvgImportDialog, { state: modalContextType })), (0, studio_runtime_config_1.getStudioAskAIEnabled)() && jsx_runtime_1.jsx(AskAiModal_1.AskAiModal, {})] }));
54
61
  };
@@ -3,6 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.GuiRenderStatus = void 0;
4
4
  const jsx_runtime_1 = require("react/jsx-runtime");
5
5
  const react_1 = require("react");
6
+ const browser_studio_operations_1 = require("../../helpers/browser-studio-operations");
6
7
  const colors_1 = require("../../helpers/colors");
7
8
  const layout_1 = require("../layout");
8
9
  const actions_1 = require("../RenderQueue/actions");
@@ -78,6 +79,7 @@ const DownloadsProgress = ({ downloads }) => {
78
79
  ] }));
79
80
  };
80
81
  const OpenFile = ({ job }) => {
82
+ const isBrowserStudio = (0, browser_studio_operations_1.getBrowserStudioOperations)() !== null;
81
83
  const labelStyle = (0, react_1.useMemo)(() => {
82
84
  return {
83
85
  ...label,
@@ -93,7 +95,7 @@ const OpenFile = ({ job }) => {
93
95
  (0, actions_1.openInFileExplorer)({ directory: job.outName });
94
96
  }, [job.outName]);
95
97
  return (jsx_runtime_1.jsxs("div", { style: progressItem, children: [
96
- jsx_runtime_1.jsx(SuccessIcon_1.SuccessIcon, {}), jsx_runtime_1.jsx(layout_1.Spacing, { x: 1 }), jsx_runtime_1.jsx("button", { style: labelStyle, type: "button", onClick: onClick, children: job.outName }), jsx_runtime_1.jsx("div", { style: right, children: jsx_runtime_1.jsx(RenderQueueOpenInFolder_1.RenderQueueOpenInFinderItem, { job: job }) })
98
+ jsx_runtime_1.jsx(SuccessIcon_1.SuccessIcon, {}), jsx_runtime_1.jsx(layout_1.Spacing, { x: 1 }), isBrowserStudio ? (jsx_runtime_1.jsx("div", { style: labelStyle, children: job.outName })) : (jsx_runtime_1.jsx("button", { style: labelStyle, type: "button", onClick: onClick, children: job.outName })), jsx_runtime_1.jsx("div", { style: right, children: jsx_runtime_1.jsx(RenderQueueOpenInFolder_1.RenderQueueOpenInFinderItem, { job: job }) })
97
99
  ] }));
98
100
  };
99
101
  const GuiRenderStatus = ({ job }) => {
@@ -3,6 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.RenderModalOutputName = void 0;
4
4
  const jsx_runtime_1 = require("react/jsx-runtime");
5
5
  const react_1 = require("react");
6
+ const browser_studio_operations_1 = require("../../helpers/browser-studio-operations");
6
7
  const colors_1 = require("../../helpers/colors");
7
8
  const get_file_manager_name_1 = require("../../helpers/get-file-manager-name");
8
9
  const folder_1 = require("../../icons/folder");
@@ -47,14 +48,13 @@ const RenderModalOutputName = ({ existence, inputStyle, outName, onValueChange,
47
48
  return jsx_runtime_1.jsx(folder_1.ExpandedFolderIconSolid, { style: openIconStyle, color: color });
48
49
  }, []);
49
50
  const fileManagerName = (0, get_file_manager_name_1.getFileManagerName)(window.remotion_fileSystemPlatform);
51
+ const isBrowserStudio = (0, browser_studio_operations_1.getBrowserStudioOperations)() !== null;
50
52
  return (jsx_runtime_1.jsxs("div", { style: outputNameRow, children: [
51
53
  jsx_runtime_1.jsx(layout_1.Column, { children: jsx_runtime_1.jsx("div", { style: layout_2.label, children: labelText }) }), jsx_runtime_1.jsx("div", { style: layout_2.rightRow, children: jsx_runtime_1.jsxs("div", { style: outputNameInputContainer, children: [
52
54
  jsx_runtime_1.jsx(RemInput_1.RemotionInput, { status: validationMessage ? 'error' : existence ? 'warning' : 'ok', style: inputStyle, type: "text", value: outName, onChange: onValueChange, rightAlign: true }), validationMessage ? (jsx_runtime_1.jsxs(jsx_runtime_1.Fragment, { children: [
53
55
  jsx_runtime_1.jsx(layout_1.Spacing, { y: 1, block: true }), jsx_runtime_1.jsx(ValidationMessage_1.ValidationMessage, { align: "flex-end", message: validationMessage, type: 'error' })
54
56
  ] })) : existence ? (jsx_runtime_1.jsxs(jsx_runtime_1.Fragment, { children: [
55
- jsx_runtime_1.jsx(layout_1.Spacing, { y: 1, block: true }), jsx_runtime_1.jsx(ValidationMessage_1.ValidationMessage, { align: "flex-end", message: jsx_runtime_1.jsxs("span", { style: existsMessageStyle, children: [
56
- jsx_runtime_1.jsx(InlineAction_1.InlineAction, { variant: null, onClick: openExistingOutput, renderAction: renderOpenIcon, title: `Open in ${fileManagerName}` }),
57
- "Exists, will be overwritten"] }), type: 'warning' })
57
+ jsx_runtime_1.jsx(layout_1.Spacing, { y: 1, block: true }), jsx_runtime_1.jsx(ValidationMessage_1.ValidationMessage, { align: "flex-end", message: jsx_runtime_1.jsxs("span", { style: existsMessageStyle, children: [isBrowserStudio ? null : (jsx_runtime_1.jsx(InlineAction_1.InlineAction, { variant: null, onClick: openExistingOutput, renderAction: renderOpenIcon, title: `Open in ${fileManagerName}` })), "Exists, will be overwritten"] }), type: 'warning' })
58
58
  ] })) : null] }) })
59
59
  ] }));
60
60
  };