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$,
};
}

View File

@@ -848,7 +848,6 @@
"com.affine.payment.billing-type-form.title": "Tell us your use case",
"com.affine.payment.blob-limit.description.local": "The maximum file upload size for local workspaces is {{quota}}.",
"com.affine.payment.blob-limit.description.member": "The maximum file upload size for this joined workspace is {{quota}}. You can contact the owner of this workspace.",
"com.affine.payment.blob-limit.description.owner": "The maximum file upload size for this workspace is {{quota}}. To proceed, you can:",
"com.affine.payment.blob-limit.description.owner.tips-1": "Upgrade your account for larger file upload limits",
"com.affine.payment.blob-limit.description.owner.tips-2": "Upgrade the workspace plan to increase storage for all member",
@@ -1617,5 +1616,6 @@
"com.affine.payment.sync-paused.member.both.description": "This workspace has exceeded both storage and member limits, causing synchronization to pause. Please contact your workspace owner to address these limits and resume syncing.",
"com.affine.payment.sync-paused.member.storage.description": "This workspace has exceeded its storage limit and synchronization has been paused. Please contact your workspace owner to either reduce storage usage or upgrade the plan to resume syncing.",
"com.affine.payment.sync-paused.member.member.description": "This workspace has reached its maximum member capacity and synchronization has been paused. Please contact your workspace owner to either adjust team membership or upgrade the plan to resume syncing.",
"com.affine.payment.sync-paused.member.member.confirm": "Got It"
"com.affine.payment.sync-paused.member.member.confirm": "Got It",
"com.affine.server.delete": "Delete Server"
}