Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 14 additions & 18 deletions apps/desktop/src/components/editor/editor.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ import {
restoreHistorySelection,
toTabHistorySelection,
} from "./utils/history-restore-utils"
import { restoreSelectionOnEditorActivate } from "./utils/restore-selection-on-activate"

export function Editor({ destroyOnClose }: { destroyOnClose?: boolean }) {
const {
Expand Down Expand Up @@ -366,34 +367,29 @@ function EditorContent({
return
}

const pathDidChange = lastPathRef.current !== path
lastPathRef.current = path
const isAliasSwitch =
previous.active &&
previous.tabId !== null &&
previous.tabId !== activeTabId &&
previous.path === path
if (isAliasSwitch) {
lastPathRef.current = path
return
}

const pathDidChange = lastPathRef.current !== path
lastPathRef.current = path
const timeoutId = window.setTimeout(() => {
const pendingRestore = consumeTabPendingHistorySelectionRestore(
activeTabId,
path,
)
if (pendingRestore.found) {
restoreHistorySelection(editor, pendingRestore.selection)
return
}

// Keep the current selection when only the backing file path changes.
if (pathDidChange) {
return
}

focusEditorAtDefaultSelection(editor)
editor.tf.focus()
restoreSelectionOnEditorActivate({
editor,
pathDidChange,
pendingRestore: consumeTabPendingHistorySelectionRestore(
activeTabId,
path,
),
restoreHistorySelection,
focusEditorAtDefaultSelection,
})
}, 0)

return () => {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
import { describe, expect, it, vi } from "vitest"
import { restoreSelectionOnEditorActivate } from "./restore-selection-on-activate"

describe("restoreSelectionOnEditorActivate", () => {
it("restores pending selection and keeps focus behavior delegated", () => {
const focus = vi.fn()
const select = vi.fn()
const restoreHistorySelection = vi.fn()
const focusEditorAtDefaultSelection = vi.fn()
const editor = {
children: [],
api: {
isVoid: vi.fn(),
},
tf: {
focus,
select,
},
}

restoreSelectionOnEditorActivate({
editor,
pathDidChange: false,
pendingRestore: {
found: true,
selection: {
anchor: { path: [0, 0], offset: 0 },
focus: { path: [0, 0], offset: 4 },
},
},
restoreHistorySelection,
focusEditorAtDefaultSelection,
})

expect(restoreHistorySelection).toHaveBeenCalledOnce()
expect(focusEditorAtDefaultSelection).not.toHaveBeenCalled()
expect(focus).not.toHaveBeenCalled()
})

it("keeps the current selection when only the backing path changes", () => {
const restoreHistorySelection = vi.fn()
const focusEditorAtDefaultSelection = vi.fn()

restoreSelectionOnEditorActivate({
editor: {
children: [],
api: {
isVoid: vi.fn(),
},
tf: {
focus: vi.fn(),
select: vi.fn(),
},
},
pathDidChange: true,
pendingRestore: {
found: false,
},
restoreHistorySelection,
focusEditorAtDefaultSelection,
})

expect(restoreHistorySelection).not.toHaveBeenCalled()
expect(focusEditorAtDefaultSelection).not.toHaveBeenCalled()
})

it("prepares the default selection without forcing focus on normal note open", () => {
const focus = vi.fn()
const select = vi.fn()
const restoreHistorySelection = vi.fn()
const focusEditorAtDefaultSelection = vi.fn()

restoreSelectionOnEditorActivate({
editor: {
children: [],
api: {
isVoid: vi.fn(),
},
tf: {
focus,
select,
},
},
pathDidChange: false,
pendingRestore: {
found: false,
},
restoreHistorySelection,
focusEditorAtDefaultSelection,
})

expect(restoreHistorySelection).not.toHaveBeenCalled()
expect(focusEditorAtDefaultSelection).toHaveBeenCalledOnce()
expect(focus).not.toHaveBeenCalled()
Comment thread
hhhjin marked this conversation as resolved.
})
})
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import type { PendingHistorySelectionRestoreResult } from "@/store"

type HistoryRestoreEditor = {
children: unknown[]
api: {
isVoid(element: unknown): boolean
}
tf: {
select(...args: [unknown, ...unknown[]]): void
focus(): void
}
}

type RestoreSelectionOnEditorActivateOptions = {
editor: HistoryRestoreEditor
pathDidChange: boolean
pendingRestore: PendingHistorySelectionRestoreResult
restoreHistorySelection: typeof import("./history-restore-utils").restoreHistorySelection
focusEditorAtDefaultSelection: typeof import("./history-restore-utils").focusEditorAtDefaultSelection
}
Comment thread
hhhjin marked this conversation as resolved.

export function restoreSelectionOnEditorActivate({
editor,
pathDidChange,
pendingRestore,
restoreHistorySelection,
focusEditorAtDefaultSelection,
}: RestoreSelectionOnEditorActivateOptions): void {
if (pendingRestore.found) {
restoreHistorySelection(editor, pendingRestore.selection)
return
}

// Keep the current selection when only the backing file path changes.
if (pathDidChange) {
return
}

focusEditorAtDefaultSelection(editor)
Comment thread
hhhjin marked this conversation as resolved.
}
Loading