From 0fc6271b57937fbdbdd8521ce1d14f903de8c031 Mon Sep 17 00:00:00 2001 From: Philip Molares Date: Sun, 25 Sep 2022 12:35:54 +0200 Subject: [PATCH] feat: add hooks for METADATA_UPDATED DOCUMENT_DELETED messages (#2343) Signed-off-by: Erik Michelson Signed-off-by: Philip Molares Co-authored-by: Erik Michelson --- locales/en.json | 6 +++ .../editor-page/editor-pane/editor-pane.tsx | 4 ++ .../hooks/yjs/use-on-metadata-updated.ts | 28 ++++++++++++ .../hooks/yjs/use-on-note-deleted.ts | 44 +++++++++++++++++++ 4 files changed, 82 insertions(+) create mode 100644 src/components/editor-page/editor-pane/hooks/yjs/use-on-metadata-updated.ts create mode 100644 src/components/editor-page/editor-pane/hooks/yjs/use-on-note-deleted.ts diff --git a/locales/en.json b/locales/en.json index 92aa27cd3..3f5af04de 100644 --- a/locales/en.json +++ b/locales/en.json @@ -586,5 +586,11 @@ "title": "Note could not be created", "description": "The note could not be created. Maybe you don't have permission to create notes." } + }, + "notifications": { + "noteDeleted": { + "title": "Note '{{noteTitle}}' deleted", + "text": "You were redirected to the history page, because the note you just edited was deleted." + } } } diff --git a/src/components/editor-page/editor-pane/editor-pane.tsx b/src/components/editor-page/editor-pane/editor-pane.tsx index 9291d8941..b101030b4 100644 --- a/src/components/editor-page/editor-pane/editor-pane.tsx +++ b/src/components/editor-page/editor-pane/editor-pane.tsx @@ -34,6 +34,7 @@ import { useWebsocketConnection } from './hooks/yjs/use-websocket-connection' import { useBindYTextToRedux } from './hooks/yjs/use-bind-y-text-to-redux' import { useInsertNoteContentIntoYTextInMockModeEffect } from './hooks/yjs/use-insert-note-content-into-y-text-in-mock-mode-effect' import { useOnFirstEditorUpdateExtension } from './hooks/yjs/use-on-first-editor-update-extension' +import { useOnMetadataUpdated } from './hooks/yjs/use-on-metadata-updated' import { useIsConnectionSynced } from './hooks/yjs/use-is-connection-synced' import { useMarkdownContentYText } from './hooks/yjs/use-markdown-content-y-text' import { lintGutter } from '@codemirror/lint' @@ -43,6 +44,7 @@ import { VimeoMarkdownExtension } from '../../markdown-renderer/markdown-extensi import { SequenceDiagramMarkdownExtension } from '../../markdown-renderer/markdown-extension/sequence-diagram/sequence-diagram-markdown-extension' import { LegacyShortcodesMarkdownExtension } from '../../markdown-renderer/markdown-extension/legacy-short-codes/legacy-shortcodes-markdown-extension' import { FrontmatterLinter } from './linter/frontmatter-linter' +import { useOnNoteDeleted } from './hooks/yjs/use-on-note-deleted' /** * Renders the text editor pane of the editor. @@ -80,6 +82,8 @@ export const EditorPane: React.FC = ({ scrollState, onScroll, onMak const websocketConnection = useWebsocketConnection(yDoc, awareness) const connectionSynced = useIsConnectionSynced(websocketConnection) useBindYTextToRedux(yText) + useOnMetadataUpdated(websocketConnection) + useOnNoteDeleted(websocketConnection) const yjsExtension = useCodeMirrorYjsExtension(yText, awareness) const [firstEditorUpdateExtension, firstUpdateHappened] = useOnFirstEditorUpdateExtension() diff --git a/src/components/editor-page/editor-pane/hooks/yjs/use-on-metadata-updated.ts b/src/components/editor-page/editor-pane/hooks/yjs/use-on-metadata-updated.ts new file mode 100644 index 000000000..0718a5646 --- /dev/null +++ b/src/components/editor-page/editor-pane/hooks/yjs/use-on-metadata-updated.ts @@ -0,0 +1,28 @@ +/* + * SPDX-FileCopyrightText: 2022 The HedgeDoc developers (see AUTHORS file) + * + * SPDX-License-Identifier: AGPL-3.0-only + */ + +import type { YDocMessageTransporter } from '@hedgedoc/realtime' +import { MessageType } from '@hedgedoc/realtime' +import { updateMetadata } from '../../../../../redux/note-details/methods' +import { useCallback, useEffect } from 'react' + +/** + * Hook that updates the metadata if the server announced an update of the metadata. + * + * @param websocketConnection The websocket connection that emits the metadata changed event + */ +export const useOnMetadataUpdated = (websocketConnection: YDocMessageTransporter): void => { + const updateMetadataHandler = useCallback(async () => { + await updateMetadata() + }, []) + + useEffect(() => { + websocketConnection.on(MessageType.METADATA_UPDATED, updateMetadataHandler) + return () => { + websocketConnection.off(MessageType.METADATA_UPDATED, updateMetadataHandler) + } + }) +} diff --git a/src/components/editor-page/editor-pane/hooks/yjs/use-on-note-deleted.ts b/src/components/editor-page/editor-pane/hooks/yjs/use-on-note-deleted.ts new file mode 100644 index 000000000..12a6e8726 --- /dev/null +++ b/src/components/editor-page/editor-pane/hooks/yjs/use-on-note-deleted.ts @@ -0,0 +1,44 @@ +/* + * SPDX-FileCopyrightText: 2022 The HedgeDoc developers (see AUTHORS file) + * + * SPDX-License-Identifier: AGPL-3.0-only + */ + +import type { YDocMessageTransporter } from '@hedgedoc/realtime' +import { MessageType } from '@hedgedoc/realtime' +import { useCallback, useEffect } from 'react' +import { useRouter } from 'next/router' +import { Logger } from '../../../../../utils/logger' +import { useApplicationState } from '../../../../../hooks/common/use-application-state' +import { useUiNotifications } from '../../../../notifications/ui-notification-boundary' + +const logger = new Logger('UseOnNoteDeleted') + +/** + * Hook that redirects the user to the history page and displays a notification when the note is deleted. + * + * @param websocketConnection The websocket connection that emits the deletion event + */ +export const useOnNoteDeleted = (websocketConnection: YDocMessageTransporter): void => { + const router = useRouter() + const noteTitle = useApplicationState((state) => state.noteDetails.title) + const { dispatchUiNotification } = useUiNotifications() + + const noteDeletedHandler = useCallback(() => { + dispatchUiNotification('notifications.noteDeleted.title', 'notifications.noteDeleted.text', { + titleI18nOptions: { + noteTitle + } + }) + router?.push('/history').catch((error: Error) => { + logger.error(`Error while redirecting to /history`, error) + }) + }, [router, noteTitle, dispatchUiNotification]) + + useEffect(() => { + websocketConnection.on(MessageType.DOCUMENT_DELETED, noteDeletedHandler) + return () => { + websocketConnection.off(MessageType.DOCUMENT_DELETED, noteDeletedHandler) + } + }) +}