fix: preserve focused editor after pulls

This commit is contained in:
lucaronin
2026-05-14 05:53:37 +02:00
parent 6bb9c7fbc9
commit 2eae7a0899
3 changed files with 35 additions and 6 deletions

View File

@@ -86,7 +86,7 @@ import { initializeNoteProperties } from './utils/initializeNoteProperties'
import { filterEntries, filterInboxEntries, type NoteListFilter } from './utils/noteListHelpers'
import { openNoteInNewWindow } from './utils/openNoteWindow'
import { isWindows } from './utils/platform'
import { refreshPulledVaultState } from './utils/pulledVaultRefresh'
import { getPulledVaultUpdateOptions, refreshPulledVaultState } from './utils/pulledVaultRefresh'
import { isNoteWindow, getNoteWindowParams } from './utils/windowMode'
import { GitSetupDialog } from './components/GitRequiredModal'
import { RenameDetectedBanner } from './components/RenameDetectedBanner'
@@ -652,7 +652,7 @@ function App() {
vault.unsavedPaths,
])
const handlePulledVaultUpdate = useCallback(
(updatedFiles: string[]) => handleVaultUpdate(updatedFiles),
(updatedFiles: string[]) => handleVaultUpdate(updatedFiles, getPulledVaultUpdateOptions()),
[handleVaultUpdate],
)
const handleFocusedVaultUpdate = useCallback(

View File

@@ -1,6 +1,6 @@
import { describe, expect, it, vi } from 'vitest'
import type { VaultEntry } from '../types'
import { refreshPulledVaultState } from './pulledVaultRefresh'
import { getPulledVaultUpdateOptions, refreshPulledVaultState } from './pulledVaultRefresh'
function makeEntry(path: string, title = 'Test note'): VaultEntry {
return {
@@ -30,6 +30,10 @@ function makeOptions(overrides: Partial<Parameters<typeof refreshPulledVaultStat
}
describe('refreshPulledVaultState', () => {
it('marks pull-originated vault updates as focused-editor preserving', () => {
expect(getPulledVaultUpdateOptions()).toEqual({ preserveFocusedEditor: true })
})
it('reloads vault-derived data and refreshes the active note when pull updated it', async () => {
const options = makeOptions()

View File

@@ -15,6 +15,13 @@ interface PulledVaultRefreshOptions {
vaultPath: string
}
interface ActiveTabRefreshGuardOptions {
activeTabPath: string
latestActiveTabPath: string
hasUnsavedChanges: (path: string) => boolean
shouldKeepActiveEditorMounted?: () => boolean
}
function resolveUpdatedFilePath(path: string, vaultPath: string): string {
if (path.startsWith('/')) return normalizeNotePathForIdentity(path)
return normalizeNotePathForIdentity(joinVaultPath(vaultPath, path))
@@ -28,6 +35,21 @@ function didActivePathChange(initialPath: string, latestPath: string): boolean {
return !notePathsMatch(initialPath, latestPath)
}
function shouldKeepCurrentActiveTabMounted({
activeTabPath,
latestActiveTabPath,
hasUnsavedChanges,
shouldKeepActiveEditorMounted,
}: ActiveTabRefreshGuardOptions): boolean {
if (didActivePathChange(activeTabPath, latestActiveTabPath)) return true
if (hasUnsavedChanges(latestActiveTabPath)) return true
return shouldKeepActiveEditorMounted?.() === true
}
export function getPulledVaultUpdateOptions(): { preserveFocusedEditor: true } {
return { preserveFocusedEditor: true }
}
export async function refreshPulledVaultState(options: PulledVaultRefreshOptions): Promise<VaultEntry[]> {
const {
activeTabPath,
@@ -51,9 +73,12 @@ export async function refreshPulledVaultState(options: PulledVaultRefreshOptions
const latestActiveTabPath = getActiveTabPath?.() ?? activeTabPath
if (!activeTabPath || !latestActiveTabPath) return entries
if (didActivePathChange(activeTabPath, latestActiveTabPath)) return entries
if (hasUnsavedChanges(latestActiveTabPath)) return entries
if (shouldKeepActiveEditorMounted?.()) return entries
if (shouldKeepCurrentActiveTabMounted({
activeTabPath,
latestActiveTabPath,
hasUnsavedChanges,
shouldKeepActiveEditorMounted,
})) return entries
const refreshedEntry = findByNotePath(entries, latestActiveTabPath)
if (!refreshedEntry) {