Skip to content

Commit 799599e

Browse files
authored
Merge pull request #24 from caido-community/ae-issue-19-restore-focus
Fixed Restore Focus while switching Notes, tabs
2 parents eade948 + 9c5a31e commit 799599e

File tree

3 files changed

+67
-4
lines changed

3 files changed

+67
-4
lines changed

packages/frontend/src/components/content/editor/NoteEditor.vue

Lines changed: 63 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ import { StarterKit } from "@tiptap/starter-kit";
1919
import { type Editor, EditorContent, useEditor } from "@tiptap/vue-3";
2020
import { useDebounceFn } from "@vueuse/core";
2121
import { type NoteContent } from "shared";
22-
import { onMounted, watch } from "vue";
22+
import { onMounted, onUnmounted, watch } from "vue";
2323
2424
import "./editor.css";
2525
import { ArrowKeysFix } from "./extensions/arrows-fix";
@@ -32,6 +32,7 @@ import SearchUI from "./extensions/search/SearchUI.vue";
3232
3333
import { useSDK } from "@/plugins/sdk";
3434
import { useNotesStore } from "@/stores/notes";
35+
import { emitter } from "@/utils/eventBus";
3536
import { compressImage } from "@/utils/images";
3637
3738
const sdk = useSDK();
@@ -42,6 +43,44 @@ const SessionMention = createSessionMention(sdk);
4243
const MAX_IMAGE_SIZE_MB = 30;
4344
const ALLOWED_IMAGE_TYPES = ["image/jpeg", "image/png", "image/gif"];
4445
46+
const cursorPositions = new Map<string, { from: number; to: number }>();
47+
48+
const saveCursorPosition = () => {
49+
if (!editor.value || !notesStore.currentNotePath) return;
50+
51+
const { from, to } = editor.value.state.selection;
52+
cursorPositions.set(notesStore.currentNotePath, { from, to });
53+
};
54+
55+
const restoreCursorPosition = (notePath: string) => {
56+
if (!editor.value) return;
57+
58+
const savedPosition = cursorPositions.get(notePath);
59+
if (savedPosition) {
60+
const docLength = editor.value.state.doc.content.size;
61+
const from = Math.min(savedPosition.from, docLength);
62+
const to = Math.min(savedPosition.to, docLength);
63+
64+
editor.value.commands.setTextSelection({ from, to });
65+
}
66+
67+
editor.value.view.focus();
68+
};
69+
70+
const restoreFocus = () => {
71+
if (!editor.value || !notesStore.currentNotePath) return;
72+
73+
editor.value.view.focus();
74+
75+
const savedPosition = cursorPositions.get(notesStore.currentNotePath);
76+
if (savedPosition) {
77+
const docLength = editor.value.state.doc.content.size;
78+
const from = Math.min(savedPosition.from, docLength);
79+
const to = Math.min(savedPosition.to, docLength);
80+
editor.value.commands.setTextSelection({ from, to });
81+
}
82+
};
83+
4584
const saveNote = async (editor: Editor) => {
4685
if (!notesStore.currentNote) return;
4786
@@ -189,16 +228,29 @@ const editor = useEditor({
189228
debouncedSave(editor as Editor);
190229
}
191230
},
231+
onBlur: () => {
232+
saveCursorPosition();
233+
},
192234
});
193235
236+
let previousNotePath: string | undefined;
237+
194238
watch(
195239
() => notesStore.currentNote,
196-
(newNote) => {
240+
(newNote, oldNote) => {
241+
// Save cursor position of the previous note before switching
242+
if (previousNotePath && editor.value) {
243+
const { from, to } = editor.value.state.selection;
244+
cursorPositions.set(previousNotePath, { from, to });
245+
}
246+
197247
if (editor.value && newNote) {
198248
const content = newNote.content;
199249
editor.value.commands.setContent(content);
200-
editor.value.commands.focus("end");
250+
restoreCursorPosition(newNote.path);
201251
}
252+
253+
previousNotePath = newNote?.path;
202254
},
203255
{ immediate: true },
204256
);
@@ -207,8 +259,15 @@ onMounted(() => {
207259
if (editor.value && notesStore.currentNote) {
208260
const content = notesStore.currentNote.content;
209261
editor.value.commands.setContent(content);
210-
editor.value.commands.focus("end");
262+
restoreCursorPosition(notesStore.currentNote.path);
211263
}
264+
265+
emitter.on("restoreFocus", restoreFocus);
266+
});
267+
268+
onUnmounted(() => {
269+
saveCursorPosition();
270+
emitter.off("restoreFocus", restoreFocus);
212271
});
213272
</script>
214273

packages/frontend/src/index.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,9 @@ export const init = (sdk: FrontendSDK) => {
8585
onEnter: () => {
8686
emitter.emit("refreshEditors");
8787
checkLegacyNotes(sdk);
88+
setTimeout(() => {
89+
emitter.emit("restoreFocus");
90+
}, 200);
8891
},
8992
});
9093

packages/frontend/src/utils/eventBus.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import mitt from "mitt";
33
type Events = {
44
refreshEditors: void;
55
refreshTree: number;
6+
restoreFocus: void;
67
showMigrationDialog: { path: string; content: string }[];
78
confirmMigration: { path: string; content: string }[];
89
};

0 commit comments

Comments
 (0)