feat: Windows download link + self-served update feed + install tracking
Downloads/updates: - config: DOWNLOADS_DIR (override to a mounted volume in prod). - static.js: serves /downloads/* (installer, latest.yml, .blockmap) with range support for resumable + differential auto-updates; /download/windows redirects to the current .exe (stable link). Landing page gets a "Download the Windows desktop app" button (hidden in-app). Install tracking (who installed the app): - db app_installs + repos.appInstalls (upsert by install_id, fills in the user on sign-in). - POST /api/v1/telemetry/install (records install + user once authenticated); GET /api/v1/admin/installs (admin: list installs with user/version/os/last-seen). - desktop main.js: stable per-install id in userData, exposed via preload (bizConnectNative.installId/version/os); home.html reportInstall() posts it after login. - e2e: +2 checks (telemetry recorded, admin sees it). 119/119. build batch20. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -731,7 +731,7 @@
|
||||
</head>
|
||||
<body>
|
||||
<script src="/icons.js?v=4"></script>
|
||||
<script>window.__BUILD='2026-07-01-batch19';console.log('%cBiz Connect','color:#1F3B73;font-weight:bold','build '+window.__BUILD);</script>
|
||||
<script>window.__BUILD='2026-07-01-batch20';console.log('%cBiz Connect','color:#1F3B73;font-weight:bold','build '+window.__BUILD);</script>
|
||||
<div class="loading" id="loading">Loading…</div>
|
||||
|
||||
<header>
|
||||
@@ -1831,6 +1831,13 @@ function urlB64ToUint8(base64){ const pad='='.repeat((4-base64.length%4)%4); con
|
||||
// FCM/APNs (see server/push.js). No bundler needed — plugins live on Capacitor.Plugins.
|
||||
function capPlugin(name){ const C=window.Capacitor; return (C && C.isNativePlatform && C.isNativePlatform() && C.Plugins && C.Plugins[name]) ? C.Plugins[name] : null; }
|
||||
function nativePlatform(){ const C=window.Capacitor; if(C && C.getPlatform){ const p=C.getPlatform(); if(p==='ios'||p==='android') return p; } if(window.__NATIVE__==='desktop') return 'desktop'; return ''; }
|
||||
// Record this install against the signed-in user (desktop shell exposes a stable installId).
|
||||
// Fires post-login; the request carries the session so admins can see who installed the app.
|
||||
function reportInstall(){
|
||||
try{ const n=window.bizConnectNative; if(!n||!n.installId) return;
|
||||
postJSON('/api/v1/telemetry/install',{ installId:n.installId, platform:n.platform||'desktop', appVersion:n.version||'', os:n.os||'' }).catch(()=>{});
|
||||
}catch(_){}
|
||||
}
|
||||
let _nativeTok=null;
|
||||
async function setupNativePush(){
|
||||
const PN=capPlugin('PushNotifications'); const plat=nativePlatform();
|
||||
@@ -2756,6 +2763,7 @@ async function doRegister(){
|
||||
loadNotifs(); wireBell(); wireProfile();
|
||||
placeHdrRight(); window.addEventListener('resize', placeHdrRight); // mobile: bell+profile live in the chat-list header (no top bar)
|
||||
connectChatWs();
|
||||
reportInstall(); // desktop/mobile shell: record this install against the signed-in user
|
||||
setupPush(); // register the notification service worker + subscribe to Web Push (if granted)
|
||||
{ const cl=document.getElementById('chatlist'); if(cl) enablePullRefresh(cl, loadSidebar); } // pull-to-refresh the chat list
|
||||
setTimeout(maybeNotifPrompt, 1500); // gentle "enable notifications" prompt if still undecided (key for iOS PWA)
|
||||
|
||||
Reference in New Issue
Block a user