diff --git a/lib/community-sync.ts b/lib/community-sync.ts index f83103f..44239e1 100644 --- a/lib/community-sync.ts +++ b/lib/community-sync.ts @@ -699,7 +699,7 @@ export class CommunitySync extends EventTarget { this.dispatchEvent(new CustomEvent("shape-state-changed", { detail: { shapeId, state: 'forgotten', data: this.#doc.shapes?.[shapeId] } })); - this.#scheduleSave(); + this.#saveImmediate(); this.#syncToServer(); } @@ -734,7 +734,7 @@ export class CommunitySync extends EventTarget { this.dispatchEvent(new CustomEvent("shape-state-changed", { detail: { shapeId, state: 'present', data: this.#doc.shapes?.[shapeId] } })); - this.#scheduleSave(); + this.#saveImmediate(); this.#syncToServer(); } @@ -756,7 +756,7 @@ export class CommunitySync extends EventTarget { this.dispatchEvent(new CustomEvent("shape-state-changed", { detail: { shapeId, state: 'deleted', data: this.#doc.shapes?.[shapeId] } })); - this.#scheduleSave(); + this.#saveImmediate(); this.#syncToServer(); } @@ -1013,6 +1013,18 @@ export class CommunitySync extends EventTarget { }, 2000); } + /** Flush doc to IndexedDB immediately (no debounce). Use for destructive ops. */ + #saveImmediate(): void { + if (!this.#offlineStore) return; + if (this.#saveDebounceTimer) { + clearTimeout(this.#saveDebounceTimer); + this.#saveDebounceTimer = null; + } + const binary = Automerge.save(this.#doc); + this.#offlineStore.saveDocImmediate(this.#communitySlug, binary); + this.#offlineStore.saveDocEmergency(this.#communitySlug, binary); + } + #persistSyncState(): void { if (!this.#offlineStore) return; diff --git a/server/shell.ts b/server/shell.ts index 469a51f..ab66d29 100644 --- a/server/shell.ts +++ b/server/shell.ts @@ -228,6 +228,14 @@ export function renderShell(opts: ShellOptions): string { ${spaceEncrypted ? '🔒' : ''} +
+ + +
+
+ + +
@@ -237,14 +245,6 @@ export function renderShell(opts: ShellOptions): string { -
- - -
-
- - -