diff --git a/public/css/grocy.css b/public/css/grocy.css index 356f0e2d..21c1af09 100755 --- a/public/css/grocy.css +++ b/public/css/grocy.css @@ -209,7 +209,7 @@ a:not([href]) { white-space: pre-wrap; } -/* Barcodescanner Quagga */ +/* Barcodescanner Quagga2 */ #barcodescanner-container { max-height: 90vw; } diff --git a/public/viewjs/components/barcodescanner.js b/public/viewjs/components/camerabarcodescanner.js similarity index 61% rename from public/viewjs/components/barcodescanner.js rename to public/viewjs/components/camerabarcodescanner.js index e3fa9ad3..ffe05287 100644 --- a/public/viewjs/components/barcodescanner.js +++ b/public/viewjs/components/camerabarcodescanner.js @@ -1,7 +1,10 @@ -Grocy.Components.BarcodeScanner = {}; +Grocy.Components.CameraBarcodeScanner = {}; -Grocy.Components.BarcodeScanner.LiveVideoSizeAdjusted = false; -Grocy.Components.BarcodeScanner.CheckCapabilities = async function() +Grocy.Components.CameraBarcodeScanner.LiveVideoSizeAdjusted = false; +Grocy.Components.CameraBarcodeScanner.CameraSelectLoaded = false; +Grocy.Components.CameraBarcodeScanner.TorchIsOn = false; + +Grocy.Components.CameraBarcodeScanner.CheckCapabilities = async function() { var track = Quagga.CameraAccess.getActiveTrack(); var capabilities = {}; @@ -10,31 +13,42 @@ Grocy.Components.BarcodeScanner.CheckCapabilities = async function() capabilities = track.getCapabilities(); } - // If there is more than 1 camera, show the camera selection - var cameras = await Quagga.CameraAccess.enumerateVideoDevices(); - var cameraSelect = document.querySelector('.cameraSelect-wrapper'); - if (cameraSelect) + // Init camera select dropdown + if (!Grocy.Components.CameraBarcodeScanner.CameraSelectLoaded) { - // Ignore devices without any name - cameraSelect.style.display = cameras.filter(x => x.label || x.deviceId).length > 1 ? 'inline-block' : 'none'; + var cameraSelect = document.querySelector('.cameraSelect'); + var cameras = await Quagga.CameraAccess.enumerateVideoDevices(); + cameras.forEach(camera => + { + var option = document.createElement("option"); + option.text = camera.label; + option.value = camera.deviceId; + if (track.label == camera.label) + { + option.selected = "selected"; + } + cameraSelect.appendChild(option); + }); + + Grocy.Components.CameraBarcodeScanner.CameraSelectLoaded = true; } - // Check if the camera is capable to turn on a torch. - var canTorch = typeof capabilities.torch === 'boolean' && capabilities.torch - // Remove the torch button, if either the device can not torch or AutoTorchOn is set. - var node = document.querySelector('.torch'); - if (node) + // Check if the camera is capable to turn on a torch + var hasTorch = typeof capabilities.torch === 'boolean' && capabilities.torch; + + // Remove the torch button if the select camera doesn't have a torch + var button = document.querySelector('.torch'); + if (!hasTorch) { - node.style.display = canTorch && !Grocy.FeatureFlags.GROCY_FEATURE_FLAG_AUTO_TORCH_ON_WITH_CAMERA ? 'inline-block' : 'none'; + button.classList.add('disabled'); } - // If AutoTorchOn is set, turn on the torch. - if (canTorch && Grocy.FeatureFlags.GROCY_FEATURE_FLAG_AUTO_TORCH_ON_WITH_CAMERA) + else { - Grocy.Components.BarcodeScanner.TorchOn(track); + button.classList.remove('disabled'); } // Reduce the height of the video, if it's higher than then the viewport - if (!Grocy.Components.BarcodeScanner.LiveVideoSizeAdjusted) + if (!Grocy.Components.CameraBarcodeScanner.LiveVideoSizeAdjusted) { var bc = document.getElementById('barcodescanner-container'); if (bc) @@ -43,7 +57,7 @@ Grocy.Components.BarcodeScanner.CheckCapabilities = async function() var settings = track.getSettings(); if (bcAspectRatio > settings.aspectRatio) { - var v = document.querySelector('#barcodescanner-livestream video') + var v = document.querySelector('#barcodescanner-livestream video'); if (v) { var c = document.querySelector('#barcodescanner-livestream canvas') @@ -53,15 +67,15 @@ Grocy.Components.BarcodeScanner.CheckCapabilities = async function() } } - Grocy.Components.BarcodeScanner.LiveVideoSizeAdjusted = true; + Grocy.Components.CameraBarcodeScanner.LiveVideoSizeAdjusted = true; } } } -Grocy.Components.BarcodeScanner.StartScanning = function() +Grocy.Components.CameraBarcodeScanner.StartScanning = function() { - Grocy.Components.BarcodeScanner.DecodedCodesCount = 0; - Grocy.Components.BarcodeScanner.DecodedCodesErrorCount = 0; + Grocy.Components.CameraBarcodeScanner.DecodedCodesCount = 0; + Grocy.Components.CameraBarcodeScanner.DecodedCodesErrorCount = 0; Quagga.init({ inputStream: { @@ -70,7 +84,7 @@ Grocy.Components.BarcodeScanner.StartScanning = function() target: document.querySelector("#barcodescanner-livestream"), constraints: { facingMode: "environment", - ...(window.localStorage.getItem('cameraId') && { deviceId: window.localStorage.getItem('cameraId') }) // If preferred cameraId is set, request to use that specific camera + ...(window.localStorage.getItem('cameraId') && { deviceId: window.localStorage.getItem('cameraId') }), // If preferred cameraId is set, request to use that specific camera } }, locator: { @@ -130,30 +144,39 @@ Grocy.Components.BarcodeScanner.StartScanning = function() return; } - Grocy.Components.BarcodeScanner.CheckCapabilities(); - + Grocy.Components.CameraBarcodeScanner.CheckCapabilities(); Quagga.start(); + + if (Grocy.FeatureFlags.GROCY_FEATURE_FLAG_AUTO_TORCH_ON_WITH_CAMERA) + { + setTimeout(function() + { + Grocy.Components.CameraBarcodeScanner.TorchToggle(Quagga.CameraAccess.getActiveTrack()); + }, 250); + } }); } -Grocy.Components.BarcodeScanner.StopScanning = function() +Grocy.Components.CameraBarcodeScanner.StopScanning = function() { Quagga.stop(); - Grocy.Components.BarcodeScanner.DecodedCodesCount = 0; - Grocy.Components.BarcodeScanner.DecodedCodesErrorCount = 0; - - $(".modal").last().modal("hide"); + Grocy.Components.CameraBarcodeScanner.DecodedCodesCount = 0; + Grocy.Components.CameraBarcodeScanner.DecodedCodesErrorCount = 0; + Grocy.Components.CameraBarcodeScanner.LiveVideoSizeAdjusted = false; + Grocy.Components.CameraBarcodeScanner.CameraSelectLoaded = false; + Grocy.Components.CameraBarcodeScanner.TorchIsOn = false; } -Grocy.Components.BarcodeScanner.TorchOn = function(track) +Grocy.Components.CameraBarcodeScanner.TorchToggle = function(track) { if (track) { + Grocy.Components.CameraBarcodeScanner.TorchIsOn = !Grocy.Components.CameraBarcodeScanner.TorchIsOn; track.applyConstraints({ advanced: [ { - torch: true + torch: Grocy.Components.CameraBarcodeScanner.TorchIsOn } ] }); @@ -166,16 +189,16 @@ Quagga.onDetected(function(result) { if (error.error != undefined) { - Grocy.Components.BarcodeScanner.DecodedCodesCount++; - Grocy.Components.BarcodeScanner.DecodedCodesErrorCount += Number.parseFloat(error.error); + Grocy.Components.CameraBarcodeScanner.DecodedCodesCount++; + Grocy.Components.CameraBarcodeScanner.DecodedCodesErrorCount += Number.parseFloat(error.error); } }); - if ((Grocy.Components.BarcodeScanner.DecodedCodesErrorCount / Grocy.Components.BarcodeScanner.DecodedCodesCount < 0.15) || - (Grocy.Components.BarcodeScanner.DecodedCodesErrorCount == 0 && Grocy.Components.BarcodeScanner.DecodedCodesCount == 0 && result.codeResult.code.length != 0)) + if ((Grocy.Components.CameraBarcodeScanner.DecodedCodesErrorCount / Grocy.Components.CameraBarcodeScanner.DecodedCodesCount < 0.15) || + (Grocy.Components.CameraBarcodeScanner.DecodedCodesErrorCount == 0 && Grocy.Components.CameraBarcodeScanner.DecodedCodesCount == 0 && result.codeResult.code.length != 0)) { - Grocy.Components.BarcodeScanner.StopScanning(); - $(document).trigger("Grocy.BarcodeScanned", [result.codeResult.code, Grocy.Components.BarcodeScanner.CurrentTarget]); + Grocy.Components.CameraBarcodeScanner.StopScanning(); + $(document).trigger("Grocy.BarcodeScanned", [result.codeResult.code, Grocy.Components.CameraBarcodeScanner.CurrentTarget]); } }); @@ -221,72 +244,49 @@ $(document).on("click", "#barcodescanner-start-button", async function(e) return; } - Grocy.Components.BarcodeScanner.CurrentTarget = inputElement.attr("data-target"); + Grocy.Components.CameraBarcodeScanner.CurrentTarget = inputElement.attr("data-target"); var dialog = bootbox.dialog({ message: '
', title: __t('Scan a barcode'), - onEscape: function() - { - Grocy.Components.BarcodeScanner.StopScanning(); - }, - size: 'big', + size: 'large', backdrop: true, closeButton: true, + className: "form", buttons: { torch: { label: '', className: 'btn-warning responsive-button torch', callback: function() { - Grocy.Components.BarcodeScanner.TorchOn(Quagga.CameraAccess.getActiveTrack()); + Grocy.Components.CameraBarcodeScanner.TorchToggle(Quagga.CameraAccess.getActiveTrack()); return false; } - }, - cancel: { - label: __t('Cancel'), - className: 'btn-secondary responsive-button', - callback: function() - { - Grocy.Components.BarcodeScanner.StopScanning(); - } } + }, + onHide: function(e) + { + Grocy.Components.CameraBarcodeScanner.StopScanning(); } }); // Add camera select to existing dialog - dialog.find('.bootbox-body').append('
'); + dialog.find('.bootbox-body').append('
'); var cameraSelect = document.querySelector('.cameraSelect'); - - var cameras = await Quagga.CameraAccess.enumerateVideoDevices(); - cameras.forEach(camera => - { - var option = document.createElement("option"); - if (camera.label || camera.deviceId) // Ignore devices without any name - { - option.text = camera.label ? camera.label : camera.deviceId; // Use camera label if it exists, else show device id - option.value = camera.deviceId; - cameraSelect.appendChild(option); - } - }); - - // Set initial value to preferred camera if one exists - and if not, start out empty - cameraSelect.value = window.localStorage.getItem('cameraId'); - cameraSelect.onchange = function() { window.localStorage.setItem('cameraId', cameraSelect.value); Quagga.stop(); - Grocy.Components.BarcodeScanner.StartScanning(); + Grocy.Components.CameraBarcodeScanner.StartScanning(); }; - Grocy.Components.BarcodeScanner.StartScanning(); + Grocy.Components.CameraBarcodeScanner.StartScanning(); }); -Grocy.Components.BarcodeScanner.InitDone = false; -Grocy.Components.BarcodeScanner.Init = function() +Grocy.Components.CameraBarcodeScanner.InitDone = false; +Grocy.Components.CameraBarcodeScanner.Init = function() { - if (Grocy.Components.BarcodeScanner.InitDone) + if (Grocy.Components.CameraBarcodeScanner.InitDone) { return; } @@ -302,11 +302,11 @@ Grocy.Components.BarcodeScanner.Init = function() $(this).after(''); } - Grocy.Components.BarcodeScanner.InitDone = true; + Grocy.Components.CameraBarcodeScanner.InitDone = true; }); } setTimeout(function() { - Grocy.Components.BarcodeScanner.Init(); + Grocy.Components.CameraBarcodeScanner.Init(); }, 50); diff --git a/public/viewjs/mealplan.js b/public/viewjs/mealplan.js index df35c092..8d372f5f 100644 --- a/public/viewjs/mealplan.js +++ b/public/viewjs/mealplan.js @@ -475,7 +475,7 @@ $("#add-recipe-modal").on("shown.bs.modal", function(e) { if (!Grocy.FeatureFlags.GROCY_FEATURE_FLAG_DISABLE_BROWSER_BARCODE_CAMERA_SCANNING) { - Grocy.Components.BarcodeScanner.Init(); + Grocy.Components.CameraBarcodeScanner.Init(); } Grocy.Components.RecipePicker.GetInputElement().focus(); @@ -490,7 +490,7 @@ $("#add-product-modal").on("shown.bs.modal", function(e) { if (!Grocy.FeatureFlags.GROCY_FEATURE_FLAG_DISABLE_BROWSER_BARCODE_CAMERA_SCANNING) { - Grocy.Components.BarcodeScanner.Init(); + Grocy.Components.CameraBarcodeScanner.Init(); } Grocy.Components.ProductPicker.GetInputElement().focus(); diff --git a/views/barcodescannertesting.blade.php b/views/barcodescannertesting.blade.php index 91c80a00..56f0bc62 100644 --- a/views/barcodescannertesting.blade.php +++ b/views/barcodescannertesting.blade.php @@ -61,5 +61,5 @@ -@include('components.barcodescanner') +@include('components.camerabarcodescanner') @stop diff --git a/views/batterytracking.blade.php b/views/batterytracking.blade.php index 60b3056f..c7daad9a 100644 --- a/views/batterytracking.blade.php +++ b/views/batterytracking.blade.php @@ -60,5 +60,5 @@ -@include('components.barcodescanner') +@include('components.camerabarcodescanner') @stop diff --git a/views/choretracking.blade.php b/views/choretracking.blade.php index 45d03440..e9860c65 100644 --- a/views/choretracking.blade.php +++ b/views/choretracking.blade.php @@ -75,5 +75,5 @@ -@include('components.barcodescanner') +@include('components.camerabarcodescanner') @stop diff --git a/views/components/barcodescanner.blade.php b/views/components/camerabarcodescanner.blade.php similarity index 81% rename from views/components/barcodescanner.blade.php rename to views/components/camerabarcodescanner.blade.php index 98b4ad66..087ecb0b 100644 --- a/views/components/barcodescanner.blade.php +++ b/views/components/camerabarcodescanner.blade.php @@ -4,7 +4,7 @@ @once @push('componentScripts') - + @endpush @endonce diff --git a/views/components/productpicker.blade.php b/views/components/productpicker.blade.php index d7defad8..7198e8b2 100644 --- a/views/components/productpicker.blade.php +++ b/views/components/productpicker.blade.php @@ -77,4 +77,4 @@ class="form-text text-info small d-none"> {{ $__t('will be added to the list of barcodes for the selected product on submit') }} -@include('components.barcodescanner') +@include('components.camerabarcodescanner') diff --git a/views/components/recipepicker.blade.php b/views/components/recipepicker.blade.php index c2de6cfa..418f665f 100644 --- a/views/components/recipepicker.blade.php +++ b/views/components/recipepicker.blade.php @@ -41,4 +41,4 @@
{{ $__t('You have to select a recipe') }}
-@include('components.barcodescanner') +@include('components.camerabarcodescanner') diff --git a/views/productbarcodeform.blade.php b/views/productbarcodeform.blade.php index 199da09c..8a196f45 100644 --- a/views/productbarcodeform.blade.php +++ b/views/productbarcodeform.blade.php @@ -57,7 +57,7 @@ name="barcode" value="@if($mode == 'edit'){{ $barcode->barcode }}@endif" data-target="#barcode"> - @include('components.barcodescanner') + @include('components.camerabarcodescanner')