mirror of
https://github.com/toeverything/AFFiNE.git
synced 2026-02-24 18:02:47 +08:00
feat: add shared page filter to all pages (#5540)
Co-authored-by: EYHN <cneyhn@gmail.com>
This commit is contained in:
@@ -34,6 +34,7 @@ const mockVariableMap = (vars: Partial<VariableMap>): VariableMap => {
|
||||
Created: 0,
|
||||
Updated: 0,
|
||||
'Is Favourited': false,
|
||||
'Is Public': false,
|
||||
Tags: [],
|
||||
...vars,
|
||||
};
|
||||
|
||||
@@ -104,7 +104,7 @@ export const VirtualizedPageList = ({
|
||||
const filteredPageMetas = useFilteredPageMetas(
|
||||
'all',
|
||||
pageMetas,
|
||||
currentWorkspace.blockSuiteWorkspace
|
||||
currentWorkspace
|
||||
);
|
||||
const pageMetasToRender = useMemo(() => {
|
||||
if (listItem) {
|
||||
|
||||
@@ -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':
|
||||
|
||||
@@ -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(),
|
||||
// },
|
||||
|
||||
@@ -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,
|
||||
});
|
||||
};
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
@@ -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(() => {
|
||||
|
||||
@@ -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 });
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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),
|
||||
};
|
||||
};
|
||||
|
||||
@@ -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}`;
|
||||
|
||||
@@ -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,
|
||||
]);
|
||||
|
||||
@@ -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,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -63,7 +63,7 @@ export const AllPage = ({
|
||||
const filteredPageMetas = useFilteredPageMetas(
|
||||
'all',
|
||||
pageMetas,
|
||||
currentWorkspace.blockSuiteWorkspace
|
||||
currentWorkspace
|
||||
);
|
||||
const tagPageMetas = useMemo(() => {
|
||||
if (params.tagId) {
|
||||
|
||||
@@ -69,7 +69,7 @@ export const TrashPage = () => {
|
||||
const filteredPageMetas = useFilteredPageMetas(
|
||||
'trash',
|
||||
pageMetas,
|
||||
blockSuiteWorkspace
|
||||
currentWorkspace
|
||||
);
|
||||
|
||||
const { restoreFromTrash, permanentlyDeletePage } =
|
||||
|
||||
Reference in New Issue
Block a user