mirror of
https://github.com/Matysh/houseplan-card
synced 2026-10-07 23:19:14 +00:00
feat(adoption): one owner for config/layout identity and the adoption sequence
`src/config-adoption.ts` owns config/layout with revision and fingerprint; the host keeps `_serverCfg`/`_cfgRev`/`_layout`/`_layoutRev` as delegates. All seven authoritative adoptions go through `adoptAuthoritativeGated` (backdrop readiness → continuity → adopt → profile tail); the post-write paths (space/delete ×2, optimize_undo, import/apply) gain the gate and take revisions from the re-read bodies. `rollbackOptimistic` moves to the owner; plan-optimize, space copy and the vacuum writers stop assigning identity. Issue: #500 User-Visible: no
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
import type { ConfigAdoption } from './config-adoption';
|
||||
import type { DeviceLayout } from './device-position-history';
|
||||
import type { ServerConfig } from './types';
|
||||
import { contentFingerprint } from './visual-continuity';
|
||||
|
||||
interface Clearable { clear(): void }
|
||||
interface Flushable { pending(): boolean; flush(): void }
|
||||
@@ -9,11 +9,10 @@ export interface PlanOptimizeWriteHost {
|
||||
hass: { callWS(message: Record<string, unknown>): Promise<Record<string, unknown>> };
|
||||
_saveConfigDebounced: Flushable;
|
||||
_writeChain: Promise<void>;
|
||||
_cfgRev: number;
|
||||
_cfgContentFingerprint: string;
|
||||
_layoutRev: number;
|
||||
_serverCfg: ServerConfig | null;
|
||||
_layout: DeviceLayout;
|
||||
readonly _cfgRev: number;
|
||||
readonly _layoutRev: number;
|
||||
/** #500: identity owner — bodies and revisions of the pair land through it. */
|
||||
readonly _adoption: ConfigAdoption;
|
||||
_geometryHistory: Clearable;
|
||||
_devicePositionHistory: Clearable;
|
||||
_cancelDeviceDrag(): boolean;
|
||||
@@ -30,9 +29,6 @@ export interface PlanOptimizeWriteHost {
|
||||
requestUpdate(): void;
|
||||
}
|
||||
|
||||
const finiteRevision = (value: unknown, fallback: number): number =>
|
||||
typeof value === 'number' && Number.isFinite(value) ? value : fallback;
|
||||
|
||||
/** The one adoption path shared by the Optimize dialog and Copy space. */
|
||||
export async function commitPlanOptimization(
|
||||
host: PlanOptimizeWriteHost,
|
||||
@@ -48,14 +44,11 @@ export async function commitPlanOptimization(
|
||||
expected_config_rev: host._cfgRev,
|
||||
expected_layout_rev: host._layoutRev,
|
||||
});
|
||||
host._serverCfg = config;
|
||||
host._cfgContentFingerprint = contentFingerprint(config);
|
||||
host._layout = layout;
|
||||
// Both bodies with both revisions from the reply that accepted them (#500 I2).
|
||||
host._adoption.acceptPairWrite(config, layout, response);
|
||||
host._geometryHistory.clear();
|
||||
host._cancelDeviceDrag();
|
||||
host._devicePositionHistory.clear();
|
||||
host._cfgRev = finiteRevision(response.config_rev, host._cfgRev + 1);
|
||||
host._layoutRev = finiteRevision(response.layout_rev, host._layoutRev + 1);
|
||||
host._canOptimizeUndo = response.can_undo === true;
|
||||
host._undoKind = response.can_undo === true ? 'optimize' : null;
|
||||
host._dirtyPos.clear();
|
||||
|
||||
Reference in New Issue
Block a user