Skip to content

Commit

Permalink
Reduce lag when typing fast (#58)
Browse files Browse the repository at this point in the history
* Debounce onModelChange to improve performance when typing fast

* Change app window title in dev

* Debounce setViewState too
  • Loading branch information
EddieAbbondanzio authored Apr 17, 2023
1 parent aadf5a6 commit 66d6253
Show file tree
Hide file tree
Showing 4 changed files with 60 additions and 40 deletions.
1 change: 0 additions & 1 deletion packages/marqus-desktop/src/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Marqus</title>
</head>

<body>
Expand Down
9 changes: 8 additions & 1 deletion packages/marqus-desktop/src/main/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,8 @@ export async function main(): Promise<void> {
// If the app is closed while writing to the file system, we risk corrupting
// a file so we block it from "closing" by keeping it running in the background
// until we can finish whatever we were doing.

// TODO: Fix this because it likely doesn't handle multiple calls at once.
let keepAlivePromise: Promise<unknown> | undefined;
const blockAppFromQuitting = async (
cb: () => Promise<void>,
Expand All @@ -74,10 +76,15 @@ export async function main(): Promise<void> {

const { windowHeight, windowWidth, autoHideAppMenu } = configFile.content;

let title = "Marqus";
if (isDevelopment()) {
title = `${title} (DEVELOPMENT)`;
}

mainWindow = new BrowserWindow({
// Title must be specified otherwise npm package name will be used until
// index.html has loaded.
title: "Marqus",
title,
icon: "static/icon.png",
height: windowHeight,
width: windowWidth,
Expand Down
5 changes: 4 additions & 1 deletion packages/marqus-desktop/src/renderer/components/Editor.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import { EditorToolbar, TOOLBAR_HEIGHT } from "./EditorToolbar";
import { getNoteById } from "../../shared/domain/note";
import { Config } from "../../shared/domain/config";

const NOTE_SAVE_INTERVAL_MS = 500;
const NOTE_SAVE_INTERVAL_MS = 1000;

interface EditorProps {
store: Store;
Expand Down Expand Up @@ -114,6 +114,9 @@ const setContent: Listener<"editor.setContent"> = async ({ value }, ctx) => {
};
});

// TODO: Reduce the amount of work here. `getNoteById` flattens the entire
// note tree then searches for the note in the resulting array. It works fine
// for a limited number of notes but will eventually bottle neck.
ctx.setNotes(notes => {
const note = getNoteById(notes, noteId);
note.content = content;
Expand Down
85 changes: 48 additions & 37 deletions packages/marqus-desktop/src/renderer/components/Monaco.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@ import { TOOLBAR_HEIGHT } from "./EditorToolbar";
import { Section } from "../../shared/ui/app";
import { Attachment, Protocol } from "../../shared/domain/protocols";
import { Config } from "../../shared/domain/config";
import { debounce } from "lodash";

const DEBOUNCE_INTERVAL_MS = 250;

// Fixes: Error: Language id "vs.editor.nullLanguage" is not configured nor known
// See https://github.com/microsoft/monaco-editor/issues/2962
Expand Down Expand Up @@ -216,48 +219,56 @@ export function Monaco(props: MonacoProps): JSX.Element {
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);

const onModelChange = useCallback(async () => {
if (monacoEditor.current == null) {
return;
}
const value = monacoEditor.current.getModel()?.getValue();
if (value == null) {
return;
}
// eslint-disable-next-line react-hooks/exhaustive-deps
const onModelChange = useCallback(
debounce(async () => {
if (monacoEditor.current == null) {
return;
}
const value = monacoEditor.current.getModel()?.getValue();
if (value == null) {
return;
}

if (activeNoteId.current == null) {
return;
}
if (activeNoteId.current == null) {
return;
}

const viewState = monacoEditor.current.saveViewState()!;
const model = monacoEditor.current.getModel()!;
await store.dispatch("editor.setModelViewState", {
noteId: activeNoteId.current,
modelViewState: {
model,
viewState,
},
});
const viewState = monacoEditor.current.saveViewState()!;
const model = monacoEditor.current.getModel()!;
await store.dispatch("editor.setModelViewState", {
noteId: activeNoteId.current,
modelViewState: {
model,
viewState,
},
});

await store.dispatch("editor.setContent", {
content: value,
noteId: activeNoteId.current!,
});
}, [store]);
await store.dispatch("editor.setContent", {
content: value,
noteId: activeNoteId.current!,
});
}, DEBOUNCE_INTERVAL_MS),
[store],
);

const onViewStateChange = useCallback(() => {
if (monacoEditor.current == null || activeNoteId.current == null) {
return;
}
// eslint-disable-next-line react-hooks/exhaustive-deps
const onViewStateChange = useCallback(
debounce(() => {
if (monacoEditor.current == null || activeNoteId.current == null) {
return;
}

const viewState = monacoEditor.current.saveViewState()!;
store.dispatch("editor.setModelViewState", {
noteId: activeNoteId.current,
modelViewState: {
viewState,
},
});
}, [store]);
const viewState = monacoEditor.current.saveViewState()!;
store.dispatch("editor.setModelViewState", {
noteId: activeNoteId.current,
modelViewState: {
viewState,
},
});
}, DEBOUNCE_INTERVAL_MS),
[store],
);

// Subscribe to monaco editor events
useEffect(() => {
Expand Down

0 comments on commit 66d6253

Please sign in to comment.