Skip to content

Commit

Permalink
feat(core): at menu ux
Browse files Browse the repository at this point in the history
  • Loading branch information
pengx17 committed Dec 6, 2024
1 parent e83617a commit 15caa43
Show file tree
Hide file tree
Showing 6 changed files with 95 additions and 44 deletions.
5 changes: 4 additions & 1 deletion packages/frontend/core/src/modules/at-menu-config/index.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
import {
DocsService,
type Framework,
WorkspaceScope,
WorkspaceService,
} from '@toeverything/infra';

import { WorkspaceDialogService } from '../dialogs';
import { DocDisplayMetaService } from '../doc-display-meta';
import { EditorSettingService } from '../editor-setting';
import { JournalService } from '../journal';
import { RecentDocsService } from '../quicksearch';
import { AtMenuConfigService } from './services';
Expand All @@ -19,6 +21,7 @@ export function configAtMenuConfigModule(framework: Framework) {
DocDisplayMetaService,
WorkspaceDialogService,
RecentDocsService,
WorkspaceDialogService,
EditorSettingService,
DocsService,
]);
}
109 changes: 74 additions & 35 deletions packages/frontend/core/src/modules/at-menu-config/services/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,23 +2,29 @@ import { I18n, i18nTime } from '@affine/i18n';
import track from '@affine/track';
import {
type AffineInlineEditor,
type DocMode,
type LinkedMenuGroup,
type LinkedMenuItem,
type LinkedWidgetConfig,
LinkedWidgetUtils,
} from '@blocksuite/affine/blocks';
import type { EditorHost } from '@blocksuite/block-std';
import { DateTimeIcon } from '@blocksuite/icons/lit';
import {
DateTimeIcon,
NewXxxEdgelessIcon,
NewXxxPageIcon,
} from '@blocksuite/icons/lit';
import type { DocMeta } from '@blocksuite/store';
import { signal } from '@preact/signals-core';
import type { WorkspaceService } from '@toeverything/infra';
import type { DocsService, WorkspaceService } from '@toeverything/infra';
import { Service } from '@toeverything/infra';
import { cssVarV2 } from '@toeverything/theme/v2';
import dayjs from 'dayjs';
import { html } from 'lit';

import type { WorkspaceDialogService } from '../../dialogs';
import type { DocDisplayMetaService } from '../../doc-display-meta';
import type { EditorSettingService } from '../../editor-setting';
import { JOURNAL_DATE_FORMAT, type JournalService } from '../../journal';
import type { RecentDocsService } from '../../quicksearch';

