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,
|
Created: 0,
|
||||||
Updated: 0,
|
Updated: 0,
|
||||||
'Is Favourited': false,
|
'Is Favourited': false,
|
||||||
|
'Is Public': false,
|
||||||
Tags: [],
|
Tags: [],
|
||||||
...vars,
|
...vars,
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -104,7 +104,7 @@ export const VirtualizedPageList = ({
|
|||||||
const filteredPageMetas = useFilteredPageMetas(
|
const filteredPageMetas = useFilteredPageMetas(
|
||||||
'all',
|
'all',
|
||||||
pageMetas,
|
pageMetas,
|
||||||
currentWorkspace.blockSuiteWorkspace
|
currentWorkspace
|
||||||
);
|
);
|
||||||
const pageMetasToRender = useMemo(() => {
|
const pageMetasToRender = useMemo(() => {
|
||||||
if (listItem) {
|
if (listItem) {
|
||||||
|
|||||||
@@ -15,6 +15,8 @@ const useFilterTag = ({ name }: FilterTagProps) => {
|
|||||||
return t['Tags']();
|
return t['Tags']();
|
||||||
case 'Is Favourited':
|
case 'Is Favourited':
|
||||||
return t['com.affine.filter.is-favourited']();
|
return t['com.affine.filter.is-favourited']();
|
||||||
|
case 'Is Public':
|
||||||
|
return t['com.affine.filter.is-public']();
|
||||||
case 'after':
|
case 'after':
|
||||||
return t['com.affine.filter.after']();
|
return t['com.affine.filter.after']();
|
||||||
case 'before':
|
case 'before':
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import type {
|
|||||||
VariableMap,
|
VariableMap,
|
||||||
} from '@affine/env/filter';
|
} from '@affine/env/filter';
|
||||||
import {
|
import {
|
||||||
|
CloudWorkspaceIcon,
|
||||||
CreatedIcon,
|
CreatedIcon,
|
||||||
FavoriteIcon,
|
FavoriteIcon,
|
||||||
TagsIcon,
|
TagsIcon,
|
||||||
@@ -44,6 +45,10 @@ export const variableDefineMap = {
|
|||||||
type: meta => tArray(tTag.create({ tags: meta.tags?.options ?? [] })),
|
type: meta => tArray(tTag.create({ tags: meta.tags?.options ?? [] })),
|
||||||
icon: <TagsIcon />,
|
icon: <TagsIcon />,
|
||||||
},
|
},
|
||||||
|
'Is Public': {
|
||||||
|
type: () => tBoolean.create(),
|
||||||
|
icon: <CloudWorkspaceIcon />,
|
||||||
|
},
|
||||||
// Imported: {
|
// Imported: {
|
||||||
// type: tBoolean.create(),
|
// type: tBoolean.create(),
|
||||||
// },
|
// },
|
||||||
|
|||||||
@@ -97,24 +97,30 @@ export const useCollectionManager = (collectionService: CollectionService) => {
|
|||||||
export const filterByFilterList = (filterList: Filter[], varMap: VariableMap) =>
|
export const filterByFilterList = (filterList: Filter[], varMap: VariableMap) =>
|
||||||
evalFilterList(filterList, varMap);
|
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) {
|
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);
|
return filterPageByRules(collection.filterList, collection.allowList, page);
|
||||||
};
|
};
|
||||||
export const filterPageByRules = (
|
export const filterPageByRules = (
|
||||||
rules: Filter[],
|
rules: Filter[],
|
||||||
allowList: string[],
|
allowList: string[],
|
||||||
page: PageMeta
|
{ meta, publicMode }: PageDataForFilter
|
||||||
) => {
|
) => {
|
||||||
if (allowList?.includes(page.id)) {
|
if (allowList?.includes(meta.id)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return filterByFilterList(rules, {
|
return filterByFilterList(rules, {
|
||||||
'Is Favourited': !!page.favorite,
|
'Is Favourited': !!meta.favorite,
|
||||||
Created: page.createDate,
|
'Is Public': !!publicMode,
|
||||||
Updated: page.updatedDate ?? page.createDate,
|
Created: meta.createDate,
|
||||||
Tags: page.tags,
|
Updated: meta.updatedDate ?? meta.createDate,
|
||||||
|
Tags: meta.tags,
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,8 +1,9 @@
|
|||||||
import { allPageModeSelectAtom } from '@affine/core/atoms';
|
import { allPageModeSelectAtom } from '@affine/core/atoms';
|
||||||
import { usePageHelper } from '@affine/core/components/blocksuite/block-suite-page-list/utils';
|
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 { CollectionService } from '@affine/core/modules/collection';
|
||||||
import type { BlockSuiteWorkspace } from '@affine/core/shared';
|
|
||||||
import type { PageMeta } from '@blocksuite/store';
|
import type { PageMeta } from '@blocksuite/store';
|
||||||
|
import type { Workspace } from '@toeverything/infra';
|
||||||
import { useService } from '@toeverything/infra/di';
|
import { useService } from '@toeverything/infra/di';
|
||||||
import { useAtomValue } from 'jotai';
|
import { useAtomValue } from 'jotai';
|
||||||
import { useMemo } from 'react';
|
import { useMemo } from 'react';
|
||||||
@@ -16,13 +17,14 @@ import {
|
|||||||
export const useFilteredPageMetas = (
|
export const useFilteredPageMetas = (
|
||||||
route: 'all' | 'trash',
|
route: 'all' | 'trash',
|
||||||
pageMetas: PageMeta[],
|
pageMetas: PageMeta[],
|
||||||
workspace: BlockSuiteWorkspace
|
workspace: Workspace
|
||||||
) => {
|
) => {
|
||||||
const { isPreferredEdgeless } = usePageHelper(workspace);
|
const { isPreferredEdgeless } = usePageHelper(workspace.blockSuiteWorkspace);
|
||||||
const pageMode = useAtomValue(allPageModeSelectAtom);
|
const pageMode = useAtomValue(allPageModeSelectAtom);
|
||||||
const { currentCollection, isDefault } = useCollectionManager(
|
const { currentCollection, isDefault } = useCollectionManager(
|
||||||
useService(CollectionService)
|
useService(CollectionService)
|
||||||
);
|
);
|
||||||
|
const { getPublicMode } = usePublicPages(workspace);
|
||||||
|
|
||||||
const filteredPageMetas = useMemo(
|
const filteredPageMetas = useMemo(
|
||||||
() =>
|
() =>
|
||||||
@@ -50,18 +52,23 @@ export const useFilteredPageMetas = (
|
|||||||
if (!currentCollection) {
|
if (!currentCollection) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
const pageData = {
|
||||||
|
meta: pageMeta,
|
||||||
|
publicMode: getPublicMode(pageMeta.id),
|
||||||
|
};
|
||||||
return isDefault
|
return isDefault
|
||||||
? filterPageByRules(
|
? filterPageByRules(
|
||||||
currentCollection.filterList,
|
currentCollection.filterList,
|
||||||
currentCollection.allowList,
|
currentCollection.allowList,
|
||||||
pageMeta
|
pageData
|
||||||
)
|
)
|
||||||
: filterPage(currentCollection, pageMeta);
|
: filterPage(currentCollection, pageData);
|
||||||
}),
|
}),
|
||||||
[
|
[
|
||||||
currentCollection,
|
currentCollection,
|
||||||
isDefault,
|
isDefault,
|
||||||
isPreferredEdgeless,
|
isPreferredEdgeless,
|
||||||
|
getPublicMode,
|
||||||
pageMetas,
|
pageMetas,
|
||||||
pageMode,
|
pageMode,
|
||||||
route,
|
route,
|
||||||
|
|||||||
@@ -201,6 +201,10 @@ export type AllPageListConfig = {
|
|||||||
allPages: PageMeta[];
|
allPages: PageMeta[];
|
||||||
workspace: Workspace;
|
workspace: Workspace;
|
||||||
isEdgeless: (id: string) => boolean;
|
isEdgeless: (id: string) => boolean;
|
||||||
|
/**
|
||||||
|
* Return `undefined` if the page is not public
|
||||||
|
*/
|
||||||
|
getPublicMode: (id: string) => undefined | 'page' | 'edgeless';
|
||||||
getPage: (id: string) => PageMeta | undefined;
|
getPage: (id: string) => PageMeta | undefined;
|
||||||
favoriteRender: (page: PageMeta) => ReactNode;
|
favoriteRender: (page: PageMeta) => ReactNode;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -40,7 +40,12 @@ export const PagesMode = ({
|
|||||||
clickFilter,
|
clickFilter,
|
||||||
createFilter,
|
createFilter,
|
||||||
filteredList,
|
filteredList,
|
||||||
} = useFilter(allPageListConfig.allPages);
|
} = useFilter(
|
||||||
|
allPageListConfig.allPages.map(meta => ({
|
||||||
|
meta,
|
||||||
|
publicMode: allPageListConfig.getPublicMode(meta.id),
|
||||||
|
}))
|
||||||
|
);
|
||||||
const { searchText, updateSearchText, searchedList } =
|
const { searchText, updateSearchText, searchedList } =
|
||||||
useSearch(filteredList);
|
useSearch(filteredList);
|
||||||
const clearSelected = useCallback(() => {
|
const clearSelected = useCallback(() => {
|
||||||
|
|||||||
@@ -48,18 +48,22 @@ export const RulesMode = ({
|
|||||||
setShowTips(false);
|
setShowTips(false);
|
||||||
localStorage.setItem('hide-rules-mode-include-page-tips', 'true');
|
localStorage.setItem('hide-rules-mode-include-page-tips', 'true');
|
||||||
}, []);
|
}, []);
|
||||||
allPageListConfig.allPages.forEach(v => {
|
allPageListConfig.allPages.forEach(meta => {
|
||||||
if (v.trash) {
|
if (meta.trash) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
const pageData = {
|
||||||
|
meta,
|
||||||
|
publicMode: allPageListConfig.getPublicMode(meta.id),
|
||||||
|
};
|
||||||
if (
|
if (
|
||||||
collection.filterList.length &&
|
collection.filterList.length &&
|
||||||
filterPageByRules(collection.filterList, [], v)
|
filterPageByRules(collection.filterList, [], pageData)
|
||||||
) {
|
) {
|
||||||
rulesPages.push(v);
|
rulesPages.push(meta);
|
||||||
}
|
}
|
||||||
if (collection.allowList.includes(v.id)) {
|
if (collection.allowList.includes(meta.id)) {
|
||||||
allowListPages.push(v);
|
allowListPages.push(meta);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
const { node: selectPageNode, open } = useSelectPage({ allPageListConfig });
|
const { node: selectPageNode, open } = useSelectPage({ allPageListConfig });
|
||||||
|
|||||||
@@ -42,7 +42,12 @@ export const SelectPage = ({
|
|||||||
showFilter,
|
showFilter,
|
||||||
updateFilters,
|
updateFilters,
|
||||||
filteredList,
|
filteredList,
|
||||||
} = useFilter(allPageListConfig.allPages);
|
} = useFilter(
|
||||||
|
allPageListConfig.allPages.map(meta => ({
|
||||||
|
meta,
|
||||||
|
publicMode: allPageListConfig.getPublicMode(meta.id),
|
||||||
|
}))
|
||||||
|
);
|
||||||
const { searchText, updateSearchText, searchedList } =
|
const { searchText, updateSearchText, searchedList } =
|
||||||
useSearch(filteredList);
|
useSearch(filteredList);
|
||||||
|
|
||||||
|
|||||||
@@ -1,10 +1,12 @@
|
|||||||
import type { Filter } from '@affine/env/filter';
|
import type { Filter } from '@affine/env/filter';
|
||||||
import type { PageMeta } from '@blocksuite/store';
|
|
||||||
import { type MouseEvent, useCallback, useState } from 'react';
|
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 [filters, changeFilters] = useState<Filter[]>([]);
|
||||||
const [showFilter, setShowFilter] = useState(false);
|
const [showFilter, setShowFilter] = useState(false);
|
||||||
const clickFilter = useCallback(
|
const clickFilter = useCallback(
|
||||||
@@ -30,11 +32,13 @@ export const useFilter = (list: PageMeta[]) => {
|
|||||||
updateFilters: changeFilters,
|
updateFilters: changeFilters,
|
||||||
clickFilter,
|
clickFilter,
|
||||||
createFilter: onCreateFilter,
|
createFilter: onCreateFilter,
|
||||||
filteredList: list.filter(v => {
|
filteredList: list
|
||||||
if (v.trash) {
|
.filter(pageData => {
|
||||||
return false;
|
if (pageData.meta.trash) {
|
||||||
}
|
return false;
|
||||||
return filterPageByRules(filters, [], v);
|
}
|
||||||
}),
|
return filterPageByRules(filters, [], pageData);
|
||||||
|
})
|
||||||
|
.map(pageData => pageData.meta),
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -81,9 +81,14 @@ const CollectionRenderer = ({
|
|||||||
[collection.allowList]
|
[collection.allowList]
|
||||||
);
|
);
|
||||||
|
|
||||||
const pagesToRender = pages.filter(
|
const pagesToRender = pages.filter(meta => {
|
||||||
page => filterPage(collection, page) && !page.trash
|
if (meta.trash) return false;
|
||||||
);
|
const pageData = {
|
||||||
|
meta,
|
||||||
|
publicMode: config.getPublicMode(meta.id),
|
||||||
|
};
|
||||||
|
return filterPage(collection, pageData);
|
||||||
|
});
|
||||||
const location = useLocation();
|
const location = useLocation();
|
||||||
const currentPath = location.pathname.split('?')[0];
|
const currentPath = location.pathname.split('?')[0];
|
||||||
const path = `/workspace/${workspace.id}/collection/${collection.id}`;
|
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 { usePageHelper } from '../../components/blocksuite/block-suite-page-list/utils';
|
||||||
import { useBlockSuiteMetaHelper } from './use-block-suite-meta-helper';
|
import { useBlockSuiteMetaHelper } from './use-block-suite-meta-helper';
|
||||||
|
import { usePublicPages } from './use-is-shared-page';
|
||||||
|
|
||||||
export const useAllPageListConfig = () => {
|
export const useAllPageListConfig = () => {
|
||||||
const currentWorkspace = useService(Workspace);
|
const currentWorkspace = useService(Workspace);
|
||||||
|
const { getPublicMode } = usePublicPages(currentWorkspace);
|
||||||
const workspace = currentWorkspace.blockSuiteWorkspace;
|
const workspace = currentWorkspace.blockSuiteWorkspace;
|
||||||
const pageMetas = useBlockSuitePageMeta(workspace);
|
const pageMetas = useBlockSuitePageMeta(workspace);
|
||||||
const { isPreferredEdgeless } = usePageHelper(workspace);
|
const { isPreferredEdgeless } = usePageHelper(workspace);
|
||||||
@@ -42,6 +44,7 @@ export const useAllPageListConfig = () => {
|
|||||||
return {
|
return {
|
||||||
allPages: pageMetas,
|
allPages: pageMetas,
|
||||||
isEdgeless: isPreferredEdgeless,
|
isEdgeless: isPreferredEdgeless,
|
||||||
|
getPublicMode,
|
||||||
workspace: currentWorkspace.blockSuiteWorkspace,
|
workspace: currentWorkspace.blockSuiteWorkspace,
|
||||||
getPage: id => pageMap[id],
|
getPage: id => pageMap[id],
|
||||||
favoriteRender: page => {
|
favoriteRender: page => {
|
||||||
@@ -55,9 +58,10 @@ export const useAllPageListConfig = () => {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
}, [
|
}, [
|
||||||
currentWorkspace.blockSuiteWorkspace,
|
|
||||||
isPreferredEdgeless,
|
|
||||||
pageMetas,
|
pageMetas,
|
||||||
|
isPreferredEdgeless,
|
||||||
|
getPublicMode,
|
||||||
|
currentWorkspace.blockSuiteWorkspace,
|
||||||
pageMap,
|
pageMap,
|
||||||
onToggleFavoritePage,
|
onToggleFavoritePage,
|
||||||
]);
|
]);
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import { pushNotificationAtom } from '@affine/component/notification-center';
|
import { pushNotificationAtom } from '@affine/component/notification-center';
|
||||||
|
import { WorkspaceFlavour } from '@affine/env/workspace';
|
||||||
import {
|
import {
|
||||||
getWorkspacePublicPagesQuery,
|
getWorkspacePublicPagesQuery,
|
||||||
PublicPageMode,
|
PublicPageMode,
|
||||||
@@ -6,6 +7,7 @@ import {
|
|||||||
revokePublicPageMutation,
|
revokePublicPageMutation,
|
||||||
} from '@affine/graphql';
|
} from '@affine/graphql';
|
||||||
import { useAFFiNEI18N } from '@affine/i18n/hooks';
|
import { useAFFiNEI18N } from '@affine/i18n/hooks';
|
||||||
|
import type { Workspace } from '@toeverything/infra/workspace';
|
||||||
import { useSetAtom } from 'jotai';
|
import { useSetAtom } from 'jotai';
|
||||||
import { useCallback, useMemo } from 'react';
|
import { useCallback, useMemo } from 'react';
|
||||||
|
|
||||||
@@ -192,3 +194,44 @@ export function useIsSharedPage(
|
|||||||
[isSharedPage, currentShareMode, enableShare, disableShare, changeShare]
|
[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(
|
const filteredPageMetas = useFilteredPageMetas(
|
||||||
'all',
|
'all',
|
||||||
pageMetas,
|
pageMetas,
|
||||||
currentWorkspace.blockSuiteWorkspace
|
currentWorkspace
|
||||||
);
|
);
|
||||||
const tagPageMetas = useMemo(() => {
|
const tagPageMetas = useMemo(() => {
|
||||||
if (params.tagId) {
|
if (params.tagId) {
|
||||||
|
|||||||
@@ -69,7 +69,7 @@ export const TrashPage = () => {
|
|||||||
const filteredPageMetas = useFilteredPageMetas(
|
const filteredPageMetas = useFilteredPageMetas(
|
||||||
'trash',
|
'trash',
|
||||||
pageMetas,
|
pageMetas,
|
||||||
blockSuiteWorkspace
|
currentWorkspace
|
||||||
);
|
);
|
||||||
|
|
||||||
const { restoreFromTrash, permanentlyDeletePage } =
|
const { restoreFromTrash, permanentlyDeletePage } =
|
||||||
|
|||||||
@@ -627,6 +627,7 @@
|
|||||||
"com.affine.filter.is empty": "is empty",
|
"com.affine.filter.is empty": "is empty",
|
||||||
"com.affine.filter.is not empty": "is not empty",
|
"com.affine.filter.is not empty": "is not empty",
|
||||||
"com.affine.filter.is-favourited": "Favourited",
|
"com.affine.filter.is-favourited": "Favourited",
|
||||||
|
"com.affine.filter.is-public": "Shared",
|
||||||
"com.affine.filter.save-view": "Save View",
|
"com.affine.filter.save-view": "Save View",
|
||||||
"com.affine.filter.true": "true",
|
"com.affine.filter.true": "true",
|
||||||
"com.affine.filterList.button.add": "Add Filter",
|
"com.affine.filterList.button.add": "Add Filter",
|
||||||
|
|||||||
Reference in New Issue
Block a user