@remotion/studio 4.0.506 → 4.0.507

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 (119) hide show
  1. package/dist/api/copy-render-output-to-asset.d.ts +4 -0
  2. package/dist/api/copy-render-output-to-asset.js +11 -0
  3. package/dist/components/AssetSelector.js +19 -4
  4. package/dist/components/AssetSelectorItem.js +2 -2
  5. package/dist/components/CodingAgentIcon.d.ts +4 -0
  6. package/dist/components/CodingAgentIcon.js +17 -0
  7. package/dist/components/ConfigureDefaultEditorModal.d.ts +1 -3
  8. package/dist/components/ConfigureDefaultEditorModal.js +67 -77
  9. package/dist/components/ConfigureLicenseModal.d.ts +1 -4
  10. package/dist/components/ConfigureLicenseModal.js +89 -81
  11. package/dist/components/ContextMenu.js +10 -8
  12. package/dist/components/EditorContexts.js +6 -5
  13. package/dist/components/ExpandedTracksProvider.js +10 -53
  14. package/dist/components/InspectorLocationCopy.js +8 -8
  15. package/dist/components/InspectorOpenInEditor.d.ts +1 -0
  16. package/dist/components/InspectorOpenInEditor.js +39 -49
  17. package/dist/components/InspectorPanel/SequenceInspectorHeader.d.ts +3 -0
  18. package/dist/components/InspectorPanel/SequenceInspectorHeader.js +22 -4
  19. package/dist/components/InspectorPanel/SequenceSelectionInspector.js +1 -1
  20. package/dist/components/Menu/MenuSectionHeader.d.ts +4 -0
  21. package/dist/components/Menu/MenuSectionHeader.js +20 -0
  22. package/dist/components/Menu/SubMenu.js +13 -2
  23. package/dist/components/Menu/menu-tree-context.d.ts +3 -0
  24. package/dist/components/Menu/menu-tree-context.js +13 -0
  25. package/dist/components/NewComposition/ComboBox.d.ts +6 -1
  26. package/dist/components/NewComposition/MenuContent.js +27 -19
  27. package/dist/components/NewComposition/menu-typeahead.js +2 -2
  28. package/dist/components/Preview.js +29 -4
  29. package/dist/components/RenderModal/SchemaEditor/ZodEnumEditor.d.ts +1 -0
  30. package/dist/components/RenderModal/SchemaEditor/ZodEnumEditor.js +2 -2
  31. package/dist/components/RenderModal/SchemaEditor/ZodOrNullishEditor.js +3 -3
  32. package/dist/components/RenderModal/SchemaEditor/ZodSwitch.js +1 -1
  33. package/dist/components/RenderModal/ServerRenderModal.js +4 -0
  34. package/dist/components/RenderQueue/RenderQueueItem.js +8 -2
  35. package/dist/components/RenderQueue/actions.d.ts +4 -2
  36. package/dist/components/RenderQueue/actions.js +4 -2
  37. package/dist/components/RenderQueue/index.js +3 -4
  38. package/dist/components/RenderQueue/use-render-output-file-drag.d.ts +8 -0
  39. package/dist/components/RenderQueue/use-render-output-file-drag.js +121 -0
  40. package/dist/components/SegmentedControl.js +0 -1
  41. package/dist/components/SelectedOutlineElement.d.ts +14 -17
  42. package/dist/components/SelectedOutlineElement.js +112 -930
  43. package/dist/components/SelectedOutlineKeyboardControls.d.ts +7 -0
  44. package/dist/components/SelectedOutlineKeyboardControls.js +261 -0
  45. package/dist/components/SelectedOutlineOverlay.d.ts +6 -13
  46. package/dist/components/SelectedOutlineOverlay.js +349 -864
  47. package/dist/components/SelectedOutlinePolygon.d.ts +25 -0
  48. package/dist/components/SelectedOutlinePolygon.js +359 -0
  49. package/dist/components/SelectedOutlineRenderer.d.ts +18 -0
  50. package/dist/components/SelectedOutlineRenderer.js +208 -0
  51. package/dist/components/SelectedOutlineRotationCornerHandle.d.ts +16 -0
  52. package/dist/components/SelectedOutlineRotationCornerHandle.js +269 -0
  53. package/dist/components/SelectedOutlineScaleEdgeLine.d.ts +16 -0
  54. package/dist/components/SelectedOutlineScaleEdgeLine.js +211 -0
  55. package/dist/components/SelectedOutlineSnapIndicators.d.ts +9 -0
  56. package/dist/components/SelectedOutlineSnapIndicators.js +29 -0
  57. package/dist/components/SelectedOutlineTransformOriginHandle.d.ts +9 -0
  58. package/dist/components/SelectedOutlineTransformOriginHandle.js +286 -0
  59. package/dist/components/SelectedOutlineUvControls.d.ts +3 -9
  60. package/dist/components/SelectedOutlineUvControls.js +57 -12
  61. package/dist/components/SettingsContext.d.ts +15 -0
  62. package/dist/components/SettingsContext.js +116 -0
  63. package/dist/components/SettingsModal.js +10 -4
  64. package/dist/components/SettingsModalFooter.d.ts +1 -3
  65. package/dist/components/SettingsModalFooter.js +4 -6
  66. package/dist/components/ShowOutlinesProvider.js +2 -3
  67. package/dist/components/Timeline/EasingEditorModal.js +66 -22
  68. package/dist/components/Timeline/Timeline.js +22 -5
  69. package/dist/components/Timeline/TimelineDuplicateCount.d.ts +4 -0
  70. package/dist/components/Timeline/TimelineDuplicateCount.js +28 -0
  71. package/dist/components/Timeline/TimelineExpandedKeyframeRow.js +3 -23
  72. package/dist/components/Timeline/TimelineExpandedTrackKeyframes.d.ts +4 -2
  73. package/dist/components/Timeline/TimelineExpandedTrackKeyframes.js +11 -1
  74. package/dist/components/Timeline/TimelineSequence.js +28 -25
  75. package/dist/components/Timeline/TimelineSequenceItem.js +49 -27
  76. package/dist/components/Timeline/TimelineTrack.js +2 -1
  77. package/dist/components/Timeline/get-sequence-context-menu-items.d.ts +6 -3
  78. package/dist/components/Timeline/get-sequence-context-menu-items.js +58 -53
  79. package/dist/components/Timeline/use-expanded-track-keyframe-rows.js +36 -4
  80. package/dist/components/Timeline/{use-open-sequence-in-editor.d.ts → use-open-sequence-in-apps.d.ts} +4 -1
  81. package/dist/components/Timeline/{use-open-sequence-in-editor.js → use-open-sequence-in-apps.js} +20 -4
  82. package/dist/components/Timeline/use-timeline-expanded-tree.d.ts +4 -0
  83. package/dist/components/Timeline/use-timeline-expanded-tree.js +45 -1
  84. package/dist/components/get-open-in-menu-items.d.ts +12 -0
  85. package/dist/components/get-open-in-menu-items.js +83 -0
  86. package/dist/components/selected-outline-measurement.d.ts +2 -2
  87. package/dist/components/selected-outline-order.d.ts +12 -0
  88. package/dist/components/selected-outline-order.js +251 -0
  89. package/dist/components/selected-outline-types.d.ts +9 -10
  90. package/dist/components/svg-point-to-client-point.d.ts +2 -0
  91. package/dist/components/svg-point-to-client-point.js +10 -0
  92. package/dist/components/use-auto-save-config.d.ts +8 -0
  93. package/dist/components/use-auto-save-config.js +74 -0
  94. package/dist/components/use-default-editor-info.d.ts +1 -0
  95. package/dist/components/use-default-editor-info.js +10 -30
  96. package/dist/esm/{chunk-jefhcs5z.js → chunk-fgedsvhb.js} +1 -2
  97. package/dist/esm/{chunk-b49ec3nz.js → chunk-ptnd65a9.js} +10602 -9364
  98. package/dist/esm/internals.mjs +10601 -9363
  99. package/dist/esm/previewEntry.mjs +10462 -9224
  100. package/dist/esm/renderEntry.mjs +2 -2
  101. package/dist/helpers/are-sequence-node-path-infos-equal.d.ts +2 -0
  102. package/dist/helpers/are-sequence-node-path-infos-equal.js +27 -0
  103. package/dist/helpers/calculate-timeline.js +3 -3
  104. package/dist/helpers/client-id.js +8 -1
  105. package/dist/helpers/format-file-location.d.ts +1 -1
  106. package/dist/helpers/format-file-location.js +3 -3
  107. package/dist/helpers/migrate-expanded-tracks-for-subscription-key.js +3 -3
  108. package/dist/helpers/open-in-editor.d.ts +1 -0
  109. package/dist/helpers/open-in-editor.js +5 -1
  110. package/dist/helpers/studio-runtime-config.js +3 -0
  111. package/dist/helpers/timeline-node-path-key.d.ts +2 -0
  112. package/dist/helpers/timeline-node-path-key.js +3 -1
  113. package/dist/helpers/use-asset-drag-events.d.ts +2 -1
  114. package/dist/helpers/use-asset-drag-events.js +14 -6
  115. package/dist/helpers/use-menu-structure.js +2 -2
  116. package/dist/helpers/use-runtime-values.d.ts +1 -3
  117. package/dist/state/timeline-sequence-hover.d.ts +9 -3
  118. package/dist/state/timeline-sequence-hover.js +63 -12
  119. package/package.json +12 -12
