mirror of
https://github.com/Memo-2023/mana-monorepo.git
synced 2026-05-14 23:21:08 +02:00
perf(workbench): split SceneAppBar registration from prop updates
The single $effect that wired SceneAppBar into bottomBarStore was re-writing barComponent on every reactive tick — every change to openApps, locale or activeSceneId redirected through .set() and re-assigned the component reference identically. Add a setProps() method to bottomBarStore that mutates only barProps, and split the workbench effect in two: a registration effect that fires on the scenes-empty/non-empty transition, and a props effect that pushes fresh data without touching barComponent. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
aa29ad860f
commit
e95d0487b9
2 changed files with 37 additions and 12 deletions
|
|
@ -26,6 +26,17 @@ export const bottomBarStore = {
|
|||
barComponent = component;
|
||||
barProps = props;
|
||||
},
|
||||
/**
|
||||
* Update only the props of the currently-registered bar component.
|
||||
* Use this from reactive blocks that frequently produce fresh prop
|
||||
* objects (e.g. derived arrays) — calling `set(...)` in those
|
||||
* places needlessly re-writes barComponent every tick, which
|
||||
* notifies subscribers even when the component identity hasn't
|
||||
* changed.
|
||||
*/
|
||||
setProps(props: Record<string, unknown>) {
|
||||
barProps = props;
|
||||
},
|
||||
clear() {
|
||||
barComponent = null;
|
||||
barProps = {};
|
||||
|
|
|
|||
|
|
@ -121,21 +121,35 @@
|
|||
}
|
||||
|
||||
// ── Register SceneAppBar in the layout's bottom-stack ───
|
||||
// Split into two effects so prop churn (carouselPages re-deriving on
|
||||
// every openApps change) doesn't re-write barComponent. The first
|
||||
// effect handles registration/teardown when scenes appear/disappear;
|
||||
// the second pushes fresh props on every reactive tick.
|
||||
let barRegistered = $state(false);
|
||||
$effect(() => {
|
||||
if (scenes.length > 0) {
|
||||
bottomBarStore.set(SceneAppBar, {
|
||||
scenes,
|
||||
activeSceneId,
|
||||
pages: carouselPages,
|
||||
onSceneSelect: (id: string) => workbenchScenesStore.setActiveScene(id),
|
||||
onSceneCreate: (name: string) => workbenchScenesStore.createScene({ name }),
|
||||
onSceneContextMenu: handleSceneContextMenu,
|
||||
onAppClick: scrollToPage,
|
||||
onAppContextMenu: (e: MouseEvent, id: string) => handleTabContextMenu(e, id),
|
||||
onAddApp: () => (showPicker = !showPicker),
|
||||
});
|
||||
const hasScenes = scenes.length > 0;
|
||||
if (hasScenes && !barRegistered) {
|
||||
bottomBarStore.set(SceneAppBar, {});
|
||||
barRegistered = true;
|
||||
} else if (!hasScenes && barRegistered) {
|
||||
bottomBarStore.clear();
|
||||
barRegistered = false;
|
||||
}
|
||||
});
|
||||
$effect(() => {
|
||||
if (!barRegistered) return;
|
||||
bottomBarStore.setProps({
|
||||
scenes,
|
||||
activeSceneId,
|
||||
pages: carouselPages,
|
||||
onSceneSelect: (id: string) => workbenchScenesStore.setActiveScene(id),
|
||||
onSceneCreate: (name: string) => workbenchScenesStore.createScene({ name }),
|
||||
onSceneContextMenu: handleSceneContextMenu,
|
||||
onAppClick: scrollToPage,
|
||||
onAppContextMenu: (e: MouseEvent, id: string) => handleTabContextMenu(e, id),
|
||||
onAddApp: () => (showPicker = !showPicker),
|
||||
});
|
||||
});
|
||||
|
||||
// ── App CRUD (delegated to active scene) ────────────────
|
||||
function handleAddApp(appId: string) {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue