2020-08-30 12:18:16 +02:00
Grocy . Components . BarcodeScanner = { } ;
2019-09-19 12:48:02 +02:00
2020-04-13 22:34:52 +02:00
Grocy . Components . BarcodeScanner . LiveVideoSizeAdjusted = false ;
2020-04-13 22:07:38 +02:00
Grocy . Components . BarcodeScanner . CheckCapabilities = async function ( )
2020-03-29 14:25:04 +02:00
{
var track = Quagga . CameraAccess . getActiveTrack ( ) ;
var capabilities = { } ;
2020-08-30 12:18:16 +02:00
if ( typeof track . getCapabilities === 'function' )
{
2020-03-29 14:25:04 +02:00
capabilities = track . getCapabilities ( ) ;
}
2020-08-29 16:41:27 +02:00
2020-04-13 22:07:38 +02:00
// If there is more than 1 camera, show the camera selection
var cameras = await Quagga . CameraAccess . enumerateVideoDevices ( ) ;
2020-04-13 22:30:35 +02:00
var cameraSelect = document . querySelector ( '.cameraSelect-wrapper' ) ;
2020-08-30 12:18:16 +02:00
if ( cameraSelect )
{
2020-04-13 22:07:38 +02:00
cameraSelect . style . display = cameras . length > 1 ? 'inline-block' : 'none' ;
}
2020-08-29 16:41:27 +02:00
2020-03-29 14:25:04 +02:00
// 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' ) ;
2020-08-30 12:18:16 +02:00
if ( node )
{
2020-03-29 14:25:04 +02:00
node . style . display = canTorch && ! Grocy . FeatureFlags . GROCY _FEATURE _FLAG _AUTO _TORCH _ON _WITH _CAMERA ? 'inline-block' : 'none' ;
}
// If AutoTorchOn is set, turn on the torch.
2020-08-30 12:18:16 +02:00
if ( canTorch && Grocy . FeatureFlags . GROCY _FEATURE _FLAG _AUTO _TORCH _ON _WITH _CAMERA )
{
2020-03-29 14:25:04 +02:00
Grocy . Components . BarcodeScanner . TorchOn ( track ) ;
}
// Reduce the height of the video, if it's heigher than then the viewport
2020-04-13 22:34:52 +02:00
if ( ! Grocy . Components . BarcodeScanner . LiveVideoSizeAdjusted )
{
var bc = document . getElementById ( 'barcodescanner-container' ) ;
if ( bc )
{
var bcAspectRatio = bc . offsetWidth / bc . offsetHeight ;
var settings = track . getSettings ( ) ;
if ( bcAspectRatio > settings . aspectRatio )
{
var v = document . querySelector ( '#barcodescanner-livestream video' )
if ( v )
{
var c = document . querySelector ( '#barcodescanner-livestream canvas' )
var newWidth = v . clientWidth / bcAspectRatio * settings . aspectRatio + 'px' ;
v . style . width = newWidth ;
c . style . width = newWidth ;
}
2020-03-29 14:25:04 +02:00
}
2020-04-13 22:34:52 +02:00
Grocy . Components . BarcodeScanner . LiveVideoSizeAdjusted = true ;
2020-03-29 14:25:04 +02:00
}
}
}
2019-09-19 12:48:02 +02:00
Grocy . Components . BarcodeScanner . StartScanning = function ( )
{
2019-09-21 20:46:23 +02:00
Grocy . Components . BarcodeScanner . DecodedCodesCount = 0 ;
Grocy . Components . BarcodeScanner . DecodedCodesErrorCount = 0 ;
2019-09-19 12:48:02 +02:00
Quagga . init ( {
inputStream : {
name : "Live" ,
type : "LiveStream" ,
target : document . querySelector ( "#barcodescanner-livestream" ) ,
constraints : {
2020-04-13 22:07:38 +02:00
facingMode : "environment" ,
2020-08-30 12:18:16 +02:00
... ( window . localStorage . getItem ( 'cameraId' ) && { deviceId : window . localStorage . getItem ( 'cameraId' ) } ) // If preferred cameraId is set, request to use that specific camera
2019-09-19 12:48:02 +02:00
}
} ,
locator : {
2020-08-19 14:52:04 -03:00
patchSize : Grocy . UserSettings . quagga2 _patchsize ,
halfSample : Grocy . UserSettings . quagga2 _halfsample ,
2019-09-19 12:48:02 +02:00
debug : {
2020-08-19 14:52:04 -03:00
showCanvas : Grocy . UserSettings . quagga2 _debug ,
showPatches : Grocy . UserSettings . quagga2 _debug ,
showFoundPatches : Grocy . UserSettings . quagga2 _debug ,
showSkeleton : Grocy . UserSettings . quagga2 _debug ,
showLabels : Grocy . UserSettings . quagga2 _debug ,
showPatchLabels : Grocy . UserSettings . quagga2 _debug ,
showRemainingPatchLabels : Grocy . UserSettings . quagga2 _debug ,
2019-09-19 12:48:02 +02:00
boxFromPatches : {
2020-08-19 14:52:04 -03:00
showTransformed : Grocy . UserSettings . quagga2 _debug ,
showTransformedBox : Grocy . UserSettings . quagga2 _debug ,
showBB : Grocy . UserSettings . quagga2 _debug
2019-09-19 12:48:02 +02:00
}
}
} ,
2020-04-13 16:14:43 +02:00
numOfWorkers : Grocy . UserSettings . quagga2 _numofworkers ,
2020-08-19 14:52:04 -03:00
frequency : Grocy . UserSettings . quagga2 _frequency ,
2019-09-19 12:48:02 +02:00
decoder : {
readers : [
"ean_reader" ,
"ean_8_reader" ,
2019-09-21 20:46:23 +02:00
"code_128_reader"
2019-09-19 12:48:02 +02:00
] ,
debug : {
2020-08-19 14:52:04 -03:00
showCanvas : Grocy . UserSettings . quagga2 _debug ,
showPatches : Grocy . UserSettings . quagga2 _debug ,
showFoundPatches : Grocy . UserSettings . quagga2 _debug ,
showSkeleton : Grocy . UserSettings . quagga2 _debug ,
showLabels : Grocy . UserSettings . quagga2 _debug ,
showPatchLabels : Grocy . UserSettings . quagga2 _debug ,
showRemainingPatchLabels : Grocy . UserSettings . quagga2 _debug ,
2019-09-19 12:48:02 +02:00
boxFromPatches : {
2020-08-19 14:52:04 -03:00
showTransformed : Grocy . UserSettings . quagga2 _debug ,
showTransformedBox : Grocy . UserSettings . quagga2 _debug ,
showBB : Grocy . UserSettings . quagga2 _debug
2019-09-19 12:48:02 +02:00
}
}
} ,
locate : true
} , function ( error )
{
if ( error )
{
Grocy . FrontendHelpers . ShowGenericError ( "Error while initializing the barcode scanning library" , error . message ) ;
2020-03-06 20:58:01 +01:00
toastr . info ( _ _t ( "Camera access is only possible when supported and allowed by your browser and when grocy is served via a secure (https://) connection" ) ) ;
2020-04-13 22:07:38 +02:00
window . localStorage . removeItem ( "cameraId" ) ;
2019-09-20 13:37:53 +02:00
setTimeout ( function ( )
{
bootbox . hideAll ( ) ;
} , 500 ) ;
2019-09-19 12:48:02 +02:00
return ;
}
2020-03-29 14:25:04 +02:00
Grocy . Components . BarcodeScanner . CheckCapabilities ( ) ;
2019-09-19 12:48:02 +02:00
Quagga . start ( ) ;
} ) ;
}
Grocy . Components . BarcodeScanner . StopScanning = function ( )
{
Quagga . stop ( ) ;
2020-08-29 16:41:27 +02:00
2019-09-21 20:46:23 +02:00
Grocy . Components . BarcodeScanner . DecodedCodesCount = 0 ;
Grocy . Components . BarcodeScanner . DecodedCodesErrorCount = 0 ;
2019-09-19 12:48:02 +02:00
bootbox . hideAll ( ) ;
}
2020-03-29 14:25:04 +02:00
Grocy . Components . BarcodeScanner . TorchOn = function ( track )
{
2020-08-30 12:18:16 +02:00
if ( track )
{
2020-08-29 16:41:27 +02:00
track . applyConstraints ( {
2020-03-29 14:25:04 +02:00
advanced : [
2020-08-29 16:41:27 +02:00
{
2020-03-29 14:25:04 +02:00
torch : true
}
]
} ) ;
}
}
2019-09-19 12:48:02 +02:00
Quagga . onDetected ( function ( result )
{
2019-09-21 20:46:23 +02:00
$ . each ( result . codeResult . decodedCodes , function ( id , error )
{
if ( error . error != undefined )
{
Grocy . Components . BarcodeScanner . DecodedCodesCount ++ ;
Grocy . Components . BarcodeScanner . DecodedCodesErrorCount += parseFloat ( error . error ) ;
}
} ) ;
if ( Grocy . Components . BarcodeScanner . DecodedCodesErrorCount / Grocy . Components . BarcodeScanner . DecodedCodesCount < 0.15 )
{
Grocy . Components . BarcodeScanner . StopScanning ( ) ;
2020-04-13 15:55:27 +02:00
$ ( document ) . trigger ( "Grocy.BarcodeScanned" , [ result . codeResult . code , Grocy . Components . BarcodeScanner . CurrentTarget ] ) ;
2019-09-21 20:46:23 +02:00
}
2019-09-19 12:48:02 +02:00
} ) ;
Quagga . onProcessed ( function ( result )
{
var drawingCtx = Quagga . canvas . ctx . overlay ;
var drawingCanvas = Quagga . canvas . dom . overlay ;
if ( result )
{
if ( result . boxes )
{
drawingCtx . clearRect ( 0 , 0 , parseInt ( drawingCanvas . getAttribute ( "width" ) ) , parseInt ( drawingCanvas . getAttribute ( "height" ) ) ) ;
result . boxes . filter ( function ( box )
{
return box !== result . box ;
} ) . forEach ( function ( box )
{
2019-09-21 20:46:23 +02:00
Quagga . ImageDebug . drawPath ( box , { x : 0 , y : 1 } , drawingCtx , { color : "yellow" , lineWidth : 4 } ) ;
2019-09-19 12:48:02 +02:00
} ) ;
}
if ( result . box )
{
2019-09-21 20:46:23 +02:00
Quagga . ImageDebug . drawPath ( result . box , { x : 0 , y : 1 } , drawingCtx , { color : "green" , lineWidth : 4 } ) ;
2019-09-19 12:48:02 +02:00
}
if ( result . codeResult && result . codeResult . code )
{
Quagga . ImageDebug . drawPath ( result . line , { x : 'x' , y : 'y' } , drawingCtx , { color : "red" , lineWidth : 4 } ) ;
}
}
} ) ;
2020-04-13 22:07:38 +02:00
$ ( document ) . on ( "click" , "#barcodescanner-start-button" , async function ( e )
2019-09-19 12:48:02 +02:00
{
e . preventDefault ( ) ;
2019-09-27 17:24:44 +02:00
var inputElement = $ ( e . currentTarget ) . prev ( ) ;
if ( inputElement . hasAttr ( "disabled" ) )
{
// Do nothing and disable the barcode scanner start button
$ ( e . currentTarget ) . addClass ( "disabled" ) ;
return ;
}
2020-04-13 15:55:27 +02:00
Grocy . Components . BarcodeScanner . CurrentTarget = inputElement . attr ( "data-target" ) ;
2020-08-29 16:41:27 +02:00
2020-04-13 22:07:38 +02:00
var dialog = bootbox . dialog ( {
2019-09-19 12:48:02 +02:00
message : '<div id="barcodescanner-container" class="col"><div id="barcodescanner-livestream"></div></div>' ,
title : _ _t ( 'Scan a barcode' ) ,
onEscape : function ( )
{
Grocy . Components . BarcodeScanner . StopScanning ( ) ;
} ,
size : 'big' ,
backdrop : true ,
2020-03-01 17:53:28 +01:00
closeButton : true ,
2019-09-19 12:48:02 +02:00
buttons : {
2020-03-01 17:53:28 +01:00
torch : {
2020-03-01 17:58:10 +01:00
label : '<i class="far fa-lightbulb"></i>' ,
2020-03-29 14:25:04 +02:00
className : 'btn-warning responsive-button torch' ,
2020-03-01 17:58:10 +01:00
callback : function ( )
{
2020-03-29 14:25:04 +02:00
Grocy . Components . BarcodeScanner . TorchOn ( Quagga . CameraAccess . getActiveTrack ( ) ) ;
2020-03-01 17:58:10 +01:00
return false ;
2020-08-30 12:18:16 +02:00
}
2020-08-29 16:41:27 +02:00
} ,
2019-09-19 12:48:02 +02:00
cancel : {
label : _ _t ( 'Cancel' ) ,
className : 'btn-secondary responsive-button' ,
callback : function ( )
{
Grocy . Components . BarcodeScanner . StopScanning ( ) ;
}
2019-09-20 13:37:53 +02:00
}
2019-09-19 12:48:02 +02:00
}
} ) ;
2020-08-29 16:41:27 +02:00
2020-04-13 22:07:38 +02:00
// Add camera select to existing dialog
2020-04-13 22:30:35 +02:00
dialog . find ( '.bootbox-body' ) . append ( '<div class="form-group py-0 my-1 cameraSelect-wrapper"><select class="form-control cameraSelect"><select class="form-control cameraSelect" style="display: none"></select></div>' ) ;
2020-04-13 22:07:38 +02:00
var cameraSelect = document . querySelector ( '.cameraSelect' ) ;
2020-08-29 16:41:27 +02:00
2020-04-13 22:07:38 +02:00
var cameras = await Quagga . CameraAccess . enumerateVideoDevices ( ) ;
2020-08-30 12:18:16 +02:00
cameras . forEach ( camera =>
{
2020-04-13 22:07:38 +02:00
var option = document . createElement ( "option" ) ;
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' ) ;
2020-08-30 12:18:16 +02:00
cameraSelect . onchange = function ( )
{
2020-04-13 22:07:38 +02:00
window . localStorage . setItem ( 'cameraId' , cameraSelect . value ) ;
Quagga . stop ( ) ;
Grocy . Components . BarcodeScanner . StartScanning ( ) ;
} ;
2020-08-29 16:41:27 +02:00
2019-09-19 12:48:02 +02:00
Grocy . Components . BarcodeScanner . StartScanning ( ) ;
} ) ;
setTimeout ( function ( )
{
2019-09-27 17:24:44 +02:00
$ ( ".barcodescanner-input:visible" ) . each ( function ( )
{
if ( $ ( this ) . hasAttr ( "disabled" ) )
{
2020-04-13 15:55:27 +02:00
$ ( this ) . after ( '<a id="barcodescanner-start-button" class="btn btn-sm btn-primary text-white disabled" data-target="' + $ ( this ) . attr ( "data-target" ) + '"><i class="fas fa-camera"></i></a>' ) ;
2019-09-27 17:24:44 +02:00
}
else
{
2020-04-13 15:55:27 +02:00
$ ( this ) . after ( '<a id="barcodescanner-start-button" class="btn btn-sm btn-primary text-white" data-target="' + $ ( this ) . attr ( "data-target" ) + '"><i class="fas fa-camera"></i></a>' ) ;
2019-09-27 17:24:44 +02:00
}
} ) ;
2019-09-19 12:48:02 +02:00
} , 50 ) ;