mirror of https://github.com/keeweb/keeweb.git
scan or select qr codes on mobile
This commit is contained in:
parent
c6f2f9c145
commit
2ba344a0f6
|
@ -13,6 +13,8 @@ var logger = new Logger('otp-qr-reader');
|
|||
var OtpQrReader = {
|
||||
alert: null,
|
||||
|
||||
fileInput: null,
|
||||
|
||||
read: function() {
|
||||
var screenshotKey = FeatureDetector.screenshotToClipboardShortcut();
|
||||
if (screenshotKey) {
|
||||
|
@ -22,21 +24,30 @@ var OtpQrReader = {
|
|||
Locale.detSetupOtpAlertBodyWith.replace('{}',
|
||||
'<code>' + FeatureDetector.actionShortcutSymbol() + 'V</code>');
|
||||
OtpQrReader.startListenClipoard();
|
||||
var buttons = [Alerts.buttons.cancel];
|
||||
if (FeatureDetector.isMobile()) {
|
||||
buttons.unshift({result: 'select', title: Locale.detSetupOtoScanButton});
|
||||
}
|
||||
var lastLine = FeatureDetector.isMobile() ? Locale.detSetupOtpAlertBody3Mobile :
|
||||
Locale.detSetupOtpAlertBody3.replace('{}', pasteKey || '');
|
||||
OtpQrReader.alert = Alerts.alert({
|
||||
icon: 'qrcode',
|
||||
header: Locale.detSetupOtpAlert,
|
||||
body: [Locale.detSetupOtpAlertBody,
|
||||
Locale.detSetupOtpAlertBody1,
|
||||
Locale.detSetupOtpAlertBody2.replace('{}', screenshotKey || ''),
|
||||
Locale.detSetupOtpAlertBody3.replace('{}', pasteKey || '')
|
||||
lastLine
|
||||
].join('<br/>'),
|
||||
esc: '',
|
||||
click: '',
|
||||
enter: '',
|
||||
buttons: [Alerts.buttons.cancel],
|
||||
complete: function() {
|
||||
buttons: buttons,
|
||||
complete: function(res) {
|
||||
OtpQrReader.alert = null;
|
||||
OtpQrReader.stopListenClipboard();
|
||||
if (res === 'select') {
|
||||
OtpQrReader.selectFile();
|
||||
}
|
||||
}
|
||||
});
|
||||
// var BrowserWindow = require('../../comp/launcher').remReq('browser-window');
|
||||
|
@ -47,6 +58,27 @@ var OtpQrReader = {
|
|||
// win.show();
|
||||
},
|
||||
|
||||
selectFile: function() {
|
||||
if (!OtpQrReader.fileInput) {
|
||||
var input = document.createElement('input');
|
||||
input.setAttribute('type', 'file');
|
||||
input.setAttribute('capture', 'camera');
|
||||
input.setAttribute('accept', 'image/*');
|
||||
input.setAttribute('class', 'hide-by-pos');
|
||||
OtpQrReader.fileInput = input;
|
||||
OtpQrReader.fileInput.onchange = OtpQrReader.fileSelected;
|
||||
}
|
||||
OtpQrReader.fileInput.click();
|
||||
},
|
||||
|
||||
fileSelected: function() {
|
||||
var file = OtpQrReader.fileInput.files[0];
|
||||
if (!file || file.type.indexOf('image') < 0) {
|
||||
return;
|
||||
}
|
||||
OtpQrReader.readFile(file);
|
||||
},
|
||||
|
||||
startListenClipoard: function() {
|
||||
document.addEventListener('paste', OtpQrReader.pasteEvent);
|
||||
},
|
||||
|
@ -56,26 +88,29 @@ var OtpQrReader = {
|
|||
},
|
||||
|
||||
pasteEvent: function(e) {
|
||||
logger.debug('Paste event');
|
||||
var item = _.find(e.clipboardData.items, function(item) {
|
||||
return item.kind === 'file' && item.type.indexOf('image') !== -1;
|
||||
});
|
||||
if (!item) {
|
||||
logger.debug('Paste without file');
|
||||
return;
|
||||
}
|
||||
logger.info('Reading image', item.type);
|
||||
logger.info('Reading pasted image', item.type);
|
||||
if (OtpQrReader.alert) {
|
||||
OtpQrReader.alert.change({
|
||||
header: Locale.detOtpImageReading
|
||||
});
|
||||
}
|
||||
var blob = item.getAsFile();
|
||||
OtpQrReader.readFile(item.getAsFile());
|
||||
},
|
||||
|
||||
readFile: function(file) {
|
||||
var reader = new FileReader();
|
||||
reader.onload = function() {
|
||||
logger.debug('Image data loaded');
|
||||
OtpQrReader.readQr(reader.result);
|
||||
};
|
||||
reader.readAsDataURL(blob);
|
||||
reader.readAsDataURL(file);
|
||||
},
|
||||
|
||||
readQr: function(imageData) {
|
||||
|
@ -86,8 +121,7 @@ var OtpQrReader = {
|
|||
var ts = logger.ts();
|
||||
var url = new QrCode(image).decode();
|
||||
logger.info('QR code read', logger.ts(ts));
|
||||
OtpQrReader.alert.remove();
|
||||
OtpQrReader.stopListenClipboard();
|
||||
OtpQrReader.removeAlert();
|
||||
try {
|
||||
var otp = Otp.parseUrl(url);
|
||||
OtpQrReader.trigger('qr-read', otp);
|
||||
|
@ -100,8 +134,7 @@ var OtpQrReader = {
|
|||
}
|
||||
} catch (e) {
|
||||
logger.error('Error reading QR code', e);
|
||||
OtpQrReader.alert.remove();
|
||||
OtpQrReader.stopListenClipboard();
|
||||
OtpQrReader.removeAlert();
|
||||
Alerts.error({
|
||||
header: Locale.detOtpQrError,
|
||||
body: Locale.detOtpQrErrorBody
|
||||
|
@ -110,14 +143,20 @@ var OtpQrReader = {
|
|||
};
|
||||
image.onerror = function() {
|
||||
logger.debug('Image load error');
|
||||
OtpQrReader.alert.remove();
|
||||
OtpQrReader.stopListenClipboard();
|
||||
OtpQrReader.removeAlert();
|
||||
Alerts.error({
|
||||
header: Locale.detOtpImageError,
|
||||
body: Locale.detOtpImageErrorBody
|
||||
});
|
||||
};
|
||||
image.src = imageData;
|
||||
},
|
||||
|
||||
removeAlert: function() {
|
||||
if (OtpQrReader.alert) {
|
||||
OtpQrReader.alert.remove();
|
||||
}
|
||||
OtpQrReader.stopListenClipboard();
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -206,6 +206,8 @@ var Locale = {
|
|||
detSetupOtpAlertBody1: '1. go to the authorization page',
|
||||
detSetupOtpAlertBody2: '2. make a screenshot of the QR code {}',
|
||||
detSetupOtpAlertBody3: '3. paste it here {}',
|
||||
detSetupOtpAlertBody3Mobile: '3. select it or scan with your camera using Select/Scan button below',
|
||||
detSetupOtoScanButton: 'Select/Scan',
|
||||
detSetupOtpAlertBodyWith: 'with {}',
|
||||
detOtpImageError: 'Error reading image',
|
||||
detOtpImageErrorBody: 'Sorry, we could not read the image format, please contact the app authors with error details.',
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
var FieldViewText = require('./field-view-text'),
|
||||
Timeouts = require('../../const/timeouts');
|
||||
|
||||
var MinOpacity = 0.2;
|
||||
var MinOpacity = 0.1;
|
||||
|
||||
var FieldViewOtp = FieldViewText.extend({
|
||||
otpTimeout: null,
|
||||
|
|
Loading…
Reference in New Issue