mirror of
https://github.com/toeverything/AFFiNE.git
synced 2026-02-14 05:14:54 +00:00
fix(core): at menu ux (#10485)
fix AF-2285 1. loading icon will be rendered to the group name 2. make the focused item more stable
This commit is contained in:
@@ -32,6 +32,12 @@ function resolveSignal<T>(data: T | Signal<T>): T {
|
||||
return data instanceof Signal ? data.value : data;
|
||||
}
|
||||
|
||||
const RESERVED_ITEM_KEYS = {
|
||||
createPage: 'create:page',
|
||||
createEdgeless: 'create:edgeless',
|
||||
datePicker: 'date-picker',
|
||||
};
|
||||
|
||||
export class AtMenuConfigService extends Service {
|
||||
constructor(
|
||||
private readonly journalService: JournalService,
|
||||
@@ -50,7 +56,7 @@ export class AtMenuConfigService extends Service {
|
||||
return {
|
||||
getMenus: this.getMenusFn(),
|
||||
mobile: this.getMobileConfig(),
|
||||
autoFocusedItem: this.autoFocusedItem,
|
||||
autoFocusedItemKey: this.autoFocusedItemKey,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -61,18 +67,27 @@ export class AtMenuConfigService extends Service {
|
||||
});
|
||||
}
|
||||
|
||||
private readonly autoFocusedItem = (
|
||||
private readonly autoFocusedItemKey = (
|
||||
menus: LinkedMenuGroup[],
|
||||
query: string
|
||||
): LinkedMenuItem | null => {
|
||||
query: string,
|
||||
currentActiveKey: string | null
|
||||
): string | null => {
|
||||
if (query.trim().length === 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (
|
||||
currentActiveKey === RESERVED_ITEM_KEYS.createPage ||
|
||||
currentActiveKey === RESERVED_ITEM_KEYS.createEdgeless
|
||||
) {
|
||||
return currentActiveKey;
|
||||
}
|
||||
|
||||
// if the second group (linkToDocGroup) is EMPTY,
|
||||
// if the query is NOT empty && the second group (linkToDocGroup) is EMPTY,
|
||||
// we will focus on the first item of the third group (create), which is the "New Doc" item.
|
||||
if (resolveSignal(menus[1].items).length === 0) {
|
||||
return resolveSignal(menus[2].items)[0];
|
||||
return resolveSignal(menus[2].items)[0]?.key;
|
||||
}
|
||||
return null;
|
||||
};
|
||||
@@ -95,11 +110,9 @@ export class AtMenuConfigService extends Service {
|
||||
? originalNewDocMenuGroup.items
|
||||
: originalNewDocMenuGroup.items.value;
|
||||
|
||||
const newDocItem = items.find(item => item.key === 'create');
|
||||
const importItem = items.find(item => item.key === 'import');
|
||||
|
||||
// should have both new doc and import item
|
||||
if (!newDocItem || !importItem) {
|
||||
if (!importItem) {
|
||||
return originalNewDocMenuGroup;
|
||||
}
|
||||
|
||||
@@ -117,7 +130,7 @@ export class AtMenuConfigService extends Service {
|
||||
|
||||
const customNewDocItems: LinkedMenuItem[] = [
|
||||
{
|
||||
key: 'create-page',
|
||||
key: RESERVED_ITEM_KEYS.createPage,
|
||||
icon: NewXxxPageIcon(),
|
||||
name: I18n.t('com.affine.editor.at-menu.create-page', {
|
||||
name: query || I18n.t('Untitled'),
|
||||
@@ -132,7 +145,7 @@ export class AtMenuConfigService extends Service {
|
||||
},
|
||||
},
|
||||
{
|
||||
key: 'create-edgeless',
|
||||
key: RESERVED_ITEM_KEYS.createEdgeless,
|
||||
icon: NewXxxEdgelessIcon(),
|
||||
name: I18n.t('com.affine.editor.at-menu.create-edgeless', {
|
||||
name: query || I18n.t('Untitled'),
|
||||
@@ -190,7 +203,7 @@ export class AtMenuConfigService extends Service {
|
||||
const items: LinkedMenuItem[] = [
|
||||
{
|
||||
icon: DateTimeIcon(),
|
||||
key: 'date-picker',
|
||||
key: RESERVED_ITEM_KEYS.datePicker,
|
||||
name: I18n.t('com.affine.editor.at-menu.date-picker'),
|
||||
action: () => {
|
||||
close();
|
||||
@@ -245,7 +258,7 @@ export class AtMenuConfigService extends Service {
|
||||
|
||||
items.unshift({
|
||||
icon: icon(),
|
||||
key: dateString,
|
||||
key: RESERVED_ITEM_KEYS.datePicker + ':' + dateString,
|
||||
name: alias
|
||||
? html`${alias},
|
||||
<span style="color: ${cssVarV2('text/secondary')}"
|
||||
|
||||
@@ -11,7 +11,7 @@ import { Service } from '@toeverything/infra';
|
||||
import { cssVarV2 } from '@toeverything/theme/v2';
|
||||
import { html } from 'lit';
|
||||
import { unsafeHTML } from 'lit/directives/unsafe-html.js';
|
||||
import { map } from 'rxjs';
|
||||
import { map, takeWhile } from 'rxjs';
|
||||
|
||||
import type { DocDisplayMetaService } from '../../doc-display-meta';
|
||||
import type { DocsSearchService } from '../../docs-search';
|
||||
@@ -105,7 +105,8 @@ export class DocSearchMenuService extends Service {
|
||||
const { signal: isIndexerLoading, cleanup: cleanupIndexerLoading } =
|
||||
createSignalFromObservable(
|
||||
this.docsSearch.indexer.status$.pipe(
|
||||
map(status => status.remaining !== undefined && status.remaining > 0)
|
||||
map(status => status.remaining !== undefined && status.remaining > 0),
|
||||
takeWhile(isLoading => isLoading, true)
|
||||
),
|
||||
false
|
||||
);
|
||||
@@ -127,7 +128,6 @@ export class DocSearchMenuService extends Service {
|
||||
query,
|
||||
}),
|
||||
loading: isIndexerLoading,
|
||||
loadingText: I18n.t('com.affine.editor.at-menu.loading'),
|
||||
items: docsSignal,
|
||||
maxDisplay: MAX_DOCS,
|
||||
overflowText,
|
||||
|
||||
Reference in New Issue
Block a user