diff --git a/packages/frontend/core/src/mobile/components/app-tabs/create.tsx b/packages/frontend/core/src/mobile/components/app-tabs/create.tsx
index 6575413637..900bfacdde 100644
--- a/packages/frontend/core/src/mobile/components/app-tabs/create.tsx
+++ b/packages/frontend/core/src/mobile/components/app-tabs/create.tsx
@@ -1,51 +1,29 @@
import { usePageHelper } from '@affine/core/components/blocksuite/block-suite-page-list/utils';
-import { JournalService } from '@affine/core/modules/journal';
-import { WorkbenchService } from '@affine/core/modules/workbench';
import track from '@affine/track';
import { EditIcon } from '@blocksuite/icons/rc';
-import {
- DocsService,
- useLiveData,
- useServices,
- WorkspaceService,
-} from '@toeverything/infra';
+import { useService, WorkspaceService } from '@toeverything/infra';
import { useCallback } from 'react';
-import { tabItem } from './styles.css';
+import type { AppTabCustomFCProps } from './data';
+import { TabItem } from './tab-item';
-export const AppTabCreate = () => {
- const { docsService, workbenchService, workspaceService, journalService } =
- useServices({
- DocsService,
- WorkbenchService,
- WorkspaceService,
- JournalService,
- });
- const workbench = workbenchService.workbench;
+export const AppTabCreate = ({ tab }: AppTabCustomFCProps) => {
+ const workspaceService = useService(WorkspaceService);
const currentWorkspace = workspaceService.workspace;
- const location = useLiveData(workbench.location$);
const pageHelper = usePageHelper(currentWorkspace.docCollection);
- const maybeDocId = location.pathname.split('/')[1].split('?')[0];
- const doc = useLiveData(docsService.list.doc$(maybeDocId));
- const journalDate = useLiveData(journalService.journalDate$(maybeDocId));
- const isActive = !!doc && !journalDate;
-
- const createPage = useCallback(() => {
- if (isActive) return;
- pageHelper.createPage(undefined, true);
- track.$.navigationPanel.$.createDoc();
- }, [isActive, pageHelper]);
+ const createPage = useCallback(
+ (isActive: boolean) => {
+ if (isActive) return;
+ pageHelper.createPage(undefined, true);
+ track.$.navigationPanel.$.createDoc();
+ },
+ [pageHelper]
+ );
return (
-
+
-
+
);
};
diff --git a/packages/frontend/core/src/mobile/components/app-tabs/data.tsx b/packages/frontend/core/src/mobile/components/app-tabs/data.tsx
new file mode 100644
index 0000000000..9260228c62
--- /dev/null
+++ b/packages/frontend/core/src/mobile/components/app-tabs/data.tsx
@@ -0,0 +1,46 @@
+import { AllDocsIcon, MobileHomeIcon } from '@blocksuite/icons/rc';
+import type { Framework } from '@toeverything/infra';
+
+import { AppTabCreate } from './create';
+import { AppTabJournal } from './journal';
+
+interface AppTabBase {
+ key: string;
+ onClick?: (framework: Framework, isActive: boolean) => void;
+}
+export interface AppTabLink extends AppTabBase {
+ Icon: React.FC;
+ to: string;
+ LinkComponent?: React.FC;
+}
+
+export interface AppTabCustom extends AppTabBase {
+ custom: (props: AppTabCustomFCProps) => React.ReactNode;
+}
+
+export type Tab = AppTabLink | AppTabCustom;
+
+export interface AppTabCustomFCProps {
+ tab: Tab;
+}
+
+export const tabs: Tab[] = [
+ {
+ key: 'home',
+ to: '/home',
+ Icon: MobileHomeIcon,
+ },
+ {
+ key: 'all',
+ to: '/all',
+ Icon: AllDocsIcon,
+ },
+ {
+ key: 'journal',
+ custom: AppTabJournal,
+ },
+ {
+ key: 'new',
+ custom: AppTabCreate,
+ },
+];
diff --git a/packages/frontend/core/src/mobile/components/app-tabs/index.tsx b/packages/frontend/core/src/mobile/components/app-tabs/index.tsx
index 55e54dd69b..1a5de84202 100644
--- a/packages/frontend/core/src/mobile/components/app-tabs/index.tsx
+++ b/packages/frontend/core/src/mobile/components/app-tabs/index.tsx
@@ -1,59 +1,14 @@
import { SafeArea } from '@affine/component';
-import {
- WorkbenchLink,
- WorkbenchService,
-} from '@affine/core/modules/workbench';
-import { AllDocsIcon, MobileHomeIcon } from '@blocksuite/icons/rc';
+import { WorkbenchLink } from '@affine/core/modules/workbench';
import { useLiveData, useService } from '@toeverything/infra';
import { assignInlineVars } from '@vanilla-extract/dynamic';
import React from 'react';
import { createPortal } from 'react-dom';
-import type { Location } from 'react-router-dom';
import { VirtualKeyboardService } from '../../modules/virtual-keyboard/services/virtual-keyboard';
-import { AppTabCreate } from './create';
-import { AppTabJournal } from './journal';
+import { type AppTabLink, tabs } from './data';
import * as styles from './styles.css';
-
-interface AppTabBaseProps {
- key: string;
-}
-interface AppTabLinkProps extends AppTabBaseProps {
- Icon: React.FC;
- to: string;
- LinkComponent?: React.FC;
- isActive?: (location: Location) => boolean;
-}
-interface AppTabCustomProps extends AppTabBaseProps {
- node: React.ReactNode;
-}
-
-type Route = AppTabLinkProps | AppTabCustomProps;
-
-const routes: Route[] = [
- {
- key: 'home',
- to: '/home',
- Icon: MobileHomeIcon,
- },
- {
- key: 'all',
- to: '/all',
- Icon: AllDocsIcon,
- isActive: location =>
- location.pathname === '/all' ||
- location.pathname.startsWith('/collection') ||
- location.pathname.startsWith('/tag'),
- },
- {
- key: 'journal',
- node: ,
- },
- {
- key: 'new',
- node: ,
- },
-];
+import { TabItem } from './tab-item';
export const AppTabs = ({ background }: { background?: string }) => {
const virtualKeyboardService = useService(VirtualKeyboardService);
@@ -72,12 +27,14 @@ export const AppTabs = ({ background }: { background?: string }) => {
}}
>
- {routes.map(route => {
- if ('to' in route) {
- return ;
+ {tabs.map(tab => {
+ if ('to' in tab) {
+ return ;
} else {
return (
- {route.node}
+
+ {}
+
);
}
})}
@@ -87,27 +44,19 @@ export const AppTabs = ({ background }: { background?: string }) => {
);
};
-const AppTabLink = ({ route }: { route: AppTabLinkProps }) => {
- const workbench = useService(WorkbenchService).workbench;
- const location = useLiveData(workbench.location$);
+const AppTabLink = ({ route }: { route: AppTabLink }) => {
const Link = route.LinkComponent || WorkbenchLink;
- const isActive = route.isActive
- ? route.isActive(location)
- : location.pathname === route.to;
return (
- -
+
-
+
);
};
diff --git a/packages/frontend/core/src/mobile/components/app-tabs/journal.tsx b/packages/frontend/core/src/mobile/components/app-tabs/journal.tsx
index a85ad2e208..53b731b246 100644
--- a/packages/frontend/core/src/mobile/components/app-tabs/journal.tsx
+++ b/packages/frontend/core/src/mobile/components/app-tabs/journal.tsx
@@ -6,9 +6,10 @@ import { TodayIcon } from '@blocksuite/icons/rc';
import { useLiveData, useService } from '@toeverything/infra';
import { useCallback } from 'react';
-import { tabItem } from './styles.css';
+import type { AppTabCustomFCProps } from './data';
+import { TabItem } from './tab-item';
-export const AppTabJournal = () => {
+export const AppTabJournal = ({ tab }: AppTabCustomFCProps) => {
const workbench = useService(WorkbenchService).workbench;
const location = useLiveData(workbench.location$);
const journalService = useService(JournalService);
@@ -26,14 +27,8 @@ export const AppTabJournal = () => {
const Icon = journalDate ? JournalIcon : TodayIcon;
return (
-
+
-
+
);
};
diff --git a/packages/frontend/core/src/mobile/components/app-tabs/tab-item.tsx b/packages/frontend/core/src/mobile/components/app-tabs/tab-item.tsx
new file mode 100644
index 0000000000..f5194ddd2a
--- /dev/null
+++ b/packages/frontend/core/src/mobile/components/app-tabs/tab-item.tsx
@@ -0,0 +1,44 @@
+import {
+ GlobalCacheService,
+ LiveData,
+ useLiveData,
+ useService,
+} from '@toeverything/infra';
+import { type PropsWithChildren, useCallback, useMemo } from 'react';
+
+import { tabItem } from './styles.css';
+
+export interface TabItemProps extends PropsWithChildren {
+ id: string;
+ label: string;
+ onClick?: (isActive: boolean) => void;
+}
+
+const cacheKey = 'activeAppTabId';
+export const TabItem = ({ id, label, children, onClick }: TabItemProps) => {
+ const globalCache = useService(GlobalCacheService).globalCache;
+ const activeTabId$ = useMemo(
+ () => LiveData.from(globalCache.watch(cacheKey), 'home'),
+ [globalCache]
+ );
+ const activeTabId = useLiveData(activeTabId$) ?? 'home';
+
+ const isActive = id === activeTabId;
+
+ const handleClick = useCallback(() => {
+ globalCache.set(cacheKey, id);
+ onClick?.(isActive);
+ }, [globalCache, id, isActive, onClick]);
+
+ return (
+ -
+ {children}
+
+ );
+};