feat: add mobile install flow
CI / lint (pull_request) Successful in 28s
CI / build-frontend (pull_request) Successful in 5s

Closes #291
This commit is contained in:
timmy committed 2026-08-08 10:55:35 +00:00
1 parent b458dbaa78
commit 31a07e4a46
5 files changed
+308 -4

No files matched your search

+28
View File
@@ -62,6 +62,10 @@ textarea { resize: vertical; min-height: 120px; }
.offline-work-controls label { display:flex; gap:8px; align-items:center; min-height:44px; }
.offline-work-controls input { width:20px; height:20px; }
.offline-work-controls button { min-height:44px; }
.install-app-card { display:flex; gap:10px; align-items:center; flex-wrap:wrap; width:100%; padding:10px; border:1px solid #31577f; border-radius:12px; background:#10233a; }
.install-app-card[hidden] { display:none; }
.install-app-card p { margin:0; flex:1 1 240px; }
.install-app-card button { min-height:44px; }
.widget { border: 1px solid #1b2d45; border-radius: 12px; padding: 10px; background: linear-gradient(180deg,#0f1d33,#0b1526); }
.widget h3 { margin: 4px 0 8px; font-size: 13px; color: #7aa1c9; }
.event { padding: 8px 0; border-bottom: 1px solid #1b2d45; }
@@ -343,6 +347,13 @@ textarea { resize: vertical; min-height: 120px; }
<button id="clear-offline-work" type="button">Clear offline work data</button>
<span class="small" id="offline-work-status" role="status" aria-live="polite"></span>
<span class="small" id="delivery-receipt-status" role="status" aria-live="polite"></span>
<div class="install-app-card" id="install-app-card" hidden>
<p><strong>Install Stackchain</strong><br><span class="small">Keep mobile work one tap away and launch the saved app shell during an outage.</span></p>
<p class="small" id="install-app-guidance" hidden>On Safari, tap Share, then choose <strong>Add to Home Screen</strong>.</p>
<button id="install-app" type="button">Install Stackchain</button>
<button id="dismiss-install-app" type="button">Not now</button>
</div>
<span class="small" id="install-app-status" role="status" aria-live="polite"></span>
</div>
</div>
<div class="my-work-list" id="my-work-list"></div>
@@ -792,6 +803,7 @@ textarea { resize: vertical; min-height: 120px; }
<script src="static/work-route.js"></script>
<script src="static/context-poller.js"></script>
<script src="static/mobile-task-dock.js"></script>
<script src="static/install-app.js"></script>
<script>
(function(){
const qs = (s, el=document) => el.querySelector(s);
@@ -3731,6 +3743,22 @@ textarea { resize: vertical; min-height: 120px; }
console.warn('Stackchain install support unavailable', error)
);
}
const isIosDevice = /iPad|iPhone|iPod/.test(navigator.userAgent) ||
(navigator.platform === 'MacIntel' && navigator.maxTouchPoints > 1);
const isIosSafari = isIosDevice && /Safari/.test(navigator.userAgent) &&
!/CriOS|FxiOS|EdgiOS|OPiOS/.test(navigator.userAgent);
createInstallApp({
window,
card: qs('#install-app-card'),
installButton: qs('#install-app'),
dismissButton: qs('#dismiss-install-app'),
guidance: qs('#install-app-guidance'),
status: qs('#install-app-status'),
storage: localStorage,
isStandalone: () => window.matchMedia('(display-mode: standalone)').matches ||
navigator.standalone === true,
isIosSafari: () => isIosSafari,
}).start();
contextPoller.start();
document.addEventListener('visibilitychange', () => {
contextPoller.setVisible(!document.hidden);