@remotion/studio: Add editor picker to inspectors - #9951
Conversation
1247911 to
a33a897
Compare
a33a897 to
686bdd3
Compare
686bdd3 to
a2be644
Compare
There was a problem hiding this comment.
[!IMPORTANT]
The new throw in openOriginalPositionInEditor on {success: false} introduces one unhandled rejection at an existing call site that was not prepared for it.
Reviewed changes
resolveEditor—preferredEditorparameter: new early-return path resolves an editor by ID without falling through to defaults or legacy detectionopenInEditorHandler—editorIdvalidation and passthrough: validates the incoming editor ID againstdefaultEditorIdsbefore handing it toresolveEditorInspectorOpenInEditor— new split-button component: renders an "Open in" branded button with a dropdown to pick alternate editors; fetches installed editor info from/api/default-editor-infoInspectorLocationCopy— newopenInEditorLocationprop: grafts the editor picker into existing composition and sequence inspector headers alongside the copy-to-clipboard actionopenOriginalPositionInEditor— now checksresponse.successand throws on failure: previously a fire-and-forget call that silently swallowed{success: false}responses; now it throwsError('Could not open the file in the editor.')so callers can surface failuresEditorIcon— brand SVGs for seven editors: VS Code, Cursor, Windsurf, Zed, VSCodium, WebStorm, and Sublime Text, withCustomEditorIconas fallback- Tests: new editor-registry tests for picker override and no-fallback behavior; new custom-editor test for unknown-ID rejection
⚠️ Unhandled promise rejection in ClickableFileName
packages/studio/src/components/VisualControls/ClickableFileName.tsx:56 calls openOriginalPositionInEditor(originalFileName.originalFileName) inside an onClick handler that has no error handling. Previously this function resolved silently on {success: false} responses; now it throws. When the editor cannot be opened, the user sees an unhandled rejection in the console instead of the previous silent no-op.
Technical details
# ClickableFileName — missing error catch
## Affected sites
- `packages/studio/src/components/VisualControls/ClickableFileName.tsx:51-57` — async `onClick` calls `openOriginalPositionInEditor` without `.catch()` or try/catch
## Required outcome
- Callers of `openOriginalPositionInEditor` without error handling must catch the new throw so a failed open does not produce an unhandled rejection in the console. Either wrap in `.catch()` or add a try/catch similar to what `CompositionInspectorHeader` (lines 99, 108) and `SelectedOutlineElement` (line 1703) already do.
## Suggested approach
```tsx
const onClick = useCallback(async () => {
if (originalFileName.type !== 'loaded') {
return;
}
openOriginalPositionInEditor(originalFileName.originalFileName).catch(() => undefined);
}, [originalFileName]);
```Note: 1 inline comment(s) dropped because they did not anchor to lines inside the PR diff:
packages/studio/src/components/VisualControls/ClickableFileName.tsx:56(LEFT) — file not in PR diff
DeepSeek Pro (free via Pullfrog for OSS) (Claude Opus not used — the program covers this model; add its provider key to run your pick) | 𝕏
There was a problem hiding this comment.
[!IMPORTANT]
The new throw in openOriginalPositionInEditor on {success: false} introduces an unhandled rejection at one existing call site that was not prepared for it.
Reviewed changes
resolveEditor—preferredEditorparameter: new early-return path resolves an editor by ID without falling through to defaults or legacy detectionopenInEditorHandler—editorIdvalidation and passthrough: validates the incoming editor ID againstdefaultEditorIdsbefore handing it toresolveEditorInspectorOpenInEditor— new split-button component: renders an "Open in" branded button with a dropdown to pick alternate editors; fetches installed editor info from/api/default-editor-infoInspectorLocationCopy— newopenInEditorLocationprop: grafts the editor picker into existing composition and sequence inspector headers alongside the copy-to-clipboard actionopenOriginalPositionInEditor— now checksresponse.successand throws on failure: previously a fire-and-forget call that silently swallowed{success: false}responses; now it throwsError('Could not open the file in the editor.')so callers can surface failuresEditorIcon— brand SVGs for seven editors: VS Code, Cursor, Windsurf, Zed, VSCodium, WebStorm, and Sublime Text, withCustomEditorIconas fallback- Tests: new editor-registry tests for picker override and no-fallback behavior; new custom-editor test for unknown-ID rejection
⚠️ Unhandled promise rejection at ClickableFileName
packages/studio/src/components/VisualControls/ClickableFileName.tsx:56 calls openOriginalPositionInEditor inside an onClick handler with no error handling. Previously this function resolved silently on {success: false}; now it throws. When the editor cannot be opened, this produces an unhandled rejection in the browser console where it was previously a silent no-op. Every other caller of openOriginalPositionInEditor either catches or is inside a try/catch (checked: SelectedOutlineElement, CompositionInspectorHeader, MenuCompositionName, TimelineSequence, TimelineSequencePropItem, TimelineEffectPropItem).
Technical details
# ClickableFileName — missing error catch
## Affected sites
- `packages/studio/src/components/VisualControls/ClickableFileName.tsx:51-57` — async `onClick` calls `openOriginalPositionInEditor` without `.catch()` or try/catch
## Required outcome
- The `onClick` in `ClickableFileName` must catch the new throw so a failed open does not produce an unhandled rejection. The simplest fix matches the pattern used by other callers: `.catch(() => undefined)`.
## Suggested approach
```tsx
openOriginalPositionInEditor(originalFileName.originalFileName).catch(() => undefined);
```DeepSeek Pro (free via Pullfrog for OSS) (Claude Opus not used — the program covers this model; add its provider key to run your pick) | 𝕏
a2be644 to
e2df1cb
Compare
5267514 to
c2f09bb
Compare

Summary
Test plan
bun test packages/studio-server/src/test/editor-registry.test.ts packages/studio-server/src/test/custom-editor.test.tsbunx turbo run lint test --filter='@remotion/studio'bunx turbo run make --filter='@remotion/studio' --filter='@remotion/studio-server' --filter='@remotion/studio-shared'bun run buildbun run stylecheckStack
@remotion/studio: Support custom editors #9950Closes #9920
Closes #9921