feat(core): sidebar local workspace enable cloud directly (#6366)

- Add a new hook `useEnableClould`, remove `<EnableAffineClouldModal />`
- Sidebar local workspace list item support enable AFFiNE Cloud
This commit is contained in:
CatsJuice
2024-03-29 02:08:09 +00:00
parent 1a873ecf3c
commit 35715ab1d8
11 changed files with 273 additions and 211 deletions
@@ -1,54 +0,0 @@
import type { ConfirmModalProps } from '@affine/component/ui/modal';
import { ConfirmModal } from '@affine/component/ui/modal';
import { useAFFiNEI18N } from '@affine/i18n/hooks';
import { useSetAtom } from 'jotai';
import { useCallback } from 'react';
import { authAtom } from '../../../atoms';
import { setOnceSignedInEventAtom } from '../../../atoms/event';
import { useCurrentLoginStatus } from '../../../hooks/affine/use-current-login-status';
export const EnableAffineCloudModal = ({
onConfirm: propsOnConfirm,
...props
}: Omit<ConfirmModalProps, 'onConfirm'> & { onConfirm: () => void }) => {
const t = useAFFiNEI18N();
const loginStatus = useCurrentLoginStatus();
const setAuthAtom = useSetAtom(authAtom);
const setOnceSignedInEvent = useSetAtom(setOnceSignedInEventAtom);
const confirm = useCallback(() => {
return propsOnConfirm?.();
}, [propsOnConfirm]);
const onConfirm = useCallback(() => {
if (loginStatus === 'unauthenticated') {
setAuthAtom(prev => ({
...prev,
openModal: true,
}));
setOnceSignedInEvent(confirm);
}
if (loginStatus === 'authenticated') {
return propsOnConfirm?.();
}
}, [confirm, loginStatus, propsOnConfirm, setAuthAtom, setOnceSignedInEvent]);
return (
<ConfirmModal
title={t['Enable AFFiNE Cloud']()}
description={t['Enable AFFiNE Cloud Description']()}
cancelText={t['com.affine.enableAffineCloudModal.button.cancel']()}
onConfirm={onConfirm}
confirmButtonOptions={{
type: 'primary',
['data-testid' as string]: 'confirm-enable-affine-cloud-button',
children:
loginStatus === 'authenticated'
? t['Enable']()
: t['Sign in and Enable'](),
}}
{...props}
/>
);
};
@@ -3,64 +3,43 @@ import {
openDisableCloudAlertModalAtom,
openHistoryTipsModalAtom,
} from '@affine/core/atoms';
import { useAsyncCallback } from '@affine/core/hooks/affine-async-hooks';
import { useNavigateHelper } from '@affine/core/hooks/use-navigate-helper';
import { WorkspaceSubPath } from '@affine/core/shared';
import { useEnableCloud } from '@affine/core/hooks/affine/use-enable-cloud';
import { useAFFiNEI18N } from '@affine/i18n/hooks';
import { useService, Workspace, WorkspaceManager } from '@toeverything/infra';
import { useService, Workspace } from '@toeverything/infra';
import { useAtom, useSetAtom } from 'jotai';
import { useCallback, useState } from 'react';
import { useCallback } from 'react';
import { EnableAffineCloudModal } from '../enable-affine-cloud-modal';
import TopSvg from './top-svg';
export const HistoryTipsModal = () => {
const t = useAFFiNEI18N();
const { openPage } = useNavigateHelper();
const workspaceManager = useService(WorkspaceManager);
const currentWorkspace = useService(Workspace);
const [open, setOpen] = useAtom(openHistoryTipsModalAtom);
const setTempDisableCloudOpen = useSetAtom(openDisableCloudAlertModalAtom);
const [openEnableCloudModal, setOpenEnableCloudModal] = useState(false);
const confirmEnableCloud = useEnableCloud();
const handleConfirm = useCallback(() => {
setOpen(false);
if (runtimeConfig.enableCloud) {
return setOpenEnableCloudModal(true);
}
return setTempDisableCloudOpen(true);
}, [setOpen, setTempDisableCloudOpen]);
const handEnableCloud = useAsyncCallback(async () => {
if (!currentWorkspace) {
confirmEnableCloud(currentWorkspace);
return;
}
const { id: newId } =
await workspaceManager.transformLocalToCloud(currentWorkspace);
openPage(newId, WorkspaceSubPath.ALL);
setOpenEnableCloudModal(false);
}, [openPage, currentWorkspace, workspaceManager]);
return setTempDisableCloudOpen(true);
}, [confirmEnableCloud, currentWorkspace, setOpen, setTempDisableCloudOpen]);
return (
<>
<OverlayModal
open={open}
topImage={<TopSvg />}
title={t['com.affine.history-vision.tips-modal.title']()}
onOpenChange={setOpen}
description={t['com.affine.history-vision.tips-modal.description']()}
cancelText={t['com.affine.history-vision.tips-modal.cancel']()}
confirmButtonOptions={{
type: 'primary',
}}
onConfirm={handleConfirm}
confirmText={t['com.affine.history-vision.tips-modal.confirm']()}
/>
<EnableAffineCloudModal
open={openEnableCloudModal}
onOpenChange={setOpenEnableCloudModal}
onConfirm={handEnableCloud}
/>
</>
<OverlayModal
open={open}
topImage={<TopSvg />}
title={t['com.affine.history-vision.tips-modal.title']()}
onOpenChange={setOpen}
description={t['com.affine.history-vision.tips-modal.description']()}
cancelText={t['com.affine.history-vision.tips-modal.cancel']()}
confirmButtonOptions={{
type: 'primary',
}}
onConfirm={handleConfirm}
confirmText={t['com.affine.history-vision.tips-modal.confirm']()}
/>
);
};
@@ -1,19 +1,15 @@
import { SettingRow } from '@affine/component/setting-components';
import { Button } from '@affine/component/ui/button';
import { useAsyncCallback } from '@affine/core/hooks/affine-async-hooks';
import { useEnableCloud } from '@affine/core/hooks/affine/use-enable-cloud';
import { useWorkspaceInfo } from '@affine/core/hooks/use-workspace-info';
import { UNTITLED_WORKSPACE_NAME } from '@affine/env/constant';
import { WorkspaceFlavour } from '@affine/env/workspace';
import { useAFFiNEI18N } from '@affine/i18n/hooks';
import type { Workspace } from '@toeverything/infra';
import { useService, WorkspaceManager } from '@toeverything/infra';
import { useSetAtom } from 'jotai';
import { useState } from 'react';
import { useCallback, useState } from 'react';
import { openSettingModalAtom } from '../../../../../atoms';
import { useNavigateHelper } from '../../../../../hooks/use-navigate-helper';
import { WorkspaceSubPath } from '../../../../../shared';
import { EnableAffineCloudModal } from '../../../enable-affine-cloud-modal';
import { TmpDisableAffineCloudModal } from '../../../tmp-disable-affine-cloud-modal';
import type { WorkspaceSettingDetailProps } from './types';
@@ -26,28 +22,21 @@ export const EnableCloudPanel = ({
workspace,
}: PublishPanelProps) => {
const t = useAFFiNEI18N();
const confirmEnableCloud = useEnableCloud();
const { openPage } = useNavigateHelper();
const workspaceManager = useService(WorkspaceManager);
const workspaceInfo = useWorkspaceInfo(workspaceMetadata);
const setSettingModal = useSetAtom(openSettingModalAtom);
const [open, setOpen] = useState(false);
const handleEnableCloud = useAsyncCallback(async () => {
if (!workspace) {
return;
}
const { id: newId } =
await workspaceManager.transformLocalToCloud(workspace);
openPage(newId, WorkspaceSubPath.ALL);
setOpen(false);
setSettingModal(settings => ({
...settings,
open: false,
}));
}, [openPage, setSettingModal, workspace, workspaceManager]);
const confirmEnableCloudAndClose = useCallback(() => {
if (!workspace) return;
confirmEnableCloud(workspace, {
onSuccess: () => {
setSettingModal(settings => ({ ...settings, open: false }));
},
});
}, [confirmEnableCloud, setSettingModal, workspace]);
if (workspaceMetadata.flavour !== WorkspaceFlavour.LOCAL) {
return null;
@@ -69,21 +58,13 @@ export const EnableCloudPanel = ({
<Button
data-testid="publish-enable-affine-cloud-button"
type="primary"
onClick={() => {
setOpen(true);
}}
onClick={confirmEnableCloudAndClose}
style={{ marginTop: '12px' }}
>
{t['Enable AFFiNE Cloud']()}
</Button>
</SettingRow>
{runtimeConfig.enableCloud ? (
<EnableAffineCloudModal
open={open}
onOpenChange={setOpen}
onConfirm={handleEnableCloud}
/>
) : (
{runtimeConfig.enableCloud ? null : (
<TmpDisableAffineCloudModal open={open} onOpenChange={setOpen} />
)}
</>
@@ -1,12 +1,7 @@
import { useAsyncCallback } from '@affine/core/hooks/affine-async-hooks';
import { WorkspaceFlavour } from '@affine/env/workspace';
import { useEnableCloud } from '@affine/core/hooks/affine/use-enable-cloud';
import type { Doc } from '@blocksuite/store';
import type { Workspace } from '@toeverything/infra';
import { useService, WorkspaceManager } from '@toeverything/infra';
import { useState } from 'react';
import { useNavigateHelper } from '../../../hooks/use-navigate-helper';
import { EnableAffineCloudModal } from '../enable-affine-cloud-modal';
import { ShareMenu } from './share-menu';
type SharePageModalProps = {
@@ -20,37 +15,18 @@ export const SharePageButton = ({
page,
isJournal,
}: SharePageModalProps) => {
const [open, setOpen] = useState(false);
const { openPage } = useNavigateHelper();
const workspaceManager = useService(WorkspaceManager);
const handleConfirm = useAsyncCallback(async () => {
if (workspace.flavour !== WorkspaceFlavour.LOCAL) {
return;
}
const { id: newId } =
await workspaceManager.transformLocalToCloud(workspace);
openPage(newId, page.id);
setOpen(false);
}, [openPage, page.id, workspace, workspaceManager]);
const confirmEnableCloud = useEnableCloud();
return (
<>
<ShareMenu
isJournal={isJournal}
workspaceMetadata={workspace.meta}
currentPage={page}
onEnableAffineCloud={() => setOpen(true)}
/>
{workspace.flavour === WorkspaceFlavour.LOCAL ? (
<EnableAffineCloudModal
open={open}
onOpenChange={setOpen}
onConfirm={handleConfirm}
/>
) : null}
</>
<ShareMenu
isJournal={isJournal}
workspaceMetadata={workspace.meta}
currentPage={page}
onEnableAffineCloud={() =>
confirmEnableCloud(workspace, {
openPageId: page.id,
})
}
/>
);
};
@@ -2,6 +2,7 @@ import { ScrollableContainer } from '@affine/component';
import { Divider } from '@affine/component/ui/divider';
import { WorkspaceList } from '@affine/component/workspace-list';
import { useSession } from '@affine/core/hooks/affine/use-current-user';
import { useEnableCloud } from '@affine/core/hooks/affine/use-enable-cloud';
import {
useWorkspaceAvatar,
useWorkspaceName,
@@ -13,7 +14,7 @@ import type { DragEndEvent } from '@dnd-kit/core';
import type { WorkspaceMetadata } from '@toeverything/infra';
import { useLiveData, useService, WorkspaceManager } from '@toeverything/infra';
import { useSetAtom } from 'jotai';
import { useCallback, useMemo } from 'react';
import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
import {
openCreateWorkspaceModalAtom,
@@ -28,8 +29,10 @@ interface WorkspaceModalProps {
disabled?: boolean;
workspaces: WorkspaceMetadata[];
currentWorkspaceId?: string | null;
openingId?: string | null;
onClickWorkspace: (workspaceMetadata: WorkspaceMetadata) => void;
onClickWorkspaceSetting: (workspaceMetadata: WorkspaceMetadata) => void;
onClickEnableCloud?: (meta: WorkspaceMetadata) => void;
onNewWorkspace: () => void;
onAddWorkspace: () => void;
onDragEnd: (event: DragEndEvent) => void;
@@ -77,6 +80,8 @@ const LocalWorkspaces = ({
workspaces,
onClickWorkspace,
onClickWorkspaceSetting,
onClickEnableCloud,
openingId,
currentWorkspaceId,
onDragEnd,
}: WorkspaceModalProps) => {
@@ -95,11 +100,13 @@ const LocalWorkspaces = ({
{t['com.affine.workspaceList.workspaceListType.local']()}
</div>
<WorkspaceList
openingId={openingId}
disabled={disabled}
items={workspaces}
currentWorkspaceId={currentWorkspaceId}
onClick={onClickWorkspace}
onSettingClick={onClickWorkspaceSetting}
onEnableCloudClick={onClickEnableCloud}
onDragEnd={onDragEnd}
useIsWorkspaceOwner={useIsWorkspaceOwner}
useWorkspaceName={useWorkspaceName}
@@ -114,11 +121,13 @@ export const AFFiNEWorkspaceList = ({
}: {
onEventEnd?: () => void;
}) => {
const workspaces = useLiveData(
useService(WorkspaceManager).list.workspaceList$
);
const openWsRef = useRef<ReturnType<typeof workspaceManager.open>>();
const workspaceManager = useService(WorkspaceManager);
const workspaces = useLiveData(workspaceManager.list.workspaceList$);
const setOpenCreateWorkspaceModal = useSetAtom(openCreateWorkspaceModalAtom);
const [openingId, setOpeningId] = useState<string | null>(null);
const confirmEnableCloud = useEnableCloud();
const { jumpToSubPath } = useNavigateHelper();
@@ -160,6 +169,28 @@ export const AFFiNEWorkspaceList = ({
[onEventEnd, setOpenSettingModalAtom]
);
const onClickEnableCloud = useCallback(
(meta: WorkspaceMetadata) => {
openWsRef.current?.release();
openWsRef.current = workspaceManager.open(meta);
confirmEnableCloud(openWsRef.current.workspace, {
onFinished: () => {
openWsRef.current?.release();
openWsRef.current = undefined;
setOpeningId(null);
},
});
setOpeningId(meta.id);
},
[confirmEnableCloud, workspaceManager]
);
useEffect(() => {
return () => {
openWsRef.current?.release();
};
}, []);
const onMoveWorkspace = useCallback((_activeId: string, _overId: string) => {
// TODO: order
// const oldIndex = workspaces.findIndex(w => w.id === activeId);
@@ -219,9 +250,11 @@ export const AFFiNEWorkspaceList = ({
</div>
) : null}
<LocalWorkspaces
openingId={openingId}
workspaces={localWorkspaces}
onClickWorkspace={onClickWorkspace}
onClickWorkspaceSetting={onClickWorkspaceSetting}
onClickEnableCloud={onClickEnableCloud}
onNewWorkspace={onNewWorkspace}
onAddWorkspace={onAddWorkspace}
currentWorkspaceId={currentWorkspace?.id}
@@ -1,18 +1,14 @@
import { BrowserWarning, LocalDemoTips } from '@affine/component/affine-banner';
import { useAsyncCallback } from '@affine/core/hooks/affine-async-hooks';
import { WorkspaceFlavour } from '@affine/env/workspace';
import { Trans } from '@affine/i18n';
import { useAFFiNEI18N } from '@affine/i18n/hooks';
import type { Workspace } from '@toeverything/infra';
import { useService, WorkspaceManager } from '@toeverything/infra';
import { useSetAtom } from 'jotai';
import { useCallback, useState } from 'react';
import { authAtom } from '../atoms';
import { useCurrentLoginStatus } from '../hooks/affine/use-current-login-status';
import { useNavigateHelper } from '../hooks/use-navigate-helper';
import { WorkspaceSubPath } from '../shared';
import { EnableAffineCloudModal } from './affine/enable-affine-cloud-modal';
import { useEnableCloud } from '../hooks/affine/use-enable-cloud';
const minimumChromeVersion = 106;
@@ -68,47 +64,29 @@ export const TopTip = ({
const [showWarning, setShowWarning] = useState(shouldShowWarning);
const [showLocalDemoTips, setShowLocalDemoTips] = useState(true);
const [open, setOpen] = useState(false);
const confirmEnableCloud = useEnableCloud();
const setAuthModal = useSetAtom(authAtom);
const onLogin = useCallback(() => {
setAuthModal({ openModal: true, state: 'signIn' });
}, [setAuthModal]);
const { openPage } = useNavigateHelper();
const workspaceManager = useService(WorkspaceManager);
const handleConfirm = useAsyncCallback(async () => {
if (workspace.flavour !== WorkspaceFlavour.LOCAL) {
return;
}
// TODO: we need to transform local to cloud
const { id: newId } =
await workspaceManager.transformLocalToCloud(workspace);
openPage(newId, pageId || WorkspaceSubPath.ALL);
setOpen(false);
}, [openPage, pageId, workspace, workspaceManager]);
if (
showLocalDemoTips &&
!environment.isDesktop &&
workspace.flavour === WorkspaceFlavour.LOCAL
) {
return (
<>
<LocalDemoTips
isLoggedIn={isLoggedIn}
onLogin={onLogin}
onEnableCloud={() => setOpen(true)}
onClose={() => {
setShowLocalDemoTips(false);
}}
/>
<EnableAffineCloudModal
open={open}
onOpenChange={setOpen}
onConfirm={handleConfirm}
/>
</>
<LocalDemoTips
isLoggedIn={isLoggedIn}
onLogin={onLogin}
onEnableCloud={() =>
confirmEnableCloud(workspace, { openPageId: pageId })
}
onClose={() => {
setShowLocalDemoTips(false);
}}
/>
);
}