Merge branch 'main' of http://192.168.1.200:3000/Stratawiz/Rapport-Laravel
Specific Folder FTP Upload / ftp-deploy (push) Successful in 30s
Details
Specific Folder FTP Upload / ftp-deploy (push) Successful in 30s
Details
This commit is contained in:
commit
06560951c2
|
|
@ -190,6 +190,13 @@
|
||||||
style="display:none;">
|
style="display:none;">
|
||||||
|
|
||||||
<div class="d-flex flex-wrap gap-2 mt-2">
|
<div class="d-flex flex-wrap gap-2 mt-2">
|
||||||
|
|
||||||
|
<button type="button" id="switch-photo-camera"
|
||||||
|
class="btn btn-info" style="display:none;">
|
||||||
|
<i class="mdi mdi-camera-switch me-1"></i>
|
||||||
|
Switch Camera
|
||||||
|
</button>
|
||||||
|
|
||||||
<button type="button" id="capture-photo"
|
<button type="button" id="capture-photo"
|
||||||
class="btn btn-success" style="display:none;">
|
class="btn btn-success" style="display:none;">
|
||||||
Capture Photo
|
Capture Photo
|
||||||
|
|
@ -391,31 +398,33 @@
|
||||||
|
|
||||||
|
|
||||||
let photoStream = null;
|
let photoStream = null;
|
||||||
|
let currentCamera = 'environment';
|
||||||
|
|
||||||
const video = document.getElementById('photo-camera-preview');
|
const video = document.getElementById('photo-camera-preview');
|
||||||
const preview = document.getElementById('photo-captured-preview');
|
const preview = document.getElementById('photo-captured-preview');
|
||||||
const photoInput = document.getElementById('field-upload_photo');
|
const photoInput = document.getElementById('field-upload_photo');
|
||||||
|
|
||||||
$('#start-photo-camera').on('click', async function () {
|
// Start camera
|
||||||
|
async function startPhotoCamera(cameraType = currentCamera) {
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
// Stop previous camera before switching
|
||||||
|
stopPhotoCamera();
|
||||||
|
|
||||||
|
currentCamera = cameraType;
|
||||||
|
|
||||||
if (!navigator.mediaDevices ||
|
if (!navigator.mediaDevices ||
|
||||||
!navigator.mediaDevices.getUserMedia) {
|
!navigator.mediaDevices.getUserMedia) {
|
||||||
throw new Error('Camera API is unavailable. Use HTTPS or localhost.');
|
throw new Error('Camera access requires HTTPS or localhost.');
|
||||||
}
|
}
|
||||||
|
|
||||||
// Request camera permission
|
|
||||||
photoStream = await navigator.mediaDevices.getUserMedia({
|
photoStream = await navigator.mediaDevices.getUserMedia({
|
||||||
video: {
|
video: {
|
||||||
facingMode: { ideal: 'environment' }
|
facingMode: { exact: currentCamera }
|
||||||
},
|
},
|
||||||
audio: false
|
audio: false
|
||||||
});
|
});
|
||||||
|
|
||||||
// Check required elements
|
|
||||||
if (!video || !preview || !photoInput) {
|
|
||||||
throw new Error('Camera elements are missing from the page.');
|
|
||||||
}
|
|
||||||
|
|
||||||
video.srcObject = photoStream;
|
video.srcObject = photoStream;
|
||||||
video.style.display = 'block';
|
video.style.display = 'block';
|
||||||
preview.style.display = 'none';
|
preview.style.display = 'none';
|
||||||
|
|
@ -423,43 +432,73 @@
|
||||||
await video.play();
|
await video.play();
|
||||||
|
|
||||||
$('#start-photo-camera').hide();
|
$('#start-photo-camera').hide();
|
||||||
|
$('#switch-photo-camera').show();
|
||||||
$('#capture-photo').show();
|
$('#capture-photo').show();
|
||||||
$('#retake-photo').hide();
|
$('#retake-photo').hide();
|
||||||
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
|
||||||
console.error('Camera error:', error);
|
console.error('Camera error:', error);
|
||||||
|
|
||||||
// Stop any partially opened camera stream
|
stopPhotoCamera();
|
||||||
if (photoStream) {
|
|
||||||
photoStream.getTracks().forEach(track => track.stop());
|
// Some devices do not support the requested camera.
|
||||||
photoStream = null;
|
// Fall back to the browser's preferred camera.
|
||||||
|
if (error.name === 'OverconstrainedError' ||
|
||||||
|
error.name === 'NotFoundError') {
|
||||||
|
|
||||||
|
try {
|
||||||
|
photoStream = await navigator.mediaDevices.getUserMedia({
|
||||||
|
video: true,
|
||||||
|
audio: false
|
||||||
|
});
|
||||||
|
|
||||||
|
video.srcObject = photoStream;
|
||||||
|
video.style.display = 'block';
|
||||||
|
await video.play();
|
||||||
|
|
||||||
|
$('#start-photo-camera').hide();
|
||||||
|
$('#switch-photo-camera').show();
|
||||||
|
$('#capture-photo').show();
|
||||||
|
|
||||||
|
return;
|
||||||
|
|
||||||
|
} catch (fallbackError) {
|
||||||
|
console.error('Fallback camera error:', fallbackError);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (error.name === 'NotAllowedError' ||
|
Swal.fire({
|
||||||
error.name === 'PermissionDeniedError') {
|
icon: 'warning',
|
||||||
|
title: 'Camera Unavailable',
|
||||||
Swal.fire({
|
text: 'Please check camera permission and camera availability.'
|
||||||
icon: 'warning',
|
});
|
||||||
title: 'Camera Access Denied',
|
|
||||||
text: 'Please enable camera permission for this website in your browser settings, then try again.'
|
|
||||||
});
|
|
||||||
|
|
||||||
} else {
|
|
||||||
Swal.fire({
|
|
||||||
icon: 'error',
|
|
||||||
title: 'Unable to Open Camera',
|
|
||||||
text: error.message || 'Please check your camera and try again.'
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Open camera
|
||||||
|
$('#start-photo-camera').on('click', function () {
|
||||||
|
startPhotoCamera('environment');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Switch between front and back cameras
|
||||||
|
$('#switch-photo-camera').on('click', function () {
|
||||||
|
|
||||||
|
const nextCamera =
|
||||||
|
currentCamera === 'environment' ? 'user' : 'environment';
|
||||||
|
|
||||||
|
startPhotoCamera(nextCamera);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Capture photo
|
||||||
$('#capture-photo').on('click', function () {
|
$('#capture-photo').on('click', function () {
|
||||||
|
|
||||||
if (!photoStream || !video.videoWidth) {
|
if (!photoStream || !video.videoWidth) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const canvas = document.createElement('canvas');
|
const canvas = document.createElement('canvas');
|
||||||
|
|
||||||
canvas.width = video.videoWidth;
|
canvas.width = video.videoWidth;
|
||||||
canvas.height = video.videoHeight;
|
canvas.height = video.videoHeight;
|
||||||
|
|
||||||
|
|
@ -468,6 +507,7 @@
|
||||||
);
|
);
|
||||||
|
|
||||||
canvas.toBlob(function (blob) {
|
canvas.toBlob(function (blob) {
|
||||||
|
|
||||||
if (!blob) {
|
if (!blob) {
|
||||||
Swal.fire('Error', 'Could not capture the photo.', 'error');
|
Swal.fire('Error', 'Could not capture the photo.', 'error');
|
||||||
return;
|
return;
|
||||||
|
|
@ -481,7 +521,7 @@
|
||||||
|
|
||||||
const transfer = new DataTransfer();
|
const transfer = new DataTransfer();
|
||||||
transfer.items.add(file);
|
transfer.items.add(file);
|
||||||
photoInput.files = transfer.files;
|
photoInput.files = transfer.files;
|
||||||
|
|
||||||
preview.src = URL.createObjectURL(blob);
|
preview.src = URL.createObjectURL(blob);
|
||||||
preview.style.display = 'block';
|
preview.style.display = 'block';
|
||||||
|
|
@ -489,27 +529,37 @@
|
||||||
|
|
||||||
stopPhotoCamera();
|
stopPhotoCamera();
|
||||||
|
|
||||||
$('#capture-photo').hide();
|
|
||||||
$('#start-photo-camera').hide();
|
$('#start-photo-camera').hide();
|
||||||
|
$('#switch-photo-camera').hide();
|
||||||
|
$('#capture-photo').hide();
|
||||||
$('#retake-photo').show();
|
$('#retake-photo').show();
|
||||||
|
|
||||||
}, 'image/jpeg', 0.9);
|
}, 'image/jpeg', 0.9);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Retake photo
|
||||||
$('#retake-photo').on('click', function () {
|
$('#retake-photo').on('click', function () {
|
||||||
|
|
||||||
photoInput.value = '';
|
photoInput.value = '';
|
||||||
preview.src = '';
|
preview.src = '';
|
||||||
preview.style.display = 'none';
|
preview.style.display = 'none';
|
||||||
|
|
||||||
$('#retake-photo').hide();
|
$('#retake-photo').hide();
|
||||||
$('#start-photo-camera').trigger('click');
|
|
||||||
|
startPhotoCamera(currentCamera);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Stop camera
|
||||||
function stopPhotoCamera() {
|
function stopPhotoCamera() {
|
||||||
|
|
||||||
if (photoStream) {
|
if (photoStream) {
|
||||||
photoStream.getTracks().forEach(track => track.stop());
|
photoStream.getTracks().forEach(track => track.stop());
|
||||||
photoStream = null;
|
photoStream = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
video.srcObject = null;
|
if (video) {
|
||||||
|
video.srcObject = null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
window.addEventListener('beforeunload', stopPhotoCamera);
|
window.addEventListener('beforeunload', stopPhotoCamera);
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue