mirror of
https://github.com/hedgedoc/hedgedoc.git
synced 2024-11-21 17:26:29 -05:00
wip
Signed-off-by: Tilman Vatteroth <git@tilmanvatteroth.de>
This commit is contained in:
parent
4d70ccafbc
commit
5f27996ed0
5 changed files with 79 additions and 30 deletions
|
@ -0,0 +1,27 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2023 The HedgeDoc developers (see AUTHORS file)
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
import { useMemo } from 'react'
|
||||
import { EditorView } from '@codemirror/view'
|
||||
import { setNoteContent } from '../../../../redux/note-details/methods'
|
||||
|
||||
/**
|
||||
* Syncs the CodeMirror content to the redux store.
|
||||
*
|
||||
* @return the codemirror extension that updates the redux state
|
||||
*/
|
||||
export const useSyncToReduxExtension = () => {
|
||||
return useMemo(
|
||||
() =>
|
||||
EditorView.updateListener.of((update) => {
|
||||
if (!update.docChanged) {
|
||||
return
|
||||
}
|
||||
setNoteContent(update.state.sliceDoc())
|
||||
}),
|
||||
[]
|
||||
)
|
||||
}
|
|
@ -24,7 +24,6 @@ import { useApplyScrollState } from './hooks/use-apply-scroll-state'
|
|||
import { useCursorActivityCallback } from './hooks/use-cursor-activity-callback'
|
||||
import { useDisconnectOnUserLoginStatusChange } from './hooks/use-disconnect-on-user-login-status-change'
|
||||
import { useUpdateCodeMirrorReference } from './hooks/use-update-code-mirror-reference'
|
||||
import { useBindYTextToRedux } from './hooks/yjs/use-bind-y-text-to-redux'
|
||||
import { useCodeMirrorYjsExtension } from './hooks/yjs/use-code-mirror-yjs-extension'
|
||||
import { useOnMetadataUpdated } from './hooks/yjs/use-on-metadata-updated'
|
||||
import { useOnNoteDeleted } from './hooks/yjs/use-on-note-deleted'
|
||||
|
@ -43,6 +42,7 @@ import { lintGutter } from '@codemirror/lint'
|
|||
import { oneDark } from '@codemirror/theme-one-dark'
|
||||
import ReactCodeMirror from '@uiw/react-codemirror'
|
||||
import React, { useEffect, useMemo } from 'react'
|
||||
import { useSyncToReduxExtension } from './codemirror-extensions/use-sync-to-redux-extension'
|
||||
|
||||
export type EditorPaneProps = ScrollProps
|
||||
|
||||
|
@ -83,12 +83,14 @@ export const EditorPane: React.FC<EditorPaneProps> = ({ scrollState, onScroll, o
|
|||
useOnMetadataUpdated(messageTransporter)
|
||||
useOnNoteDeleted(messageTransporter)
|
||||
|
||||
useBindYTextToRedux(realtimeDoc)
|
||||
useReceiveRealtimeUsers(messageTransporter)
|
||||
useSendRealtimeActivity(messageTransporter)
|
||||
|
||||
const syncToReduxExtension = useSyncToReduxExtension()
|
||||
|
||||
const extensions = useMemo(
|
||||
() => [
|
||||
syncToReduxExtension,
|
||||
linterExtension,
|
||||
lintGutter(),
|
||||
markdown({
|
||||
|
@ -107,17 +109,18 @@ export const EditorPane: React.FC<EditorPaneProps> = ({ scrollState, onScroll, o
|
|||
spellCheckExtension
|
||||
],
|
||||
[
|
||||
syncToReduxExtension,
|
||||
linterExtension,
|
||||
remoteCursorsExtension,
|
||||
autoCompletionExtension,
|
||||
lineWrappingExtension,
|
||||
editorScrollExtension,
|
||||
tablePasteExtensions,
|
||||
fileInsertExtension,
|
||||
autoCompletionExtension,
|
||||
cursorActivityExtension,
|
||||
updateViewContextExtension,
|
||||
yjsExtension,
|
||||
spellCheckExtension,
|
||||
lineWrappingExtension
|
||||
spellCheckExtension
|
||||
]
|
||||
)
|
||||
|
||||
|
|
|
@ -1,22 +0,0 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2022 The HedgeDoc developers (see AUTHORS file)
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
import { setNoteContent } from '../../../../../redux/note-details/methods'
|
||||
import type { RealtimeDoc } from '@hedgedoc/commons'
|
||||
import { useEffect } from 'react'
|
||||
|
||||
/**
|
||||
* One-Way-synchronizes the text of the markdown content channel from the given {@link RealtimeDoc realtime doc} into the global application state.
|
||||
*
|
||||
* @param realtimeDoc The {@link RealtimeDoc realtime doc} that contains the markdown content
|
||||
*/
|
||||
export const useBindYTextToRedux = (realtimeDoc: RealtimeDoc): void => {
|
||||
useEffect(() => {
|
||||
const yText = realtimeDoc.getMarkdownContentChannel()
|
||||
const yTextCallback = () => setNoteContent(yText.toString())
|
||||
yText.observe(yTextCallback)
|
||||
return () => yText.unobserve(yTextCallback)
|
||||
}, [realtimeDoc])
|
||||
}
|
39
frontend/src/hooks/common/use-deferred-state.ts
Normal file
39
frontend/src/hooks/common/use-deferred-state.ts
Normal file
|
@ -0,0 +1,39 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2023 The HedgeDoc developers (see AUTHORS file)
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
import { useCallback, useEffect, useRef, useState } from 'react'
|
||||
import { useInterval } from 'react-use'
|
||||
|
||||
/**
|
||||
* Takes a value that changes often and outputs the last value that hasn't been changed in the last interval.
|
||||
*
|
||||
* @param value The value to defer
|
||||
* @param initialValue The initial value that is used until the first update
|
||||
* @param checkInterval The interval in ms that is used to check for updates. Default is 200ms.
|
||||
* @return The slowed down value
|
||||
*/
|
||||
export const useDeferredState = <T>(value: T, initialValue: T, checkInterval = 200): T => {
|
||||
const valueRef = useRef<T>(initialValue)
|
||||
const lastTimestamp = useRef<number>(0)
|
||||
const [deferredValue, setDeferredValue] = useState<T>(initialValue)
|
||||
|
||||
useEffect(() => {
|
||||
valueRef.current = value
|
||||
lastTimestamp.current = new Date().getTime()
|
||||
}, [value])
|
||||
|
||||
useInterval(
|
||||
useCallback(() => {
|
||||
const currentTimeStamp = new Date().getTime()
|
||||
if (currentTimeStamp - lastTimestamp.current >= checkInterval) {
|
||||
setDeferredValue(valueRef.current)
|
||||
}
|
||||
}, [checkInterval]),
|
||||
checkInterval
|
||||
)
|
||||
|
||||
return deferredValue
|
||||
}
|
|
@ -6,6 +6,7 @@
|
|||
import { useFrontendConfig } from '../../components/common/frontend-config-context/use-frontend-config'
|
||||
import { useApplicationState } from './use-application-state'
|
||||
import { useMemo } from 'react'
|
||||
import { useDeferredState } from './use-deferred-state'
|
||||
|
||||
/**
|
||||
* Returns the markdown content from the global application state trimmed to the maximal note length and without the frontmatter lines.
|
||||
|
@ -28,7 +29,8 @@ export const useTrimmedNoteMarkdownContentWithoutFrontmatter = (): string[] => {
|
|||
}
|
||||
}, [markdownContent, maxLength])
|
||||
|
||||
return useMemo(() => {
|
||||
return trimmedLines.slice(lineOffset)
|
||||
}, [lineOffset, trimmedLines])
|
||||
return useDeferredState(
|
||||
useMemo(() => trimmedLines.slice(lineOffset), [lineOffset, trimmedLines]),
|
||||
[]
|
||||
)
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue