From 16a89df8b7e15b6cfb05fac35fc6dad1c23a0447 Mon Sep 17 00:00:00 2001 From: Eddie Abbondanzio Date: Sat, 25 Mar 2023 00:20:09 -0400 Subject: [PATCH] Reduce jitter in note editor (#41) * Fix eslint * Reduce number of re-renders and set models on monaco --- packages/marqus-desktop/.eslintrc.js | 35 ++++++++++++++++++ packages/marqus-desktop/.eslintrc.json | 35 ------------------ .../src/renderer/components/Monaco.tsx | 36 +++++++++++++------ 3 files changed, 60 insertions(+), 46 deletions(-) create mode 100644 packages/marqus-desktop/.eslintrc.js delete mode 100644 packages/marqus-desktop/.eslintrc.json diff --git a/packages/marqus-desktop/.eslintrc.js b/packages/marqus-desktop/.eslintrc.js new file mode 100644 index 00000000..62b452fc --- /dev/null +++ b/packages/marqus-desktop/.eslintrc.js @@ -0,0 +1,35 @@ +module.exports = { + env: { + browser: true, + es6: true, + jest: true, + }, + rules: { + indent: ["error", 2, { SwitchCase: 1 }], + "no-console": ["warn", { allow: ["warn", "error"] }], + "react/prop-types": "off", + "@typescript-eslint/no-non-null-assertion": "off", + "no-prototype-builtins": "off", + }, + extends: [ + "eslint:recommended", + "plugin:react/recommended", + "plugin:@typescript-eslint/recommended", + "plugin:react-hooks/recommended", + ], + ignorePatterns: ["jest.config.js", "webpack.*.js", ".eslintrc.js"], + parser: "@typescript-eslint/parser", + root: true, + plugins: ["react", "@typescript-eslint"], + parserOptions: { + ecmaFeatures: { + jsx: true, + }, + }, + settings: { + react: { + pragma: "React", + version: "detect", + }, + }, +}; diff --git a/packages/marqus-desktop/.eslintrc.json b/packages/marqus-desktop/.eslintrc.json deleted file mode 100644 index eba2237b..00000000 --- a/packages/marqus-desktop/.eslintrc.json +++ /dev/null @@ -1,35 +0,0 @@ -{ - "env": { - "browser": true, - "es6": true, - "jest": true - }, - "rules": { - "no-console": ["warn", { "allow": ["warn", "error"] }], - "react/prop-types": "off", - "@typescript-eslint/no-non-null-assertion": "off", - "no-prototype-builtins": "off", - "@typescript-eslint/no-floating-promises": "error" - }, - "extends": [ - "eslint:recommended", - "plugin:react/recommended", - "plugin:@typescript-eslint/recommended", - "plugin:react-hooks/recommended" - ], - "ignorePatterns": ["jest.config.js", "webpack.*.js"], - "parser": "@typescript-eslint/parser", - "root": true, - "plugins": ["react", "@typescript-eslint"], - "parserOptions": { - "ecmaFeatures": { - "jsx": true - } - }, - "settings": { - "react": { - "pragma": "React", - "version": "detect" - } - } -} \ No newline at end of file diff --git a/packages/marqus-desktop/src/renderer/components/Monaco.tsx b/packages/marqus-desktop/src/renderer/components/Monaco.tsx index cdb9c995..b3ecac98 100644 --- a/packages/marqus-desktop/src/renderer/components/Monaco.tsx +++ b/packages/marqus-desktop/src/renderer/components/Monaco.tsx @@ -184,10 +184,18 @@ export function Monaco(props: MonacoProps): JSX.Element { if (monacoEditor.current != null) { monacoEditor.current.dispose(); + monacoEditor.current = null; + + // N.B. Disposing monaco editor will also dispose the active model so + // we remove it from the cache. + if (activeNoteId.current != null) { + props.removeCache(activeNoteId.current); + } } if (onChangeSub.current != null) { onChangeSub.current.dispose(); + onChangeSub.current = null; } if (el != null) { @@ -251,8 +259,13 @@ export function Monaco(props: MonacoProps): JSX.Element { } } - // Load new tab - if (editor.activeTabNoteId != null) { + // Load new model when switching to a new tab (either no previous tab, or the + // new active tab is different). + if ( + editor.activeTabNoteId != null && + (lastActiveTabNoteId == null || + lastActiveTabNoteId !== editor.activeTabNoteId) + ) { const newTab = editor.tabs.find( t => t.note.id === editor.activeTabNoteId, ); @@ -262,19 +275,20 @@ export function Monaco(props: MonacoProps): JSX.Element { let cache = props.modelAndViewStateCache[newTab.note.id]; // First load, gotta create the model. - if (cache == null) { + if (cache == null || cache.model.isDisposed()) { cache = { model: createMarkdownModel(newTab.note.content), }!; - } - monacoEditor.current.setModel(cache.model); + props.updateCache(newTab.note.id, cache); + monacoEditor.current.setModel(cache.model); - if (cache.viewState) { - monacoEditor.current.restoreViewState(cache.viewState); - } - if (state.focused[0] === Section.Editor) { - monacoEditor.current.focus(); + if (cache.viewState) { + monacoEditor.current.restoreViewState(cache.viewState); + } + if (state.focused[0] === Section.Editor) { + monacoEditor.current.focus(); + } } activeNoteId.current = newTab.note.id; @@ -394,6 +408,6 @@ export function disableKeybinding( _standaloneKeybindingService.addDynamicKeybinding( `-${commandId}`, undefined, - () => {}, + () => void undefined, ); }