fix(core): persist sidebar open state and width to prevent flash on load (#12743)

https://github.com/user-attachments/assets/6b61c9f2-80bd-4f2c-943d-1fd610a69ecf

This PR change updates the sidebar initialization so it reads the open
and width values from persistent storage. This prevents the UI from
flashing open by default on startup.

Both left and right sidebars restore correctly from the last known state
from storage.

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

- **New Features**
- Sidebar and workbench panels now retain their open/closed status and
width based on your previously saved preferences, providing a more
personalized and consistent experience across sessions.
- **Tests**
- Added comprehensive tests to ensure sidebar state persistence and
behavior are reliable and consistent.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->

---------

Co-authored-by: Norkz <richardlora557@gmail.com>
This commit is contained in:
Richard Lora 2025-06-23 06:46:10 -04:00 committed by GitHub
parent 4507c88792
commit 74106ba7c6
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 59 additions and 5 deletions

View File

@ -0,0 +1,54 @@
import { Framework, MemoryMemento } from '@toeverything/infra';
import { beforeEach, describe, expect, test } from 'vitest';
import { AppSidebarState } from '../../providers/storage';
import { AppSidebar } from '../app-sidebar';
describe('AppSidebar', () => {
let framework: Framework;
let memento: MemoryMemento;
let sidebar: AppSidebar;
beforeEach(() => {
framework = new Framework();
memento = new MemoryMemento();
framework.entity(AppSidebar, [AppSidebarState]);
framework.impl(AppSidebarState, memento);
sidebar = framework.provider().get(AppSidebar);
});
test('default values', () => {
expect(sidebar.open$.value).toBe(true);
expect(sidebar.width$.value).toBe(248);
expect(sidebar.smallScreenMode$.value).toBe(false);
expect(sidebar.hovering$.value).toBe(false);
});
test('state setters update live data and storage', () => {
sidebar.setOpen(false);
expect(sidebar.open$.value).toBe(false);
expect(memento.get('open')).toBe(false);
sidebar.toggleSidebar();
expect(sidebar.open$.value).toBe(true);
expect(memento.get('open')).toBe(true);
sidebar.setWidth(260);
expect(sidebar.width$.value).toBe(260);
expect(memento.get('width')).toBe(260);
sidebar.setSmallScreenMode(true);
expect(sidebar.smallScreenMode$.value).toBe(true);
sidebar.setHovering(true);
expect(sidebar.hovering$.value).toBe(true);
sidebar.setPreventHovering(true);
expect(sidebar.preventHovering$.value).toBe(true);
sidebar.setResizing(true);
expect(sidebar.resizing$.value).toBe(true);
});
test('getCachedAppSidebarOpenState', () => {
sidebar.setOpen(false);
expect(sidebar.getCachedAppSidebarOpenState()).toBe(false);
});
});

View File

@ -21,14 +21,14 @@ export class AppSidebar extends Entity {
this.appSidebarState
.watch<boolean>(APP_SIDEBAR_STATE.OPEN)
.pipe(map(value => value ?? true)),
true
this.appSidebarState.get<boolean>(APP_SIDEBAR_STATE.OPEN) ?? true
);
width$ = LiveData.from(
this.appSidebarState
.watch<number>(APP_SIDEBAR_STATE.WIDTH)
.pipe(map(value => value ?? 248)),
248
this.appSidebarState.get<number>(APP_SIDEBAR_STATE.WIDTH) ?? 248
);
/**

View File

@ -58,14 +58,14 @@ export class Workbench extends Entity {
});
sidebarOpen$ = LiveData.from(
this.globalState.watch<boolean>(sidebarOpenKey),
false
this.globalState.get<boolean>(sidebarOpenKey) ?? false
);
setSidebarOpen(open: boolean) {
this.globalState.set(sidebarOpenKey, open);
}
sidebarWidth$ = LiveData.from(
this.globalState.watch<number>(sidebarWidthKey),
320
this.globalState.get<number>(sidebarWidthKey) ?? 320
);
setSidebarWidth(width: number) {
this.globalState.set(sidebarWidthKey, width);
@ -73,7 +73,7 @@ export class Workbench extends Entity {
workspaceSelectorOpen$ = LiveData.from(
this.globalState.watch<boolean>(workspaceSelectorOpenKey),
false
this.globalState.get<boolean>(workspaceSelectorOpenKey) ?? false
);
setWorkspaceSelectorOpen(open: boolean) {
this.globalState.set(workspaceSelectorOpenKey, open);