mirror of
https://github.com/toeverything/AFFiNE.git
synced 2026-08-06 11:59:51 +08:00
refactor(core): adapter to new journal and property (#8508)
remove old WorkspacePropertyAdapter add JournalService
This commit is contained in:
@@ -43,6 +43,12 @@ export class DocRecord extends Entity<{ id: string }> {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
setProperty(propertyId: string, value: string) {
|
||||||
|
this.docPropertiesStore.updateDocProperties(this.id, {
|
||||||
|
[propertyId]: value,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
setMeta(meta: Partial<DocMeta>): void {
|
setMeta(meta: Partial<DocMeta>): void {
|
||||||
this.docsStore.setDocMeta(this.id, meta);
|
this.docsStore.setDocMeta(this.id, meta);
|
||||||
}
|
}
|
||||||
|
|||||||
+3
-3
@@ -1,5 +1,5 @@
|
|||||||
import { DocDisplayMetaService } from '@affine/core/modules/doc-display-meta';
|
import { DocDisplayMetaService } from '@affine/core/modules/doc-display-meta';
|
||||||
import { WorkspacePropertiesAdapter } from '@affine/core/modules/properties';
|
import { JournalService } from '@affine/core/modules/journal';
|
||||||
import { I18n } from '@affine/i18n';
|
import { I18n } from '@affine/i18n';
|
||||||
import { track } from '@affine/track';
|
import { track } from '@affine/track';
|
||||||
import type { EditorHost } from '@blocksuite/affine/block-std';
|
import type { EditorHost } from '@blocksuite/affine/block-std';
|
||||||
@@ -21,9 +21,9 @@ export function createLinkedWidgetConfig(
|
|||||||
) => {
|
) => {
|
||||||
const currentWorkspace = framework.get(WorkspaceService).workspace;
|
const currentWorkspace = framework.get(WorkspaceService).workspace;
|
||||||
const rawMetas = currentWorkspace.docCollection.meta.docMetas;
|
const rawMetas = currentWorkspace.docCollection.meta.docMetas;
|
||||||
const adapter = framework.get(WorkspacePropertiesAdapter);
|
const journalService = framework.get(JournalService);
|
||||||
const isJournal = (d: DocMeta) =>
|
const isJournal = (d: DocMeta) =>
|
||||||
!!adapter.getJournalPageDateString(d.id);
|
!!journalService.journalDate$(d.id).value;
|
||||||
|
|
||||||
const docDisplayMetaService = framework.get(DocDisplayMetaService);
|
const docDisplayMetaService = framework.get(DocDisplayMetaService);
|
||||||
const docMetas = rawMetas
|
const docMetas = rawMetas
|
||||||
|
|||||||
+1
-1
@@ -1,5 +1,5 @@
|
|||||||
import { FavoriteTag } from '@affine/core/components/page-list';
|
import { FavoriteTag } from '@affine/core/components/page-list';
|
||||||
import { CompatibleFavoriteItemsAdapter } from '@affine/core/modules/properties';
|
import { CompatibleFavoriteItemsAdapter } from '@affine/core/modules/favorite';
|
||||||
import { toast } from '@affine/core/utils';
|
import { toast } from '@affine/core/utils';
|
||||||
import { useI18n } from '@affine/i18n';
|
import { useI18n } from '@affine/i18n';
|
||||||
import { track } from '@affine/track';
|
import { track } from '@affine/track';
|
||||||
|
|||||||
@@ -9,12 +9,11 @@ import {
|
|||||||
Scrollable,
|
Scrollable,
|
||||||
} from '@affine/component';
|
} from '@affine/component';
|
||||||
import { useNavigateHelper } from '@affine/core/components/hooks/use-navigate-helper';
|
import { useNavigateHelper } from '@affine/core/components/hooks/use-navigate-helper';
|
||||||
import { WorkspaceLegacyProperties } from '@affine/core/modules/properties';
|
|
||||||
import type { Tag } from '@affine/core/modules/tag';
|
import type { Tag } from '@affine/core/modules/tag';
|
||||||
import { DeleteTagConfirmModal, TagService } from '@affine/core/modules/tag';
|
import { DeleteTagConfirmModal, TagService } from '@affine/core/modules/tag';
|
||||||
import { useI18n } from '@affine/i18n';
|
import { useI18n } from '@affine/i18n';
|
||||||
import { DeleteIcon, MoreHorizontalIcon, TagsIcon } from '@blocksuite/icons/rc';
|
import { DeleteIcon, MoreHorizontalIcon, TagsIcon } from '@blocksuite/icons/rc';
|
||||||
import { useLiveData, useService } from '@toeverything/infra';
|
import { useLiveData, useService, WorkspaceService } from '@toeverything/infra';
|
||||||
import clsx from 'clsx';
|
import clsx from 'clsx';
|
||||||
import { clamp } from 'lodash-es';
|
import { clamp } from 'lodash-es';
|
||||||
import type { HTMLAttributes, PropsWithChildren } from 'react';
|
import type { HTMLAttributes, PropsWithChildren } from 'react';
|
||||||
@@ -84,7 +83,7 @@ export const EditTagMenu = ({
|
|||||||
onTagDelete: (tagIds: string[]) => void;
|
onTagDelete: (tagIds: string[]) => void;
|
||||||
}>) => {
|
}>) => {
|
||||||
const t = useI18n();
|
const t = useI18n();
|
||||||
const legacyProperties = useService(WorkspaceLegacyProperties);
|
const workspaceService = useService(WorkspaceService);
|
||||||
const tagService = useService(TagService);
|
const tagService = useService(TagService);
|
||||||
const tagList = tagService.tagList;
|
const tagList = tagService.tagList;
|
||||||
const tag = useLiveData(tagList.tagByTagId$(tagId));
|
const tag = useLiveData(tagList.tagByTagId$(tagId));
|
||||||
@@ -135,7 +134,7 @@ export const EditTagMenu = ({
|
|||||||
<MenuItem
|
<MenuItem
|
||||||
prefixIcon={<TagsIcon />}
|
prefixIcon={<TagsIcon />}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
navigate.jumpToTag(legacyProperties.workspaceId, tag?.id || '');
|
navigate.jumpToTag(workspaceService.workspace.id, tag?.id || '');
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{t['com.affine.page-properties.tags.open-tags-page']()}
|
{t['com.affine.page-properties.tags.open-tags-page']()}
|
||||||
@@ -171,7 +170,7 @@ export const EditTagMenu = ({
|
|||||||
),
|
),
|
||||||
} satisfies Partial<MenuProps>;
|
} satisfies Partial<MenuProps>;
|
||||||
}, [
|
}, [
|
||||||
legacyProperties.workspaceId,
|
workspaceService,
|
||||||
navigate,
|
navigate,
|
||||||
onTagDelete,
|
onTagDelete,
|
||||||
t,
|
t,
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import { toast } from '@affine/component';
|
import { toast } from '@affine/component';
|
||||||
import { useBlockSuiteDocMeta } from '@affine/core/components/hooks/use-block-suite-page-meta';
|
import { useBlockSuiteDocMeta } from '@affine/core/components/hooks/use-block-suite-page-meta';
|
||||||
import { FavoriteTag } from '@affine/core/components/page-list/components/favorite-tag';
|
import { FavoriteTag } from '@affine/core/components/page-list/components/favorite-tag';
|
||||||
import { CompatibleFavoriteItemsAdapter } from '@affine/core/modules/properties';
|
import { CompatibleFavoriteItemsAdapter } from '@affine/core/modules/favorite';
|
||||||
import { ShareDocsListService } from '@affine/core/modules/share-doc';
|
import { ShareDocsListService } from '@affine/core/modules/share-doc';
|
||||||
import { PublicPageMode } from '@affine/graphql';
|
import { PublicPageMode } from '@affine/graphql';
|
||||||
import { useI18n } from '@affine/i18n';
|
import { useI18n } from '@affine/i18n';
|
||||||
|
|||||||
+1
-1
@@ -5,7 +5,7 @@ import {
|
|||||||
} from '@affine/core/commands';
|
} from '@affine/core/commands';
|
||||||
import { DocInfoService } from '@affine/core/modules/doc-info';
|
import { DocInfoService } from '@affine/core/modules/doc-info';
|
||||||
import type { Editor } from '@affine/core/modules/editor';
|
import type { Editor } from '@affine/core/modules/editor';
|
||||||
import { CompatibleFavoriteItemsAdapter } from '@affine/core/modules/properties';
|
import { CompatibleFavoriteItemsAdapter } from '@affine/core/modules/favorite';
|
||||||
import { WorkspaceFlavour } from '@affine/env/workspace';
|
import { WorkspaceFlavour } from '@affine/env/workspace';
|
||||||
import { useI18n } from '@affine/i18n';
|
import { useI18n } from '@affine/i18n';
|
||||||
import { track } from '@affine/track';
|
import { track } from '@affine/track';
|
||||||
|
|||||||
@@ -1,39 +0,0 @@
|
|||||||
import { useService } from '@toeverything/infra';
|
|
||||||
import { useDebouncedState } from 'foxact/use-debounced-state';
|
|
||||||
import { useEffect } from 'react';
|
|
||||||
|
|
||||||
import { WorkspacePropertiesAdapter } from '../../modules/properties';
|
|
||||||
|
|
||||||
function getProxy<T extends object>(obj: T) {
|
|
||||||
return new Proxy(obj, {});
|
|
||||||
}
|
|
||||||
|
|
||||||
const useReactiveAdapter = (adapter: WorkspacePropertiesAdapter) => {
|
|
||||||
// hack: delay proxy creation to avoid unnecessary re-render + render in another component issue
|
|
||||||
const [proxy, setProxy] = useDebouncedState(adapter, 0);
|
|
||||||
useEffect(() => {
|
|
||||||
// TODO(@Peng): track which properties are used and then filter by property path change
|
|
||||||
// using Y.YEvent.path
|
|
||||||
function observe() {
|
|
||||||
setProxy(getProxy(adapter));
|
|
||||||
}
|
|
||||||
const disposables: (() => void)[] = [];
|
|
||||||
disposables.push(
|
|
||||||
adapter.workspace.docCollection.meta.docMetaUpdated.on(observe).dispose
|
|
||||||
);
|
|
||||||
adapter.properties.observeDeep(observe);
|
|
||||||
disposables.push(() => adapter.properties.unobserveDeep(observe));
|
|
||||||
return () => {
|
|
||||||
for (const dispose of disposables) {
|
|
||||||
dispose();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}, [adapter, setProxy]);
|
|
||||||
|
|
||||||
return proxy;
|
|
||||||
};
|
|
||||||
|
|
||||||
export function useCurrentWorkspacePropertiesAdapter() {
|
|
||||||
const adapter = useService(WorkspacePropertiesAdapter);
|
|
||||||
return useReactiveAdapter(adapter);
|
|
||||||
}
|
|
||||||
@@ -1,4 +1,5 @@
|
|||||||
import { EditorSettingService } from '@affine/core/modules/editor-settting';
|
import { EditorSettingService } from '@affine/core/modules/editor-settting';
|
||||||
|
import { JournalService } from '@affine/core/modules/journal';
|
||||||
import { i18nTime } from '@affine/i18n';
|
import { i18nTime } from '@affine/i18n';
|
||||||
import { track } from '@affine/track';
|
import { track } from '@affine/track';
|
||||||
import { type DocCollection, Text } from '@blocksuite/affine/store';
|
import { type DocCollection, Text } from '@blocksuite/affine/store';
|
||||||
@@ -13,7 +14,6 @@ import dayjs from 'dayjs';
|
|||||||
import { useCallback, useMemo } from 'react';
|
import { useCallback, useMemo } from 'react';
|
||||||
|
|
||||||
import { WorkbenchService } from '../../modules/workbench';
|
import { WorkbenchService } from '../../modules/workbench';
|
||||||
import { useCurrentWorkspacePropertiesAdapter } from './use-affine-adapter';
|
|
||||||
import { useDocCollectionHelper } from './use-block-suite-workspace-helper';
|
import { useDocCollectionHelper } from './use-block-suite-workspace-helper';
|
||||||
|
|
||||||
type MaybeDate = Date | string | number;
|
type MaybeDate = Date | string | number;
|
||||||
@@ -30,14 +30,16 @@ function toDayjs(j?: string | false) {
|
|||||||
return day;
|
return day;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @deprecated use `JournalService` directly
|
||||||
|
*/
|
||||||
export const useJournalHelper = (docCollection: DocCollection) => {
|
export const useJournalHelper = (docCollection: DocCollection) => {
|
||||||
const bsWorkspaceHelper = useDocCollectionHelper(docCollection);
|
const bsWorkspaceHelper = useDocCollectionHelper(docCollection);
|
||||||
const { docsService, editorSettingService } = useServices({
|
const { docsService, editorSettingService, journalService } = useServices({
|
||||||
DocsService,
|
DocsService,
|
||||||
EditorSettingService,
|
EditorSettingService,
|
||||||
|
JournalService,
|
||||||
});
|
});
|
||||||
const adapter = useCurrentWorkspacePropertiesAdapter();
|
|
||||||
const { isPageJournal } = useJournalInfoHelper();
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @internal
|
* @internal
|
||||||
@@ -62,10 +64,10 @@ export const useJournalHelper = (docCollection: DocCollection) => {
|
|||||||
note: editorSettingService.editorSetting.get('affine:note'),
|
note: editorSettingService.editorSetting.get('affine:note'),
|
||||||
};
|
};
|
||||||
initDocFromProps(page, docProps);
|
initDocFromProps(page, docProps);
|
||||||
adapter.setJournalPageDateString(page.id, title);
|
journalService.setJournalDate(page.id, title);
|
||||||
return page;
|
return page;
|
||||||
},
|
},
|
||||||
[adapter, bsWorkspaceHelper, docsService.list, editorSettingService]
|
[journalService, bsWorkspaceHelper, docsService.list, editorSettingService]
|
||||||
);
|
);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -73,17 +75,11 @@ export const useJournalHelper = (docCollection: DocCollection) => {
|
|||||||
*/
|
*/
|
||||||
const getJournalsByDate = useCallback(
|
const getJournalsByDate = useCallback(
|
||||||
(maybeDate: MaybeDate) => {
|
(maybeDate: MaybeDate) => {
|
||||||
const day = dayjs(maybeDate);
|
return journalService.getJournalsByDate(
|
||||||
return Array.from(docCollection.docs.values()).filter(page => {
|
dayjs(maybeDate).format(JOURNAL_DATE_FORMAT)
|
||||||
const pageId = page.id;
|
);
|
||||||
if (!isPageJournal(pageId)) return false;
|
|
||||||
if (page.meta?.trash) return false;
|
|
||||||
const journalDate = adapter.getJournalPageDateString(page.id);
|
|
||||||
if (!journalDate) return false;
|
|
||||||
return day.isSame(journalDate, 'day');
|
|
||||||
});
|
|
||||||
},
|
},
|
||||||
[adapter, isPageJournal, docCollection.docs]
|
[journalService]
|
||||||
);
|
);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -92,34 +88,18 @@ export const useJournalHelper = (docCollection: DocCollection) => {
|
|||||||
const getJournalByDate = useCallback(
|
const getJournalByDate = useCallback(
|
||||||
(maybeDate: MaybeDate) => {
|
(maybeDate: MaybeDate) => {
|
||||||
const pages = getJournalsByDate(maybeDate);
|
const pages = getJournalsByDate(maybeDate);
|
||||||
if (pages.length) return pages[0].getDoc();
|
if (pages.length) return pages[0];
|
||||||
return _createJournal(maybeDate);
|
return _createJournal(maybeDate);
|
||||||
},
|
},
|
||||||
[_createJournal, getJournalsByDate]
|
[_createJournal, getJournalsByDate]
|
||||||
);
|
);
|
||||||
|
|
||||||
const appendContentToToday = useCallback(
|
|
||||||
async (content: string) => {
|
|
||||||
if (!content) return;
|
|
||||||
const page = getJournalByDate(dayjs().format(JOURNAL_DATE_FORMAT));
|
|
||||||
if (!page) return;
|
|
||||||
const blockId = page.addBlock(
|
|
||||||
'affine:paragraph',
|
|
||||||
{ text: new page.Text(content) },
|
|
||||||
page.getBlockByFlavour('affine:note')[0].id
|
|
||||||
);
|
|
||||||
return { page, blockId };
|
|
||||||
},
|
|
||||||
[getJournalByDate]
|
|
||||||
);
|
|
||||||
|
|
||||||
return useMemo(
|
return useMemo(
|
||||||
() => ({
|
() => ({
|
||||||
getJournalsByDate,
|
getJournalsByDate,
|
||||||
getJournalByDate,
|
getJournalByDate,
|
||||||
appendContentToToday,
|
|
||||||
}),
|
}),
|
||||||
[getJournalsByDate, getJournalByDate, appendContentToToday]
|
[getJournalsByDate, getJournalByDate]
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -164,31 +144,33 @@ export const useJournalRouteHelper = (docCollection: DocCollection) => {
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
// get journal info that don't rely on `docCollection`
|
/**
|
||||||
|
* @deprecated use `JournalService` directly
|
||||||
|
*/
|
||||||
export const useJournalInfoHelper = (pageId?: string | null) => {
|
export const useJournalInfoHelper = (pageId?: string | null) => {
|
||||||
const adapter = useCurrentWorkspacePropertiesAdapter();
|
const journalService = useService(JournalService);
|
||||||
|
|
||||||
const isPageJournal = useCallback(
|
const isPageJournal = useCallback(
|
||||||
(pageId: string) => {
|
(pageId: string) => {
|
||||||
return !!adapter.getJournalPageDateString(pageId);
|
return !!journalService.journalDate$(pageId).value;
|
||||||
},
|
},
|
||||||
[adapter]
|
[journalService]
|
||||||
);
|
);
|
||||||
|
|
||||||
const isPageTodayJournal = useCallback(
|
const isPageTodayJournal = useCallback(
|
||||||
(pageId: string) => {
|
(pageId: string) => {
|
||||||
const date = dayjs().format(JOURNAL_DATE_FORMAT);
|
const date = dayjs().format(JOURNAL_DATE_FORMAT);
|
||||||
const d = adapter.getJournalPageDateString(pageId);
|
const d = journalService.journalDate$(pageId).value;
|
||||||
return isPageJournal(pageId) && d === date;
|
return isPageJournal(pageId) && d === date;
|
||||||
},
|
},
|
||||||
[adapter, isPageJournal]
|
[isPageJournal, journalService]
|
||||||
);
|
);
|
||||||
|
|
||||||
const getJournalDateString = useCallback(
|
const getJournalDateString = useCallback(
|
||||||
(pageId: string) => {
|
(pageId: string) => {
|
||||||
return adapter.getJournalPageDateString(pageId);
|
return journalService.journalDate$(pageId).value;
|
||||||
},
|
},
|
||||||
[adapter]
|
[journalService]
|
||||||
);
|
);
|
||||||
|
|
||||||
const getLocalizedJournalDateString = useCallback(
|
const getLocalizedJournalDateString = useCallback(
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { toast } from '@affine/component';
|
import { toast } from '@affine/component';
|
||||||
import { CollectionService } from '@affine/core/modules/collection';
|
import { CollectionService } from '@affine/core/modules/collection';
|
||||||
import { CompatibleFavoriteItemsAdapter } from '@affine/core/modules/properties';
|
import { CompatibleFavoriteItemsAdapter } from '@affine/core/modules/favorite';
|
||||||
import { useI18n } from '@affine/i18n';
|
import { useI18n } from '@affine/i18n';
|
||||||
import { useLiveData, useService, WorkspaceService } from '@toeverything/infra';
|
import { useLiveData, useService, WorkspaceService } from '@toeverything/infra';
|
||||||
import { useCallback, useMemo, useState } from 'react';
|
import { useCallback, useMemo, useState } from 'react';
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { CompatibleFavoriteItemsAdapter } from '@affine/core/modules/properties';
|
import { CompatibleFavoriteItemsAdapter } from '@affine/core/modules/favorite';
|
||||||
import type { Tag } from '@affine/core/modules/tag';
|
import type { Tag } from '@affine/core/modules/tag';
|
||||||
import { TagService } from '@affine/core/modules/tag';
|
import { TagService } from '@affine/core/modules/tag';
|
||||||
import { useI18n } from '@affine/i18n';
|
import { useI18n } from '@affine/i18n';
|
||||||
|
|||||||
@@ -9,8 +9,10 @@ import { useBlockSuiteMetaHelper } from '@affine/core/components/hooks/affine/us
|
|||||||
import { useTrashModalHelper } from '@affine/core/components/hooks/affine/use-trash-modal-helper';
|
import { useTrashModalHelper } from '@affine/core/components/hooks/affine/use-trash-modal-helper';
|
||||||
import { useCatchEventCallback } from '@affine/core/components/hooks/use-catch-event-hook';
|
import { useCatchEventCallback } from '@affine/core/components/hooks/use-catch-event-hook';
|
||||||
import { DocInfoService } from '@affine/core/modules/doc-info';
|
import { DocInfoService } from '@affine/core/modules/doc-info';
|
||||||
import { FavoriteService } from '@affine/core/modules/favorite';
|
import {
|
||||||
import { CompatibleFavoriteItemsAdapter } from '@affine/core/modules/properties';
|
CompatibleFavoriteItemsAdapter,
|
||||||
|
FavoriteService,
|
||||||
|
} from '@affine/core/modules/favorite';
|
||||||
import { WorkbenchService } from '@affine/core/modules/workbench';
|
import { WorkbenchService } from '@affine/core/modules/workbench';
|
||||||
import type { Collection, DeleteCollectionInfo } from '@affine/env/filter';
|
import type { Collection, DeleteCollectionInfo } from '@affine/env/filter';
|
||||||
import { useI18n } from '@affine/i18n';
|
import { useI18n } from '@affine/i18n';
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { CompatibleFavoriteItemsAdapter } from '@affine/core/modules/properties';
|
import { CompatibleFavoriteItemsAdapter } from '@affine/core/modules/favorite';
|
||||||
import { ShareDocsListService } from '@affine/core/modules/share-doc';
|
import { ShareDocsListService } from '@affine/core/modules/share-doc';
|
||||||
import type { Collection, Filter } from '@affine/env/filter';
|
import type { Collection, Filter } from '@affine/env/filter';
|
||||||
import { PublicPageMode } from '@affine/graphql';
|
import { PublicPageMode } from '@affine/graphql';
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import type { MenuItemProps } from '@affine/component';
|
import type { MenuItemProps } from '@affine/component';
|
||||||
import { Menu, MenuItem } from '@affine/component';
|
import { Menu, MenuItem } from '@affine/component';
|
||||||
import { useDeleteCollectionInfo } from '@affine/core/components/hooks/affine/use-delete-collection-info';
|
import { useDeleteCollectionInfo } from '@affine/core/components/hooks/affine/use-delete-collection-info';
|
||||||
import { CompatibleFavoriteItemsAdapter } from '@affine/core/modules/properties';
|
import { CompatibleFavoriteItemsAdapter } from '@affine/core/modules/favorite';
|
||||||
import { WorkbenchService } from '@affine/core/modules/workbench';
|
import { WorkbenchService } from '@affine/core/modules/workbench';
|
||||||
import type { Collection } from '@affine/env/filter';
|
import type { Collection } from '@affine/env/filter';
|
||||||
import { useI18n } from '@affine/i18n';
|
import { useI18n } from '@affine/i18n';
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import { Button, IconButton, Tooltip } from '@affine/component';
|
import { Button, IconButton, Tooltip } from '@affine/component';
|
||||||
import { CompatibleFavoriteItemsAdapter } from '@affine/core/modules/properties';
|
import { CompatibleFavoriteItemsAdapter } from '@affine/core/modules/favorite';
|
||||||
import type { Collection } from '@affine/env/filter';
|
import type { Collection } from '@affine/env/filter';
|
||||||
import { Trans, useI18n } from '@affine/i18n';
|
import { Trans, useI18n } from '@affine/i18n';
|
||||||
import type { DocMeta } from '@blocksuite/affine/store';
|
import type { DocMeta } from '@blocksuite/affine/store';
|
||||||
|
|||||||
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
import { IconButton, Menu, toast } from '@affine/component';
|
import { IconButton, Menu, toast } from '@affine/component';
|
||||||
import { useBlockSuiteDocMeta } from '@affine/core/components/hooks/use-block-suite-page-meta';
|
import { useBlockSuiteDocMeta } from '@affine/core/components/hooks/use-block-suite-page-meta';
|
||||||
import { CompatibleFavoriteItemsAdapter } from '@affine/core/modules/properties';
|
import { CompatibleFavoriteItemsAdapter } from '@affine/core/modules/favorite';
|
||||||
import { ShareDocsListService } from '@affine/core/modules/share-doc';
|
import { ShareDocsListService } from '@affine/core/modules/share-doc';
|
||||||
import { PublicPageMode } from '@affine/graphql';
|
import { PublicPageMode } from '@affine/graphql';
|
||||||
import { Trans, useI18n } from '@affine/i18n';
|
import { Trans, useI18n } from '@affine/i18n';
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import { IconButton } from '@affine/component';
|
|||||||
import { useCatchEventCallback } from '@affine/core/components/hooks/use-catch-event-hook';
|
import { useCatchEventCallback } from '@affine/core/components/hooks/use-catch-event-hook';
|
||||||
import { PagePreview } from '@affine/core/components/page-list/page-content-preview';
|
import { PagePreview } from '@affine/core/components/page-list/page-content-preview';
|
||||||
import { IsFavoriteIcon } from '@affine/core/components/pure/icons';
|
import { IsFavoriteIcon } from '@affine/core/components/pure/icons';
|
||||||
import { CompatibleFavoriteItemsAdapter } from '@affine/core/modules/properties';
|
import { CompatibleFavoriteItemsAdapter } from '@affine/core/modules/favorite';
|
||||||
import {
|
import {
|
||||||
WorkbenchLink,
|
WorkbenchLink,
|
||||||
type WorkbenchLinkProps,
|
type WorkbenchLinkProps,
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import { IconButton } from '@affine/component';
|
import { IconButton } from '@affine/component';
|
||||||
import type { CollectionMeta } from '@affine/core/components/page-list';
|
import type { CollectionMeta } from '@affine/core/components/page-list';
|
||||||
import { IsFavoriteIcon } from '@affine/core/components/pure/icons';
|
import { IsFavoriteIcon } from '@affine/core/components/pure/icons';
|
||||||
import { CompatibleFavoriteItemsAdapter } from '@affine/core/modules/properties';
|
import { CompatibleFavoriteItemsAdapter } from '@affine/core/modules/favorite';
|
||||||
import { WorkbenchLink } from '@affine/core/modules/workbench';
|
import { WorkbenchLink } from '@affine/core/modules/workbench';
|
||||||
import { ViewLayersIcon } from '@blocksuite/icons/rc';
|
import { ViewLayersIcon } from '@blocksuite/icons/rc';
|
||||||
import { useLiveData, useService } from '@toeverything/infra';
|
import { useLiveData, useService } from '@toeverything/infra';
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { IconButton } from '@affine/component';
|
import { IconButton } from '@affine/component';
|
||||||
import { IsFavoriteIcon } from '@affine/core/components/pure/icons';
|
import { IsFavoriteIcon } from '@affine/core/components/pure/icons';
|
||||||
import { CompatibleFavoriteItemsAdapter } from '@affine/core/modules/properties';
|
import { CompatibleFavoriteItemsAdapter } from '@affine/core/modules/favorite';
|
||||||
import type { Tag } from '@affine/core/modules/tag';
|
import type { Tag } from '@affine/core/modules/tag';
|
||||||
import { WorkbenchLink } from '@affine/core/modules/workbench';
|
import { WorkbenchLink } from '@affine/core/modules/workbench';
|
||||||
import { useLiveData, useService } from '@toeverything/infra';
|
import { useLiveData, useService } from '@toeverything/infra';
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import {
|
|||||||
WorkspaceScope,
|
WorkspaceScope,
|
||||||
} from '@toeverything/infra';
|
} from '@toeverything/infra';
|
||||||
|
|
||||||
import { WorkspacePropertiesAdapter } from '../properties';
|
import { JournalService } from '../journal';
|
||||||
import { DocDisplayMetaService } from './services/doc-display-meta';
|
import { DocDisplayMetaService } from './services/doc-display-meta';
|
||||||
|
|
||||||
export { DocDisplayMetaService };
|
export { DocDisplayMetaService };
|
||||||
@@ -14,7 +14,7 @@ export function configureDocDisplayMetaModule(framework: Framework) {
|
|||||||
framework
|
framework
|
||||||
.scope(WorkspaceScope)
|
.scope(WorkspaceScope)
|
||||||
.service(DocDisplayMetaService, [
|
.service(DocDisplayMetaService, [
|
||||||
WorkspacePropertiesAdapter,
|
JournalService,
|
||||||
DocsService,
|
DocsService,
|
||||||
FeatureFlagService,
|
FeatureFlagService,
|
||||||
]);
|
]);
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ import { LiveData, Service } from '@toeverything/infra';
|
|||||||
import type { Dayjs } from 'dayjs';
|
import type { Dayjs } from 'dayjs';
|
||||||
import dayjs from 'dayjs';
|
import dayjs from 'dayjs';
|
||||||
|
|
||||||
import type { WorkspacePropertiesAdapter } from '../../properties';
|
import type { JournalService } from '../../journal';
|
||||||
|
|
||||||
type IconType = 'rc' | 'lit';
|
type IconType = 'rc' | 'lit';
|
||||||
interface DocDisplayIconOptions<T extends IconType> {
|
interface DocDisplayIconOptions<T extends IconType> {
|
||||||
@@ -83,7 +83,7 @@ const icons = { rc: rcIcons, lit: litIcons } as {
|
|||||||
|
|
||||||
export class DocDisplayMetaService extends Service {
|
export class DocDisplayMetaService extends Service {
|
||||||
constructor(
|
constructor(
|
||||||
private readonly propertiesAdapter: WorkspacePropertiesAdapter,
|
private readonly journalService: JournalService,
|
||||||
private readonly docsService: DocsService,
|
private readonly docsService: DocsService,
|
||||||
private readonly featureFlagService: FeatureFlagService
|
private readonly featureFlagService: FeatureFlagService
|
||||||
) {
|
) {
|
||||||
@@ -110,7 +110,7 @@ export class DocDisplayMetaService extends Service {
|
|||||||
|
|
||||||
// journal icon
|
// journal icon
|
||||||
const journalDate = this._toDayjs(
|
const journalDate = this._toDayjs(
|
||||||
this.propertiesAdapter.getJournalPageDateString(docId)
|
this.journalService.journalDate$(docId).value
|
||||||
);
|
);
|
||||||
if (journalDate) {
|
if (journalDate) {
|
||||||
if (!options?.compareDate) return iconSet.TodayIcon;
|
if (!options?.compareDate) return iconSet.TodayIcon;
|
||||||
@@ -148,8 +148,7 @@ export class DocDisplayMetaService extends Service {
|
|||||||
const doc = get(this.docsService.list.doc$(docId));
|
const doc = get(this.docsService.list.doc$(docId));
|
||||||
const docTitle = doc ? get(doc.title$) : undefined;
|
const docTitle = doc ? get(doc.title$) : undefined;
|
||||||
|
|
||||||
const journalDateString =
|
const journalDateString = get(this.journalService.journalDate$(docId));
|
||||||
this.propertiesAdapter.getJournalPageDateString(docId);
|
|
||||||
|
|
||||||
// journal
|
// journal
|
||||||
if (journalDateString) {
|
if (journalDateString) {
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ import {
|
|||||||
useEditCollection,
|
useEditCollection,
|
||||||
} from '@affine/core/components/page-list';
|
} from '@affine/core/components/page-list';
|
||||||
import { CollectionService } from '@affine/core/modules/collection';
|
import { CollectionService } from '@affine/core/modules/collection';
|
||||||
import { CompatibleFavoriteItemsAdapter } from '@affine/core/modules/properties';
|
import { CompatibleFavoriteItemsAdapter } from '@affine/core/modules/favorite';
|
||||||
import { ShareDocsListService } from '@affine/core/modules/share-doc';
|
import { ShareDocsListService } from '@affine/core/modules/share-doc';
|
||||||
import type { AffineDNDData } from '@affine/core/types/dnd';
|
import type { AffineDNDData } from '@affine/core/types/dnd';
|
||||||
import type { Collection } from '@affine/env/filter';
|
import type { Collection } from '@affine/env/filter';
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ import { usePageHelper } from '@affine/core/components/blocksuite/block-suite-pa
|
|||||||
import { useDeleteCollectionInfo } from '@affine/core/components/hooks/affine/use-delete-collection-info';
|
import { useDeleteCollectionInfo } from '@affine/core/components/hooks/affine/use-delete-collection-info';
|
||||||
import { IsFavoriteIcon } from '@affine/core/components/pure/icons';
|
import { IsFavoriteIcon } from '@affine/core/components/pure/icons';
|
||||||
import { CollectionService } from '@affine/core/modules/collection';
|
import { CollectionService } from '@affine/core/modules/collection';
|
||||||
import { CompatibleFavoriteItemsAdapter } from '@affine/core/modules/properties';
|
import { CompatibleFavoriteItemsAdapter } from '@affine/core/modules/favorite';
|
||||||
import { WorkbenchService } from '@affine/core/modules/workbench';
|
import { WorkbenchService } from '@affine/core/modules/workbench';
|
||||||
import { useI18n } from '@affine/i18n';
|
import { useI18n } from '@affine/i18n';
|
||||||
import { track } from '@affine/track';
|
import { track } from '@affine/track';
|
||||||
|
|||||||
@@ -56,7 +56,6 @@ export const ExplorerDocNode = ({
|
|||||||
DocDisplayMetaService,
|
DocDisplayMetaService,
|
||||||
FeatureFlagService,
|
FeatureFlagService,
|
||||||
});
|
});
|
||||||
// const pageInfoAdapter = useCurrentWorkspacePropertiesAdapter();
|
|
||||||
|
|
||||||
const active =
|
const active =
|
||||||
useLiveData(globalContextService.globalContext.docId.$) === docId;
|
useLiveData(globalContextService.globalContext.docId.$) === docId;
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ import { usePageHelper } from '@affine/core/components/blocksuite/block-suite-pa
|
|||||||
import { useBlockSuiteMetaHelper } from '@affine/core/components/hooks/affine/use-block-suite-meta-helper';
|
import { useBlockSuiteMetaHelper } from '@affine/core/components/hooks/affine/use-block-suite-meta-helper';
|
||||||
import { useAsyncCallback } from '@affine/core/components/hooks/affine-async-hooks';
|
import { useAsyncCallback } from '@affine/core/components/hooks/affine-async-hooks';
|
||||||
import { IsFavoriteIcon } from '@affine/core/components/pure/icons';
|
import { IsFavoriteIcon } from '@affine/core/components/pure/icons';
|
||||||
import { CompatibleFavoriteItemsAdapter } from '@affine/core/modules/properties';
|
import { CompatibleFavoriteItemsAdapter } from '@affine/core/modules/favorite';
|
||||||
import { WorkbenchService } from '@affine/core/modules/workbench';
|
import { WorkbenchService } from '@affine/core/modules/workbench';
|
||||||
import { useI18n } from '@affine/i18n';
|
import { useI18n } from '@affine/i18n';
|
||||||
import { track } from '@affine/track';
|
import { track } from '@affine/track';
|
||||||
|
|||||||
@@ -15,11 +15,11 @@ import {
|
|||||||
useSelectDoc,
|
useSelectDoc,
|
||||||
useSelectTag,
|
useSelectTag,
|
||||||
} from '@affine/core/components/page-list/selector';
|
} from '@affine/core/components/page-list/selector';
|
||||||
|
import { CompatibleFavoriteItemsAdapter } from '@affine/core/modules/favorite';
|
||||||
import {
|
import {
|
||||||
type FolderNode,
|
type FolderNode,
|
||||||
OrganizeService,
|
OrganizeService,
|
||||||
} from '@affine/core/modules/organize';
|
} from '@affine/core/modules/organize';
|
||||||
import { CompatibleFavoriteItemsAdapter } from '@affine/core/modules/properties';
|
|
||||||
import { WorkbenchService } from '@affine/core/modules/workbench';
|
import { WorkbenchService } from '@affine/core/modules/workbench';
|
||||||
import type { AffineDNDData } from '@affine/core/types/dnd';
|
import type { AffineDNDData } from '@affine/core/types/dnd';
|
||||||
import { Unreachable } from '@affine/env/constant';
|
import { Unreachable } from '@affine/env/constant';
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { MenuItem } from '@affine/component';
|
import { MenuItem } from '@affine/component';
|
||||||
import { IsFavoriteIcon } from '@affine/core/components/pure/icons';
|
import { IsFavoriteIcon } from '@affine/core/components/pure/icons';
|
||||||
import { CompatibleFavoriteItemsAdapter } from '@affine/core/modules/properties';
|
import { CompatibleFavoriteItemsAdapter } from '@affine/core/modules/favorite';
|
||||||
import { useI18n } from '@affine/i18n';
|
import { useI18n } from '@affine/i18n';
|
||||||
import { useLiveData, useService } from '@toeverything/infra';
|
import { useLiveData, useService } from '@toeverything/infra';
|
||||||
import { useMemo } from 'react';
|
import { useMemo } from 'react';
|
||||||
|
|||||||
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
import { IconButton, useConfirmModal } from '@affine/component';
|
import { IconButton, useConfirmModal } from '@affine/component';
|
||||||
import { ExplorerTreeRoot } from '@affine/core/modules/explorer/views/tree';
|
import { ExplorerTreeRoot } from '@affine/core/modules/explorer/views/tree';
|
||||||
import { MigrationFavoriteItemsAdapter } from '@affine/core/modules/properties';
|
import { MigrationFavoriteItemsAdapter } from '@affine/core/modules/favorite';
|
||||||
import { Trans, useI18n } from '@affine/i18n';
|
import { Trans, useI18n } from '@affine/i18n';
|
||||||
import { track } from '@affine/track';
|
import { track } from '@affine/track';
|
||||||
import { BroomIcon, HelpIcon } from '@blocksuite/icons/rc';
|
import { BroomIcon, HelpIcon } from '@blocksuite/icons/rc';
|
||||||
|
|||||||
@@ -8,16 +8,26 @@ import {
|
|||||||
import { AuthService } from '../cloud';
|
import { AuthService } from '../cloud';
|
||||||
import { FavoriteList } from './entities/favorite-list';
|
import { FavoriteList } from './entities/favorite-list';
|
||||||
import { FavoriteService } from './services/favorite';
|
import { FavoriteService } from './services/favorite';
|
||||||
|
import {
|
||||||
|
CompatibleFavoriteItemsAdapter,
|
||||||
|
MigrationFavoriteItemsAdapter,
|
||||||
|
} from './services/old/adapter';
|
||||||
import { FavoriteStore } from './stores/favorite';
|
import { FavoriteStore } from './stores/favorite';
|
||||||
|
|
||||||
export { FavoriteSupportType, isFavoriteSupportType } from './constant';
|
export { FavoriteSupportType, isFavoriteSupportType } from './constant';
|
||||||
export type { FavoriteList } from './entities/favorite-list';
|
export type { FavoriteList } from './entities/favorite-list';
|
||||||
export { FavoriteService } from './services/favorite';
|
export { FavoriteService } from './services/favorite';
|
||||||
|
export {
|
||||||
|
CompatibleFavoriteItemsAdapter,
|
||||||
|
MigrationFavoriteItemsAdapter,
|
||||||
|
} from './services/old/adapter';
|
||||||
|
|
||||||
export function configureFavoriteModule(framework: Framework) {
|
export function configureFavoriteModule(framework: Framework) {
|
||||||
framework
|
framework
|
||||||
.scope(WorkspaceScope)
|
.scope(WorkspaceScope)
|
||||||
.service(FavoriteService)
|
.service(FavoriteService)
|
||||||
.entity(FavoriteList, [FavoriteStore])
|
.entity(FavoriteList, [FavoriteStore])
|
||||||
.store(FavoriteStore, [AuthService, WorkspaceDBService, WorkspaceService]);
|
.store(FavoriteStore, [AuthService, WorkspaceDBService, WorkspaceService])
|
||||||
|
.service(MigrationFavoriteItemsAdapter, [WorkspaceService])
|
||||||
|
.service(CompatibleFavoriteItemsAdapter, [FavoriteService]);
|
||||||
}
|
}
|
||||||
|
|||||||
+8
-4
@@ -6,7 +6,8 @@ import { LiveData, Service } from '@toeverything/infra';
|
|||||||
import { defaultsDeep } from 'lodash-es';
|
import { defaultsDeep } from 'lodash-es';
|
||||||
import { Observable } from 'rxjs';
|
import { Observable } from 'rxjs';
|
||||||
|
|
||||||
import type { FavoriteService, FavoriteSupportType } from '../../favorite';
|
import type { FavoriteSupportType } from '../../constant';
|
||||||
|
import type { FavoriteService } from '../favorite';
|
||||||
import {
|
import {
|
||||||
PagePropertyType,
|
PagePropertyType,
|
||||||
PageSystemPropertyId,
|
PageSystemPropertyId,
|
||||||
@@ -23,8 +24,10 @@ const AFFINE_PROPERTIES_ID = 'affine:workspace-properties';
|
|||||||
* May abstract the adapter for each property type, e.g. PagePropertiesAdapter, SchemaAdapter, etc.
|
* May abstract the adapter for each property type, e.g. PagePropertiesAdapter, SchemaAdapter, etc.
|
||||||
* So that the adapter could be more focused and easier to maintain (like assigning default values)
|
* So that the adapter could be more focused and easier to maintain (like assigning default values)
|
||||||
* However the properties for an abstraction may not be limited to a single yjs map.
|
* However the properties for an abstraction may not be limited to a single yjs map.
|
||||||
|
*
|
||||||
|
* @deprecated use docService.doc.properties$
|
||||||
*/
|
*/
|
||||||
export class WorkspacePropertiesAdapter extends Service {
|
class WorkspacePropertiesAdapter {
|
||||||
// provides a easy-to-use interface for workspace properties
|
// provides a easy-to-use interface for workspace properties
|
||||||
public readonly proxy: WorkspaceAffineProperties;
|
public readonly proxy: WorkspaceAffineProperties;
|
||||||
public readonly properties: Y.Map<any>;
|
public readonly properties: Y.Map<any>;
|
||||||
@@ -38,7 +41,6 @@ export class WorkspacePropertiesAdapter extends Service {
|
|||||||
}
|
}
|
||||||
|
|
||||||
constructor(public readonly workspaceService: WorkspaceService) {
|
constructor(public readonly workspaceService: WorkspaceService) {
|
||||||
super();
|
|
||||||
// check if properties exists, if not, create one
|
// check if properties exists, if not, create one
|
||||||
const rootDoc = workspaceService.workspace.docCollection.doc;
|
const rootDoc = workspaceService.workspace.docCollection.doc;
|
||||||
this.properties = rootDoc.getMap(AFFINE_PROPERTIES_ID);
|
this.properties = rootDoc.getMap(AFFINE_PROPERTIES_ID);
|
||||||
@@ -165,7 +167,9 @@ export class WorkspacePropertiesAdapter extends Service {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export class MigrationFavoriteItemsAdapter extends Service {
|
export class MigrationFavoriteItemsAdapter extends Service {
|
||||||
constructor(private readonly adapter: WorkspacePropertiesAdapter) {
|
adapter = new WorkspacePropertiesAdapter(this.workspaceService);
|
||||||
|
|
||||||
|
constructor(public readonly workspaceService: WorkspaceService) {
|
||||||
super();
|
super();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -16,11 +16,11 @@ import { configureFavoriteModule } from './favorite';
|
|||||||
import { configureFindInPageModule } from './find-in-page';
|
import { configureFindInPageModule } from './find-in-page';
|
||||||
import { configureI18nModule } from './i18n';
|
import { configureI18nModule } from './i18n';
|
||||||
import { configureImportTemplateModule } from './import-template';
|
import { configureImportTemplateModule } from './import-template';
|
||||||
|
import { configureJournalModule } from './journal';
|
||||||
import { configureNavigationModule } from './navigation';
|
import { configureNavigationModule } from './navigation';
|
||||||
import { configureOrganizeModule } from './organize';
|
import { configureOrganizeModule } from './organize';
|
||||||
import { configurePeekViewModule } from './peek-view';
|
import { configurePeekViewModule } from './peek-view';
|
||||||
import { configurePermissionsModule } from './permissions';
|
import { configurePermissionsModule } from './permissions';
|
||||||
import { configureWorkspacePropertiesModule } from './properties';
|
|
||||||
import { configureQuickSearchModule } from './quicksearch';
|
import { configureQuickSearchModule } from './quicksearch';
|
||||||
import { configureShareDocsModule } from './share-doc';
|
import { configureShareDocsModule } from './share-doc';
|
||||||
import { configureShareSettingModule } from './share-setting';
|
import { configureShareSettingModule } from './share-setting';
|
||||||
@@ -36,7 +36,6 @@ export function configureCommonModules(framework: Framework) {
|
|||||||
configureCollectionModule(framework);
|
configureCollectionModule(framework);
|
||||||
configureNavigationModule(framework);
|
configureNavigationModule(framework);
|
||||||
configureTagModule(framework);
|
configureTagModule(framework);
|
||||||
configureWorkspacePropertiesModule(framework);
|
|
||||||
configureCloudModule(framework);
|
configureCloudModule(framework);
|
||||||
configureQuotaModule(framework);
|
configureQuotaModule(framework);
|
||||||
configurePermissionsModule(framework);
|
configurePermissionsModule(framework);
|
||||||
@@ -61,4 +60,5 @@ export function configureCommonModules(framework: Framework) {
|
|||||||
configureUserspaceModule(framework);
|
configureUserspaceModule(framework);
|
||||||
configureDocInfoModule(framework);
|
configureDocInfoModule(framework);
|
||||||
configureAppSidebarModule(framework);
|
configureAppSidebarModule(framework);
|
||||||
|
configureJournalModule(framework);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,23 @@
|
|||||||
|
import {
|
||||||
|
DocScope,
|
||||||
|
DocService,
|
||||||
|
DocsService,
|
||||||
|
type Framework,
|
||||||
|
WorkspaceScope,
|
||||||
|
} from '@toeverything/infra';
|
||||||
|
|
||||||
|
import { JournalService } from './services/journal';
|
||||||
|
import { JournalDocService } from './services/journal-doc';
|
||||||
|
import { JournalStore } from './store/journal';
|
||||||
|
|
||||||
|
export { JournalService } from './services/journal';
|
||||||
|
export { JournalDocService } from './services/journal-doc';
|
||||||
|
|
||||||
|
export function configureJournalModule(framework: Framework) {
|
||||||
|
framework
|
||||||
|
.scope(WorkspaceScope)
|
||||||
|
.service(JournalService, [JournalStore])
|
||||||
|
.store(JournalStore, [DocsService])
|
||||||
|
.scope(DocScope)
|
||||||
|
.service(JournalDocService, [DocService, JournalService]);
|
||||||
|
}
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
import { type DocService, Service } from '@toeverything/infra';
|
||||||
|
|
||||||
|
import type { JournalService } from './journal';
|
||||||
|
|
||||||
|
export class JournalDocService extends Service {
|
||||||
|
constructor(
|
||||||
|
private readonly docService: DocService,
|
||||||
|
private readonly journalService: JournalService
|
||||||
|
) {
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
|
||||||
|
readonly journalDate$ = this.journalService.journalDate$(
|
||||||
|
this.docService.doc.id
|
||||||
|
);
|
||||||
|
|
||||||
|
setJournalDate(date: string) {
|
||||||
|
this.journalService.setJournalDate(this.docService.doc.id, date);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
import { LiveData, Service } from '@toeverything/infra';
|
||||||
|
|
||||||
|
import type { JournalStore } from '../store/journal';
|
||||||
|
|
||||||
|
export class JournalService extends Service {
|
||||||
|
constructor(private readonly store: JournalStore) {
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
|
||||||
|
journalDate$(docId: string) {
|
||||||
|
return LiveData.from(this.store.watchDocJournalDate(docId), undefined);
|
||||||
|
}
|
||||||
|
|
||||||
|
setJournalDate(docId: string, date: string) {
|
||||||
|
this.store.setDocJournalDate(docId, date);
|
||||||
|
}
|
||||||
|
|
||||||
|
getJournalsByDate(date: string) {
|
||||||
|
return this.store.getDocsByJournalDate(date);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,43 @@
|
|||||||
|
import type { DocsService } from '@toeverything/infra';
|
||||||
|
import { LiveData, Store } from '@toeverything/infra';
|
||||||
|
import type { Observable } from 'rxjs';
|
||||||
|
|
||||||
|
function isJournalString(j?: string | false) {
|
||||||
|
return j ? !!j?.match(/^\d{4}-\d{2}-\d{2}$/) : false;
|
||||||
|
}
|
||||||
|
|
||||||
|
export class JournalStore extends Store {
|
||||||
|
constructor(private readonly docsService: DocsService) {
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
|
||||||
|
watchDocJournalDate(docId: string): Observable<string | undefined> {
|
||||||
|
return LiveData.computed(get => {
|
||||||
|
const doc = get(this.docsService.list.doc$(docId));
|
||||||
|
if (!doc) {
|
||||||
|
// if doc not exists
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
const journal = get(doc.properties$.selector(p => p.journal));
|
||||||
|
if (journal && !isJournalString(journal)) {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
return journal ?? undefined;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
setDocJournalDate(docId: string, date: string) {
|
||||||
|
const doc = this.docsService.list.doc$(docId).value;
|
||||||
|
if (!doc) {
|
||||||
|
// doc not exists, do nothing
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
doc.setProperty('journal', date);
|
||||||
|
}
|
||||||
|
|
||||||
|
getDocsByJournalDate(date: string) {
|
||||||
|
return this.docsService.list.docs$.value.filter(
|
||||||
|
doc => doc.properties$.value.journal === date
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,29 +0,0 @@
|
|||||||
export {
|
|
||||||
CompatibleFavoriteItemsAdapter,
|
|
||||||
MigrationFavoriteItemsAdapter,
|
|
||||||
WorkspacePropertiesAdapter,
|
|
||||||
} from './services/adapter';
|
|
||||||
export { WorkspaceLegacyProperties } from './services/legacy-properties';
|
|
||||||
|
|
||||||
import {
|
|
||||||
type Framework,
|
|
||||||
WorkspaceScope,
|
|
||||||
WorkspaceService,
|
|
||||||
} from '@toeverything/infra';
|
|
||||||
|
|
||||||
import { FavoriteService } from '../favorite';
|
|
||||||
import {
|
|
||||||
CompatibleFavoriteItemsAdapter,
|
|
||||||
MigrationFavoriteItemsAdapter,
|
|
||||||
WorkspacePropertiesAdapter,
|
|
||||||
} from './services/adapter';
|
|
||||||
import { WorkspaceLegacyProperties } from './services/legacy-properties';
|
|
||||||
|
|
||||||
export function configureWorkspacePropertiesModule(framework: Framework) {
|
|
||||||
framework
|
|
||||||
.scope(WorkspaceScope)
|
|
||||||
.service(WorkspaceLegacyProperties, [WorkspaceService])
|
|
||||||
.service(WorkspacePropertiesAdapter, [WorkspaceService])
|
|
||||||
.service(MigrationFavoriteItemsAdapter, [WorkspacePropertiesAdapter])
|
|
||||||
.service(CompatibleFavoriteItemsAdapter, [FavoriteService]);
|
|
||||||
}
|
|
||||||
@@ -1,86 +0,0 @@
|
|||||||
import type { Tag } from '@affine/env/filter';
|
|
||||||
import type { DocsPropertiesMeta } from '@blocksuite/affine/store';
|
|
||||||
import type { WorkspaceService } from '@toeverything/infra';
|
|
||||||
import { LiveData, Service } from '@toeverything/infra';
|
|
||||||
import { Observable } from 'rxjs';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @deprecated use WorkspacePropertiesAdapter instead (later)
|
|
||||||
*/
|
|
||||||
export class WorkspaceLegacyProperties extends Service {
|
|
||||||
constructor(private readonly workspaceService: WorkspaceService) {
|
|
||||||
super();
|
|
||||||
}
|
|
||||||
|
|
||||||
get workspaceId() {
|
|
||||||
return this.workspaceService.workspace.id;
|
|
||||||
}
|
|
||||||
|
|
||||||
get properties() {
|
|
||||||
return this.workspaceService.workspace.docCollection.meta.properties;
|
|
||||||
}
|
|
||||||
get tagOptions() {
|
|
||||||
return this.properties.tags?.options ?? [];
|
|
||||||
}
|
|
||||||
|
|
||||||
updateProperties = (properties: DocsPropertiesMeta) => {
|
|
||||||
this.workspaceService.workspace.docCollection.meta.setProperties(
|
|
||||||
properties
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
subscribe(cb: () => void) {
|
|
||||||
const disposable =
|
|
||||||
this.workspaceService.workspace.docCollection.meta.docMetaUpdated.on(cb);
|
|
||||||
return disposable.dispose;
|
|
||||||
}
|
|
||||||
|
|
||||||
properties$ = LiveData.from(
|
|
||||||
new Observable<DocsPropertiesMeta>(sub => {
|
|
||||||
return this.subscribe(() => sub.next(this.properties));
|
|
||||||
}),
|
|
||||||
this.properties
|
|
||||||
);
|
|
||||||
|
|
||||||
tagOptions$ = LiveData.from(
|
|
||||||
new Observable<Tag[]>(sub => {
|
|
||||||
return this.subscribe(() => sub.next(this.tagOptions));
|
|
||||||
}),
|
|
||||||
this.tagOptions
|
|
||||||
);
|
|
||||||
|
|
||||||
updateTagOptions = (options: Tag[]) => {
|
|
||||||
this.updateProperties({
|
|
||||||
...this.properties,
|
|
||||||
tags: {
|
|
||||||
options,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
updateTagOption = (id: string, option: Tag) => {
|
|
||||||
this.updateTagOptions(this.tagOptions.map(o => (o.id === id ? option : o)));
|
|
||||||
};
|
|
||||||
|
|
||||||
removeTagOption = (id: string) => {
|
|
||||||
this.workspaceService.workspace.docCollection.doc.transact(() => {
|
|
||||||
this.updateTagOptions(this.tagOptions.filter(o => o.id !== id));
|
|
||||||
// need to remove tag from all pages
|
|
||||||
this.workspaceService.workspace.docCollection.docs.forEach(doc => {
|
|
||||||
const tags = doc.meta?.tags ?? [];
|
|
||||||
if (tags.includes(id)) {
|
|
||||||
this.updatePageTags(
|
|
||||||
doc.id,
|
|
||||||
tags.filter(t => t !== id)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
updatePageTags = (pageId: string, tags: string[]) => {
|
|
||||||
this.workspaceService.workspace.docCollection.setDocMeta(pageId, {
|
|
||||||
tags,
|
|
||||||
});
|
|
||||||
};
|
|
||||||
}
|
|
||||||
@@ -7,9 +7,9 @@ import {
|
|||||||
DocsService,
|
DocsService,
|
||||||
type Framework,
|
type Framework,
|
||||||
WorkspaceScope,
|
WorkspaceScope,
|
||||||
|
WorkspaceService,
|
||||||
} from '@toeverything/infra';
|
} from '@toeverything/infra';
|
||||||
|
|
||||||
import { WorkspaceLegacyProperties } from '../properties';
|
|
||||||
import { Tag } from './entities/tag';
|
import { Tag } from './entities/tag';
|
||||||
import { TagList } from './entities/tag-list';
|
import { TagList } from './entities/tag-list';
|
||||||
import { TagService } from './service/tag';
|
import { TagService } from './service/tag';
|
||||||
@@ -19,7 +19,7 @@ export function configureTagModule(framework: Framework) {
|
|||||||
framework
|
framework
|
||||||
.scope(WorkspaceScope)
|
.scope(WorkspaceScope)
|
||||||
.service(TagService)
|
.service(TagService)
|
||||||
.store(TagStore, [WorkspaceLegacyProperties])
|
.store(TagStore, [WorkspaceService])
|
||||||
.entity(TagList, [TagStore, DocsService])
|
.entity(TagList, [TagStore, DocsService])
|
||||||
.entity(Tag, [TagStore, DocsService]);
|
.entity(Tag, [TagStore, DocsService]);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,24 +1,43 @@
|
|||||||
import type { Tag as TagSchema } from '@affine/env/filter';
|
import type { Tag, Tag as TagSchema } from '@affine/env/filter';
|
||||||
import { Store } from '@toeverything/infra';
|
import type { DocsPropertiesMeta } from '@blocksuite/affine/store';
|
||||||
|
import type { WorkspaceService } from '@toeverything/infra';
|
||||||
|
import { LiveData, Store } from '@toeverything/infra';
|
||||||
import { nanoid } from 'nanoid';
|
import { nanoid } from 'nanoid';
|
||||||
|
import { Observable } from 'rxjs';
|
||||||
import type { WorkspaceLegacyProperties } from '../../properties';
|
|
||||||
|
|
||||||
export class TagStore extends Store {
|
export class TagStore extends Store {
|
||||||
constructor(private readonly properties: WorkspaceLegacyProperties) {
|
get properties() {
|
||||||
|
return this.workspaceService.workspace.docCollection.meta.properties;
|
||||||
|
}
|
||||||
|
get tagOptions() {
|
||||||
|
return this.properties.tags?.options ?? [];
|
||||||
|
}
|
||||||
|
|
||||||
|
tagOptions$ = LiveData.from(
|
||||||
|
new Observable<Tag[]>(sub => {
|
||||||
|
return this.subscribe(() => sub.next(this.tagOptions));
|
||||||
|
}),
|
||||||
|
this.tagOptions
|
||||||
|
);
|
||||||
|
|
||||||
|
subscribe(cb: () => void) {
|
||||||
|
const disposable =
|
||||||
|
this.workspaceService.workspace.docCollection.meta.docMetaUpdated.on(cb);
|
||||||
|
return disposable.dispose;
|
||||||
|
}
|
||||||
|
|
||||||
|
constructor(private readonly workspaceService: WorkspaceService) {
|
||||||
super();
|
super();
|
||||||
}
|
}
|
||||||
|
|
||||||
watchTagIds() {
|
watchTagIds() {
|
||||||
return this.properties.tagOptions$
|
return this.tagOptions$.map(tags => tags.map(tag => tag.id)).asObservable();
|
||||||
.map(tags => tags.map(tag => tag.id))
|
|
||||||
.asObservable();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
createNewTag(value: string, color: string) {
|
createNewTag(value: string, color: string) {
|
||||||
const newId = nanoid();
|
const newId = nanoid();
|
||||||
this.properties.updateTagOptions([
|
this.updateTagOptions([
|
||||||
...this.properties.tagOptions$.value,
|
...this.tagOptions$.value,
|
||||||
{
|
{
|
||||||
id: newId,
|
id: newId,
|
||||||
value,
|
value,
|
||||||
@@ -30,24 +49,65 @@ export class TagStore extends Store {
|
|||||||
return newId;
|
return newId;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
updateProperties = (properties: DocsPropertiesMeta) => {
|
||||||
|
this.workspaceService.workspace.docCollection.meta.setProperties(
|
||||||
|
properties
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
updateTagOptions = (options: Tag[]) => {
|
||||||
|
this.updateProperties({
|
||||||
|
...this.properties,
|
||||||
|
tags: {
|
||||||
|
options,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
updateTagOption = (id: string, option: Tag) => {
|
||||||
|
this.updateTagOptions(this.tagOptions.map(o => (o.id === id ? option : o)));
|
||||||
|
};
|
||||||
|
|
||||||
|
removeTagOption = (id: string) => {
|
||||||
|
this.workspaceService.workspace.docCollection.doc.transact(() => {
|
||||||
|
this.updateTagOptions(this.tagOptions.filter(o => o.id !== id));
|
||||||
|
// need to remove tag from all pages
|
||||||
|
this.workspaceService.workspace.docCollection.docs.forEach(doc => {
|
||||||
|
const tags = doc.meta?.tags ?? [];
|
||||||
|
if (tags.includes(id)) {
|
||||||
|
this.updatePageTags(
|
||||||
|
doc.id,
|
||||||
|
tags.filter(t => t !== id)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
updatePageTags = (pageId: string, tags: string[]) => {
|
||||||
|
this.workspaceService.workspace.docCollection.setDocMeta(pageId, {
|
||||||
|
tags,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
deleteTag(id: string) {
|
deleteTag(id: string) {
|
||||||
this.properties.removeTagOption(id);
|
this.removeTagOption(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
watchTagInfo(id: string) {
|
watchTagInfo(id: string) {
|
||||||
return this.properties.tagOptions$.map(
|
return this.tagOptions$.map(
|
||||||
tags => tags.find(tag => tag.id === id) as TagSchema | undefined
|
tags => tags.find(tag => tag.id === id) as TagSchema | undefined
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
updateTagInfo(id: string, tagInfo: Partial<TagSchema>) {
|
updateTagInfo(id: string, tagInfo: Partial<TagSchema>) {
|
||||||
const tag = this.properties.tagOptions$.value.find(tag => tag.id === id) as
|
const tag = this.tagOptions$.value.find(tag => tag.id === id) as
|
||||||
| TagSchema
|
| TagSchema
|
||||||
| undefined;
|
| undefined;
|
||||||
if (!tag) {
|
if (!tag) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
this.properties.updateTagOption(id, {
|
this.updateTagOption(id, {
|
||||||
id: id,
|
id: id,
|
||||||
value: tag.value,
|
value: tag.value,
|
||||||
color: tag.color,
|
color: tag.color,
|
||||||
|
|||||||
Reference in New Issue
Block a user