- Progressive Web App with Express + JSON backend - PIN-based auth, multi-device sync - Invoice + Statement PDF generation (branded, Grandstander + Nunito) - Mobile + Desktop responsive layouts - n8n backup integration - Custom logo upload - Settings for business info, fees, banking - Bulk invoice generation - Web Share API integration
85 lines
2.4 KiB
JavaScript
85 lines
2.4 KiB
JavaScript
/* Slim Uiltjies — Share helpers
|
|
Uses the Web Share API where available, falls back to download or WhatsApp deep-link.
|
|
*/
|
|
(function () {
|
|
'use strict';
|
|
|
|
function canShareFiles() {
|
|
return !!(navigator.canShare && navigator.canShare({ files: [new File([new Blob()], 'x.txt', { type: 'text/plain' })] }));
|
|
}
|
|
|
|
function isMobile() {
|
|
return /Android|iPhone|iPad|iPod/i.test(navigator.userAgent);
|
|
}
|
|
|
|
async function shareFile(file, { title = 'Invoice', text = '' } = {}) {
|
|
if (navigator.canShare && navigator.canShare({ files: [file] })) {
|
|
try {
|
|
await navigator.share({ files: [file], title, text });
|
|
return { ok: true, method: 'native' };
|
|
} catch (e) {
|
|
if (e && e.name === 'AbortError') return { ok: false, cancelled: true };
|
|
// fall through
|
|
}
|
|
}
|
|
// Fallback: download the file
|
|
downloadBlob(file);
|
|
return { ok: true, method: 'download' };
|
|
}
|
|
|
|
async function shareText({ title = '', text = '', url = '' } = {}) {
|
|
if (navigator.share) {
|
|
try {
|
|
await navigator.share({ title, text, url });
|
|
return { ok: true };
|
|
} catch (e) {
|
|
if (e && e.name === 'AbortError') return { ok: false, cancelled: true };
|
|
}
|
|
}
|
|
// WhatsApp deep link fallback
|
|
if (isMobile()) {
|
|
const msg = [text, url].filter(Boolean).join('\n');
|
|
window.open(`https://wa.me/?text=${encodeURIComponent(msg)}`, '_blank');
|
|
return { ok: true, method: 'whatsapp' };
|
|
}
|
|
// Copy to clipboard fallback
|
|
try {
|
|
await navigator.clipboard.writeText([title, text, url].filter(Boolean).join('\n'));
|
|
return { ok: true, method: 'clipboard' };
|
|
} catch {
|
|
return { ok: false };
|
|
}
|
|
}
|
|
|
|
function downloadBlob(blob, filename) {
|
|
const a = document.createElement('a');
|
|
const url = URL.createObjectURL(blob);
|
|
a.href = url;
|
|
a.download = filename || blob.name || 'download';
|
|
document.body.appendChild(a);
|
|
a.click();
|
|
setTimeout(() => {
|
|
document.body.removeChild(a);
|
|
URL.revokeObjectURL(url);
|
|
}, 100);
|
|
}
|
|
|
|
function openPrintDialog() {
|
|
setTimeout(() => window.print(), 200);
|
|
}
|
|
|
|
function whatsappUrl(phone, message) {
|
|
const num = (phone || '').replace(/[^0-9+]/g, '');
|
|
return `https://wa.me/${num}?text=${encodeURIComponent(message || '')}`;
|
|
}
|
|
|
|
window.SUShare = {
|
|
canShareFiles,
|
|
isMobile,
|
|
shareFile,
|
|
shareText,
|
|
downloadBlob,
|
|
openPrintDialog,
|
|
whatsappUrl,
|
|
};
|
|
})();
|