Repository navigation
Conversation
…enu item Reload from Disk already exists as a user action, but its only entry point is the external-change banner, which appears only when a tab holds unsaved edits and the file changed on disk. Dismissing it with Keep My Edits re-stamps the disk baseline, so until the file changes again there is no way back to the disk version short of closing the tab. Expose the existing action the way Word Wrap is exposed (stablyai#10086): an editor keybinding action plus an item in the editor actions menu. Both call the existing reloadTabContentFromDisk, so behavior matches the banner exactly. Ships unbound by default, matching sourceControl.sendReviewNotes (stablyai#10070) and the sleeping-workspaces toggle (stablyai#6169) — Ctrl+R and Ctrl+Shift+R are already taken on Windows/Linux. Gated on editable file tabs: diff surfaces are excluded because the reload rotates the Monaco model and drops its undo stack, and read-only live-tail tabs already follow the file. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Contributor
📝 WalkthroughWalkthroughAdds reload-from-disk support for editable editor tabs. The feature introduces eligibility checks, a localized markdown actions menu item, shell and header wiring, and a platform-aware editor keyboard shortcut hook scoped to the active panel. The shortcut action is registered in the keybinding definitions without default bindings. Tests cover tab eligibility, menu visibility, callback invocation, and updated component props. 🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
9 tasks done
Open
9 tasks done
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #11085
Summary
Reload from Diskalready exists as a user action, but its only entry point isExternalFileChangeBanner, which appears only when a tab holds unsaved edits and the file changed on disk. Dismissing it withKeep My EditsrunskeepTabEditsOverExternalChange, which re-stampslastKnownDiskSignatureto the current disk content — so until the file changes on disk again, there is no way back to the disk version short of closing the tab and losing the draft. On a clean tab there is no entry point at all; the only lever isapp.forceReload, which re-renders the whole app.This exposes the existing action through the two surfaces editor features already use, the same shape as Word Wrap (#10086):
editor.reloadFromDisk— new keybinding action,group: 'Editors',scope: 'editor', unbound by default.Ctrl+R(reverse-search) andCtrl+Shift+R(reload) are already taken on Windows/Linux — see the comment aboveworkspace.renameinsrc/shared/keybindings.ts— so this followssourceControl.sendReviewNotes(feat(review): assignable "Send Review Notes to Agent" keyboard shortcut (#10027) #10070) and the sleeping-workspaces toggle (feat(shortcuts): add assignable shortcut to toggle sleeping workspaces #6169) and ships assign-it-yourself.Reload from Disk— new item inEditorPanelMarkdownActionsMenu(the…menu), belowExport as PDF.Both call the already-exported
reloadTabContentFromDisk(file, reloadContent)fromExternalFileChangeBanner.tsx:23, so behavior is identical to the banner button, including the "Reloaded from disk" toast with Undo. No new reload logic — the reload pipeline itself is untouched.Both surfaces share one predicate,
canReloadTabFromDisk(file.mode === 'edit' && file.readOnly !== true):reloadTabContentFromDiskalready carries the note that on diff tabs the reload rotates the Monaco model and destroys its undo stack. Inside the banner that is an informed choice among Compare / Reload / Keep; from a standalone menu item it would not be, so diff tabs do not get the entry point.The keyboard path is
useEditorReloadFromDiskShortcut, modeled directly on the existinguseMarkdownPreviewShortcut— awindowkeydown listener scoped bypanelRef.current.contains(target)so a split's inactive editor cannot swallow the chord.Screenshots
No visual change unless the action is available. When it is, the editor actions menu gains one item:
Settings → Shortcuts → Editorsgains aReload from Diskrow with no binding assigned, rendered by the existing definition-driven list. No new components, tokens, or layout.Testing
pnpm lintpnpm typecheckpnpm test— 38672 passed, 63 skipped, 3673 filespnpm build— see note belowRun on macOS 15 (arm64), Node 24.18.0, pnpm 10.24.0.
New tests:
EditorPanelMarkdownActionsMenu.test.tsx— the item renders and firesonReloadFromDiskwhencanReloadFromDiskis true, and is absent when it is false.ExternalFileChangeBanner.test.tsx—canReloadTabFromDiskaccepts editable file tabs and rejects diff surfaces and read-only tabs, so the diff undo-stack exclusion is pinned by a test rather than by a comment.Targeted run while iterating:
Build note:
pnpm buildisbuild:desktop && build:native.build:desktoppasses (renderer, main, preload, and the projected web client — 761 files, 40.3 MiB).build:nativefails on this machine innative/computer-use-macos, becausexcode-select -ppoints at/Library/Developer/CommandLineToolsand the Swift 6PackageDescriptionlibrary is only in a full Xcode install. That failure is a toolchain gap on my side and is unrelated to this PR, which touches no native or Swift code — but I could not verify it green, so I am flagging it rather than ticking it silently.AI Review Report
I ran the change through an AI review pass focused on the risks specific to it, plus an independent adversarial review of the proposal itself before writing any code.
What it checked and what it changed:
reloadTabContentFromDiskto a key and a menu item. The review flagged that this function unconditionally runsclearEditorDraft/markFileDirty(false), which is safe inside the banner — where the user is answering a three-way conflict prompt — but not from a context-free entry point, especially on diff tabs where the function's own comment warns the Monaco undo stack is destroyed. Result: added thecanReloadTabFromDiskgate excluding diff surfaces and read-only tabs, and covered it with tests.Keep My Editsdismissal path, which survives a perfect watcher. The linked issue states this explicitly.EditorPanelMarkdownActionsMenuis a pure presentational component, so props still have to be threaded fromEditorPanelShell. Corrected: the reload logic is unchanged; the exposure path is new.metaKeyis hardcoded anywhere in this change — matching goes throughkeybindingMatchesActionwithgetShortcutPlatform(), the same path every other editor shortcut uses. The action ships withplatformBindings([])on all three platforms, so no chord is claimed and no conflict can be introduced;findKeybindingConflictshas nothing to report. Shortcut labels are rendered by the existing definition-driven Settings list, so⌘/Ctrlpresentation is unchanged. No paths, shell invocations, or Electron platform APIs are touched.auto.*key derived byconfig/scripts/localize-renderer-strings.mjsand added to all five catalogs (en, ko, ja, zh, es).pnpm lintrunsverify:localization-catalogandverify:localization-coverage, both green, including locale parity at 11473 keys each.Security Audit
Low risk. No new IPC channel, no new command execution, no auth or secret handling, no dependency change.
Specifics reviewed for this change:
reloadContentcallback, which is the same one the banner, the load-error retry, and the live-tail hook already use. It carries the file's ownworktreeId,runtimeEnvironmentId,connectionId, andexpectedExternalSshTargetIdthroughreadRuntimeFileContent, so SSH and remote-runtime tabs read from their owning runtime, not the local disk. No path is constructed or joined in this PR —OpenFile.filePathis passed through unchanged.canReloadTabFromDiskgate and the existing 8-second Undo toast address. Worth a reviewer's opinion: the item is offered on dirty tabs so the post-dismissal case is recoverable, with Undo as the safety net. If you would rather it route dirty tabs intoExternalFileChangeCompareDialoginstead of reloading directly, that is a small follow-up and I am happy to make it.capture: trueonwindowand removed in the effect cleanup, guarded bypanelRef.current.contains(target)so it cannot fire for another split's editor. It bails onevent.repeatandevent.defaultPrevented.Notes
mode: 'edit', so the action is offered on them. Reloading one that has no file on disk yet surfaces the existingFileLoadErrorViewwith its Retry button rather than failing silently. Happy to exclude them explicitly if you would prefer.Settings → Shortcuts.Keep My Editsstate described in the Summary.X (Twitter): @rkh1206