diff --git a/packages/frontend/core/src/components/workspace-selector/user-with-workspace-list/index.tsx b/packages/frontend/core/src/components/workspace-selector/user-with-workspace-list/index.tsx index 22accb5c84..0089be0e38 100644 --- a/packages/frontend/core/src/components/workspace-selector/user-with-workspace-list/index.tsx +++ b/packages/frontend/core/src/components/workspace-selector/user-with-workspace-list/index.tsx @@ -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 (
- {workspaces.length > 0 ? : null} - Delete Server + {t['com.affine.server.delete']()} ), accountStatus === 'authenticated' && ( - Sign Out + {t['com.affine.sign.out']()} ), accountStatus === 'unauthenticated' && ( - Sign In + {t['com.affine.sign.in']()} ), ]} @@ -206,6 +206,7 @@ const LocalWorkspaces = ({ onSettingClick={onClickWorkspaceSetting} onEnableCloudClick={onClickEnableCloud} /> +
); }; diff --git a/packages/frontend/core/src/desktop/dialogs/create-workspace/index.tsx b/packages/frontend/core/src/desktop/dialogs/create-workspace/index.tsx index 17b08cebc1..2aba7fdf03 100644 --- a/packages/frontend/core/src/desktop/dialogs/create-workspace/index.tsx +++ b/packages/frontend/core/src/desktop/dialogs/create-workspace/index.tsx @@ -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" /> -
-
{t['AFFiNE Cloud']()}
-
-
-
- {t['com.affine.nameWorkspace.affine-cloud.title']()} - + {!serverId || serverId === 'affine-cloud' ? ( +
+
{t['AFFiNE Cloud']()}
+
+
+
+ + {t['com.affine.nameWorkspace.affine-cloud.title']()} + + +
+
+ {t['com.affine.nameWorkspace.affine-cloud.description']()} +
-
- {t['com.affine.nameWorkspace.affine-cloud.description']()} +
+
-
- -
+ {forcedCloud && BUILD_CONFIG.isWeb ? ( + + {t['com.affine.nameWorkspace.affine-cloud.web-tips']()} + + ) : null}
- {forcedCloud ? ( - - {t['com.affine.nameWorkspace.affine-cloud.web-tips']()} - - ) : null} -
+ ) : null} ); }; @@ -150,10 +164,14 @@ export const CreateWorkspaceDialog = ({ close, }: DialogComponentProps) => { 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 ( - + + + ); }; diff --git a/packages/frontend/core/src/desktop/dialogs/setting/index.tsx b/packages/frontend/core/src/desktop/dialogs/setting/index.tsx index d1638e9c4e..80a29076c3 100644 --- a/packages/frontend/core/src/desktop/dialogs/setting/index.tsx +++ b/packages/frontend/core/src/desktop/dialogs/setting/index.tsx @@ -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(null); const modalContentWrapperRef = useRef(null); @@ -120,7 +139,7 @@ const SettingModalInner = ({ }, [setOpenStarAFFiNEModal]); return ( - <> + - + ); }; diff --git a/packages/frontend/core/src/desktop/dialogs/setting/workspace-setting/new-workspace-setting-detail/index.tsx b/packages/frontend/core/src/desktop/dialogs/setting/workspace-setting/new-workspace-setting-detail/index.tsx index bebc4677a1..bc897f4ba3 100644 --- a/packages/frontend/core/src/desktop/dialogs/setting/workspace-setting/new-workspace-setting-detail/index.tsx +++ b/packages/frontend/core/src/desktop/dialogs/setting/workspace-setting/new-workspace-setting-detail/index.tsx @@ -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 ( - - - - - - - - - - - - - - - {BUILD_CONFIG.isElectron && ( - - + + + + + + + + - )} - - - - {t['com.affine.resetSyncStatus.button']()} - - } - desc={t['com.affine.resetSyncStatus.description']()} - style={{ cursor: 'pointer' }} - onClick={handleResetSyncStatus} - data-testid="reset-sync-status" - > - - - + + + + + + + {BUILD_CONFIG.isElectron && ( + + + + )} + + + + {t['com.affine.resetSyncStatus.button']()} + + } + desc={t['com.affine.resetSyncStatus.description']()} + style={{ cursor: 'pointer' }} + onClick={handleResetSyncStatus} + data-testid="reset-sync-status" + > + + + + ); }; diff --git a/packages/frontend/core/src/desktop/pages/root/index.tsx b/packages/frontend/core/src/desktop/pages/root/index.tsx index 0b7aff417d..05004d446c 100644 --- a/packages/frontend/core/src/desktop/pages/root/index.tsx +++ b/packages/frontend/core/src/desktop/pages/root/index.tsx @@ -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 ( diff --git a/packages/frontend/core/src/modules/feature-flag/constant.ts b/packages/frontend/core/src/modules/feature-flag/constant.ts index b69ac31b12..13119a102e 100644 --- a/packages/frontend/core/src/modules/feature-flag/constant.ts +++ b/packages/frontend/core/src/modules/feature-flag/constant.ts @@ -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', diff --git a/packages/frontend/core/src/modules/global-context/entities/global-context.ts b/packages/frontend/core/src/modules/global-context/entities/global-context.ts index a589a3b789..caf240bda5 100644 --- a/packages/frontend/core/src/modules/global-context/entities/global-context.ts +++ b/packages/frontend/core/src/modules/global-context/entities/global-context.ts @@ -7,7 +7,7 @@ export class GlobalContext extends Entity { workspaceId = this.define('workspaceId'); workspaceFlavour = this.define('workspaceFlavour'); - serverId = this.define('serverId'); + serverId = this.define('serverId', 'affine-cloud'); /** * is in doc page @@ -39,12 +39,14 @@ export class GlobalContext extends Entity { */ isAllDocs = this.define('isAllDocs'); - define(key: string) { - this.memento.set(key, null); - const livedata$ = LiveData.from(this.memento.watch(key), null); + define(key: string, defaultValue: T | null = null) { + this.memento.set(key, defaultValue); + const livedata$ = LiveData.from(this.memento.watch(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$, }; } diff --git a/packages/frontend/i18n/src/resources/en.json b/packages/frontend/i18n/src/resources/en.json index 51d7aa9512..55f9df4379 100644 --- a/packages/frontend/i18n/src/resources/en.json +++ b/packages/frontend/i18n/src/resources/en.json @@ -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" }