From b1896746f9f4bd37fc767caefa427661f03b5c5c Mon Sep 17 00:00:00 2001 From: pengx17 Date: Wed, 15 Jan 2025 13:00:06 +0000 Subject: [PATCH] refactor(core): move setting dialog to workspace scope (#9706) --- .../apps/electron-renderer/src/app.tsx | 4 +- .../core/src/commands/affine-help.tsx | 8 +- .../core/src/commands/affine-navigation.tsx | 10 +- .../affine/ai-onboarding/edgeless.dialog.tsx | 8 +- .../affine/ai-onboarding/general.dialog.tsx | 8 +- .../page-history-modal/history-modal.tsx | 8 +- .../quota-reached-modal/cloud-quota-modal.tsx | 8 +- .../share-menu/share-page.tsx | 8 +- .../hooks/use-register-workspace-commands.ts | 13 +- .../src/components/over-capacity/index.tsx | 8 +- .../providers/workspace-side-effects.tsx | 13 +- .../src/components/pure/help-island/index.tsx | 8 +- .../src/components/root-app-sidebar/index.tsx | 11 +- .../components/root-app-sidebar/user-info.tsx | 27 ++- .../core/src/desktop/dialogs/index.tsx | 2 +- .../dialogs/setting/general-setting/index.tsx | 14 +- .../src/desktop/dialogs/setting/index.tsx | 10 +- .../dialogs/setting/setting-sidebar/index.tsx | 223 ++++++------------ .../core/src/desktop/dialogs/setting/types.ts | 8 + .../setting/workspace-setting/index.tsx | 80 +++++-- .../core/src/mobile/dialogs/index.tsx | 2 +- .../core/src/mobile/dialogs/setting/index.tsx | 4 +- .../src/mobile/views/home-header/index.tsx | 8 +- .../core/src/modules/dialogs/constant.ts | 2 +- .../open-in-app/views/open-in-app-page.tsx | 8 +- .../src/modules/quota/views/quota-check.tsx | 8 +- tests/affine-desktop/e2e/basic.spec.ts | 2 +- tests/affine-desktop/e2e/workspace.spec.ts | 2 +- .../e2e/local-first-avatar.spec.ts | 4 +- tests/kit/src/utils/cloud.ts | 2 +- tests/kit/src/utils/properties.ts | 2 +- tests/kit/src/utils/setting.ts | 2 +- 32 files changed, 248 insertions(+), 277 deletions(-) diff --git a/packages/frontend/apps/electron-renderer/src/app.tsx b/packages/frontend/apps/electron-renderer/src/app.tsx index a9d04be2b..83a1a2add 100644 --- a/packages/frontend/apps/electron-renderer/src/app.tsx +++ b/packages/frontend/apps/electron-renderer/src/app.tsx @@ -9,7 +9,7 @@ import { configureDesktopApiModule, DesktopApiService, } from '@affine/core/modules/desktop-api'; -import { GlobalDialogService } from '@affine/core/modules/dialogs'; +import { WorkspaceDialogService } from '@affine/core/modules/dialogs'; import { DocsService } from '@affine/core/modules/doc'; import { configureSpellCheckSettingModule, @@ -124,7 +124,7 @@ window.addEventListener('unload', () => { }); events?.applicationMenu.openAboutPageInSettingModal(() => - frameworkProvider.get(GlobalDialogService).open('setting', { + frameworkProvider.get(WorkspaceDialogService).open('setting', { activeTab: 'about', }) ); diff --git a/packages/frontend/core/src/commands/affine-help.tsx b/packages/frontend/core/src/commands/affine-help.tsx index d0136ca67..812dc0d97 100644 --- a/packages/frontend/core/src/commands/affine-help.tsx +++ b/packages/frontend/core/src/commands/affine-help.tsx @@ -2,18 +2,18 @@ import type { useI18n } from '@affine/i18n'; import { track } from '@affine/track'; import { ContactWithUsIcon, NewIcon } from '@blocksuite/icons/rc'; -import type { GlobalDialogService } from '../modules/dialogs'; +import type { WorkspaceDialogService } from '../modules/dialogs'; import type { UrlService } from '../modules/url'; import { registerAffineCommand } from './registry'; export function registerAffineHelpCommands({ t, urlService, - globalDialogService, + workspaceDialogService, }: { t: ReturnType; urlService: UrlService; - globalDialogService: GlobalDialogService; + workspaceDialogService: WorkspaceDialogService; }) { const unsubs: Array<() => void> = []; unsubs.push( @@ -36,7 +36,7 @@ export function registerAffineHelpCommands({ label: t['com.affine.cmdk.affine.contact-us'](), run() { track.$.cmdk.help.contactUs(); - globalDialogService.open('setting', { + workspaceDialogService.open('setting', { activeTab: 'about', }); }, diff --git a/packages/frontend/core/src/commands/affine-navigation.tsx b/packages/frontend/core/src/commands/affine-navigation.tsx index f96025499..360c50ceb 100644 --- a/packages/frontend/core/src/commands/affine-navigation.tsx +++ b/packages/frontend/core/src/commands/affine-navigation.tsx @@ -6,7 +6,7 @@ import type { createStore } from 'jotai'; import { openWorkspaceListModalAtom } from '../components/atoms'; import type { useNavigateHelper } from '../components/hooks/use-navigate-helper'; -import type { GlobalDialogService } from '../modules/dialogs'; +import type { WorkspaceDialogService } from '../modules/dialogs'; import { registerAffineCommand } from './registry'; export function registerAffineNavigationCommands({ @@ -14,13 +14,13 @@ export function registerAffineNavigationCommands({ store, docCollection, navigationHelper, - globalDialogService, + workspaceDialogService, }: { t: ReturnType; store: ReturnType; navigationHelper: ReturnType; docCollection: Workspace; - globalDialogService: GlobalDialogService; + workspaceDialogService: WorkspaceDialogService; }) { const unsubs: Array<() => void> = []; unsubs.push( @@ -96,7 +96,7 @@ export function registerAffineNavigationCommands({ keyBinding: '$mod+,', run() { track.$.cmdk.settings.openSettings(); - globalDialogService.open('setting', { + workspaceDialogService.open('setting', { activeTab: 'appearance', }); }, @@ -111,7 +111,7 @@ export function registerAffineNavigationCommands({ label: t['com.affine.cmdk.affine.navigation.open-account-settings'](), run() { track.$.cmdk.settings.openSettings({ to: 'account' }); - globalDialogService.open('setting', { + workspaceDialogService.open('setting', { activeTab: 'account', }); }, diff --git a/packages/frontend/core/src/components/affine/ai-onboarding/edgeless.dialog.tsx b/packages/frontend/core/src/components/affine/ai-onboarding/edgeless.dialog.tsx index 522e2c2d4..b91595a81 100644 --- a/packages/frontend/core/src/components/affine/ai-onboarding/edgeless.dialog.tsx +++ b/packages/frontend/core/src/components/affine/ai-onboarding/edgeless.dialog.tsx @@ -1,6 +1,6 @@ import { Button, FlexWrapper, notify } from '@affine/component'; import { SubscriptionService } from '@affine/core/modules/cloud'; -import { GlobalDialogService } from '@affine/core/modules/dialogs'; +import { WorkspaceDialogService } from '@affine/core/modules/dialogs'; import { EditorService } from '@affine/core/modules/editor'; import { useI18n } from '@affine/i18n'; import { track } from '@affine/track'; @@ -50,18 +50,18 @@ export const AIOnboardingEdgeless = () => { const notifyId = useLiveData(edgelessNotifyId$); const generalAIOnboardingOpened = useLiveData(showAIOnboardingGeneral$); const aiSubscription = useLiveData(subscriptionService.subscription.ai$); - const globalDialogService = useService(GlobalDialogService); + const workspaceDialogService = useService(WorkspaceDialogService); const timeoutRef = useRef | null>(null); const mode = useLiveData(editorService.editor.mode$); const goToPricingPlans = useCallback(() => { track.$.aiOnboarding.dialog.viewPlans(); - globalDialogService.open('setting', { + workspaceDialogService.open('setting', { activeTab: 'plans', scrollAnchor: 'aiPricingPlan', }); - }, [globalDialogService]); + }, [workspaceDialogService]); useEffect(() => { if (generalAIOnboardingOpened) return; diff --git a/packages/frontend/core/src/components/affine/ai-onboarding/general.dialog.tsx b/packages/frontend/core/src/components/affine/ai-onboarding/general.dialog.tsx index 1a9f9d02a..2c3f989f2 100644 --- a/packages/frontend/core/src/components/affine/ai-onboarding/general.dialog.tsx +++ b/packages/frontend/core/src/components/affine/ai-onboarding/general.dialog.tsx @@ -1,7 +1,7 @@ import { Button, IconButton, Modal } from '@affine/component'; import { useBlurRoot } from '@affine/core/components/hooks/use-blur-root'; import { AuthService, SubscriptionService } from '@affine/core/modules/cloud'; -import { GlobalDialogService } from '@affine/core/modules/dialogs'; +import { WorkspaceDialogService } from '@affine/core/modules/dialogs'; import { Trans, useI18n } from '@affine/i18n'; import { track } from '@affine/track'; import { ArrowLeftSmallIcon } from '@blocksuite/icons/rc'; @@ -95,7 +95,7 @@ export const AIOnboardingGeneral = () => { const aiSubscription = useLiveData(subscriptionService.subscription.ai$); const [index, setIndex] = useState(0); const list = useMemo(() => getPlayList(t), [t]); - const globalDialogService = useService(GlobalDialogService); + const workspaceDialogService = useService(WorkspaceDialogService); const readyToOpen = isLoggedIn; useBlurRoot(open && readyToOpen); @@ -110,13 +110,13 @@ export const AIOnboardingGeneral = () => { toggleGeneralAIOnboarding(false); }, []); const goToPricingPlans = useCallback(() => { - globalDialogService.open('setting', { + workspaceDialogService.open('setting', { activeTab: 'plans', scrollAnchor: 'aiPricingPlan', }); track.$.aiOnboarding.dialog.viewPlans(); closeAndDismiss(); - }, [closeAndDismiss, globalDialogService]); + }, [closeAndDismiss, workspaceDialogService]); const onPrev = useCallback(() => { setIndex(i => Math.max(0, i - 1)); }, []); diff --git a/packages/frontend/core/src/components/affine/page-history-modal/history-modal.tsx b/packages/frontend/core/src/components/affine/page-history-modal/history-modal.tsx index 75a953669..1b3aac64c 100644 --- a/packages/frontend/core/src/components/affine/page-history-modal/history-modal.tsx +++ b/packages/frontend/core/src/components/affine/page-history-modal/history-modal.tsx @@ -2,7 +2,7 @@ import { Loading, Scrollable } from '@affine/component'; import { EditorLoading } from '@affine/component/page-detail-skeleton'; import { Button, IconButton } from '@affine/component/ui/button'; import { Modal, useConfirmModal } from '@affine/component/ui/modal'; -import { GlobalDialogService } from '@affine/core/modules/dialogs'; +import { WorkspaceDialogService } from '@affine/core/modules/dialogs'; import { DocDisplayMetaService } from '@affine/core/modules/doc-display-meta'; import { EditorService } from '@affine/core/modules/editor'; import { WorkspacePermissionService } from '@affine/core/modules/permissions'; @@ -187,18 +187,18 @@ const PlanPrompt = () => { }, [permissionService]); const [planPromptClosed, setPlanPromptClosed] = useAtom(planPromptClosedAtom); - const globalDialogService = useService(GlobalDialogService); + const workspaceDialogService = useService(WorkspaceDialogService); const closeFreePlanPrompt = useCallback(() => { setPlanPromptClosed(true); }, [setPlanPromptClosed]); const onClickUpgrade = useCallback(() => { - globalDialogService.open('setting', { + workspaceDialogService.open('setting', { activeTab: 'plans', scrollAnchor: 'cloudPricingPlan', }); track.$.docHistory.$.viewPlans(); - }, [globalDialogService]); + }, [workspaceDialogService]); const t = useI18n(); diff --git a/packages/frontend/core/src/components/affine/quota-reached-modal/cloud-quota-modal.tsx b/packages/frontend/core/src/components/affine/quota-reached-modal/cloud-quota-modal.tsx index 232eaed07..52775be33 100644 --- a/packages/frontend/core/src/components/affine/quota-reached-modal/cloud-quota-modal.tsx +++ b/packages/frontend/core/src/components/affine/quota-reached-modal/cloud-quota-modal.tsx @@ -1,7 +1,7 @@ import { ConfirmModal } from '@affine/component/ui/modal'; import { openQuotaModalAtom } from '@affine/core/components/atoms'; import { UserQuotaService } from '@affine/core/modules/cloud'; -import { GlobalDialogService } from '@affine/core/modules/dialogs'; +import { WorkspaceDialogService } from '@affine/core/modules/dialogs'; import { WorkspacePermissionService } from '@affine/core/modules/permissions'; import { WorkspaceQuotaService } from '@affine/core/modules/quota'; import { WorkspaceService } from '@affine/core/modules/workspace'; @@ -42,16 +42,16 @@ export const CloudQuotaModal = () => { ) ); - const globalDialogService = useService(GlobalDialogService); + const workspaceDialogService = useService(WorkspaceDialogService); const handleUpgradeConfirm = useCallback(() => { - globalDialogService.open('setting', { + workspaceDialogService.open('setting', { activeTab: 'plans', scrollAnchor: 'cloudPricingPlan', }); track.$.paywall.storage.viewPlans(); setOpen(false); - }, [globalDialogService, setOpen]); + }, [workspaceDialogService, setOpen]); const description = useMemo(() => { if (userQuota && isOwner) { diff --git a/packages/frontend/core/src/components/affine/share-page-modal/share-menu/share-page.tsx b/packages/frontend/core/src/components/affine/share-page-modal/share-menu/share-page.tsx index d1467ff7f..44d9acfde 100644 --- a/packages/frontend/core/src/components/affine/share-page-modal/share-menu/share-page.tsx +++ b/packages/frontend/core/src/components/affine/share-page-modal/share-menu/share-page.tsx @@ -7,7 +7,7 @@ import { } from '@affine/core/components/hooks/affine/use-share-url'; import { useAsyncCallback } from '@affine/core/components/hooks/affine-async-hooks'; import { ServerService } from '@affine/core/modules/cloud'; -import { GlobalDialogService } from '@affine/core/modules/dialogs'; +import { WorkspaceDialogService } from '@affine/core/modules/dialogs'; import { EditorService } from '@affine/core/modules/editor'; import { WorkspacePermissionService } from '@affine/core/modules/permissions'; import { ShareInfoService } from '@affine/core/modules/share-doc'; @@ -81,13 +81,13 @@ export const AFFiNESharePage = (props: ShareMenuProps) => { const permissionService = useService(WorkspacePermissionService); const isOwner = useLiveData(permissionService.permission.isOwner$); - const globalDialogService = useService(GlobalDialogService); + const workspaceDialogService = useService(WorkspaceDialogService); const onOpenWorkspaceSettings = useCallback(() => { - globalDialogService.open('setting', { + workspaceDialogService.open('setting', { activeTab: 'workspace:preference', }); - }, [globalDialogService]); + }, [workspaceDialogService]); const onClickAnyoneReadOnlyShare = useAsyncCallback(async () => { if (isSharedPage) { diff --git a/packages/frontend/core/src/components/hooks/use-register-workspace-commands.ts b/packages/frontend/core/src/components/hooks/use-register-workspace-commands.ts index c8082ba8c..86643b690 100644 --- a/packages/frontend/core/src/components/hooks/use-register-workspace-commands.ts +++ b/packages/frontend/core/src/components/hooks/use-register-workspace-commands.ts @@ -1,6 +1,9 @@ import { AppSidebarService } from '@affine/core/modules/app-sidebar'; import { DesktopApiService } from '@affine/core/modules/desktop-api'; -import { GlobalDialogService } from '@affine/core/modules/dialogs'; +import { + GlobalDialogService, + WorkspaceDialogService, +} from '@affine/core/modules/dialogs'; import { I18nService } from '@affine/core/modules/i18n'; import { UrlService } from '@affine/core/modules/url'; import { WorkspaceService } from '@affine/core/modules/workspace'; @@ -76,6 +79,7 @@ export function useRegisterWorkspaceCommands() { const [editor] = useActiveBlocksuiteEditor(); const cmdkQuickSearchService = useService(CMDKQuickSearchService); const editorSettingService = useService(EditorSettingService); + const workspaceDialogService = useService(WorkspaceDialogService); const globalDialogService = useService(GlobalDialogService); const appSidebarService = useService(AppSidebarService); const i18n = useService(I18nService).i18n; @@ -115,7 +119,7 @@ export function useRegisterWorkspaceCommands() { t, docCollection: currentWorkspace.docCollection, navigationHelper, - globalDialogService, + workspaceDialogService, }); return () => { @@ -127,6 +131,7 @@ export function useRegisterWorkspaceCommands() { currentWorkspace.docCollection, navigationHelper, globalDialogService, + workspaceDialogService, ]); // register AffineSettingsCommands @@ -182,11 +187,11 @@ export function useRegisterWorkspaceCommands() { const unsub = registerAffineHelpCommands({ t, urlService, - globalDialogService, + workspaceDialogService, }); return () => { unsub(); }; - }, [t, globalDialogService, urlService]); + }, [t, globalDialogService, urlService, workspaceDialogService]); } diff --git a/packages/frontend/core/src/components/over-capacity/index.tsx b/packages/frontend/core/src/components/over-capacity/index.tsx index 09c96a8e1..faa8f237a 100644 --- a/packages/frontend/core/src/components/over-capacity/index.tsx +++ b/packages/frontend/core/src/components/over-capacity/index.tsx @@ -1,5 +1,5 @@ import { notify } from '@affine/component'; -import { GlobalDialogService } from '@affine/core/modules/dialogs'; +import { WorkspaceDialogService } from '@affine/core/modules/dialogs'; import { WorkspacePermissionService } from '@affine/core/modules/permissions'; import { WorkspaceService } from '@affine/core/modules/workspace'; import { useI18n } from '@affine/i18n'; @@ -20,13 +20,13 @@ export const OverCapacityNotification = () => { permissionService.permission.revalidate(); }, [permissionService]); - const globalDialogService = useService(GlobalDialogService); + const workspaceDialogService = useService(WorkspaceDialogService); const jumpToPricePlan = useCallback(() => { - globalDialogService.open('setting', { + workspaceDialogService.open('setting', { activeTab: 'plans', scrollAnchor: 'cloudPricingPlan', }); - }, [globalDialogService]); + }, [workspaceDialogService]); // debounce sync engine status useEffect(() => { diff --git a/packages/frontend/core/src/components/providers/workspace-side-effects.tsx b/packages/frontend/core/src/components/providers/workspace-side-effects.tsx index e6bb3b840..59e69c9cb 100644 --- a/packages/frontend/core/src/components/providers/workspace-side-effects.tsx +++ b/packages/frontend/core/src/components/providers/workspace-side-effects.tsx @@ -14,7 +14,10 @@ import { FetchService, GraphQLService, } from '@affine/core/modules/cloud'; -import { GlobalDialogService } from '@affine/core/modules/dialogs'; +import { + GlobalDialogService, + WorkspaceDialogService, +} from '@affine/core/modules/dialogs'; import { DocsService } from '@affine/core/modules/doc'; import { EditorSettingService } from '@affine/core/modules/editor-setting'; import { useRegisterNavigationCommands } from '@affine/core/modules/navigation/view/use-register-navigation-commands'; @@ -123,11 +126,12 @@ export const WorkspaceSideEffects = () => { workbench, ]); + const workspaceDialogService = useService(WorkspaceDialogService); const globalDialogService = useService(GlobalDialogService); useEffect(() => { const disposable = AIProvider.slots.requestUpgradePlan.on(() => { - globalDialogService.open('setting', { + workspaceDialogService.open('setting', { activeTab: 'billing', }); track.$.paywall.aiAction.viewPlans(); @@ -135,7 +139,7 @@ export const WorkspaceSideEffects = () => { return () => { disposable.dispose(); }; - }, [globalDialogService]); + }, [workspaceDialogService]); const graphqlService = useService(GraphQLService); const eventSourceService = useService(EventSourceService); @@ -158,9 +162,10 @@ export const WorkspaceSideEffects = () => { }, [ eventSourceService, fetchService, - globalDialogService, + workspaceDialogService, graphqlService, networkSearchService, + globalDialogService, ]); useRegisterWorkspaceCommands(); diff --git a/packages/frontend/core/src/components/pure/help-island/index.tsx b/packages/frontend/core/src/components/pure/help-island/index.tsx index a7e801121..6d1c68157 100644 --- a/packages/frontend/core/src/components/pure/help-island/index.tsx +++ b/packages/frontend/core/src/components/pure/help-island/index.tsx @@ -1,5 +1,5 @@ import { Tooltip } from '@affine/component/ui/tooltip'; -import { GlobalDialogService } from '@affine/core/modules/dialogs'; +import { WorkspaceDialogService } from '@affine/core/modules/dialogs'; import type { SettingTab } from '@affine/core/modules/dialogs/constant'; import { GlobalContextService } from '@affine/core/modules/global-context'; import { UrlService } from '@affine/core/modules/url'; @@ -36,18 +36,18 @@ export const HelpIsland = () => { }); const docId = useLiveData(globalContextService.globalContext.docId.$); const docMode = useLiveData(globalContextService.globalContext.docMode.$); - const globalDialogService = useService(GlobalDialogService); + const workspaceDialogService = useService(WorkspaceDialogService); const [spread, setShowSpread] = useState(false); const t = useI18n(); const openSettingModal = useCallback( (tab: SettingTab) => { setShowSpread(false); - globalDialogService.open('setting', { + workspaceDialogService.open('setting', { activeTab: tab, }); }, - [globalDialogService] + [workspaceDialogService] ); const openAbout = useCallback( () => openSettingModal('about'), diff --git a/packages/frontend/core/src/components/root-app-sidebar/index.tsx b/packages/frontend/core/src/components/root-app-sidebar/index.tsx index 458320f7d..8cc9e38a0 100644 --- a/packages/frontend/core/src/components/root-app-sidebar/index.tsx +++ b/packages/frontend/core/src/components/root-app-sidebar/index.tsx @@ -1,3 +1,4 @@ +// Import is already correct, no changes needed import { AddPageButton, AppDownloadButton, @@ -10,10 +11,7 @@ import { SidebarScrollableContainer, } from '@affine/core/modules/app-sidebar/views'; import { ExternalMenuLinkItem } from '@affine/core/modules/app-sidebar/views/menu-item/external-menu-link-item'; -import { - GlobalDialogService, - WorkspaceDialogService, -} from '@affine/core/modules/dialogs'; +import { WorkspaceDialogService } from '@affine/core/modules/dialogs'; import { ExplorerCollections, ExplorerFavorites, @@ -95,7 +93,6 @@ export const RootAppSidebar = memo((): ReactElement => { CMDKQuickSearchService, }); const t = useI18n(); - const globalDialogService = useService(GlobalDialogService); const workspaceDialogService = useService(WorkspaceDialogService); const workbench = workbenchService.workbench; const onOpenQuickSearchModal = useCallback(() => { @@ -103,11 +100,11 @@ export const RootAppSidebar = memo((): ReactElement => { }, [cMDKQuickSearchService]); const onOpenSettingModal = useCallback(() => { - globalDialogService.open('setting', { + workspaceDialogService.open('setting', { activeTab: 'appearance', }); track.$.navigationPanel.$.openSettings(); - }, [globalDialogService]); + }, [workspaceDialogService]); const handleOpenDocs = useCallback( (result: { diff --git a/packages/frontend/core/src/components/root-app-sidebar/user-info.tsx b/packages/frontend/core/src/components/root-app-sidebar/user-info.tsx index bd3672f25..36190de6a 100644 --- a/packages/frontend/core/src/components/root-app-sidebar/user-info.tsx +++ b/packages/frontend/core/src/components/root-app-sidebar/user-info.tsx @@ -8,7 +8,10 @@ import { type MenuProps, Skeleton, } from '@affine/component'; -import { GlobalDialogService } from '@affine/core/modules/dialogs'; +import { + GlobalDialogService, + WorkspaceDialogService, +} from '@affine/core/modules/dialogs'; import { useI18n } from '@affine/i18n'; import { track } from '@affine/track'; import { AccountIcon, SignOutIcon } from '@blocksuite/icons/rc'; @@ -75,15 +78,15 @@ const UnauthorizedUserInfo = () => { }; const AccountMenu = () => { - const globalDialogService = useService(GlobalDialogService); + const workspaceDialogService = useService(WorkspaceDialogService); const openSignOutModal = useSignOut(); const onOpenAccountSetting = useCallback(() => { track.$.navigationPanel.profileAndBadge.openSettings({ to: 'account' }); - globalDialogService.open('setting', { + workspaceDialogService.open('setting', { activeTab: 'account', }); - }, [globalDialogService]); + }, [workspaceDialogService]); const t = useI18n(); @@ -112,13 +115,13 @@ const CloudUsage = () => { const quota = useService(UserQuotaService).quota; const quotaError = useLiveData(quota.error$); - const globalDialogService = useService(GlobalDialogService); + const workspaceDialogService = useService(WorkspaceDialogService); const handleClick = useCatchEventCallback(() => { - globalDialogService.open('setting', { + workspaceDialogService.open('setting', { activeTab: 'plans', scrollAnchor: 'cloudPricingPlan', }); - }, [globalDialogService]); + }, [workspaceDialogService]); useEffect(() => { // revalidate quota to get the latest status @@ -192,20 +195,20 @@ const AIUsage = () => { const loading = copilotActionLimit === null || copilotActionUsed === null; const loadError = useLiveData(copilotQuotaService.copilotQuota.error$); - const globalDialogService = useService(GlobalDialogService); + const workspaceDialogService = useService(WorkspaceDialogService); const goToAIPlanPage = useCallback(() => { - globalDialogService.open('setting', { + workspaceDialogService.open('setting', { activeTab: 'plans', scrollAnchor: 'aiPricingPlan', }); - }, [globalDialogService]); + }, [workspaceDialogService]); const goToAccountSetting = useCallback(() => { - globalDialogService.open('setting', { + workspaceDialogService.open('setting', { activeTab: 'account', }); - }, [globalDialogService]); + }, [workspaceDialogService]); if (loading) { if (loadError) console.error(loadError); diff --git a/packages/frontend/core/src/desktop/dialogs/index.tsx b/packages/frontend/core/src/desktop/dialogs/index.tsx index 0ec8b3565..07e1c1570 100644 --- a/packages/frontend/core/src/desktop/dialogs/index.tsx +++ b/packages/frontend/core/src/desktop/dialogs/index.tsx @@ -27,7 +27,6 @@ const GLOBAL_DIALOGS = { 'create-workspace': CreateWorkspaceDialog, 'import-workspace': ImportWorkspaceDialog, 'import-template': ImportTemplateDialog, - setting: SettingDialog, 'sign-in': SignInDialog, 'change-password': ChangePasswordDialog, 'verify-email': VerifyEmailDialog, @@ -45,6 +44,7 @@ const WORKSPACE_DIALOGS = { 'doc-selector': DocSelectorDialog, 'collection-selector': CollectionSelectorDialog, 'date-selector': DateSelectorDialog, + setting: SettingDialog, import: ImportDialog, } satisfies { [key in keyof WORKSPACE_DIALOG_SCHEMA]?: React.FC< diff --git a/packages/frontend/core/src/desktop/dialogs/setting/general-setting/index.tsx b/packages/frontend/core/src/desktop/dialogs/setting/general-setting/index.tsx index ee8a83c1b..f963fd35f 100644 --- a/packages/frontend/core/src/desktop/dialogs/setting/general-setting/index.tsx +++ b/packages/frontend/core/src/desktop/dialogs/setting/general-setting/index.tsx @@ -10,11 +10,10 @@ import { PenIcon, } from '@blocksuite/icons/rc'; import { useLiveData, useServices } from '@toeverything/infra'; -import type { ReactNode } from 'react'; import { useEffect } from 'react'; import { AuthService, ServerService } from '../../../../modules/cloud'; -import type { SettingState } from '../types'; +import type { SettingSidebarItem, SettingState } from '../types'; import { AboutAffine } from './about'; import { AppearanceSettings } from './appearance'; import { BillingSettings } from './billing'; @@ -24,14 +23,7 @@ import { PaymentIcon, UpgradeIcon } from './icons'; import { AFFiNEPricingPlans } from './plans'; import { Shortcuts } from './shortcuts'; -interface GeneralSettingListItem { - key: SettingTab; - title: string; - icon: ReactNode; - testId: string; -} - -export type GeneralSettingList = GeneralSettingListItem[]; +export type GeneralSettingList = SettingSidebarItem[]; export const useGeneralSettingList = (): GeneralSettingList => { const t = useI18n(); @@ -54,7 +46,7 @@ export const useGeneralSettingList = (): GeneralSettingList => { userFeatureService.userFeature.revalidate(); }, [userFeatureService]); - const settings: GeneralSettingListItem[] = [ + const settings: GeneralSettingList = [ { key: 'appearance', title: t['com.affine.settings.appearance'](), diff --git a/packages/frontend/core/src/desktop/dialogs/setting/index.tsx b/packages/frontend/core/src/desktop/dialogs/setting/index.tsx index 6545a5216..131cd2700 100644 --- a/packages/frontend/core/src/desktop/dialogs/setting/index.tsx +++ b/packages/frontend/core/src/desktop/dialogs/setting/index.tsx @@ -7,11 +7,11 @@ import { DefaultServerService, ServersService, } from '@affine/core/modules/cloud'; +import type { DialogComponentProps } from '@affine/core/modules/dialogs'; import type { - DialogComponentProps, - GLOBAL_DIALOG_SCHEMA, -} from '@affine/core/modules/dialogs'; -import type { SettingTab } from '@affine/core/modules/dialogs/constant'; + SettingTab, + WORKSPACE_DIALOG_SCHEMA, +} from '@affine/core/modules/dialogs/constant'; import { GlobalContextService } from '@affine/core/modules/global-context'; import { Trans } from '@affine/i18n'; import { ContactWithUsIcon } from '@blocksuite/icons/rc'; @@ -207,7 +207,7 @@ const SettingModalInner = ({ export const SettingDialog = ({ close, activeTab, -}: DialogComponentProps) => { +}: DialogComponentProps) => { return ( { ); }; +type SettingSidebarItemProps = { + isActive: boolean; + icon: ReactNode; + title: string; + key: string; + testId?: string; +} & HTMLAttributes; + const SettingSidebarItem = ({ isActive, icon, - label, + title, + testId, ...props -}: { - isActive: boolean; - label: string; - icon: ReactNode; -} & HTMLAttributes) => { +}: SettingSidebarItemProps) => { return (
{icon}
-
{label}
+
{title}
+
+ ); +}; + +const SettingSidebarGroup = ({ + title, + items, +}: { + title: string; + items: SettingSidebarItemProps[]; +}) => { + return ( +
+
{title}
+
+ {items.map(({ key, ...props }) => ( + + ))} +
); }; @@ -152,12 +164,11 @@ export const SettingSidebar = ({ const t = useI18n(); const loginStatus = useLiveData(useService(AuthService).session.status$); const generalList = useGeneralSettingList(); + const workspaceSettingList = useWorkspaceSettingList(); const gotoTab = useCallback( - (e: MouseEvent) => { - const tab = e.currentTarget.dataset.eventArg; - if (!tab) return; + (tab: SettingTab) => { track.$.settingsPanel.menu.openSettings({ to: tab }); - onTabChange(tab as SettingTab); + onTabChange(tab); }, [onTabChange] ); @@ -165,16 +176,34 @@ export const SettingSidebar = ({ track.$.settingsPanel.menu.openSettings({ to: 'account' }); onTabChange('account'); }, [onTabChange]); - const onWorkspaceSettingClick = useCallback( - (tab: SettingTab) => { - track.$.settingsPanel.menu.openSettings({ - to: 'workspace', - control: tab, - }); - onTabChange(tab); - }, - [onTabChange] - ); + + const groups = useMemo(() => { + const res = [ + { + key: 'setting:general', + title: t['com.affine.settingSidebar.settings.general'](), + items: generalList, + }, + { + key: 'setting:workspace', + title: t['com.affine.settingSidebar.settings.workspace'](), + items: workspaceSettingList, + }, + ].map(group => { + return { + ...group, + items: group.items.map(item => { + return { + ...item, + isActive: item.key === activeTab, + 'data-event-arg': item.key, + onClick: () => gotoTab(item.key), + }; + }), + }; + }); + return res; + }, [activeTab, generalList, gotoTab, t, workspaceSettingList]); return (
@@ -193,117 +222,13 @@ export const SettingSidebar = ({ ) : null} -
-
- {t['com.affine.settingSidebar.settings.general']()} -
-
- {generalList.map(({ title, icon, key, testId }) => { - return ( - - ); - })} -
-
- -
-
- {t['com.affine.settingSidebar.settings.workspace']()} -
-
- }> - - - - -
-
-
- ); -}; - -const WorkspaceSettingItems = ({ - onWorkspaceSettingClick, - activeTab, -}: { - onWorkspaceSettingClick: (activeTab: SettingTab) => void; - activeTab: SettingTab; -}) => { - const { userFeatureService } = useServices({ - UserFeatureService, - }); - - const workspaceService = useService(WorkspaceService); - const information = useWorkspaceInfo(workspaceService.workspace); - - const t = useI18n(); - - useEffect(() => { - userFeatureService.userFeature.revalidate(); - }, [userFeatureService]); - - const showBilling = information?.isTeam && information?.isOwner; - const subTabs = useMemo(() => { - const subTabConfigs = [ - { - key: 'workspace:preference', - title: 'com.affine.settings.workspace.preferences', - icon: , - }, - { - key: 'workspace:properties', - title: 'com.affine.settings.workspace.properties', - icon: , - }, - ...(showBilling - ? [ - { - key: 'workspace:billing' as SettingTab, - title: 'com.affine.settings.workspace.billing', - icon: , - }, - ] - : []), - ] satisfies { - key: SettingTab; - title: keyof ReturnType; - icon: ReactNode; - }[]; - - return subTabConfigs.map(({ key, title, icon }) => { - return ( - { - onWorkspaceSettingClick(key); - }} - className={clsx(style.sidebarSelectItem, { - active: activeTab === key, - })} - key={key} + {groups.map(group => ( + - ); - }); - }, [activeTab, onWorkspaceSettingClick, showBilling, t]); - - return ( -
- {/* TODO: remove the suspense? */} - }>{subTabs} + ))}
); }; diff --git a/packages/frontend/core/src/desktop/dialogs/setting/types.ts b/packages/frontend/core/src/desktop/dialogs/setting/types.ts index 41d352760..38f60d6cb 100644 --- a/packages/frontend/core/src/desktop/dialogs/setting/types.ts +++ b/packages/frontend/core/src/desktop/dialogs/setting/types.ts @@ -1,6 +1,14 @@ import type { SettingTab } from '@affine/core/modules/dialogs/constant'; +import type { ReactNode } from 'react'; export interface SettingState { activeTab: SettingTab; scrollAnchor?: string; } + +export interface SettingSidebarItem { + key: SettingTab; + title: string; + icon: ReactNode; + testId: string; +} diff --git a/packages/frontend/core/src/desktop/dialogs/setting/workspace-setting/index.tsx b/packages/frontend/core/src/desktop/dialogs/setting/workspace-setting/index.tsx index b0cd5a358..747f30e40 100644 --- a/packages/frontend/core/src/desktop/dialogs/setting/workspace-setting/index.tsx +++ b/packages/frontend/core/src/desktop/dialogs/setting/workspace-setting/index.tsx @@ -1,8 +1,12 @@ -import { CurrentWorkspaceScopeProvider } from '@affine/core/components/providers/current-workspace-scope'; +import { useWorkspaceInfo } from '@affine/core/components/hooks/use-workspace-info'; import type { SettingTab } from '@affine/core/modules/dialogs/constant'; +import { WorkspaceService } from '@affine/core/modules/workspace'; +import { useI18n } from '@affine/i18n'; +import { PaymentIcon, PropertyIcon, SettingsIcon } from '@blocksuite/icons/rc'; +import { useService } from '@toeverything/infra'; import { useMemo } from 'react'; -import type { SettingState } from '../types'; +import type { SettingSidebarItem, SettingState } from '../types'; import { WorkspaceSettingBilling } from './billing'; import { WorkspaceSettingDetail } from './new-workspace-setting-detail'; import { WorkspaceSettingProperties } from './properties'; @@ -16,24 +20,56 @@ export const WorkspaceSetting = ({ onCloseSetting: () => void; onChangeSettingState: (settingState: SettingState) => void; }) => { - const element = useMemo(() => { - switch (activeTab) { - case 'workspace:preference': - return ( - - ); - case 'workspace:properties': - return ; - case 'workspace:billing': - return ; - default: - return null; - } - }, [activeTab, onCloseSetting, onChangeSettingState]); - return ( - {element} - ); + switch (activeTab) { + case 'workspace:preference': + return ( + + ); + case 'workspace:properties': + return ; + case 'workspace:billing': + return ; + default: + return null; + } +}; + +export const useWorkspaceSettingList = (): SettingSidebarItem[] => { + const workspaceService = useService(WorkspaceService); + const information = useWorkspaceInfo(workspaceService.workspace); + + const t = useI18n(); + + const showBilling = information?.isTeam && information?.isOwner; + const items = useMemo(() => { + return [ + { + key: 'workspace:preference', + title: t['com.affine.settings.workspace.preferences'](), + icon: , + testId: 'workspace-setting:preference', + }, + { + key: 'workspace:properties', + title: t['com.affine.settings.workspace.properties'](), + icon: , + testId: 'workspace-setting:properties', + }, + ...(showBilling + ? [ + { + key: 'workspace:billing' as SettingTab, + title: t['com.affine.settings.workspace.billing'](), + icon: , + testId: 'workspace-setting:billing', + }, + ] + : []), + ]; + }, [showBilling, t]); + + return items; }; diff --git a/packages/frontend/core/src/mobile/dialogs/index.tsx b/packages/frontend/core/src/mobile/dialogs/index.tsx index 698b65d9f..e31db41e3 100644 --- a/packages/frontend/core/src/mobile/dialogs/index.tsx +++ b/packages/frontend/core/src/mobile/dialogs/index.tsx @@ -18,7 +18,6 @@ const GLOBAL_DIALOGS = { // 'create-workspace': CreateWorkspaceDialog, // 'import-workspace': ImportWorkspaceDialog, // 'import-template': ImportTemplateDialog, - setting: SettingDialog, // import: ImportDialog, 'sign-in': SignInDialog, } satisfies { @@ -34,6 +33,7 @@ const WORKSPACE_DIALOGS = { 'doc-selector': DocSelectorDialog, 'collection-selector': CollectionSelectorDialog, 'date-selector': DateSelectorDialog, + setting: SettingDialog, } satisfies { [key in keyof WORKSPACE_DIALOG_SCHEMA]?: React.FC< DialogComponentProps diff --git a/packages/frontend/core/src/mobile/dialogs/setting/index.tsx b/packages/frontend/core/src/mobile/dialogs/setting/index.tsx index 65028036c..410c94571 100644 --- a/packages/frontend/core/src/mobile/dialogs/setting/index.tsx +++ b/packages/frontend/core/src/mobile/dialogs/setting/index.tsx @@ -1,7 +1,7 @@ import { AuthService } from '@affine/core/modules/cloud'; import type { DialogComponentProps, - GLOBAL_DIALOG_SCHEMA, + WORKSPACE_DIALOG_SCHEMA, } from '@affine/core/modules/dialogs'; import { useI18n } from '@affine/i18n'; import { useService } from '@toeverything/infra'; @@ -34,7 +34,7 @@ const MobileSetting = () => { export const SettingDialog = ({ close, -}: DialogComponentProps) => { +}: DialogComponentProps) => { const t = useI18n(); return ( diff --git a/packages/frontend/core/src/mobile/views/home-header/index.tsx b/packages/frontend/core/src/mobile/views/home-header/index.tsx index f526e3d24..20a3065ed 100644 --- a/packages/frontend/core/src/mobile/views/home-header/index.tsx +++ b/packages/frontend/core/src/mobile/views/home-header/index.tsx @@ -3,7 +3,7 @@ import { SafeArea, startScopedViewTransition, } from '@affine/component'; -import { GlobalDialogService } from '@affine/core/modules/dialogs'; +import { WorkspaceDialogService } from '@affine/core/modules/dialogs'; import { WorkbenchService } from '@affine/core/modules/workbench'; import { useI18n } from '@affine/i18n'; import { SettingsIcon } from '@blocksuite/icons/rc'; @@ -23,7 +23,7 @@ import * as styles from './styles.css'; * - hide Search */ export const HomeHeader = () => { - const globalDialogService = useService(GlobalDialogService); + const workspaceDialogService = useService(WorkspaceDialogService); const workspaceCardRef = useRef(null); const floatWorkspaceCardRef = useRef(null); @@ -50,10 +50,10 @@ export const HomeHeader = () => { ); const openSetting = useCallback(() => { - globalDialogService.open('setting', { + workspaceDialogService.open('setting', { activeTab: 'appearance', }); - }, [globalDialogService]); + }, [workspaceDialogService]); return ( <> diff --git a/packages/frontend/core/src/modules/dialogs/constant.ts b/packages/frontend/core/src/modules/dialogs/constant.ts index caa3365e5..56cf5e6f2 100644 --- a/packages/frontend/core/src/modules/dialogs/constant.ts +++ b/packages/frontend/core/src/modules/dialogs/constant.ts @@ -26,7 +26,6 @@ export type GLOBAL_DIALOG_SCHEMA = { templateMode: DocMode; snapshotUrl: string; }) => void; - setting: (props: { activeTab?: SettingTab; scrollAnchor?: string }) => void; 'sign-in': (props: { server?: string; step?: string }) => void; 'change-password': (props: { server?: string }) => void; 'verify-email': (props: { server?: string; changeEmail?: boolean }) => void; @@ -38,6 +37,7 @@ export type GLOBAL_DIALOG_SCHEMA = { }; export type WORKSPACE_DIALOG_SCHEMA = { + setting: (props: { activeTab?: SettingTab; scrollAnchor?: string }) => void; 'doc-info': (props: { docId: string }) => void; 'doc-selector': (props: { init: string[]; diff --git a/packages/frontend/core/src/modules/open-in-app/views/open-in-app-page.tsx b/packages/frontend/core/src/modules/open-in-app/views/open-in-app-page.tsx index 77b67026b..ac4906de9 100644 --- a/packages/frontend/core/src/modules/open-in-app/views/open-in-app-page.tsx +++ b/packages/frontend/core/src/modules/open-in-app/views/open-in-app-page.tsx @@ -1,4 +1,5 @@ import { Button } from '@affine/component/ui/button'; +import { WorkspaceDialogService } from '@affine/core/modules/dialogs'; import { appIconMap, appNames } from '@affine/core/utils/channel'; import { Trans, useI18n } from '@affine/i18n'; import { LocalWorkspaceIcon, Logo1Icon } from '@blocksuite/icons/rc'; @@ -6,7 +7,6 @@ import { useService } from '@toeverything/infra'; import type { MouseEvent } from 'react'; import { useCallback } from 'react'; -import { GlobalDialogService } from '../../dialogs'; import { getOpenUrlInDesktopAppLink } from '../utils'; import * as styles from './open-in-app-page.css'; @@ -28,7 +28,7 @@ export const OpenInAppPage = ({ }: OpenAppProps) => { // default to open the current page in desktop app urlToOpen ??= getOpenUrlInDesktopAppLink(window.location.href, true); - const globalDialogService = useService(GlobalDialogService); + const workspaceDialogService = useService(WorkspaceDialogService); const t = useI18n(); const openDownloadLink = useCallback(() => { @@ -41,11 +41,11 @@ export const OpenInAppPage = ({ const goToAppearanceSetting = useCallback( (e: MouseEvent) => { openHereClicked?.(e); - globalDialogService.open('setting', { + workspaceDialogService.open('setting', { activeTab: 'appearance', }); }, - [globalDialogService, openHereClicked] + [workspaceDialogService, openHereClicked] ); if (urlToOpen && lastOpened !== urlToOpen) { diff --git a/packages/frontend/core/src/modules/quota/views/quota-check.tsx b/packages/frontend/core/src/modules/quota/views/quota-check.tsx index f80d7d43c..4ae4f26f1 100644 --- a/packages/frontend/core/src/modules/quota/views/quota-check.tsx +++ b/packages/frontend/core/src/modules/quota/views/quota-check.tsx @@ -1,5 +1,5 @@ import { useConfirmModal } from '@affine/component'; -import { GlobalDialogService } from '@affine/core/modules/dialogs'; +import { WorkspaceDialogService } from '@affine/core/modules/dialogs'; import { type I18nString, useI18n } from '@affine/i18n'; import { InformationFillDuotoneIcon } from '@blocksuite/icons/rc'; import { useLiveData, useService } from '@toeverything/infra'; @@ -36,18 +36,18 @@ export const QuotaCheck = ({ const profile = useLiveData(workspaceProfile.profile$); const isOwner = profile?.isOwner; const isTeam = profile?.isTeam; - const globalDialogService = useService(GlobalDialogService); + const workspaceDialogService = useService(WorkspaceDialogService); const t = useI18n(); const onConfirm = useCallback(() => { if (!isOwner) { return; } - globalDialogService.open('setting', { + workspaceDialogService.open('setting', { activeTab: 'plans', scrollAnchor: 'cloudPricingPlan', }); - }, [globalDialogService, isOwner]); + }, [workspaceDialogService, isOwner]); useEffect(() => { workspaceQuota?.revalidate(); diff --git a/tests/affine-desktop/e2e/basic.spec.ts b/tests/affine-desktop/e2e/basic.spec.ts index c0554a99a..9dc3ce816 100644 --- a/tests/affine-desktop/e2e/basic.spec.ts +++ b/tests/affine-desktop/e2e/basic.spec.ts @@ -121,7 +121,7 @@ test('delete workspace', async ({ page }) => { // }); await page.waitForTimeout(1000); await clickSideBarSettingButton(page); - await page.getByTestId('workspace-list-item-workspace:preference').click(); + await page.getByTestId('workspace-setting:preference').click(); await expect(page.getByTestId('workspace-name-input')).toHaveValue( 'Delete Me' ); diff --git a/tests/affine-desktop/e2e/workspace.spec.ts b/tests/affine-desktop/e2e/workspace.spec.ts index 36a8f596a..fee552a76 100644 --- a/tests/affine-desktop/e2e/workspace.spec.ts +++ b/tests/affine-desktop/e2e/workspace.spec.ts @@ -42,7 +42,7 @@ test('export then add', async ({ page, appInfo, workspace }) => { const newWorkspaceName = 'new-test-name'; // goto workspace setting - await page.getByTestId('workspace-list-item-workspace:preference').click(); + await page.getByTestId('workspace-setting:preference').click(); const input = page.getByTestId('workspace-name-input'); await expect(input).toBeVisible(); diff --git a/tests/affine-local/e2e/local-first-avatar.spec.ts b/tests/affine-local/e2e/local-first-avatar.spec.ts index 152355fa1..610785d6d 100644 --- a/tests/affine-local/e2e/local-first-avatar.spec.ts +++ b/tests/affine-local/e2e/local-first-avatar.spec.ts @@ -24,7 +24,7 @@ test('should create a page with a local first avatar and remove it', async ({ .nth(1) .click({ position: { x: 10, y: 10 } }); await page.getByTestId('settings-modal-trigger').click(); - await page.getByTestId('workspace-list-item-workspace:preference').click(); + await page.getByTestId('workspace-setting:preference').click(); await page .getByTestId('upload-avatar') .setInputFiles(ProjectRoot.join('tests', 'fixtures', 'blue.png').value); @@ -61,7 +61,7 @@ test('should create a page with a local first avatar and remove it', async ({ // Click remove button to remove workspace avatar await page.getByTestId('settings-modal-trigger').click(); - await page.getByTestId('workspace-list-item-workspace:preference').click(); + await page.getByTestId('workspace-setting:preference').click(); await page.getByTestId('workspace-setting-avatar').hover(); await page.getByTestId('workspace-setting-remove-avatar-button').click(); await page.mouse.click(0, 0); diff --git a/tests/kit/src/utils/cloud.ts b/tests/kit/src/utils/cloud.ts index 7c7992b9f..fc4bcbbcd 100644 --- a/tests/kit/src/utils/cloud.ts +++ b/tests/kit/src/utils/cloud.ts @@ -282,7 +282,7 @@ export async function loginUserDirectly( export async function enableCloudWorkspace(page: Page) { await clickSideBarSettingButton(page); - await page.getByTestId('workspace-list-item-workspace:preference').click(); + await page.getByTestId('workspace-setting:preference').click(); await page.getByTestId('publish-enable-affine-cloud-button').click(); await page.getByTestId('confirm-enable-affine-cloud-button').click(); // wait for upload and delete local workspace diff --git a/tests/kit/src/utils/properties.ts b/tests/kit/src/utils/properties.ts index f5c76a8ca..6495c385d 100644 --- a/tests/kit/src/utils/properties.ts +++ b/tests/kit/src/utils/properties.ts @@ -149,7 +149,7 @@ export const expectPropertyOrdering = async ( export const openWorkspaceProperties = async (page: Page) => { await page.getByTestId('slider-bar-workspace-setting-button').click(); - await page.getByTestId('workspace-list-item-workspace:properties').click(); + await page.getByTestId('workspace-setting:properties').click(); }; export const selectVisibilitySelector = async ( diff --git a/tests/kit/src/utils/setting.ts b/tests/kit/src/utils/setting.ts index 2fa9301b0..293b20b54 100644 --- a/tests/kit/src/utils/setting.ts +++ b/tests/kit/src/utils/setting.ts @@ -41,7 +41,7 @@ export async function confirmExperimentalPrompt(page: Page) { export async function openWorkspaceSettingPanel(page: Page) { await page .getByTestId('settings-sidebar') - .getByTestId('workspace-list-item-workspace:preference') + .getByTestId('workspace-setting:preference') .click(); }