From 63c836498e4afd7063a9e569c1163fdb474f3660 Mon Sep 17 00:00:00 2001 From: "afiq.hamzah" Date: Wed, 14 Dec 2022 12:38:08 +0800 Subject: [PATCH] Add priority camera models for taking marhun photo --- .env.example | 2 + config/marhun_camera.php | 7 + public/js/marhun-photo-capture-debugger.js | 42 ++++ public/js/marhun-photo-capture.js | 277 ++++++++++----------- resources/views/marhun/marhun.blade.php | 3 + 5 files changed, 181 insertions(+), 150 deletions(-) create mode 100644 config/marhun_camera.php create mode 100644 public/js/marhun-photo-capture-debugger.js diff --git a/.env.example b/.env.example index ac3e40ab..dde40a3b 100644 --- a/.env.example +++ b/.env.example @@ -298,3 +298,5 @@ PUSHER_APP_CLUSTER=mt1 MIX_PUSHER_APP_KEY="${PUSHER_APP_KEY}" MIX_PUSHER_APP_CLUSTER="${PUSHER_APP_CLUSTER}" + +MARHUN_CAMERAS = "Doccamera" diff --git a/config/marhun_camera.php b/config/marhun_camera.php new file mode 100644 index 00000000..a3c2f753 --- /dev/null +++ b/config/marhun_camera.php @@ -0,0 +1,7 @@ + array_map(fn ($camera_label) => trim($camera_label), explode(',', env('MARHUN_CAMERAS'))) ?? 'Doccamera' + +]; diff --git a/public/js/marhun-photo-capture-debugger.js b/public/js/marhun-photo-capture-debugger.js new file mode 100644 index 00000000..7ba6bcea --- /dev/null +++ b/public/js/marhun-photo-capture-debugger.js @@ -0,0 +1,42 @@ + +function marhunPhotoCapturerDebugger() { + + return { + + scan: function () { + if ('mediaDevices' in navigator && navigator.mediaDevices.getUserMedia) { + + // let camera_label = "HP TrueVision HD Camera (05c8:03d2)"; + // let camera_label = "USB Camera (0c45:6366)"; + let camera_label = "Doccamera (2b19:0200)"; + + const generateCameraListing = (cameras) => { + let title = "Available cameras: "; + + let content = cameras.map((camera, index) => { + index = index + 1; + return `${index}. ${camera.label}\n`; + }); + + return `${title}\n${content.join('')}`; + }; + + navigator.mediaDevices.enumerateDevices() + .then(devices => devices.filter(x => x.kind === 'videoinput')) + .then(devices => devices.map(device => { + let altered_label = device.label.split(" "); + altered_label.splice(-1); + altered_label = altered_label.join(" "); + + return { + label: altered_label, + deviceId: device.deviceId, + }; + })) + .then(devices => alert(generateCameraListing(devices))) + } + + return true; + }, + } +} diff --git a/public/js/marhun-photo-capture.js b/public/js/marhun-photo-capture.js index cdd8d5e5..23fc6412 100644 --- a/public/js/marhun-photo-capture.js +++ b/public/js/marhun-photo-capture.js @@ -1,183 +1,160 @@ function marhunPhotoCapturerFactory(modal_selector) { - return { + return { - constraints: { - audio: false, - video: { - height: { ideal: 1080 } - }, - facingMode: { exact: "environment" }, - }, + constraints: { + audio: false, + video: true, + }, - imageCapturer: null, + imageCapturer: null, - start: function start() { - navigator.mediaDevices.getUserMedia(this.constraints) - .then(this.gotMedia) - .catch(e => { console.error('getUserMedia() failed: ', e); }); - }, + captureMedia: function (mediastream) { - gotMedia: function (mediastream) { + let videoTrack = mediastream.getVideoTracks()[0]; + let imageCapturer = new ImageCapture(videoTrack); - let modal = document.querySelector(modal_selector); - let videoTag = modal.querySelector('.video-tag-overallmarhun'); + let modal = document.querySelector(modal_selector); + let imageTag = modal.querySelector('.image-tag-overallmarhun'); - videoTag.srcObject = mediastream; + let setMarhunPhotoInputToCapturedPhoto = function (blob) { + const modal = document.querySelector(modal_selector); + const marhunPhotoInput = modal.querySelector('#inputGroupFile04'); - let videoTrack = mediastream.getVideoTracks()[0]; - this.imageCapturer = new ImageCapture(videoTrack); + const marhunPhotoFile = new File([blob], 'marhun_photo.png', { + type: 'image/png', + lastModified: new Date().getTime(), + }); + + const dataTransfer = new DataTransfer(); + dataTransfer.items.add(marhunPhotoFile); + marhunPhotoInput.files = dataTransfer.files; + + }; + + imageCapturer.takePhoto() + .then((blob) => { + imageTag.src = URL.createObjectURL(blob); + imageTag.classList.add('marhun-uploaded'); - // Timeout needed in Chrome, see https://crbug.com/711524 - setTimeout(() => { - const capabilities = videoTrack.getCapabilities() - console.log(capabilities) + modal.querySelector('.video-tag-overallmarhun').classList.add('d-none'); - // Check whether zoom is supported or not. - if (!capabilities.zoom) { - return; - } + modal.querySelector('.camera-shutter').classList.remove('d-none'); + modal.querySelector('.camera-shutter').classList.add('d-flex'); - }, 500); + window.setTimeout(() => { + modal.querySelector('.image-tag-overallmarhun').classList.remove('d-none'); + modal.querySelector('.camera-shutter').classList.remove('d-flex'); + modal.querySelector('.camera-shutter').classList.add('d-none'); + modal.querySelector('.camera-button').classList.add('d-none') + }, 1000); - }, + modal.querySelector('button[type="submit"]').disabled = false; - captureMedia: function (mediastream) { + return blob; - let videoTrack = mediastream.getVideoTracks()[0]; - let imageCapturer = new ImageCapture(videoTrack); + }) + .then(blob => setMarhunPhotoInputToCapturedPhoto(blob)) + .catch((err) => { + console.error("takePhoto() failed: ", err); + }); - let modal = document.querySelector(modal_selector); - let imageTag = modal.querySelector('.image-tag-overallmarhun'); + }, + takePhoto: function () { - let setMarhunPhotoInputToCapturedPhoto = function (blob) { - const modal = document.querySelector(modal_selector); - const marhunPhotoInput = modal.querySelector('#inputGroupFile04'); + if ('mediaDevices' in navigator && navigator.mediaDevices.getUserMedia) { + this.getCamera() + .then(this.captureMedia) + .catch(e => { console.error('getUserMedia() failed: ', e); }); + } + }, + + getCamera: function () { + function getCameraList() { + return navigator.mediaDevices.enumerateDevices() + .then(devices => devices.filter(x => x.kind === 'videoinput')) + } + + function selectNearWorkingCamera(listOfCameras) { + return listOfCameras.at(0); + } - const marhunPhotoFile = new File([blob], 'marhun_photo.png', { - type: 'image/png', - lastModified: new Date().getTime(), - }); + function selectPriorityCameraIfExist(listOfCameras) { + + const available_cameras = listOfCameras.map(camera => { + let altered_label = camera.label.split(" "); + altered_label.splice(-1); + altered_label = altered_label.join(" "); + + return { + label: altered_label, + deviceId: camera.deviceId, + }; + + }); + + const filtered = available_cameras.filter(camera => { + return marhun_camera_config.includes(camera.label); + }) + + // Get the first available priority referencing to env + return filtered.at(-1); + } + + function selectCamera(listOfCameras) { + let priorityCamera = selectPriorityCameraIfExist(listOfCameras); + + if (!priorityCamera) { + return selectNearWorkingCamera(listOfCameras) + } + + return priorityCamera; + } + + function composeConstraint(camera) { + var constraints = { deviceId: { exact: camera.deviceId } }; + return navigator.mediaDevices.getUserMedia({ video: constraints }); + } + + return getCameraList() + .then(selectCamera) + .then(composeConstraint); + + }, + + initiateTakeMarhunPhoto: function () { + if ('mediaDevices' in navigator && navigator.mediaDevices.getUserMedia) { - const dataTransfer = new DataTransfer(); - dataTransfer.items.add(marhunPhotoFile); - marhunPhotoInput.files = dataTransfer.files; + function showCaptureMarhunModal() { + let modal = document.querySelector(modal_selector); - }; + modal.querySelector('.video-tag-overallmarhun').classList.remove('d-none'); + modal.querySelector('.image-tag-overallmarhun').classList.add('d-none'); + modal.querySelector('.camera-shutter').classList.add('d-none'); + modal.querySelector('.camera-button').classList.remove('d-none'); + modal.querySelector('button[type="submit"]').disabled = true; - imageCapturer.takePhoto() - .then((blob) => { - imageTag.src = URL.createObjectURL(blob); - imageTag.classList.add('marhun-uploaded'); + $(modal_selector).modal('show'); + } + function streamCameraView(stream) { + let modal = document.querySelector(modal_selector); + let videoTag = modal.querySelector('.video-tag-overallmarhun'); - modal.querySelector('.video-tag-overallmarhun').classList.add('d-none'); + videoTag.srcObject = stream; + } - modal.querySelector('.camera-shutter').classList.remove('d-none'); - modal.querySelector('.camera-shutter').classList.add('d-flex'); - - window.setTimeout(() => { - modal.querySelector('.image-tag-overallmarhun').classList.remove('d-none'); - modal.querySelector('.camera-shutter').classList.remove('d-flex'); - modal.querySelector('.camera-shutter').classList.add('d-none'); - modal.querySelector('.camera-button').classList.add('d-none') - }, 1500); - - modal.querySelector('button[type="submit"]').disabled = false; - - return blob; - - }) - .then(blob => setMarhunPhotoInputToCapturedPhoto(blob)) - .catch((err) => { - console.error("takePhoto() failed: ", err); - }); - - }, - - - takePhoto: function () { - navigator.mediaDevices.getUserMedia(this.constraints) - .then(this.captureMedia) - .catch(e => { console.error('getUserMedia() failed: ', e); }); - }, - - viewCapturedPhoto: function () { - - let imageTag = document.getElementById('image-tag'); - - if (!imageTag.classList.contains('marhun-uploaded')) { - - Swal.fire({ - icon: 'error', - title: 'Amaran!', - text: 'Sila ambil gambar marhun' - }); - - return; - } - - displayInNewTab(imageTag.src); - }, - - displayInNewTab: function (src) { - let image = new Image(); - image.src = src; - - let w = window.open(""); - w.document.write(image.outerHTML); - }, - - initiateTakeMarhunPhoto: function () { - - navigator.mediaDevices.getUserMedia(this.constraints) - .then(this.gotMedia) - .catch(e => { console.error('getUserMedia() failed: ', e); }); - - let modal = document.querySelector(modal_selector); - - modal.querySelector('.video-tag-overallmarhun').classList.remove('d-none'); - modal.querySelector('.image-tag-overallmarhun').classList.add('d-none'); - modal.querySelector('.camera-shutter').classList.add('d-none'); - modal.querySelector('.camera-button').classList.remove('d-none'); - modal.querySelector('button[type="submit"]').disabled = true; - - $(modal_selector).modal('show'); - }, - - - initiateUploadMarhunPhoto: function () { - let file_marhun_photo = document.getElementById('marhun_photo'); - let image_tag = document.getElementById('image-tag'); - - let displayUploadFileToImageTag = (event) => { - let selectedFile = event.target.files[0]; - let reader = new FileReader(); - - image_tag.title = selectedFile.name; - - reader.onload = function (event) { - image_tag.src = event.target.result; - }; - - reader.readAsDataURL(selectedFile); - - this.removeEventListener('change', displayUploadFileToImageTag); - - }; - - file_marhun_photo.addEventListener('change', displayUploadFileToImageTag); - - image_tag.classList.add('marhun-uploaded'); - - file_marhun_photo.click(); + this.getCamera() + .then(streamCameraView) + .then(showCaptureMarhunModal); + } + }, } - } } diff --git a/resources/views/marhun/marhun.blade.php b/resources/views/marhun/marhun.blade.php index 894f0697..5961d37b 100644 --- a/resources/views/marhun/marhun.blade.php +++ b/resources/views/marhun/marhun.blade.php @@ -3,12 +3,15 @@ @push('additional_scripts') + @endpush