From 228b0d789d741535c8e2375a92f8ef65d97a1259 Mon Sep 17 00:00:00 2001 From: Whitewater Date: Fri, 23 Feb 2024 16:07:13 +0800 Subject: [PATCH] feat: add shared page filter to all pages (#5540) Co-authored-by: EYHN --- .../page-list/__tests__/filter.spec.tsx | 1 + .../page-list/docs/virtualized-page-list.tsx | 2 +- .../filter/filter-tag-translation.tsx | 2 + .../page-list/filter/shared-types.tsx | 5 +++ .../page-list/use-collection-manager.ts | 22 ++++++---- .../page-list/use-filtered-page-metas.tsx | 17 +++++--- .../view/edit-collection/edit-collection.tsx | 4 ++ .../view/edit-collection/pages-mode.tsx | 7 ++- .../view/edit-collection/rules-mode.tsx | 16 ++++--- .../view/edit-collection/select-page.tsx | 7 ++- .../view/edit-collection/use-filter.tsx | 22 ++++++---- .../collections/collections-list.tsx | 11 +++-- .../hooks/affine/use-all-page-list-config.tsx | 8 +++- .../src/hooks/affine/use-is-shared-page.ts | 43 +++++++++++++++++++ .../src/pages/workspace/all-page/all-page.tsx | 2 +- .../core/src/pages/workspace/trash-page.tsx | 2 +- packages/frontend/i18n/src/resources/en.json | 1 + 17 files changed, 134 insertions(+), 38 deletions(-) diff --git a/packages/frontend/core/src/components/page-list/__tests__/filter.spec.tsx b/packages/frontend/core/src/components/page-list/__tests__/filter.spec.tsx index 4f6c210f8..8604ff721 100644 --- a/packages/frontend/core/src/components/page-list/__tests__/filter.spec.tsx +++ b/packages/frontend/core/src/components/page-list/__tests__/filter.spec.tsx @@ -34,6 +34,7 @@ const mockVariableMap = (vars: Partial): VariableMap => { Created: 0, Updated: 0, 'Is Favourited': false, + 'Is Public': false, Tags: [], ...vars, }; diff --git a/packages/frontend/core/src/components/page-list/docs/virtualized-page-list.tsx b/packages/frontend/core/src/components/page-list/docs/virtualized-page-list.tsx index 983b12055..9035f4dfc 100644 --- a/packages/frontend/core/src/components/page-list/docs/virtualized-page-list.tsx +++ b/packages/frontend/core/src/components/page-list/docs/virtualized-page-list.tsx @@ -104,7 +104,7 @@ export const VirtualizedPageList = ({ const filteredPageMetas = useFilteredPageMetas( 'all', pageMetas, - currentWorkspace.blockSuiteWorkspace + currentWorkspace ); const pageMetasToRender = useMemo(() => { if (listItem) { diff --git a/packages/frontend/core/src/components/page-list/filter/filter-tag-translation.tsx b/packages/frontend/core/src/components/page-list/filter/filter-tag-translation.tsx index 1c3d8c27b..a8158d8c5 100644 --- a/packages/frontend/core/src/components/page-list/filter/filter-tag-translation.tsx +++ b/packages/frontend/core/src/components/page-list/filter/filter-tag-translation.tsx @@ -15,6 +15,8 @@ const useFilterTag = ({ name }: FilterTagProps) => { return t['Tags'](); case 'Is Favourited': return t['com.affine.filter.is-favourited'](); + case 'Is Public': + return t['com.affine.filter.is-public'](); case 'after': return t['com.affine.filter.after'](); case 'before': diff --git a/packages/frontend/core/src/components/page-list/filter/shared-types.tsx b/packages/frontend/core/src/components/page-list/filter/shared-types.tsx index dafa441cb..29d1eedd3 100644 --- a/packages/frontend/core/src/components/page-list/filter/shared-types.tsx +++ b/packages/frontend/core/src/components/page-list/filter/shared-types.tsx @@ -5,6 +5,7 @@ import type { VariableMap, } from '@affine/env/filter'; import { + CloudWorkspaceIcon, CreatedIcon, FavoriteIcon, TagsIcon, @@ -44,6 +45,10 @@ export const variableDefineMap = { type: meta => tArray(tTag.create({ tags: meta.tags?.options ?? [] })), icon: , }, + 'Is Public': { + type: () => tBoolean.create(), + icon: , + }, // Imported: { // type: tBoolean.create(), // }, diff --git a/packages/frontend/core/src/components/page-list/use-collection-manager.ts b/packages/frontend/core/src/components/page-list/use-collection-manager.ts index 866a91961..7116f5176 100644 --- a/packages/frontend/core/src/components/page-list/use-collection-manager.ts +++ b/packages/frontend/core/src/components/page-list/use-collection-manager.ts @@ -97,24 +97,30 @@ export const useCollectionManager = (collectionService: CollectionService) => { export const filterByFilterList = (filterList: Filter[], varMap: VariableMap) => evalFilterList(filterList, varMap); -export const filterPage = (collection: Collection, page: PageMeta) => { +export type PageDataForFilter = { + meta: PageMeta; + publicMode: undefined | 'page' | 'edgeless'; +}; + +export const filterPage = (collection: Collection, page: PageDataForFilter) => { if (collection.filterList.length === 0) { - return collection.allowList.includes(page.id); + return collection.allowList.includes(page.meta.id); } return filterPageByRules(collection.filterList, collection.allowList, page); }; export const filterPageByRules = ( rules: Filter[], allowList: string[], - page: PageMeta + { meta, publicMode }: PageDataForFilter ) => { - if (allowList?.includes(page.id)) { + if (allowList?.includes(meta.id)) { return true; } return filterByFilterList(rules, { - 'Is Favourited': !!page.favorite, - Created: page.createDate, - Updated: page.updatedDate ?? page.createDate, - Tags: page.tags, + 'Is Favourited': !!meta.favorite, + 'Is Public': !!publicMode, + Created: meta.createDate, + Updated: meta.updatedDate ?? meta.createDate, + Tags: meta.tags, }); }; diff --git a/packages/frontend/core/src/components/page-list/use-filtered-page-metas.tsx b/packages/frontend/core/src/components/page-list/use-filtered-page-metas.tsx index 81969434d..4031a55ff 100644 --- a/packages/frontend/core/src/components/page-list/use-filtered-page-metas.tsx +++ b/packages/frontend/core/src/components/page-list/use-filtered-page-metas.tsx @@ -1,8 +1,9 @@ import { allPageModeSelectAtom } from '@affine/core/atoms'; import { usePageHelper } from '@affine/core/components/blocksuite/block-suite-page-list/utils'; +import { usePublicPages } from '@affine/core/hooks/affine/use-is-shared-page'; import { CollectionService } from '@affine/core/modules/collection'; -import type { BlockSuiteWorkspace } from '@affine/core/shared'; import type { PageMeta } from '@blocksuite/store'; +import type { Workspace } from '@toeverything/infra'; import { useService } from '@toeverything/infra/di'; import { useAtomValue } from 'jotai'; import { useMemo } from 'react'; @@ -16,13 +17,14 @@ import { export const useFilteredPageMetas = ( route: 'all' | 'trash', pageMetas: PageMeta[], - workspace: BlockSuiteWorkspace + workspace: Workspace ) => { - const { isPreferredEdgeless } = usePageHelper(workspace); + const { isPreferredEdgeless } = usePageHelper(workspace.blockSuiteWorkspace); const pageMode = useAtomValue(allPageModeSelectAtom); const { currentCollection, isDefault } = useCollectionManager( useService(CollectionService) ); + const { getPublicMode } = usePublicPages(workspace); const filteredPageMetas = useMemo( () => @@ -50,18 +52,23 @@ export const useFilteredPageMetas = ( if (!currentCollection) { return true; } + const pageData = { + meta: pageMeta, + publicMode: getPublicMode(pageMeta.id), + }; return isDefault ? filterPageByRules( currentCollection.filterList, currentCollection.allowList, - pageMeta + pageData ) - : filterPage(currentCollection, pageMeta); + : filterPage(currentCollection, pageData); }), [ currentCollection, isDefault, isPreferredEdgeless, + getPublicMode, pageMetas, pageMode, route, diff --git a/packages/frontend/core/src/components/page-list/view/edit-collection/edit-collection.tsx b/packages/frontend/core/src/components/page-list/view/edit-collection/edit-collection.tsx index 895431fd7..eec39d437 100644 --- a/packages/frontend/core/src/components/page-list/view/edit-collection/edit-collection.tsx +++ b/packages/frontend/core/src/components/page-list/view/edit-collection/edit-collection.tsx @@ -201,6 +201,10 @@ export type AllPageListConfig = { allPages: PageMeta[]; workspace: Workspace; isEdgeless: (id: string) => boolean; + /** + * Return `undefined` if the page is not public + */ + getPublicMode: (id: string) => undefined | 'page' | 'edgeless'; getPage: (id: string) => PageMeta | undefined; favoriteRender: (page: PageMeta) => ReactNode; }; diff --git a/packages/frontend/core/src/components/page-list/view/edit-collection/pages-mode.tsx b/packages/frontend/core/src/components/page-list/view/edit-collection/pages-mode.tsx index b0c707bba..69e5f5632 100644 --- a/packages/frontend/core/src/components/page-list/view/edit-collection/pages-mode.tsx +++ b/packages/frontend/core/src/components/page-list/view/edit-collection/pages-mode.tsx @@ -40,7 +40,12 @@ export const PagesMode = ({ clickFilter, createFilter, filteredList, - } = useFilter(allPageListConfig.allPages); + } = useFilter( + allPageListConfig.allPages.map(meta => ({ + meta, + publicMode: allPageListConfig.getPublicMode(meta.id), + })) + ); const { searchText, updateSearchText, searchedList } = useSearch(filteredList); const clearSelected = useCallback(() => { diff --git a/packages/frontend/core/src/components/page-list/view/edit-collection/rules-mode.tsx b/packages/frontend/core/src/components/page-list/view/edit-collection/rules-mode.tsx index 1bdf1a1bf..8cbdf6592 100644 --- a/packages/frontend/core/src/components/page-list/view/edit-collection/rules-mode.tsx +++ b/packages/frontend/core/src/components/page-list/view/edit-collection/rules-mode.tsx @@ -48,18 +48,22 @@ export const RulesMode = ({ setShowTips(false); localStorage.setItem('hide-rules-mode-include-page-tips', 'true'); }, []); - allPageListConfig.allPages.forEach(v => { - if (v.trash) { + allPageListConfig.allPages.forEach(meta => { + if (meta.trash) { return; } + const pageData = { + meta, + publicMode: allPageListConfig.getPublicMode(meta.id), + }; if ( collection.filterList.length && - filterPageByRules(collection.filterList, [], v) + filterPageByRules(collection.filterList, [], pageData) ) { - rulesPages.push(v); + rulesPages.push(meta); } - if (collection.allowList.includes(v.id)) { - allowListPages.push(v); + if (collection.allowList.includes(meta.id)) { + allowListPages.push(meta); } }); const { node: selectPageNode, open } = useSelectPage({ allPageListConfig }); diff --git a/packages/frontend/core/src/components/page-list/view/edit-collection/select-page.tsx b/packages/frontend/core/src/components/page-list/view/edit-collection/select-page.tsx index 3974edb58..f64b70930 100644 --- a/packages/frontend/core/src/components/page-list/view/edit-collection/select-page.tsx +++ b/packages/frontend/core/src/components/page-list/view/edit-collection/select-page.tsx @@ -42,7 +42,12 @@ export const SelectPage = ({ showFilter, updateFilters, filteredList, - } = useFilter(allPageListConfig.allPages); + } = useFilter( + allPageListConfig.allPages.map(meta => ({ + meta, + publicMode: allPageListConfig.getPublicMode(meta.id), + })) + ); const { searchText, updateSearchText, searchedList } = useSearch(filteredList); diff --git a/packages/frontend/core/src/components/page-list/view/edit-collection/use-filter.tsx b/packages/frontend/core/src/components/page-list/view/edit-collection/use-filter.tsx index 8775c5a06..8fd5de060 100644 --- a/packages/frontend/core/src/components/page-list/view/edit-collection/use-filter.tsx +++ b/packages/frontend/core/src/components/page-list/view/edit-collection/use-filter.tsx @@ -1,10 +1,12 @@ import type { Filter } from '@affine/env/filter'; -import type { PageMeta } from '@blocksuite/store'; import { type MouseEvent, useCallback, useState } from 'react'; -import { filterPageByRules } from '../../use-collection-manager'; +import { + filterPageByRules, + type PageDataForFilter, +} from '../../use-collection-manager'; -export const useFilter = (list: PageMeta[]) => { +export const useFilter = (list: PageDataForFilter[]) => { const [filters, changeFilters] = useState([]); const [showFilter, setShowFilter] = useState(false); const clickFilter = useCallback( @@ -30,11 +32,13 @@ export const useFilter = (list: PageMeta[]) => { updateFilters: changeFilters, clickFilter, createFilter: onCreateFilter, - filteredList: list.filter(v => { - if (v.trash) { - return false; - } - return filterPageByRules(filters, [], v); - }), + filteredList: list + .filter(pageData => { + if (pageData.meta.trash) { + return false; + } + return filterPageByRules(filters, [], pageData); + }) + .map(pageData => pageData.meta), }; }; diff --git a/packages/frontend/core/src/components/pure/workspace-slider-bar/collections/collections-list.tsx b/packages/frontend/core/src/components/pure/workspace-slider-bar/collections/collections-list.tsx index ffe696ce6..2a85c2014 100644 --- a/packages/frontend/core/src/components/pure/workspace-slider-bar/collections/collections-list.tsx +++ b/packages/frontend/core/src/components/pure/workspace-slider-bar/collections/collections-list.tsx @@ -81,9 +81,14 @@ const CollectionRenderer = ({ [collection.allowList] ); - const pagesToRender = pages.filter( - page => filterPage(collection, page) && !page.trash - ); + const pagesToRender = pages.filter(meta => { + if (meta.trash) return false; + const pageData = { + meta, + publicMode: config.getPublicMode(meta.id), + }; + return filterPage(collection, pageData); + }); const location = useLocation(); const currentPath = location.pathname.split('?')[0]; const path = `/workspace/${workspace.id}/collection/${collection.id}`; diff --git a/packages/frontend/core/src/hooks/affine/use-all-page-list-config.tsx b/packages/frontend/core/src/hooks/affine/use-all-page-list-config.tsx index b556192d9..e83ab7673 100644 --- a/packages/frontend/core/src/hooks/affine/use-all-page-list-config.tsx +++ b/packages/frontend/core/src/hooks/affine/use-all-page-list-config.tsx @@ -12,9 +12,11 @@ import { useCallback, useMemo } from 'react'; import { usePageHelper } from '../../components/blocksuite/block-suite-page-list/utils'; import { useBlockSuiteMetaHelper } from './use-block-suite-meta-helper'; +import { usePublicPages } from './use-is-shared-page'; export const useAllPageListConfig = () => { const currentWorkspace = useService(Workspace); + const { getPublicMode } = usePublicPages(currentWorkspace); const workspace = currentWorkspace.blockSuiteWorkspace; const pageMetas = useBlockSuitePageMeta(workspace); const { isPreferredEdgeless } = usePageHelper(workspace); @@ -42,6 +44,7 @@ export const useAllPageListConfig = () => { return { allPages: pageMetas, isEdgeless: isPreferredEdgeless, + getPublicMode, workspace: currentWorkspace.blockSuiteWorkspace, getPage: id => pageMap[id], favoriteRender: page => { @@ -55,9 +58,10 @@ export const useAllPageListConfig = () => { }, }; }, [ - currentWorkspace.blockSuiteWorkspace, - isPreferredEdgeless, pageMetas, + isPreferredEdgeless, + getPublicMode, + currentWorkspace.blockSuiteWorkspace, pageMap, onToggleFavoritePage, ]); diff --git a/packages/frontend/core/src/hooks/affine/use-is-shared-page.ts b/packages/frontend/core/src/hooks/affine/use-is-shared-page.ts index bb0ad064a..08316a170 100644 --- a/packages/frontend/core/src/hooks/affine/use-is-shared-page.ts +++ b/packages/frontend/core/src/hooks/affine/use-is-shared-page.ts @@ -1,4 +1,5 @@ import { pushNotificationAtom } from '@affine/component/notification-center'; +import { WorkspaceFlavour } from '@affine/env/workspace'; import { getWorkspacePublicPagesQuery, PublicPageMode, @@ -6,6 +7,7 @@ import { revokePublicPageMutation, } from '@affine/graphql'; import { useAFFiNEI18N } from '@affine/i18n/hooks'; +import type { Workspace } from '@toeverything/infra/workspace'; import { useSetAtom } from 'jotai'; import { useCallback, useMemo } from 'react'; @@ -192,3 +194,44 @@ export function useIsSharedPage( [isSharedPage, currentShareMode, enableShare, disableShare, changeShare] ); } + +export function usePublicPages(workspace: Workspace) { + const isLocalWorkspace = workspace.flavour === WorkspaceFlavour.LOCAL; + const { data } = useQuery( + isLocalWorkspace + ? undefined + : { + query: getWorkspacePublicPagesQuery, + variables: { + workspaceId: workspace.id, + }, + } + ); + const maybeData = data as typeof data | undefined; + + const publicPages: { + id: string; + mode: PageMode; + }[] = useMemo( + () => + maybeData?.workspace.publicPages.map(i => ({ + id: i.id, + mode: i.mode === PublicPageMode.Edgeless ? 'edgeless' : 'page', + })) ?? [], + [maybeData?.workspace.publicPages] + ); + + /** + * Return `undefined` if the page is not public. + */ + const getPublicMode = useCallback( + (pageId: string) => { + return publicPages.find(i => i.id === pageId)?.mode; + }, + [publicPages] + ); + return { + publicPages, + getPublicMode, + }; +} diff --git a/packages/frontend/core/src/pages/workspace/all-page/all-page.tsx b/packages/frontend/core/src/pages/workspace/all-page/all-page.tsx index a8ddf7e77..1ca91df95 100644 --- a/packages/frontend/core/src/pages/workspace/all-page/all-page.tsx +++ b/packages/frontend/core/src/pages/workspace/all-page/all-page.tsx @@ -63,7 +63,7 @@ export const AllPage = ({ const filteredPageMetas = useFilteredPageMetas( 'all', pageMetas, - currentWorkspace.blockSuiteWorkspace + currentWorkspace ); const tagPageMetas = useMemo(() => { if (params.tagId) { diff --git a/packages/frontend/core/src/pages/workspace/trash-page.tsx b/packages/frontend/core/src/pages/workspace/trash-page.tsx index 511c65ac7..409b6a1e9 100644 --- a/packages/frontend/core/src/pages/workspace/trash-page.tsx +++ b/packages/frontend/core/src/pages/workspace/trash-page.tsx @@ -69,7 +69,7 @@ export const TrashPage = () => { const filteredPageMetas = useFilteredPageMetas( 'trash', pageMetas, - blockSuiteWorkspace + currentWorkspace ); const { restoreFromTrash, permanentlyDeletePage } = diff --git a/packages/frontend/i18n/src/resources/en.json b/packages/frontend/i18n/src/resources/en.json index deac7d1d8..5a27f56a7 100644 --- a/packages/frontend/i18n/src/resources/en.json +++ b/packages/frontend/i18n/src/resources/en.json @@ -627,6 +627,7 @@ "com.affine.filter.is empty": "is empty", "com.affine.filter.is not empty": "is not empty", "com.affine.filter.is-favourited": "Favourited", + "com.affine.filter.is-public": "Shared", "com.affine.filter.save-view": "Save View", "com.affine.filter.true": "true", "com.affine.filterList.button.add": "Add Filter",