feat: add spatial workspace refactor design document and implement dirty tracking for layout persistence.
This commit is contained in:
@@ -26,6 +26,7 @@ export class LayoutCard implements LayoutCardState {
|
||||
public store: LayoutStore;
|
||||
public dragStartX: number = 0;
|
||||
public dragStartY: number = 0;
|
||||
public isDirty: boolean = false;
|
||||
private dragOffset: { x: number, y: number } | null = null;
|
||||
|
||||
constructor(id: string, store: LayoutStore, initialData: Partial<LayoutCardState> = {}, ref: HTMLElement | null = null) {
|
||||
@@ -56,18 +57,23 @@ export class LayoutCard implements LayoutCardState {
|
||||
this.update({
|
||||
x: newX,
|
||||
y: newY
|
||||
});
|
||||
}, { markDirty: true });
|
||||
}
|
||||
|
||||
finishDrag() {
|
||||
this.dragOffset = null;
|
||||
}
|
||||
|
||||
update(changes: Partial<LayoutCardState>) {
|
||||
update(changes: Partial<LayoutCardState>, options: { markDirty?: boolean } = {}) {
|
||||
Object.assign(this, changes);
|
||||
if (changes.width !== undefined || changes.height !== undefined) {
|
||||
this.recalculateRadii();
|
||||
}
|
||||
|
||||
if (options.markDirty) {
|
||||
this.isDirty = true;
|
||||
}
|
||||
|
||||
this.applyTransform();
|
||||
}
|
||||
|
||||
@@ -181,7 +187,7 @@ export class LayoutCard implements LayoutCardState {
|
||||
}
|
||||
|
||||
snapTo(x: number, y: number) {
|
||||
this.update({ x, y });
|
||||
this.update({ x, y }, { markDirty: true });
|
||||
|
||||
if (!this.ref)
|
||||
return;
|
||||
@@ -273,9 +279,15 @@ export class LayoutStore {
|
||||
height,
|
||||
z
|
||||
}, ref);
|
||||
|
||||
// If it was a saved layout, it's not dirty.
|
||||
if (!saved) {
|
||||
card.isDirty = true;
|
||||
}
|
||||
|
||||
this.items.set(id, card);
|
||||
} else {
|
||||
card.update({ width, height });
|
||||
card.update({ width, height }, { markDirty: false });
|
||||
}
|
||||
|
||||
// Always update ref and ensure transform is applied
|
||||
@@ -334,7 +346,7 @@ export class LayoutStore {
|
||||
|
||||
// Assign new Z-indices
|
||||
for (const card of cards) {
|
||||
card.update({ z: this.zCounter++ });
|
||||
card.update({ z: this.zCounter++ }, { markDirty: true });
|
||||
}
|
||||
}
|
||||
|
||||
@@ -371,7 +383,7 @@ export class LayoutStore {
|
||||
for (const [id, card] of this.items) {
|
||||
const saved = this.savedLayouts.get(id);
|
||||
if (saved) {
|
||||
card.update(saved);
|
||||
card.update(saved, { markDirty: false });
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -379,7 +391,10 @@ export class LayoutStore {
|
||||
async saveLayout() {
|
||||
if (!this.tenantId || !this.viewId) return;
|
||||
|
||||
const entries = Array.from(this.items.values()).map(card => ({
|
||||
const dirtyCards = Array.from(this.items.values()).filter(card => card.isDirty);
|
||||
if (dirtyCards.length === 0) return;
|
||||
|
||||
const entries = dirtyCards.map(card => ({
|
||||
documentId: card.id,
|
||||
centerX: card.x,
|
||||
centerY: card.y,
|
||||
@@ -393,5 +408,10 @@ export class LayoutStore {
|
||||
viewId: this.viewId,
|
||||
entries
|
||||
});
|
||||
|
||||
// Reset dirty flag for saved cards
|
||||
for (const card of dirtyCards) {
|
||||
card.isDirty = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user