diff --git a/pos_clientlist_scan_button/README.rst b/pos_clientlist_scan_button/README.rst new file mode 100644 index 0000000000..7aa607d70a --- /dev/null +++ b/pos_clientlist_scan_button/README.rst @@ -0,0 +1,51 @@ +.. image:: https://img.shields.io/badge/license-LGPL--3-blue.png + :target: https://www.gnu.org/licenses/lgpl + :alt: License: LGPL-3 + +============================ + Pos Clientlist Scan Button +============================ + +Adds scan button for some fields on clientlist screen + +Adds scan button for some fields on clientlist screen + +Credits +======= + +Contributors +------------ +* `Kolushov Alexandr `__: + + * :one::zero: init version of the module + +Sponsors +-------- +* `IT-Projects LLC `__ + +Maintainers +----------- +* `IT-Projects LLC `__ + + To get a guaranteed support + you are kindly requested to purchase the module + at `odoo apps store `__. + + Thank you for understanding! + + `IT-Projects Team `__ + +Further information +=================== + +Demo: http://runbot.it-projects.info/demo/pos-addons/12.0 + +HTML Description: https://apps.odoo.com/apps/modules/12.0/pos_clientlist_scan_button/ + +Usage instructions: ``_ + +Changelog: ``_ + +Notifications on updates: `via Atom `_, `by Email `_ + +Tested on Odoo 12.0 3d0f8d07a494997be96868dd609bf4cc2ccc750c diff --git a/pos_clientlist_scan_button/__init__.py b/pos_clientlist_scan_button/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/pos_clientlist_scan_button/__manifest__.py b/pos_clientlist_scan_button/__manifest__.py new file mode 100644 index 0000000000..231f2021d9 --- /dev/null +++ b/pos_clientlist_scan_button/__manifest__.py @@ -0,0 +1,51 @@ +# Copyright 2019 Kolushov Alexandr +# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl.html). + +{ + "name": """pos_clientlist_scan_button""", + "summary": """Adds scan button for some fields on clientlist screen""", + "category": "Point of Sale", + # "live_test_url": "http://apps.it-projects.info/shop/product/DEMO-URL?version=12.0", + "images": [], + "version": "12.0.1.0.0", + "application": False, + + "author": "IT-Projects LLC, Kolushov Alexandr", + "support": "apps@it-projects.info", + "website": "https://apps.odoo.com/apps/modules/12.0/pos_clientlist_scan_button/", + "license": "LGPL-3", + # "price": 9.00, + # "currency": "EUR", + + "depends": [ + 'pos_qr_scan', + ], + "external_dependencies": {"python": [], "bin": []}, + "data": [ + 'views/assets.xml', + ], + "demo": [ + ], + "qweb": [ + 'static/src/xml/clientlist.xml', + ], + + "post_load": None, + "pre_init_hook": None, + "post_init_hook": None, + "uninstall_hook": None, + + "auto_install": False, + "installable": True, + + # "demo_title": "pos_clientlist_scan_button", + # "demo_addons": [ + # ], + # "demo_addons_hidden": [ + # ], + # "demo_url": "DEMO-URL", + # "demo_summary": "Adds scan button for some fields on clientlist screen", + # "demo_images": [ + # "images/MAIN_IMAGE", + # ] +} diff --git a/pos_clientlist_scan_button/doc/changelog.rst b/pos_clientlist_scan_button/doc/changelog.rst new file mode 100644 index 0000000000..5583eb326a --- /dev/null +++ b/pos_clientlist_scan_button/doc/changelog.rst @@ -0,0 +1,4 @@ +`1.0.0` +------- + +- **Init version** diff --git a/pos_clientlist_scan_button/doc/index.rst b/pos_clientlist_scan_button/doc/index.rst new file mode 100644 index 0000000000..f693428cc9 --- /dev/null +++ b/pos_clientlist_scan_button/doc/index.rst @@ -0,0 +1,35 @@ +============================ + Pos Clientlist Scan Button +============================ + +Installation +============ +{Instruction about things to do before actual installation} + +* {OPTIONAL }`Activate longpolling `__ +* {Additional notes if any} +* `Install `__ this module in a usual way + +Configuration +============= + +{Instruction how to configure the module before start to use it} + +* `Log in as SUPERUSER `__ +* `Activate Developer Mode `__ +* Open menu ``[[ {Menu} ]] >> {Submenu} >> {Subsubmenu}`` +* Click ``[{Button Name}]`` + +Usage +===== + +{Instruction for daily usage. It should describe how to check that module works. What shall user do and what would user get.} + +* Open menu ``[[ {Menu} ]]>> {Submenu} >> {Subsubmenu}`` +* Click ``[{Button Name}]`` +* RESULT: {what user gets, how the modules changes default behaviour} + +Uninstallation +============== + +{Optional section for uninstallation notes. Delete it if you don't have notes for uninstallation.} diff --git a/pos_clientlist_scan_button/static/description/icon.png b/pos_clientlist_scan_button/static/description/icon.png new file mode 100644 index 0000000000..8a058284ed Binary files /dev/null and b/pos_clientlist_scan_button/static/description/icon.png differ diff --git a/pos_clientlist_scan_button/static/src/js/pos.js b/pos_clientlist_scan_button/static/src/js/pos.js new file mode 100644 index 0000000000..d9e3e92d82 --- /dev/null +++ b/pos_clientlist_scan_button/static/src/js/pos.js @@ -0,0 +1,38 @@ +/* Copyright 2019 Kolushov Alexandr + License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html). */ +odoo.define('pos_clientlist_scan_button.pos', function (require) { + "use strict"; + + var screens = require('point_of_sale.screens'); + + screens.ClientListScreenWidget.include({ + + display_client_details: function(visibility, partner, clickpos){ + var self = this; + this._super(visibility, partner, clickpos); + var $buttons = this.$el.find('.button.scan').off(); + if(visibility === 'edit'){ + $buttons.on('click', function(ev) { + var field = this.attributes.data.value; + self.gui.show_popup('qr_scan', { + read_callback: self.scan_callback, + field: field, + ClientListScreenWidget: self + }); + }); + } + }, + + scan_callback: function(value, method) { + if (this.pos.debug){ + console.log(method.toUpperCase() + ' scanned', value); + } + var $input = this.options.ClientListScreenWidget.$el.find('input.' + this.options.field); + if ($input) { + $input.val(value); + } + this.click_cancel(); + }, + }); + +}); diff --git a/pos_clientlist_scan_button/static/src/xml/clientlist.xml b/pos_clientlist_scan_button/static/src/xml/clientlist.xml new file mode 100644 index 0000000000..81d274506b --- /dev/null +++ b/pos_clientlist_scan_button/static/src/xml/clientlist.xml @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + diff --git a/pos_clientlist_scan_button/views/assets.xml b/pos_clientlist_scan_button/views/assets.xml new file mode 100644 index 0000000000..c9d3865338 --- /dev/null +++ b/pos_clientlist_scan_button/views/assets.xml @@ -0,0 +1,11 @@ + + + + + + diff --git a/pos_qr_scan/README.rst b/pos_qr_scan/README.rst index 1ddd1ba05e..ac9f0bf67e 100644 --- a/pos_qr_scan/README.rst +++ b/pos_qr_scan/README.rst @@ -1,19 +1,31 @@ ========================= - QR Code Scanning in POS + POS QR/Barcode Scanning ========================= -Scans QR codes via device's camera. +Scans QR codes and barcodes via device's camera. + +the module supports next barcode codings: + +* code 128 +* ean +* ean 8 +* code 39 +* code 39 vin +* codabar +* upc +* upc e +* i2of5 +* code 93 Usage ===== -To subscribe to scanning event use following code in js:: +To subscribe to qr scanning event use following code in js:: var core = require('web.core'); core.bus.on('qr_scanned', this, function(value){ // your handler here - }) - + }); Credits ======= @@ -41,4 +53,4 @@ Usage instructions: ``_ Changelog: ``_ -Tested on Odoo 11.0 c7171795f891335e8a8b6d5a6b796c28cea77fea +Tested on Odoo 12.0 53dcdd5a9e22429a9638f68674264436ce21e42b diff --git a/pos_qr_scan/__init__.py b/pos_qr_scan/__init__.py index e69de29bb2..75d7924518 100644 --- a/pos_qr_scan/__init__.py +++ b/pos_qr_scan/__init__.py @@ -0,0 +1,3 @@ +# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl.html). + +from . import models diff --git a/pos_qr_scan/__manifest__.py b/pos_qr_scan/__manifest__.py index 15c3d9b3d4..c7897ed999 100644 --- a/pos_qr_scan/__manifest__.py +++ b/pos_qr_scan/__manifest__.py @@ -1,10 +1,13 @@ +# Copyright 2018-2019 Kolushov Alexandr +# Copyright 2018 Ivan Yelizariev +# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl.html). { "name": """QR Code Scanning in POS""", "summary": """Scans QR codes via device's camera""", "category": "Point of Sale", # "live_test_url": "", "images": ["images/main.png"], - "version": "12.0.1.0.1", + "version": "12.0.2.0.0", "application": False, "author": "IT-Projects LLC, KolushovAlexandr", @@ -20,6 +23,7 @@ "external_dependencies": {"python": [], "bin": []}, "data": [ "views/assets.xml", + 'views/pos_config.xml', ], "qweb": [ "static/src/xml/templates.xml", diff --git a/pos_qr_scan/doc/changelog.rst b/pos_qr_scan/doc/changelog.rst index c5536123cd..862a3f0bef 100644 --- a/pos_qr_scan/doc/changelog.rst +++ b/pos_qr_scan/doc/changelog.rst @@ -1,3 +1,13 @@ +`2.0.0` +------- + +- **Improvement:** - Barcode scanner added + +`1.0.2` +------- + +- **Fix:** - Scanner didn't work due to "ReferenceError: gCtx is not defined" + `1.0.1` ------- diff --git a/pos_qr_scan/doc/index.rst b/pos_qr_scan/doc/index.rst index f63dd852e1..c44078aeb5 100644 --- a/pos_qr_scan/doc/index.rst +++ b/pos_qr_scan/doc/index.rst @@ -1,5 +1,5 @@ ========================= - QR Code Scanning in POS + POS QR/Barcode Scanning ========================= Installation @@ -10,7 +10,9 @@ Installation Configuration ============= -Browser can get access to camera only on using via ``https`` connection. +Browser may not give access to camera if using insecure ``http`` connection. + +Reference: https://www.w3.org/TR/secure-contexts/#threat-risks Possible NGINX configurations to support ``https``:: diff --git a/pos_qr_scan/models/__init__.py b/pos_qr_scan/models/__init__.py new file mode 100644 index 0000000000..ec2e5e609e --- /dev/null +++ b/pos_qr_scan/models/__init__.py @@ -0,0 +1,3 @@ +# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl.html) + +from . import pos_config diff --git a/pos_qr_scan/models/pos_config.py b/pos_qr_scan/models/pos_config.py new file mode 100644 index 0000000000..7a9738c64c --- /dev/null +++ b/pos_qr_scan/models/pos_config.py @@ -0,0 +1,21 @@ +# Copyright 2019 Kolushov Alexandr +# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl.html). + +from odoo import api, fields, models + + +class PosConfig(models.Model): + _inherit = 'pos.config' + + use_only_qr_scan = fields.Boolean('Only QR scanning') + use_only_barcode_scan = fields.Boolean('Only Barcode scanning') + + @api.onchange('use_only_qr_scan') + def _onchange_use_only_qr_scan(self): + if self.use_only_qr_scan: + self.use_only_barcode_scan = False + + @api.onchange('use_only_barcode_scan') + def _onchange_use_only_barcode_scan(self): + if self.use_only_barcode_scan: + self.use_only_qr_scan = False diff --git a/pos_qr_scan/static/lib/Quagga/quagga.min.js b/pos_qr_scan/static/lib/Quagga/quagga.min.js new file mode 100644 index 0000000000..f7a30f41b4 --- /dev/null +++ b/pos_qr_scan/static/lib/Quagga/quagga.min.js @@ -0,0 +1 @@ +!function(t,e){"object"==typeof exports&&"object"==typeof module?module.exports=e(e.toString()).default:"object"==typeof exports?exports.Quagga=e(e.toString()).default:t.Quagga=e(e.toString()).default}(this,function(t){return function(t){function e(r){if(n[r])return n[r].exports;var o=n[r]={i:r,l:!1,exports:{}};return t[r].call(o.exports,o,o.exports,e),o.l=!0,o.exports}var n={};return e.m=t,e.c=n,e.i=function(t){return t},e.d=function(t,n,r){e.o(t,n)||Object.defineProperty(t,n,{configurable:!1,enumerable:!0,get:r})},e.n=function(t){var n=t&&t.__esModule?function(){return t.default}:function(){return t};return e.d(n,"a",n),n},e.o=function(t,e){return Object.prototype.hasOwnProperty.call(t,e)},e.p="/",e(e.s=166)}([function(t,e){function n(t){var e=typeof t;return null!=t&&("object"==e||"function"==e)}t.exports=n},function(t,e,n){"use strict";function r(t,e){return this._row=[],this.config=t||{},this.supplements=e,this}var o=n(3);r.prototype._nextUnset=function(t,e){var n;for(void 0===e&&(e=0),n=e;nn)return Number.MAX_VALUE;u+=c}return u/f},r.prototype._nextSet=function(t,e){var n;for(e=e||0,n=e;n1&&(t[n[r]]=o)},r.prototype._matchTrace=function(t,e){var n,r,o=[],i=this,a=i._nextSet(i._row),u=!i._row[a],c=0,s={error:Number.MAX_VALUE,code:-1,start:0};if(t){for(n=0;n=0;r--)e=Math.floor(Math.random()*r),n=t[r],t[r]=t[e],t[e]=n;return t},toPointList:function(t){var e,n,r=[],o=[];for(e=0;e=e&&o.push(t[r]);return o},maxIndex:function(t){var e,n=0;for(e=0;et[n]&&(n=e);return n},max:function t(e){var n,t=0;for(n=0;nt&&(t=e[n]);return t},sum:function t(e){for(var n=e.length,t=0;n--;)t+=e[n];return t}}},function(t,e,n){"use strict";function r(t,e){t=a()(o(),t),u.a.call(this,t,e)}function o(){var t={};return Object.keys(r.CONFIG_KEYS).forEach(function(e){t[e]=r.CONFIG_KEYS[e].default}),t}var i=n(28),a=n.n(i),u=n(1),c=Object.assign||function(t){for(var e=1;ea.AVG_CODE_ERROR?null:f}s++,i[s]=1,c=!c}return null},r.prototype._findPattern=function(t,e,n,r,o){var i,a,u,c,s=[],f=this,l=0,d={error:Number.MAX_VALUE,code:-1,start:0,end:0};for(e||(e=f._nextSet(f._row)),void 0===n&&(n=!1),void 0===r&&(r=!0),void 0===o&&(o=f.AVG_CODE_ERROR),i=0;i=0&&n._matchRange(t,e.start,0))return e;r=e.end,e=null}},r.prototype._verifyTrailingWhitespace=function(t){var e,n=this;return e=t.end+(t.end-t.start),e=i.CODE_G_START?(t.code=t.code-i.CODE_G_START,a|=1<<5-r):a|=0<<5-r,e.push(t.code),n.push(t)}if(null===(o=i._calculateFirstDigit(a)))return null;if(e.unshift(o),null===(t=i._findPattern(i.MIDDLE_PATTERN,t.end,!0,!1)))return null;for(n.push(t),r=0;r<6;r++){if(!(t=i._decodeCode(t.end,i.CODE_G_START)))return null;n.push(t),e.push(t.code)}return t},r.prototype._decode=function(){var t,e,n=this,r=[],o=[],i={};if(!(t=n._findStart()))return null;if(e={code:t.code,start:t.start,end:t.end},o.push(e),!(e=n._decodePayload(e,r,o)))return null;if(!(e=n._findEnd(e.end,!1)))return null;if(o.push(e),!n._checksum(r))return null;if(this.supplements.length>0){var a=this._decodeExtensions(e.end);if(!a)return null;var u=a.decodedCodes[a.decodedCodes.length-1],s={start:u.start+((u.end-u.start)/2|0),end:u.end};if(!n._verifyTrailingWhitespace(s))return null;i={supplement:a,code:r.join("")+a.code}}return c({code:r.join(""),start:t.start,end:e.end,codeset:"",startInfo:t,decodedCodes:o},i)},r.prototype._decodeExtensions=function(t){var e,n,r=this._nextSet(this._row,t),o=this._findPattern(this.EXTENSION_START_PATTERN,r,!1,!1);if(null===o)return null;for(e=0;e=0;e-=2)n+=t[e];for(n*=3,e=t.length-1;e>=0;e-=2)n+=t[e];return n%10==0},r.CONFIG_KEYS={supplements:{type:"arrayOf(string)",default:[],description:"Allowed extensions to be decoded (2 and/or 5)"}},e.a=r},function(t,e,n){var r=n(38),o="object"==typeof self&&self&&self.Object===Object&&self,i=r||o||Function("return this")();t.exports=i},function(t,e){function n(t){return null!=t&&"object"==typeof t}t.exports=n},function(t,e){function n(t){var e=new Float32Array(2);return e[0]=t[0],e[1]=t[1],e}t.exports=n},function(t,e,n){function r(t){return null==t?void 0===t?c:u:s&&s in Object(t)?i(t):a(t)}var o=n(11),i=n(119),a=n(146),u="[object Null]",c="[object Undefined]",s=o?o.toStringTag:void 0;t.exports=r},function(t,e,n){"use strict";e.a={drawRect:function(t,e,n,r){n.strokeStyle=r.color,n.fillStyle=r.color,n.lineWidth=1,n.beginPath(),n.strokeRect(t.x,t.y,e.x,e.y)},drawPath:function(t,e,n,r){n.strokeStyle=r.color,n.fillStyle=r.color,n.lineWidth=r.lineWidth,n.beginPath(),n.moveTo(t[0][e.x],t[0][e.y]);for(var o=1;o-1&&t%1==0&&t0?Math.floor(this.x+.5):Math.floor(this.x-.5),this.y=this.y>0?Math.floor(this.y+.5):Math.floor(this.y-.5),this}}}function o(t,e,n){n||(n=t);for(var r=t.data,o=r.length,i=n.data;o--;)i[o]=r[o]>o]++;return a}function a(t,e){function n(t,e){var n,r=0;for(n=t;n<=e;n++)r+=a[n];return r}function r(t,e){var n,r=0;for(n=t;n<=e;n++)r+=n*a[n];return r}function o(){var o,u,c,s,f,l,d,h=[0],p=(1<c)for(i=s[u],i.score=o,i.item=t[r],c=Number.MAX_VALUE,a=0;ae[r]?r++:n++;return o}function _(t,e){function n(t){for(var e=0,n=t[Math.floor(t.length/2)];e0&&(n=Math.abs(t[e]-d)>Math.abs(t[e-1]-d)?t[e-1]:t[e]),d/nc[f-1]/c[f]?{x:n,y:n}:null}var r,o=p(e.x),i=p(e.y),a=Math.max(e.x,e.y),u=v(o,i),c=[8,10,15,20,32,60,80],s={"x-small":5,small:4,medium:3,large:2,"x-large":1},f=s[t]||s.medium,l=c[f],d=Math.floor(a/l);return r=n(u),r||(r=n(p(a)))||(r=n(p(d*l))),r}function g(t){return{value:parseFloat(t),unit:(t.indexOf("%"),t.length,"%")}}function y(t,e,n){var r={width:t,height:e},o=Object.keys(n).reduce(function(t,e){var o=n[e],i=g(o),a=C[e](i,r);return t[e]=a,t},{});return{sx:o.left,sy:o.top,sw:o.right-o.left,sh:o.bottom-o.top}}var m=n(50),x=n(3);e.b=r,e.f=u,e.g=c,e.h=s,e.c=f,e.d=l,e.i=d,e.a=h,e.e=_,e.j=y;var b={clone:n(7)},E={clone:n(83)},C={top:function(t,e){if("%"===t.unit)return Math.floor(e.height*(t.value/100))},right:function(t,e){if("%"===t.unit)return Math.floor(e.width-e.width*(t.value/100))},bottom:function(t,e){if("%"===t.unit)return Math.floor(e.height-e.height*(t.value/100))},left:function(t,e){if("%"===t.unit)return Math.floor(e.width*(t.value/100))}}},function(t,e,n){"use strict";function r(t,e,n,r){e?this.data=e:n?(this.data=new n(t.x*t.y),n===Array&&r&&a.a.init(this.data,0)):(this.data=new Uint8Array(t.x*t.y),Uint8Array===Array&&r&&a.a.init(this.data,0)),this.size=t}var o=n(53),i=n(19),a=n(3),u={clone:n(7)};r.prototype.inImageWithBorder=function(t,e){return t.x>=e&&t.y>=e&&t.x0&&(a=g[r-1],a.m00+=1,a.m01+=n,a.m10+=e,a.m11+=e*n,a.m02+=o,a.m20+=e*e);for(i=0;i=0?x:-x)+m,a.theta=(180*h/m+90)%180-90,a.theta<0&&(a.theta+=180),a.rad=h>m?h-m:h,a.vec=u.clone([Math.cos(h),Math.sin(h)]),y.push(a));return y},r.prototype.show=function(t,e){var n,r,o,i,a,u,c;for(e||(e=1),n=t.getContext("2d"),t.width=this.size.x,t.height=this.size.y,r=n.getImageData(0,0,t.width,t.height),o=r.data,i=0,c=0;c360)&&(e=360);for(var o=[0,1,1],a=[0,0,0],u=[255,255,255],c=[0,0,0],s=[],f=t.getContext("2d"),l=f.getImageData(r.x,r.y,this.size.x,this.size.y),d=l.data,h=this.data.length;h--;)o[0]=this.data[h]*e,s=o[0]<=0?u:o[0]>=360?c:n.i(i.a)(o,a),d[4*h+0]=s[0],d[4*h+1]=s[1],d[4*h+2]=s[2],d[4*h+3]=255;f.putImageData(l,r.x,r.y)},e.a=r},function(t,e,n){function r(t,e,n){"__proto__"==e&&o?o(t,e,{configurable:!0,enumerable:!0,value:n,writable:!0}):t[e]=n}var o=n(37);t.exports=r},function(t,e,n){function r(t,e){var n=i(t,e);return o(n)?n:void 0}var o=n(97),i=n(120);t.exports=r},function(t,e,n){function r(t){if("string"==typeof t||o(t))return t;var e=t+"";return"0"==e&&1/t==-i?"-0":e}var o=n(27),i=1/0;t.exports=r},function(t,e,n){function r(t){return null!=t&&i(t.length)&&!o(t)}var o=n(25),i=n(26);t.exports=r},function(t,e,n){function r(t){if(!i(t))return!1;var e=o(t);return e==u||e==c||e==a||e==s}var o=n(8),i=n(0),a="[object AsyncFunction]",u="[object Function]",c="[object GeneratorFunction]",s="[object Proxy]";t.exports=r},function(t,e){function n(t){return"number"==typeof t&&t>-1&&t%1==0&&t<=r}var r=9007199254740991;t.exports=n},function(t,e,n){function r(t){return"symbol"==typeof t||i(t)&&o(t)==a}var o=n(8),i=n(6),a="[object Symbol]";t.exports=r},function(t,e,n){var r=n(100),o=n(116),i=o(function(t,e,n){r(t,e,n)});t.exports=i},function(t,e){t.exports=function(t){return t.webpackPolyfill||(t.deprecate=function(){},t.paths=[],t.children||(t.children=[]),Object.defineProperty(t,"loaded",{enumerable:!0,get:function(){return t.l}}),Object.defineProperty(t,"id",{enumerable:!0,get:function(){return t.i}}),t.webpackPolyfill=1),t}},function(t,e,n){"use strict";var r={searchDirections:[[0,1],[1,1],[1,0],[1,-1],[0,-1],[-1,-1],[-1,0],[-1,1]],create:function(t,e){function n(t,e,n,r){var o,f,l;for(o=0;o<7;o++){if(f=t.cy+c[t.dir][0],l=t.cx+c[t.dir][1],i=f*s+l,a[i]===e&&(0===u[i]||u[i]===n))return u[i]=n,t.cy=f,t.cx=l,!0;0===u[i]&&(u[i]=r),t.dir=(t.dir+1)%8}return!1}function r(t,e,n){return{dir:n,x:t,y:e,next:null,prev:null}}function o(t,e,o,i,a){var u,c,s,f=null,l={cx:e,cy:t,dir:0};if(n(l,i,o,a)){f=r(e,t,l.dir),u=f,s=l.dir,c=r(l.cx,l.cy,0),c.prev=u,u.next=c,c.next=null,u=c;do l.dir=(l.dir+6)%8,n(l,i,o,a),s!==l.dir?(u.dir=l.dir,c=r(l.cx,l.cy,0),c.prev=u,u.next=c,c.next=null,u=c):(u.dir=s,u.x=l.cx,u.y=l.cy),s=l.dir;while(l.cx!==e||l.cy!==t);f.prev=u.prev,u.prev.next=f}return f}var i,a=t.data,u=e.data,c=this.searchDirections,s=t.size.x;return{trace:function(t,e,r,o){return n(t,e,r,o)},contourTracing:function(t,e,n,r,i){return o(t,e,n,r,i)}}}};e.a=r},function(t,e,n){"use strict";function r(){o.a.call(this)}var o=n(1),i=n(3),a={ALPHABETH_STRING:{value:"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ-. *$/+%"},ALPHABET:{value:[48,49,50,51,52,53,54,55,56,57,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,45,46,32,42,36,47,43,37]},CHARACTER_ENCODINGS:{value:[52,289,97,352,49,304,112,37,292,100,265,73,328,25,280,88,13,268,76,28,259,67,322,19,274,82,7,262,70,22,385,193,448,145,400,208,133,388,196,148,168,162,138,42]},ASTERISK:{value:148},FORMAT:{value:"code_39",writeable:!1}};r.prototype=Object.create(o.a.prototype,a),r.prototype.constructor=r,r.prototype._decode=function(){var t,e,n,r,o=this,a=[0,0,0,0,0,0,0,0,0],u=[],c=o._findStart();if(!c)return null;r=o._nextSet(o._row,c.end);do{if(a=o._toCounters(r,a),(n=o._toPattern(a))<0)return null;if((t=o._patternToChar(n))<0)return null;u.push(t),e=r,r+=i.a.sum(a),r=o._nextSet(o._row,r)}while("*"!==t);return u.pop(),u.length&&o._verifyTrailingWhitespace(e,r,a)?{code:u.join(""),start:c.start,end:r,startInfo:c,decodedCodes:u}:null},r.prototype._verifyTrailingWhitespace=function(t,e,n){var r=i.a.sum(n);return 3*(e-t-r)>=r},r.prototype._patternToChar=function(t){var e,n=this;for(e=0;ee&&(r=t[n]);return r},r.prototype._toPattern=function(t){for(var e,n,r=t.length,o=0,i=r,a=0,u=this;i>3;){for(o=u._findNextWidth(t,o),i=0,e=0,n=0;no&&(e|=1<0;n++)if(t[n]>o&&(i--,2*t[n]>=a))return-1;return e}}return-1},r.prototype._findStart=function(){var t,e,n,r=this,o=r._nextSet(r._row),i=o,a=[0,0,0,0,0,0,0,0,0],u=0,c=!1;for(t=o;t0)for(r=0;r0){if(!(t=Y.filter(function(t){return!t.busy})[0]))return;w.attachData(t.imageData)}else w.attachData(S.data);w.grab()&&(t?(t.busy=!0,t.worker.postMessage({cmd:"process",imageData:t.imageData},[t.imageData.buffer])):_())}else _()}function y(){var t=null,e=1e3/($.frequency||60);T=!1,function n(r){t=t||r,T||(r>=t&&(t+=e,g()),window.requestAnimFrame(n))}(performance.now())}function m(){Q&&"LiveStream"===$.inputStream.type?y():g()}function x(t){var e,n={worker:void 0,imageData:new Uint8Array(R.getWidth()*R.getHeight()),busy:!0};e=C(),n.worker=new Worker(e),n.worker.onmessage=function(r){if("initialized"===r.data.event)return URL.revokeObjectURL(e),n.busy=!1,n.imageData=new Uint8Array(r.data.imageData),t(n);"processed"===r.data.event?(n.imageData=new Uint8Array(r.data.imageData),n.busy=!1,v(r.data.result,n.imageData)):r.data.event},n.worker.postMessage({cmd:"init",size:{x:R.getWidth(),y:R.getHeight()},imageData:n.imageData,config:b($)},[n.imageData.buffer])}function b(t){return X({},t,{inputStream:X({},t.inputStream,{target:null})})}function E(t){function e(t){self.postMessage({event:"processed",imageData:o.data,result:t},[o.data.buffer])}function n(){self.postMessage({event:"initialized",imageData:o.data},[o.data.buffer])}if(t){var r=t().default;if(!r)return void self.postMessage({event:"error",message:"Quagga could not be created"})}var o;self.onmessage=function(t){if("init"===t.data.cmd){var i=t.data.config;i.numOfWorkers=0,o=new r.ImageWrapper({x:t.data.size.x,y:t.data.size.y},new Uint8Array(t.data.imageData)),r.init(i,n,o),r.onProcessed(e)}else"process"===t.data.cmd?(o.data=new Uint8Array(t.data.imageData),r.start()):"setReaders"===t.data.cmd&&r.setReaders(t.data.readers)}}function C(){var e,n;return void 0!==t&&(n=t),e=new Blob(["("+E.toString()+")("+n+");"],{type:"text/javascript"}),window.URL.createObjectURL(e)}function O(t){P?P.setReaders(t):Q&&Y.length>0&&Y.forEach(function(e){e.worker.postMessage({cmd:"setReaders",readers:t})})}function A(t,e){var n=t-Y.length;if(0===n)return e&&e();if(n<0){return Y.slice(n).forEach(function(t){t.worker.terminate()}),Y=Y.slice(0,n),e&&e()}for(var r=function(n){Y.push(n),Y.length>=t&&e&&e()},o=0;oe},getPoints:function(){return a},getCenter:function(){return u}}},createPoint:function(t,e,n){return{rad:t[n],point:t,id:e}}}},function(t,e,n){"use strict";e.a=function(){function t(t){return o[t]||(o[t]={subscribers:[]}),o[t]}function e(){o={}}function n(t,e){t.async?setTimeout(function(){t.callback(e)},4):t.callback(e)}function r(e,n,r){var o;if("function"==typeof n)o={callback:n,async:r};else if(o=n,!o.callback)throw"Callback was not specified on options";t(e).subscribers.push(o)}var o={};return{subscribe:function(t,e,n){return r(t,e,n)},publish:function(e,r){var o=t(e),i=o.subscribers;i.filter(function(t){return!!t.once}).forEach(function(t){n(t,r)}),o.subscribers=i.filter(function(t){return!t.once}),o.subscribers.forEach(function(t){n(t,r)})},once:function(t,e,n){r(t,{callback:e,async:n,once:!0})},unsubscribe:function(n,r){var o;n?(o=t(n),o.subscribers=o&&r?o.subscribers.filter(function(t){return t.callback!==r}):[]):e()}}}()},function(t,e,n){"use strict";function r(){return navigator.mediaDevices&&"function"==typeof navigator.mediaDevices.enumerateDevices?navigator.mediaDevices.enumerateDevices():Promise.reject(new Error("enumerateDevices is not defined"))}function o(t){return navigator.mediaDevices&&"function"==typeof navigator.mediaDevices.getUserMedia?navigator.mediaDevices.getUserMedia(t):Promise.reject(new Error("getUserMedia is not defined"))}e.b=r,e.a=o},function(t,e,n){"use strict";function r(t,e,n){n||(n={data:null,size:e}),this.data=n.data,this.originalSize=n.size,this.I=n,this.from=t,this.size=e}r.prototype.show=function(t,e){var n,r,o,i,a,u,c;for(e||(e=1),n=t.getContext("2d"),t.width=this.size.x,t.height=this.size.y,r=n.getImageData(0,0,t.width,t.height),o=r.data,i=0,a=0;a>>16&65535,r=65535&t,o=e>>>16&65535,i=65535&e;return r*i+(n*i+r*o<<16>>>0)|0},"function"!=typeof Object.assign&&(Object.assign=function(t){"use strict";if(null===t)throw new TypeError("Cannot convert undefined or null to object");for(var e=Object(t),n=1;n1&&(!e.inImageWithBorder(t[0],0)||!e.inImageWithBorder(t[1],0));)r-=Math.ceil(r/2),o(-r);return t}function u(t){return[{x:(t[1][0]-t[0][0])/2+t[0][0],y:(t[1][1]-t[0][1])/2+t[0][1]},{x:(t[3][0]-t[2][0])/2+t[2][0],y:(t[3][1]-t[2][1])/2+t[2][1]}]}function c(t){var n,o=null,i=r.a.getBarcodeLine(e,t[0],t[1]);for(r.a.toBinaryLine(i),n=0;nE?l:E,g.push(l)}var o,i,a,u,c,s,f,l,d=0|e.x,h=0|e.y,p=0|n.x,v=0|n.y,_=Math.abs(v-h)>Math.abs(p-d),g=[],y=t.data,m=t.size.x,x=0,b=255,E=0;for(_&&(s=d,d=h,h=s,s=p,p=v,v=s),d>p&&(s=d,d=p,p=s,s=h,h=v,v=s),o=p-d,i=Math.abs(v-h),a=o/2|0,c=h,u=hl?o.DIR.UP:o.DIR.DOWN,d.push({pos:0,val:f[0]}),a=0;ah&&f[a+1]>.5*l?o.DIR.UP:r,r!==i&&(d.push({pos:a,val:f[a]}),r=i);for(d.push({pos:f.length,val:f[f.length-1]}),u=d[0].pos;ul?0:1;for(a=1;ad[a].val?d[a].val+(d[a+1].val-d[a].val)/3*2|0:d[a+1].val+(d[a].val-d[a+1].val)/3|0,u=d[a].pos;uh?0:1;return{line:f,threshold:h}},r.debug={printFrequency:function(t,e){var n,r=e.getContext("2d");for(e.width=t.length,e.height=256,r.beginPath(),r.strokeStyle="blue",n=0;n0?t.videoWidth>10&&t.videoHeight>10?e():window.setTimeout(r,500):n("Unable to play video stream. Is webcam working?"),o--}var o=10;r()})}function o(t,e){return n.i(d.a)(e).then(function(e){return new Promise(function(n){s=e,t.setAttribute("autoplay",!0),t.setAttribute("muted",!0),t.setAttribute("playsinline",!0),t.srcObject=e,t.addEventListener("loadedmetadata",function(){t.play(),n()})})}).then(r.bind(null,t))}function i(t){var e=l()(t,["width","height","facingMode","aspectRatio","deviceId"]);return void 0!==t.minAspectRatio&&t.minAspectRatio>0&&(e.aspectRatio=t.minAspectRatio,console.log("WARNING: Constraint 'minAspectRatio' is deprecated; Use 'aspectRatio' instead")),void 0!==t.facing&&(e.facingMode=t.facing,console.log("WARNING: Constraint 'facing' is deprecated. Use 'facingMode' instead'")),e}function a(t){var e={audio:!1,video:i(t)};return e.video.deviceId&&e.video.facingMode&&delete e.video.facingMode,Promise.resolve(e)}function u(){return n.i(d.b)().then(function(t){return t.filter(function(t){return"videoinput"===t.kind})})}function c(){if(s){var t=s.getVideoTracks();if(t&&t.length)return t[0]}}var s,f=n(162),l=n.n(f),d=n(52);e.a={request:function(t,e){return a(e).then(o.bind(null,t))},release:function(){var t=s&&s.getVideoTracks();t&&t.length&&t[0].stop(),s=null},enumerateVideoDevices:u,getActiveStreamLabel:function(){var t=c();return t?t.label:""},getActiveTrack:c}},function(t,e,n){"use strict";function r(t){var e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:d;return/^blob\:/i.test(t)?i(t).then(o).then(function(t){return a(t,e)}):Promise.resolve(null)}function o(t){return new Promise(function(e){var n=new FileReader;n.onload=function(t){return e(t.target.result)},n.readAsArrayBuffer(t)})}function i(t){return new Promise(function(e,n){var r=new XMLHttpRequest;r.open("GET",t,!0),r.responseType="blob",r.onreadystatechange=function(){r.readyState!==XMLHttpRequest.DONE||200!==r.status&&0!==r.status||e(this.response)},r.onerror=n,r.send()})}function a(t){var e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:d,n=new DataView(t),r=t.byteLength,o=e.reduce(function(t,e){var n=Object.keys(l).filter(function(t){return l[t]===e})[0];return n&&(t[n]=e),t},{}),i=2;if(255!==n.getUint8(0)||216!==n.getUint8(1))return!1;for(;i1?i.size:Math.floor(e/o*i.size):e,r=i.size?e/o>1?Math.floor(o/e*i.size):i.size:o,s.x=n,s.y=r}var n,r,o={},i=null,a=["canrecord","ended"],u={},c={x:0,y:0},s={x:0,y:0};return o.getRealWidth=function(){return t.videoWidth},o.getRealHeight=function(){return t.videoHeight},o.getWidth=function(){return n},o.getHeight=function(){return r},o.setWidth=function(t){n=t},o.setHeight=function(t){r=t},o.setInputStream=function(e){i=e,t.src=void 0!==e.src?e.src:""},o.ended=function(){return t.ended},o.getConfig=function(){return i},o.setAttribute=function(e,n){t.setAttribute(e,n)},o.pause=function(){t.pause()},o.play=function(){t.play()},o.setCurrentTime=function(e){"LiveStream"!==i.type&&(t.currentTime=e)},o.addEventListener=function(e,n,r){a.indexOf(e)!==-1?(u[e]||(u[e]=[]),u[e].push(n)):t.addEventListener(e,n,r)},o.clearEventHandlers=function(){a.forEach(function(e){var n=u[e];n&&n.length>0&&n.forEach(function(n){t.removeEventListener(e,n)})})},o.trigger=function(t,n){var r,i=u[t];if("canrecord"===t&&e(),i&&i.length>0)for(r=0;r1?a.size:Math.floor(u/c*a.size):u,o=a.size?u/c>1?Math.floor(c/u*a.size):a.size:c,x.x=n,x.y=o,l=!0,s=0,setTimeout(function(){e("canrecord",[])},0)},p,h,a.sequence)}function e(t,e){var n,r=y[t];if(r&&r.length>0)for(n=0;nf&&(f=o.box[r][0]),o.box[r][1]l&&(l=o.box[r][1]);for(a=[[c,s],[f,s],[f,l],[c,l]],u=p.halfSample?2:1,i=M.invert(i,i),r=0;r<4;r++)I.transformMat2(a[r],a[r],i);for(r=0;r<4;r++)I.scale(a[r],a[r],u);return a}function a(){n.i(w.f)(v,E),E.zeroBorder()}function u(){var t,e,n,r,o,i,a,u=[];for(t=0;t0&&r[x.data[n]-1]++;return r=r.map(function(t,e){return{val:t,label:e+1}}),r.sort(function(t,e){return e.val-t.val}),r.filter(function(t){return t.val>=5})}function s(t,e){var n,r,o,a,u=[],c=[];for(n=0;n=2){for(o=0;ol&&c.push(t[o]);if(c.length>=2){for(a=f(c),i=0,o=0;o1&&a.length>=c.length/4*3&&a.length>t.length/4&&(i/=a.length,u={index:e[1]*z.x+e[0],pos:{x:n,y:r},box:[I.clone([n,r]),I.clone([n+g.size.x,r]),I.clone([n+g.size.x,r+g.size.y]),I.clone([n,r+g.size.y])],moments:a,rad:i,vec:I.clone([Math.cos(i),Math.sin(i)])},s.push(u))}}return s}function h(t){function e(){var t;for(t=0;ta&&n(u):x.data[u]=Number.MAX_VALUE}var r,o,i=0,a=.95,u=0;for(T.a.init(m.data,0),T.a.init(x.data,0),T.a.init(b.data,null),r=0;r0) {length=length - 1|0;images[outImagePtr+length|0]=(images[aImagePtr+length|0]|0) - (images[bImagePtr+length|0]|0)|0;}}function bitwiseOr(aImagePtr, bImagePtr, outImagePtr) {aImagePtr=aImagePtr|0;bImagePtr=bImagePtr|0;outImagePtr=outImagePtr|0;var length=0;length=imul(size, size)|0;while ((length|0)>0) {length=length - 1|0;images[outImagePtr+length|0]=images[aImagePtr+length|0]|0|(images[bImagePtr+length|0]|0)|0;}}function countNonZero(imagePtr) {imagePtr=imagePtr|0;var sum=0,length=0;length=imul(size, size)|0;while ((length|0)>0) {length=length - 1|0;sum=(sum|0)+(images[imagePtr+length|0]|0)|0;}return sum|0;}function init(imagePtr, value) {imagePtr=imagePtr|0;value=value|0;var length=0;length=imul(size, size)|0;while ((length|0)>0) {length=length - 1|0;images[imagePtr+length|0]=value;}}function dilate(inImagePtr, outImagePtr) {inImagePtr=inImagePtr|0;outImagePtr=outImagePtr|0;var v=0,u=0,sum=0,yStart1=0,yStart2=0,xStart1=0,xStart2=0,offset=0;for (v=1; (v|0)<(size - 1|0); v=v+1|0) {offset=offset+size|0;for (u=1; (u|0)<(size - 1|0); u=u+1|0) {yStart1=offset - size|0;yStart2=offset+size|0;xStart1=u - 1|0;xStart2=u+1|0;sum=(images[inImagePtr+yStart1+xStart1|0]|0)+(images[inImagePtr+yStart1+xStart2|0]|0)+(images[inImagePtr+offset+u|0]|0)+(images[inImagePtr+yStart2+xStart1|0]|0)+(images[inImagePtr+yStart2+xStart2|0]|0)|0;if ((sum|0)>(0|0)) {images[outImagePtr+offset+u|0]=1;} else {images[outImagePtr+offset+u|0]=0;}}}return;}function memcpy(srcImagePtr, dstImagePtr) {srcImagePtr=srcImagePtr|0;dstImagePtr=dstImagePtr|0;var length=0;length=imul(size, size)|0;while ((length|0)>0) {length=length - 1|0;images[dstImagePtr+length|0]=images[srcImagePtr+length|0]|0;}}function zeroBorder(imagePtr) {imagePtr=imagePtr|0;var x=0,y=0;for (x=0; (x|0)<(size - 1|0); x=x+1|0) {images[imagePtr+x|0]=0;images[imagePtr+y|0]=0;y=y+size - 1|0;images[imagePtr+y|0]=0;y=y+1|0;}for (x=0; (x|0)<(size|0); x=x+1|0) {images[imagePtr+y|0]=0;y=y+1|0;}}function skeletonize() {var subImagePtr=0,erodedImagePtr=0,tempImagePtr=0,skelImagePtr=0,sum=0,done=0;erodedImagePtr=imul(size, size)|0;tempImagePtr=erodedImagePtr+erodedImagePtr|0;skelImagePtr=tempImagePtr+erodedImagePtr|0;init(skelImagePtr, 0);zeroBorder(subImagePtr);do {erode(subImagePtr, erodedImagePtr);dilate(erodedImagePtr, tempImagePtr);subtract(subImagePtr, tempImagePtr, tempImagePtr);bitwiseOr(skelImagePtr, tempImagePtr, skelImagePtr);memcpy(erodedImagePtr, subImagePtr);sum=countNonZero(subImagePtr)|0;done=(sum|0) == 0|0;} while (!done);}return {skeletonize: skeletonize};} __webpack_exports__["a"]=Skeletonizer; },function(t,e,n){"use strict";function r(t){o.a.call(this,t),this.barSpaceRatio=[1,1]}var o=n(1),i=1,a=3,u={START_PATTERN:{value:[a,i,a,i,i,i]},STOP_PATTERN:{value:[a,i,i,i,a]},CODE_PATTERN:{value:[[i,i,a,a,i],[a,i,i,i,a],[i,a,i,i,a],[a,a,i,i,i],[i,i,a,i,a],[a,i,a,i,i],[i,a,a,i,i],[i,i,i,a,a],[a,i,i,a,i],[i,a,i,a,i]]},SINGLE_CODE_ERROR:{value:.78,writable:!0},AVG_CODE_ERROR:{value:.3,writable:!0},FORMAT:{value:"2of5"}},c=u.START_PATTERN.value.reduce(function(t,e){return t+e},0);r.prototype=Object.create(o.a.prototype,u),r.prototype.constructor=r,r.prototype._findPattern=function(t,e,n,r){var o,i,a,u,c=[],s=this,f=0,l={error:Number.MAX_VALUE,code:-1,start:0,end:0},d=s.AVG_CODE_ERROR;for(n=n||!1,r=r||!1,e||(e=s._nextSet(s._row)),o=0;o=0&&n._matchRange(t,e.start,0))return e;r=e.end,e=null}},r.prototype._verifyTrailingWhitespace=function(t){var e,n=this;return e=t.end+(t.end-t.start)/2,e1&&i._isStartEnd(n))break}while(ri._counters.length?i._counters.length:r,o=t.start+i._sumCounters(t.startCounter,r-8),{code:a.join(""),start:t.start,end:o,startInfo:t,decodedCodes:a}):null},r.prototype._verifyWhitespace=function(t,e){return(t-1<=0||this._counters[t-1]>=this._calculatePatternLength(t)/2)&&(e+8>=this._counters.length||this._counters[e+7]>=this._calculatePatternLength(e)/2)},r.prototype._calculatePatternLength=function(t){var e,n=0;for(e=t;e=0;i--)n=2==(1&i)?c.bar:c.space,r=1==(1&a)?n.wide:n.narrow,r.size+=u._counters[s+i],r.counts++,a>>=1;s+=8}return["space","bar"].forEach(function(t){var e=c[t];e.wide.min=Math.floor((e.narrow.size/e.narrow.counts+e.wide.size/e.wide.counts)/2),e.narrow.max=Math.ceil(e.wide.min),e.wide.max=Math.ceil((e.wide.size*u.MAX_ACCEPTABLE+u.PADDING)/e.wide.counts)}),c},r.prototype._charToPattern=function(t){var e,n=this,r=t.charCodeAt(0);for(e=0;e=0;r--){if(o=0==(1&r)?s.bar:s.space,i=1==(1&u)?o.wide:o.narrow,(a=c._counters[f+r])i.max)return!1;u>>=1}f+=8}return!0},r.prototype._patternToChar=function(t){var e,n=this;for(e=0;ei&&(i=r),rthis._counters.length)return-1;for(e=this._computeAlternatingThreshold(t,a),n=this._computeAlternatingThreshold(t+1,a),r=0;ro&&(c|=u),u>>=1;return c},r.prototype._isStartEnd=function(t){var e;for(e=0;eu.AVG_CODE_ERROR?null:(u.CODE_PATTERN[l.code]&&(l.correction.bar=o(u.CODE_PATTERN[l.code],a,this.MODULE_INDICES.bar),l.correction.space=o(u.CODE_PATTERN[l.code],a,this.MODULE_INDICES.space)),l)}f++,a[f]=1,s=!s}return null},r.prototype._correct=function(t,e){this._correctBars(t,e.bar,this.MODULE_INDICES.bar),this._correctBars(t,e.space,this.MODULE_INDICES.space)},r.prototype._findStart=function(){var t,e,n,r,i,a=[0,0,0,0,0,0],u=this,c=u._nextSet(u._row),s=!1,f=0,l={error:Number.MAX_VALUE,code:-1,start:0,end:0,correction:{bar:1,space:1}};for(t=c;t4)return-1;if(0==(1&i))for(var u=0;u="a"&&o<="d"){if(r>e-2)return null;var i=t[++r],a=i.charCodeAt(0),u=void 0;switch(o){case"a":if(!(i>="A"&&i<="Z"))return null;u=String.fromCharCode(a-64);break;case"b":if(i>="A"&&i<="E")u=String.fromCharCode(a-38);else if(i>="F"&&i<="J")u=String.fromCharCode(a-11);else if(i>="K"&&i<="O")u=String.fromCharCode(a+16);else if(i>="P"&&i<="S")u=String.fromCharCode(a+43);else{if(!(i>="T"&&i<="Z"))return null;u=String.fromCharCode(127)}break;case"c":if(i>="A"&&i<="O")u=String.fromCharCode(a-32);else{if("Z"!==i)return null;u=":"}break;case"d":if(!(i>="A"&&i<="Z"))return null;u=String.fromCharCode(a+32)}n.push(u)}else n.push(o)}return n},r.prototype._verifyChecksums=function(t){return this._matchCheckChar(t,t.length-2,20)&&this._matchCheckChar(t,t.length-1,15)},r.prototype._matchCheckChar=function(t,e,n){var r=this,o=t.slice(0,e),i=o.length,a=o.reduce(function(t,e,o){return t+((o*-1+(i-1))%n+1)*r.ALPHABET.indexOf(e.charCodeAt(0))},0);return this.ALPHABET[a%47]===t[e].charCodeAt(0)},e.a=r},function(t,e,n){"use strict";function r(){o.a.call(this)}var o=n(4),i={FORMAT:{value:"ean_2",writeable:!1}};r.prototype=Object.create(o.a.prototype,i),r.prototype.constructor=r,r.prototype.decode=function(t,e){this._row=t;var n,r=0,o=0,i=e,a=this._row.length,u=[],c=[];for(o=0;o<2&&i=this.CODE_G_START&&(r|=1<<1-o),1!=o&&(i=this._nextSet(this._row,n.end),i=this._nextUnset(this._row,i))}return 2!=u.length||parseInt(u.join(""))%4!==r?null:{code:u.join(""),decodedCodes:c,end:n.end}},e.a=r},function(t,e,n){"use strict";function r(){a.a.call(this)}function o(t){var e;for(e=0;e<10;e++)if(t===c[e])return e;return null}function i(t){var e,n=t.length,r=0;for(e=n-2;e>=0;e-=2)r+=t[e];for(r*=3,e=n-1;e>=0;e-=2)r+=t[e];return(r*=3)%10}var a=n(4),u={FORMAT:{value:"ean_5",writeable:!1}},c=[24,20,18,17,12,6,3,10,9,5];r.prototype=Object.create(a.a.prototype,u),r.prototype.constructor=r,r.prototype.decode=function(t,e){this._row=t;var n,r=0,a=0,u=e,c=this._row.length,s=[],f=[];for(a=0;a<5&&u=this.CODE_G_START&&(r|=1<<4-a),4!=a&&(u=this._nextSet(this._row,n.end),u=this._nextUnset(this._row,u))}return 5!=s.length?null:i(s)!==o(r)?null:{code:s.join(""),decodedCodes:f,end:n.end}},e.a=r},function(t,e,n){"use strict";function r(t,e){o.a.call(this,t,e)}var o=n(4),i={FORMAT:{value:"ean_8",writeable:!1}};r.prototype=Object.create(o.a.prototype,i),r.prototype.constructor=r,r.prototype._decodePayload=function(t,e,n){var r,o=this;for(r=0;r<4;r++){if(!(t=o._decodeCode(t.end,o.CODE_G_START)))return null;e.push(t.code),n.push(t)}if(null===(t=o._findPattern(o.MIDDLE_PATTERN,t.end,!0,!1)))return null;for(n.push(t),r=0;r<4;r++){if(!(t=o._decodeCode(t.end,o.CODE_G_START)))return null;n.push(t),e.push(t.code)}return t},e.a=r},function(t,e,n){"use strict";function r(t){t=a()(o(),t),u.a.call(this,t),this.barSpaceRatio=[1,1],t.normalizeBarSpaceWidth&&(this.SINGLE_CODE_ERROR=.38,this.AVG_CODE_ERROR=.09)}function o(){var t={};return Object.keys(r.CONFIG_KEYS).forEach(function(e){t[e]=r.CONFIG_KEYS[e].default}),t}var i=n(28),a=n.n(i),u=n(1),c=1,s=3,f={START_PATTERN:{value:[c,c,c,c]},STOP_PATTERN:{value:[c,c,s]},CODE_PATTERN:{value:[[c,c,s,s,c],[s,c,c,c,s],[c,s,c,c,s],[s,s,c,c,c],[c,c,s,c,s],[s,c,s,c,c],[c,s,s,c,c],[c,c,c,s,s],[s,c,c,s,c],[c,s,c,s,c]]},SINGLE_CODE_ERROR:{value:.78,writable:!0},AVG_CODE_ERROR:{value:.38,writable:!0},MAX_CORRECTION_FACTOR:{value:5},FORMAT:{value:"i2of5"}};r.prototype=Object.create(u.a.prototype,f),r.prototype.constructor=r,r.prototype._matchPattern=function(t,e){if(this.config.normalizeBarSpaceWidth){var n,r=[0,0],o=[0,0],i=[0,0],a=this.MAX_CORRECTION_FACTOR,c=1/a;for(n=0;n=0&&n._matchRange(t,e.start,0))return e;r=e.end,e=null}},r.prototype._verifyTrailingWhitespace=function(t){var e,n=this;return e=t.end+(t.end-t.start)/2,e=o.CODE_G_START&&(t.code=t.code-o.CODE_G_START,i|=1<<5-r),e.push(t.code),n.push(t)}return o._determineParity(i,e)?t:null},r.prototype._determineParity=function(t,e){var n,r;for(r=0;r0&&n(f)?e>1?r(f,e-1,n,a,u):o(u,f):a||(u[u.length]=f)}return u}var o=n(90),i=n(128);t.exports=r},function(t,e,n){var r=n(117),o=r();t.exports=o},function(t,e,n){function r(t,e){e=o(e,t);for(var n=0,r=e.length;null!=t&&n1?n[o-1]:void 0,u=o>2?n[2]:void 0;for(a=t.length>3&&"function"==typeof a?(o--,a):void 0,u&&i(n[0],n[1],u)&&(a=o<3?void 0:a,o=1),e=Object(e);++r-1}var o=n(12);t.exports=r},function(t,e,n){function r(t,e){var n=this.__data__,r=o(n,t);return r<0?(++this.size,n.push([t,e])):n[r][1]=e,this}var o=n(12);t.exports=r},function(t,e,n){function r(){this.size=0,this.__data__={hash:new o,map:new(a||i),string:new o}}var o=n(84),i=n(10),a=n(33);t.exports=r},function(t,e,n){function r(t){var e=o(this,t).delete(t);return this.size-=e?1:0,e}var o=n(14);t.exports=r},function(t,e,n){function r(t){return o(this,t).get(t)}var o=n(14);t.exports=r},function(t,e,n){function r(t){return o(this,t).has(t)}var o=n(14);t.exports=r},function(t,e,n){function r(t,e){var n=o(this,t),r=n.size;return n.set(t,e),this.size+=n.size==r?0:1,this}var o=n(14);t.exports=r},function(t,e,n){function r(t){var e=o(t,function(t){return n.size===i&&n.clear(),t}),n=e.cache;return e}var o=n(161),i=500;t.exports=r},function(t,e){function n(t){var e=[];if(null!=t)for(var n in Object(t))e.push(n);return e}t.exports=n},function(t,e,n){(function(t){var r=n(38),o="object"==typeof e&&e&&!e.nodeType&&e,i=o&&"object"==typeof t&&t&&!t.nodeType&&t,a=i&&i.exports===o,u=a&&r.process,c=function(){try{return u&&u.binding&&u.binding("util")}catch(t){}}();t.exports=c}).call(e,n(29)(t))},function(t,e){function n(t){return o.call(t)}var r=Object.prototype,o=r.toString;t.exports=n},function(t,e){function n(t,e){return function(n){return t(e(n))}}t.exports=n},function(t,e){function n(t){var e=0,n=0;return function(){var a=i(),u=o-(a-n);if(n=a,u>0){if(++e>=r)return arguments[0]}else e=0;return t.apply(void 0,arguments)}}var r=800,o=16,i=Date.now;t.exports=n},function(t,e,n){function r(){this.__data__=new o,this.size=0}var o=n(10);t.exports=r},function(t,e){function n(t){var e=this.__data__,n=e.delete(t);return this.size=e.size,n}t.exports=n},function(t,e){function n(t){return this.__data__.get(t)}t.exports=n},function(t,e){function n(t){return this.__data__.has(t)}t.exports=n},function(t,e,n){function r(t,e){var n=this.__data__;if(n instanceof o){var r=n.__data__;if(!i||r.length config.threshold) { + binary.push(1); + } else { + binary.push(0); + } + } + + // determine bar widths + + var current = binary[0]; + var count = 0; + + for (var i = 0, ii = binary.length; i < ii; i++) { + if (binary[i] == current) { + count++; + } else { + pixelBars.push(count); + count = 1; + current = binary[i] + } + } + pixelBars.push(count); + + // quality check + + if (pixelBars.length < (3 + 24 + 5 + 24 + 3 + 1)) { + return; + } + + // find starting sequence + + var startIndex = 0; + var minFactor = 0.5; + var maxFactor = 1.5; + + for (var i = 3, ii = pixelBars.length; i < ii; i++) { + var refLength = (pixelBars[i] + pixelBars[i-1] + pixelBars[i-2]) / 3; + if ( + (pixelBars[i] > (minFactor * refLength) || pixelBars[i] < (maxFactor * refLength)) + && (pixelBars[i-1] > (minFactor * refLength) || pixelBars[i-1] < (maxFactor * refLength)) + && (pixelBars[i-2] > (minFactor * refLength) || pixelBars[i-2] < (maxFactor * refLength)) + && (pixelBars[i-3] > 3 * refLength) + ) { + startIndex = i - 2; + break; + } + } + + console.log("startIndex: " + startIndex ); + + // return if no starting sequence found + + if (startIndex == 0) { + return; + } + + // discard leading and trailing patterns + + pixelBars = pixelBars.slice(startIndex, startIndex + 3 + 24 + 5 + 24 + 3); + + console.log("pixelBars: " + pixelBars ); + + // calculate relative widths + + var ref = (pixelBars[0] + pixelBars[1] + pixelBars[2]) / 3; + + for (var i = 0, ii = pixelBars.length; i < ii; i++) { + bars.push(Math.round(pixelBars[i] / ref * 100) / 100); + } + + // analyze pattern + + analyze(); + + } + + function analyze() { + + console.clear(); + + console.log("analyzing"); + + // determine parity first digit and reverse sequence if necessary + + var first = normalize(bars.slice(3, 3 + 4), 7); + if (!isOdd(Math.round(first[1] + first[3]))) { + bars = bars.reverse(); + } + + // split into digits + + var digits = [ + normalize(bars.slice(3, 3 + 4), 7), + normalize(bars.slice(7, 7 + 4), 7), + normalize(bars.slice(11, 11 + 4), 7), + normalize(bars.slice(15, 15 + 4), 7), + normalize(bars.slice(19, 19 + 4), 7), + normalize(bars.slice(23, 23 + 4), 7), + normalize(bars.slice(32, 32 + 4), 7), + normalize(bars.slice(36, 36 + 4), 7), + normalize(bars.slice(40, 40 + 4), 7), + normalize(bars.slice(44, 44 + 4), 7), + normalize(bars.slice(48, 48 + 4), 7), + normalize(bars.slice(52, 52 + 4), 7) + ] + + console.log("digits: " + digits); + + // determine parity and reverse if necessary + + var parities = []; + + for (var i = 0; i < 6; i++) { + if (parity(digits[i])) { + parities.push('o'); + } else { + parities.push('e'); + digits[i] = digits[i].reverse(); + } + } + + // identify digits + + var result = []; + var quality = 0; + + for (var i = 0, ii = digits.length; i < ii; i++) { + + var distance = 9; + var bestKey = ''; + + for (key in upc) { + if (maxDistance(digits[i], upc[key]) < distance) { + distance = maxDistance(digits[i], upc[key]); + bestKey = key; + } + } + + result.push(bestKey); + if (distance > quality) { + quality = distance; + } + + } + + console.log("result: " + result); + + // check digit + + var checkDigit = check[parities.join('')]; + + // output + + console.log("quality: " + quality); + + if(quality < config.quality) { + if (handler != null) { + handler(checkDigit + result.join('')); + } + } + + } + + function setHandler(h) { + handler = h; + } + + function normalize(input, total) { + var sum = 0; + var result = []; + for (var i = 0, ii = input.length; i < ii; i++) { + sum = sum + input[i]; + } + for (var i = 0, ii = input.length; i < ii; i++) { + result.push(input[i] / sum * total); + } + return result; + } + + function isOdd(num) { + return num % 2; + } + + function maxDistance(a, b) { + var distance = 0; + for (var i = 0, ii = a.length; i < ii; i++) { + if (Math.abs(a[i] - b[i]) > distance) { + distance = Math.abs(a[i] - b[i]); + } + } + return distance; + } + + function parity(digit) { + return isOdd(Math.round(digit[1] + digit[3])); + } + + function drawGraphics() { + elements.ctxg.strokeStyle = config.strokeColor; + elements.ctxg.lineWidth = 3; + elements.ctxg.beginPath(); + elements.ctxg.moveTo(dimensions.start, dimensions.height * 0.5); + elements.ctxg.lineTo(dimensions.end, dimensions.height * 0.5); + elements.ctxg.stroke(); + } + + return { + init: init, + setHandler: setHandler, + config: config + }; + + // debugging utilities + + function drawBars(binary) { + for (var i = 0, ii = binary.length; i < ii; i++) { + if (binary[i] == 1) { + elements.ctxg.strokeStyle = '#fff'; + } else { + elements.ctxg.strokeStyle = '#000'; + } + elements.ctxg.lineWidth = 3; + elements.ctxg.beginPath(); + elements.ctxg.moveTo(start + i, height * 0.5); + elements.ctxg.lineTo(start + i + 1, height * 0.5); + elements.ctxg.stroke(); + } + } + +}(); diff --git a/pos_qr_scan/static/src/css/pos.css b/pos_qr_scan/static/src/css/pos.css index 48838baee0..9524717267 100644 --- a/pos_qr_scan/static/src/css/pos.css +++ b/pos_qr_scan/static/src/css/pos.css @@ -49,3 +49,11 @@ .fa-qrcode:before { content: "\f029"; } + +video { + -moz-transform:scale(1.8); + -webkit-transform:scale(1.8); + -o-transform:scale(1.8); + -ms-transform:scale(1.8); + transform:scale(1.8); +} \ No newline at end of file diff --git a/pos_qr_scan/static/src/js/qr_scan.js b/pos_qr_scan/static/src/js/qr_scan.js index bc046f18ea..c9c7ca428a 100644 --- a/pos_qr_scan/static/src/js/qr_scan.js +++ b/pos_qr_scan/static/src/js/qr_scan.js @@ -1,5 +1,5 @@ /* Copyright 2018 Ivan Yelizariev - Copyright 2018 Kolushov Alexandr + Copyright 2018-2019 Kolushov Alexandr License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl.html). */ odoo.define('pos_qr_scan', function(require){ var exports = {}; @@ -9,6 +9,9 @@ odoo.define('pos_qr_scan', function(require){ var gui = require('point_of_sale.gui'); var PopupWidget = require('point_of_sale.popups'); var screens = require('point_of_sale.screens'); + var core = require('web.core'); + var _t = core._t; + var Quagga = window.Quagga; var QrButton = screens.ActionButtonWidget.extend({ template: 'QrButton', @@ -32,17 +35,88 @@ odoo.define('pos_qr_scan', function(require){ var self = this; this.gUM = false; this._super(options); - this.generate_qr_scanner(); + this.prepare_video_element(); + var config = this.pos.config; + if (config.use_only_qr_scan) { + this.generate_qr_scanner(); + } else if (config.use_only_barcode_scan) { + this.generate_barcode_scanner(); + } else { + this.generate_qr_scanner(); + this.generate_barcode_scanner(); + } + this.read_callback = options.read_callback || this.read; + }, + init: function(parent, args) { + this._super(parent, args); + }, + generate_barcode_scanner: function () { + var self = this; + barcode.config.start = 0.1; + barcode.config.end = 0.9; + barcode.config.video = '#preview'; + barcode.config.canvas = '#qr-canvas'; + barcode.config.canvasg = '#qr-canvasg'; + barcode.setHandler(function(barcode) { + if (this.lastResult !== barcode) { + this.lastResult = barcode; + self.read_callback(barcode, 'barcode'); + } + }); + barcode.init(); + // Quagga.init({ + // inputStream : { + // name : "Live", + // type : "LiveStream", + // target: document.querySelector('#preview') + // }, + // decoder : { + // readers : [ + // // "code_128_reader", + // "ean_reader", + // // "ean_8_reader", + // // "code_39_reader", + // // "code_39_vin_reader", + // // "codabar_reader", + // // "upc_reader", + // // "upc_e_reader", + // // "i2of5_reader", + // // "code_93_reader", + // ] + // } + // }, function(err) { + // if (err) { + // console.log(err); + // return; + // } + // console.log("Initialization finished. Ready to start"); + // Quagga.start(); + // }); + // + // Quagga.onDetected(function(result) { + // var code = result.codeResult.code; + // + // if (this.lastResult !== code) { + // this.lastResult = code; + // var $node = null, + // canvas = Quagga.canvas.dom.image; + // self.read_callback(code, 'barcode'); + // } + // }); }, click_cancel: function() { - this.stop_camera(); this._super(arguments); + this.stop_camera(); }, stop_camera: function(camera){ this.cam_is_on = false; if (this.stream){ this.stream.getTracks()[0].stop(); } + if (!this.pos.config.use_only_qr_scan) { + // Quagga.stop(); + // Quagga.offDetected(); + } }, add_button: function(content) { var button = document.createElement('div'); @@ -64,16 +138,16 @@ odoo.define('pos_qr_scan', function(require){ return cam.deviceId === id; }); }, - generate_qr_scanner: function() { - var options = false; - var self = this; + prepare_video_element: function() { this.video_element = document.getElementById("preview"); $(this.video_element).on('click',function(){ self.click_cancel(); }); + var options = false; + var self = this; if(navigator.mediaDevices && navigator.mediaDevices.enumerateDevices){ this.capture_timeout = 700; - try{ + try { navigator.mediaDevices.enumerateDevices().then(function(devices) { self.video_devices = _.filter(devices, function(d) { return d.kind === 'videoinput'; @@ -96,31 +170,40 @@ odoo.define('pos_qr_scan', function(require){ } self.start_webcam(options); }); - } - catch(e){ + } catch(e){ alert(e); } - } - else{ + } else{ console.log("no navigator.mediaDevices.enumerateDevices" ); - this.start_webcam(options); + this.pos.gui.show_popup('alert', { + title: _t('Error'), + body: _t('No Media Devices Found') + }); } }, + generate_qr_scanner: function() { + var self = this; + this.cam_is_on = true; + setTimeout(function(){ + self.captureToCanvas(); + }, this.capture_timeout); + }, - read: function(result){ + read: function(result, method){ + method = method || 'qr'; // Trigger event on scanning and close camera window if (this.pos.debug){ - console.log('QR scanned', result); + console.log(method.toUpperCase() + ' scanned', result); } - core.bus.trigger('qr_scanned', result); - posmodel.gui.popup_instances.qr_scan.click_cancel(); + this.click_cancel(); + core.bus.trigger(method + '_scanned', result); }, start_webcam: function(options){ var self = this; this.initCanvas(800, 600); qrcode.callback = function(value){ - self.read(value); + self.read_callback(value, 'qr'); } if(navigator.mediaDevices.getUserMedia){ navigator.mediaDevices.getUserMedia({video: options, audio: false}). @@ -141,11 +224,6 @@ odoo.define('pos_qr_scan', function(require){ webkit = true; navigator.webkitGetUserMedia({video:options, audio: false}, success, error); } - - this.cam_is_on = true; - setTimeout(function(){ - self.captureToCanvas(); - }, this.capture_timeout); }, success: function(stream){ @@ -160,7 +238,7 @@ odoo.define('pos_qr_scan', function(require){ if(this.gUM){ var self = this; try{ - gCtx.drawImage(this.video_element,0,0); + this.gCtx.drawImage(this.video_element,0,0); try{ qrcode.decode(); } @@ -180,13 +258,14 @@ odoo.define('pos_qr_scan', function(require){ } }, initCanvas: function(w,h){ - var gCanvas = document.getElementById("qr-canvas"); + var gCanvas = document.getElementById("qr-canvasg"); gCanvas.style.width = w + "px"; gCanvas.style.height = h + "px"; gCanvas.width = w; gCanvas.height = h; var gCtx = gCanvas.getContext("2d"); gCtx.clearRect(0, 0, w, h); + this.gCtx = gCtx; } }); diff --git a/pos_qr_scan/static/src/xml/templates.xml b/pos_qr_scan/static/src/xml/templates.xml index 3336b43602..b319fbb7bb 100644 --- a/pos_qr_scan/static/src/xml/templates.xml +++ b/pos_qr_scan/static/src/xml/templates.xml @@ -1,9 +1,11 @@ +
- QR Scan + QR / Barcode Scan
@@ -12,10 +14,11 @@ diff --git a/pos_qr_scan/views/assets.xml b/pos_qr_scan/views/assets.xml index 7ad161ac78..ecfb43c165 100644 --- a/pos_qr_scan/views/assets.xml +++ b/pos_qr_scan/views/assets.xml @@ -1,11 +1,10 @@ - - + + - - + diff --git a/pos_qr_scan/views/pos_config.xml b/pos_qr_scan/views/pos_config.xml new file mode 100644 index 0000000000..84619eea89 --- /dev/null +++ b/pos_qr_scan/views/pos_config.xml @@ -0,0 +1,36 @@ + + + + + pos.config.form.view.inherit + pos.config + + + +

QR / Barcode Scanning

+
+
+ By Default QR and Barcode scanning are both enabled +
+
+
+ +
+
+
+
+
+
+ +
+
+
+
+
+
+
+
+