import Backbone from 'backbone';
import QrCode from 'jsqrcode';
import { Shortcuts } from 'comp/app/shortcuts';
import { Alerts } from 'comp/ui/alerts';
import { Otp } from 'util/data/otp';
import { Features } from 'util/features';
import { Locale } from 'util/locale';
import { Logger } from 'util/logger';
const logger = new Logger('otp-qr-reader');
const OtpQrReader = {
alert: null,
fileInput: null,
read() {
let screenshotKey = Shortcuts.screenshotToClipboardShortcut();
if (screenshotKey) {
screenshotKey = Locale.detSetupOtpAlertBodyWith.replace(
'{}',
'' + screenshotKey + '
'
);
}
const pasteKey = Features.isMobile
? ''
: Locale.detSetupOtpAlertBodyWith.replace(
'{}',
'' + Shortcuts.actionShortcutSymbol() + 'V
'
);
OtpQrReader.startListenClipoard();
const buttons = [
{ result: 'manually', title: Locale.detSetupOtpManualButton, silent: true },
Alerts.buttons.cancel
];
if (Features.isMobile) {
buttons.unshift({ result: 'select', title: Locale.detSetupOtpScanButton });
}
const line3 = Features.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 || ''),
line3,
Locale.detSetupOtpAlertBody4
].join('
'),
esc: '',
click: '',
enter: '',
buttons,
complete(res) {
OtpQrReader.alert = null;
OtpQrReader.stopListenClipboard();
if (res === 'select') {
OtpQrReader.selectFile();
} else if (res === 'manually') {
OtpQrReader.enterManually();
}
}
});
},
selectFile() {
if (!OtpQrReader.fileInput) {
const 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() {
const file = OtpQrReader.fileInput.files[0];
if (!file || file.type.indexOf('image') < 0) {
return;
}
OtpQrReader.readFile(file);
},
startListenClipoard() {
document.addEventListener('paste', OtpQrReader.pasteEvent);
},
stopListenClipboard() {
document.removeEventListener('paste', OtpQrReader.pasteEvent);
},
pasteEvent(e) {
const item = _.find(
e.clipboardData.items,
item => item.kind === 'file' && item.type.indexOf('image') !== -1
);
if (!item) {
logger.debug('Paste without file');
return;
}
logger.info('Reading pasted image', item.type);
if (OtpQrReader.alert) {
OtpQrReader.alert.change({
header: Locale.detOtpImageReading
});
}
OtpQrReader.readFile(item.getAsFile());
},
readFile(file) {
const reader = new FileReader();
reader.onload = function() {
logger.debug('Image data loaded');
OtpQrReader.readQr(reader.result);
};
reader.readAsDataURL(file);
},
readQr(imageData) {
const image = new Image();
image.onload = function() {
logger.debug('Image format loaded');
try {
const ts = logger.ts();
const url = new QrCode(image).decode();
logger.info('QR code read', logger.ts(ts));
OtpQrReader.removeAlert();
try {
const otp = Otp.parseUrl(url);
OtpQrReader.trigger('qr-read', otp);
} catch (err) {
logger.error('Error parsing QR code', err);
Alerts.error({
header: Locale.detOtpQrWrong,
body:
Locale.detOtpQrWrongBody +
'
' + _.escape(err.toString()) + '' }); } } catch (e) { logger.error('Error reading QR code', e); OtpQrReader.removeAlert(); Alerts.error({ header: Locale.detOtpQrError, body: Locale.detOtpQrErrorBody }); } }; image.onerror = function() { logger.debug('Image load error'); OtpQrReader.removeAlert(); Alerts.error({ header: Locale.detOtpImageError, body: Locale.detOtpImageErrorBody }); }; image.src = imageData; }, enterManually() { OtpQrReader.trigger('enter-manually'); }, removeAlert() { if (OtpQrReader.alert) { OtpQrReader.alert.closeImmediate(); } } }; _.extend(OtpQrReader, Backbone.Events); export { OtpQrReader };