@@ -0,0 +1,4 @@
1
+ export declare const copyRenderOutputToAsset: ({ outputPath, assetPath, }: {
2
+ outputPath: string;
3
+ assetPath: string;
4
+ }) => Promise<import("@remotion/studio-shared").CopyRenderOutputToAssetResponse>;
@@ -0,0 +1,11 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.copyRenderOutputToAsset = void 0;
4
+ const call_api_1 = require("../components/call-api");
5
+ const copyRenderOutputToAsset = ({ outputPath, assetPath, }) => {
6
+ return (0, call_api_1.callApi)('/api/copy-render-output-to-asset', {
7
+ outputPath,
8
+ assetPath,
9
+ });
10
+ };
11
+ exports.copyRenderOutputToAsset = copyRenderOutputToAsset;
@@ -36,6 +36,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
36
36
  exports.AssetSelector = void 0;
37
37
  const jsx_runtime_1 = require("react/jsx-runtime");
38
38
  const react_1 = require("react");
39
+ const copy_render_output_to_asset_1 = require("../api/copy-render-output-to-asset");
39
40
  const write_static_file_1 = require("../api/write-static-file");
40
41
  const browser_studio_operations_1 = require("../helpers/browser-studio-operations");
41
42
  const client_id_1 = require("../helpers/client-id");
@@ -109,25 +110,39 @@ const AssetSelector = ({ readOnlyStudio }) => {
109
110
  setDropLocation,
110
111
  });
