diff --git a/app.js b/app.js index 208b3d72..0af70d2b 100644 --- a/app.js +++ b/app.js @@ -20,9 +20,15 @@ var app = new Vue({ pattern: '', output: '' }, + currentHttpAction: { + url: '', + captureImage: false, + enabling: false + }, scans: store.get('scans') || [], transforms: store.get('transforms') || [], - linkAction: store.get('link-action') || 'ignore', + linkAction: store.get('link-action') || 'none', + httpAction: store.get('http-action') || { enabled: false }, activeCamera: store.get('active-camera') || null, playAudio: store.get('play-audio') || false, allowBackgroundScan: store.get('background-scan') || false @@ -71,6 +77,20 @@ var app = new Vue({ self.store.set('background-scan', allowBackgroundScan); }); + this.$watch('httpAction', function (action) { + self.store.set('http-action', action); + }, { deep: true }); + + this.$watch('httpAction.captureImage', function (capture) { + scanner.setCaptureImage(capture); + }); + + this.$watch('httpAction.enabled', function (enabled) { + if (enabled) { + this.editHttpAction(true); + } + }); + new Clipboard('.clipboard-copy', { text: function (trigger) { return trigger.dataset.clipboard; @@ -139,11 +159,40 @@ var app = new Vue({ this.transforms.splice(index, 1); }, + editHttpAction: function (enabling = false) { + this.currentHttpAction.url = this.httpAction.url; + this.currentHttpAction.captureImage = this.httpAction.captureImage; + this.currentHttpAction.enabling = enabling; + $('#http-action-dialog').modal(); + }, + + closeHttpActionDialog: function () { + $('#http-action-dialog').modal('hide'); + }, + + cancelHttpActionDialog: function () { + if (this.currentHttpAction.enabling) { + this.httpAction.enabled = false; + } + + this.closeHttpActionDialog(); + }, + + acceptHttpActionDialog: function () { + this.httpAction.url = this.currentHttpAction.url; + this.httpAction.captureImage = this.currentHttpAction.captureImage; + this.closeHttpActionDialog(); + }, + addScan: function (content) { - this.scans.push({ + var scan = { content: content, date: +(new Date()) - }); + }; + + this.scans.push(scan); + + return scan; }, deleteScan: function (scan) { @@ -164,11 +213,15 @@ var app = new Vue({ return string.match(/^https?:\/\//i); }, - onScanResult: function (content) { + onScanResult: function (content, image) { content = this.transform(content); var isHttpUrl = this.isHttpUrl(content); + if (this.playAudio) { + this.chime.play(); + } + var snackbarContent = 'Scanned: ' + content + 'call_made Open'; } - if (this.playAudio) { - this.chime.play(); - } - $('body').snackbar({ alive: 5 * 1000, content: snackbarContent }); - this.addScan(content); + var scan = this.addScan(content); - if (this.linkAction !== 'ignore' && isHttpUrl) { + if (this.linkAction !== 'none' && isHttpUrl) { if (this.linkAction === 'new-tab') { var win = window.open(content, '_blank'); win.focus(); @@ -201,6 +250,29 @@ var app = new Vue({ window.location = content; } } + + if (this.httpAction.enabled) { + var body = { + content: scan.content, + date: scan.date + }; + + if (image) { + body.image = image; + } + + $.ajax({ + method: 'POST', + url: this.httpAction.url, + contentType: 'application/json', + data: JSON.stringify(body), + processData: false + }).done(function () { + // TODO. + }).fail(function () { + // TODO. + }); + } } } }); diff --git a/index.html b/index.html index 01ee659f..6dda3b05 100644 --- a/index.html +++ b/index.html @@ -94,6 +94,13 @@

After scanning

Play a sound +
+ + Edit +
@@ -102,8 +109,8 @@

After scanning a link

-
+
history diff --git a/qr.js b/qr.js index ea00a85b..1dbd224f 100644 --- a/qr.js +++ b/qr.js @@ -5,6 +5,7 @@ function CameraQrScanner(previewContainer) { this.scanActive = false; this.lastResult = null; this.refractoryTimeout = null; + this.captureImage = false; var cameraElement = document.createElement('video'); cameraElement.setAttribute('autoplay', 'autoplay'); @@ -50,6 +51,7 @@ function CameraQrScanner(previewContainer) { cameraElement.src = window.URL.createObjectURL(stream); startScan(); }, function (err) { + // TODO. }); }; @@ -65,7 +67,11 @@ function CameraQrScanner(previewContainer) { } }; - var image; + this.setCaptureImage = function (captureImage) { + this.captureImage = captureImage; + }; + + this.imageBuffer = null; var context; var sensorLeft; @@ -107,7 +113,7 @@ function CameraQrScanner(previewContainer) { return; } - if (!image) { + if (!this.imageBuffer) { var videoWidth = cameraElement.videoWidth; var videoHeight = cameraElement.videoHeight; @@ -119,7 +125,7 @@ function CameraQrScanner(previewContainer) { canvas.height = sensorHeight; context = canvas.getContext('2d'); - image = ZXing._resize(sensorWidth, sensorHeight); + this.imageBuffer = ZXing._resize(sensorWidth, sensorHeight); return; } @@ -127,7 +133,7 @@ function CameraQrScanner(previewContainer) { var data = context.getImageData(0, 0, sensorWidth, sensorHeight).data; for (var i = 0, j = 0; i < data.length; i += 4, j++) { - ZXing.HEAPU8[image + j] = data[i]; + ZXing.HEAPU8[this.imageBuffer + j] = data[i]; } var err = ZXing._decode_qr(decodeCallback); @@ -142,9 +148,11 @@ function CameraQrScanner(previewContainer) { self.lastResult = null; }, 5 * 1000); + var image = self.captureImage ? canvas.toDataURL('image/webp', 0.8) : null; + self.lastResult = result; setTimeout(function () { - self.onResult(result); + self.onResult(result, image); }, 0); } } diff --git a/style.css b/style.css index 679e102e..1c605ebb 100644 --- a/style.css +++ b/style.css @@ -4,6 +4,9 @@ html, body { background: #000; overflow: hidden; } +a { + cursor: pointer !important; +} video { margin: 0; padding: 0;