Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(core): emoji as doc icon support with feature flag #8348

Merged
merged 1 commit into from
Oct 10, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions packages/common/infra/src/modules/feature-flag/constant.ts
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,17 @@ export const AFFINE_FLAGS = {
configurable: true,
defaultState: true,
},
enable_emoji_doc_icon: {
category: 'affine',
displayName: 'Emoji Doc Icon',
description:
'Once enabled, you can use an emoji as the page icon. When the first character of the folder name is an emoji, it will be extracted and used as its icon.',
feedbackType: 'discord',
feedbackLink:
'https://discord.com/channels/959027316334407691/1280014319865696351',
configurable: true,
defaultState: true,
},
enable_editor_settings: {
category: 'affine',
displayName: 'Editor Settings',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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 = (
<>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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](),
Expand Down
7 changes: 6 additions & 1 deletion packages/frontend/core/src/modules/doc-display-meta/index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import {
DocsService,
FeatureFlagService,
type Framework,
WorkspaceScope,
} from '@toeverything/infra';
Expand All @@ -12,5 +13,9 @@ export { DocDisplayMetaService };
export function configureDocDisplayMetaModule(framework: Framework) {
framework
.scope(WorkspaceScope)
.service(DocDisplayMetaService, [WorkspacePropertiesAdapter, DocsService]);
.service(DocDisplayMetaService, [
WorkspacePropertiesAdapter,
DocsService,
FeatureFlagService,
]);
}
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { extractEmojiIcon } from '@affine/core/utils';
import { i18nTime } from '@affine/i18n';
import {
BlockLinkIcon as LitBlockLinkIcon,
Expand All @@ -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';
Expand All @@ -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 = {
Expand Down Expand Up @@ -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();
}
Expand All @@ -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);
Expand All @@ -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);
Expand All @@ -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,
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import { useI18n } from '@affine/i18n';
import { track } from '@affine/track';
import {
DocsService,
FeatureFlagService,
GlobalContextService,
LiveData,
useLiveData,
Expand Down Expand Up @@ -47,11 +48,13 @@ export const ExplorerDocNode = ({
docsService,
globalContextService,
docDisplayMetaService,
featureFlagService,
} = useServices({
DocsSearchService,
DocsService,
GlobalContextService,
DocDisplayMetaService,
FeatureFlagService,
});
// const pageInfoAdapter = useCurrentWorkspacePropertiesAdapter();

Expand All @@ -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 }) => {
Expand Down Expand Up @@ -206,6 +212,7 @@ export const ExplorerDocNode = ({
dndData={dndData}
onDrop={handleDropOnDoc}
renameable
extractEmojiAsIcon={enableEmojiIcon}
collapsed={collapsed}
setCollapsed={setCollapsed}
canDrop={handleCanDrop}
Expand Down
Loading