feat(core): simple recovery history ui poc (#5033)

Simple recovery history UI poc.
What's missing
- [x] e2e

All biz logic should be done, excluding complete ui details.
- [ ] offline prompt
- [ ] history timeline
- [ ] page ui

https://github.com/toeverything/AFFiNE/assets/584378/fc3f6a48-ff7f-4265-b9f5-9c0087cb2635
This commit is contained in:
Peng Xiao
2023-11-27 02:41:19 +00:00
parent f04ec50d12
commit 34d575078c
23 changed files with 1291 additions and 14 deletions
@@ -4,6 +4,7 @@ import { useSWRConfig } from 'swr';
export function useMutateCloud() {
const { mutate } = useSWRConfig();
return useCallback(async () => {
// todo: should not mutate all graphql cache
return mutate(key => {
if (Array.isArray(key)) {
return key[0] === 'cloud';
@@ -1,25 +1,29 @@
import { toast } from '@affine/component';
import { WorkspaceFlavour } from '@affine/env/workspace';
import { useAFFiNEI18N } from '@affine/i18n/hooks';
import { assertExists } from '@blocksuite/global/utils';
import { EdgelessIcon, PageIcon } from '@blocksuite/icons';
import type { Workspace } from '@blocksuite/store';
import { EdgelessIcon, HistoryIcon, PageIcon } from '@blocksuite/icons';
import { usePageMetaHelper } from '@toeverything/hooks/use-block-suite-page-meta';
import {
PreconditionStrategy,
registerAffineCommand,
} from '@toeverything/infra/command';
import { useSetAtom } from 'jotai';
import { useCallback, useEffect } from 'react';
import { pageHistoryModalAtom } from '../../atoms/page-history';
import { useCurrentWorkspace } from '../current/use-current-workspace';
import { useBlockSuiteMetaHelper } from './use-block-suite-meta-helper';
import { useExportPage } from './use-export-page';
import { useTrashModalHelper } from './use-trash-modal-helper';
export function useRegisterBlocksuiteEditorCommands(
blockSuiteWorkspace: Workspace,
pageId: string,
mode: 'page' | 'edgeless'
) {
const t = useAFFiNEI18N();
const [workspace] = useCurrentWorkspace();
const blockSuiteWorkspace = workspace.blockSuiteWorkspace;
const { getPageMeta } = usePageMetaHelper(blockSuiteWorkspace);
const currentPage = blockSuiteWorkspace.getPage(pageId);
assertExists(currentPage);
@@ -28,6 +32,15 @@ export function useRegisterBlocksuiteEditorCommands(
const favorite = pageMeta.favorite ?? false;
const trash = pageMeta.trash ?? false;
const setPageHistoryModalState = useSetAtom(pageHistoryModalAtom);
const openHistoryModal = useCallback(() => {
setPageHistoryModalState(() => ({
pageId,
open: true,
}));
}, [pageId, setPageHistoryModalState]);
const { togglePageMode, toggleFavorite, restoreFromTrash } =
useBlockSuiteMetaHelper(blockSuiteWorkspace);
const exportHandler = useExportPage(currentPage);
@@ -40,12 +53,14 @@ export function useRegisterBlocksuiteEditorCommands(
});
}, [pageId, pageMeta.title, setTrashModal]);
const isCloudWorkspace = workspace.flavour === WorkspaceFlavour.AFFINE_CLOUD;
useEffect(() => {
const unsubs: Array<() => void> = [];
const preconditionStrategy = () =>
PreconditionStrategy.InPaperOrEdgeless && !trash;
//TODO: add back when edgeless presentation is ready
// TODO: add back when edgeless presentation is ready
// this is pretty hack and easy to break. need a better way to communicate with blocksuite editor
// unsubs.push(
@@ -189,6 +204,20 @@ export function useRegisterBlocksuiteEditorCommands(
})
);
if (runtimeConfig.enablePageHistory && isCloudWorkspace) {
unsubs.push(
registerAffineCommand({
id: `editor:${mode}-page-history`,
category: `editor:${mode}`,
icon: <HistoryIcon />,
label: t['com.affine.cmdk.affine.editor.reveal-page-history-modal'](),
run() {
openHistoryModal();
},
})
);
}
return () => {
unsubs.forEach(unsub => unsub());
};
@@ -198,11 +227,12 @@ export function useRegisterBlocksuiteEditorCommands(
onClickDelete,
exportHandler,
pageId,
pageMeta.title,
restoreFromTrash,
t,
toggleFavorite,
togglePageMode,
trash,
isCloudWorkspace,
openHistoryModal,
]);
}
@@ -12,7 +12,12 @@ const errorHandler: Middleware = useSWRNext => (key, fetcher, config) => {
export const useServerFlavor = () => {
const { data: config, error } = useQuery(
{ query: serverConfigQuery },
{ use: [errorHandler] }
{
use: [errorHandler],
revalidateOnFocus: false,
revalidateOnMount: false,
revalidateIfStale: false,
}
);
if (error || !config) {
@@ -4,7 +4,7 @@ import {
} from '@toeverything/infra/command';
import { useEffect } from 'react';
export function useRegisterBlocksuiteEditorCommands(
export function useRegisterBrowserHistoryCommands(
back: () => unknown,
forward: () => unknown
) {