From 9f129075dde5c1d45808da155ad6a6e828e10972 Mon Sep 17 00:00:00 2001 From: Himself65 Date: Fri, 9 Jun 2023 00:58:46 +0800 Subject: [PATCH] feat: add page setting atom (#2725) --- apps/web/src/atoms/index.ts | 87 +++++++---- .../block-suite-page-list/index.tsx | 4 +- .../block-suite-page-list/utils.tsx | 29 ++-- .../editor-mode-switch/index.tsx | 23 ++- .../header-right-items/editor-option-menu.tsx | 11 +- .../web/src/components/page-detail-editor.tsx | 8 +- .../pure/quick-search-modal/results.tsx | 8 +- .../favorite/favorite-list.tsx | 6 +- .../components/pure/workspace-title/index.tsx | 7 +- .../hooks/__tests__/use-recent-views.spec.tsx | 137 ------------------ .../web/src/hooks/current/use-current-mode.ts | 8 +- apps/web/src/hooks/use-recent-views.ts | 62 -------- .../workspace/[workspaceId]/[pageId].tsx | 2 - tsconfig.json | 2 + 14 files changed, 119 insertions(+), 275 deletions(-) delete mode 100644 apps/web/src/hooks/__tests__/use-recent-views.spec.tsx delete mode 100644 apps/web/src/hooks/use-recent-views.ts diff --git a/apps/web/src/atoms/index.ts b/apps/web/src/atoms/index.ts index 1aa19d2f52..55c536a693 100644 --- a/apps/web/src/atoms/index.ts +++ b/apps/web/src/atoms/index.ts @@ -2,9 +2,8 @@ import { DebugLogger } from '@affine/debug'; import { WorkspaceFlavour } from '@affine/env/workspace'; import type { RootWorkspaceMetadata } from '@affine/workspace/atom'; import { rootWorkspacesMetadataAtom } from '@affine/workspace/atom'; -import type { Page } from '@blocksuite/store'; import { atom } from 'jotai'; -import { atomWithStorage } from 'jotai/utils'; +import { atomFamily, atomWithStorage } from 'jotai/utils'; import { WorkspaceAdapters } from '../adapters/workspace'; import type { CreateWorkspaceMode } from '../components/affine/create-workspace-modal'; @@ -96,34 +95,70 @@ export const workspaceRecentViewsAtom = atomWithStorage( {} ); -export type PreferredModeRecord = Record; -/** - * @deprecated Use `useWorkspacePreferredMode` instead. - */ -export const workspacePreferredModeAtom = atomWithStorage( - 'preferredMode', - {} +type PageMode = 'page' | 'edgeless'; +type PageLocalSetting = { + mode: PageMode; +}; + +type PartialPageLocalSettingWithPageId = Partial & { + id: string; +}; + +const pageSettingsBaseAtom = atomWithStorage( + 'pageSettings', + {} as Record ); -export const workspaceRecentViresWriteAtom = atom( - null, - (get, set, id, value) => { - const record = get(workspaceRecentViewsAtom); - if (Array.isArray(record[id])) { - const idx = record[id].findIndex(view => view.id === value.id); - if (idx !== -1) { - record[id].splice(idx, 1); - } - record[id] = [value, ...record[id]]; - } else { - record[id] = [value]; - } +// readonly atom by design +export const pageSettingsAtom = atom(get => get(pageSettingsBaseAtom)); - record[id] = record[id].slice(0, 3); - set(workspaceRecentViewsAtom, { ...record }); - return record[id]; +const recentPageSettingsBaseAtom = atomWithStorage( + 'recentPageSettings', + [] +); + +export const recentPageSettingsAtom = atom( + get => { + const recentPageIDs = get(recentPageSettingsBaseAtom); + const pageSettings = get(pageSettingsAtom); + return recentPageIDs.map(id => ({ + ...pageSettings[id], + id, + })); + } +); + +export const pageSettingFamily = atomFamily((pageId: string) => + atom( + get => get(pageSettingsBaseAtom)[pageId], + ( + get, + set, + patch: + | Partial + | ((prevSetting: PageLocalSetting | undefined) => void) + ) => { + set(recentPageSettingsBaseAtom, ids => { + // pick 3 recent page ids + return [...new Set([pageId, ...ids]).values()].slice(0, 3); + }); + set(pageSettingsBaseAtom, settings => ({ + ...settings, + [pageId]: { + ...settings[pageId], + ...(typeof patch === 'function' ? patch(settings[pageId]) : patch), + }, + })); + } + ) +); + +export const setPageModeAtom = atom( + void 0, + (get, set, pageId: string, mode: PageMode) => { + set(pageSettingFamily(pageId), { mode }); } ); export type PageModeOption = 'all' | 'page' | 'edgeless'; -export const pageModeSelectAtom = atom('all'); +export const allPageModeSelectAtom = atom('all'); diff --git a/apps/web/src/components/blocksuite/block-suite-page-list/index.tsx b/apps/web/src/components/blocksuite/block-suite-page-list/index.tsx index ab70da6adf..e97c3b5df7 100644 --- a/apps/web/src/components/blocksuite/block-suite-page-list/index.tsx +++ b/apps/web/src/components/blocksuite/block-suite-page-list/index.tsx @@ -17,7 +17,7 @@ import { useAtom } from 'jotai'; import type React from 'react'; import { useMemo } from 'react'; -import { pageModeSelectAtom } from '../../../atoms'; +import { allPageModeSelectAtom } from '../../../atoms'; import { useBlockSuiteMetaHelper } from '../../../hooks/affine/use-block-suite-meta-helper'; import type { BlockSuiteWorkspace } from '../../../shared'; import { toast } from '../../../utils'; @@ -107,7 +107,7 @@ export const BlockSuitePageList: React.FC = ({ permanentlyDeletePage, cancelPublicPage, } = useBlockSuiteMetaHelper(blockSuiteWorkspace); - const [filterMode] = useAtom(pageModeSelectAtom); + const [filterMode] = useAtom(allPageModeSelectAtom); const { createPage, createEdgeless, importFile, isPreferredEdgeless } = usePageHelper(blockSuiteWorkspace); const t = useAFFiNEI18N(); diff --git a/apps/web/src/components/blocksuite/block-suite-page-list/utils.tsx b/apps/web/src/components/blocksuite/block-suite-page-list/utils.tsx index 99103789ad..890cf3780e 100644 --- a/apps/web/src/components/blocksuite/block-suite-page-list/utils.tsx +++ b/apps/web/src/components/blocksuite/block-suite-page-list/utils.tsx @@ -1,7 +1,9 @@ import { useBlockSuiteWorkspaceHelper } from '@toeverything/hooks/use-block-suite-workspace-helper'; +import { useAtomValue, useSetAtom } from 'jotai'; import { useRouter } from 'next/router'; +import { useCallback } from 'react'; -import { useWorkspacePreferredMode } from '../../../hooks/use-recent-views'; +import { pageSettingsAtom, setPageModeAtom } from '../../../atoms'; import { useRouterHelper } from '../../../hooks/use-router-helper'; import type { BlockSuiteWorkspace } from '../../../shared'; @@ -9,24 +11,25 @@ export const usePageHelper = (blockSuiteWorkspace: BlockSuiteWorkspace) => { const router = useRouter(); const { openPage } = useRouterHelper(router); const { createPage } = useBlockSuiteWorkspaceHelper(blockSuiteWorkspace); - const { getPreferredMode, setPreferredMode } = useWorkspacePreferredMode(); - const isPreferredEdgeless = (pageId: string) => { - return getPreferredMode(pageId) === 'edgeless'; - }; - - const createPageAndOpen = () => { + const pageSettings = useAtomValue(pageSettingsAtom); + const isPreferredEdgeless = useCallback( + (pageId: string) => pageSettings[pageId]?.mode === 'edgeless', + [pageSettings] + ); + const setPageMode = useSetAtom(setPageModeAtom); + const createPageAndOpen = useCallback(() => { const page = createPage(); return openPage(blockSuiteWorkspace.id, page.id); - }; - const createEdgelessAndOpen = () => { + }, [blockSuiteWorkspace.id, createPage, openPage]); + const createEdgelessAndOpen = useCallback(() => { const page = createPage(); - setPreferredMode(page.id, 'edgeless'); + setPageMode(page.id, 'edgeless'); return openPage(blockSuiteWorkspace.id, page.id); - }; - const importFileAndOpen = async () => { + }, [blockSuiteWorkspace.id, createPage, openPage, setPageMode]); + const importFileAndOpen = useCallback(async () => { const { showImportModal } = await import('@blocksuite/blocks'); showImportModal({ workspace: blockSuiteWorkspace }); - }; + }, [blockSuiteWorkspace]); return { createPage: createPageAndOpen, createEdgeless: createEdgelessAndOpen, diff --git a/apps/web/src/components/blocksuite/workspace-header/editor-mode-switch/index.tsx b/apps/web/src/components/blocksuite/workspace-header/editor-mode-switch/index.tsx index 02c29e3403..1223cf548c 100644 --- a/apps/web/src/components/blocksuite/workspace-header/editor-mode-switch/index.tsx +++ b/apps/web/src/components/blocksuite/workspace-header/editor-mode-switch/index.tsx @@ -1,10 +1,10 @@ import { useAFFiNEI18N } from '@affine/i18n/hooks'; import { assertExists } from '@blocksuite/store'; import { useBlockSuitePageMeta } from '@toeverything/hooks/use-block-suite-page-meta'; -import { useAtomValue, useSetAtom } from 'jotai'; +import { useAtom } from 'jotai'; import type { CSSProperties } from 'react'; -import { workspacePreferredModeAtom } from '../../../../atoms'; +import { pageSettingFamily } from '../../../../atoms'; import type { BlockSuiteWorkspace } from '../../../../shared'; import { toast } from '../../../../utils'; import { StyledEditorModeSwitch } from './style'; @@ -22,9 +22,8 @@ export const EditorModeSwitch = ({ blockSuiteWorkspace, pageId, }: EditorModeSwitchProps) => { - const currentMode = - useAtomValue(workspacePreferredModeAtom)[pageId] ?? 'page'; - const setMode = useSetAtom(workspacePreferredModeAtom); + const [setting, setSetting] = useAtom(pageSettingFamily(pageId)); + const currentMode = setting?.mode ?? 'page'; const pageMeta = useBlockSuitePageMeta(blockSuiteWorkspace).find( meta => meta.id === pageId ); @@ -43,11 +42,11 @@ export const EditorModeSwitch = ({ active={currentMode === 'page'} hide={trash && currentMode !== 'page'} onClick={() => { - setMode(mode => { - if (mode[pageMeta.id] !== 'page') { + setSetting(setting => { + if (setting?.mode !== 'page') { toast(t['com.affine.pageMode']()); } - return { ...mode, [pageMeta.id]: 'page' }; + return { ...setting, mode: 'page' }; }); }} /> @@ -56,11 +55,11 @@ export const EditorModeSwitch = ({ active={currentMode === 'edgeless'} hide={trash && currentMode !== 'edgeless'} onClick={() => { - setMode(mode => { - if (mode[pageMeta.id] !== 'edgeless') { - toast(t['com.affine.edgelessMode']()); + setSetting(setting => { + if (setting?.mode !== 'edgeless') { + toast(t['com.affine.pageMode']()); } - return { ...mode, [pageMeta.id]: 'edgeless' }; + return { ...setting, mode: 'edgeless' }; }); }} /> diff --git a/apps/web/src/components/blocksuite/workspace-header/header-right-items/editor-option-menu.tsx b/apps/web/src/components/blocksuite/workspace-header/header-right-items/editor-option-menu.tsx index 0518d6bc64..0b6bcdd165 100644 --- a/apps/web/src/components/blocksuite/workspace-header/header-right-items/editor-option-menu.tsx +++ b/apps/web/src/components/blocksuite/workspace-header/header-right-items/editor-option-menu.tsx @@ -18,7 +18,7 @@ import { useAtom } from 'jotai'; import { useRouter } from 'next/router'; import { useState } from 'react'; -import { workspacePreferredModeAtom } from '../../../../atoms'; +import { pageSettingFamily } from '../../../../atoms'; import { useBlockSuiteMetaHelper } from '../../../../hooks/affine/use-block-suite-meta-helper'; import { useCurrentPageId } from '../../../../hooks/current/use-current-page-id'; import { useCurrentWorkspace } from '../../../../hooks/current/use-current-workspace'; @@ -64,8 +64,8 @@ const PageMenu = () => { meta => meta.id === pageId ); assertExists(pageMeta); - const [record, set] = useAtom(workspacePreferredModeAtom); - const mode = record[pageId] ?? 'page'; + const [setting, setSetting] = useAtom(pageSettingFamily(pageId)); + const mode = setting?.mode ?? 'page'; const favorite = pageMeta.favorite ?? false; const { setPageMeta } = usePageMetaHelper(blockSuiteWorkspace); @@ -98,9 +98,8 @@ const PageMenu = () => { icon={mode === 'page' ? : } data-testid="editor-option-menu-edgeless" onClick={() => { - set(record => ({ - ...record, - [pageId]: mode === 'page' ? 'edgeless' : 'page', + setSetting(setting => ({ + mode: setting?.mode === 'page' ? 'edgeless' : 'page', })); }} > diff --git a/apps/web/src/components/page-detail-editor.tsx b/apps/web/src/components/page-detail-editor.tsx index 1ad13dd84d..c440141b7a 100644 --- a/apps/web/src/components/page-detail-editor.tsx +++ b/apps/web/src/components/page-detail-editor.tsx @@ -30,7 +30,7 @@ import React, { } from 'react'; import { Panel, PanelGroup, PanelResizeHandle } from 'react-resizable-panels'; -import { workspacePreferredModeAtom } from '../atoms'; +import { pageSettingFamily } from '../atoms'; import { contentLayoutAtom } from '../atoms/layout'; import type { AffineOfficialWorkspace } from '../shared'; import { BlockSuiteEditor as Editor } from './blocksuite/block-suite-editor'; @@ -63,11 +63,13 @@ const EditorWrapper = memo(function EditorWrapper({ const meta = useBlockSuitePageMeta(blockSuiteWorkspace).find( meta => meta.id === pageId ); + const pageSettingAtom = pageSettingFamily(pageId); + const pageSetting = useAtomValue(pageSettingAtom); const currentMode = - useAtomValue(workspacePreferredModeAtom)[pageId] ?? - DEFAULT_HELLO_WORLD_PAGE_ID === pageId + pageSetting?.mode ?? DEFAULT_HELLO_WORLD_PAGE_ID === pageId ? 'edgeless' : 'page'; + const setEditor = useSetAtom(rootCurrentEditorAtom); assertExists(meta); return ( diff --git a/apps/web/src/components/pure/quick-search-modal/results.tsx b/apps/web/src/components/pure/quick-search-modal/results.tsx index 5bb4c22478..79988b9c04 100644 --- a/apps/web/src/components/pure/quick-search-modal/results.tsx +++ b/apps/web/src/components/pure/quick-search-modal/results.tsx @@ -5,12 +5,13 @@ import { assertExists } from '@blocksuite/store'; import { useBlockSuitePageMeta } from '@toeverything/hooks/use-block-suite-page-meta'; import { useBlockSuiteWorkspaceHelper } from '@toeverything/hooks/use-block-suite-workspace-helper'; import { Command } from 'cmdk'; +import { useAtomValue } from 'jotai'; import Image from 'next/legacy/image'; import type { NextRouter } from 'next/router'; import type { Dispatch, FC, SetStateAction } from 'react'; import { useEffect } from 'react'; -import { useRecentlyViewed } from '../../../hooks/use-recent-views'; +import { recentPageSettingsAtom } from '../../../atoms'; import { useRouterHelper } from '../../../hooks/use-router-helper'; import type { BlockSuiteWorkspace } from '../../../shared'; import { useSwitchToConfig } from './config'; @@ -35,7 +36,7 @@ export const Results: FC = ({ assertExists(blockSuiteWorkspace.id); const List = useSwitchToConfig(blockSuiteWorkspace.id); - const recentlyViewed = useRecentlyViewed(); + const recentPageSetting = useAtomValue(recentPageSettingsAtom); const t = useAFFiNEI18N(); const { jumpToPage } = useRouterHelper(router); const results = blockSuiteWorkspace.search(query); @@ -45,7 +46,8 @@ export const Results: FC = ({ const resultsPageMeta = pageList.filter( page => pageIds.indexOf(page.id) > -1 && !page.trash ); - const recentlyViewedItem = recentlyViewed.filter(recent => { + + const recentlyViewedItem = recentPageSetting.filter(recent => { const page = pageList.find(page => recent.id === page.id); if (!page) { return false; diff --git a/apps/web/src/components/pure/workspace-slider-bar/favorite/favorite-list.tsx b/apps/web/src/components/pure/workspace-slider-bar/favorite/favorite-list.tsx index c271194a07..dd2ec28f2f 100644 --- a/apps/web/src/components/pure/workspace-slider-bar/favorite/favorite-list.tsx +++ b/apps/web/src/components/pure/workspace-slider-bar/favorite/favorite-list.tsx @@ -8,7 +8,7 @@ import { useAtomValue } from 'jotai'; import { useRouter } from 'next/router'; import { useMemo, useState } from 'react'; -import { workspacePreferredModeAtom } from '../../../../atoms'; +import { pageSettingFamily } from '../../../../atoms'; import type { FavoriteListProps } from '../index'; import EmptyItem from './empty-item'; import * as styles from './styles.css'; @@ -27,9 +27,9 @@ function FavoriteMenuItem({ parentIds, }: FavoriteMenuItemProps) { const router = useRouter(); - const record = useAtomValue(workspacePreferredModeAtom); + const setting = useAtomValue(pageSettingFamily(pageId)); const active = router.query.pageId === pageId; - const icon = record[pageId] === 'edgeless' ? : ; + const icon = setting?.mode === 'edgeless' ? : ; const references = useBlockSuitePageReferences(workspace, pageId); const referencesToShow = useMemo(() => { return [ diff --git a/apps/web/src/components/pure/workspace-title/index.tsx b/apps/web/src/components/pure/workspace-title/index.tsx index 337f1742eb..ecd573801b 100644 --- a/apps/web/src/components/pure/workspace-title/index.tsx +++ b/apps/web/src/components/pure/workspace-title/index.tsx @@ -5,7 +5,10 @@ import { useAtom } from 'jotai'; import type { ReactNode } from 'react'; import type React from 'react'; -import { openQuickSearchModalAtom, pageModeSelectAtom } from '../../../atoms'; +import { + allPageModeSelectAtom, + openQuickSearchModalAtom, +} from '../../../atoms'; import type { HeaderProps } from '../../blocksuite/workspace-header/header'; import { Header } from '../../blocksuite/workspace-header/header'; import * as styles from '../../blocksuite/workspace-header/styles.css'; @@ -40,7 +43,7 @@ export const WorkspaceTitle: React.FC = ({ export const WorkspaceModeFilterTab = ({ ...props }: WorkspaceTitleProps) => { const t = useAFFiNEI18N(); - const [value, setMode] = useAtom(pageModeSelectAtom); + const [value, setMode] = useAtom(allPageModeSelectAtom); const handleValueChange = (value: string) => { if (value !== 'all' && value !== 'page' && value !== 'edgeless') { throw new Error('Invalid value for page mode option'); diff --git a/apps/web/src/hooks/__tests__/use-recent-views.spec.tsx b/apps/web/src/hooks/__tests__/use-recent-views.spec.tsx deleted file mode 100644 index aa64ab8781..0000000000 --- a/apps/web/src/hooks/__tests__/use-recent-views.spec.tsx +++ /dev/null @@ -1,137 +0,0 @@ -/** - * @vitest-environment happy-dom - */ -import type { LocalWorkspace } from '@affine/env/workspace'; -import { WorkspaceFlavour, WorkspaceSubPath } from '@affine/env/workspace'; -import { - rootCurrentWorkspaceIdAtom, - rootWorkspacesMetadataAtom, -} from '@affine/workspace/atom'; -import { __unstableSchemas, AffineSchemas } from '@blocksuite/blocks/models'; -import type { Page } from '@blocksuite/store'; -import { assertExists } from '@blocksuite/store'; -import { renderHook } from '@testing-library/react'; -import { createStore, Provider } from 'jotai'; -import { useRouter } from 'next/router'; -import routerMock from 'next-router-mock'; -import { createDynamicRouteParser } from 'next-router-mock/dynamic-routes'; -import type { FC, PropsWithChildren } from 'react'; -import { beforeAll, beforeEach, describe, expect, test, vi } from 'vitest'; - -import { LocalAdapter } from '../../adapters/local'; -import { workspacesAtom } from '../../atoms'; -import { rootCurrentWorkspaceAtom } from '../../atoms/root'; -import { BlockSuiteWorkspace } from '../../shared'; -import { useCurrentWorkspace } from '../current/use-current-workspace'; -import { - useRecentlyViewed, - useSyncRecentViewsWithRouter, -} from '../use-recent-views'; - -let blockSuiteWorkspace: BlockSuiteWorkspace; -beforeAll(() => { - routerMock.useParser( - createDynamicRouteParser([ - `/workspace/[workspaceId/${WorkspaceSubPath.ALL}`, - `/workspace/[workspaceId/${WorkspaceSubPath.SETTING}`, - `/workspace/[workspaceId/${WorkspaceSubPath.TRASH}`, - '/workspace/[workspaceId]/[pageId]', - ]) - ); -}); - -async function getJotaiContext() { - const store = createStore(); - const ProviderWrapper: FC = function ProviderWrapper({ - children, - }) { - return {children}; - }; - const workspaces = await store.get(workspacesAtom); - expect(workspaces.length).toBe(0); - return { - store, - ProviderWrapper, - initialWorkspaces: workspaces, - } as const; -} - -beforeEach(async () => { - blockSuiteWorkspace = new BlockSuiteWorkspace({ id: 'test' }) - .register(AffineSchemas) - .register(__unstableSchemas); - const initPage = (page: Page) => { - expect(page).not.toBeNull(); - assertExists(page); - const pageBlockId = page.addBlock('affine:page', { - title: new page.Text(''), - }); - const frameId = page.addBlock('affine:frame', {}, pageBlockId); - page.addBlock('affine:paragraph', {}, frameId); - }; - initPage( - blockSuiteWorkspace.createPage({ - id: 'page0', - }) - ); - initPage(blockSuiteWorkspace.createPage({ id: 'page1' })); - initPage(blockSuiteWorkspace.createPage({ id: 'page2' })); -}); - -describe('useRecentlyViewed', () => { - test('basic', async () => { - const { ProviderWrapper, store } = await getJotaiContext(); - const workspaceId = blockSuiteWorkspace.id; - const pageId = 'page0'; - store.set(rootWorkspacesMetadataAtom, [ - { - id: workspaceId, - flavour: WorkspaceFlavour.LOCAL, - }, - ]); - LocalAdapter.CRUD.get = vi.fn().mockResolvedValue({ - id: workspaceId, - flavour: WorkspaceFlavour.LOCAL, - blockSuiteWorkspace, - providers: [], - } satisfies LocalWorkspace); - store.set(rootCurrentWorkspaceIdAtom, blockSuiteWorkspace.id); - const workspace = await store.get(rootCurrentWorkspaceAtom); - expect(workspace?.id).toBe(blockSuiteWorkspace.id); - const currentHook = renderHook(() => useCurrentWorkspace(), { - wrapper: ProviderWrapper, - }); - expect(currentHook.result.current[0]?.id).toEqual(workspaceId); - store.set(rootCurrentWorkspaceIdAtom, blockSuiteWorkspace.id); - await store.get(rootCurrentWorkspaceAtom); - const recentlyViewedHook = renderHook(() => useRecentlyViewed(), { - wrapper: ProviderWrapper, - }); - expect(recentlyViewedHook.result.current).toEqual([]); - const routerHook = renderHook(() => useRouter(), { - wrapper: ProviderWrapper, - }); - await routerHook.result.current.push({ - pathname: '/workspace/[workspaceId]/[pageId]', - query: { - workspaceId, - pageId, - }, - }); - routerHook.rerender(); - const syncHook = renderHook( - router => useSyncRecentViewsWithRouter(router, blockSuiteWorkspace), - { - wrapper: ProviderWrapper, - initialProps: routerHook.result.current, - } - ); - syncHook.rerender(routerHook.result.current); - expect(recentlyViewedHook.result.current).toEqual([ - { - id: 'page0', - mode: 'page', - }, - ]); - }); -}); diff --git a/apps/web/src/hooks/current/use-current-mode.ts b/apps/web/src/hooks/current/use-current-mode.ts index 6508259469..2cc31a8fbb 100644 --- a/apps/web/src/hooks/current/use-current-mode.ts +++ b/apps/web/src/hooks/current/use-current-mode.ts @@ -1,15 +1,15 @@ import { rootCurrentPageIdAtom } from '@affine/workspace/atom'; import { atom, useAtomValue } from 'jotai'; -import { workspacePreferredModeAtom } from '../../atoms'; +import { pageSettingFamily } from '../../atoms'; const currentModeAtom = atom<'page' | 'edgeless'>(get => { const pageId = get(rootCurrentPageIdAtom); - const record = get(workspacePreferredModeAtom); - if (pageId) return record[pageId] ?? 'page'; - else { + // fixme(himself65): pageId should not be null + if (!pageId) { return 'page'; } + return get(pageSettingFamily(pageId))?.mode ?? 'page'; }); export const useCurrentMode = () => { diff --git a/apps/web/src/hooks/use-recent-views.ts b/apps/web/src/hooks/use-recent-views.ts deleted file mode 100644 index 7b6845581a..0000000000 --- a/apps/web/src/hooks/use-recent-views.ts +++ /dev/null @@ -1,62 +0,0 @@ -import type { Page, Workspace } from '@blocksuite/store'; -import { useBlockSuitePageMeta } from '@toeverything/hooks/use-block-suite-page-meta'; -import { useAtom, useAtomValue, useSetAtom } from 'jotai'; -import type { NextRouter } from 'next/router'; -import { useEffect } from 'react'; - -import { - workspacePreferredModeAtom, - workspaceRecentViewsAtom, - workspaceRecentViresWriteAtom, -} from '../atoms'; -import { useCurrentWorkspace } from './current/use-current-workspace'; - -export const useWorkspacePreferredMode = () => { - const [record, setPreferred] = useAtom(workspacePreferredModeAtom); - return { - getPreferredMode: (pageId: Page['id']) => record[pageId] ?? 'page', - setPreferredMode: (pageId: Page['id'], mode: 'page' | 'edgeless') => { - setPreferred(record => ({ - ...record, - [pageId]: mode, - })); - }, - }; -}; - -export function useRecentlyViewed() { - const [workspace] = useCurrentWorkspace(); - const workspaceId = workspace?.id || null; - const recentlyViewed = useAtomValue(workspaceRecentViewsAtom); - - if (!workspaceId) return []; - return recentlyViewed[workspaceId] ?? []; -} - -export function useSyncRecentViewsWithRouter( - router: NextRouter, - blockSuiteWorkspace: Workspace -) { - const workspaceId = blockSuiteWorkspace.id; - const pageId = router.query.pageId; - const set = useSetAtom(workspaceRecentViresWriteAtom); - const meta = useBlockSuitePageMeta(blockSuiteWorkspace).find( - meta => meta.id === pageId - ); - const { getPreferredMode } = useWorkspacePreferredMode(); - - const currentMode = - typeof pageId === 'string' ? getPreferredMode(pageId) : 'page'; - useEffect(() => { - if (!workspaceId) return; - if (pageId && meta) { - set(workspaceId, { - id: pageId as string, - /** - * @deprecated No necessary update `mode` at here, use `mode` from {@link useWorkspacePreferredMode} directly. - */ - mode: currentMode, - }); - } - }, [pageId, meta, workspaceId, set, currentMode]); -} diff --git a/apps/web/src/pages/workspace/[workspaceId]/[pageId].tsx b/apps/web/src/pages/workspace/[workspaceId]/[pageId].tsx index 525b8d4e72..f449efd382 100644 --- a/apps/web/src/pages/workspace/[workspaceId]/[pageId].tsx +++ b/apps/web/src/pages/workspace/[workspaceId]/[pageId].tsx @@ -12,7 +12,6 @@ import { useCallback } from 'react'; import { getUIAdapter } from '../../../adapters/workspace'; import { rootCurrentWorkspaceAtom } from '../../../atoms/root'; import { useCurrentWorkspace } from '../../../hooks/current/use-current-workspace'; -import { useSyncRecentViewsWithRouter } from '../../../hooks/use-recent-views'; import { useRouterHelper } from '../../../hooks/use-router-helper'; import { WorkspaceLayout } from '../../../layouts/workspace-layout'; import type { NextPageWithLayout } from '../../../shared'; @@ -25,7 +24,6 @@ const WorkspaceDetail: React.FC = () => { assertExists(currentWorkspace); assertExists(currentPageId); const blockSuiteWorkspace = currentWorkspace.blockSuiteWorkspace; - useSyncRecentViewsWithRouter(router, blockSuiteWorkspace); const onLoad = useCallback( (page: Page, editor: EditorContainer) => { diff --git a/tsconfig.json b/tsconfig.json index 9b9e83da7c..d71967dd32 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -7,6 +7,8 @@ "skipLibCheck": true, "strict": true, "forceConsistentCasingInFileNames": true, + // FIXME: add this back + "noUncheckedIndexedAccess": false, "esModuleInterop": true, "module": "esnext", "moduleResolution": "node",