keeweb/app/scripts/auto-type/index.js

210 lines
6.7 KiB
JavaScript
Raw Normal View History

2016-04-08 17:40:00 +02:00
'use strict';
2016-07-24 19:11:25 +02:00
var Backbone = require('backbone'),
AutoTypeParser = require('./auto-type-parser'),
2016-07-25 20:27:22 +02:00
AutoTypeFilter = require('./auto-type-filter'),
2016-04-09 20:58:22 +02:00
AutoTypeHelperFactory = require('./auto-type-helper-factory'),
2016-04-23 16:50:40 +02:00
Launcher = require('../comp/launcher'),
2016-07-24 19:11:25 +02:00
Alerts = require('../comp/alerts'),
2016-07-24 22:57:12 +02:00
AutoTypeSelectView = require('../views/auto-type/auto-type-select-view'),
2016-04-23 16:50:40 +02:00
Logger = require('../util/logger'),
2016-07-24 19:11:25 +02:00
Locale = require('../util/locale'),
2016-04-23 16:50:40 +02:00
Timeouts = require('../const/timeouts');
2016-04-08 17:40:00 +02:00
var logger = new Logger('auto-type');
2016-04-09 14:55:27 +02:00
var clearTextAutoTypeLog = localStorage.autoTypeDebug;
2016-04-09 11:28:14 +02:00
2016-04-08 17:40:00 +02:00
var AutoType = {
2016-04-09 20:58:22 +02:00
helper: AutoTypeHelperFactory.create(),
2016-04-23 16:50:40 +02:00
enabled: !!Launcher,
2016-07-24 22:57:12 +02:00
selectEntryView: false,
2016-08-07 19:34:31 +02:00
pendingEvent: null,
2016-04-23 16:50:40 +02:00
2016-08-07 19:34:31 +02:00
init(appModel) {
2016-07-24 22:57:12 +02:00
if (!this.enabled) {
return;
}
this.appModel = appModel;
2016-08-07 19:34:31 +02:00
Backbone.on('auto-type', this.handleEvent, this);
Backbone.on('main-window-blur main-window-will-close', this.resetPendingEvent, this);
2016-07-24 19:11:25 +02:00
},
2016-08-07 19:34:31 +02:00
handleEvent(e) {
2016-07-30 21:12:29 +02:00
let entry = e && e.entry || null;
2016-07-24 19:11:25 +02:00
logger.debug('Auto type event', entry);
if (entry) {
this.hideWindow(() => { this.runAndHandleResult(entry); });
} else {
if (this.selectEntryView) {
return;
}
if (Launcher.isAppFocused()) {
return Alerts.error({
header: Locale.autoTypeError,
body: Locale.autoTypeErrorGlobal,
skipIfAlertDisplayed: true
});
}
this.selectEntryAndRun();
}
},
2016-08-07 19:34:31 +02:00
runAndHandleResult(entry) {
2016-07-24 19:11:25 +02:00
this.run(entry, err => {
if (err) {
Alerts.error({
header: Locale.autoTypeError,
body: Locale.autoTypeErrorGeneric.replace('{}', err.toString())
});
}
});
},
2016-08-07 19:34:31 +02:00
run(entry, callback) {
2016-04-23 17:05:33 +02:00
var sequence = entry.getEffectiveAutoTypeSeq();
2016-04-08 17:40:00 +02:00
logger.debug('Start', sequence);
2016-04-23 17:05:33 +02:00
var ts = logger.ts();
2016-04-08 17:40:00 +02:00
try {
var parser = new AutoTypeParser(sequence);
var runner = parser.parse();
2016-07-17 13:30:38 +02:00
logger.debug('Parsed', this.printOps(runner.ops));
runner.resolve(entry, err => {
2016-04-08 17:40:00 +02:00
if (err) {
2016-04-08 23:14:09 +02:00
logger.error('Resolve error', err);
2016-04-23 17:05:33 +02:00
return callback && callback(err);
2016-04-08 17:40:00 +02:00
}
2016-07-17 13:30:38 +02:00
logger.debug('Resolved', this.printOps(runner.ops));
2016-04-23 21:35:30 +02:00
if (entry.autoTypeObfuscation) {
2016-04-09 14:55:27 +02:00
try {
runner.obfuscate();
} catch (e) {
logger.error('Obfuscate error', e);
2016-04-23 17:05:33 +02:00
return callback && callback(e);
2016-04-09 14:55:27 +02:00
}
2016-04-10 09:31:08 +02:00
logger.debug('Obfuscated');
2016-04-09 10:41:52 +02:00
}
2016-07-17 13:30:38 +02:00
runner.run(err => {
2016-04-08 17:40:00 +02:00
if (err) {
logger.error('Run error', err);
2016-04-23 17:05:33 +02:00
return callback && callback(err);
2016-04-08 17:40:00 +02:00
}
2016-04-23 17:05:33 +02:00
logger.debug('Complete', logger.ts(ts));
return callback && callback();
2016-04-08 17:40:00 +02:00
});
});
} catch (ex) {
logger.error('Parse error', ex);
2016-04-23 17:05:33 +02:00
return callback && callback(ex);
2016-04-08 17:40:00 +02:00
}
2016-04-09 11:17:01 +02:00
},
2016-08-07 19:34:31 +02:00
validate(entry, sequence, callback) {
2016-04-23 16:50:40 +02:00
try {
var parser = new AutoTypeParser(sequence);
var runner = parser.parse();
runner.resolve(entry, callback);
} catch (ex) {
return callback(ex);
}
},
2016-08-07 19:34:31 +02:00
printOps(ops) {
2016-04-09 11:17:01 +02:00
return '[' + ops.map(this.printOp, this).join(',') + ']';
},
2016-08-07 19:34:31 +02:00
printOp(op) {
2016-04-09 11:17:01 +02:00
var mod = op.mod ? Object.keys(op.mod).join('') : '';
if (op.type === 'group') {
return mod + this.printOps(op.value);
}
if (op.type === 'text') {
2016-04-09 11:28:14 +02:00
var value = op.value;
if (!clearTextAutoTypeLog) {
value = value.replace(/./g, '*');
}
return mod + value;
2016-04-09 11:17:01 +02:00
}
return mod + op.type + ':' + op.value;
2016-04-09 20:58:22 +02:00
},
2016-08-07 19:34:31 +02:00
hideWindow(callback) {
2016-04-09 20:58:22 +02:00
logger.debug('Hide window');
2016-07-24 19:11:25 +02:00
if (Launcher.isAppFocused()) {
Launcher.hideApp();
2016-04-09 20:58:22 +02:00
setTimeout(callback, Timeouts.AutoTypeAfterHide);
} else {
callback();
}
},
2016-08-07 19:34:31 +02:00
getActiveWindowTitle(callback) {
2016-04-09 20:58:22 +02:00
logger.debug('Get window title');
2016-07-17 13:30:38 +02:00
return this.helper.getActiveWindowTitle((err, title, url) => {
2016-04-09 20:58:22 +02:00
if (err) {
logger.error('Error get window title', err);
} else {
2016-04-09 22:19:56 +02:00
logger.debug('Window title', title, url);
2016-04-09 20:58:22 +02:00
}
2016-07-24 19:11:25 +02:00
return callback(err, title, url);
});
},
2016-08-07 19:34:31 +02:00
selectEntryAndRun() {
2016-07-24 19:11:25 +02:00
this.getActiveWindowTitle((e, title, url) => {
2016-07-25 20:27:22 +02:00
let filter = new AutoTypeFilter({title, url}, this.appModel);
2016-08-07 19:34:31 +02:00
let evt = { filter };
if (!this.appModel.files.hasOpenFiles()) {
this.pendingEvent = evt;
this.appModel.files.once('update', this.processPendingEvent, this);
logger.debug('auto-type event delayed');
2016-08-14 10:09:35 +02:00
setTimeout(() => Launcher.showMainWindow(), Timeouts.RedrawInactiveWindow);
2016-08-07 19:34:31 +02:00
} else {
this.processEventWithFilter(evt);
2016-07-24 19:11:25 +02:00
}
2016-08-07 19:34:31 +02:00
});
},
processEventWithFilter(evt) {
let entries = evt.filter.getEntries();
if (entries.length === 1) {
2016-08-11 20:15:23 +02:00
this.runAndHandleResult(entries.at(0));
2016-08-07 19:34:31 +02:00
return;
}
this.selectEntryView = new AutoTypeSelectView({
model: { filter: evt.filter }
}).render();
this.selectEntryView.on('result', result => {
logger.debug('Entry selected', result);
this.selectEntryView.off('result');
this.selectEntryView.remove();
this.selectEntryView = null;
this.hideWindow(() => {
if (result) {
this.runAndHandleResult(result);
2016-07-24 22:57:12 +02:00
}
2016-07-24 19:11:25 +02:00
});
2016-04-09 20:58:22 +02:00
});
2016-08-07 19:34:31 +02:00
},
resetPendingEvent() {
if (this.pendingEvent) {
this.pendingEvent = null;
this.appModel.files.off('update', this.processPendingEvent, this);
logger.debug('auto-type event cancelled');
}
},
processPendingEvent() {
if (!this.pendingEvent) {
return;
}
logger.debug('processing pending auto-type event');
let evt = this.pendingEvent;
this.appModel.files.off('update', this.processPendingEvent, this);
this.pendingEvent = null;
this.processEventWithFilter(evt);
2016-04-08 17:40:00 +02:00
}
};
module.exports = AutoType;