diff --git a/.eslintignore b/.eslintignore index 27f8a719b5..3f9c753e35 100644 --- a/.eslintignore +++ b/.eslintignore @@ -322,6 +322,8 @@ packages/app-desktop/gui/NoteEditor/utils/useMarkupToHtml.js packages/app-desktop/gui/NoteEditor/utils/useMessageHandler.js packages/app-desktop/gui/NoteEditor/utils/useNoteSearchBar.js packages/app-desktop/gui/NoteEditor/utils/usePluginServiceRegistration.js +packages/app-desktop/gui/NoteEditor/utils/useScheduleSaveCallbacks.js +packages/app-desktop/gui/NoteEditor/utils/useScrollWhenReadyOptions.js packages/app-desktop/gui/NoteEditor/utils/useSearchMarkers.js packages/app-desktop/gui/NoteEditor/utils/useWindowCommandHandler.js packages/app-desktop/gui/NoteList/NoteList2.js diff --git a/.gitignore b/.gitignore index 4e7f135bbc..a173867bef 100644 --- a/.gitignore +++ b/.gitignore @@ -301,6 +301,8 @@ packages/app-desktop/gui/NoteEditor/utils/useMarkupToHtml.js packages/app-desktop/gui/NoteEditor/utils/useMessageHandler.js packages/app-desktop/gui/NoteEditor/utils/useNoteSearchBar.js packages/app-desktop/gui/NoteEditor/utils/usePluginServiceRegistration.js +packages/app-desktop/gui/NoteEditor/utils/useScheduleSaveCallbacks.js +packages/app-desktop/gui/NoteEditor/utils/useScrollWhenReadyOptions.js packages/app-desktop/gui/NoteEditor/utils/useSearchMarkers.js packages/app-desktop/gui/NoteEditor/utils/useWindowCommandHandler.js packages/app-desktop/gui/NoteList/NoteList2.js diff --git a/packages/app-desktop/app.reducer.ts b/packages/app-desktop/app.reducer.ts index ed1added68..35711b19b2 100644 --- a/packages/app-desktop/app.reducer.ts +++ b/packages/app-desktop/app.reducer.ts @@ -26,6 +26,10 @@ export interface AppStateDialog { props: Record; } +export interface EditorScrollPercents { + [noteId: string]: number; +} + export interface AppState extends State { route: AppStateRoute; // eslint-disable-next-line @typescript-eslint/no-explicit-any -- Old code before rule was applied @@ -34,8 +38,7 @@ export interface AppState extends State { // eslint-disable-next-line @typescript-eslint/no-explicit-any -- Old code before rule was applied windowContentSize: any; watchedNoteFiles: string[]; - // eslint-disable-next-line @typescript-eslint/no-explicit-any -- Old code before rule was applied - lastEditorScrollPercents: any; + lastEditorScrollPercents: EditorScrollPercents; devToolsVisible: boolean; // eslint-disable-next-line @typescript-eslint/no-explicit-any -- Old code before rule was applied visibleDialogs: any; // empty object if no dialog is visible. Otherwise contains the list of visible dialogs. diff --git a/packages/app-desktop/gui/NoteEditor/NoteEditor.tsx b/packages/app-desktop/gui/NoteEditor/NoteEditor.tsx index 2732633d34..4cc81cd2eb 100644 --- a/packages/app-desktop/gui/NoteEditor/NoteEditor.tsx +++ b/packages/app-desktop/gui/NoteEditor/NoteEditor.tsx @@ -3,19 +3,18 @@ import { useState, useEffect, useCallback, useRef, useMemo } from 'react'; import TinyMCE from './NoteBody/TinyMCE/TinyMCE'; import { connect } from 'react-redux'; import MultiNoteActions from '../MultiNoteActions'; -import { htmlToMarkdown, formNoteToNote } from './utils'; +import { htmlToMarkdown } from './utils'; import useSearchMarkers from './utils/useSearchMarkers'; import useNoteSearchBar from './utils/useNoteSearchBar'; import useMessageHandler from './utils/useMessageHandler'; import useWindowCommandHandler from './utils/useWindowCommandHandler'; import useDropHandler from './utils/useDropHandler'; import useMarkupToHtml from './utils/useMarkupToHtml'; -import useFormNote, { OnLoadEvent } from './utils/useFormNote'; +import useFormNote, { OnLoadEvent, SetFormNote } from './utils/useFormNote'; import useEffectiveNoteId from './utils/useEffectiveNoteId'; import useFolder from './utils/useFolder'; import styles_ from './styles'; -import { NoteEditorProps, FormNote, ScrollOptions, ScrollOptionTypes, OnChangeEvent, NoteBodyEditorProps, AllAssetsOptions, NoteBodyEditorRef } from './utils/types'; -import ResourceEditWatcher from '@joplin/lib/services/ResourceEditWatcher/index'; +import { NoteEditorProps, FormNote, OnChangeEvent, NoteBodyEditorProps, AllAssetsOptions, NoteBodyEditorRef } from './utils/types'; import CommandService from '@joplin/lib/services/CommandService'; import ToolbarButton from '../ToolbarButton/ToolbarButton'; import Button, { ButtonLevel } from '../Button/Button'; @@ -26,7 +25,6 @@ import { _, _n } from '@joplin/lib/locale'; import TagList from '../TagList'; import NoteTitleBar from './NoteTitle/NoteTitleBar'; import markupLanguageUtils from '../../utils/markupLanguageUtils'; -import usePrevious from '../hooks/usePrevious'; import Setting from '@joplin/lib/models/Setting'; import stateToWhenClauseContext from '../../services/commands/stateToWhenClauseContext'; import ExternalEditWatcher from '@joplin/lib/services/ExternalEditWatcher'; @@ -37,7 +35,7 @@ import NoteSearchBar from '../NoteSearchBar'; import { reg } from '@joplin/lib/registry'; import Note from '@joplin/lib/models/Note'; import Folder from '@joplin/lib/models/Folder'; -const bridge = require('@electron/remote').require('./bridge').default; +import bridge from '../../services/bridge'; import NoteRevisionViewer from '../NoteRevisionViewer'; import { parseShareCache } from '@joplin/lib/services/share/reducer'; import useAsyncEffect from '@joplin/lib/hooks/useAsyncEffect'; @@ -51,6 +49,8 @@ import CodeMirror5 from './NoteBody/CodeMirror/v5/CodeMirror'; import { openItemById } from './utils/contextMenu'; import getPluginSettingValue from '@joplin/lib/services/plugins/utils/getPluginSettingValue'; import { MarkupLanguage } from '@joplin/renderer'; +import useScrollWhenReadyOptions from './utils/useScrollWhenReadyOptions'; +import useScheduleSaveCallbacks from './utils/useScheduleSaveCallbacks'; const commands = [ require('./commands/showRevisions'), @@ -61,20 +61,21 @@ const toolbarButtonUtils = new ToolbarButtonUtils(CommandService.instance()); function NoteEditor(props: NoteEditorProps) { const [showRevisions, setShowRevisions] = useState(false); const [titleHasBeenManuallyChanged, setTitleHasBeenManuallyChanged] = useState(false); - const [scrollWhenReady, setScrollWhenReady] = useState(null); const [isReadOnly, setIsReadOnly] = useState(false); const editorRef = useRef(); - // eslint-disable-next-line @typescript-eslint/no-explicit-any -- Old code before rule was applied - const titleInputRef = useRef(); + const titleInputRef = useRef(); const isMountedRef = useRef(true); const noteSearchBarRef = useRef(null); + const setFormNoteRef = useRef(); + const { saveNoteIfWillChange, scheduleSaveNote } = useScheduleSaveCallbacks({ + setFormNote: setFormNoteRef, dispatch: props.dispatch, editorRef, + }); const formNote_beforeLoad = useCallback(async (event: OnLoadEvent) => { await saveNoteIfWillChange(event.formNote); setShowRevisions(false); - // eslint-disable-next-line @seiyab/react-hooks/exhaustive-deps -- Old code before rule was applied - }, []); + }, [saveNoteIfWillChange]); const formNote_afterLoad = useCallback(async () => { setTitleHasBeenManuallyChanged(false); @@ -92,6 +93,7 @@ function NoteEditor(props: NoteEditorProps) { onBeforeLoad: formNote_beforeLoad, onAfterLoad: formNote_afterLoad, }); + setFormNoteRef.current = setFormNote; const formNoteRef = useRef(); formNoteRef.current = { ...formNote }; @@ -116,53 +118,6 @@ function NoteEditor(props: NoteEditorProps) { const styles = styles_(props); - function scheduleSaveNote(formNote: FormNote) { - if (!formNote.saveActionQueue) throw new Error('saveActionQueue is not set!!'); // Sanity check - - // reg.logger().debug('Scheduling...', formNote); - - const makeAction = (formNote: FormNote) => { - return async function() { - const note = await formNoteToNote(formNote); - reg.logger().debug('Saving note...', note); - const savedNote = await Note.save(note); - - setFormNote((prev: FormNote) => { - return { ...prev, user_updated_time: savedNote.user_updated_time, hasChanged: false }; - }); - - void ExternalEditWatcher.instance().updateNoteFile(savedNote); - - props.dispatch({ - type: 'EDITOR_NOTE_STATUS_REMOVE', - id: formNote.id, - }); - - eventManager.emit(EventName.NoteContentChange, { note: savedNote }); - }; - }; - - formNote.saveActionQueue.push(makeAction(formNote)); - } - - async function saveNoteIfWillChange(formNote: FormNote) { - if (!formNote.id || !formNote.bodyWillChangeId) return; - - const body = await editorRef.current.content(); - - scheduleSaveNote({ - ...formNote, - body: body, - bodyWillChangeId: 0, - bodyChangeId: 0, - }); - } - - async function saveNoteAndWait(formNote: FormNote) { - await saveNoteIfWillChange(formNote); - return formNote.saveActionQueue.waitForAllDone(); - } - const whiteBackgroundNoteRendering = formNote.markup_language === MarkupLanguage.Html; const markupToHtml = useMarkupToHtml({ @@ -201,26 +156,8 @@ function NoteEditor(props: NoteEditorProps) { id: formNote.id, }); } - // eslint-disable-next-line @seiyab/react-hooks/exhaustive-deps -- Old code before rule was applied - }, [props.isProvisional, formNote.id]); + }, [props.isProvisional, formNote.id, props.dispatch]); - const previousNoteId = usePrevious(formNote.id); - - useEffect(() => { - if (formNote.id === previousNoteId) return; - - if (editorRef.current) { - editorRef.current.resetScroll(); - } - - setScrollWhenReady({ - type: props.selectedNoteHash ? ScrollOptionTypes.Hash : ScrollOptionTypes.Percent, - value: props.selectedNoteHash ? props.selectedNoteHash : props.lastEditorScrollPercents[formNote.id] || 0, - }); - - void ResourceEditWatcher.instance().stopWatchingAll(); - // eslint-disable-next-line @seiyab/react-hooks/exhaustive-deps -- Old code before rule was applied - }, [formNote.id, previousNoteId]); // eslint-disable-next-line @typescript-eslint/no-explicit-any -- Old code before rule was applied const onFieldChange = useCallback((field: string, value: any, changeId = 0) => { @@ -263,19 +200,16 @@ function NoteEditor(props: NoteEditorProps) { // The previously loaded note, that was modified, will be saved via saveNoteIfWillChange() } else { setFormNote(newNote); - scheduleSaveNote(newNote); + void scheduleSaveNote(newNote); } - // eslint-disable-next-line @seiyab/react-hooks/exhaustive-deps -- Old code before rule was applied - }, [handleProvisionalFlag, formNote, isNewNote, titleHasBeenManuallyChanged]); + }, [handleProvisionalFlag, formNote, setFormNote, isNewNote, titleHasBeenManuallyChanged, scheduleSaveNote]); useWindowCommandHandler({ dispatch: props.dispatch, - formNote, setShowLocalSearch, noteSearchBarRef, editorRef, titleInputRef, - saveNoteAndWait, setFormNote, }); @@ -339,10 +273,15 @@ function NoteEditor(props: NoteEditorProps) { id: formNote.id, status: 'saving', }); - // eslint-disable-next-line @seiyab/react-hooks/exhaustive-deps -- Old code before rule was applied - }, [formNote, handleProvisionalFlag]); + }, [formNote, setFormNote, handleProvisionalFlag, props.dispatch]); - const onMessage = useMessageHandler(scrollWhenReady, setScrollWhenReady, editorRef, setLocalSearchResultCount, props.dispatch, formNote, htmlToMarkdown, markupToHtml); + const { scrollWhenReady, clearScrollWhenReady } = useScrollWhenReadyOptions({ + noteId: formNote.id, + selectedNoteHash: props.selectedNoteHash, + lastEditorScrollPercents: props.lastEditorScrollPercents, + editorRef, + }); + const onMessage = useMessageHandler(scrollWhenReady, clearScrollWhenReady, editorRef, setLocalSearchResultCount, props.dispatch, formNote, htmlToMarkdown, markupToHtml); // eslint-disable-next-line @typescript-eslint/no-explicit-any -- Old code before rule was applied const externalEditWatcher_noteChange = useCallback((event: any) => { @@ -355,8 +294,7 @@ function NoteEditor(props: NoteEditorProps) { setFormNote(newFormNote); } - // eslint-disable-next-line @seiyab/react-hooks/exhaustive-deps -- Old code before rule was applied - }, [formNote]); + }, [formNote, setFormNote]); // eslint-disable-next-line @typescript-eslint/no-explicit-any -- Old code before rule was applied const onNotePropertyChange = useCallback((event: any) => { @@ -373,8 +311,7 @@ function NoteEditor(props: NoteEditorProps) { return newFormNote; }); - // eslint-disable-next-line @seiyab/react-hooks/exhaustive-deps -- Old code before rule was applied - }, []); + }, [setFormNote]); useEffect(() => { eventManager.on(EventName.AlarmChange, onNotePropertyChange); @@ -409,8 +346,7 @@ function NoteEditor(props: NoteEditorProps) { }); }, [props.dispatch]); - // eslint-disable-next-line @typescript-eslint/no-explicit-any -- Old code before rule was applied - function renderNoNotes(rootStyle: any) { + function renderNoNotes(rootStyle: React.CSSProperties) { const emptyDivStyle = { backgroundColor: 'black', opacity: 0.1, @@ -493,7 +429,7 @@ function NoteEditor(props: NoteEditorProps) { } const onRichTextReadMoreLinkClick = useCallback(() => { - bridge().openExternal('https://joplinapp.org/help/apps/rich_text_editor'); + void bridge().openExternal('https://joplinapp.org/help/apps/rich_text_editor'); }, []); const onRichTextDismissLinkClick = useCallback(() => { @@ -521,8 +457,7 @@ function NoteEditor(props: NoteEditorProps) { if (showRevisions) { const theme = themeStyle(props.themeId); - // eslint-disable-next-line @typescript-eslint/no-explicit-any -- Old code before rule was applied - const revStyle: any = { + const revStyle: React.CSSProperties = { // ...props.style, display: 'inline-flex', padding: theme.margin, diff --git a/packages/app-desktop/gui/NoteEditor/NoteTitle/NoteTitleBar.tsx b/packages/app-desktop/gui/NoteEditor/NoteTitle/NoteTitleBar.tsx index 34b9cddac9..09235c5430 100644 --- a/packages/app-desktop/gui/NoteEditor/NoteTitle/NoteTitleBar.tsx +++ b/packages/app-desktop/gui/NoteEditor/NoteTitle/NoteTitleBar.tsx @@ -36,8 +36,7 @@ interface Props { noteTitle: string; noteIsTodo: number; isProvisional: boolean; - // eslint-disable-next-line @typescript-eslint/no-explicit-any -- Old code before rule was applied - titleInputRef: any; + titleInputRef: React.RefObject; onTitleChange(event: ChangeEvent): void; disabled: boolean; } diff --git a/packages/app-desktop/gui/NoteEditor/utils/useFormNote.ts b/packages/app-desktop/gui/NoteEditor/utils/useFormNote.ts index 4c638c36f1..20edeb676d 100644 --- a/packages/app-desktop/gui/NoteEditor/utils/useFormNote.ts +++ b/packages/app-desktop/gui/NoteEditor/utils/useFormNote.ts @@ -1,4 +1,4 @@ -import { useState, useEffect, useCallback } from 'react'; +import { useState, useEffect, useCallback, RefObject } from 'react'; import { FormNote, defaultFormNote, ResourceInfos } from './types'; import { clearResourceCache, attachedResources } from './resourceHandling'; import AsyncActionQueue from '@joplin/lib/AsyncActionQueue'; @@ -25,14 +25,15 @@ export interface HookDependencies { decryptionStarted: boolean; noteId: string; isProvisional: boolean; - // eslint-disable-next-line @typescript-eslint/no-explicit-any -- Old code before rule was applied - titleInputRef: any; + titleInputRef: RefObject; // eslint-disable-next-line @typescript-eslint/no-explicit-any -- Old code before rule was applied editorRef: any; onBeforeLoad(event: OnLoadEvent): void; onAfterLoad(event: OnLoadEvent): void; } +export type SetFormNote = ReturnType>[1]; + // eslint-disable-next-line @typescript-eslint/ban-types -- Old code before rule was applied function installResourceChangeHandler(onResourceChangeHandler: Function) { ResourceFetcher.instance().on('downloadComplete', onResourceChangeHandler); diff --git a/packages/app-desktop/gui/NoteEditor/utils/useMarkupToHtml.ts b/packages/app-desktop/gui/NoteEditor/utils/useMarkupToHtml.ts index 3ed479fe14..52fabd6b46 100644 --- a/packages/app-desktop/gui/NoteEditor/utils/useMarkupToHtml.ts +++ b/packages/app-desktop/gui/NoteEditor/utils/useMarkupToHtml.ts @@ -25,7 +25,6 @@ export default function useMarkupToHtml(deps: HookDependencies) { resourceBaseUrl: `file://${Setting.value('resourceDir')}/`, customCss: customCss || '', }); - // eslint-disable-next-line @seiyab/react-hooks/exhaustive-deps -- Old code before rule was applied }, [plugins, customCss]); // eslint-disable-next-line @typescript-eslint/no-explicit-any -- Old code before rule was applied @@ -63,6 +62,5 @@ export default function useMarkupToHtml(deps: HookDependencies) { }); return result; - // eslint-disable-next-line @seiyab/react-hooks/exhaustive-deps -- Old code before rule was applied - }, [themeId, customCss, markupToHtml, whiteBackgroundNoteRendering]); + }, [themeId, markupToHtml, whiteBackgroundNoteRendering, deps.settingValue]); } diff --git a/packages/app-desktop/gui/NoteEditor/utils/useMessageHandler.ts b/packages/app-desktop/gui/NoteEditor/utils/useMessageHandler.ts index 5bfb7f19ef..bc65a56aa0 100644 --- a/packages/app-desktop/gui/NoteEditor/utils/useMessageHandler.ts +++ b/packages/app-desktop/gui/NoteEditor/utils/useMessageHandler.ts @@ -1,5 +1,5 @@ import { useCallback } from 'react'; -import { FormNote, HtmlToMarkdownHandler, MarkupToHtmlHandler } from './types'; +import { FormNote, HtmlToMarkdownHandler, MarkupToHtmlHandler, ScrollOptions } from './types'; import contextMenu from './contextMenu'; import CommandService from '@joplin/lib/services/CommandService'; import PostMessageService from '@joplin/lib/services/PostMessageService'; @@ -8,7 +8,7 @@ import { reg } from '@joplin/lib/registry'; const bridge = require('@electron/remote').require('./bridge').default; // eslint-disable-next-line @typescript-eslint/ban-types, @typescript-eslint/no-explicit-any -- Old code before rule was applied, Old code before rule was applied -export default function useMessageHandler(scrollWhenReady: any, setScrollWhenReady: Function, editorRef: any, setLocalSearchResultCount: Function, dispatch: Function, formNote: FormNote, htmlToMd: HtmlToMarkdownHandler, mdToHtml: MarkupToHtmlHandler) { +export default function useMessageHandler(scrollWhenReady: ScrollOptions|null, clearScrollWhenReady: ()=> void, editorRef: any, setLocalSearchResultCount: Function, dispatch: Function, formNote: FormNote, htmlToMd: HtmlToMarkdownHandler, mdToHtml: MarkupToHtmlHandler) { // eslint-disable-next-line @typescript-eslint/no-explicit-any -- Old code before rule was applied return useCallback(async (event: any) => { const msg = event.channel ? event.channel : ''; @@ -25,7 +25,7 @@ export default function useMessageHandler(scrollWhenReady: any, setScrollWhenRea } else if (msg === 'noteRenderComplete') { if (scrollWhenReady) { const options = { ...scrollWhenReady }; - setScrollWhenReady(null); + clearScrollWhenReady(); editorRef.current.scrollTo(options); } } else if (msg === 'setMarkerCount') { diff --git a/packages/app-desktop/gui/NoteEditor/utils/useScheduleSaveCallbacks.ts b/packages/app-desktop/gui/NoteEditor/utils/useScheduleSaveCallbacks.ts new file mode 100644 index 0000000000..eddacfba66 --- /dev/null +++ b/packages/app-desktop/gui/NoteEditor/utils/useScheduleSaveCallbacks.ts @@ -0,0 +1,65 @@ +import Logger from '@joplin/utils/Logger'; +import { RefObject, useCallback } from 'react'; +import { FormNote, NoteBodyEditorRef } from './types'; +import { formNoteToNote } from '.'; +import ExternalEditWatcher from '@joplin/lib/services/ExternalEditWatcher'; +import Note from '@joplin/lib/models/Note'; +import type { Dispatch } from 'redux'; +import eventManager, { EventName } from '@joplin/lib/eventManager'; +import type { SetFormNote } from './useFormNote'; + +const logger = Logger.create('useScheduleSaveCallbacks'); + +interface Props { + setFormNote: RefObject; + dispatch: Dispatch; + editorRef: RefObject; +} + +const useScheduleSaveCallbacks = (props: Props) => { + const scheduleSaveNote = useCallback(async (formNote: FormNote) => { + if (!formNote.saveActionQueue) throw new Error('saveActionQueue is not set!!'); // Sanity check + + // reg.logger().debug('Scheduling...', formNote); + + const makeAction = (formNote: FormNote) => { + return async function() { + const note = await formNoteToNote(formNote); + logger.debug('Saving note...', note); + const savedNote = await Note.save(note); + + props.setFormNote.current((prev: FormNote) => { + return { ...prev, user_updated_time: savedNote.user_updated_time, hasChanged: false }; + }); + + void ExternalEditWatcher.instance().updateNoteFile(savedNote); + + props.dispatch({ + type: 'EDITOR_NOTE_STATUS_REMOVE', + id: formNote.id, + }); + + eventManager.emit(EventName.NoteContentChange, { note: savedNote }); + }; + }; + + formNote.saveActionQueue.push(makeAction(formNote)); + }, [props.dispatch, props.setFormNote]); + + const saveNoteIfWillChange = useCallback(async (formNote: FormNote) => { + if (!formNote.id || !formNote.bodyWillChangeId) return; + + const body = await props.editorRef.current.content(); + + void scheduleSaveNote({ + ...formNote, + body: body, + bodyWillChangeId: 0, + bodyChangeId: 0, + }); + }, [scheduleSaveNote, props.editorRef]); + + return { saveNoteIfWillChange, scheduleSaveNote }; +}; + +export default useScheduleSaveCallbacks; diff --git a/packages/app-desktop/gui/NoteEditor/utils/useScrollWhenReadyOptions.ts b/packages/app-desktop/gui/NoteEditor/utils/useScrollWhenReadyOptions.ts new file mode 100644 index 0000000000..1d9b4a7030 --- /dev/null +++ b/packages/app-desktop/gui/NoteEditor/utils/useScrollWhenReadyOptions.ts @@ -0,0 +1,44 @@ +import { RefObject, useCallback, useEffect, useRef, useState } from 'react'; +import { NoteBodyEditorRef, ScrollOptions, ScrollOptionTypes } from './types'; +import usePrevious from '@joplin/lib/hooks/usePrevious'; +import ResourceEditWatcher from '@joplin/lib/services/ResourceEditWatcher'; +import type { EditorScrollPercents } from '../../../app.reducer'; + +interface Props { + noteId: string; + selectedNoteHash: string; + lastEditorScrollPercents: EditorScrollPercents; + editorRef: RefObject; +} + +const useScrollWhenReadyOptions = ({ noteId, selectedNoteHash, lastEditorScrollPercents, editorRef }: Props) => { + const [scrollWhenReady, setScrollWhenReady] = useState(null); + + const previousNoteId = usePrevious(noteId); + const lastScrollPercentsRef = useRef(); + lastScrollPercentsRef.current = lastEditorScrollPercents; + + useEffect(() => { + if (noteId === previousNoteId) return; + + if (editorRef.current) { + editorRef.current.resetScroll(); + } + + const lastScrollPercent = lastScrollPercentsRef.current[noteId] || 0; + setScrollWhenReady({ + type: selectedNoteHash ? ScrollOptionTypes.Hash : ScrollOptionTypes.Percent, + value: selectedNoteHash ? selectedNoteHash : lastScrollPercent, + }); + + void ResourceEditWatcher.instance().stopWatchingAll(); + }, [noteId, previousNoteId, selectedNoteHash, editorRef]); + + const clearScrollWhenReady = useCallback(() => { + setScrollWhenReady(null); + }, []); + + return { scrollWhenReady, clearScrollWhenReady }; +}; + +export default useScrollWhenReadyOptions; diff --git a/packages/app-desktop/gui/NoteEditor/utils/useWindowCommandHandler.ts b/packages/app-desktop/gui/NoteEditor/utils/useWindowCommandHandler.ts index 96f277b5f8..ae739b7624 100644 --- a/packages/app-desktop/gui/NoteEditor/utils/useWindowCommandHandler.ts +++ b/packages/app-desktop/gui/NoteEditor/utils/useWindowCommandHandler.ts @@ -15,7 +15,6 @@ const commandsWithDependencies = [ type SetFormNoteCallback = (callback: (prev: FormNote)=> FormNote)=> void; interface HookDependencies { - formNote: FormNote; // eslint-disable-next-line @typescript-eslint/ban-types -- Old code before rule was applied setShowLocalSearch: Function; // eslint-disable-next-line @typescript-eslint/ban-types -- Old code before rule was applied @@ -23,10 +22,7 @@ interface HookDependencies { // eslint-disable-next-line @typescript-eslint/no-explicit-any -- Old code before rule was applied noteSearchBarRef: any; editorRef: RefObject; - // eslint-disable-next-line @typescript-eslint/no-explicit-any -- Old code before rule was applied - titleInputRef: any; - // eslint-disable-next-line @typescript-eslint/ban-types -- Old code before rule was applied - saveNoteAndWait: Function; + titleInputRef: RefObject; setFormNote: SetFormNoteCallback; } @@ -109,6 +105,5 @@ export default function useWindowCommandHandler(dependencies: HookDependencies) CommandService.instance().unregisterRuntime(command.declaration.name); } }; - // eslint-disable-next-line @seiyab/react-hooks/exhaustive-deps -- Old code before rule was applied - }, [editorRef, setShowLocalSearch, noteSearchBarRef, titleInputRef]); + }, [editorRef, setShowLocalSearch, noteSearchBarRef, titleInputRef, setFormNote]); } diff --git a/packages/app-mobile/components/NoteBodyViewer/hooks/useRerenderHandler.ts b/packages/app-mobile/components/NoteBodyViewer/hooks/useRerenderHandler.ts index 49472132a4..0650f79e51 100644 --- a/packages/app-mobile/components/NoteBodyViewer/hooks/useRerenderHandler.ts +++ b/packages/app-mobile/components/NoteBodyViewer/hooks/useRerenderHandler.ts @@ -83,7 +83,8 @@ const useRerenderHandler = (props: Props) => { return accum; }, {}); const onlyNoteBodyHasChanged = Object.keys(changedDeps).length === 1 && changedDeps[0]; - const onlyCheckboxesHaveChanged = previousDeps[0] && changedDeps[0] && onlyCheckboxHasChangedHack(previousDeps[0], props.noteBody); + const previousBody = previousDeps[0] as string; + const onlyCheckboxesHaveChanged = previousDeps[0] && changedDeps[0] && onlyCheckboxHasChangedHack(previousBody, props.noteBody); const previousHash = usePrevious(props.noteHash, ''); const hashChanged = previousHash !== props.noteHash; diff --git a/packages/lib/hooks/usePrevious.ts b/packages/lib/hooks/usePrevious.ts index d5cc56bcb7..381f8731bb 100644 --- a/packages/lib/hooks/usePrevious.ts +++ b/packages/lib/hooks/usePrevious.ts @@ -2,9 +2,8 @@ import shim from '../shim'; const { useRef, useEffect } = shim.react(); -// eslint-disable-next-line @typescript-eslint/no-explicit-any -- Old code before rule was applied -const usePrevious = (value: any, initialValue: any = null) => { - const ref = useRef(initialValue); +const usePrevious = (value: T, initialValue: T = null) => { + const ref = useRef(initialValue); useEffect(() => { ref.current = value; });