mirror of
https://github.com/toeverything/AFFiNE.git
synced 2026-02-13 21:05:19 +00:00
feat(core): emoji as doc icon support with feature flag (#8348)
close AF-1412 Adjusted the priority of the public doc icon: 1. block-reference 2. journal 3. page reference 4. **emoji** (*new) 5. default
This commit is contained in:
@@ -52,7 +52,9 @@ export function AffinePageReference({
|
||||
referenceToNode: linkToNode,
|
||||
})
|
||||
);
|
||||
const title = useLiveData(docDisplayMetaService.title$(pageId));
|
||||
const title = useLiveData(
|
||||
docDisplayMetaService.title$(pageId, { reference: true })
|
||||
);
|
||||
|
||||
const el = (
|
||||
<>
|
||||
|
||||
@@ -34,7 +34,9 @@ export function createLinkedWidgetConfig(
|
||||
return !meta.trash;
|
||||
})
|
||||
.map(meta => {
|
||||
const title = docDisplayMetaService.title$(meta.id).value;
|
||||
const title = docDisplayMetaService.title$(meta.id, {
|
||||
reference: true,
|
||||
}).value;
|
||||
return {
|
||||
...meta,
|
||||
title: typeof title === 'string' ? title : I18n[title.key](),
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import {
|
||||
DocsService,
|
||||
FeatureFlagService,
|
||||
type Framework,
|
||||
WorkspaceScope,
|
||||
} from '@toeverything/infra';
|
||||
@@ -12,5 +13,9 @@ export { DocDisplayMetaService };
|
||||
export function configureDocDisplayMetaModule(framework: Framework) {
|
||||
framework
|
||||
.scope(WorkspaceScope)
|
||||
.service(DocDisplayMetaService, [WorkspacePropertiesAdapter, DocsService]);
|
||||
.service(DocDisplayMetaService, [
|
||||
WorkspacePropertiesAdapter,
|
||||
DocsService,
|
||||
FeatureFlagService,
|
||||
]);
|
||||
}
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { extractEmojiIcon } from '@affine/core/utils';
|
||||
import { i18nTime } from '@affine/i18n';
|
||||
import {
|
||||
BlockLinkIcon as LitBlockLinkIcon,
|
||||
@@ -19,7 +20,11 @@ import {
|
||||
TomorrowIcon,
|
||||
YesterdayIcon,
|
||||
} from '@blocksuite/icons/rc';
|
||||
import type { DocRecord, DocsService } from '@toeverything/infra';
|
||||
import type {
|
||||
DocRecord,
|
||||
DocsService,
|
||||
FeatureFlagService,
|
||||
} from '@toeverything/infra';
|
||||
import { LiveData, Service } from '@toeverything/infra';
|
||||
import type { Dayjs } from 'dayjs';
|
||||
import dayjs from 'dayjs';
|
||||
@@ -37,6 +42,18 @@ interface DocDisplayIconOptions<T extends IconType> {
|
||||
mode?: 'edgeless' | 'page';
|
||||
reference?: boolean;
|
||||
referenceToNode?: boolean;
|
||||
/**
|
||||
* @default true
|
||||
*/
|
||||
enableEmojiIcon?: boolean;
|
||||
}
|
||||
interface DocDisplayTitleOptions {
|
||||
originalTitle?: string;
|
||||
reference?: boolean;
|
||||
/**
|
||||
* @default true
|
||||
*/
|
||||
enableEmojiIcon?: boolean;
|
||||
}
|
||||
|
||||
const rcIcons = {
|
||||
@@ -67,7 +84,8 @@ const icons = { rc: rcIcons, lit: litIcons } as {
|
||||
export class DocDisplayMetaService extends Service {
|
||||
constructor(
|
||||
private readonly propertiesAdapter: WorkspacePropertiesAdapter,
|
||||
private readonly docsService: DocsService
|
||||
private readonly docsService: DocsService,
|
||||
private readonly featureFlagService: FeatureFlagService
|
||||
) {
|
||||
super();
|
||||
}
|
||||
@@ -80,6 +98,7 @@ export class DocDisplayMetaService extends Service {
|
||||
|
||||
return LiveData.computed(get => {
|
||||
const doc = get(this.docsService.list.doc$(docId));
|
||||
const title = doc ? get(doc.title$) : '';
|
||||
const mode = doc ? get(doc.primaryMode$) : undefined;
|
||||
const finalMode = options?.mode ?? mode ?? 'page';
|
||||
const referenceToNode = !!(options?.reference && options.referenceToNode);
|
||||
@@ -89,10 +108,10 @@ export class DocDisplayMetaService extends Service {
|
||||
return iconSet.BlockLinkIcon;
|
||||
}
|
||||
|
||||
// journal icon
|
||||
const journalDate = this._toDayjs(
|
||||
this.propertiesAdapter.getJournalPageDateString(docId)
|
||||
);
|
||||
|
||||
if (journalDate) {
|
||||
if (!options?.compareDate) return iconSet.TodayIcon;
|
||||
const compareDate = dayjs(options?.compareDate);
|
||||
@@ -103,36 +122,65 @@ export class DocDisplayMetaService extends Service {
|
||||
: iconSet.TodayIcon;
|
||||
}
|
||||
|
||||
return options?.reference
|
||||
? finalMode === 'edgeless'
|
||||
// reference icon
|
||||
if (options?.reference) {
|
||||
return finalMode === 'edgeless'
|
||||
? iconSet.LinkedEdgelessIcon
|
||||
: iconSet.LinkedPageIcon
|
||||
: finalMode === 'edgeless'
|
||||
? iconSet.EdgelessIcon
|
||||
: iconSet.PageIcon;
|
||||
: iconSet.LinkedPageIcon;
|
||||
}
|
||||
|
||||
// emoji icon
|
||||
const enableEmojiIcon =
|
||||
get(this.featureFlagService.flags.enable_emoji_doc_icon.$) &&
|
||||
options?.enableEmojiIcon !== false;
|
||||
if (enableEmojiIcon) {
|
||||
const { emoji } = extractEmojiIcon(title);
|
||||
if (emoji) return () => emoji;
|
||||
}
|
||||
|
||||
// default icon
|
||||
return finalMode === 'edgeless' ? iconSet.EdgelessIcon : iconSet.PageIcon;
|
||||
});
|
||||
}
|
||||
|
||||
title$(docId: string, originalTitle?: string) {
|
||||
title$(docId: string, options?: DocDisplayTitleOptions) {
|
||||
return LiveData.computed(get => {
|
||||
const doc = get(this.docsService.list.doc$(docId));
|
||||
const docTitle = doc ? get(doc.title$) : undefined;
|
||||
|
||||
const journalDateString =
|
||||
this.propertiesAdapter.getJournalPageDateString(docId);
|
||||
return journalDateString
|
||||
? i18nTime(journalDateString, { absolute: { accuracy: 'day' } })
|
||||
: originalTitle ||
|
||||
docTitle ||
|
||||
({
|
||||
key: 'Untitled',
|
||||
} as const);
|
||||
|
||||
// journal
|
||||
if (journalDateString) {
|
||||
return i18nTime(journalDateString, { absolute: { accuracy: 'day' } });
|
||||
}
|
||||
|
||||
if (options?.originalTitle) return options.originalTitle;
|
||||
|
||||
// empty title
|
||||
if (!docTitle) return { key: 'Untitled' } as const;
|
||||
|
||||
// reference
|
||||
if (options?.reference) return docTitle;
|
||||
|
||||
// check emoji
|
||||
const enableEmojiIcon =
|
||||
get(this.featureFlagService.flags.enable_emoji_doc_icon.$) &&
|
||||
options?.enableEmojiIcon !== false;
|
||||
if (enableEmojiIcon) {
|
||||
const { rest } = extractEmojiIcon(docTitle);
|
||||
return rest;
|
||||
}
|
||||
|
||||
// default
|
||||
return docTitle;
|
||||
});
|
||||
}
|
||||
|
||||
getDocDisplayMeta(docRecord: DocRecord, originalTitle?: string) {
|
||||
return {
|
||||
title: this.title$(docRecord.id, originalTitle).value,
|
||||
title: this.title$(docRecord.id, { originalTitle }).value,
|
||||
icon: this.icon$(docRecord.id).value,
|
||||
updatedDate: docRecord.meta$.value.updatedDate,
|
||||
};
|
||||
|
||||
@@ -14,6 +14,7 @@ import { useI18n } from '@affine/i18n';
|
||||
import { track } from '@affine/track';
|
||||
import {
|
||||
DocsService,
|
||||
FeatureFlagService,
|
||||
GlobalContextService,
|
||||
LiveData,
|
||||
useLiveData,
|
||||
@@ -47,11 +48,13 @@ export const ExplorerDocNode = ({
|
||||
docsService,
|
||||
globalContextService,
|
||||
docDisplayMetaService,
|
||||
featureFlagService,
|
||||
} = useServices({
|
||||
DocsSearchService,
|
||||
DocsService,
|
||||
GlobalContextService,
|
||||
DocDisplayMetaService,
|
||||
FeatureFlagService,
|
||||
});
|
||||
// const pageInfoAdapter = useCurrentWorkspacePropertiesAdapter();
|
||||
|
||||
@@ -67,6 +70,9 @@ export const ExplorerDocNode = ({
|
||||
);
|
||||
const docTitle = useLiveData(docDisplayMetaService.title$(docId));
|
||||
const isInTrash = useLiveData(docRecord?.trash$);
|
||||
const enableEmojiIcon = useLiveData(
|
||||
featureFlagService.flags.enable_emoji_doc_icon.$
|
||||
);
|
||||
|
||||
const Icon = useCallback(
|
||||
({ className }: { className?: string }) => {
|
||||
@@ -206,6 +212,7 @@ export const ExplorerDocNode = ({
|
||||
dndData={dndData}
|
||||
onDrop={handleDropOnDoc}
|
||||
renameable
|
||||
extractEmojiAsIcon={enableEmojiIcon}
|
||||
collapsed={collapsed}
|
||||
setCollapsed={setCollapsed}
|
||||
canDrop={handleCanDrop}
|
||||
|
||||
Reference in New Issue
Block a user