Expand All @@ -31,7 +37,8 @@ export class AtMenuConfigService extends Service {
private readonly docDisplayMetaService: DocDisplayMetaService,
private readonly dialogService: WorkspaceDialogService,
private readonly recentDocsService: RecentDocsService,
private readonly workspaceDialogService: WorkspaceDialogService
private readonly editorSettingService: EditorSettingService,
private readonly docsService: DocsService
) {
super();
}
Expand Down Expand Up @@ -64,26 +71,17 @@ export class AtMenuConfigService extends Service {
!!this.journalService.journalDate$(d.id).value;
const docItems = signal<LinkedMenuItem[]>([]);

// recent docs should be at the top
const recentDocs = this.recentDocsService.getRecentDocs();

const sortedRawMetas =
query.trim().length === 0
? rawMetas.toSorted((a, b) => {
const indexA = recentDocs.findIndex(doc => doc.id === a.id);
const indexB = recentDocs.findIndex(doc => doc.id === b.id);

if (indexA > -1 && indexB < 0) {
return -1;
} else if (indexA < 0 && indexB > -1) {
return 1;
} else if (indexA > -1 && indexB > -1) {
return indexA - indexB;
}
const showRecent = query.trim().length === 0;

return Number.MAX_SAFE_INTEGER;
// recent docs should be at the top
const docMetas = showRecent
? this.recentDocsService
.getRecentDocs()
.map(record => {
return rawMetas.find(meta => meta.id === record.id);
})
: rawMetas;
.filter((m): m is DocMeta => !!m)
: rawMetas;

const docDisplayMetaService = this.docDisplayMetaService;

Expand Down Expand Up @@ -126,7 +124,7 @@ export class AtMenuConfigService extends Service {
};

(async () => {
for (const [index, meta] of sortedRawMetas.entries()) {
for (const [index, meta] of docMetas.entries()) {
if (abortSignal.aborted) {
return;
}
Expand All @@ -144,7 +142,11 @@ export class AtMenuConfigService extends Service {
})().catch(console.error);

return {
name: I18n.t('com.affine.editor.at-menu.link-to-doc'),
name: showRecent
? I18n.t('com.affine.editor.at-menu.recent-docs')
: I18n.t('com.affine.editor.at-menu.link-to-doc', {
query,
}),
items: docItems,
maxDisplay: MAX_DOCS,
get overflowText() {
Expand Down Expand Up @@ -182,13 +184,53 @@ export class AtMenuConfigService extends Service {
return originalNewDocMenuGroup;
}

const customNewDocItem: LinkedMenuItem = {
...newDocItem,
name: I18n.t('com.affine.editor.at-menu.create-doc', {
name: query || I18n.t('Untitled'),
}),
const createPage = (mode: DocMode) => {
const page = this.docsService.createDoc({
docProps: {
note: this.editorSettingService.editorSetting.get('affine:note'),
},
primaryMode: mode,
});

page.setMeta({
title: query,
});

return page;
};

const customNewDocItems: LinkedMenuItem[] = [
{
key: 'create-page',
icon: NewXxxPageIcon(),
name: I18n.t('com.affine.editor.at-menu.create-page', {
name: query || I18n.t('Untitled'),
}),
action: () => {
close();
const page = createPage('page');
this.insertDoc(inlineEditor, page.id);
track.doc.editor.atMenu.createDoc({
mode: 'page',
});
},
},
{
key: 'create-edgeless',
icon: NewXxxEdgelessIcon(),
name: I18n.t('com.affine.editor.at-menu.create-edgeless', {
name: query || I18n.t('Untitled'),
}),
action: () => {
close();
const page = createPage('edgeless');
this.insertDoc(inlineEditor, page.id);
track.doc.editor.atMenu.createDoc({
mode: 'edgeless',
});
},
},
];
const customImportItem: LinkedMenuItem = {
...importItem,
name: I18n.t('com.affine.editor.at-menu.import'),
Expand All @@ -203,10 +245,7 @@ export class AtMenuConfigService extends Service {
// If the imported file is a workspace file, insert the entry page node.
const { docIds, entryId, isWorkspaceFile } = payload;
if (isWorkspaceFile && entryId) {
LinkedWidgetUtils.insertLinkedNode({
inlineEditor,
docId: entryId,
});
this.insertDoc(inlineEditor, entryId);
return;
}

Expand All @@ -221,7 +260,7 @@ export class AtMenuConfigService extends Service {
return {
...originalNewDocMenuGroup,
name: I18n.t('com.affine.editor.at-menu.new-doc'),
items: [customNewDocItem, customImportItem],
items: [...customNewDocItems, customImportItem],
};
}

Expand Down Expand Up @@ -252,12 +291,12 @@ export class AtMenuConfigService extends Service {

const { x, y, width, height } = getRect();

const id = this.workspaceDialogService.open('date-selector', {
const id = this.dialogService.open('date-selector', {
position: [x, y, width, height || 20],
onSelect: date => {
if (date) {
onSelectDate(date);
this.workspaceDialogService.close(id);
this.dialogService.close(id);
}
},
});
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import type { DocMode } from '@blocksuite/affine/blocks';
import { EdgelessIcon, PageIcon } from '@blocksuite/icons/rc';
import { NewXxxEdgelessIcon, NewXxxPageIcon } from '@blocksuite/icons/rc';
import { Entity, LiveData } from '@toeverything/infra';

import type { QuickSearchSession } from '../providers/quick-search-provider';
Expand Down Expand Up @@ -34,7 +34,7 @@ export class CreationQuickSearchSession
options: { keyWord: query },
},
group,
icon: PageIcon,
icon: NewXxxPageIcon,
payload: { mode: 'edgeless', title: query },
},
{
Expand All @@ -45,7 +45,7 @@ export class CreationQuickSearchSession
options: { keyWord: query },
},
group,
icon: EdgelessIcon,
icon: NewXxxEdgelessIcon,
payload: { mode: 'edgeless', title: query },
},
] as QuickSearchItem<'creation', { title: string; mode: DocMode }>[];
Expand Down
9 changes: 8 additions & 1 deletion packages/frontend/graphql/src/schema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -193,7 +193,6 @@ export interface CreateCheckoutSessionInput {
coupon?: InputMaybe<Scalars['String']['input']>;
idempotencyKey?: InputMaybe<Scalars['String']['input']>;
plan?: InputMaybe<SubscriptionPlan>;
quantity?: InputMaybe<Scalars['Int']['input']>;
recurring?: InputMaybe<SubscriptionRecurring>;
successCallbackLink: Scalars['String']['input'];
variant?: InputMaybe<SubscriptionVariant>;
Expand Down Expand Up @@ -1257,6 +1256,9 @@ export interface WorkspaceType {
id: Scalars['ID']['output'];
/** is current workspace initialized */
initialized: Scalars['Boolean']['output'];
/** Get user invoice count */
invoiceCount: Scalars['Int']['output'];
invoices: Array<InvoiceType>;
/** member count of workspace */
memberCount: Scalars['Int']['output'];
/** Members of workspace */
Expand Down Expand Up @@ -1290,6 +1292,11 @@ export interface WorkspaceTypeHistoriesArgs {
take?: InputMaybe<Scalars['Int']['input']>;
}

export interface WorkspaceTypeInvoicesArgs {
skip?: InputMaybe<Scalars['Int']['input']>;
take?: InputMaybe<Scalars['Int']['input']>;
}

export interface WorkspaceTypeMembersArgs {
skip?: InputMaybe<Scalars['Int']['input']>;
take?: InputMaybe<Scalars['Int']['input']>;
Expand Down
8 changes: 5 additions & 3 deletions packages/frontend/i18n/src/resources/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -1491,9 +1491,11 @@
"com.affine.attachment.preview.error.title": "Unable to preview this file",
"com.affine.attachment.preview.error.subtitle": "file type not supported.",
"com.affine.pdf.page.render.error": "Failed to render page.",
"com.affine.editor.at-menu.link-to-doc": "Link to Doc",
"com.affine.editor.at-menu.new-doc": "New Doc",
"com.affine.editor.at-menu.create-doc": "Create \"{{name}}\" Doc",
"com.affine.editor.at-menu.link-to-doc": "Search for \"{{query}}\"",
"com.affine.editor.at-menu.recent-docs": "Recent",
"com.affine.editor.at-menu.new-doc": "New",
"com.affine.editor.at-menu.create-page": "New \"{{name}}\" page",
"com.affine.editor.at-menu.create-edgeless": "New \"{{name}}\" edgeless",
"com.affine.editor.at-menu.import": "Import",
"com.affine.editor.at-menu.more-docs-hint": "{{count}} more docs",
"com.affine.editor.at-menu.journal": "Journal",
Expand Down
2 changes: 1 addition & 1 deletion packages/frontend/track/src/events.ts
Original file line number Diff line number Diff line change
Expand Up @@ -278,7 +278,7 @@ const PageEvents = {
doc: {
editor: {
slashMenu: ['linkDoc', 'createDoc', 'bookmark'],
atMenu: ['linkDoc', 'import'],
atMenu: ['linkDoc', 'import', 'createDoc'],
quickSearch: ['createDoc'],
formatToolbar: ['bold'],
pageRef: ['navigate'],
Expand Down

0 comments on commit 15caa43

Please sign in to comment.