added systemd service howto traefik nginix set_real_ip_from improved readme visuals fixed on mobile labels removed updated readme fixed visuals overlay for the hotkey disable screen lock clean up git precommit hooks clean up clean up update check for update feature added build-time information fixed date
69 lines
3.1 KiB
JavaScript
69 lines
3.1 KiB
JavaScript
export const CameraService = {
|
|
async getPhoto() {
|
|
return new Promise(async (resolve, reject) => {
|
|
if (!navigator.mediaDevices || !navigator.mediaDevices.getUserMedia) {
|
|
reject(new Error('Camera API not available.'));
|
|
return;
|
|
}
|
|
|
|
try {
|
|
const stream = await navigator.mediaDevices.getUserMedia({ video: { facingMode: "user" }, audio: false });
|
|
|
|
// Create a modal or an overlay to show the video stream and a capture button
|
|
const videoElement = document.createElement('video');
|
|
videoElement.srcObject = stream;
|
|
videoElement.setAttribute('playsinline', ''); // Required for iOS
|
|
videoElement.style.cssText = "position: fixed; top: 50%; left: 50%; transform: translate(-50%, -50%); max-width: 90%; max-height: 70vh; z-index: 1001; border-radius: 8px; box-shadow: 0 4px 12px rgba(0,0,0,0.2);";
|
|
|
|
const captureButton = document.createElement('button');
|
|
captureButton.textContent = 'Capture';
|
|
captureButton.style.cssText = "position: fixed; bottom: 10%; left: 50%; transform: translateX(-50%); z-index: 1002; padding: 12px 24px; background-color: #3b82f6; color: white; border: none; border-radius: 8px; font-size: 16px; cursor: pointer;";
|
|
|
|
const closeButton = document.createElement('button');
|
|
closeButton.textContent = 'Cancel';
|
|
closeButton.style.cssText = "position: fixed; top: 10px; right: 10px; z-index: 1002; padding: 8px 12px; background-color: #ef4444; color: white; border: none; border-radius: 8px; font-size: 14px; cursor: pointer;";
|
|
|
|
|
|
const overlay = document.createElement('div');
|
|
overlay.style.cssText = "position: fixed; top: 0; left: 0; width: 100%; height: 100%; background-color: rgba(0,0,0,0.7); z-index: 1000;";
|
|
|
|
document.body.appendChild(overlay);
|
|
document.body.appendChild(videoElement);
|
|
document.body.appendChild(captureButton);
|
|
document.body.appendChild(closeButton);
|
|
|
|
videoElement.onloadedmetadata = () => {
|
|
videoElement.play();
|
|
};
|
|
|
|
const cleanup = () => {
|
|
stream.getTracks().forEach(track => track.stop());
|
|
document.body.removeChild(videoElement);
|
|
document.body.removeChild(captureButton);
|
|
document.body.removeChild(closeButton);
|
|
document.body.removeChild(overlay);
|
|
};
|
|
|
|
captureButton.onclick = () => {
|
|
const canvas = document.createElement('canvas');
|
|
canvas.width = videoElement.videoWidth;
|
|
canvas.height = videoElement.videoHeight;
|
|
const context = canvas.getContext('2d');
|
|
context.drawImage(videoElement, 0, 0, canvas.width, canvas.height);
|
|
const dataUrl = canvas.toDataURL('image/png');
|
|
cleanup();
|
|
resolve(dataUrl);
|
|
};
|
|
|
|
closeButton.onclick = () => {
|
|
cleanup();
|
|
reject(new Error('User cancelled photo capture.'));
|
|
};
|
|
|
|
} catch (err) {
|
|
console.error("Error accessing camera: ", err);
|
|
reject(err);
|
|
}
|
|
});
|
|
}
|
|
}; |