mirror of
https://github.com/toeverything/AFFiNE.git
synced 2026-07-17 01:56:27 +08:00
feat(core): extract DocDisplayMetaService to resolve doc icon/title (#8226)
AF-1315
This commit is contained in:
+2
-1
@@ -32,5 +32,6 @@ globalStyle(`${wrapper} span`, {
|
||||
whiteSpace: 'nowrap',
|
||||
overflow: 'hidden',
|
||||
textOverflow: 'ellipsis',
|
||||
borderBottom: 'none',
|
||||
// don't modify border width to avoid layout shift
|
||||
borderBottomColor: 'transparent',
|
||||
});
|
||||
|
||||
+2
-6
@@ -1,8 +1,6 @@
|
||||
import type { Backlink, Link } from '@affine/core/modules/doc-link';
|
||||
import { useContext } from 'react';
|
||||
|
||||
import { AffinePageReference } from '../../reference-link';
|
||||
import { managerContext } from '../common';
|
||||
import * as styles from './links-row.css';
|
||||
|
||||
export const LinksRow = ({
|
||||
@@ -16,20 +14,18 @@ export const LinksRow = ({
|
||||
className?: string;
|
||||
onClick?: () => void;
|
||||
}) => {
|
||||
const manager = useContext(managerContext);
|
||||
return (
|
||||
<div className={className}>
|
||||
<div className={styles.title}>
|
||||
{label} · {references.length}
|
||||
</div>
|
||||
{references.map(link => (
|
||||
{references.map((link, index) => (
|
||||
<AffinePageReference
|
||||
key={link.docId}
|
||||
key={index}
|
||||
pageId={link.docId}
|
||||
wrapper={props => (
|
||||
<div className={styles.wrapper} onClick={onClick} {...props} />
|
||||
)}
|
||||
docCollection={manager.workspace.docCollection}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
|
||||
@@ -379,8 +379,6 @@ export const PageBacklinksPopup = ({
|
||||
backlinks,
|
||||
children,
|
||||
}: PageBacklinksPopupProps) => {
|
||||
const manager = useContext(managerContext);
|
||||
|
||||
return (
|
||||
<Menu
|
||||
contentOptions={{
|
||||
@@ -395,7 +393,6 @@ export const PageBacklinksPopup = ({
|
||||
key={link.docId + ':' + link.blockId}
|
||||
wrapper={MenuItem}
|
||||
pageId={link.docId}
|
||||
docCollection={manager.workspace.docCollection}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { useDocMetaHelper } from '@affine/core/components/hooks/use-block-suite-page-meta';
|
||||
import { useJournalHelper } from '@affine/core/components/hooks/use-journal';
|
||||
import { useJournalInfoHelper } from '@affine/core/components/hooks/use-journal';
|
||||
import { DocDisplayMetaService } from '@affine/core/modules/doc-display-meta';
|
||||
import {
|
||||
PeekViewService,
|
||||
useInsidePeekView,
|
||||
@@ -8,15 +8,8 @@ import { WorkbenchLink } from '@affine/core/modules/workbench';
|
||||
import { useI18n } from '@affine/i18n';
|
||||
import { track } from '@affine/track';
|
||||
import type { DocMode } from '@blocksuite/blocks';
|
||||
import {
|
||||
BlockLinkIcon,
|
||||
DeleteIcon,
|
||||
LinkedEdgelessIcon,
|
||||
LinkedPageIcon,
|
||||
TodayIcon,
|
||||
} from '@blocksuite/icons/rc';
|
||||
import type { DocCollection } from '@blocksuite/store';
|
||||
import { DocsService, useLiveData, useService } from '@toeverything/infra';
|
||||
import { useLiveData, useService } from '@toeverything/infra';
|
||||
import { nanoid } from 'nanoid';
|
||||
import {
|
||||
type PropsWithChildren,
|
||||
@@ -29,77 +22,18 @@ import { Link } from 'react-router-dom';
|
||||
|
||||
import * as styles from './styles.css';
|
||||
|
||||
export interface PageReferenceRendererOptions {
|
||||
pageId: string;
|
||||
docCollection: DocCollection;
|
||||
pageMetaHelper: ReturnType<typeof useDocMetaHelper>;
|
||||
journalHelper: ReturnType<typeof useJournalHelper>;
|
||||
t: ReturnType<typeof useI18n>;
|
||||
docMode?: DocMode;
|
||||
// Link to block or element
|
||||
linkToNode?: boolean;
|
||||
}
|
||||
|
||||
// use a function to be rendered in the lit renderer
|
||||
export function pageReferenceRenderer({
|
||||
pageId,
|
||||
pageMetaHelper,
|
||||
journalHelper,
|
||||
t,
|
||||
docMode,
|
||||
linkToNode = false,
|
||||
}: PageReferenceRendererOptions) {
|
||||
const { isPageJournal, getLocalizedJournalDateString } = journalHelper;
|
||||
const referencedPage = pageMetaHelper.getDocMeta(pageId);
|
||||
let title =
|
||||
referencedPage?.title ?? t['com.affine.editor.reference-not-found']();
|
||||
|
||||
let Icon = DeleteIcon;
|
||||
|
||||
if (referencedPage) {
|
||||
if (docMode === 'edgeless') {
|
||||
Icon = LinkedEdgelessIcon;
|
||||
} else {
|
||||
Icon = LinkedPageIcon;
|
||||
}
|
||||
if (linkToNode) {
|
||||
Icon = BlockLinkIcon;
|
||||
}
|
||||
}
|
||||
|
||||
const isJournal = isPageJournal(pageId);
|
||||
const localizedJournalDate = getLocalizedJournalDateString(pageId);
|
||||
if (isJournal && localizedJournalDate) {
|
||||
title = localizedJournalDate;
|
||||
Icon = TodayIcon;
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
<Icon className={styles.pageReferenceIcon} />
|
||||
<span className="affine-reference-title">
|
||||
{title ? title : t['Untitled']()}
|
||||
</span>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
export function AffinePageReference({
|
||||
pageId,
|
||||
docCollection,
|
||||
wrapper: Wrapper,
|
||||
params,
|
||||
}: {
|
||||
pageId: string;
|
||||
docCollection: DocCollection;
|
||||
wrapper?: React.ComponentType<PropsWithChildren>;
|
||||
params?: URLSearchParams;
|
||||
}) {
|
||||
const docDisplayMetaService = useService(DocDisplayMetaService);
|
||||
const journalHelper = useJournalInfoHelper();
|
||||
const t = useI18n();
|
||||
const pageMetaHelper = useDocMetaHelper();
|
||||
const journalHelper = useJournalHelper(docCollection);
|
||||
const docsService = useService(DocsService);
|
||||
const mode = useLiveData(docsService.list.primaryMode$(pageId));
|
||||
|
||||
let linkWithMode: DocMode | null = null;
|
||||
let linkToNode = false;
|
||||
@@ -111,15 +45,23 @@ export function AffinePageReference({
|
||||
linkToNode = params.has('blockIds') || params.has('elementIds');
|
||||
}
|
||||
|
||||
const el = pageReferenceRenderer({
|
||||
docMode: linkWithMode ?? mode ?? 'page',
|
||||
pageId,
|
||||
pageMetaHelper,
|
||||
journalHelper,
|
||||
docCollection,
|
||||
t,
|
||||
linkToNode,
|
||||
});
|
||||
const Icon = useLiveData(
|
||||
docDisplayMetaService.icon$(pageId, {
|
||||
mode: linkWithMode ?? undefined,
|
||||
reference: true,
|
||||
referenceToNode: linkToNode,
|
||||
})
|
||||
);
|
||||
const title = useLiveData(docDisplayMetaService.title$(pageId));
|
||||
|
||||
const el = (
|
||||
<>
|
||||
<Icon className={styles.pageReferenceIcon} />
|
||||
<span className="affine-reference-title">
|
||||
{typeof title === 'string' ? title : t[title.key]()}
|
||||
</span>
|
||||
</>
|
||||
);
|
||||
|
||||
const ref = useRef<HTMLAnchorElement>(null);
|
||||
|
||||
@@ -186,11 +128,9 @@ export function AffineSharedPageReference({
|
||||
wrapper?: React.ComponentType<PropsWithChildren>;
|
||||
params?: URLSearchParams;
|
||||
}) {
|
||||
const docDisplayMetaService = useService(DocDisplayMetaService);
|
||||
const journalHelper = useJournalInfoHelper();
|
||||
const t = useI18n();
|
||||
const pageMetaHelper = useDocMetaHelper();
|
||||
const journalHelper = useJournalHelper(docCollection);
|
||||
const docsService = useService(DocsService);
|
||||
const mode = useLiveData(docsService.list.primaryMode$(pageId));
|
||||
|
||||
let linkWithMode: DocMode | null = null;
|
||||
let linkToNode = false;
|
||||
@@ -202,15 +142,22 @@ export function AffineSharedPageReference({
|
||||
linkToNode = params.has('blockIds') || params.has('elementIds');
|
||||
}
|
||||
|
||||
const el = pageReferenceRenderer({
|
||||
docMode: linkWithMode ?? mode ?? 'page',
|
||||
pageId,
|
||||
pageMetaHelper,
|
||||
journalHelper,
|
||||
docCollection,
|
||||
t,
|
||||
linkToNode,
|
||||
});
|
||||
const Icon = useLiveData(
|
||||
docDisplayMetaService.icon$(pageId, {
|
||||
mode: linkWithMode ?? undefined,
|
||||
reference: true,
|
||||
referenceToNode: linkToNode,
|
||||
})
|
||||
);
|
||||
const title = useLiveData(docDisplayMetaService.title$(pageId));
|
||||
const el = (
|
||||
<>
|
||||
<Icon className={styles.pageReferenceIcon} />
|
||||
<span className="affine-reference-title">
|
||||
{typeof title === 'string' ? title : t[title.key]()}
|
||||
</span>
|
||||
</>
|
||||
);
|
||||
|
||||
const ref = useRef<HTMLAnchorElement>(null);
|
||||
|
||||
|
||||
+4
-17
@@ -1,10 +1,6 @@
|
||||
import { DocLinksService } from '@affine/core/modules/doc-link';
|
||||
import { useI18n } from '@affine/i18n';
|
||||
import {
|
||||
useLiveData,
|
||||
useServices,
|
||||
WorkspaceService,
|
||||
} from '@toeverything/infra';
|
||||
import { useLiveData, useServices } from '@toeverything/infra';
|
||||
import { useCallback, useState } from 'react';
|
||||
|
||||
import { AffinePageReference } from '../../affine/reference-link';
|
||||
@@ -12,9 +8,8 @@ import * as styles from './bi-directional-link-panel.css';
|
||||
|
||||
export const BiDirectionalLinkPanel = () => {
|
||||
const [show, setShow] = useState(false);
|
||||
const { docLinksService, workspaceService } = useServices({
|
||||
const { docLinksService } = useServices({
|
||||
DocLinksService,
|
||||
WorkspaceService,
|
||||
});
|
||||
const t = useI18n();
|
||||
|
||||
@@ -50,11 +45,7 @@ export const BiDirectionalLinkPanel = () => {
|
||||
</div>
|
||||
{backlinks.map(link => (
|
||||
<div key={link.docId} className={styles.link}>
|
||||
<AffinePageReference
|
||||
key={link.docId}
|
||||
pageId={link.docId}
|
||||
docCollection={workspaceService.workspace.docCollection}
|
||||
/>
|
||||
<AffinePageReference key={link.docId} pageId={link.docId} />
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
@@ -68,11 +59,7 @@ export const BiDirectionalLinkPanel = () => {
|
||||
key={`${link.docId}-${link.params?.toString()}-${i}`}
|
||||
className={styles.link}
|
||||
>
|
||||
<AffinePageReference
|
||||
pageId={link.docId}
|
||||
params={link.params}
|
||||
docCollection={workspaceService.workspace.docCollection}
|
||||
/>
|
||||
<AffinePageReference pageId={link.docId} params={link.params} />
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
|
||||
+1
-1
@@ -6,7 +6,7 @@ import * as styles from './styles.css';
|
||||
|
||||
export const BlocksuiteEditorJournalDocTitle = ({ page }: { page: Doc }) => {
|
||||
const { localizedJournalDate, isTodayJournal, journalDate } =
|
||||
useJournalInfoHelper(page.collection, page.id);
|
||||
useJournalInfoHelper(page.id);
|
||||
const t = useI18n();
|
||||
|
||||
// TODO(catsjuice): i18n
|
||||
|
||||
@@ -72,7 +72,7 @@ interface BlocksuiteEditorProps {
|
||||
shared?: boolean;
|
||||
}
|
||||
|
||||
const usePatchSpecs = (page: Doc, shared: boolean, mode: DocMode) => {
|
||||
const usePatchSpecs = (shared: boolean, mode: DocMode) => {
|
||||
const [reactToLit, portals] = useLitPortalFactory();
|
||||
const {
|
||||
peekViewService,
|
||||
@@ -110,15 +110,9 @@ const usePatchSpecs = (page: Doc, shared: boolean, mode: DocMode) => {
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<AffinePageReference
|
||||
docCollection={page.collection}
|
||||
pageId={pageId}
|
||||
params={params}
|
||||
/>
|
||||
);
|
||||
return <AffinePageReference pageId={pageId} params={params} />;
|
||||
};
|
||||
}, [page.collection, workspaceService]);
|
||||
}, [workspaceService]);
|
||||
|
||||
const specs = useMemo(() => {
|
||||
const enableAI = featureFlagService.flags.enable_ai.value;
|
||||
@@ -184,7 +178,7 @@ export const BlocksuiteDocEditor = forwardRef<
|
||||
) {
|
||||
const titleRef = useRef<DocTitle | null>(null);
|
||||
const docRef = useRef<PageEditor | null>(null);
|
||||
const { isJournal } = useJournalInfoHelper(page.collection, page.id);
|
||||
const { isJournal } = useJournalInfoHelper(page.id);
|
||||
|
||||
const editorSettingService = useService(EditorSettingService);
|
||||
|
||||
@@ -216,7 +210,7 @@ export const BlocksuiteDocEditor = forwardRef<
|
||||
[externalTitleRef]
|
||||
);
|
||||
|
||||
const [specs, portals] = usePatchSpecs(page, !!shared, 'page');
|
||||
const [specs, portals] = usePatchSpecs(!!shared, 'page');
|
||||
|
||||
const displayBiDirectionalLink = useLiveData(
|
||||
editorSettingService.editorSetting.settings$.selector(
|
||||
@@ -257,7 +251,7 @@ export const BlocksuiteEdgelessEditor = forwardRef<
|
||||
EdgelessEditor,
|
||||
BlocksuiteEditorProps
|
||||
>(function BlocksuiteEdgelessEditor({ page, shared }, ref) {
|
||||
const [specs, portals] = usePatchSpecs(page, !!shared, 'edgeless');
|
||||
const [specs, portals] = usePatchSpecs(!!shared, 'edgeless');
|
||||
const editorRef = useRef<EdgelessEditor | null>(null);
|
||||
|
||||
const onDocRef = useCallback(
|
||||
|
||||
+15
-31
@@ -1,20 +1,12 @@
|
||||
import { DocDisplayMetaService } from '@affine/core/modules/doc-display-meta';
|
||||
import { WorkspacePropertiesAdapter } from '@affine/core/modules/properties';
|
||||
import { I18n, i18nTime } from '@affine/i18n';
|
||||
import { I18n } from '@affine/i18n';
|
||||
import { track } from '@affine/track';
|
||||
import type { EditorHost } from '@blocksuite/block-std';
|
||||
import type { AffineInlineEditor } from '@blocksuite/blocks';
|
||||
import { LinkedWidgetUtils } from '@blocksuite/blocks';
|
||||
import {
|
||||
LinkedEdgelessIcon,
|
||||
LinkedPageIcon,
|
||||
TodayIcon,
|
||||
} from '@blocksuite/icons/lit';
|
||||
import type { DocMeta } from '@blocksuite/store';
|
||||
import {
|
||||
DocsService,
|
||||
type FrameworkProvider,
|
||||
WorkspaceService,
|
||||
} from '@toeverything/infra';
|
||||
import { type FrameworkProvider, WorkspaceService } from '@toeverything/infra';
|
||||
|
||||
// TODO: fix the type
|
||||
export function createLinkedWidgetConfig(
|
||||
@@ -33,6 +25,7 @@ export function createLinkedWidgetConfig(
|
||||
const isJournal = (d: DocMeta) =>
|
||||
!!adapter.getJournalPageDateString(d.id);
|
||||
|
||||
const docDisplayMetaService = framework.get(DocDisplayMetaService);
|
||||
const docMetas = rawMetas
|
||||
.filter(meta => {
|
||||
if (isJournal(meta) && !meta.updatedDate) {
|
||||
@@ -41,37 +34,28 @@ export function createLinkedWidgetConfig(
|
||||
return !meta.trash;
|
||||
})
|
||||
.map(meta => {
|
||||
if (isJournal(meta)) {
|
||||
const date = adapter.getJournalPageDateString(meta.id);
|
||||
if (date) {
|
||||
const title = i18nTime(date, { absolute: { accuracy: 'day' } });
|
||||
return { ...meta, title };
|
||||
}
|
||||
}
|
||||
if (!meta.title) {
|
||||
const title = I18n['Untitled']();
|
||||
return { ...meta, title };
|
||||
}
|
||||
return meta;
|
||||
const title = docDisplayMetaService.title$(meta.id).value;
|
||||
return {
|
||||
...meta,
|
||||
title: typeof title === 'string' ? title : I18n[title.key](),
|
||||
};
|
||||
})
|
||||
.filter(({ title }) => isFuzzyMatch(title, query));
|
||||
|
||||
// TODO need i18n if BlockSuite supported
|
||||
const MAX_DOCS = 6;
|
||||
const docsService = framework.get(DocsService);
|
||||
const isEdgeless = (d: DocMeta) =>
|
||||
docsService.list.getPrimaryMode(d.id) === 'edgeless';
|
||||
return Promise.resolve([
|
||||
{
|
||||
name: 'Link to Doc',
|
||||
items: docMetas.map(doc => ({
|
||||
key: doc.id,
|
||||
name: doc.title,
|
||||
icon: isJournal(doc)
|
||||
? TodayIcon()
|
||||
: isEdgeless(doc)
|
||||
? LinkedEdgelessIcon()
|
||||
: LinkedPageIcon(),
|
||||
icon: docDisplayMetaService
|
||||
.icon$(doc.id, {
|
||||
type: 'lit',
|
||||
reference: true,
|
||||
})
|
||||
.value(),
|
||||
action: () => {
|
||||
abort();
|
||||
LinkedWidgetUtils.insertLinkedNode({
|
||||
|
||||
+1
-1
@@ -19,7 +19,7 @@ export const JournalWeekDatePicker = ({
|
||||
page,
|
||||
}: JournalWeekDatePickerProps) => {
|
||||
const handleRef = useRef<WeekDatePickerHandle>(null);
|
||||
const { journalDate } = useJournalInfoHelper(docCollection, page.id);
|
||||
const { journalDate } = useJournalInfoHelper(page.id);
|
||||
const { openJournal } = useJournalRouteHelper(docCollection);
|
||||
const [date, setDate] = useState(
|
||||
(journalDate ?? dayjs()).format('YYYY-MM-DD')
|
||||
|
||||
@@ -4,7 +4,7 @@ import { useCallback, useMemo } from 'react';
|
||||
|
||||
import { useAsyncCallback } from './affine-async-hooks';
|
||||
import { useAllBlockSuiteDocMeta } from './use-all-block-suite-page-meta';
|
||||
import { useJournalHelper } from './use-journal';
|
||||
import { useJournalInfoHelper } from './use-journal';
|
||||
|
||||
/**
|
||||
* Get pageMetas excluding journal pages without updatedDate
|
||||
@@ -13,7 +13,7 @@ import { useJournalHelper } from './use-journal';
|
||||
*/
|
||||
export function useBlockSuiteDocMeta(docCollection: DocCollection) {
|
||||
const pageMetas = useAllBlockSuiteDocMeta(docCollection);
|
||||
const { isPageJournal } = useJournalHelper(docCollection);
|
||||
const { isPageJournal } = useJournalInfoHelper();
|
||||
return useMemo(
|
||||
() =>
|
||||
pageMetas.filter(
|
||||
|
||||
@@ -4,7 +4,7 @@ import type { Atom } from 'jotai';
|
||||
import { atom, useAtomValue } from 'jotai';
|
||||
import { useCallback } from 'react';
|
||||
|
||||
import { useJournalHelper, useJournalInfoHelper } from './use-journal';
|
||||
import { useJournalInfoHelper } from './use-journal';
|
||||
|
||||
const weakMap = new WeakMap<DocCollection, Map<string, Atom<string>>>();
|
||||
|
||||
@@ -32,6 +32,9 @@ function getAtom(w: DocCollection, pageId: string): Atom<string> {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated use `useDocTitle(docId: string)` instead
|
||||
*/
|
||||
export function useDocCollectionPageTitle(
|
||||
docCollection: DocCollection,
|
||||
pageId: string
|
||||
@@ -39,13 +42,13 @@ export function useDocCollectionPageTitle(
|
||||
const titleAtom = getAtom(docCollection, pageId);
|
||||
assertExists(titleAtom);
|
||||
const title = useAtomValue(titleAtom);
|
||||
const { localizedJournalDate } = useJournalInfoHelper(docCollection, pageId);
|
||||
const { localizedJournalDate } = useJournalInfoHelper(pageId);
|
||||
return localizedJournalDate || title;
|
||||
}
|
||||
|
||||
// This hook is NOT reactive to the page title change
|
||||
export function useGetDocCollectionPageTitle(docCollection: DocCollection) {
|
||||
const { getLocalizedJournalDateString } = useJournalHelper(docCollection);
|
||||
const { getLocalizedJournalDateString } = useJournalInfoHelper();
|
||||
return useCallback(
|
||||
(pageId: string) => {
|
||||
return (
|
||||
|
||||
@@ -37,6 +37,7 @@ export const useJournalHelper = (docCollection: DocCollection) => {
|
||||
EditorSettingService,
|
||||
});
|
||||
const adapter = useCurrentWorkspacePropertiesAdapter();
|
||||
const { isPageJournal } = useJournalInfoHelper();
|
||||
|
||||
/**
|
||||
* @internal
|
||||
@@ -67,13 +68,6 @@ export const useJournalHelper = (docCollection: DocCollection) => {
|
||||
[adapter, bsWorkspaceHelper, docsService.list, editorSettingService]
|
||||
);
|
||||
|
||||
const isPageJournal = useCallback(
|
||||
(pageId: string) => {
|
||||
return !!adapter.getJournalPageDateString(pageId);
|
||||
},
|
||||
[adapter]
|
||||
);
|
||||
|
||||
/**
|
||||
* query all journals by date
|
||||
*/
|
||||
@@ -104,31 +98,6 @@ export const useJournalHelper = (docCollection: DocCollection) => {
|
||||
[_createJournal, getJournalsByDate]
|
||||
);
|
||||
|
||||
const isPageTodayJournal = useCallback(
|
||||
(pageId: string) => {
|
||||
const date = dayjs().format(JOURNAL_DATE_FORMAT);
|
||||
const d = adapter.getJournalPageDateString(pageId);
|
||||
return isPageJournal(pageId) && d === date;
|
||||
},
|
||||
[adapter, isPageJournal]
|
||||
);
|
||||
|
||||
const getJournalDateString = useCallback(
|
||||
(pageId: string) => {
|
||||
return adapter.getJournalPageDateString(pageId);
|
||||
},
|
||||
[adapter]
|
||||
);
|
||||
|
||||
const getLocalizedJournalDateString = useCallback(
|
||||
(pageId: string) => {
|
||||
const journalDateString = getJournalDateString(pageId);
|
||||
if (!journalDateString) return null;
|
||||
return i18nTime(journalDateString, { absolute: { accuracy: 'day' } });
|
||||
},
|
||||
[getJournalDateString]
|
||||
);
|
||||
|
||||
const appendContentToToday = useCallback(
|
||||
async (content: string) => {
|
||||
if (!content) return;
|
||||
@@ -148,21 +117,9 @@ export const useJournalHelper = (docCollection: DocCollection) => {
|
||||
() => ({
|
||||
getJournalsByDate,
|
||||
getJournalByDate,
|
||||
getJournalDateString,
|
||||
getLocalizedJournalDateString,
|
||||
isPageJournal,
|
||||
isPageTodayJournal,
|
||||
appendContentToToday,
|
||||
}),
|
||||
[
|
||||
getJournalsByDate,
|
||||
getJournalByDate,
|
||||
getJournalDateString,
|
||||
getLocalizedJournalDateString,
|
||||
isPageJournal,
|
||||
isPageTodayJournal,
|
||||
appendContentToToday,
|
||||
]
|
||||
[getJournalsByDate, getJournalByDate, appendContentToToday]
|
||||
);
|
||||
};
|
||||
|
||||
@@ -207,16 +164,41 @@ export const useJournalRouteHelper = (docCollection: DocCollection) => {
|
||||
);
|
||||
};
|
||||
|
||||
export const useJournalInfoHelper = (
|
||||
docCollection: DocCollection,
|
||||
pageId?: string | null
|
||||
) => {
|
||||
const {
|
||||
isPageJournal,
|
||||
getJournalDateString,
|
||||
getLocalizedJournalDateString,
|
||||
isPageTodayJournal,
|
||||
} = useJournalHelper(docCollection);
|
||||
// get journal info that don't rely on `docCollection`
|
||||
export const useJournalInfoHelper = (pageId?: string | null) => {
|
||||
const adapter = useCurrentWorkspacePropertiesAdapter();
|
||||
|
||||
const isPageJournal = useCallback(
|
||||
(pageId: string) => {
|
||||
return !!adapter.getJournalPageDateString(pageId);
|
||||
},
|
||||
[adapter]
|
||||
);
|
||||
|
||||
const isPageTodayJournal = useCallback(
|
||||
(pageId: string) => {
|
||||
const date = dayjs().format(JOURNAL_DATE_FORMAT);
|
||||
const d = adapter.getJournalPageDateString(pageId);
|
||||
return isPageJournal(pageId) && d === date;
|
||||
},
|
||||
[adapter, isPageJournal]
|
||||
);
|
||||
|
||||
const getJournalDateString = useCallback(
|
||||
(pageId: string) => {
|
||||
return adapter.getJournalPageDateString(pageId);
|
||||
},
|
||||
[adapter]
|
||||
);
|
||||
|
||||
const getLocalizedJournalDateString = useCallback(
|
||||
(pageId: string) => {
|
||||
const journalDateString = getJournalDateString(pageId);
|
||||
if (!journalDateString) return null;
|
||||
return i18nTime(journalDateString, { absolute: { accuracy: 'day' } });
|
||||
},
|
||||
[getJournalDateString]
|
||||
);
|
||||
|
||||
return useMemo(
|
||||
() => ({
|
||||
@@ -226,6 +208,10 @@ export const useJournalInfoHelper = (
|
||||
? getLocalizedJournalDateString(pageId)
|
||||
: null,
|
||||
isTodayJournal: pageId ? isPageTodayJournal(pageId) : false,
|
||||
isPageJournal,
|
||||
isPageTodayJournal,
|
||||
getJournalDateString,
|
||||
getLocalizedJournalDateString,
|
||||
}),
|
||||
[
|
||||
getJournalDateString,
|
||||
|
||||
@@ -1,17 +1,11 @@
|
||||
import { useJournalInfoHelper } from '@affine/core/components/hooks/use-journal';
|
||||
import { DocDisplayMetaService } from '@affine/core/modules/doc-display-meta';
|
||||
import type { Tag } from '@affine/env/filter';
|
||||
import { useI18n } from '@affine/i18n';
|
||||
import { assertExists } from '@blocksuite/global/utils';
|
||||
import {
|
||||
EdgelessIcon,
|
||||
PageIcon,
|
||||
TodayIcon,
|
||||
ToggleCollapseIcon,
|
||||
ViewLayersIcon,
|
||||
} from '@blocksuite/icons/rc';
|
||||
import { ToggleCollapseIcon, ViewLayersIcon } from '@blocksuite/icons/rc';
|
||||
import type { DocCollection, DocMeta } from '@blocksuite/store';
|
||||
import * as Collapsible from '@radix-ui/react-collapsible';
|
||||
import { DocsService, useLiveData, useService } from '@toeverything/infra';
|
||||
import { useLiveData, useService } from '@toeverything/infra';
|
||||
import clsx from 'clsx';
|
||||
import { selectAtom } from 'jotai/utils';
|
||||
import type { MouseEventHandler } from 'react';
|
||||
@@ -284,26 +278,16 @@ function tagIdToTagOption(
|
||||
}
|
||||
|
||||
const PageTitle = ({ id }: { id: string }) => {
|
||||
const doc = useLiveData(useService(DocsService).list.doc$(id));
|
||||
const title = useLiveData(doc?.title$);
|
||||
const t = useI18n();
|
||||
return title || t['Untitled']();
|
||||
const docDisplayMetaService = useService(DocDisplayMetaService);
|
||||
const title = useLiveData(docDisplayMetaService.title$(id));
|
||||
return typeof title === 'string' ? title : t[title.key]();
|
||||
};
|
||||
|
||||
const UnifiedPageIcon = ({
|
||||
id,
|
||||
docCollection,
|
||||
}: {
|
||||
id: string;
|
||||
docCollection: DocCollection;
|
||||
}) => {
|
||||
const list = useService(DocsService).list;
|
||||
const isEdgeless = useLiveData(list.primaryMode$(id)) === 'edgeless';
|
||||
const { isJournal } = useJournalInfoHelper(docCollection, id);
|
||||
if (isJournal) {
|
||||
return <TodayIcon />;
|
||||
}
|
||||
return isEdgeless ? <EdgelessIcon /> : <PageIcon />;
|
||||
const UnifiedPageIcon = ({ id }: { id: string }) => {
|
||||
const docDisplayMetaService = useService(DocDisplayMetaService);
|
||||
const Icon = useLiveData(docDisplayMetaService.icon$(id));
|
||||
return <Icon />;
|
||||
};
|
||||
|
||||
function pageMetaToListItemProp(
|
||||
@@ -338,7 +322,7 @@ function pageMetaToListItemProp(
|
||||
updatedDate: item.updatedDate ? new Date(item.updatedDate) : undefined,
|
||||
to: props.rowAsLink && !props.selectable ? `/${item.id}` : undefined,
|
||||
onClick: toggleSelection,
|
||||
icon: <UnifiedPageIcon id={item.id} docCollection={props.docCollection} />,
|
||||
icon: <UnifiedPageIcon id={item.id} />,
|
||||
tags:
|
||||
item.tags
|
||||
?.map(id => tagIdToTagOption(id, props.docCollection))
|
||||
|
||||
@@ -3,10 +3,11 @@ import {
|
||||
useJournalInfoHelper,
|
||||
useJournalRouteHelper,
|
||||
} from '@affine/core/components/hooks/use-journal';
|
||||
import { DocDisplayMetaService } from '@affine/core/modules/doc-display-meta';
|
||||
import { WorkbenchService } from '@affine/core/modules/workbench';
|
||||
import { isNewTabTrigger } from '@affine/core/utils';
|
||||
import { useI18n } from '@affine/i18n';
|
||||
import { TodayIcon, TomorrowIcon, YesterdayIcon } from '@blocksuite/icons/rc';
|
||||
import { TodayIcon } from '@blocksuite/icons/rc';
|
||||
import type { DocCollection } from '@blocksuite/store';
|
||||
import { useLiveData, useService } from '@toeverything/infra';
|
||||
import { type MouseEvent } from 'react';
|
||||
@@ -21,13 +22,11 @@ export const AppSidebarJournalButton = ({
|
||||
docCollection,
|
||||
}: AppSidebarJournalButtonProps) => {
|
||||
const t = useI18n();
|
||||
const docDisplayMetaService = useService(DocDisplayMetaService);
|
||||
const workbench = useService(WorkbenchService).workbench;
|
||||
const location = useLiveData(workbench.location$);
|
||||
const { openToday } = useJournalRouteHelper(docCollection);
|
||||
const { journalDate, isJournal } = useJournalInfoHelper(
|
||||
docCollection,
|
||||
location.pathname.split('/')[1]
|
||||
);
|
||||
const { isJournal } = useJournalInfoHelper(location.pathname.split('/')[1]);
|
||||
|
||||
const handleOpenToday = useCatchEventCallback(
|
||||
(e: MouseEvent) => {
|
||||
@@ -36,14 +35,12 @@ export const AppSidebarJournalButton = ({
|
||||
[openToday]
|
||||
);
|
||||
|
||||
const Icon =
|
||||
isJournal && journalDate
|
||||
? journalDate.isBefore(new Date(), 'day')
|
||||
? YesterdayIcon
|
||||
: journalDate.isAfter(new Date(), 'day')
|
||||
? TomorrowIcon
|
||||
: TodayIcon
|
||||
: TodayIcon;
|
||||
const JournalIcon = useLiveData(
|
||||
docDisplayMetaService.icon$(docCollection.id, {
|
||||
compareDate: new Date(),
|
||||
})
|
||||
);
|
||||
const Icon = isJournal ? JournalIcon : TodayIcon;
|
||||
|
||||
return (
|
||||
<MenuItem
|
||||
|
||||
Reference in New Issue
Block a user