From 0bb6e362bf4b29cd48e958cddef21a4105ae4c4b Mon Sep 17 00:00:00 2001 From: Whitewater Date: Tue, 30 May 2023 20:15:23 -0700 Subject: [PATCH] feat: add page mode filter (#2601) Co-authored-by: himself65 --- apps/web/src/atoms/index.ts | 3 ++ .../block-suite-page-list/index.tsx | 43 +++++++++++++------ .../components/pure/workspace-title/index.tsx | 32 +++++++++++++- apps/web/src/components/workspace-header.tsx | 32 ++++---------- packages/component/src/ui/button/index.ts | 1 + .../component/src/ui/button/styles.css.ts | 2 + 6 files changed, 75 insertions(+), 38 deletions(-) diff --git a/apps/web/src/atoms/index.ts b/apps/web/src/atoms/index.ts index c7997330ac..8685bc2434 100644 --- a/apps/web/src/atoms/index.ts +++ b/apps/web/src/atoms/index.ts @@ -139,3 +139,6 @@ export const workspaceRecentViresWriteAtom = atom( return record[id]; } ); + +export type PageModeOption = 'all' | 'page' | 'edgeless'; +export const pageModeSelectAtom = 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 91568c8ab3..1e03d1ad4f 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 @@ -13,9 +13,11 @@ import { useAFFiNEI18N } from '@affine/i18n/hooks'; import { EdgelessIcon, PageIcon } from '@blocksuite/icons'; import type { PageMeta } from '@blocksuite/store'; import { useBlockSuitePageMeta } from '@toeverything/hooks/use-block-suite-page-meta'; +import { useAtom } from 'jotai'; import type React from 'react'; import { useMemo } from 'react'; +import { pageModeSelectAtom } from '../../../atoms'; import { useBlockSuiteMetaHelper } from '../../../hooks/affine/use-block-suite-meta-helper'; import type { BlockSuiteWorkspace } from '../../../shared'; import { toast } from '../../../utils'; @@ -80,25 +82,40 @@ export const BlockSuitePageList: React.FC = ({ permanentlyDeletePage, cancelPublicPage, } = useBlockSuiteMetaHelper(blockSuiteWorkspace); + const [filterMode] = useAtom(pageModeSelectAtom); const { createPage, createEdgeless, importFile, isPreferredEdgeless } = usePageHelper(blockSuiteWorkspace); const t = useAFFiNEI18N(); const list = useMemo( () => - pageMetas.filter(pageMeta => { - if (!filter[listType](pageMeta, pageMetas)) { - return false; - } - if (!view) { + pageMetas + .filter(pageMeta => { + if (filterMode === 'all') { + return true; + } + if (filterMode === 'edgeless') { + return isPreferredEdgeless(pageMeta.id); + } + if (filterMode === 'page') { + return !isPreferredEdgeless(pageMeta.id); + } + console.error('unknown filter mode', pageMeta, filterMode); return true; - } - return filterByFilterList(view.filterList, { - Favorite: !!pageMeta.favorite, - Created: pageMeta.createDate, - Updated: pageMeta.updatedDate ?? pageMeta.createDate, - }); - }), - [pageMetas, listType, view] + }) + .filter(pageMeta => { + if (!filter[listType](pageMeta, pageMetas)) { + return false; + } + if (!view) { + return true; + } + return filterByFilterList(view.filterList, { + Favorite: !!pageMeta.favorite, + Created: pageMeta.createDate, + Updated: pageMeta.updatedDate ?? pageMeta.createDate, + }); + }), + [pageMetas, filterMode, isPreferredEdgeless, listType, view] ); if (list.length === 0) { return ; diff --git a/apps/web/src/components/pure/workspace-title/index.tsx b/apps/web/src/components/pure/workspace-title/index.tsx index fd031bff43..7a75d9f28a 100644 --- a/apps/web/src/components/pure/workspace-title/index.tsx +++ b/apps/web/src/components/pure/workspace-title/index.tsx @@ -1,8 +1,11 @@ +import { RadioButton, RadioButtonGroup } from '@affine/component'; +import { useAFFiNEI18N } from '@affine/i18n/hooks'; import { useSetAtom } from 'jotai'; +import { useAtom } from "jotai"; import type { ReactNode } from 'react'; import type React from 'react'; -import { openQuickSearchModalAtom } from '../../../atoms'; +import { openQuickSearchModalAtom, pageModeSelectAtom } 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'; @@ -34,3 +37,30 @@ export const WorkspaceTitle: React.FC = ({ ); }; + +export const WorkspaceModeFilterTab = ({ ...props }: WorkspaceTitleProps) => { + const t = useAFFiNEI18N(); + const [value, setMode] = useAtom(pageModeSelectAtom); + const handleValueChange = (value: string) => { + if (value !== 'all' && value !== 'page' && value !== 'edgeless') { + throw new Error('Invalid value for page mode option'); + } + setMode(value); + }; + return ( +
+
+ + + {t['all']()} + + {t['Page']()} + {t['Edgeless']()} + +
+
+ ); +}; diff --git a/apps/web/src/components/workspace-header.tsx b/apps/web/src/components/workspace-header.tsx index 2e3487524b..90fef3cfed 100644 --- a/apps/web/src/components/workspace-header.tsx +++ b/apps/web/src/components/workspace-header.tsx @@ -9,19 +9,13 @@ import { config } from '@affine/env'; import { useAFFiNEI18N } from '@affine/i18n/hooks'; import type { WorkspaceHeaderProps } from '@affine/workspace/type'; import { WorkspaceFlavour, WorkspaceSubPath } from '@affine/workspace/type'; -import { - DeleteTemporarilyIcon, - FolderIcon, - SettingsIcon, - ShareIcon, -} from '@blocksuite/icons'; +import { SettingsIcon } from '@blocksuite/icons'; import { RESET } from 'jotai/utils'; import type { ReactElement } from 'react'; -import React from 'react'; import { NIL } from 'uuid'; import { BlockSuiteEditorHeader } from './blocksuite/workspace-header'; -import { WorkspaceTitle } from './pure/workspace-title'; +import { WorkspaceModeFilterTab, WorkspaceTitle } from './pure/workspace-title'; export function WorkspaceHeader({ currentWorkspace, @@ -64,18 +58,14 @@ export function WorkspaceHeader({ ); - return ( <> - } leftSlot={leftSlot} - > - {t['All pages']()} - + /> {filterContainer} ); @@ -92,25 +82,19 @@ export function WorkspaceHeader({ ); } else if (currentEntry.subPath === WorkspaceSubPath.SHARED) { return ( - } - > - {t['Shared Pages']()} - + /> ); } else if (currentEntry.subPath === WorkspaceSubPath.TRASH) { return ( - } - > - {t['Trash']()} - + /> ); } } else if ('pageId' in currentEntry) { diff --git a/packages/component/src/ui/button/index.ts b/packages/component/src/ui/button/index.ts index 92efd3a917..4873f7b9b2 100644 --- a/packages/component/src/ui/button/index.ts +++ b/packages/component/src/ui/button/index.ts @@ -1,3 +1,4 @@ export * from './button'; export * from './icon-button'; +export * from './radio'; export * from './text-button'; diff --git a/packages/component/src/ui/button/styles.css.ts b/packages/component/src/ui/button/styles.css.ts index d19fe29ce3..a21a7048dc 100644 --- a/packages/component/src/ui/button/styles.css.ts +++ b/packages/component/src/ui/button/styles.css.ts @@ -91,4 +91,6 @@ export const radioButtonGroup = style({ background: 'var(--affine-hover-color)', borderRadius: '10px', padding: '2px', + // @ts-expect-error - fix electron drag + WebkitAppRegion: 'no-drag', });