Skip to content

fix(title bar): Auto-Reload and Mod+L agree in every mode (#692) - #696

Merged
PathGao merged 2 commits into
masterfrom
fix/auto-reload-in-edit-mode
Aug 21, 2026
Merged

fix(title bar): Auto-Reload and Mod+L agree in every mode (#692)#696
PathGao merged 2 commits into
masterfrom
fix/auto-reload-in-edit-mode

Conversation

@PathGao

@PathGao PathGao commented Aug 21, 2026

Copy link
Copy Markdown
Collaborator

What this is

Closes #692, reported by @17Archangel: editing a .md file in Markpad and in VS Code at the same time, saving in VS Code, and Markpad not picking the change up until the mode was toggled.

The feature they wanted already exists — Auto-Reload. It had two surfaces that disagreed about which modes it existed in, and their answers were exact complements:

preview edit split
title-bar button yes no no
Mod+L no yes yes
shortcut panel advertises it advertises it advertises it

Whether a user got the feature depended on which surface they happened to find first. The reporter was editing, so they found neither the button (hidden) nor a reason to try the chord.

Two failures fall out of that table beyond the report. Pressing Ctrl+L in the editor did work — it armed the watcher and started reloading the document — with nothing on screen to show the state had changed. And the shortcut panel prints Mod+L unconditionally (shortcutSections filters by group only), so in the preview it advertised a chord that was bound to nothing.

After this PR every cell in that table is yes.

Mechanism

The button. !isEditing && !isSplit in TitleBar.svelte becomes "there is a file on disk", which is the condition that actually matters: an external writer can surprise all three modes equally, and what varies between them is only which pane is on screen.

The chord. view-toggle-live carried editorAction: true and nothing else, so it existed only as a Monaco action and only where Monaco does. It gets documentCommands: ['toggle-live-mode'] as well — the same pair view-toggle-edit (Mod+E) already carries — plus the branch in viewerKeymap.ts and the case in runViewerCommand. The Monaco action stays rather than being replaced: Monaco binds Ctrl+L to expandLineSelection by default, so dropping the action would make the chord select a line instead of doing nothing.

Split view stops killing live mode on the way in. That was one uncommented line in toggleSplitView, and git blame puts it in the original split-view commit. It reads as a consequence of the button being hidden in split — nothing left to turn the state off with — rather than a decision that a split pane should not follow its file. A split pane is an editor: same exposure to another program writing the file, and loadMarkdown already keeps the split through a reload and still routes a dirty buffer to the conflict bar. It also meant enabling Auto-Reload in the preview, entering split and leaving again silently lost the setting.

Nothing downstream of the toggle needed a change. The watcher effect is if (liveMode && currentFile), never gated on the mode; resolveExternalChange already sends a dirty tab to the conflict bar instead of overwriting it; and loadMarkdown skips the open-mode reset for a tab that already holds the file (!existing), so a reload keeps whichever pane you were in and an editable pane takes the read_file_content_checked branch rather than the 5MB preview slice.

Scope

visibleActionIds moves out of TitleBar.svelte into titlebarToolbar.ts as visibleTitlebarActionIds(context). That module already owns which toolbar ids exist and already consumed this function's output through getConfiguredTitlebarToolbarIds, so this is the first half of a pipeline moving next to the second, not a new layer. It is also why the bug lasted: the condition sat in a $derived.by inside a component where no test could reach it. The moved body is otherwise the same statements in the same order, and the tests below pin every branch of it rather than only the one that changed.

Considered and not done: leaving split unsupported and drawing the button disabled there instead. That keeps a rule to explain, needs a new tooltip string in 26 locales, and the rule itself did not survive being looked at — see the blame above.

Not changed: liveMode still defaults to off. Turning it on by default puts Markpad's own auto-save and an external writer on the same file, and whether the self-write grace window absorbs that needs measuring rather than guessing.

Tests

scripts/titlebarToolbar.test.ts, six cases over the extracted function: Auto-Reload offered in all three modes, absent with no file on disk, Find / editor toolbar / Sync Scroll / Edit each still answering to the mode they belong to, a non-Markdown file getting none of the Markdown actions, the home screen, and Reset Zoom.

scripts/viewerKeymap.spec.ts, one case: Mod+L resolves to toggle-live-mode from the preview, from the editor with focus in it, and from split — and Mod+Shift+L, Mod+Alt+L and a bare L resolve to nothing. The file's existing sweep already holds that every command the dispatcher can name has a case in runViewerCommand.

scripts/externalChangeReload.spec.ts, two cases: loadMarkdown(path) — the exact call the file-changed listener makes — against a clean tab with isEditing true leaves the tab in the editor with the disk content and not dirty; and toggleSplitView no longer names toggleLiveMode.

Each of the three was checked by breaking what it guards: restoring !isEditing on the button, dropping the !existing guard in documentSession, and putting the split kill back all turn the matching test red.

Verification

npm audit             0 vulnerabilities
npm run check         809 files, 0 errors, 0 warnings
npm test              957 pass, 0 fail
npm run test:vitest   43 files, 365 pass
cargo test            161 pass, 0 fail

npm run test:vitest also reports 14 failures in this environment (session-restore and window-tag snapshots, all assert.deepEqual reference-identity complaints under node 26 + jsdom). Byte-identical on a clean origin/master checkout in the same environment, verified by stashing and re-running, so this PR neither causes nor fixes them.

Not verified: the end-to-end gesture on Windows, where the report came from — button pressed in edit mode, file written by another editor, document refreshing in place. The wiring it depends on is platform-independent and the notify watcher was already carrying it in preview mode.

@PathGao PathGao changed the title fix(title bar): Auto-Reload is reachable in edit mode (#692) fix(title bar): Auto-Reload and Mod+L agree in every mode (#692) Aug 21, 2026
PathGao added 2 commits August 22, 2026 01:34
Editing a file in Markpad while another program writes it is the case
auto-reload exists for, and it was the one mode with no way to turn auto-reload
on. The button was gated on `!isEditing`; its chord, Mod+L, is an
`editorAction` in shortcuts.ts, so Monaco owns it and it fires in edit mode
ONLY. Two places answered "where is Auto-Reload available?" and gave exactly
complementary answers, so pressing Ctrl+L in the editor flipped the state with
nothing on screen to show it had.

The reload path itself already handled this: `loadMarkdown` skips the
open-mode reset for a tab that already holds the file, so a reload keeps the
editor, and a dirty buffer still goes to the conflict bar rather than being
overwritten.

Split view keeps its exclusion — its preview renders the buffer, not the file,
which is why entering it turns live mode off.

`visibleActionIds` moves out of TitleBar.svelte into titlebarToolbar.ts, whose
`getConfiguredTitlebarToolbarIds` already consumed its output. The condition
was wrong for as long as nothing could call it.
Extends the previous commit: the button now appears wherever there is a file
on disk, and Mod+L reaches it from the preview too.

Mod+L was only `editorAction: true`, so Monaco owned it and it did nothing in
the preview — the exact inverse of where the button was drawn, while the
shortcut panel advertised it in all three modes regardless. It gets the
`documentCommands` half as well, the same pair Mod+E already carries. The
Monaco action stays: Monaco's own Ctrl+L is `expandLineSelection`, so
dropping it would make the chord select a line rather than do nothing.

Split view stops killing live mode on the way in. That line arrived with the
original split-view commit carrying no comment, and it reads as a consequence
of the button being hidden there — nothing left to turn the state off with —
rather than a decision that a split pane should not follow its file. A split
pane is an editor: it has the same exposure to another program writing the
file, and the reload path already keeps the split and still routes a dirty
buffer to the conflict bar.

The setting was also silently dropped and stayed dropped after leaving split.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

希望可以自动检测文件被其他软件编辑和保存

1 participant