Merge branch 'dev'

This commit is contained in:
Jeff Emmett 2026-03-22 13:29:45 -07:00
commit 13c2062fad
2 changed files with 23 additions and 11 deletions

View File

@ -699,7 +699,7 @@ export class CommunitySync extends EventTarget {
this.dispatchEvent(new CustomEvent("shape-state-changed", { this.dispatchEvent(new CustomEvent("shape-state-changed", {
detail: { shapeId, state: 'forgotten', data: this.#doc.shapes?.[shapeId] } detail: { shapeId, state: 'forgotten', data: this.#doc.shapes?.[shapeId] }
})); }));
this.#scheduleSave(); this.#saveImmediate();
this.#syncToServer(); this.#syncToServer();
} }
@ -734,7 +734,7 @@ export class CommunitySync extends EventTarget {
this.dispatchEvent(new CustomEvent("shape-state-changed", { this.dispatchEvent(new CustomEvent("shape-state-changed", {
detail: { shapeId, state: 'present', data: this.#doc.shapes?.[shapeId] } detail: { shapeId, state: 'present', data: this.#doc.shapes?.[shapeId] }
})); }));
this.#scheduleSave(); this.#saveImmediate();
this.#syncToServer(); this.#syncToServer();
} }
@ -756,7 +756,7 @@ export class CommunitySync extends EventTarget {
this.dispatchEvent(new CustomEvent("shape-state-changed", { this.dispatchEvent(new CustomEvent("shape-state-changed", {
detail: { shapeId, state: 'deleted', data: this.#doc.shapes?.[shapeId] } detail: { shapeId, state: 'deleted', data: this.#doc.shapes?.[shapeId] }
})); }));
this.#scheduleSave(); this.#saveImmediate();
this.#syncToServer(); this.#syncToServer();
} }
@ -1013,6 +1013,18 @@ export class CommunitySync extends EventTarget {
}, 2000); }, 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 { #persistSyncState(): void {
if (!this.#offlineStore) return; if (!this.#offlineStore) return;

View File

@ -228,6 +228,14 @@ export function renderShell(opts: ShellOptions): string {
<a href="/" style="display:flex;align-items:center;margin-right:4px"><img src="/favicon.png" alt="rSpace" class="rstack-header__logo"></a> <a href="/" style="display:flex;align-items:center;margin-right:4px"><img src="/favicon.png" alt="rSpace" class="rstack-header__logo"></a>
<rstack-app-switcher current="${escapeAttr(moduleId)}"></rstack-app-switcher> <rstack-app-switcher current="${escapeAttr(moduleId)}"></rstack-app-switcher>
<rstack-space-switcher current="${escapeAttr(spaceSlug)}" name="${escapeAttr(spaceName || spaceSlug)}"></rstack-space-switcher>${spaceEncrypted ? '<span class="rstack-header__encrypted" title="End-to-end encrypted space">&#x1F512;</span>' : ''} <rstack-space-switcher current="${escapeAttr(spaceSlug)}" name="${escapeAttr(spaceName || spaceSlug)}"></rstack-space-switcher>${spaceEncrypted ? '<span class="rstack-header__encrypted" title="End-to-end encrypted space">&#x1F512;</span>' : ''}
<div class="rstack-header__dropdown-wrap">
<button class="rstack-header__history-btn" id="history-btn" title="History"><svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10"/><polyline points="12 6 12 12 16 14"/></svg></button>
<rstack-history-panel></rstack-history-panel>
</div>
<div class="rstack-header__dropdown-wrap">
<button class="rstack-header__settings-btn" id="settings-btn" title="Space Settings"><svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="3"/><path d="M19.4 15a1.65 1.65 0 0 0 .33 1.82l.06.06a2 2 0 0 1 0 2.83 2 2 0 0 1-2.83 0l-.06-.06a1.65 1.65 0 0 0-1.82-.33 1.65 1.65 0 0 0-1 1.51V21a2 2 0 0 1-2 2 2 2 0 0 1-2-2v-.09A1.65 1.65 0 0 0 9 19.4a1.65 1.65 0 0 0-1.82.33l-.06.06a2 2 0 0 1-2.83 0 2 2 0 0 1 0-2.83l.06-.06A1.65 1.65 0 0 0 4.68 15a1.65 1.65 0 0 0-1.51-1H3a2 2 0 0 1-2-2 2 2 0 0 1 2-2h.09A1.65 1.65 0 0 0 4.6 9a1.65 1.65 0 0 0-.33-1.82l-.06-.06a2 2 0 0 1 0-2.83 2 2 0 0 1 2.83 0l.06.06A1.65 1.65 0 0 0 9 4.68a1.65 1.65 0 0 0 1-1.51V3a2 2 0 0 1 2-2 2 2 0 0 1 2 2v.09a1.65 1.65 0 0 0 1 1.51 1.65 1.65 0 0 0 1.82-.33l.06-.06a2 2 0 0 1 2.83 0 2 2 0 0 1 0 2.83l-.06.06A1.65 1.65 0 0 0 19.4 9a1.65 1.65 0 0 0 1.51 1H21a2 2 0 0 1 2 2 2 2 0 0 1-2 2h-.09a1.65 1.65 0 0 0-1.51 1z"/></svg></button>
<rstack-space-settings space="${escapeAttr(spaceSlug)}" module-id="${escapeAttr(moduleId)}"></rstack-space-settings>
</div>
</div> </div>
<div class="rstack-header__center"> <div class="rstack-header__center">
<rstack-mi></rstack-mi> <rstack-mi></rstack-mi>
@ -237,14 +245,6 @@ export function renderShell(opts: ShellOptions): string {
<rstack-offline-indicator></rstack-offline-indicator> <rstack-offline-indicator></rstack-offline-indicator>
<rstack-notification-bell></rstack-notification-bell> <rstack-notification-bell></rstack-notification-bell>
<rstack-share-panel></rstack-share-panel> <rstack-share-panel></rstack-share-panel>
<div class="rstack-header__dropdown-wrap">
<button class="rstack-header__history-btn" id="history-btn" title="History"><svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10"/><polyline points="12 6 12 12 16 14"/></svg></button>
<rstack-history-panel></rstack-history-panel>
</div>
<div class="rstack-header__dropdown-wrap">
<button class="rstack-header__settings-btn" id="settings-btn" title="Space Settings"><svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="3"/><path d="M19.4 15a1.65 1.65 0 0 0 .33 1.82l.06.06a2 2 0 0 1 0 2.83 2 2 0 0 1-2.83 0l-.06-.06a1.65 1.65 0 0 0-1.82-.33 1.65 1.65 0 0 0-1 1.51V21a2 2 0 0 1-2 2 2 2 0 0 1-2-2v-.09A1.65 1.65 0 0 0 9 19.4a1.65 1.65 0 0 0-1.82.33l-.06.06a2 2 0 0 1-2.83 0 2 2 0 0 1 0-2.83l.06-.06A1.65 1.65 0 0 0 4.68 15a1.65 1.65 0 0 0-1.51-1H3a2 2 0 0 1-2-2 2 2 0 0 1 2-2h.09A1.65 1.65 0 0 0 4.6 9a1.65 1.65 0 0 0-.33-1.82l-.06-.06a2 2 0 0 1 0-2.83 2 2 0 0 1 2.83 0l.06.06A1.65 1.65 0 0 0 9 4.68a1.65 1.65 0 0 0 1-1.51V3a2 2 0 0 1 2-2 2 2 0 0 1 2 2v.09a1.65 1.65 0 0 0 1 1.51 1.65 1.65 0 0 0 1.82-.33l.06-.06a2 2 0 0 1 2.83 0 2 2 0 0 1 0 2.83l-.06.06A1.65 1.65 0 0 0 19.4 9a1.65 1.65 0 0 0 1.51 1H21a2 2 0 0 1 2 2 2 2 0 0 1-2 2h-.09a1.65 1.65 0 0 0-1.51 1z"/></svg></button>
<rstack-space-settings space="${escapeAttr(spaceSlug)}" module-id="${escapeAttr(moduleId)}"></rstack-space-settings>
</div>
<rstack-identity></rstack-identity> <rstack-identity></rstack-identity>
</div> </div>
</header> </header>