import React, { useCallback, useEffect, useMemo } from 'react';
import { useTranslation } from 'next-i18next';
import * as ReactDOMServer from 'react-dom/server';
import { SocketEventName } from '~/interfaces/websocket';
import { useGetEditingMarkdown } from '~/stores/editor';
import {
useHasDraftOnHackmd, useIsHackmdDraftUpdatingInRealtime, useRevisionIdHackmdSynced,
} from '~/stores/hackmd';
import { useSWRxCurrentPage } from '~/stores/page';
import { useRemoteRevisionBody, useRemoteRevisionId, useRemoteRevisionLastUpdatUser } from '~/stores/remote-latest-page';
import { useGlobalSocket } from '~/stores/websocket';
import { Username } from './User/Username';
import styles from './PageStatusAlert.module.scss';
type AlertComponentContents = {
additionalClasses: string[],
label: JSX.Element,
btn: JSX.Element
}
export const PageStatusAlert = (): JSX.Element => {
const { t } = useTranslation();
const { data: isHackmdDraftUpdatingInRealtime } = useIsHackmdDraftUpdatingInRealtime();
const { data: hasDraftOnHackmd } = useHasDraftOnHackmd();
const { data: getEditingMarkdown } = useGetEditingMarkdown();
// store remote latest page data
const { data: revisionIdHackmdSynced } = useRevisionIdHackmdSynced();
const { data: remoteRevisionId, mutate: mutateRemoteRevisionId } = useRemoteRevisionId();
const { data: remoteRevisionBody, mutate: mutateRemoteRevisionBody } = useRemoteRevisionBody();
const { data: remoteRevisionLastUpdateUser, mutate: mutateRemoteRevisionLastUpdateUser } = useRemoteRevisionLastUpdatUser();
const { data: pageData } = useSWRxCurrentPage();
const revision = pageData?.revision;
const pageId = pageData?._id;
const { data: socket } = useGlobalSocket();
// method from page container
// setLatestRemotePageData(s2cMessagePageUpdated) {
// const newState = {
// remoteRevisionId: s2cMessagePageUpdated.revisionId,
// remoteRevisionBody: s2cMessagePageUpdated.revisionBody,
// remoteRevisionUpdateAt: s2cMessagePageUpdated.revisionUpdateAt,
// revisionIdHackmdSynced: s2cMessagePageUpdated.revisionIdHackmdSynced,
// // TODO // TODO remove lastUpdateUsername and refactor parts that lastUpdateUsername is used
// lastUpdateUsername: s2cMessagePageUpdated.lastUpdateUsername,
// lastUpdateUser: s2cMessagePageUpdated.remoteLastUpdateUser,
// };
// if (s2cMessagePageUpdated.hasDraftOnHackmd != null) {
// newState.hasDraftOnHackmd = s2cMessagePageUpdated.hasDraftOnHackmd;
// }
// this.setState(newState);
// }
const setLatestRemotePageData = useCallback((s2cMessagePageUpdated: any) => {
mutateRemoteRevisionId(s2cMessagePageUpdated.revisionId);
mutateRemoteRevisionBody(s2cMessagePageUpdated.revisionBody);
mutateRemoteRevisionLastUpdateUser(s2cMessagePageUpdated.remoteLastUpdateUser);
}, [mutateRemoteRevisionBody, mutateRemoteRevisionId, mutateRemoteRevisionLastUpdateUser]);
useEffect(() => {
if (socket == null) { return }
socket.on(SocketEventName.PageUpdated, (data) => {
const { s2cMessagePageUpdated } = data;
if (s2cMessagePageUpdated.pageId === pageId) {
setLatestRemotePageData(s2cMessagePageUpdated);
}
});
return () => { socket.off(SocketEventName.PageUpdated) };
}, [pageId, setLatestRemotePageData, socket]);
const refreshPage = useCallback(() => {
window.location.reload();
}, []);
const onClickResolveConflict = useCallback(() => {
// this.props.pageContainer.setState({
// isConflictDiffModalOpen: true,
// });
}, []);
const getContentsForSomeoneEditingAlert = useCallback((): AlertComponentContents => {
return {
additionalClasses: ['bg-success', 'd-hackmd-none'],
label:
<>
{t('hackmd.someone_editing')}
>,
btn:
Open HackMD Editor
,
};
}, [t]);
const getContentsForDraftExistsAlert = useCallback((): AlertComponentContents => {
return {
additionalClasses: ['bg-success', 'd-hackmd-none'],
label:
<>
{t('hackmd.this_page_has_draft')}
>,
btn:
Open HackMD Editor
,
};
}, [t]);
const getContentsForUpdatedAlert = useCallback((): AlertComponentContents => {
let isConflictOnEdit = false;
if (getEditingMarkdown != null) {
const editingMarkdown = getEditingMarkdown();
isConflictOnEdit = editingMarkdown !== remoteRevisionBody;
}
// TODO: re-impl with Next.js way
const usernameComponentToString = ReactDOMServer.renderToString(
{label}
{btn}