Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Switch to single editor mode when the connection to y-socket.io fails #9452

Open
wants to merge 3 commits into
base: feat/non-yjs-mode
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ const moduleClass = styles['editor-navbar'] ?? '';

export const EditorNavbar = (): JSX.Element => {
const { data: editingUsers } = useEditingUsers();
const isYjsEnabled = useIsYjsEnabled();
const { data: isYjsEnabled } = useIsYjsEnabled();

const editorCondition = useMemo(() => {
if (isYjsEnabled) {
Expand Down
7 changes: 6 additions & 1 deletion apps/app/src/client/components/PageEditor/PageEditor.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ export const PageEditor = React.memo((props: Props): JSX.Element => {
const { data: user } = useCurrentUser();
const { onEditorsUpdated } = useEditingUsers();
const onConflict = useConflictResolver();
const isYjsEnabled = useIsYjsEnabled();
const { data: isYjsEnabled, mutate: mutateIsYjsEnabled } = useIsYjsEnabled();
const { addChangeDetector } = useUnsavedChanges();

const { data: reservedNextCaretLine, mutate: mutateReservedNextCaretLine } = useReservedNextCaretLine();
Expand All @@ -135,6 +135,10 @@ export const PageEditor = React.memo((props: Props): JSX.Element => {
const currentRevisionOrigin = currentPage?.revision?.origin;
const isRevisionIdRequiredForPageUpdate = currentRevisionOrigin === undefined || currentRevisionOrigin === Origin.EditorSingle || isYjsEnabled === false;

const yjsConnectionErrorHandler = useCallback(() => {
mutateIsYjsEnabled(false);
}, [mutateIsYjsEnabled]);

const initialValueRef = useRef('');
const initialValue = useMemo(() => {
if (!isNotFound) {
Expand Down Expand Up @@ -397,6 +401,7 @@ export const PageEditor = React.memo((props: Props): JSX.Element => {
pageId={pageId ?? undefined}
editorSettings={editorSettings}
onEditorsUpdated={onEditorsUpdated}
onYjsConnectionError={yjsConnectionErrorHandler}
isYjsEnabled={isYjsEnabled}
cmProps={cmProps}
/>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,17 +16,18 @@ type PageEditorSwitcherProps = CodeMirrorEditorProps & {
user?: IUserHasId
pageId?: string
onEditorsUpdated?: (userList: IUserHasId[]) => void,
onYjsConnectionError?: () => void
};

export const PageEditorMainSwitcher = React.memo((props: PageEditorSwitcherProps): JSX.Element => {
const {
isYjsEnabled, cmProps, user, pageId, onEditorsUpdated, ...otherProps
isYjsEnabled, cmProps, user, pageId, onEditorsUpdated, onYjsConnectionError, ...otherProps
} = props;

const { data: codeMirrorEditor } = useCodeMirrorEditorIsolated(GlobalCodeMirrorEditorKey.MAIN);

useSingleEditorMode();
useCollaborativeEditorMode(isYjsEnabled ?? false, user, pageId, onEditorsUpdated, codeMirrorEditor);
useCollaborativeEditorMode(isYjsEnabled ?? false, user, pageId, onEditorsUpdated, onYjsConnectionError, codeMirrorEditor);

const cmPropsOverride = useMemo<ReactCodeMirrorProps>(() => deepmerge(
cmProps ?? {},
Expand Down
2 changes: 1 addition & 1 deletion apps/app/src/client/services/use-single-editor-mode.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ export const useSingleEditorMode = (): void => {
const { data: currentPage } = useSWRxCurrentPage();
const { data: yjsMaxBodyLength } = useYjsMaxBodyLength();
const { data: codeMirrorEditor } = useCodeMirrorEditorIsolated(GlobalCodeMirrorEditorKey.MAIN);
const isYjsEnabled = useIsYjsEnabled();
const { data: isYjsEnabled } = useIsYjsEnabled();

const [shouldRecalculate, setShouldRecalculate] = useState(false);

Expand Down
17 changes: 10 additions & 7 deletions apps/app/src/client/services/yjs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,26 +2,29 @@ import {
useState, useEffect, useCallback,
} from 'react';

import { useSWRStatic } from '@growi/core/dist/swr';
import { useRouter } from 'next/router';
import type { SWRResponse } from 'swr';

import { useYjsMaxBodyLength } from '~/stores-universal/context';
import { EditorMode, useEditorMode } from '~/stores-universal/ui';
import { useSWRxCurrentPage } from '~/stores/page';

export const useIsYjsEnabled = (): boolean | undefined => {
export const useIsYjsEnabled = (): SWRResponse<boolean, Error> => {
const { data: yjsMaxBodyLength } = useYjsMaxBodyLength();
const { data: currentPage } = useSWRxCurrentPage();
const { data: editorMode } = useEditorMode();

const [isYjsEnabled, setIsYjsEnabled] = useState<boolean | undefined>(undefined);
const [shouldRecalculate, setShouldRecalculate] = useState<boolean>(false);

const swrResponse = useSWRStatic<boolean, Error>('isYjsEnabled', undefined);

const router = useRouter();

const onRouterChangeComplete = useCallback(() => {
setIsYjsEnabled(undefined);
setShouldRecalculate(false);
}, []);
swrResponse.mutate(undefined);
}, [swrResponse]);

useEffect(() => {
router.events.on('routeChangeComplete', onRouterChangeComplete);
Expand All @@ -36,16 +39,16 @@ export const useIsYjsEnabled = (): boolean | undefined => {
}
else {
setShouldRecalculate(false);
setIsYjsEnabled(undefined);
swrResponse.mutate(undefined);
}
}, [editorMode]);

useEffect(() => {
if (shouldRecalculate && currentPage?.revision?.body != null && yjsMaxBodyLength != null) {
setShouldRecalculate(false);
setIsYjsEnabled(currentPage.revision.body.length <= yjsMaxBodyLength);
swrResponse.mutate(currentPage.revision.body.length <= yjsMaxBodyLength);
}
}, [currentPage?.revision?.body, shouldRecalculate, yjsMaxBodyLength]);

return isYjsEnabled;
return swrResponse;
};
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ export const useCollaborativeEditorMode = (
user?: IUserHasId,
pageId?: string,
onEditorsUpdated?: (userList: IUserHasId[]) => void,
onYjsConnectionError?: () => void,
codeMirrorEditor?: UseCodeMirrorEditor,
): void => {
const [ydoc, setYdoc] = useState<Y.Doc | null>(null);
Expand Down Expand Up @@ -96,6 +97,10 @@ export const useCollaborativeEditorMode = (
}
});

socketIOProvider.on('connection-error', () => {
onYjsConnectionError?.();
});

// update args type see: SocketIOProvider.Awareness.awarenessUpdate
socketIOProvider.awareness.on('update', (update: { added: unknown[]; removed: unknown[]; }) => {
const { added, removed } = update;
Expand All @@ -106,7 +111,7 @@ export const useCollaborativeEditorMode = (
});

setProvider(socketIOProvider);
}, [onEditorsUpdated, pageId, provider, socket, user, ydoc]);
}, [onYjsConnectionError, onEditorsUpdated, pageId, provider, socket, user, ydoc]);

// Setup Ydoc Extensions
useEffect(() => {
Expand Down
Loading