@remotion/studio 4.0.434 → 4.0.436

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.
@@ -4,10 +4,13 @@ exports.CompositionSelector = exports.getKeysToExpand = exports.useCompositionNa
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 ShortcutHint_1 = require("../error-overlay/remotion-overlay/ShortcutHint");
7
8
  const colors_1 = require("../helpers/colors");
8
9
  const create_folder_tree_1 = require("../helpers/create-folder-tree");
9
10
  const persist_open_folders_1 = require("../helpers/persist-open-folders");
10
11
  const sort_by_nonce_history_1 = require("../helpers/sort-by-nonce-history");
12
+ const use_keybinding_1 = require("../helpers/use-keybinding");
13
+ const modals_1 = require("../state/modals");
11
14
  const z_index_1 = require("../state/z-index");
12
15
  const CompositionSelectorItem_1 = require("./CompositionSelectorItem");
13
16
  const CurrentComposition_1 = require("./CurrentComposition");
@@ -56,6 +59,29 @@ const container = {
56
59
  overflow: 'hidden',
57
60
  backgroundColor: colors_1.BACKGROUND,
58
61
  };
62
+ const QUICK_SWITCHER_TRIGGER_HEIGHT = 38;
63
+ const quickSwitcherArea = {
64
+ padding: '4px 12px',
65
+ borderBottom: `1px solid ${colors_1.BORDER_COLOR}`,
66
+ };
67
+ const quickSwitcherTrigger = {
68
+ backgroundColor: 'rgba(255, 255, 255, 0.06)',
69
+ borderRadius: 5,
70
+ padding: '4px 10px',
71
+ color: colors_1.LIGHT_TEXT,
72
+ fontSize: 12,
73
+ cursor: 'pointer',
74
+ display: 'flex',
75
+ alignItems: 'center',
76
+ justifyContent: 'space-between',
77
+ border: 'none',
78
+ width: '100%',
79
+ appearance: 'none',
80
+ };
81
+ const shortcutLabel = {
82
+ fontSize: 11,
83
+ opacity: 0.6,
84
+ };
59
85
  const getKeysToExpand = (initialFolderName, parentFolderName, initial = []) => {
60
86
  initial.push((0, persist_open_folders_1.openFolderKey)({
61
87
  folderName: initialFolderName,
@@ -71,6 +97,7 @@ exports.getKeysToExpand = getKeysToExpand;
71
97
  const CompositionSelector = () => {
72
98
  const { compositions, canvasContent, folders } = (0, react_1.useContext)(remotion_1.Internals.CompositionManager);
73
99
  const { foldersExpanded } = (0, react_1.useContext)(persist_open_folders_1.ExpandedFoldersContext);
100
+ const { setSelectedModal } = (0, react_1.useContext)(modals_1.ModalsContext);
74
101
  const { tabIndex } = (0, z_index_1.useZIndex)();
75
102
  const selectComposition = (0, InitialCompositionLoader_1.useSelectComposition)();
76
103
  const sortedCompositions = (0, react_1.useMemo)(() => {
@@ -84,7 +111,7 @@ const CompositionSelector = () => {
84
111
  }, [sortedCompositions, sortedFolders, foldersExpanded]);
85
112
  const list = (0, react_1.useMemo)(() => {
86
113
  return {
87
- height: `calc(100% - ${CurrentComposition_1.CURRENT_COMPOSITION_HEIGHT}px)`,
114
+ height: `calc(100% - ${CurrentComposition_1.CURRENT_COMPOSITION_HEIGHT}px - ${QUICK_SWITCHER_TRIGGER_HEIGHT}px)`,
88
115
  overflowY: 'auto',
89
116
  };
90
117
  }, []);
@@ -92,8 +119,15 @@ const CompositionSelector = () => {
92
119
  var _a;
93
120
  (_a = remotion_1.Internals.compositionSelectorRef.current) === null || _a === void 0 ? void 0 : _a.toggleFolder(folderName, parentName);
94
121
  }, []);
122
+ const openQuickSwitcher = (0, react_1.useCallback)(() => {
123
+ setSelectedModal({
124
+ type: 'quick-switcher',
125
+ mode: 'compositions',
126
+ invocationTimestamp: Date.now(),
127
+ });
128
+ }, [setSelectedModal]);
95
129
  return (jsx_runtime_1.jsxs("div", { style: container, children: [
96
- jsx_runtime_1.jsx(CurrentComposition_1.CurrentComposition, {}), jsx_runtime_1.jsx("div", { className: "__remotion-vertical-scrollbar", style: list, children: items.map((c) => {
130
+ jsx_runtime_1.jsx(CurrentComposition_1.CurrentComposition, {}), jsx_runtime_1.jsx("div", { style: quickSwitcherArea, children: jsx_runtime_1.jsxs("button", { type: "button", style: quickSwitcherTrigger, onClick: openQuickSwitcher, tabIndex: tabIndex, children: ["Search...", (0, use_keybinding_1.areKeyboardShortcutsDisabled)() ? null : (jsx_runtime_1.jsxs("span", { style: shortcutLabel, children: [ShortcutHint_1.cmdOrCtrlCharacter, "+K"] }))] }) }), jsx_runtime_1.jsx("div", { className: "__remotion-vertical-scrollbar", style: list, children: items.map((c) => {
97
131
  return (jsx_runtime_1.jsx(CompositionSelectorItem_1.CompositionSelectorItem, { level: 0, currentComposition: canvasContent && canvasContent.type === 'composition'
98
132
  ? canvasContent.compositionId
99
133
  : null, selectComposition: selectComposition, toggleFolder: toggleFolder, tabIndex: tabIndex, item: c }, c.key + c.type));
@@ -31,6 +31,7 @@ const itemStyle = {
31
31
  textAlign: 'left',
32
32
  backgroundColor: colors_1.BACKGROUND,
33
33
  height: COMPOSITION_ITEM_HEIGHT,
34
+ userSelect: 'none',
34
35
  };
35
36
  const labelStyle = {
36
37
  textAlign: 'left',
@@ -1,2 +1,2 @@
1
- export declare const CURRENT_COMPOSITION_HEIGHT = 80;
1
+ export declare const CURRENT_COMPOSITION_HEIGHT = 64;
2
2
  export declare const CurrentComposition: () => import("react/jsx-runtime").JSX.Element;
@@ -6,12 +6,11 @@ const remotion_1 = require("remotion");
6
6
  const colors_1 = require("../helpers/colors");
7
7
  const is_composition_still_1 = require("../helpers/is-composition-still");
8
8
  const render_frame_1 = require("../state/render-frame");
9
- exports.CURRENT_COMPOSITION_HEIGHT = 80;
9
+ exports.CURRENT_COMPOSITION_HEIGHT = 64;
10
10
  const container = {
11
11
  height: exports.CURRENT_COMPOSITION_HEIGHT,
12
12
  display: 'block',
13
- borderBottom: `1px solid ${colors_1.BORDER_COLOR}`,
14
- padding: 12,
13
+ padding: '6px 12px',
15
14
  color: 'white',
16
15
  backgroundColor: colors_1.BACKGROUND,
17
16
  };
@@ -6,6 +6,7 @@ const studio_shared_1 = require("@remotion/studio-shared");
6
6
  const colors_1 = require("../../helpers/colors");
7
7
  const layout_1 = require("../layout");
8
8
  const CircularProgress_1 = require("../RenderQueue/CircularProgress");
9
+ const client_render_progress_1 = require("../RenderQueue/client-render-progress");
9
10
  const SuccessIcon_1 = require("../RenderQueue/SuccessIcon");
10
11
  const progressItem = {
11
12
  padding: 10,
@@ -24,13 +25,16 @@ const right = {
24
25
  textAlign: 'right',
25
26
  flex: 1,
26
27
  };
27
- const EncodingProgress = ({ encodedFrames, totalFrames }) => {
28
- const done = encodedFrames === totalFrames;
29
- const progress = totalFrames > 0 ? encodedFrames / totalFrames : 0;
30
- return (jsx_runtime_1.jsxs("div", { style: progressItem, children: [done ? jsx_runtime_1.jsx(SuccessIcon_1.SuccessIcon, {}) : jsx_runtime_1.jsx(CircularProgress_1.CircularProgress, { progress: progress }), jsx_runtime_1.jsx(layout_1.Spacing, { x: 1 }), jsx_runtime_1.jsx("div", { style: label, children: done
31
- ? `Encoded ${totalFrames} frames`
32
- : `Encoding ${encodedFrames} / ${totalFrames} frames` })
33
- ] }));
28
+ const ProgressStatus = ({ encodedFrames, totalFrames, doneIn, renderEstimatedTime, progress }) => {
29
+ const done = doneIn !== null;
30
+ const message = (0, client_render_progress_1.getClientRenderProgressMessage)({
31
+ encodedFrames,
32
+ totalFrames,
33
+ doneIn,
34
+ renderEstimatedTime,
35
+ progress,
36
+ });
37
+ return (jsx_runtime_1.jsxs("div", { style: progressItem, children: [done ? jsx_runtime_1.jsx(SuccessIcon_1.SuccessIcon, {}) : jsx_runtime_1.jsx(CircularProgress_1.CircularProgress, { progress: progress }), jsx_runtime_1.jsx(layout_1.Spacing, { x: 1 }), jsx_runtime_1.jsx("div", { style: label, children: message }), doneIn !== null ? jsx_runtime_1.jsxs("div", { style: right, children: [doneIn, "ms"] }) : null] }));
34
38
  };
35
39
  const DoneStatus = ({ job }) => {
36
40
  return (jsx_runtime_1.jsxs("div", { style: progressItem, children: [
@@ -53,9 +57,9 @@ const ClientRenderProgress = ({ job }) => {
53
57
  jsx_runtime_1.jsx(layout_1.Spacing, { y: 0.5 }), jsx_runtime_1.jsx("div", { style: label, children: "Saving to out/..." }), jsx_runtime_1.jsx(layout_1.Spacing, { y: 1 })
54
58
  ] }));
55
59
  }
56
- const { encodedFrames, totalFrames } = job.progress;
60
+ const { encodedFrames, totalFrames, doneIn, renderEstimatedTime, progress } = job.progress;
57
61
  return (jsx_runtime_1.jsxs("div", { children: [
58
- jsx_runtime_1.jsx(layout_1.Spacing, { y: 0.5 }), job.type === 'client-video' && (jsx_runtime_1.jsx(EncodingProgress, { encodedFrames: encodedFrames, totalFrames: totalFrames })), jsx_runtime_1.jsx(layout_1.Spacing, { y: 1 })
62
+ jsx_runtime_1.jsx(layout_1.Spacing, { y: 0.5 }), job.type === 'client-video' && (jsx_runtime_1.jsx(ProgressStatus, { encodedFrames: encodedFrames, totalFrames: totalFrames, doneIn: doneIn, renderEstimatedTime: renderEstimatedTime, progress: progress })), jsx_runtime_1.jsx(layout_1.Spacing, { y: 1 })
59
63
  ] }));
60
64
  };
61
65
  exports.ClientRenderProgress = ClientRenderProgress;
@@ -90,6 +90,9 @@ const ClientRenderQueueProcessor = () => {
90
90
  onProgress(job.id, {
91
91
  encodedFrames: progress.encodedFrames,
92
92
  totalFrames,
93
+ doneIn: progress.doneIn,
94
+ renderEstimatedTime: progress.renderEstimatedTime,
95
+ progress: progress.progress,
93
96
  });
94
97
  },
95
98
  outputTarget: 'web-fs',
@@ -80,8 +80,7 @@ const RenderQueueItemStatus = ({ job }) => {
80
80
  if (job.status === 'running') {
81
81
  let progressValue;
82
82
  if (isClientJob) {
83
- const { encodedFrames, totalFrames } = job.progress;
84
- progressValue = totalFrames > 0 ? encodedFrames / totalFrames : 0;
83
+ progressValue = job.progress.progress;
85
84
  }
86
85
  else {
87
86
  progressValue = job.progress.value;
@@ -5,6 +5,7 @@ const jsx_runtime_1 = require("react/jsx-runtime");
5
5
  const react_1 = require("react");
6
6
  const modals_1 = require("../../state/modals");
7
7
  const z_index_1 = require("../../state/z-index");
8
+ const client_render_progress_1 = require("./client-render-progress");
8
9
  const context_1 = require("./context");
9
10
  const item_style_1 = require("./item-style");
10
11
  const outputLocation = {
@@ -24,9 +25,7 @@ const RenderQueueProgressMessage = ({ job }) => {
24
25
  });
25
26
  }, [job.id, setSelectedModal]);
26
27
  const message = isClientJob
27
- ? job.progress.totalFrames === 0
28
- ? 'Getting composition'
29
- : `Encoding frame ${job.progress.encodedFrames}/${job.progress.totalFrames}`
28
+ ? (0, client_render_progress_1.getClientRenderProgressMessage)(job.progress)
30
29
  : job.progress.message;
31
30
  return (jsx_runtime_1.jsx("button", { onClick: onClick, type: "button", style: outputLocation, tabIndex: tabIndex, title: message, children: message }));
32
31
  };
@@ -0,0 +1,3 @@
1
+ import type { ClientRenderJobProgress } from './client-side-render-types';
2
+ export declare const formatEtaString: (timeRemainingInMilliseconds: number) => string;
3
+ export declare const getClientRenderProgressMessage: (progress: ClientRenderJobProgress) => string;
@@ -0,0 +1,31 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.getClientRenderProgressMessage = exports.formatEtaString = void 0;
4
+ const formatEtaString = (timeRemainingInMilliseconds) => {
5
+ const remainingTime = timeRemainingInMilliseconds / 1000;
6
+ const remainingTimeHours = Math.floor(remainingTime / 3600);
7
+ const remainingTimeMinutes = Math.floor((remainingTime % 3600) / 60);
8
+ const remainingTimeSeconds = Math.floor(remainingTime % 60);
9
+ return [
10
+ remainingTimeHours ? `${remainingTimeHours}h` : null,
11
+ remainingTimeMinutes ? `${remainingTimeMinutes}m` : null,
12
+ `${remainingTimeSeconds}s`,
13
+ ]
14
+ .filter((value) => Boolean(value))
15
+ .join(' ');
16
+ };
17
+ exports.formatEtaString = formatEtaString;
18
+ const getClientRenderProgressMessage = (progress) => {
19
+ if (progress.totalFrames === 0) {
20
+ return 'Getting composition';
21
+ }
22
+ if (progress.doneIn !== null) {
23
+ return `Encoded ${progress.totalFrames}/${progress.totalFrames}`;
24
+ }
25
+ if (progress.renderEstimatedTime > 0) {
26
+ const etaString = `, time remaining: ${(0, exports.formatEtaString)(progress.renderEstimatedTime)}`;
27
+ return `Rendering ${progress.encodedFrames}/${progress.totalFrames}${etaString}`;
28
+ }
29
+ return `Encoded ${progress.encodedFrames}/${progress.totalFrames}`;
30
+ };
31
+ exports.getClientRenderProgressMessage = getClientRenderProgressMessage;
@@ -4,6 +4,9 @@ import type { LogLevel } from 'remotion';
4
4
  export type ClientRenderJobProgress = {
5
5
  encodedFrames: number;
6
6
  totalFrames: number;
7
+ doneIn: number | null;
8
+ renderEstimatedTime: number;
9
+ progress: number;
7
10
  };
8
11
  export type GetBlobCallback = () => Promise<Blob>;
9
12
  type ClientRenderJobDynamicStatus = {
@@ -86,7 +86,13 @@ const RenderQueueContextProvider = ({ children }) => {
86
86
  ? {
87
87
  ...job,
88
88
  status: 'running',
89
- progress: { encodedFrames: 0, totalFrames: 0 },
89
+ progress: {
90
+ encodedFrames: 0,
91
+ totalFrames: 0,
92
+ doneIn: null,
93
+ renderEstimatedTime: 0,
94
+ progress: 0,
95
+ },
90
96
  }
91
97
  : job));
92
98
  processJobCallbackRef.current(nextJob);