feat: persist camera zoom per camera group

Each camera now stores zoom state under a group-scoped key
(live:grid-card:zoom:<group>:<camera>), so different groups
can have independent zoom levels for the same camera.

https://claude.ai/code/session_01WidMYGkyBCFf4L9PnFEiZ5
This commit is contained in:
Claude 2026-03-22 12:03:29 +00:00
parent a92a95dea4
commit 3f39819fbe
No known key found for this signature in database
2 changed files with 17 additions and 7 deletions

View File

@ -201,14 +201,23 @@ export function getNextScaleFromWheelDelta(
return clampScale(currentScale + direction * step, minScale, maxScale);
}
export function getCameraZoomStorageKey(cameraName: string): string {
export function getCameraZoomStorageKey(
cameraName: string,
cameraGroup?: string,
): string {
if (cameraGroup) {
return `live:grid-card:zoom:${cameraGroup}:${cameraName}`;
}
return `live:grid-card:zoom:${cameraName}`;
}
export function loadPersistedCameraZoomState(
cameraName: string,
cameraGroup?: string,
): CameraZoomPersistedState | undefined {
const serialized = localStorage.getItem(getCameraZoomStorageKey(cameraName));
const serialized = localStorage.getItem(
getCameraZoomStorageKey(cameraName, cameraGroup),
);
if (!serialized) {
return undefined;
@ -225,9 +234,10 @@ export function loadPersistedCameraZoomState(
export function savePersistedCameraZoomState(
cameraName: string,
state: CameraZoomPersistedState,
cameraGroup?: string,
): void {
localStorage.setItem(
getCameraZoomStorageKey(cameraName),
getCameraZoomStorageKey(cameraName, cameraGroup),
JSON.stringify(state),
);
}

View File

@ -661,7 +661,7 @@ export default function DraggableGridLayout({
return prev;
}
const persisted = loadPersistedCameraZoomState(cameraName);
const persisted = loadPersistedCameraZoomState(cameraName, cameraGroup);
if (!persisted) {
return prev;
}
@ -677,7 +677,7 @@ export default function DraggableGridLayout({
};
});
},
[getCardZoomDimensions],
[cameraGroup, getCardZoomDimensions],
);
const getDefaultZoomTransform = useCallback(
@ -724,7 +724,7 @@ export default function DraggableGridLayout({
contentHeight: content?.clientHeight ?? bounds.height,
});
savePersistedCameraZoomState(cameraName, persisted);
savePersistedCameraZoomState(cameraName, persisted, cameraGroup);
return {
...prev,
@ -732,7 +732,7 @@ export default function DraggableGridLayout({
};
});
},
[getDefaultZoomTransform],
[cameraGroup, getDefaultZoomTransform],
);
const detachCardZoomWheelListener = useCallback((cameraName: string) => {