Merge pull request #864 from toeverything/feat/sync-status

Feat/sync status
This commit is contained in:
DarkSky 2023-02-07 19:06:52 +08:00 committed by GitHub
commit d135bcb2fd
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 48 additions and 9 deletions

View File

@ -4,13 +4,15 @@ import { Button } from '@/ui/button';
import { Check, UnCheck } from './icon'; import { Check, UnCheck } from './icon';
import { useState } from 'react'; import { useState } from 'react';
import { useTranslation } from '@affine/i18n'; import { useTranslation } from '@affine/i18n';
import { useAppState } from '@/providers/app-state-provider';
interface LoginModalProps { interface LoginModalProps {
open: boolean; open: boolean;
onClose: (wait: boolean) => void; onClose: (wait: boolean) => void;
} }
export const LogoutModal = ({ open, onClose }: LoginModalProps) => { export const LogoutModal = ({ open, onClose }: LoginModalProps) => {
const [localCache, setLocalCache] = useState(false); const [localCache, setLocalCache] = useState(true);
const { blobDataSynced } = useAppState();
const { t } = useTranslation(); const { t } = useTranslation();
return ( return (
<Modal open={open} onClose={onClose} data-testid="logout-modal"> <Modal open={open} onClose={onClose} data-testid="logout-modal">
@ -24,7 +26,11 @@ export const LogoutModal = ({ open, onClose }: LoginModalProps) => {
</Header> </Header>
<Content> <Content>
<ContentTitle>{t('Sign out')}?</ContentTitle> <ContentTitle>{t('Sign out')}?</ContentTitle>
<SignDes>{t('Set up an AFFiNE account to sync data')}</SignDes> <SignDes>
{blobDataSynced
? t('Set up an AFFiNE account to sync data')
: 'All data has been stored in the cloud'}
</SignDes>
<StyleTips> <StyleTips>
{localCache ? ( {localCache ? (
<StyleCheck <StyleCheck

View File

@ -38,7 +38,7 @@ export const useEnsureWorkspace = () => {
// } // }
const workspaceId = const workspaceId =
(router.query.workspaceId as string) || workspaceList[0]?.id; (router.query.workspaceId as string) || workspaceList[0]?.id;
loadWorkspace(workspaceId).finally(() => { loadWorkspace.current(workspaceId).finally(() => {
setWorkspaceLoaded(true); setWorkspaceLoaded(true);
setActiveWorkspaceId(activeWorkspaceId); setActiveWorkspaceId(activeWorkspaceId);
}); });

View File

@ -4,9 +4,11 @@ import { PageListHeader } from '@/components/header';
import { ReactElement } from 'react'; import { ReactElement } from 'react';
import WorkspaceLayout from '@/components/workspace-layout'; import WorkspaceLayout from '@/components/workspace-layout';
import { useTranslation } from '@affine/i18n'; import { useTranslation } from '@affine/i18n';
import { useAppState } from '@/providers/app-state-provider'; import { PageMeta, useAppState } from '@/providers/app-state-provider';
const All = () => { const All = () => {
const { pageList } = useAppState(); const { currentWorkspace } = useAppState();
const pageList = (currentWorkspace?.blocksuiteWorkspace?.meta.pageMetas ||
[]) as PageMeta[];
const { t } = useTranslation(); const { t } = useTranslation();
return ( return (
<> <>

View File

@ -10,16 +10,20 @@ import {
import { createDefaultWorkspace } from './utils'; import { createDefaultWorkspace } from './utils';
import { User } from '@affine/datacenter'; import { User } from '@affine/datacenter';
export interface Disposable {
dispose(): void;
}
type AppStateContextProps = PropsWithChildren<Record<string, unknown>>; type AppStateContextProps = PropsWithChildren<Record<string, unknown>>;
export const AppState = createContext<AppStateContext>({} as AppStateContext); export const AppState = createContext<AppStateContext>({} as AppStateContext);
export const useAppState = () => useContext(AppState); export const useAppState = () => useContext(AppState);
export const AppStateProvider = ({ export const AppStateProvider = ({
children, children,
}: PropsWithChildren<AppStateContextProps>) => { }: PropsWithChildren<AppStateContextProps>) => {
const [appState, setAppState] = useState<AppStateValue>({} as AppStateValue); const [appState, setAppState] = useState<AppStateValue>({} as AppStateValue);
const [blobState, setBlobState] = useState(false);
useEffect(() => { useEffect(() => {
const initState = async () => { const initState = async () => {
const dataCenter = await getDataCenter(); const dataCenter = await getDataCenter();
@ -90,7 +94,8 @@ export const AppStateProvider = ({
}); });
}; };
const loadWorkspace = useRef<AppStateFunction['loadWorkspace']>(); const loadWorkspace: AppStateFunction['loadWorkspace'] =
useRef() as AppStateFunction['loadWorkspace'];
loadWorkspace.current = async (workspaceId: string) => { loadWorkspace.current = async (workspaceId: string) => {
const { dataCenter, workspaceList, currentWorkspace, user } = appState; const { dataCenter, workspaceList, currentWorkspace, user } = appState;
if (!workspaceList.find(v => v.id.toString() === workspaceId)) { if (!workspaceList.find(v => v.id.toString() === workspaceId)) {
@ -99,6 +104,7 @@ export const AppStateProvider = ({
if (workspaceId === currentWorkspace?.id) { if (workspaceId === currentWorkspace?.id) {
return currentWorkspace; return currentWorkspace;
} }
const workspace = (await dataCenter.loadWorkspace(workspaceId)) ?? null; const workspace = (await dataCenter.loadWorkspace(workspaceId)) ?? null;
let isOwner; let isOwner;
if (workspace?.provider === 'local') { if (workspace?.provider === 'local') {
@ -108,6 +114,7 @@ export const AppStateProvider = ({
// We must ensure workspace.owner exists, then ensure id same. // We must ensure workspace.owner exists, then ensure id same.
isOwner = workspace?.owner && user?.id === workspace.owner.id; isOwner = workspace?.owner && user?.id === workspace.owner.id;
} }
const pageList = const pageList =
(workspace?.blocksuiteWorkspace?.meta.pageMetas as PageMeta[]) ?? []; (workspace?.blocksuiteWorkspace?.meta.pageMetas as PageMeta[]) ?? [];
setAppState({ setAppState({
@ -122,6 +129,26 @@ export const AppStateProvider = ({
return workspace; return workspace;
}; };
useEffect(() => {
let syncChangeDisposable: Disposable | undefined;
const currentWorkspace = appState.currentWorkspace;
if (!currentWorkspace) {
return;
}
const getBlobStorage = async () => {
const blobStorage = await currentWorkspace?.blocksuiteWorkspace?.blobs;
syncChangeDisposable = blobStorage?.signals.onBlobSyncStateChange.on(
() => {
setBlobState(blobStorage?.uploading);
}
);
};
getBlobStorage();
return () => {
syncChangeDisposable?.dispose();
};
}, [appState.currentWorkspace]);
const setEditor: AppStateFunction['setEditor'] = const setEditor: AppStateFunction['setEditor'] =
useRef() as AppStateFunction['setEditor']; useRef() as AppStateFunction['setEditor'];
setEditor.current = editor => { setEditor.current = editor => {
@ -163,9 +190,10 @@ export const AppStateProvider = ({
...appState, ...appState,
setEditor, setEditor,
loadPage: loadPage.current, loadPage: loadPage.current,
loadWorkspace: loadWorkspace.current, loadWorkspace: loadWorkspace,
login, login,
logout, logout,
blobDataSynced: blobState,
}} }}
> >
{children} {children}

View File

@ -24,12 +24,15 @@ export type AppStateValue = {
editor?: EditorContainer | null; editor?: EditorContainer | null;
synced: boolean; synced: boolean;
isOwner?: boolean; isOwner?: boolean;
blobDataSynced?: boolean;
}; };
export type AppStateFunction = { export type AppStateFunction = {
setEditor: MutableRefObject<(page: EditorContainer) => void>; setEditor: MutableRefObject<(page: EditorContainer) => void>;
loadWorkspace: (workspaceId: string) => Promise<WorkspaceUnit | null>; loadWorkspace: MutableRefObject<
(workspaceId: string) => Promise<WorkspaceUnit | null>
>;
loadPage: (pageId: string) => void; loadPage: (pageId: string) => void;
login: () => Promise<User>; login: () => Promise<User>;