mirror of
https://github.com/toeverything/AFFiNE.git
synced 2026-07-12 07:36:42 +08:00
feat(core): cache navigation collapsed state (#13315)
<!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Refactor** * Collapsible section state in navigation panels is now managed using a unified path-based approach, enabling more consistent and centralized control across desktop and mobile interfaces. * The collapsed/expanded state of navigation sections and nodes is now persistently tracked using hierarchical paths, improving reliability across sessions and devices. * Internal state management is streamlined, with local state replaced by a shared service, resulting in more predictable navigation behavior. * **Chores** * Removed obsolete types and legacy section management logic for improved maintainability. <!-- end of auto-generated comment: release notes by coderabbit.ai -->
This commit is contained in:
-39
@@ -1,39 +0,0 @@
|
||||
import { Entity, LiveData } from '@toeverything/infra';
|
||||
import { map } from 'rxjs';
|
||||
|
||||
import type { GlobalCache } from '../../storage';
|
||||
import type { CollapsibleSectionName } from '../types';
|
||||
|
||||
const DEFAULT_COLLAPSABLE_STATE: Record<CollapsibleSectionName, boolean> = {
|
||||
recent: true,
|
||||
favorites: false,
|
||||
organize: false,
|
||||
collections: true,
|
||||
tags: true,
|
||||
favoritesOld: true,
|
||||
migrationFavorites: true,
|
||||
others: false,
|
||||
};
|
||||
|
||||
export class NavigationPanelSection extends Entity<{
|
||||
name: CollapsibleSectionName;
|
||||
}> {
|
||||
name: CollapsibleSectionName = this.props.name;
|
||||
key = `explorer.section.${this.name}`;
|
||||
defaultValue = DEFAULT_COLLAPSABLE_STATE[this.name];
|
||||
|
||||
constructor(private readonly globalCache: GlobalCache) {
|
||||
super();
|
||||
}
|
||||
|
||||
collapsed$ = LiveData.from(
|
||||
this.globalCache
|
||||
.watch<boolean>(this.key)
|
||||
.pipe(map(v => v ?? this.defaultValue)),
|
||||
this.defaultValue
|
||||
);
|
||||
|
||||
setCollapsed(collapsed: boolean) {
|
||||
this.globalCache.set(this.key, collapsed);
|
||||
}
|
||||
}
|
||||
@@ -1,15 +1,12 @@
|
||||
import { type Framework } from '@toeverything/infra';
|
||||
|
||||
import { GlobalCache } from '../storage';
|
||||
import { WorkspaceScope } from '../workspace';
|
||||
import { NavigationPanelSection } from './entities/navigation-panel-section';
|
||||
import { WorkspaceScope, WorkspaceService } from '../workspace';
|
||||
import { NavigationPanelService } from './services/navigation-panel';
|
||||
export { NavigationPanelService } from './services/navigation-panel';
|
||||
export type { CollapsibleSectionName } from './types';
|
||||
|
||||
export function configureNavigationPanelModule(framework: Framework) {
|
||||
framework
|
||||
.scope(WorkspaceScope)
|
||||
.service(NavigationPanelService)
|
||||
.entity(NavigationPanelSection, [GlobalCache]);
|
||||
.service(NavigationPanelService, [GlobalCache, WorkspaceService]);
|
||||
}
|
||||
|
||||
@@ -1,25 +1,47 @@
|
||||
import { Service } from '@toeverything/infra';
|
||||
import { LiveData, Service } from '@toeverything/infra';
|
||||
|
||||
import { NavigationPanelSection } from '../entities/navigation-panel-section';
|
||||
import type { CollapsibleSectionName } from '../types';
|
||||
import type { GlobalCache } from '../../storage/providers/global';
|
||||
import type { WorkspaceService } from '../../workspace';
|
||||
|
||||
const allSectionName: Array<CollapsibleSectionName> = [
|
||||
'recent', // mobile only
|
||||
'favorites',
|
||||
'organize',
|
||||
'collections',
|
||||
'tags',
|
||||
'favoritesOld',
|
||||
'migrationFavorites',
|
||||
'others',
|
||||
];
|
||||
const DEFAULT_COLLAPSABLE_STATE: Record<string, boolean> = {
|
||||
recent: true,
|
||||
favorites: false,
|
||||
organize: false,
|
||||
collections: true,
|
||||
tags: true,
|
||||
favoritesOld: true,
|
||||
migrationFavorites: true,
|
||||
others: false,
|
||||
};
|
||||
|
||||
export class NavigationPanelService extends Service {
|
||||
readonly sections = allSectionName.reduce(
|
||||
(prev, name) =>
|
||||
Object.assign(prev, {
|
||||
[name]: this.framework.createEntity(NavigationPanelSection, { name }),
|
||||
}),
|
||||
{} as Record<CollapsibleSectionName, NavigationPanelSection>
|
||||
);
|
||||
constructor(
|
||||
private readonly globalCache: GlobalCache,
|
||||
private readonly workspaceService: WorkspaceService
|
||||
) {
|
||||
super();
|
||||
}
|
||||
|
||||
private readonly collapsedCache = new Map<string, LiveData<boolean>>();
|
||||
|
||||
collapsed$(path: string[]) {
|
||||
const pathKey = path.join(':');
|
||||
const key = `navigation:${this.workspaceService.workspace.id}:${pathKey}`;
|
||||
const cached$ = this.collapsedCache.get(key);
|
||||
if (!cached$) {
|
||||
const liveData$ = LiveData.from(
|
||||
this.globalCache.watch<boolean>(key),
|
||||
undefined
|
||||
).map(v => v ?? DEFAULT_COLLAPSABLE_STATE[pathKey] ?? true);
|
||||
this.collapsedCache.set(key, liveData$);
|
||||
return liveData$;
|
||||
}
|
||||
return cached$;
|
||||
}
|
||||
|
||||
setCollapsed(path: string[], collapsed: boolean) {
|
||||
const pathKey = path.join(':');
|
||||
const key = `navigation:${this.workspaceService.workspace.id}:${pathKey}`;
|
||||
this.globalCache.set(key, collapsed);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,9 +0,0 @@
|
||||
export type CollapsibleSectionName =
|
||||
| 'recent'
|
||||
| 'collections'
|
||||
| 'favorites'
|
||||
| 'tags'
|
||||
| 'organize'
|
||||
| 'favoritesOld'
|
||||
| 'migrationFavorites'
|
||||
| 'others';
|
||||
Reference in New Issue
Block a user