show auto-type view inside app window

This commit is contained in:
antelle 2016-07-24 23:57:12 +03:00
parent 6a4c6594a7
commit d9a6de570f
12 changed files with 127 additions and 152 deletions

View File

@ -5,7 +5,7 @@ var Backbone = require('backbone'),
AutoTypeHelperFactory = require('./auto-type-helper-factory'),
Launcher = require('../comp/launcher'),
Alerts = require('../comp/alerts'),
AutoTypePopupView = require('../views/auto-type/auto-type-popup-view'),
AutoTypeSelectView = require('../views/auto-type/auto-type-select-view'),
Logger = require('../util/logger'),
Locale = require('../util/locale'),
Timeouts = require('../const/timeouts');
@ -15,12 +15,14 @@ var clearTextAutoTypeLog = localStorage.autoTypeDebug;
var AutoType = {
helper: AutoTypeHelperFactory.create(),
enabled: !!Launcher,
selectEntryView: false,
selectEntryView: null,
init: function() {
init: function(appModel) {
if (!this.enabled) {
return;
}
this.appModel = appModel;
Backbone.on('auto-type', this.handleEvent.bind(this));
},
@ -146,30 +148,36 @@ var AutoType = {
selectEntryAndRun: function() {
this.getActiveWindowTitle((e, title, url) => {
let entries = this.getMatchingEntries(title, url);
let filter = { title, url };
let entries = this.getMatchingEntries(filter);
if (entries.length === 1) {
this.runAndHandleResult(entries[0]);
return;
}
Launcher.hideMainWindow();
this.selectEntryView = new AutoTypePopupView().render();
this.selectEntryView.on('closed', e => {
Launcher.unhideMainWindow();
Launcher.hideApp();
logger.debug('Popup closed', e.result);
this.selectEntryView = new AutoTypeSelectView({
model: {
appModel: this.appModel,
filter: filter
}
}).render();
this.selectEntryView.on('result', result => {
logger.debug('Entry selected', result);
this.selectEntryView.off('result');
this.selectEntryView.remove();
this.selectEntryView = null;
// this.hideWindow(() => { /* this.runAndHandleResult(e.result); */ });
this.hideWindow(() => {
if (result) {
this.runAndHandleResult(result);
}
});
});
setTimeout(() => Launcher.showMainWindow(), Timeouts.RedrawInactiveWindow);
});
},
getMatchingEntries: function() {
return [];
return this.appModel.getEntries(); // TODO
}
};
if (AutoType.enabled) {
AutoType.init();
}
module.exports = AutoType;

View File

@ -44,7 +44,6 @@ var KeyHandler = {
if (keyShortcuts && keyShortcuts.length) {
keyShortcuts.forEach(function(sh) {
if (this.modal && !sh.modal) {
e.preventDefault();
e.stopPropagation();
return;
}
@ -74,6 +73,8 @@ var KeyHandler = {
e.charCode !== Keys.DOM_VK_TAB &&
!e.altKey && !e.ctrlKey && !e.metaKey) {
this.trigger('keypress', e);
} else if (this.modal) {
this.trigger('keypress:' + this.modal, e);
}
},
reg: function() {

View File

@ -113,8 +113,11 @@ if (window.process && window.process.versions && window.process.versions.electro
updaterEnabled: function() {
return this.electron().remote.process.argv.indexOf('--disable-updater') === -1;
},
getMainWindow: function() {
return this.remoteApp().getMainWindow();
},
resolveProxy: function(url, callback) {
var window = this.remoteApp().getMainWindow();
var window = this.getMainWindow();
var session = window.webContents.session;
session.resolveProxy(url, proxy => {
var match = /^proxy\s+([\w\.]+):(\d+)+\s*/i.exec(proxy);
@ -133,15 +136,12 @@ if (window.process && window.process.versions && window.process.versions.electro
app.hide();
}
},
hideMainWindow: function() {
this.remoteApp().getMainWindow().hide();
},
unhideMainWindow: function() {
this.remoteApp().getMainWindow().showInactive();
},
isAppFocused: function() {
return !!this.electron().remote.BrowserWindow.getFocusedWindow();
},
showMainWindow: function() {
this.getMainWindow().show();
},
spawn: function(config) {
var ts = logger.ts();
var complete = config.complete;

View File

@ -9,7 +9,8 @@ var Timeouts = {
CheckWindowClosed: 300,
OtpFadeDuration: 10000,
AutoTypeAfterHide: 100,
DrobDownClickWait: 500
DrobDownClickWait: 500,
RedrawInactiveWindow: 50
};
module.exports = Timeouts;

View File

@ -14,7 +14,8 @@ var Backbone = require('backbone'),
Timeouts = require('../const/timeouts'),
IdGenerator = require('../util/id-generator'),
Logger = require('../util/logger'),
FeatureDetector = require('../util/feature-detector');
FeatureDetector = require('../util/feature-detector'),
AutoType = require('../auto-type');
require('../mixins/protected-value-ex');
@ -39,6 +40,8 @@ var AppModel = Backbone.Model.extend({
this.listenTo(Backbone, 'empty-trash', this.emptyTrash);
this.appLogger = new Logger('app');
AutoType.init(this);
},
loadConfig: function(configLocation, callback) {
@ -189,20 +192,23 @@ var AppModel = Backbone.Model.extend({
},
getEntries: function() {
var entries = new EntryCollection();
var filter = this.prepareFilter();
this.files.forEach(file => {
file.forEachEntry(filter, (entry) => {
entries.push(entry);
});
});
let entries = this.getEntriesByFilter(filter);
entries.sortEntries(this.sort);
if (this.filter.trash) {
if (filter.trash) {
this.addTrashGroups(entries);
}
return entries;
},
getEntriesByFilter: function(filter) {
var entries = new EntryCollection();
this.files.forEach(file => {
file.forEachEntry(filter, entry => entries.push(entry));
});
return entries;
},
addTrashGroups: function(collection) {
this.files.forEach(file => {
var trashGroup = file.getTrashGroup();

View File

@ -256,7 +256,7 @@ var Locale = {
autoTypeError: 'Auto-type error',
autoTypeErrorGeneric: 'There was an error performing auto-type: {}',
autoTypeErrorGlobal: 'To use system-wide shortcut, please focus the app where you want to type your password',
autoTypePopup: 'KeeWeb: Auto Type',
autoTypeHeader: 'Auto-Type: Select Entry',
appSecWarn: 'Not Secure!',
appSecWarnBody1: 'You have loaded this app with insecure connection. ' +

View File

@ -1,100 +0,0 @@
'use strict';
const Backbone = require('backbone');
const Launcher = require('../../comp/launcher');
const Locale = require('../../util/locale');
const ThemeChanger = require('../../util/theme-changer');
const Keys = require('../../const/keys');
const AppSettingsModel = require('../../models/app-settings-model');
class AutoTypePopupView {
constructor() {
this.template = require('templates/auto-type/popup.hbs');
this.popupWindow = null;
this.result = null;
}
render() {
let themeClass = ThemeChanger.getThemeClass(AppSettingsModel.instance.get('theme'));
let styleSheet = document.styleSheets[0];
let css = styleSheet.ownerNode.textContent;
if (!css) {
// dev mode, external stylesheet
css = _.map(styleSheet.rules, rule => rule.cssText).join('\n');
}
let html = this.template({
themeClass: themeClass,
css: css
});
this.popupWindow = Launcher.openWindow({
show: false,
width: 600,
minWidth: 600,
height: 300,
minHeight: 300,
minimizable: false,
maximizable: false,
alwaysOnTop: true,
fullscreenable: false,
title: Locale.autoTypePopup,
modal: true
// icon: TODO
});
this.popupWindow.on('closed', () => this.remove());
this.popupWindow.on('blur', () => this.popupWindow.close());
this.popupWindow.on('ready-to-show', () => this.popupWindow.show());
this.popupWindow.loadURL('data:text/html;charset=utf-8,' + encodeURI(html));
this.popupWindow.webContents.executeJavaScript('(' + this.init.toString() + ')()');
Backbone.on('auto-type-popup-keydown', e => this.keydown(e));
Backbone.on('auto-type-popup-keypress', e => this.keypress(e));
Backbone.on('auto-type-popup-select', e => this.select(e));
return this;
}
remove() {
if (this.popupWindow) {
this.popupWindow = null;
Backbone.off('auto-type-popup-keydown');
Backbone.off('auto-type-popup-keypress');
Backbone.off('auto-type-popup-select');
this.trigger('closed', { result: this.result });
}
}
init() {
// note: this function will be executed in popup
function emitBackboneEvent(name, arg) {
window.require('electron').remote.app.emitBackboneEvent('auto-type-popup-' + name, arg);
}
document.body.addEventListener('keydown', e => {
emitBackboneEvent('keydown', {keyCode: e.keyCode});
});
document.body.addEventListener('keypress', e => {
emitBackboneEvent('keypress', {keyCode: e.keyCode, text: e.key});
});
}
keydown(e) {
if (e.keyCode === Keys.DOM_VK_ESCAPE) {
return this.popupWindow.close();
} else if (e.keyCode === Keys.DOM_VK_ENTER || e.keyCode === Keys.DOM_VK_RETURN) {
this.result = 'entry';
return this.popupWindow.close();
}
}
keypress(e) {
// TODO
}
select(e) {
this.result = e.result;
}
}
_.extend(AutoTypePopupView.prototype, Backbone.Events);
module.exports = AutoTypePopupView;

View File

@ -0,0 +1,62 @@
'use strict';
const Backbone = require('backbone');
const Keys = require('../../const/keys');
const KeyHandler = require('../../comp/key-handler');
let AutoTypePopupView = Backbone.View.extend({
el: 'body',
template: require('templates/auto-type/auto-type-select.hbs'),
events: {
},
result: null,
initialize() {
KeyHandler.onKey(Keys.DOM_VK_ESCAPE, this.escPressed, this, false, true);
KeyHandler.onKey(Keys.DOM_VK_RETURN, this.enterPressed, this, false, true);
KeyHandler.onKey(Keys.DOM_VK_UP, this.upPressed, this, false, true);
KeyHandler.onKey(Keys.DOM_VK_DOWN, this.downPressed, this, false, true);
KeyHandler.on('keypress:auto-type', this.keyPressed.bind(this));
KeyHandler.setModal('auto-type');
},
render() {
this.renderTemplate(this.model);
document.activeElement.blur();
return this;
},
remove() {
KeyHandler.offKey(Keys.DOM_VK_ESCAPE, this.escPressed, this);
KeyHandler.offKey(Keys.DOM_VK_RETURN, this.enterPressed, this);
KeyHandler.offKey(Keys.DOM_VK_UP, this.upPressed, this);
KeyHandler.offKey(Keys.DOM_VK_DOWN, this.downPressed, this);
KeyHandler.off('keypress:auto-type');
KeyHandler.setModal(null);
Backbone.View.prototype.remove.apply(this, arguments);
},
escPressed() {
this.result = null;
this.trigger('result', this.result);
},
enterPressed() {
this.trigger('result', this.result);
},
upPressed() {
},
downPressed() {
},
keyPressed(e) {
// let char = e.charCode;
}
});
module.exports = AutoTypePopupView;

View File

@ -21,13 +21,13 @@ var ModalView = Backbone.View.extend({
if (typeof this.model.enter === 'string') {
KeyHandler.onKey(Keys.DOM_VK_RETURN, this.enterPressed, this, false, true);
}
KeyHandler.setModal(true);
KeyHandler.setModal('alert');
},
remove: function() {
KeyHandler.offKey(Keys.DOM_VK_ESCAPE, this.escPressed, this);
KeyHandler.offKey(Keys.DOM_VK_RETURN, this.enterPressed, this);
KeyHandler.setModal(false);
KeyHandler.setModal(null);
Backbone.View.prototype.remove.apply(this, arguments);
},
@ -39,6 +39,7 @@ var ModalView = Backbone.View.extend({
el.addClass('modal--hidden');
setTimeout(() => {
el.removeClass('modal--hidden');
document.activeElement.blur();
}, 20);
return this;
},

View File

@ -1,3 +1,9 @@
.at-popup {
.at-select {
@include position(absolute, 0 null null 0);
@include size(100%);
@include th { background-color: background-color(); }
box-sizing: border-box;
z-index: $z-index-no-modal;
opacity: 1;
padding: $base-padding;
}

View File

@ -0,0 +1,3 @@
<div class="at-select">
<h1>{{res 'autoTypeHeader'}}</h1>
</div>

View File

@ -1,13 +0,0 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>{{res 'autoTypePopup'}}</title>
<style>{{{css}}}</style>
</head>
<body class="{{themeClass}} at-popup">
Hello!
{{res 'autoTypePopup'}}
<button class="btn-silent">Select</button>
</body>
</html>