refactor(core): favorite adapter (#6285)

1. abstraction over favourites that supports different type of resources
2. sorting abstraction
This commit is contained in:
pengx17
2024-03-29 04:04:07 +00:00
parent 296362ced1
commit 5490944d04
26 changed files with 450 additions and 213 deletions
@@ -2,13 +2,13 @@ import { toast } from '@affine/component';
import type { AllPageListConfig } from '@affine/core/components/page-list';
import { FavoriteTag } from '@affine/core/components/page-list';
import { useBlockSuiteDocMeta } from '@affine/core/hooks/use-block-suite-page-meta';
import { FavoriteItemsAdapter } from '@affine/core/modules/workspace';
import { useAFFiNEI18N } from '@affine/i18n/hooks';
import type { DocMeta } from '@blocksuite/store';
import { useService, Workspace } from '@toeverything/infra';
import { useLiveData, useService, Workspace } from '@toeverything/infra';
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 = () => {
@@ -21,22 +21,29 @@ export const useAllPageListConfig = () => {
() => Object.fromEntries(pageMetas.map(page => [page.id, page])),
[pageMetas]
);
const { toggleFavorite } = useBlockSuiteMetaHelper(
currentWorkspace.docCollection
);
const favAdapter = useService(FavoriteItemsAdapter);
const t = useAFFiNEI18N();
const favoriteItems = useLiveData(favAdapter.favorites$);
const isActive = useCallback(
(page: DocMeta) => {
return favoriteItems.some(fav => fav.id === page.id);
},
[favoriteItems]
);
const onToggleFavoritePage = useCallback(
(page: DocMeta) => {
const status = page.favorite;
toggleFavorite(page.id);
const status = isActive(page);
favAdapter.toggle(page.id, 'doc');
toast(
status
? t['com.affine.toastMessage.removedFavorites']()
: t['com.affine.toastMessage.addedFavorites']()
);
},
[t, toggleFavorite]
[favAdapter, isActive, t]
);
return useMemo<AllPageListConfig>(() => {
return {
allPages: pageMetas,
@@ -49,7 +56,7 @@ export const useAllPageListConfig = () => {
<FavoriteTag
style={{ marginRight: 8 }}
onClick={() => onToggleFavoritePage(page)}
active={!!page.favorite}
active={isActive(page)}
/>
);
},
@@ -60,6 +67,7 @@ export const useAllPageListConfig = () => {
getPublicMode,
currentWorkspace.docCollection,
pageMap,
isActive,
onToggleFavoritePage,
]);
};
@@ -19,32 +19,6 @@ export function useBlockSuiteMetaHelper(docCollection: DocCollection) {
const collectionService = useService(CollectionService);
const pageRecordList = useService(PageRecordList);
const addToFavorite = useCallback(
(pageId: string) => {
setDocMeta(pageId, {
favorite: true,
});
},
[setDocMeta]
);
const removeFromFavorite = useCallback(
(pageId: string) => {
setDocMeta(pageId, {
favorite: false,
});
},
[setDocMeta]
);
const toggleFavorite = useCallback(
(pageId: string) => {
const { favorite } = getDocMeta(pageId) ?? {};
setDocMeta(pageId, {
favorite: !favorite,
});
},
[getDocMeta, setDocMeta]
);
// TODO-Doma
// "Remove" may cause ambiguity here. Consider renaming as "moveToTrash".
const removeToTrash = useCallback(
@@ -126,7 +100,6 @@ export function useBlockSuiteMetaHelper(docCollection: DocCollection) {
setDocMeta(newPage.id, {
tags: currentPageMeta.tags,
favorite: currentPageMeta.favorite,
});
const lastDigitRegex = /\((\d+)\)$/;
@@ -157,10 +130,6 @@ export function useBlockSuiteMetaHelper(docCollection: DocCollection) {
publicPage,
cancelPublicPage,
addToFavorite,
removeFromFavorite,
toggleFavorite,
removeToTrash,
restoreFromTrash,
permanentlyDeletePage,
@@ -1,5 +1,6 @@
import { toast } from '@affine/component';
import { useDocMetaHelper } from '@affine/core/hooks/use-block-suite-page-meta';
import { FavoriteItemsAdapter } from '@affine/core/modules/workspace';
import { WorkspaceFlavour } from '@affine/env/workspace';
import { useAFFiNEI18N } from '@affine/i18n/hooks';
import { assertExists } from '@blocksuite/global/utils';
@@ -32,7 +33,9 @@ export function useRegisterBlocksuiteEditorCommands() {
assertExists(currentPage);
const pageMeta = getDocMeta(pageId);
assertExists(pageMeta);
const favorite = pageMeta.favorite ?? false;
const favAdapter = useService(FavoriteItemsAdapter);
const favorite = useLiveData(favAdapter.isFavorite$(pageId, 'doc'));
const trash = pageMeta.trash ?? false;
const setPageHistoryModalState = useSetAtom(pageHistoryModalAtom);
@@ -44,7 +47,7 @@ export function useRegisterBlocksuiteEditorCommands() {
}));
}, [pageId, setPageHistoryModalState]);
const { toggleFavorite, restoreFromTrash, duplicate } =
const { restoreFromTrash, duplicate } =
useBlockSuiteMetaHelper(docCollection);
const exportHandler = useExportPage(currentPage);
const { setTrashModal } = useTrashModalHelper(docCollection);
@@ -94,7 +97,7 @@ export function useRegisterBlocksuiteEditorCommands() {
? t['com.affine.favoritePageOperation.remove']()
: t['com.affine.favoritePageOperation.add'](),
run() {
toggleFavorite(pageId);
favAdapter.toggle(pageId, 'doc');
toast(
favorite
? t['com.affine.cmdk.affine.editor.remove-from-favourites']()
@@ -246,11 +249,11 @@ export function useRegisterBlocksuiteEditorCommands() {
pageId,
restoreFromTrash,
t,
toggleFavorite,
trash,
isCloudWorkspace,
openHistoryModal,
duplicate,
page,
favAdapter,
]);
}
@@ -1,12 +1,12 @@
import { toast } from '@affine/component';
import type { DraggableTitleCellData } from '@affine/core/components/page-list';
import { useDocMetaHelper } from '@affine/core/hooks/use-block-suite-page-meta';
import { FavoriteItemsAdapter } from '@affine/core/modules/workspace';
import { useAFFiNEI18N } from '@affine/i18n/hooks';
import type { DragEndEvent, UniqueIdentifier } from '@dnd-kit/core';
import { useService, Workspace } from '@toeverything/infra';
import { useCallback } from 'react';
import { useBlockSuiteMetaHelper } from './use-block-suite-meta-helper';
import { useTrashModalHelper } from './use-trash-modal-helper';
// Unique droppable IDs
@@ -69,10 +69,10 @@ export function getDragItemId(
export const useSidebarDrag = () => {
const t = useAFFiNEI18N();
const currentWorkspace = useService(Workspace);
const favAdapter = useService(FavoriteItemsAdapter);
const workspace = currentWorkspace.docCollection;
const { setTrashModal } = useTrashModalHelper(workspace);
const { addToFavorite, removeFromFavorite } =
useBlockSuiteMetaHelper(workspace);
const { getDocMeta } = useDocMetaHelper(workspace);
const isDropArea = useCallback(
@@ -123,7 +123,7 @@ export const useSidebarDrag = () => {
const processFavouritesDrag = useCallback(
(e: DragEndEvent) => {
const { pageId } = e.active.data.current as DraggableTitleCellData;
const isFavourited = getDocMeta(pageId)?.favorite;
const isFavourited = favAdapter.isFavorite(pageId, 'doc');
const isFavouriteDrag = String(e.over?.id).startsWith(
DropPrefix.SidebarFavorites
);
@@ -131,11 +131,11 @@ export const useSidebarDrag = () => {
return toast(t['com.affine.collection.addPage.alreadyExists']());
}
processDrag(e, DropPrefix.SidebarFavorites, pageId => {
addToFavorite(pageId);
favAdapter.set(pageId, 'doc', true);
toast(t['com.affine.cmdk.affine.editor.add-to-favourites']());
});
},
[getDocMeta, processDrag, addToFavorite, t]
[processDrag, t, favAdapter]
);
const processRemoveDrag = useCallback(
@@ -146,7 +146,7 @@ export const useSidebarDrag = () => {
if (String(e.active.id).startsWith(DragPrefix.FavouriteListItem)) {
const pageId = e.active.data.current?.pageId;
removeFromFavorite(pageId);
favAdapter.remove(pageId, 'doc');
toast(t['com.affine.cmdk.affine.editor.remove-from-favourites']());
return;
}
@@ -155,7 +155,7 @@ export const useSidebarDrag = () => {
}
},
[removeFromFavorite, t]
[favAdapter, t]
);
return useCallback(