feat: add shared page filter to all pages (#5540)

Co-authored-by: EYHN <cneyhn@gmail.com>
This commit is contained in:
Whitewater
2024-02-23 16:07:13 +08:00
committed by GitHub
parent 745110c799
commit 228b0d789d
17 changed files with 134 additions and 38 deletions

View File

@@ -34,6 +34,7 @@ const mockVariableMap = (vars: Partial<VariableMap>): VariableMap => {
Created: 0,
Updated: 0,
'Is Favourited': false,
'Is Public': false,
Tags: [],
...vars,
};

View File

@@ -104,7 +104,7 @@ export const VirtualizedPageList = ({
const filteredPageMetas = useFilteredPageMetas(
'all',
pageMetas,
currentWorkspace.blockSuiteWorkspace
currentWorkspace
);
const pageMetasToRender = useMemo(() => {
if (listItem) {

View File

@@ -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':

View File

@@ -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: <TagsIcon />,
},
'Is Public': {
type: () => tBoolean.create(),
icon: <CloudWorkspaceIcon />,
},
// Imported: {
// type: tBoolean.create(),
// },

View File

@@ -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,
});
};

View File

@@ -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,

View File

@@ -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;
};

View File

@@ -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(() => {

View File

@@ -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 });

View File

@@ -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);

View File

@@ -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<Filter[]>([]);
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),
};
};

View File

@@ -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}`;

View File

@@ -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,
]);

View File

@@ -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,
};
}

View File

@@ -63,7 +63,7 @@ export const AllPage = ({
const filteredPageMetas = useFilteredPageMetas(
'all',
pageMetas,
currentWorkspace.blockSuiteWorkspace
currentWorkspace
);
const tagPageMetas = useMemo(() => {
if (params.tagId) {

View File

@@ -69,7 +69,7 @@ export const TrashPage = () => {
const filteredPageMetas = useFilteredPageMetas(
'trash',
pageMetas,
blockSuiteWorkspace
currentWorkspace
);
const { restoreFromTrash, permanentlyDeletePage } =