fix(core): fix create workspace force cloud (#9382)

This commit is contained in:
EYHN
2024-12-27 13:33:05 +00:00
parent cbfe38b189
commit cff3a73db4
9 changed files with 165 additions and 130 deletions

View File

@@ -1,12 +1,8 @@
import { Divider } from '@affine/component/ui/divider';
import { MenuItem } from '@affine/component/ui/menu';
import { AuthService } from '@affine/core/modules/cloud';
import { GlobalDialogService } from '@affine/core/modules/dialogs';
import { FeatureFlagService } from '@affine/core/modules/feature-flag';
import {
type WorkspaceMetadata,
WorkspacesService,
} from '@affine/core/modules/workspace';
import { type WorkspaceMetadata } from '@affine/core/modules/workspace';
import { useI18n } from '@affine/i18n';
import { track } from '@affine/track';
import { Logo1Icon } from '@blocksuite/icons/rc';
@@ -119,9 +115,6 @@ const UserWithWorkspaceListInner = ({
globalDialogService.open('sign-in', { step: 'addSelfhosted' });
}, [globalDialogService]);
const workspaceManager = useService(WorkspacesService);
const workspaces = useLiveData(workspaceManager.list.workspaces$);
return (
<div className={styles.workspaceListWrapper}>
<AFFiNEWorkspaceList
@@ -130,7 +123,6 @@ const UserWithWorkspaceListInner = ({
showEnableCloudButton={showEnableCloudButton}
showSettingsButton={showSettingsButton}
/>
{workspaces.length > 0 ? <Divider size="thinner" /> : null}
<AddWorkspace
onAddWorkspace={onAddWorkspace}
onNewWorkspace={onNewWorkspace}

View File

@@ -138,17 +138,17 @@ const CloudWorkSpaceList = ({
items={[
server.id !== 'affine-cloud' && (
<MenuItem key="delete-server" onClick={handleDeleteServer}>
Delete Server
{t['com.affine.server.delete']()}
</MenuItem>
),
accountStatus === 'authenticated' && (
<MenuItem key="sign-out" onClick={handleSignOut}>
Sign Out
{t['com.affine.sign.out']()}
</MenuItem>
),
accountStatus === 'unauthenticated' && (
<MenuItem key="sign-in" onClick={handleSignIn}>
Sign In
{t['com.affine.sign.in']()}
</MenuItem>
),
]}
@@ -206,6 +206,7 @@ const LocalWorkspaces = ({
onSettingClick={onClickWorkspaceSetting}
onEnableCloudClick={onClickEnableCloud}
/>
<Divider size="thinner" />
</div>
);
};

View File

@@ -1,8 +1,8 @@
import { Avatar, ConfirmModal, Input, Switch } from '@affine/component';
import { Avatar, ConfirmModal, Input, notify, Switch } from '@affine/component';
import type { ConfirmModalProps } from '@affine/component/ui/modal';
import { CloudSvg } from '@affine/core/components/affine/share-page-modal/cloud-svg';
import { useAsyncCallback } from '@affine/core/components/hooks/affine-async-hooks';
import { AuthService } from '@affine/core/modules/cloud';
import { AuthService, ServersService } from '@affine/core/modules/cloud';
import {
type DialogComponentProps,
type GLOBAL_DIALOG_SCHEMA,
@@ -12,7 +12,7 @@ import { FeatureFlagService } from '@affine/core/modules/feature-flag';
import { WorkspacesService } from '@affine/core/modules/workspace';
import { useI18n } from '@affine/i18n';
import { track } from '@affine/track';
import { useLiveData, useService } from '@toeverything/infra';
import { FrameworkScope, useLiveData, useService } from '@toeverything/infra';
import { useCallback, useState } from 'react';
import { buildShowcaseWorkspace } from '../../../utils/first-app-data';
@@ -60,8 +60,18 @@ const NameWorkspaceContent = ({
);
const handleCreateWorkspace = useCallback(() => {
if (loginStatus !== 'authenticated' && enable) {
return openSignInModal();
}
onConfirmName(workspaceName, enable ? serverId || 'affine-cloud' : 'local');
}, [enable, onConfirmName, serverId, workspaceName]);
}, [
enable,
loginStatus,
onConfirmName,
openSignInModal,
serverId,
workspaceName,
]);
const onEnter = useCallback(() => {
if (workspaceName) {
@@ -109,37 +119,41 @@ const NameWorkspaceContent = ({
size="large"
/>
</div>
<div className={styles.affineCloudWrapper}>
<div className={styles.subTitle}>{t['AFFiNE Cloud']()}</div>
<div className={styles.card}>
<div className={styles.cardText}>
<div className={styles.cardTitle}>
<span>{t['com.affine.nameWorkspace.affine-cloud.title']()}</span>
<Switch
checked={enable}
onChange={onSwitchChange}
disabled={forcedCloud}
/>
{!serverId || serverId === 'affine-cloud' ? (
<div className={styles.affineCloudWrapper}>
<div className={styles.subTitle}>{t['AFFiNE Cloud']()}</div>
<div className={styles.card}>
<div className={styles.cardText}>
<div className={styles.cardTitle}>
<span>
{t['com.affine.nameWorkspace.affine-cloud.title']()}
</span>
<Switch
checked={enable}
onChange={onSwitchChange}
disabled={forcedCloud}
/>
</div>
<div className={styles.cardDescription}>
{t['com.affine.nameWorkspace.affine-cloud.description']()}
</div>
</div>
<div className={styles.cardDescription}>
{t['com.affine.nameWorkspace.affine-cloud.description']()}
<div className={styles.cloudSvgContainer}>
<CloudSvg />
</div>
</div>
<div className={styles.cloudSvgContainer}>
<CloudSvg />
</div>
{forcedCloud && BUILD_CONFIG.isWeb ? (
<a
className={styles.cloudTips}
href={BUILD_CONFIG.downloadUrl}
target="_blank"
rel="noreferrer"
>
{t['com.affine.nameWorkspace.affine-cloud.web-tips']()}
</a>
) : null}
</div>
{forcedCloud ? (
<a
className={styles.cloudTips}
href={BUILD_CONFIG.downloadUrl}
target="_blank"
rel="noreferrer"
>
{t['com.affine.nameWorkspace.affine-cloud.web-tips']()}
</a>
) : null}
</div>
) : null}
</ConfirmModal>
);
};
@@ -150,10 +164,14 @@ export const CreateWorkspaceDialog = ({
close,
}: DialogComponentProps<GLOBAL_DIALOG_SCHEMA['create-workspace']>) => {
const workspacesService = useService(WorkspacesService);
const serversService = useService(ServersService);
const featureFlagService = useService(FeatureFlagService);
const enableLocalWorkspace = useLiveData(
featureFlagService.flags.enable_local_workspace.$
);
const server = useLiveData(
serverId ? serversService.server$(serverId) : null
);
const [loading, setLoading] = useState(false);
const onConfirmName = useAsyncCallback(
@@ -164,14 +182,22 @@ export const CreateWorkspaceDialog = ({
// this will be the last step for web for now
// fix me later
const { meta, defaultDocId } = await buildShowcaseWorkspace(
workspacesService,
workspaceFlavour,
name
);
close({ metadata: meta, defaultDocId });
setLoading(false);
try {
const { meta, defaultDocId } = await buildShowcaseWorkspace(
workspacesService,
workspaceFlavour,
name
);
close({ metadata: meta, defaultDocId });
} catch (e) {
console.error(e);
notify.error({
title: 'Failed to create workspace',
message: 'please try again later.',
});
} finally {
setLoading(false);
}
},
[loading, workspacesService, close]
);
@@ -186,13 +212,15 @@ export const CreateWorkspaceDialog = ({
);
return (
<NameWorkspaceContent
loading={loading}
open
serverId={serverId}
forcedCloud={forcedCloud || !enableLocalWorkspace}
onOpenChange={onOpenChange}
onConfirmName={onConfirmName}
/>
<FrameworkScope scope={server?.scope}>
<NameWorkspaceContent
loading={loading}
serverId={serverId}
open
forcedCloud={forcedCloud || !enableLocalWorkspace}
onOpenChange={onOpenChange}
onConfirmName={onConfirmName}
/>
</FrameworkScope>
);
};

View File

@@ -2,16 +2,21 @@ import { Loading, Scrollable } from '@affine/component';
import { WorkspaceDetailSkeleton } from '@affine/component/setting-components';
import type { ModalProps } from '@affine/component/ui/modal';
import { Modal } from '@affine/component/ui/modal';
import { AuthService } from '@affine/core/modules/cloud';
import {
AuthService,
DefaultServerService,
ServersService,
} from '@affine/core/modules/cloud';
import type {
DialogComponentProps,
GLOBAL_DIALOG_SCHEMA,
} from '@affine/core/modules/dialogs';
import type { SettingTab } from '@affine/core/modules/dialogs/constant';
import { GlobalContextService } from '@affine/core/modules/global-context';
import type { WorkspaceMetadata } from '@affine/core/modules/workspace';
import { Trans } from '@affine/i18n';
import { ContactWithUsIcon } from '@blocksuite/icons/rc';
import { useLiveData, useService } from '@toeverything/infra';
import { FrameworkScope, useLiveData, useService } from '@toeverything/infra';
import { debounce } from 'lodash-es';
import {
Suspense,
@@ -57,7 +62,21 @@ const SettingModalInner = ({
activeWorkspaceMetadata: initialWorkspaceMetadata,
scrollAnchor: undefined,
});
const loginStatus = useLiveData(useService(AuthService).session.status$);
const globalContextService = useService(GlobalContextService);
const currentServerId = useLiveData(
globalContextService.globalContext.serverId.$
);
console.log(currentServerId);
const serversService = useService(ServersService);
const defaultServerService = useService(DefaultServerService);
const currentServer =
useLiveData(
currentServerId ? serversService.server$(currentServerId) : null
) ?? defaultServerService.server;
const loginStatus = useLiveData(
currentServer.scope.get(AuthService).session.status$
);
const modalContentRef = useRef<HTMLDivElement>(null);
const modalContentWrapperRef = useRef<HTMLDivElement>(null);
@@ -120,7 +139,7 @@ const SettingModalInner = ({
}, [setOpenStarAFFiNEModal]);
return (
<>
<FrameworkScope scope={currentServer.scope}>
<SettingSidebar
activeTab={settingState.activeTab}
onTabChange={onTabChange}
@@ -188,7 +207,7 @@ const SettingModalInner = ({
<Scrollable.Scrollbar />
</Scrollable.Viewport>
</Scrollable.Root>
</>
</FrameworkScope>
);
};

View File

@@ -5,6 +5,7 @@ import {
} from '@affine/component/setting-components';
import { useWorkspace } from '@affine/core/components/hooks/use-workspace';
import { useWorkspaceInfo } from '@affine/core/components/hooks/use-workspace-info';
import { WorkspaceServerService } from '@affine/core/modules/cloud';
import { UNTITLED_WORKSPACE_NAME } from '@affine/env/constant';
import { useI18n } from '@affine/i18n';
import { ArrowRightSmallIcon } from '@blocksuite/icons/rc';
@@ -31,6 +32,7 @@ export const WorkspaceSettingDetail = ({
// useWorkspace hook is a vary heavy operation here, but we need syncing name and avatar changes here,
// we don't have a better way to do this now
const workspace = useWorkspace(workspaceMetadata);
const server = workspace?.scope.get(WorkspaceServerService).server;
const workspaceInfo = useWorkspaceInfo(workspaceMetadata);
@@ -50,53 +52,55 @@ export const WorkspaceSettingDetail = ({
}
return (
<FrameworkScope scope={workspace.scope}>
<SettingHeader
title={t[`Workspace Settings with name`]({
name: workspaceInfo?.name ?? UNTITLED_WORKSPACE_NAME,
})}
subtitle={t['com.affine.settings.workspace.description']()}
/>
<SettingWrapper title={t['Info']()}>
<SettingRow
name={t['Workspace Profile']()}
desc={t['com.affine.settings.workspace.not-owner']()}
spreadCol={false}
>
<ProfilePanel />
<LabelsPanel />
</SettingRow>
</SettingWrapper>
<SettingWrapper title={t['com.affine.brand.affineCloud']()}>
<EnableCloudPanel onCloseSetting={onCloseSetting} />
<WorkspaceQuotaPanel />
<MembersPanel onChangeSettingState={onChangeSettingState} />
</SettingWrapper>
<SharingPanel />
{BUILD_CONFIG.isElectron && (
<SettingWrapper title={t['Storage and Export']()}>
<DesktopExportPanel
workspace={workspace}
workspaceMetadata={workspaceMetadata}
/>
<FrameworkScope scope={server?.scope}>
<FrameworkScope scope={workspace.scope}>
<SettingHeader
title={t[`Workspace Settings with name`]({
name: workspaceInfo?.name ?? UNTITLED_WORKSPACE_NAME,
})}
subtitle={t['com.affine.settings.workspace.description']()}
/>
<SettingWrapper title={t['Info']()}>
<SettingRow
name={t['Workspace Profile']()}
desc={t['com.affine.settings.workspace.not-owner']()}
spreadCol={false}
>
<ProfilePanel />
<LabelsPanel />
</SettingRow>
</SettingWrapper>
)}
<SettingWrapper>
<DeleteLeaveWorkspace onCloseSetting={onCloseSetting} />
<SettingRow
name={
<span style={{ color: 'var(--affine-text-secondary-color)' }}>
{t['com.affine.resetSyncStatus.button']()}
</span>
}
desc={t['com.affine.resetSyncStatus.description']()}
style={{ cursor: 'pointer' }}
onClick={handleResetSyncStatus}
data-testid="reset-sync-status"
>
<ArrowRightSmallIcon />
</SettingRow>
</SettingWrapper>
<SettingWrapper title={t['com.affine.brand.affineCloud']()}>
<EnableCloudPanel onCloseSetting={onCloseSetting} />
<WorkspaceQuotaPanel />
<MembersPanel onChangeSettingState={onChangeSettingState} />
</SettingWrapper>
<SharingPanel />
{BUILD_CONFIG.isElectron && (
<SettingWrapper title={t['Storage and Export']()}>
<DesktopExportPanel
workspace={workspace}
workspaceMetadata={workspaceMetadata}
/>
</SettingWrapper>
)}
<SettingWrapper>
<DeleteLeaveWorkspace onCloseSetting={onCloseSetting} />
<SettingRow
name={
<span style={{ color: 'var(--affine-text-secondary-color)' }}>
{t['com.affine.resetSyncStatus.button']()}
</span>
}
desc={t['com.affine.resetSyncStatus.description']()}
style={{ cursor: 'pointer' }}
onClick={handleResetSyncStatus}
data-testid="reset-sync-status"
>
<ArrowRightSmallIcon />
</SettingRow>
</SettingWrapper>
</FrameworkScope>
</FrameworkScope>
);
};

View File

@@ -1,6 +1,5 @@
import { NotificationCenter } from '@affine/component';
import { DefaultServerService } from '@affine/core/modules/cloud';
import { GlobalContextService } from '@affine/core/modules/global-context';
import { FrameworkScope, useService } from '@toeverything/infra';
import { useEffect, useState } from 'react';
import { Outlet } from 'react-router-dom';
@@ -11,7 +10,6 @@ import { FindInPageModal } from './find-in-page/find-in-page-modal';
export const RootWrapper = () => {
const defaultServerService = useService(DefaultServerService);
const globalContextService = useService(GlobalContextService);
const [isServerReady, setIsServerReady] = useState(false);
useEffect(() => {
@@ -32,15 +30,6 @@ export const RootWrapper = () => {
};
}, [defaultServerService, isServerReady]);
useEffect(() => {
globalContextService.globalContext.serverId.set(
defaultServerService.server.id
);
return () => {
globalContextService.globalContext.serverId.set(null);
};
}, [defaultServerService, globalContextService]);
return (
<FrameworkScope scope={defaultServerService.server.scope}>
<GlobalDialogs />

View File

@@ -222,8 +222,8 @@ export const AFFINE_FLAGS = {
'com.affine.settings.workspace.experimental-features.enable-multiple-cloud-servers.name',
description:
'com.affine.settings.workspace.experimental-features.enable-multiple-cloud-servers.description',
configurable: isDesktopEnvironment,
defaultState: false,
configurable: false,
defaultState: isDesktopEnvironment,
},
enable_mobile_edgeless_editing: {
category: 'affine',

View File

@@ -7,7 +7,7 @@ export class GlobalContext extends Entity {
workspaceId = this.define<string>('workspaceId');
workspaceFlavour = this.define<string>('workspaceFlavour');
serverId = this.define<string>('serverId');
serverId = this.define<string>('serverId', 'affine-cloud');
/**
* is in doc page
@@ -39,12 +39,14 @@ export class GlobalContext extends Entity {
*/
isAllDocs = this.define<boolean>('isAllDocs');
define<T>(key: string) {
this.memento.set(key, null);
const livedata$ = LiveData.from(this.memento.watch<T>(key), null);
define<T>(key: string, defaultValue: T | null = null) {
this.memento.set(key, defaultValue);
const livedata$ = LiveData.from(this.memento.watch<T>(key), defaultValue);
return {
get: () => this.memento.get(key) as T | null,
set: (value: T | null) => this.memento.set(key, value),
set: (value: T | null) => {
this.memento.set(key, value);
},
$: livedata$,
};
}