Files
nexarch/web/dms-upload/lib/mobileCapture.ts
rootandClaude Sonnet 5 0097c8cf2b
CI / Web-Barrierefreiheitspruefung (axe, Tastatur, Reflow, Textabstaende) (pull_request) Canceled after 0s
CI / Web-Barrierefreiheitspruefung (axe, Tastatur, Reflow, Textabstaende) (push) Canceled after 0s
CI / Core-Modul (Build/Vet/Test) (push) Canceled after 0s
CI / DMS Security-Test-Gate (AC5, Merge-Gate) (push) Canceled after 0s
CI / DMS-Modul Supply-Chain-Scan (govulncheck) (push) Canceled after 0s
CI / Web (dms-browser) (push) Canceled after 0s
CI / Web (pdf-viewer) (push) Canceled after 0s
CI / Web (shl) (push) Canceled after 0s
Supply-Chain-Scan (Go) / govulncheck (push) Canceled after 0s
CI / Core-Modul (Build/Vet/Test) (pull_request) Canceled after 0s
CI / DMS Security-Test-Gate (AC5, Merge-Gate) (pull_request) Canceled after 0s
Supply-Chain-Scan (Go) / govulncheck (pull_request) Canceled after 0s
CI / DMS-Modul Supply-Chain-Scan (govulncheck) (pull_request) Canceled after 0s
CI / Web (dms-browser) (pull_request) Canceled after 0s
CI / Web (pdf-viewer) (pull_request) Canceled after 0s
CI / Web (shl) (pull_request) Canceled after 0s
Core-Schnittstellen-Vertragstests / contract-tests (pull_request) Canceled after 0s
Supply-Chain-Scan (npm) / npm-audit (pull_request) Canceled after 0s
Core-Pflichttest-Gate / pflichttest-gate (pull_request) Canceled after 0s
RBAC-Rollenhierarchie-Pflichtgate / rbac-policy-invariant (pull_request) Canceled after 0s
CI / DMS-Modul (Lint/Build/Test/Coverage/Artefakt) (push) Canceled after 0s
CI / DMS-Modul (Lint/Build/Test/Coverage/Artefakt) (pull_request) Canceled after 0s
INT-19: mobile erfassung mobilfreundliche weboberflaeche
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-26 12:06:19 +00:00

38 lines
1.6 KiB
TypeScript

// INT-19: Abschalt-Schalter fuer die mobile Erfassung (Akzeptanzkriterium 4).
// Bewusst OHNE NEXT_PUBLIC_-Praefix: der Wert wird nur serverseitig
// (app/mobil/page.tsx als Server Component) zur Anfragezeit gelesen, nie in
// das Client-Bundle gebacken. Standard ist aus (Produkt-DNA: "Kein Kanal ohne
// ausdrueckliche Freigabe").
export function mobileCaptureEnabled(): boolean {
return process.env.NEXARCH_MOBILE_CAPTURE_ENABLED === "true";
}
export interface CapturedPage {
id: string;
blob: Blob;
previewUrl: string;
}
let pageCounter = 0;
// captureFrame liest EIN Standbild aus einem laufenden <video>-Element ueber
// einen Offscreen-<canvas> (Browser-Kamera-API, kein separates App-Paket).
// Als eigene, reine Funktion, damit CameraCapture.tsx sie mocken kann, ohne
// echtes getUserMedia/Canvas in Tests zu brauchen.
export async function captureFrame(video: HTMLVideoElement, canvas: HTMLCanvasElement): Promise<CapturedPage> {
canvas.width = video.videoWidth;
canvas.height = video.videoHeight;
const ctx = canvas.getContext("2d");
if (!ctx) throw new Error("Kamera-Aufnahme: 2D-Kontext nicht verfuegbar");
ctx.drawImage(video, 0, 0, canvas.width, canvas.height);
const blob = await new Promise<Blob>((resolve, reject) => {
canvas.toBlob((b) => (b ? resolve(b) : reject(new Error("Kamera-Aufnahme: Bild konnte nicht erzeugt werden"))), "image/jpeg", 0.9);
});
pageCounter += 1;
return { id: `seite-${pageCounter}`, blob, previewUrl: URL.createObjectURL(blob) };
}
export function pageToFile(page: CapturedPage, index: number): File {
return new File([page.blob], `kassenbeleg-${index + 1}.jpg`, { type: "image/jpeg" });
}