From 2cef65fb1f8b8242f4537f583c4fe0a4cfd66171 Mon Sep 17 00:00:00 2001 From: Daniel Date: Wed, 13 May 2026 16:04:06 +0200 Subject: [PATCH] Fix mobile assistant image downloads --- mobile/android/app/build.gradle | 4 ++-- mobile/package-lock.json | 4 ++-- mobile/package.json | 2 +- package-lock.json | 4 ++-- package.json | 2 +- public/js/assistant/images.js | 34 ++++++++++++++++++++++++++------- 6 files changed, 35 insertions(+), 15 deletions(-) diff --git a/mobile/android/app/build.gradle b/mobile/android/app/build.gradle index 581397d..7aaca82 100644 --- a/mobile/android/app/build.gradle +++ b/mobile/android/app/build.gradle @@ -9,8 +9,8 @@ android { targetSdkVersion rootProject.ext.targetSdkVersion // Version values below are overwritten by scripts/release.sh from // the root package.json. versionCode auto-increments per release. - versionCode 714003 - versionName "7.14.3" + versionCode 714007 + versionName "7.14.7" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" aaptOptions { // Files and dirs to omit from the packaged assets dir, modified to accommodate modern web apps. diff --git a/mobile/package-lock.json b/mobile/package-lock.json index 3ba7dce..339a6c2 100644 --- a/mobile/package-lock.json +++ b/mobile/package-lock.json @@ -1,12 +1,12 @@ { "name": "pedscribe-mobile", - "version": "7.14.3", + "version": "7.14.7", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "pedscribe-mobile", - "version": "7.14.3", + "version": "7.14.7", "dependencies": { "@aparajita/capacitor-biometric-auth": "^8.0.0", "@capacitor/android": "^6.0.0", diff --git a/mobile/package.json b/mobile/package.json index 08b3f57..16b6113 100644 --- a/mobile/package.json +++ b/mobile/package.json @@ -1,6 +1,6 @@ { "name": "pedscribe-mobile", - "version": "7.14.3", + "version": "7.14.7", "description": "PedScribe native mobile app — Capacitor wrapper for Pediatric AI Scribe", "private": true, "scripts": { diff --git a/package-lock.json b/package-lock.json index 4f09356..86e743a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "pediatric-ai-scribe", - "version": "7.14.6", + "version": "7.14.7", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "pediatric-ai-scribe", - "version": "7.14.6", + "version": "7.14.7", "dependencies": { "@marp-team/marp-cli": "^4.3.1", "@marp-team/marp-core": "^4.3.0", diff --git a/package.json b/package.json index 990cff5..2c4bf7b 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "pediatric-ai-scribe", - "version": "7.14.6", + "version": "7.14.7", "description": "AI-powered pediatric clinical documentation platform", "main": "server.js", "scripts": { diff --git a/public/js/assistant/images.js b/public/js/assistant/images.js index f571740..ea1798b 100644 --- a/public/js/assistant/images.js +++ b/public/js/assistant/images.js @@ -49,13 +49,7 @@ export function createAssistantImageStore() { if (typeof window.showToast === 'function') window.showToast('Image saving is not available in this app build yet. Update the app and try again.', 'error'); return; } - var a = document.createElement('a'); - a.href = src; - a.download = 'clinical-visual.png'; - a.rel = 'noopener'; - document.body.appendChild(a); - a.click(); - a.remove(); + await downloadWithBrowser(src); } catch (e) { if (typeof window.showToast === 'function') window.showToast(e.message || 'Image download failed', 'error'); } @@ -145,6 +139,32 @@ async function shareWithWebFile(src) { } catch (e) { return isShareCancel(e) ? 'cancelled' : 'unavailable'; } } +async function downloadWithBrowser(src) { + var blob = await imageSourceToBlob(src); + var objectUrl = URL.createObjectURL(blob); + var a = document.createElement('a'); + a.href = objectUrl; + a.download = 'clinical-visual.png'; + a.rel = 'noopener'; + document.body.appendChild(a); + a.click(); + a.remove(); + setTimeout(function() { URL.revokeObjectURL(objectUrl); }, 60000); + + if (isMobileBrowser()) { + setTimeout(function() { + var opened = window.open(objectUrl, '_blank', 'noopener'); + if (opened && typeof window.showToast === 'function') { + window.showToast('If the download did not start, long-press the opened image and save it.', 'success'); + } + }, 300); + } +} + +function isMobileBrowser() { + return !isNativeApp() && /Android|iPhone|iPad|iPod|Mobile/i.test(navigator.userAgent || ''); +} + function isNativeApp() { return !!(window.Capacitor && (!window.Capacitor.isNativePlatform || window.Capacitor.isNativePlatform())); }