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

Configure Feed

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

Disable presentations, update local storage warning (#11)

scott 7ea9eeca 80f44a33

+17 -37
+1 -6
public/manifest.json
··· 1 1 { 2 2 "name": "Atmosphere Office", 3 3 "short_name": "Atmosphere Office", 4 - "description": "Documents, spreadsheets, slides, and more — stored locally in your browser", 4 + "description": "Documents, spreadsheets, and more — stored locally in your browser", 5 5 "start_url": "/", 6 6 "display": "standalone", 7 7 "background_color": "#111111", ··· 25 25 { 26 26 "name": "New Form", 27 27 "url": "/?action=new-form", 28 - "icons": [{ "src": "/favicon.svg", "sizes": "any" }] 29 - }, 30 - { 31 - "name": "New Presentation", 32 - "url": "/?action=new-slide", 33 28 "icons": [{ "src": "/favicon.svg", "sizes": "any" }] 34 29 }, 35 30 {
+2 -6
src/index.html
··· 4 4 <meta charset="UTF-8"> 5 5 <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1, viewport-fit=cover"> 6 6 <link rel="manifest" href="/manifest.json"> 7 - <meta name="description" content="Documents, spreadsheets, slides, and more — stored locally in your browser. Sign in with your Bluesky account."> 7 + <meta name="description" content="Documents, spreadsheets, and more — stored locally in your browser. Sign in with your Bluesky account."> 8 8 <meta property="og:title" content="Atmosphere Office"> 9 - <meta property="og:description" content="Documents, spreadsheets, slides, and more — stored locally in your browser. Sign in with your Bluesky account."> 9 + <meta property="og:description" content="Documents, spreadsheets, and more — stored locally in your browser. Sign in with your Bluesky account."> 10 10 <meta property="og:type" content="website"> 11 11 <meta property="og:image" content="/favicon.svg"> 12 12 <title>Atmosphere Office</title> ··· 42 42 <button class="new-menu-item" data-new="sheet" role="menuitem"> 43 43 <span class="new-menu-icon">&#9638;</span> 44 44 <span class="new-menu-label">Spreadsheet</span> 45 - </button> 46 - <button class="new-menu-item" data-new="slide" role="menuitem"> 47 - <span class="new-menu-icon">&#9707;</span> 48 - <span class="new-menu-label">Presentation</span> 49 45 </button> 50 46 <button class="new-menu-item" data-new="form" role="menuitem"> 51 47 <span class="new-menu-icon">&#9783;</span>
-3
src/landing.ts
··· 169 169 case 'doc': 170 170 case 'sheet': 171 171 case 'form': 172 - case 'slide': 173 172 case 'diagram': 174 173 createDocument(createDeps, kind); 175 174 break; ··· 302 301 { id: 'new-doc', label: 'New Document', category: 'action', icon: '\u270e', action: () => createDocument(createDeps, 'doc') }, 303 302 { id: 'new-sheet', label: 'New Spreadsheet', category: 'action', icon: '\u25a6', action: () => createDocument(createDeps, 'sheet') }, 304 303 { id: 'new-form', label: 'New Form', category: 'action', icon: '\u2637', action: () => createDocument(createDeps, 'form') }, 305 - { id: 'new-slide', label: 'New Presentation', category: 'action', icon: '\u25eb', action: () => createDocument(createDeps, 'slide') }, 306 304 { id: 'new-diagram', label: 'New Diagram', category: 'action', icon: '\u25d3', action: () => createDocument(createDeps, 'diagram') }, 307 305 { id: 'new-calendar', label: 'Calendar', category: 'action', icon: '\u2630', action: () => openCalendar(createDeps) }, 308 306 { id: 'daily-note', label: "Today's Note", category: 'action', icon: '\u2666', action: () => openDailyNote(createDeps) }, ··· 352 350 'new-doc': () => createDocument(createDeps, 'doc'), 353 351 'new-sheet': () => createDocument(createDeps, 'sheet'), 354 352 'new-form': () => createDocument(createDeps, 'form'), 355 - 'new-slide': () => createDocument(createDeps, 'slide'), 356 353 'new-diagram': () => createDocument(createDeps, 'diagram'), 357 354 'new-calendar': () => openCalendar(createDeps), 358 355 };
+3 -3
src/lib/instance-info.ts
··· 88 88 switch (info.flavor) { 89 89 case 'pds-operator': { 90 90 const caps: string[] = [ 91 - 'Documents, spreadsheets, slides, diagrams, forms, and calendar', 91 + 'Documents, spreadsheets, diagrams, forms, and calendar', 92 92 'Data stored locally in your browser', 93 93 'Sign in with your Bluesky account', 94 94 ]; ··· 115 115 title: 'Self-Hosted Instance', 116 116 summary: 'You are running your own instance of Atmosphere Office. You have full control over your data and configuration.', 117 117 capabilities: [ 118 - 'Documents, spreadsheets, slides, diagrams, forms, and calendar', 118 + 'Documents, spreadsheets, diagrams, forms, and calendar', 119 119 'Data stored locally in your browser', 120 120 'Full control over configuration and data', 121 121 'Sign in with your Bluesky account', ··· 132 132 title: 'Atmosphere Office', 133 133 summary: 'A local-only office suite for the AT Protocol ecosystem. All your data stays in this browser — nothing is sent to a server.', 134 134 capabilities: [ 135 - 'Documents, spreadsheets, slides, diagrams, forms, and calendar', 135 + 'Documents, spreadsheets, diagrams, forms, and calendar', 136 136 'All data stored locally in your browser', 137 137 'Sign in with your Bluesky account', 138 138 'Export and import documents for backup',
+11 -19
src/lib/key-warning.ts
··· 94 94 function copyForLevel(level: KeyLossRiskLevel): ModalCopy { 95 95 switch (level) { 96 96 case 'anonymous': 97 - return { 98 - title: 'Save this link before you close the tab', 99 - body: 100 - 'This document is end-to-end encrypted. The decryption key lives in the URL after the "#". ' + 101 - 'If you lose this URL, nothing can recover the document. ' + 102 - 'Sign in to save the key to your device, or copy the link somewhere safe.', 103 - cta: 'I understand', 104 - tone: 'warn', 105 - }; 106 97 case 'at-risk': 107 98 return { 108 - title: "Back up this document's key", 99 + title: 'This document is stored locally', 109 100 body: 110 - "This document is end-to-end encrypted. The key hasn't been saved to your device yet. " + 111 - 'Keep this tab open until the key saves, or copy the URL as a manual backup.', 112 - cta: 'Got it', 101 + 'Your data only exists in this browser. If you clear your browser data, ' + 102 + 'use a different device, or are in a private/incognito window, your document will be lost. ' + 103 + 'Export your work when you are done.', 104 + cta: 'I understand', 113 105 tone: 'warn', 114 106 }; 115 107 case 'safe': 116 108 return { 117 - title: 'Your document is safely encrypted', 109 + title: 'This document is stored locally', 118 110 body: 119 - 'This document is end-to-end encrypted. Its key is saved on this device. ' + 120 - 'Export your keys regularly to protect against browser data loss.', 111 + 'Your data only exists in this browser on this device. ' + 112 + 'Export your work regularly to protect against browser data loss.', 121 113 cta: 'Close', 122 114 tone: 'info', 123 115 }; ··· 261 253 const updateTitle = (): void => { 262 254 const level = classifyKeyLossRisk({ user: current.user, hasLocalKey: current.hasLocalKey }); 263 255 const titles: Record<KeyLossRiskLevel, string> = { 264 - anonymous: 'End-to-end encrypted \u2014 save this link to keep access', 265 - 'at-risk': 'End-to-end encrypted \u2014 key not yet saved', 266 - safe: 'End-to-end encrypted \u2014 key saved on this device', 256 + anonymous: 'Stored locally \u2014 export your work to keep it safe', 257 + 'at-risk': 'Stored locally \u2014 export your work to keep it safe', 258 + safe: 'Stored locally on this device', 267 259 }; 268 260 btn.title = titles[level]; 269 261 };