111
112
  const onDragOver = (0, react_1.useCallback)((e) => {
112
- if (!(0, use_asset_drag_events_1.isFileDragEvent)(e)) {
113
+ if (!(0, use_asset_drag_events_1.isAssetUploadDragEvent)(e)) {
113
114
  return;
114
115
  }
115
116
  e.preventDefault();
116
117
  }, []);
117
118
  const onDrop = (0, react_1.useCallback)(async (e) => {
118
119
  try {
119
- if (!(0, use_asset_drag_events_1.isFileDragEvent)(e)) {
120
+ if (!(0, use_asset_drag_events_1.isAssetUploadDragEvent)(e)) {
120
121
  setDropLocation(null);
121
122
  return;
122
123
  }
123
124
  e.preventDefault();
124
125
  e.stopPropagation();
126
+ const assetPath = dropLocation !== null && dropLocation !== void 0 ? dropLocation : null;
127
+ const renderOutput = (0, use_asset_drag_events_1.getRenderOutputDragData)(e.dataTransfer);
128
+ if (renderOutput) {
129
+ const destination = [assetPath, renderOutput.fileName]
130
+ .filter(Boolean)
131
+ .join('/');
132
+ const result = await (0, copy_render_output_to_asset_1.copyRenderOutputToAsset)({
133
+ outputPath: renderOutput.outputPath,
134
+ assetPath: destination,
135
+ });
136
+ (0, NotificationCenter_1.showNotification)(result.created
137
+ ? `Created ${destination}`
138
+ : `${destination} already exists`, 3000);
139
+ return;
140
+ }
125
141
  const { files } = e.dataTransfer;
126
142
  if (files.length === 0) {
127
143
  setDropLocation(null);
128
144
  return;
129
145
  }
130
- const assetPath = dropLocation !== null && dropLocation !== void 0 ? dropLocation : null;
131
146
  const makePath = (file) => {
132
147
  return [assetPath, file.name].filter(Boolean).join('/');
133
148
  };
@@ -161,7 +176,7 @@ const AssetSelector = ({ readOnlyStudio }) => {
161
176
  setDropLocation(null);
162
177
  }
163
178
  }, [dropLocation, staticFiles]);
164
- return (jsx_runtime_1.jsxs("div", { style: container, onDragOver: shouldAllowUpload ? onDragOver : undefined, onDrop: shouldAllowUpload ? onDrop : undefined, children: [
179
+ return (jsx_runtime_1.jsxs("div", { "data-asset-selector": true, style: container, onDragOver: shouldAllowUpload ? onDragOver : undefined, onDrop: shouldAllowUpload ? onDrop : undefined, children: [
165
180
  jsx_runtime_1.jsx(ExplorerQuickSwitcherTrigger_1.ExplorerQuickSwitcherTrigger, { mode: "assets", showShortcut: true, tabIndex: tabIndex }), staticFiles.length === 0 ? (publicFolderExists ? (jsx_runtime_1.jsx("div", { style: emptyState, children: jsx_runtime_1.jsxs("div", { style: label, children: ["To add assets, place a file in the", ' ', jsx_runtime_1.jsx("code", { style: styles_1.inlineCodeSnippet, children: "public" }),
166
181
  " folder of your project or drag and drop a file here."] }) })) : (jsx_runtime_1.jsx("div", { style: emptyState, children: jsx_runtime_1.jsxs("div", { style: label, children: ["To add assets, create a folder called", ' ', jsx_runtime_1.jsx("code", { style: styles_1.inlineCodeSnippet, children: "public" }),
167
182
  " in the root of your project and place a file in it."] }) }))) : (jsx_runtime_1.jsx("div", { className: "__remotion-vertical-scrollbar", style: {
@@ -226,7 +226,7 @@ const AssetFolderItem = ({ tabIndex, item, level, parentFolder, toggleFolder, dr
226
226
  backgroundColor: isDropDiv ? colors_1.WHITE_ALPHA_06 : colors_1.BACKGROUND,
227
227
  }, children: [
228
228
  jsx_runtime_1.jsx("div", { style: folderStyle, onPointerEnter: onPointerEnter, onPointerLeave: onPointerLeave, tabIndex: tabIndex, title: item.name, onClick: onClick, onDragEnter: (event) => {
229
- if (!(0, use_asset_drag_events_1.isFileDragEvent)(event)) {
229
+ if (!(0, use_asset_drag_events_1.isAssetUploadDragEvent)(event)) {
230
230
  return;
231
231
  }
232
232
  if (!item.expanded) {
@@ -235,7 +235,7 @@ const AssetFolderItem = ({ tabIndex, item, level, parentFolder, toggleFolder, dr
235
235
  }, 1000);
236
236
  }
237
237
  }, onDragLeave: (event) => {
238
- if (!(0, use_asset_drag_events_1.isFileDragEvent)(event)) {
238
+ if (!(0, use_asset_drag_events_1.isAssetUploadDragEvent)(event)) {
239
239
  return;
240
240
  }
241
241
  if (openFolderTimerRef.current) {
@@ -0,0 +1,4 @@
1
+ import React from 'react';
2
+ export declare const CodingAgentIcon: React.FC<{
3
+ readonly iconDataUrl: string | null;
4
+ }>;
@@ -0,0 +1,17 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.CodingAgentIcon = void 0;
4
+ const jsx_runtime_1 = require("react/jsx-runtime");
5
+ const apps_1 = require("../icons/apps");
6
+ const iconStyle = {
7
+ flexShrink: 0,
8
+ height: 18,
9
+ width: 18,
10
+ };
11
+ const CodingAgentIcon = ({ iconDataUrl }) => {
12
+ if (iconDataUrl === null) {
13
+ return jsx_runtime_1.jsx(apps_1.AppsIcon, { height: 18, width: 18 });
14
+ }
15
+ return (jsx_runtime_1.jsx("img", { alt: "", "aria-hidden": true, draggable: false, src: iconDataUrl, style: iconStyle }));
16
+ };
17
+ exports.CodingAgentIcon = CodingAgentIcon;
@@ -1,4 +1,2 @@
1
1
  import React from 'react';
2
- export declare const DefaultEditorSettings: React.FC<{
3
- readonly onSaved: () => void;
4
- }>;
2
+ export declare const DefaultEditorSettings: React.FC;
@@ -5,13 +5,13 @@ 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 Checkmark_1 = require("../icons/Checkmark");
8
- const custom_editor_1 = require("../icons/custom-editor");
9
- const call_api_1 = require("./call-api");
8
+ const editor_1 = require("../icons/editor");
9
+ const CodingAgentIcon_1 = require("./CodingAgentIcon");
10
10
  const layout_1 = require("./layout");
11
- const ModalButton_1 = require("./ModalButton");
12
11
  const ComboBox_1 = require("./NewComposition/ComboBox");
13
12
  const ValidationMessage_1 = require("./NewComposition/ValidationMessage");
14
- const SettingsModalFooter_1 = require("./SettingsModalFooter");
13
+ const SettingsContext_1 = require("./SettingsContext");
14
+ const use_auto_save_config_1 = require("./use-auto-save-config");
15
15
  const container = {
16
16
  display: 'flex',
17
17
  flex: 1,
@@ -30,7 +30,7 @@ const description = {
30
30
  margin: 0,
31
31
  };
32
32
  const title = {
33
- color: colors_1.WHITE,
33
+ color: colors_1.LIGHT_TEXT,
34
34
  fontFamily: 'sans-serif',
35
35
  fontSize: 14,
36
36
  lineHeight: 1.5,
@@ -40,8 +40,8 @@ const comboBoxStyle = {
40
40
  boxSizing: 'border-box',
41
41
  width: '100%',
42
42
  };
43
- const customEditorLabel = {
44
- display: 'inline-flex',
43
+ const appLabel = {
44
+ display: 'flex',
45
45
  alignItems: 'center',
46
46
  gap: 8,
47
47
  maxWidth: '100%',
@@ -51,7 +51,7 @@ const customEditorLabel = {
51
51
  fontSize: 'inherit',
52
52
  lineHeight: 'inherit',
53
53
  };
54
- const customEditorName = {
54
+ const appName = {
55
55
  minWidth: 0,
56
56
  overflow: 'hidden',
57
57
  textOverflow: 'ellipsis',
@@ -62,12 +62,11 @@ const customEditorName = {
62
62
  lineHeight: 'inherit',
63
63
  };
64
64
  const NO_PREFERENCE_ID = 'no-preference';
65
- const DefaultEditorSettings = ({ onSaved }) => {
66
- const [editorInfo, setEditorInfo] = (0, react_1.useState)(null);
67
- const [codingAgentInfo, setCodingAgentInfo] = (0, react_1.useState)(null);
65
+ const DefaultEditorSettings = () => {
66
+ const { codingAgentInfo, editorInfo, error: settingsError, revision, } = (0, SettingsContext_1.useSettings)();
68
67
  const [selectedEditor, setSelectedEditor] = (0, react_1.useState)(null);
69
68
  const [selectedCodingAgent, setSelectedCodingAgent] = (0, react_1.useState)(null);
70
- const [isSubmitting, setIsSubmitting] = (0, react_1.useState)(false);
69
+ const [syncedRevision, setSyncedRevision] = (0, react_1.useState)(-1);
71
70
  const [error, setError] = (0, react_1.useState)(null);
72
71
  const editorValues = (0, react_1.useMemo)(() => {
73
72
  var _a;
@@ -89,9 +88,9 @@ const DefaultEditorSettings = ({ onSaved }) => {
89
88
  return {
90
89
  id: editor.id,
91
90
  keyHint: null,
92
- label: editor.id === 'custom' ? (jsx_runtime_1.jsxs("span", { style: customEditorLabel, children: [
93
- jsx_runtime_1.jsx(custom_editor_1.CustomEditorIcon, { size: null }), jsx_runtime_1.jsx("span", { style: customEditorName, children: editor.name })
94
- ] })) : (editor.name),
91
+ label: (jsx_runtime_1.jsxs("span", { style: appLabel, children: [
92
+ jsx_runtime_1.jsx(editor_1.EditorIcon, { editorId: editor.id, size: 18 }), jsx_runtime_1.jsx("span", { style: appName, children: editor.name })
93
+ ] })),
95
94
  leftItem: selectedEditor === editor.id ? jsx_runtime_1.jsx(Checkmark_1.Checkmark, {}) : null,
96
95
  onClick: () => {
97
96
  setSelectedEditor(editor.id);
@@ -125,7 +124,9 @@ const DefaultEditorSettings = ({ onSaved }) => {
125
124
  return {
126
125
  id: codingAgent.id,
127
126
  keyHint: null,
128
- label: codingAgent.name,
127
+ label: (jsx_runtime_1.jsxs("span", { style: appLabel, children: [
128
+ jsx_runtime_1.jsx(CodingAgentIcon_1.CodingAgentIcon, { iconDataUrl: codingAgent.iconDataUrl }), jsx_runtime_1.jsx("span", { style: appName, children: codingAgent.name })
129
+ ] })),
129
130
  leftItem: selectedCodingAgent === codingAgent.id ? jsx_runtime_1.jsx(Checkmark_1.Checkmark, {}) : null,
130
131
  onClick: () => {
131
132
  setSelectedCodingAgent(codingAgent.id);
@@ -140,70 +141,59 @@ const DefaultEditorSettings = ({ onSaved }) => {
140
141
  return [noPreference, ...installedCodingAgents];
141
142
  }, [codingAgentInfo === null || codingAgentInfo === void 0 ? void 0 : codingAgentInfo.installedCodingAgents, selectedCodingAgent]);
142
143
  (0, react_1.useEffect)(() => {
143
- const controller = new AbortController();
144
- Promise.all([
145
- (0, call_api_1.callApi)('/api/default-editor-info', {}, controller.signal),
146
- (0, call_api_1.callApi)('/api/default-coding-agent-info', {}, controller.signal),
147
- ])
148
- .then(([editorResponse, codingAgentResponse]) => {
149
- setEditorInfo(editorResponse);
150
- setSelectedEditor(editorResponse.defaultEditor !== null &&
151
- editorResponse.installedEditors.some(({ id }) => id === editorResponse.defaultEditor)
152
- ? editorResponse.defaultEditor
153
- : null);
154
- setCodingAgentInfo(codingAgentResponse);
155
- setSelectedCodingAgent(codingAgentResponse.defaultCodingAgent !== null &&
156
- codingAgentResponse.installedCodingAgents.some(({ id }) => id === codingAgentResponse.defaultCodingAgent)
157
- ? codingAgentResponse.defaultCodingAgent
158
- : null);
159
- })
160
- .catch((err) => {
161
- if (controller.signal.aborted) {
162
- return;
163
- }
164
- setError(err.message);
165
- });
166
- return () => controller.abort();
167
- }, []);
168
- const submit = (0, react_1.useCallback)(async () => {
169
144
  if (editorInfo === null || codingAgentInfo === null) {
170
145
  return;
171
146
  }
172
- setIsSubmitting(true);
147
+ setSelectedEditor(editorInfo.defaultEditor !== null &&
148
+ editorInfo.installedEditors.some(({ id }) => id === editorInfo.defaultEditor)
149
+ ? editorInfo.defaultEditor
150
+ : null);
151
+ setSelectedCodingAgent(codingAgentInfo.defaultCodingAgent !== null &&
152
+ codingAgentInfo.installedCodingAgents.some(({ id }) => id === codingAgentInfo.defaultCodingAgent)
153
+ ? codingAgentInfo.defaultCodingAgent
154
+ : null);
155
+ setSyncedRevision(revision);
173
156
  setError(null);
174
- try {
175
- const editorResponse = await (0, call_api_1.callApi)('/api/update-default-editor', {
176
- defaultEditor: selectedEditor,
177
- });
178
- if (!editorResponse.success) {
179
- setError(editorResponse.reason);
180
- setIsSubmitting(false);
181
- return;
182
- }
183
- const codingAgentResponse = await (0, call_api_1.callApi)('/api/update-default-coding-agent', { defaultCodingAgent: selectedCodingAgent });
184
- if (!codingAgentResponse.success) {
185
- setError(codingAgentResponse.reason);
186
- setIsSubmitting(false);
187
- return;
188
- }
189
- onSaved();
190
- }
191
- catch (err) {
192
- setError(err.message);
193
- setIsSubmitting(false);
194
- }
195
- }, [
196
- codingAgentInfo,
197
- editorInfo,
198
- onSaved,
199
- selectedCodingAgent,
200
- selectedEditor,
201
- ]);
202
- return (jsx_runtime_1.jsxs("div", { style: container, children: [
203
- jsx_runtime_1.jsxs("div", { style: content, children: [
204
- jsx_runtime_1.jsx("p", { style: title, children: "Default editor" }), jsx_runtime_1.jsx("p", { style: description, children: "Used when Remotion Studio opens source files." }), jsx_runtime_1.jsx(layout_1.Spacing, { y: 1, block: true }), editorInfo === null && error === null ? (jsx_runtime_1.jsx("p", { style: description, children: "Loading installed editors..." })) : null, (editorInfo === null || editorInfo === void 0 ? void 0 : editorInfo.installedEditors.length) === 0 ? (jsx_runtime_1.jsx("p", { style: description, children: "No supported editors were found on this computer." })) : null, editorInfo === null ? null : (jsx_runtime_1.jsx(ComboBox_1.Combobox, { values: editorValues, selectedId: selectedEditor !== null && selectedEditor !== void 0 ? selectedEditor : NO_PREFERENCE_ID, style: comboBoxStyle, title: "Default editor" })), jsx_runtime_1.jsx(layout_1.Spacing, { y: 2, block: true }), jsx_runtime_1.jsx("p", { style: title, children: "Default coding agent" }), jsx_runtime_1.jsx("p", { style: description, children: "Used when Remotion Studio hands a project to a coding agent." }), jsx_runtime_1.jsx(layout_1.Spacing, { y: 1, block: true }), codingAgentInfo === null && error === null ? (jsx_runtime_1.jsx("p", { style: description, children: "Loading installed coding agents..." })) : null, (codingAgentInfo === null || codingAgentInfo === void 0 ? void 0 : codingAgentInfo.installedCodingAgents.length) === 0 ? (jsx_runtime_1.jsx("p", { style: description, children: "No supported coding agents were found on this computer." })) : null, codingAgentInfo === null ? null : (jsx_runtime_1.jsx(ComboBox_1.Combobox, { values: codingAgentValues, selectedId: selectedCodingAgent !== null && selectedCodingAgent !== void 0 ? selectedCodingAgent : NO_PREFERENCE_ID, style: comboBoxStyle, title: "Default coding agent" })), error ? (jsx_runtime_1.jsxs(jsx_runtime_1.Fragment, { children: [
205
- jsx_runtime_1.jsx(layout_1.Spacing, { y: 1.5 }), jsx_runtime_1.jsx(ValidationMessage_1.ValidationMessage, { message: error, align: "flex-start", type: "error" })
206
- ] })) : null] }), jsx_runtime_1.jsx(SettingsModalFooter_1.SettingsModalFooter, { children: jsx_runtime_1.jsx(ModalButton_1.ModalButton, { onClick: submit, disabled: isSubmitting || editorInfo === null || codingAgentInfo === null, children: isSubmitting ? 'Saving...' : 'Save and reload' }) })
207
- ] }));
157
+ }, [codingAgentInfo, editorInfo, revision]);
158
+ const updates = (0, react_1.useMemo)(() => {
159
+ // The browser only receives an opaque ID for a custom editor. Omitting the
160
+ // update preserves its executable and arguments in the existing config call.
161
+ const editorUpdate = selectedEditor === 'custom'
162
+ ? []
163
+ : [
164
+ selectedEditor === null
165
+ ? { setter: 'setDefaultEditor', type: 'delete' }
166
+ : {
167
+ setter: 'setDefaultEditor',
168
+ type: 'set',
169
+ value: selectedEditor,
170
+ },
171
+ ];
172
+ return [
173
+ ...editorUpdate,
174
+ selectedCodingAgent === null
175
+ ? { setter: 'setDefaultCodingAgent', type: 'delete' }
176
+ : {
177
+ setter: 'setDefaultCodingAgent',
178
+ type: 'set',
179
+ value: selectedCodingAgent,
180
+ },
181
+ ];
182
+ }, [selectedCodingAgent, selectedEditor]);
183
+ const ready = editorInfo !== null &&
184
+ codingAgentInfo !== null &&
185
+ syncedRevision === revision;
186
+ (0, use_auto_save_config_1.useAutoSaveConfig)({
187
+ enabled: ready,
188
+ onError: setError,
189
+ ready,
190
+ syncRevision: syncedRevision,
191
+ updates,
192
+ });
193
+ const displayedError = error !== null && error !== void 0 ? error : settingsError;
194
+ return (jsx_runtime_1.jsx("div", { style: container, children: jsx_runtime_1.jsxs("div", { style: content, children: [
195
+ jsx_runtime_1.jsx("p", { style: title, children: "Default editor" }), jsx_runtime_1.jsx(layout_1.Spacing, { y: 1, block: true }), editorInfo === null && displayedError === null ? (jsx_runtime_1.jsx("p", { style: description, children: "Loading installed editors..." })) : null, (editorInfo === null || editorInfo === void 0 ? void 0 : editorInfo.installedEditors.length) === 0 ? (jsx_runtime_1.jsx("p", { style: description, children: "No supported editors were found on this computer." })) : null, editorInfo === null ? null : (jsx_runtime_1.jsx(ComboBox_1.Combobox, { values: editorValues, selectedId: selectedEditor !== null && selectedEditor !== void 0 ? selectedEditor : NO_PREFERENCE_ID, style: comboBoxStyle, title: "Default editor" })), jsx_runtime_1.jsx(layout_1.Spacing, { y: 2, block: true }), jsx_runtime_1.jsx("p", { style: title, children: "Default coding agent" }), jsx_runtime_1.jsx(layout_1.Spacing, { y: 1, block: true }), codingAgentInfo === null && displayedError === null ? (jsx_runtime_1.jsx("p", { style: description, children: "Loading installed coding agents..." })) : null, (codingAgentInfo === null || codingAgentInfo === void 0 ? void 0 : codingAgentInfo.installedCodingAgents.length) === 0 ? (jsx_runtime_1.jsx("p", { style: description, children: "No supported coding agents were found on this computer." })) : null, codingAgentInfo === null ? null : (jsx_runtime_1.jsx(ComboBox_1.Combobox, { values: codingAgentValues, selectedId: selectedCodingAgent !== null && selectedCodingAgent !== void 0 ? selectedCodingAgent : NO_PREFERENCE_ID, style: comboBoxStyle, title: "Default coding agent" })), displayedError ? (jsx_runtime_1.jsxs(jsx_runtime_1.Fragment, { children: [
196
+ jsx_runtime_1.jsx(layout_1.Spacing, { y: 1.5 }), jsx_runtime_1.jsx(ValidationMessage_1.ValidationMessage, { message: displayedError, align: "flex-start", type: "error" })
197
+ ] })) : null] }) }));
208
198
  };
209
199
  exports.DefaultEditorSettings = DefaultEditorSettings;
@@ -1,5 +1,2 @@
1
1
  import React from 'react';
2
- export declare const LicenseSettings: React.FC<{
3
- readonly initialPublicLicenseKey: string | null;
4
- readonly onSaved: () => void;
5
- }>;
2
+ export declare const LicenseSettings: React.FC;
@@ -4,14 +4,13 @@ exports.LicenseSettings = void 0;
4
4
  const jsx_runtime_1 = require("react/jsx-runtime");
5
5
  const react_1 = require("react");
6
6
  const colors_1 = require("../helpers/colors");
7
- const call_api_1 = require("./call-api");
8
7
  const Checkbox_1 = require("./Checkbox");
9
8
  const layout_1 = require("./layout");
10
9
  const LicenseKeyValidation_1 = require("./LicenseKeyValidation");
11
- const ModalButton_1 = require("./ModalButton");
12
10
  const RemInput_1 = require("./NewComposition/RemInput");
13
11
  const ValidationMessage_1 = require("./NewComposition/ValidationMessage");
14
- const SettingsModalFooter_1 = require("./SettingsModalFooter");
12
+ const SettingsContext_1 = require("./SettingsContext");
13
+ const use_auto_save_config_1 = require("./use-auto-save-config");
15
14
  const container = {
16
15
  display: 'flex',
17
16
  flex: 1,
@@ -60,19 +59,34 @@ const inputLabel = {
60
59
  marginBottom: 6,
61
60
  marginTop: 10,
62
61
  };
63
- const LicenseSettings = ({ initialPublicLicenseKey, onSaved }) => {
64
- const initialLicenseType = initialPublicLicenseKey === 'free-license'
62
+ const LicenseSettings = () => {
63
+ const { error: settingsError, publicLicenseKey, revision } = (0, SettingsContext_1.useSettings)();
64
+ const initialLicenseType = publicLicenseKey === 'free-license'
65
65
  ? 'free'
66
- : initialPublicLicenseKey === null
66
+ : publicLicenseKey === null
67
67
  ? null
68
68
  : 'company';
69
69
  const [licenseType, setLicenseType] = (0, react_1.useState)(initialLicenseType);
70
- const [companyLicenseKey, setCompanyLicenseKey] = (0, react_1.useState)(initialLicenseType === 'company' ? (initialPublicLicenseKey !== null && initialPublicLicenseKey !== void 0 ? initialPublicLicenseKey : '') : '');
71
- const [isSubmitting, setIsSubmitting] = (0, react_1.useState)(false);
70
+ const [companyLicenseKey, setCompanyLicenseKey] = (0, react_1.useState)(initialLicenseType === 'company' ? (publicLicenseKey !== null && publicLicenseKey !== void 0 ? publicLicenseKey : '') : '');
71
+ const [companyLicenseKeyToSave, setCompanyLicenseKeyToSave] = (0, react_1.useState)(companyLicenseKey);
72
72
  const [error, setError] = (0, react_1.useState)(null);
73
+ const [syncedRevision, setSyncedRevision] = (0, react_1.useState)(revision);
73
74
  const [isValidatingLicenseKey, setIsValidatingLicenseKey] = (0, react_1.useState)(false);
74
75
  const [remoteValidationMessage, setRemoteValidationMessage] = (0, react_1.useState)(null);
75
76
  const [licenseKeyDetails, setLicenseKeyDetails] = (0, react_1.useState)(null);
77
+ (0, react_1.useEffect)(() => {
78
+ const nextLicenseType = publicLicenseKey === 'free-license'
79
+ ? 'free'
80
+ : publicLicenseKey === null
81
+ ? null
82
+ : 'company';
83
+ const nextCompanyLicenseKey = nextLicenseType === 'company' ? (publicLicenseKey !== null && publicLicenseKey !== void 0 ? publicLicenseKey : '') : '';
84
+ setLicenseType(nextLicenseType);
85
+ setCompanyLicenseKey(nextCompanyLicenseKey);
86
+ setCompanyLicenseKeyToSave(nextCompanyLicenseKey);
87
+ setSyncedRevision(revision);
88
+ setError(null);
89
+ }, [publicLicenseKey, revision]);
76
90
  const toggleLicenseType = (0, react_1.useCallback)((newLicenseType) => {
77
91
  setLicenseType((currentLicenseType) => currentLicenseType === newLicenseType ? null : newLicenseType);
78
92
  setError(null);
@@ -83,15 +97,6 @@ const LicenseSettings = ({ initialPublicLicenseKey, onSaved }) => {
83
97
  const toggleCompanyLicense = (0, react_1.useCallback)(() => {
84
98
  toggleLicenseType('company');
85
99
  }, [toggleLicenseType]);
86
- const publicLicenseKey = (0, react_1.useMemo)(() => {
87
- if (licenseType === 'free') {
88
- return 'free-license';
89
- }
90
- if (licenseType === 'company') {
91
- return companyLicenseKey.trim();
92
- }
93
- return '';
94
- }, [companyLicenseKey, licenseType]);
95
100
  const localLicenseKeyValidation = (0, react_1.useMemo)(() => (0, LicenseKeyValidation_1.validateLicenseKey)(companyLicenseKey.trim()), [companyLicenseKey]);
96
101
  (0, react_1.useEffect)(() => {
97
102
  let cancelled = false;
@@ -131,72 +136,75 @@ const LicenseSettings = ({ initialPublicLicenseKey, onSaved }) => {
131
136
  const companyLicenseKeyIsValid = localLicenseKeyValidation.valid &&
132
137
  (licenseKeyDetails === null || licenseKeyDetails === void 0 ? void 0 : licenseKeyDetails.isValid) === true &&
133
138
  !isValidatingLicenseKey;
134
- const submit = (0, react_1.useCallback)(async () => {
135
- if (publicLicenseKey.length === 0) {
136
- setError(licenseType === null
137
- ? 'Select a license type.'
138
- : 'Enter your public license key.');
139
- return;
140
- }
141
- if (licenseType === 'company' && !companyLicenseKeyIsValid) {
142
- return;
139
+ const publicLicenseKeyToSave = (0, react_1.useMemo)(() => {
140
+ if (licenseType === 'free') {
141
+ return 'free-license';
143
142
  }
144
- setIsSubmitting(true);
145
- setError(null);
146
- try {
147
- const response = await (0, call_api_1.callApi)('/api/update-public-license', {
148
- publicLicenseKey,
149
- });
150
- if (!response.success) {
151
- setError(response.reason);
152
- setIsSubmitting(false);
153
- return;
154
- }
155
- onSaved();
143
+ if (licenseType === 'company') {
144
+ return companyLicenseKeyToSave;
156
145
  }
157
- catch (err) {
158
- setError(err.message);
159
- setIsSubmitting(false);
146
+ return '';
147
+ }, [companyLicenseKeyToSave, licenseType]);
148
+ const updates = (0, react_1.useMemo)(() => {
149
+ if (licenseType === null) {
150
+ return [{ setter: 'setPublicLicenseKey', type: 'delete' }];
160
151
  }
161
- }, [companyLicenseKeyIsValid, licenseType, onSaved, publicLicenseKey]);
162
- return (jsx_runtime_1.jsxs("div", { style: container, children: [
163
- jsx_runtime_1.jsxs("div", { style: content, children: [
164
- jsx_runtime_1.jsxs("p", { style: description, children: ["Remotion is free to use if you are an individual or company with a headcount of 3 or less.",
165
- jsx_runtime_1.jsx("br", {}),
166
- "If used in an organization with 4 people or more, a", ' ', jsx_runtime_1.jsx("a", { style: descriptionLink, href: "https://remotion.pro/license", children: "Company License" }), ' needs to be obtained.'] }), jsx_runtime_1.jsx(layout_1.Spacing, { y: 2 }), jsx_runtime_1.jsxs("div", { style: checkboxRow, onClick: (event) => {
167
- if (!(event.target instanceof HTMLInputElement)) {
168
- toggleFreeLicense();
169
- }
170
- }, children: [
171
- jsx_runtime_1.jsx(Checkbox_1.Checkbox, { checked: licenseType === 'free', onChange: toggleFreeLicense, name: "free-license", rounded: true }), jsx_runtime_1.jsx(layout_1.Spacing, { x: 1 }), jsx_runtime_1.jsx("div", { style: checkboxLabel, children: "I am eligible for the Free License" })
172
- ] }), jsx_runtime_1.jsxs("div", { style: checkboxRow, onClick: (event) => {
173
- if (!(event.target instanceof HTMLInputElement)) {
174
- toggleCompanyLicense();
175
- }
176
- }, children: [
177
- jsx_runtime_1.jsx(Checkbox_1.Checkbox, { checked: licenseType === 'company', onChange: toggleCompanyLicense, name: "company-license", rounded: true }), jsx_runtime_1.jsx(layout_1.Spacing, { x: 1 }), jsx_runtime_1.jsx("div", { style: checkboxLabel, children: "I need a Company License" })
178
- ] }), licenseType === 'company' ? (jsx_runtime_1.jsxs(jsx_runtime_1.Fragment, { children: [
179
- jsx_runtime_1.jsxs("p", { style: description, children: ["Visit", ' ', jsx_runtime_1.jsx("a", { style: descriptionLink, href: "https://remotion.pro/license", children: "remotion.pro/license" }), ' ', "to obtain a license key. Enter the public license key from", ' "License Keys".'] }), jsx_runtime_1.jsxs("label", { style: inputLabel, children: ["Public license key",
180
- jsx_runtime_1.jsx(RemInput_1.RemotionInput, { status: localLicenseKeyValidation.message ||
181
- remoteValidationMessage ||
182
- (licenseKeyDetails !== null &&
183
- !(0, LicenseKeyValidation_1.hasActiveCompanyLicense)(licenseKeyDetails))
184
- ? 'error'
185
- : 'ok', rightAlign: false, value: companyLicenseKey, onChange: (event) => {
186
- setCompanyLicenseKey(event.target.value);
187
- setError(null);
188
- }, placeholder: "rm_pub_...", autoFocus: true })
189
- ] }), localLicenseKeyValidation.message ? (jsx_runtime_1.jsxs(jsx_runtime_1.Fragment, { children: [
190
- jsx_runtime_1.jsx(layout_1.Spacing, { y: 1 }), jsx_runtime_1.jsx(ValidationMessage_1.ValidationMessage, { message: localLicenseKeyValidation.message, align: "flex-start", type: "error" })
191
- ] })) : null, remoteValidationMessage ? (jsx_runtime_1.jsxs(jsx_runtime_1.Fragment, { children: [
192
- jsx_runtime_1.jsx(layout_1.Spacing, { y: 1 }), jsx_runtime_1.jsx(ValidationMessage_1.ValidationMessage, { message: remoteValidationMessage, align: "flex-start", type: "error" })
193
- ] })) : null, isValidatingLicenseKey ? (jsx_runtime_1.jsxs(jsx_runtime_1.Fragment, { children: [
194
- jsx_runtime_1.jsx(layout_1.Spacing, { y: 1 }), jsx_runtime_1.jsx("p", { style: description, children: "Loading license key details..." })
195
- ] })) : null, licenseKeyDetails ? (jsx_runtime_1.jsx(LicenseKeyValidation_1.LicenseKeyDetailsDisplay, { details: licenseKeyDetails })) : null] })) : null, error ? (jsx_runtime_1.jsxs(jsx_runtime_1.Fragment, { children: [
196
- jsx_runtime_1.jsx(layout_1.Spacing, { y: 1.5 }), jsx_runtime_1.jsx(ValidationMessage_1.ValidationMessage, { message: error, align: "flex-start", type: "error" })
197
- ] })) : null] }), jsx_runtime_1.jsx(SettingsModalFooter_1.SettingsModalFooter, { children: jsx_runtime_1.jsx(ModalButton_1.ModalButton, { onClick: submit, disabled: isSubmitting ||
198
- publicLicenseKey.length === 0 ||
199
- (licenseType === 'company' && !companyLicenseKeyIsValid), autoFocus: licenseType !== 'company', children: isSubmitting ? 'Submitting...' : 'Submit and reload' }) })
200
- ] }));
152
+ return [
153
+ {
154
+ setter: 'setPublicLicenseKey',
155
+ type: 'set',
156
+ value: publicLicenseKeyToSave,
157
+ },
158
+ ];
159
+ }, [licenseType, publicLicenseKeyToSave]);
160
+ (0, use_auto_save_config_1.useAutoSaveConfig)({
161
+ enabled: licenseType === null ||
162
+ (publicLicenseKeyToSave.length > 0 &&
163
+ (licenseType !== 'company' ||
164
+ (companyLicenseKeyToSave === companyLicenseKey.trim() &&
165
+ companyLicenseKeyIsValid))),
166
+ onError: setError,
167
+ ready: syncedRevision === revision,
168
+ syncRevision: syncedRevision,
169
+ updates,
170
+ });
171
+ const displayedError = error !== null && error !== void 0 ? error : settingsError;
172
+ return (jsx_runtime_1.jsx("div", { style: container, children: jsx_runtime_1.jsxs("div", { style: content, children: [
173
+ jsx_runtime_1.jsxs("p", { style: description, children: ["Remotion is free to use if you are an individual or company with a headcount of 3 or less.",
174
+ jsx_runtime_1.jsx("br", {}),
175
+ "If used in an organization with 4 people or more, a", ' ', jsx_runtime_1.jsx("a", { style: descriptionLink, href: "https://remotion.pro/license", children: "Company License" }), ' needs to be obtained.'] }), jsx_runtime_1.jsx(layout_1.Spacing, { y: 2 }), jsx_runtime_1.jsxs("div", { style: checkboxRow, onClick: (event) => {
176
+ if (!(event.target instanceof HTMLInputElement)) {
177
+ toggleFreeLicense();
178
+ }
179
+ }, children: [
180
+ jsx_runtime_1.jsx(Checkbox_1.Checkbox, { checked: licenseType === 'free', onChange: toggleFreeLicense, name: "free-license", rounded: true }), jsx_runtime_1.jsx(layout_1.Spacing, { x: 1 }), jsx_runtime_1.jsx("div", { style: checkboxLabel, children: "I am eligible for the Free License" })
181
+ ] }), jsx_runtime_1.jsxs("div", { style: checkboxRow, onClick: (event) => {
182
+ if (!(event.target instanceof HTMLInputElement)) {
183
+ toggleCompanyLicense();
184
+ }
185
+ }, children: [
186
+ jsx_runtime_1.jsx(Checkbox_1.Checkbox, { checked: licenseType === 'company', onChange: toggleCompanyLicense, name: "company-license", rounded: true }), jsx_runtime_1.jsx(layout_1.Spacing, { x: 1 }), jsx_runtime_1.jsx("div", { style: checkboxLabel, children: "I need a Company License" })
187
+ ] }), licenseType === 'company' ? (jsx_runtime_1.jsxs(jsx_runtime_1.Fragment, { children: [
188
+ jsx_runtime_1.jsxs("p", { style: description, children: ["Visit", ' ', jsx_runtime_1.jsx("a", { style: descriptionLink, href: "https://remotion.pro/license", children: "remotion.pro/license" }), ' ', "to obtain a license key. Enter the public license key from", ' "License Keys".'] }), jsx_runtime_1.jsxs("label", { style: inputLabel, children: ["Public license key",
189
+ jsx_runtime_1.jsx(RemInput_1.RemotionInput, { status: localLicenseKeyValidation.message ||
190
+ remoteValidationMessage ||
191
+ (licenseKeyDetails !== null &&
192
+ !(0, LicenseKeyValidation_1.hasActiveCompanyLicense)(licenseKeyDetails))
193
+ ? 'error'
194
+ : 'ok', rightAlign: false, value: companyLicenseKey, onChange: (event) => {
195
+ setCompanyLicenseKey(event.target.value);
196
+ setError(null);
197
+ }, onBlur: () => {
198
+ setCompanyLicenseKeyToSave(companyLicenseKey.trim());
199
+ }, placeholder: "rm_pub_...", autoFocus: true })
200
+ ] }), localLicenseKeyValidation.message ? (jsx_runtime_1.jsxs(jsx_runtime_1.Fragment, { children: [
201
+ jsx_runtime_1.jsx(layout_1.Spacing, { y: 1 }), jsx_runtime_1.jsx(ValidationMessage_1.ValidationMessage, { message: localLicenseKeyValidation.message, align: "flex-start", type: "error" })
202
+ ] })) : null, remoteValidationMessage ? (jsx_runtime_1.jsxs(jsx_runtime_1.Fragment, { children: [
203
+ jsx_runtime_1.jsx(layout_1.Spacing, { y: 1 }), jsx_runtime_1.jsx(ValidationMessage_1.ValidationMessage, { message: remoteValidationMessage, align: "flex-start", type: "error" })
204
+ ] })) : null, isValidatingLicenseKey ? (jsx_runtime_1.jsxs(jsx_runtime_1.Fragment, { children: [
205
+ jsx_runtime_1.jsx(layout_1.Spacing, { y: 1 }), jsx_runtime_1.jsx("p", { style: description, children: "Loading license key details..." })
206
+ ] })) : null, licenseKeyDetails ? (jsx_runtime_1.jsx(LicenseKeyValidation_1.LicenseKeyDetailsDisplay, { details: licenseKeyDetails })) : null] })) : null, displayedError ? (jsx_runtime_1.jsxs(jsx_runtime_1.Fragment, { children: [
207
+ jsx_runtime_1.jsx(layout_1.Spacing, { y: 1.5 }), jsx_runtime_1.jsx(ValidationMessage_1.ValidationMessage, { message: displayedError, align: "flex-start", type: "error" })
208
+ ] })) : null] }) }));
201
209
  };
202
210
  exports.LicenseSettings = LicenseSettings;