feat(capture): ship Milestone 1 browser capture app
Why Phone and PC need a single capture flow that ends at inventory PNG and board-foot numbers with no backend, inference, or Woo create. Scope Add frontend/ Vite+Svelte capture UI with Resume, Add photo, Mask, Length axis, and Measure. Mask runs in a worker with Auto/Green/Black and a 2.0s sensitivity debounce. Measure computes scale, widths, sqft, bdft, and a 3:4 alpha inventory PNG. Persist one device draft in IndexedDB. Serve the static build from frontend/Dockerfile via nginx (deploy/nginx-m1.conf). No FastAPI. Verification sudo docker build -f frontend/Dockerfile -t slabuploader-m1 . sudo docker run -d --name slabuploader-m1 -p 0.0.0.0:18080:80 slabuploader-m1 curl http://127.0.0.1:18080/ returns 200 Playwright: synthetic green-sheet photo through Calculate shows sqft/bdft
This commit is contained in:
@@ -0,0 +1,26 @@
|
||||
// Supported clients: iOS Safari, Android Chrome, PC Chrome/Edge/Firefox.
|
||||
// Gated on required API presence; anything missing → hard stop.
|
||||
export function supported(): string | null {
|
||||
if (typeof window === 'undefined') return 'window unavailable';
|
||||
if (typeof createImageBitmap !== 'function') return 'createImageBitmap';
|
||||
if (typeof Worker === 'undefined') return 'Worker';
|
||||
if (typeof indexedDB === 'undefined') return 'IndexedDB';
|
||||
const hasOffscreen =
|
||||
typeof OffscreenCanvas !== 'undefined' &&
|
||||
typeof OffscreenCanvas.prototype.convertToBlob === 'function';
|
||||
const hasCanvasBlob =
|
||||
typeof HTMLCanvasElement !== 'undefined' &&
|
||||
typeof HTMLCanvasElement.prototype.toBlob === 'function';
|
||||
if (!hasOffscreen && !hasCanvasBlob) return 'canvas PNG encode';
|
||||
const ua = navigator.userAgent;
|
||||
const isIOS = /iPad|iPhone|iPod/.test(ua) || (navigator.platform === 'MacIntel' && navigator.maxTouchPoints > 1);
|
||||
const isAndroid = /Android/i.test(ua);
|
||||
const isSafari = /Safari/i.test(ua) && !/Chrome|CriOS|Edg|Firefox|FxiOS/i.test(ua);
|
||||
const isChrome = /Chrome|CriOS/i.test(ua) && !/Edg/i.test(ua);
|
||||
const isEdge = /Edg/i.test(ua);
|
||||
const isFirefox = /Firefox|FxiOS/i.test(ua);
|
||||
if (isIOS && isSafari) return null;
|
||||
if (isAndroid && isChrome) return null;
|
||||
if (!isIOS && !isAndroid && (isChrome || isEdge || isFirefox)) return null;
|
||||
return 'unsupported browser';
|
||||
}
|
||||
Reference in New Issue
Block a user