pediatric-ai-scribe-v3/mobile/src/launcher.js
Daniel b43bc614da Mobile app: haptics, deep linking, share intent, push notifications, keep-awake
Native improvements:
- Add haptic feedback on recording start (heavy) and stop (medium)
- Add keep-screen-awake during recording (nativeKeepAwake)
- Add isNativeApp() detection helper
- Android: deep linking (pedscribe:// + https://app.pedshub.com)
- Android: share intent for text/plain and application/pdf
- iOS: deep linking (pedscribe:// URL scheme)
- iOS: remote-notification background mode
- Add Capacitor plugins: haptics, keyboard, push-notifications,
  screen-orientation, share

Updated README with complete build/deploy instructions,
App Store listing suggestions, and icon generation guide.
2026-04-11 02:28:30 +02:00

118 lines
3.6 KiB
JavaScript

// PedScribe Mobile Launcher
// Handles configurable server URL, auto-redirect, and native features
(function() {
var STORAGE_KEY = 'pedscribe_server_url';
var DEFAULT_URL = 'https://app.pedshub.com';
var setupScreen = document.getElementById('setup-screen');
var connectingScreen = document.getElementById('connecting-screen');
var urlInput = document.getElementById('server-url');
var connectBtn = document.getElementById('btn-connect');
var changeBtn = document.getElementById('btn-change-server');
// Check for saved server URL
var savedUrl = localStorage.getItem(STORAGE_KEY);
if (savedUrl) {
showConnecting(savedUrl);
} else {
urlInput.value = DEFAULT_URL;
setupScreen.style.display = '';
connectingScreen.style.display = 'none';
}
// Connect button
connectBtn.addEventListener('click', function() {
var url = (urlInput.value || DEFAULT_URL).trim().replace(/\/+$/, '');
if (!url.startsWith('http')) url = 'https://' + url;
connectBtn.disabled = true;
connectBtn.textContent = 'Connecting...';
hapticFeedback();
testServer(url, function(ok) {
if (ok) {
localStorage.setItem(STORAGE_KEY, url);
navigateToServer(url);
} else {
connectBtn.disabled = false;
connectBtn.textContent = 'Connect';
showError('Could not reach server. Check the URL and try again.');
}
});
});
// Enter key
urlInput.addEventListener('keydown', function(e) {
if (e.key === 'Enter') connectBtn.click();
});
// Change server button
changeBtn.addEventListener('click', function() {
localStorage.removeItem(STORAGE_KEY);
setupScreen.style.display = '';
connectingScreen.style.display = 'none';
urlInput.value = savedUrl || DEFAULT_URL;
urlInput.focus();
});
function showConnecting(url) {
setupScreen.style.display = 'none';
connectingScreen.style.display = '';
setTimeout(function() {
testServer(url, function(ok) {
if (ok) {
navigateToServer(url);
} else {
setupScreen.style.display = '';
connectingScreen.style.display = 'none';
urlInput.value = url;
showError('Server not reachable. Check your connection or change the URL.');
}
});
}, 500);
}
function testServer(url, callback) {
var done = false;
function respond(ok) {
if (done) return;
done = true;
callback(ok);
}
fetch(url + '/api/health', { mode: 'no-cors', signal: AbortSignal.timeout(8000) })
.then(function() { respond(true); })
.catch(function() {
var fallbackTimer = setTimeout(function() { respond(false); }, 5000);
var img = new Image();
img.onload = function() { clearTimeout(fallbackTimer); respond(true); };
img.onerror = function() { clearTimeout(fallbackTimer); respond(false); };
img.src = url + '/favicon.ico?t=' + Date.now();
});
}
function navigateToServer(url) {
window.location.href = url;
}
function showError(msg) {
var existing = document.querySelector('.error-msg');
if (existing) existing.remove();
var div = document.createElement('div');
div.className = 'error-msg';
div.style.display = 'block';
div.textContent = msg;
connectBtn.parentNode.insertBefore(div, connectBtn.nextSibling);
setTimeout(function() { if (div.parentNode) div.remove(); }, 8000);
}
// Haptic feedback (Capacitor native)
function hapticFeedback() {
if (window.Capacitor && window.Capacitor.Plugins && window.Capacitor.Plugins.Haptics) {
window.Capacitor.Plugins.Haptics.impact({ style: 'medium' });
}
}
})();