Skip to content

Commit 64fd12a

Browse files
authored
Break out helper functions from the frontend's managers and stores (#3920)
* Move destructor call to each manager/store constructor for safety * Break out utility functions
1 parent 0c7b5cd commit 64fd12a

19 files changed

Lines changed: 843 additions & 823 deletions

File tree

frontend/src/components/floating-menus/Dialog.svelte

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
<script lang="ts">
22
import { getContext, onMount } from "svelte";
33
4-
import { wipeDocuments } from "@graphite/managers/persistence";
54
import type { DialogStore } from "@graphite/stores/dialog";
65
import { crashReportUrl } from "@graphite/utility-functions/crash-report";
6+
import { wipeDocuments } from "@graphite/utility-functions/persistence";
77
88
import FloatingMenu from "@graphite/components/layout/FloatingMenu.svelte";
99
import LayoutCol from "@graphite/components/layout/LayoutCol.svelte";

frontend/src/managers/clipboard.ts

Lines changed: 3 additions & 82 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,11 @@
11
import type { Editor } from "@graphite/editor";
2+
import { insertAtCaret, readAtCaret } from "@graphite/utility-functions/clipboard";
23

34
let editorRef: Editor | undefined = undefined;
45

56
export function createClipboardManager(editor: Editor) {
7+
destroyClipboardManager();
8+
69
editorRef = editor;
710

811
editor.subscriptions.subscribeFrontendMessage("TriggerClipboardWrite", (data) => {
@@ -28,89 +31,7 @@ export function destroyClipboardManager() {
2831
editor.subscriptions.unsubscribeFrontendMessage("TriggerSelectionWrite");
2932
}
3033

31-
function readAtCaret(cut: boolean): string | undefined {
32-
const element = window.document.activeElement;
33-
34-
if (element instanceof HTMLInputElement || element instanceof HTMLTextAreaElement) {
35-
const start = element.selectionStart;
36-
const end = element.selectionEnd;
37-
38-
if ((!start && start !== 0) || (!end && end !== 0) || start === end) {
39-
return undefined;
40-
}
41-
42-
const value = element.value;
43-
const selectedText = value.slice(start, end);
44-
45-
if (cut) {
46-
element.value = value.slice(0, start) + value.slice(end);
47-
48-
element.selectionStart = element.selectionEnd = start;
49-
element.dispatchEvent(new Event("input", { bubbles: true }));
50-
}
51-
52-
return selectedText;
53-
}
54-
55-
const selection = window.getSelection();
56-
if (!selection || selection.rangeCount === 0) {
57-
return undefined;
58-
}
59-
60-
const selectedText = String(selection);
61-
if (!selectedText) return undefined;
62-
63-
if (cut) {
64-
const range = selection.getRangeAt(0);
65-
range.deleteContents();
66-
67-
range.collapse(true);
68-
selection.removeAllRanges();
69-
selection.addRange(range);
70-
}
71-
72-
return selectedText;
73-
}
74-
75-
function insertAtCaret(text: string) {
76-
const element = window.document.activeElement;
77-
78-
if (!element) return;
79-
80-
if (element instanceof HTMLInputElement || element instanceof HTMLTextAreaElement) {
81-
const start = element.selectionStart;
82-
const end = element.selectionEnd;
83-
84-
if ((!start && start !== 0) || (!end && end !== 0)) return;
85-
86-
const value = element.value;
87-
88-
element.value = value.slice(0, start) + text + value.slice(end);
89-
90-
const newPos = start + text.length;
91-
element.selectionStart = element.selectionEnd = newPos;
92-
} else if (element instanceof HTMLElement && element.isContentEditable) {
93-
const selection = window.getSelection();
94-
if (!selection || selection.rangeCount === 0) return;
95-
96-
const range = selection.getRangeAt(0);
97-
range.deleteContents();
98-
99-
const textNode = window.document.createTextNode(text);
100-
range.insertNode(textNode);
101-
102-
range.setStartAfter(textNode);
103-
range.collapse(true);
104-
105-
selection.removeAllRanges();
106-
selection.addRange(range);
107-
}
108-
109-
element.dispatchEvent(new Event("input", { bubbles: true }));
110-
}
111-
11234
// Self-accepting HMR: tear down the old instance and re-create with the new module's code
11335
import.meta.hot?.accept((newModule) => {
114-
destroyClipboardManager();
11536
if (editorRef) newModule?.createClipboardManager(editorRef);
11637
});

frontend/src/managers/fonts.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@ let editorRef: Editor | undefined = undefined;
88
let abortController: AbortController | undefined = undefined;
99

1010
export function createFontsManager(editor: Editor) {
11+
destroyFontsManager();
12+
1113
editorRef = editor;
1214
abortController = new AbortController();
1315

@@ -66,6 +68,5 @@ export function destroyFontsManager() {
6668

6769
// Self-accepting HMR: tear down the old instance and re-create with the new module's code
6870
import.meta.hot?.accept((newModule) => {
69-
destroyFontsManager();
7071
if (editorRef) newModule?.createFontsManager(editorRef);
7172
});

frontend/src/managers/hyperlink.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@ import type { Editor } from "@graphite/editor";
33
let editorRef: Editor | undefined = undefined;
44

55
export function createHyperlinkManager(editor: Editor) {
6+
destroyHyperlinkManager();
7+
68
editorRef = editor;
79

810
editor.subscriptions.subscribeFrontendMessage("TriggerVisitLink", async (data) => {
@@ -19,6 +21,5 @@ export function destroyHyperlinkManager() {
1921

2022
// Self-accepting HMR: tear down the old instance and re-create with the new module's code
2123
import.meta.hot?.accept((newModule) => {
22-
destroyHyperlinkManager();
2324
if (editorRef) newModule?.createHyperlinkManager(editorRef);
2425
});

0 commit comments

Comments
 (0)