Full document, spreadsheet, slideshow, and diagram tooling
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

fix: replace misleading "Connecting" status with "Local" in all editors

The status chip showed "Connecting…" because event listeners were
registered after await provider.whenReady, missing the connect/sync
events. Since there's no server to connect to, replace with a static
"Local" label and green dot across all 6 editor templates.

Chainlink: #14

+30 -45
+2 -2
src/calendar/index.html
··· 29 29 <span id="save-text">Saved</span> 30 30 </div> 31 31 <div class="status-indicator" id="status"> 32 - <span class="status-dot" id="status-dot"></span> 33 - <span id="status-text">Connecting&hellip;</span> 32 + <span class="status-dot connected" id="status-dot"></span> 33 + <span id="status-text">Local</span> 34 34 </div> 35 35 <button class="btn-icon" id="btn-cal-settings" title="Calendar settings" aria-label="Calendar settings"> 36 36 <svg class="tb-icon icon-gear" viewBox="0 0 16 16" style="width:16px;height:16px" fill="none" stroke="currentColor" stroke-width="1.25" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M14.57 6.24 L14.57 9.76 L12.44 9.19 L11.98 10.30 L13.89 11.40 L11.40 13.89 L10.30 11.98 L9.19 12.44 L9.76 14.57 L6.24 14.57 L6.81 12.44 L5.70 11.98 L4.60 13.89 L2.11 11.40 L4.02 10.30 L3.56 9.19 L1.43 9.76 L1.43 6.24 L3.56 6.81 L4.02 5.70 L2.11 4.60 L4.60 2.11 L5.70 4.02 L6.81 3.56 L6.24 1.43 L9.76 1.43 L9.19 3.56 L10.30 4.02 L11.40 2.11 L13.89 4.60 L11.98 5.70 L12.44 6.81 Z"/><circle cx="8" cy="8" r="2.2"/></svg>
+2 -2
src/diagrams/index.html
··· 40 40 <span id="save-text">Saved</span> 41 41 </div> 42 42 <div class="status-indicator" id="status"> 43 - <span class="status-dot" id="status-dot"></span> 44 - <span id="status-text">Connecting&hellip;</span> 43 + <span class="status-dot connected" id="status-dot"></span> 44 + <span id="status-text">Local</span> 45 45 </div> 46 46 </div> 47 47
+2 -2
src/docs/index.html
··· 68 68 <span id="save-text">Saved</span> 69 69 </div> 70 70 <div class="status-indicator" id="status"> 71 - <span class="status-dot" id="status-dot"></span> 72 - <span id="status-text">Connecting…</span> 71 + <span class="status-dot connected" id="status-dot"></span> 72 + <span id="status-text">Local</span> 73 73 </div> 74 74 <button class="btn-icon" id="btn-shortcuts" title="Keyboard shortcuts">?</button> 75 75 <button class="theme-toggle" id="theme-toggle" title="Toggle dark mode"></button>
+3 -3
src/docs/main.ts
··· 355 355 }, 500); 356 356 }); 357 357 358 - // --- Connection status --- 358 + // --- Storage status --- 359 359 const statusDot = $('status-dot'); 360 360 const statusText = $('status-text'); 361 361 362 362 provider.on('status', ({ connected }) => { 363 363 statusDot.classList.toggle('connected', connected); 364 - statusText.textContent = connected ? 'Connected' : 'Reconnecting\u2026'; 364 + statusText.textContent = connected ? 'Local' : 'Error'; 365 365 }); 366 366 367 367 provider.on('sync', () => { 368 - statusText.textContent = 'Synced'; 368 + statusText.textContent = 'Local'; 369 369 370 370 // Check for pending file import from landing page drag-and-drop 371 371 const pendingKey = `pending-import-${docId}`;
+2 -2
src/forms/index.html
··· 30 30 <span id="save-text">Saved</span> 31 31 </div> 32 32 <div class="status-indicator" id="status"> 33 - <span class="status-dot" id="status-dot"></span> 34 - <span id="status-text">Connecting&hellip;</span> 33 + <span class="status-dot connected" id="status-dot"></span> 34 + <span id="status-text">Local</span> 35 35 </div> 36 36 <button class="btn-icon" id="btn-ai-chat" title="AI Chat (Cmd+Shift+L)"> 37 37 <svg class="tb-icon" viewBox="0 0 16 16" style="width:16px;height:16px" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><path d="M2 3h12a1 1 0 0 1 1 1v7a1 1 0 0 1-1 1H5l-3 3V4a1 1 0 0 1 1-1z"/><circle cx="5.5" cy="7.5" r="0.5" fill="currentColor" stroke="none"/><circle cx="8" cy="7.5" r="0.5" fill="currentColor" stroke="none"/><circle cx="10.5" cy="7.5" r="0.5" fill="currentColor" stroke="none"/></svg>
+7 -22
src/lib/status-chips.ts
··· 1 1 /** 2 - * Status chips — "Synced" + "E2EE" indicators rendered next to the 3 - * shared "Saved" indicator in every editor's topbar. 2 + * Status chips — "Local" indicator rendered next to the shared "Saved" 3 + * indicator in every editor's topbar. 4 4 * 5 - * Regression: #695 — before this helper, only docs and sheets showed the 6 - * Synced/E2EE chips. Slides, forms, diagrams, and calendar only surfaced 7 - * the Saved indicator, leaving users guessing whether their data had 8 - * actually synced to the server and whether it was encrypted. 9 - * 10 - * Expected DOM in the host page: 11 - * <div class="status-indicator" id="status"> 12 - * <span class="status-dot" id="status-dot"></span> 13 - * <span id="status-text">Connecting…</span> 14 - * </div> 15 - * <div class="status-indicator"> 16 - * <span class="status-dot encrypted"></span> 17 - * <span>E2EE</span> 18 - * </div> 19 - * 20 - * The E2EE chip is static (there's nothing dynamic about it — the doc is 21 - * always encrypted). This helper only wires the Synced chip to the 22 - * provider's `status` + `sync` events. 5 + * In local-only mode the status chip stays at "Local" (green dot). 6 + * This helper wires the chip to provider events so it can reflect 7 + * save errors if they occur. 23 8 */ 24 9 25 10 export interface StatusChipsDeps { ··· 36 21 37 22 deps.provider.on('status', (payload: { connected: boolean }) => { 38 23 statusDot.classList.toggle('connected', payload.connected); 39 - statusText.textContent = payload.connected ? 'Connected' : 'Reconnecting\u2026'; 24 + statusText.textContent = payload.connected ? 'Local' : 'Error'; 40 25 }); 41 26 42 27 deps.provider.on('sync', () => { 43 - statusText.textContent = 'Synced'; 28 + statusText.textContent = 'Local'; 44 29 statusDot.classList.add('connected'); 45 30 }); 46 31 }
+1 -1
src/sheets/collaboration-ui.ts
··· 20 20 21 21 deps.provider.on('status', ({ connected }: { connected: boolean }) => { 22 22 statusDot.classList.toggle('connected', connected); 23 - statusText.textContent = connected ? 'Connected' : 'Reconnecting...'; 23 + statusText.textContent = connected ? 'Local' : 'Error'; 24 24 }); 25 25 } 26 26
+2 -2
src/sheets/index.html
··· 43 43 <span id="save-text">Saved</span> 44 44 </div> 45 45 <div class="status-indicator" id="status"> 46 - <span class="status-dot" id="status-dot"></span> 47 - <span id="status-text">Connecting…</span> 46 + <span class="status-dot connected" id="status-dot"></span> 47 + <span id="status-text">Local</span> 48 48 </div> 49 49 <button class="btn-icon" id="btn-shortcuts" title="Keyboard shortcuts">?</button> 50 50 <button class="theme-toggle" id="theme-toggle" title="Toggle dark mode"></button>
+1 -1
src/sheets/sync-observers.ts
··· 79 79 80 80 provider.on('sync', () => { 81 81 const _st = document.getElementById('status-text'); 82 - if (_st) _st.textContent = 'Synced'; 82 + if (_st) _st.textContent = 'Local'; 83 83 84 84 // Re-attach ALL observers after sync — the snapshot may have replaced the Y.Map/Y.Array 85 85 // objects that were observed during initial setup (before data loaded from peers)
+2 -2
src/slides/index.html
··· 31 31 <span id="save-text">Saved</span> 32 32 </div> 33 33 <div class="status-indicator" id="status"> 34 - <span class="status-dot" id="status-dot"></span> 35 - <span id="status-text">Connecting&hellip;</span> 34 + <span class="status-dot connected" id="status-dot"></span> 35 + <span id="status-text">Local</span> 36 36 </div> 37 37 <button class="btn-secondary" id="btn-present" title="Present (F5)">&#9655; Present</button> 38 38 <button class="btn-secondary" id="btn-export" title="Export">Export</button>
+6 -6
tests/status-chips.test.ts
··· 6 6 * 7 7 * These tests pin the contract so future refactors can't silently regress: 8 8 * - `status-dot` flips `.connected` on provider `status` events 9 - * - `status-text` transitions to `Synced` on provider `sync` events 9 + * - `status-text` transitions to `Local` on provider `sync` events 10 10 * - Helper is safe to call when the host page has not opted in to the 11 11 * status-indicator markup (no-op instead of throwing). 12 12 */ ··· 48 48 49 49 provider.emit('status', { connected: true }); 50 50 expect(dot.classList.contains('connected')).toBe(true); 51 - expect(text.textContent).toBe('Connected'); 51 + expect(text.textContent).toBe('Local'); 52 52 53 53 provider.emit('status', { connected: false }); 54 54 expect(dot.classList.contains('connected')).toBe(false); 55 - expect(text.textContent).toBe('Reconnecting\u2026'); 55 + expect(text.textContent).toBe('Error'); 56 56 }); 57 57 58 - it('sets status-text to "Synced" on provider sync event and marks dot connected', () => { 58 + it('sets status-text to "Local" on provider sync event and marks dot connected', () => { 59 59 document.body.innerHTML = ` 60 60 <span id="status-dot"></span> 61 - <span id="status-text">Connecting…</span> 61 + <span id="status-text">Local</span> 62 62 `; 63 63 const provider = mockProvider(); 64 64 wireStatusChips({ provider }); 65 65 66 66 provider.emit('sync'); 67 - expect(document.getElementById('status-text')!.textContent).toBe('Synced'); 67 + expect(document.getElementById('status-text')!.textContent).toBe('Local'); 68 68 expect(document.getElementById('status-dot')!.classList.contains('connected')).toBe(true); 69 69 }); 70 70