desktop v0.1.20 + web: notify on download complete (was silent) (batch135)
Suppressing the save dialog made downloads completely silent — "nothing happened" even though the file saved to Downloads. Now on download 'done': (1) tell the web UI → branded toast "Saved X to your Downloads folder" when the window is focused; (2) native OS notification (click → reveal in Explorer) when the app is minimized/in the tray, so it's never double-noticed; (3) a failure notice. preload exposes onDownloadDone; home.html shows the toast. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -465,6 +465,24 @@ function configureSession() {
|
||||
let target = path.join(dir, name), n = 1;
|
||||
while (fs.existsSync(target)) target = path.join(dir, `${base} (${n++})${ext}`);
|
||||
item.setSavePath(target);
|
||||
// Since we suppressed the save dialog, the download would otherwise be completely silent. Give feedback
|
||||
// when it finishes: a notification (click → reveal the file in Explorer) so the user knows it saved and
|
||||
// where. Also tell the web UI so it can show its own toast. On failure, say so.
|
||||
item.once('done', (_ev, state) => {
|
||||
try {
|
||||
const ok = state === 'completed';
|
||||
const savedName = ok ? path.basename(target) : (item.getFilename() || 'file');
|
||||
// Always tell the web UI (it shows a branded toast when the window is up).
|
||||
try { if (win && !win.isDestroyed()) win.webContents.send('download-done', { name: savedName, path: ok ? target : '', ok }); } catch (_) {}
|
||||
// If the window is focused, that toast is enough — skip the native notification to avoid a double
|
||||
// notice. If the app is minimized/in the tray, show a native notification instead (click → reveal).
|
||||
const focused = win && !win.isDestroyed() && win.isVisible() && win.isFocused();
|
||||
if (!focused && Notification.isSupported()) {
|
||||
if (ok) { const note = new Notification({ title: 'Download complete', body: savedName + ' — saved to your Downloads folder. Click to show it.' }); note.on('click', () => { try { shell.showItemInFolder(target); } catch (_) {} }); note.show(); }
|
||||
else new Notification({ title: 'Download failed', body: savedName + ' could not be saved.' }).show();
|
||||
}
|
||||
} catch (_) {}
|
||||
});
|
||||
} catch (_) {}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "biz-connect-desktop",
|
||||
"version": "0.1.19",
|
||||
"version": "0.1.20",
|
||||
"description": "Biz Connect technician desktop client — loads the Connect web UI with native screen capture",
|
||||
"author": {
|
||||
"name": "BizGaze",
|
||||
|
||||
@@ -43,5 +43,6 @@ contextBridge.exposeInMainWorld('bizConnectNative', Object.freeze({
|
||||
// #3: subscribe to auto-update lifecycle events so the UI can show download progress + "ready".
|
||||
// cb receives {phase:'checking'|'available'|'downloading'|'ready'|'current'|'error', percent?, version?}.
|
||||
onUpdateEvent: (cb) => { try { ipcRenderer.on('update-event', (_e, data) => { try { cb(data); } catch (_) {} }); } catch (_) {} },
|
||||
onDownloadDone: (cb) => { try { ipcRenderer.on('download-done', (_e, data) => { try { cb(data); } catch (_) {} }); } catch (_) {} }, // desktop: a file finished downloading to the Downloads folder → show a toast
|
||||
restartToUpdate: () => ipcRenderer.invoke('restart-to-update'),
|
||||
}));
|
||||
|
||||
@@ -1158,7 +1158,7 @@
|
||||
</head>
|
||||
<body>
|
||||
<script src="/icons.js?v=6"></script>
|
||||
<script>window.__BUILD='2026-07-19-batch134';console.log('%cBiz Connect','color:#1F3B73;font-weight:bold','build '+window.__BUILD);
|
||||
<script>window.__BUILD='2026-07-19-batch135';console.log('%cBiz Connect','color:#1F3B73;font-weight:bold','build '+window.__BUILD);
|
||||
// Emoji are rendered with the OS's own (colour) emoji font — instant, zero network.
|
||||
//
|
||||
// We used to run Twemoji over every emoji, which swapped each one for an <img> pulled INDIVIDUALLY from
|
||||
@@ -3408,6 +3408,10 @@ function wireUpdateBanner(){
|
||||
else if(d.phase==='ready'){ ensure().innerHTML=ic('check',15)+' <span>Update ready</span> <button id="updRestart">Restart now</button>'; el.classList.add('show','ready'); const b=el.querySelector('#updRestart'); if(b) b.onclick=()=>{ try{ n.restartToUpdate&&n.restartToUpdate(); }catch(_){} }; }
|
||||
else if(d.phase==='current'||d.phase==='error'){ if(el){ el.classList.remove('show'); setTimeout(()=>{ if(el&&!el.classList.contains('show')) el.remove(); }, 400); } }
|
||||
});
|
||||
// Desktop: a download finished (saved straight to the Downloads folder, no dialog) → confirm with a toast
|
||||
// so it never feels like "nothing happened". The native app also shows a click-to-reveal OS notification
|
||||
// when its window isn't focused.
|
||||
if(n.onDownloadDone) n.onDownloadDone((d)=>{ if(!d) return; toast(d.ok ? ('Saved “'+(d.name||'file')+'” to your Downloads folder') : ('Couldn’t download '+(d.name||'the file'))); });
|
||||
}
|
||||
// ---- New-web-build detection ----------------------------------------------------------------
|
||||
// The desktop app closes to TRAY, so it can stay open for weeks and keep running the page it loaded on
|
||||
|
||||
Reference in New Issue
Block a user