Merge branch 'upstream/develop' into develop

# Conflicts:
#	app/scripts/app.js
This commit is contained in:
Alex Shpak 2017-02-11 23:06:03 +01:00
commit bda4cbf2ad
14 changed files with 108 additions and 29 deletions

View File

@ -39,7 +39,6 @@ module.exports = function(grunt) {
const data = fs.readFileSync('tmp/fonts/' + fontFile, 'base64');
const src = 'url(data:application/font-woff;charset=utf-8;base64,{data}) format(\'woff\')'
.replace('{data}', data);
// var src = 'url(\'../fonts/fontawesome-webfont.woff\') format(\'woff\')';
rule.nodes = rule.nodes.filter(n => n.prop !== 'src');
rule.append({ prop: 'src', value: src });
});
@ -102,7 +101,7 @@ module.exports = function(grunt) {
{ test: /\.json$/, loader: 'json-loader' },
{ test: /argon2-asm\.min\.js$/, loader: 'raw-loader' },
{ test: /argon2\.wasm$/, loader: 'base64-loader' },
{ test: /argon2\.min\.js/, loader: 'raw-loader' } // exports-loader?Module
{ test: /argon2\.min\.js/, loader: 'raw-loader' }
]
},
plugins: [

View File

@ -72,7 +72,7 @@ ready(() => {
if (configParam) {
appModel.loadConfig(configParam, err => {
SettingsManager.setBySettings(appModel.settings);
if (err) {
if (err && !appModel.settings.get('cacheConfigSettings')) {
showSettingsLoadError();
reject(err);
} else {

View File

@ -2,10 +2,26 @@
const AppSettingsModel = require('../models/app-settings-model');
const Libs = {
backbone: require('backbone'),
_: require('underscore'),
underscore: require('underscore'),
$: require('jquery'),
jquery: require('jquery'),
kdbxweb: require('kdbxweb'),
hbs: require('hbs'),
pikaday: require('pikaday'),
filesaver: require('filesaver'),
qrcode: require('qrcode')
};
const ExportApi = {
settings: {
get: function(key) { return key ? AppSettingsModel.instance.get(key) : AppSettingsModel.instance.toJSON(); },
set: function(key, value) { AppSettingsModel.instance.set(key, value); }
},
require: function(module) {
return Libs[module] || require('../' + module);
}
};

View File

@ -231,6 +231,7 @@
"detClone": "Make a copy",
"detClonedName": "Copy",
"detAutoType": "Auto-type",
"detAutoTypeSettings": "Auto-type settings",
"detAutoTypeEnabled": "Enable auto-type for this entry",
"detAutoTypeSequence": "Keystrokes",
"detAutoTypeInput": "Input",

View File

@ -68,6 +68,7 @@ const AppModel = Backbone.Model.extend({
response = JSON.parse(response);
} catch (e) {
this.appLogger.error('Error parsing response', e, response);
return callback(true);
}
}
if (!response.settings) {
@ -87,6 +88,9 @@ const AppModel = Backbone.Model.extend({
applyUserConfig(config) {
this.settings.set(config.settings);
if (config.files) {
if (config.showOnlyFilesFromConfig) {
this.fileInfos.reset();
}
config.files
.filter(file => file && file.storage && file.name && file.path &&
!this.fileInfos.getMatch(file.storage, file.name, file.path))

View File

@ -29,12 +29,15 @@ const AppSettingsModel = Backbone.Model.extend({
fontSize: 0,
tableViewColumns: null,
generatorPresets: null,
cacheConfigSettings: false,
canOpen: true,
canOpenDemo: true,
canOpenSettings: true,
canCreate: true,
canImportXml: true,
canRemoveLatest: true,
dropbox: true,
webdav: true,
gdrive: true,
@ -69,6 +72,9 @@ const AppSettingsModel = Backbone.Model.extend({
if (data.rememberKeyFiles === true) {
data.rememberKeyFiles = 'data';
}
if (data.versionWarningShown) {
delete data.versionWarningShown;
}
},
save: function() {

View File

@ -90,6 +90,14 @@ const AppView = Backbone.View.extend({
KeyHandler.onKey(Keys.DOM_VK_F12, this.openDevTools, this, KeyHandler.SHORTCUT_ACTION);
setInterval(this.syncAllByTimer.bind(this), Timeouts.AutoSync);
this.setWindowClass();
},
setWindowClass: function() {
if (window.chrome && window.chrome.webstore) {
this.$el.addClass('chrome');
}
},
render: function () {

View File

@ -251,7 +251,7 @@ const DetailsView = Backbone.View.extend({
}
moreOptions.push({value: 'otp', icon: 'clock-o', text: Locale.detSetupOtp});
if (AutoType.enabled) {
moreOptions.push({value: 'auto-type', icon: 'keyboard-o', text: Locale.detAutoType});
moreOptions.push({value: 'auto-type', icon: 'keyboard-o', text: Locale.detAutoTypeSettings});
}
moreOptions.push({value: 'clone', icon: 'clone', text: Locale.detClone});
const rect = this.moreView.labelEl[0].getBoundingClientRect();
@ -774,6 +774,9 @@ const DetailsView = Backbone.View.extend({
}
options.push({ value: 'det-add-new', icon: 'plus', text: Locale.detMenuAddNewField });
options.push({ value: 'det-clone', icon: 'clone', text: Locale.detClone });
if (AutoType.enabled) {
options.push({ value: 'det-auto-type', icon: 'keyboard-o', text: Locale.detAutoType });
}
Backbone.trigger('show-context-menu', _.extend(e, { options }));
},
@ -791,6 +794,9 @@ const DetailsView = Backbone.View.extend({
case 'det-clone':
this.clone();
break;
case 'det-auto-type':
this.autoType();
break;
}
},

View File

@ -1,6 +1,7 @@
'use strict';
const FieldViewText = require('./field-view-text');
const Keys = require('../../const/keys');
const FieldViewAutocomplete = FieldViewText.extend({
endEdit: function(newVal, extra) {
@ -8,6 +9,7 @@ const FieldViewAutocomplete = FieldViewText.extend({
this.autocomplete.remove();
this.autocomplete = null;
}
delete this.selectedCopmletionIx;
FieldViewText.prototype.endEdit.call(this, newVal, extra);
},
@ -20,6 +22,7 @@ const FieldViewAutocomplete = FieldViewText.extend({
left: fieldRect.left,
width: fieldRect.width - 2
});
delete this.selectedCopmletionIx;
this.autocomplete.mousedown(this.autocompleteClick.bind(this));
if (this.input.val()) {
this.autocomplete.hide();
@ -34,10 +37,44 @@ const FieldViewAutocomplete = FieldViewText.extend({
FieldViewText.prototype.fieldValueInput.call(this, e);
},
fieldValueKeydown: function(e) {
switch (e.which) {
case Keys.DOM_VK_UP:
this.moveAutocomplete(false);
e.preventDefault();
break;
case Keys.DOM_VK_DOWN:
this.moveAutocomplete(true);
e.preventDefault();
break;
case Keys.DOM_VK_RETURN:
const selectedItem = this.autocomplete.find('.details__field-autocomplete-item--selected').text();
if (selectedItem) {
this.input.val(selectedItem);
this.endEdit(selectedItem);
}
break;
default:
delete this.selectedCopmletionIx;
}
FieldViewText.prototype.fieldValueKeydown.call(this, e);
},
moveAutocomplete: function(next) {
const completions = this.model.getCompletions(this.input.val());
if (typeof this.selectedCopmletionIx === 'number') {
this.selectedCopmletionIx = (completions.length + this.selectedCopmletionIx + (next ? 1 : -1)) % completions.length;
} else {
this.selectedCopmletionIx = next ? 0 : completions.length - 1;
}
this.updateAutocomplete();
},
updateAutocomplete: function() {
const completions = this.model.getCompletions(this.input.val());
const completionsHtml = completions.map(item => {
return '<div class="details__field-autocomplete-item">' + _.escape(item) + '</div>';
const completionsHtml = completions.map((item, ix) => {
const sel = ix === this.selectedCopmletionIx ? 'details__field-autocomplete-item--selected' : '';
return '<div class="details__field-autocomplete-item ' + sel + '">' + _.escape(item) + '</div>';
}).join('');
this.autocomplete.html(completionsHtml);
this.autocomplete.toggle(!!completionsHtml);

View File

@ -3,7 +3,6 @@
const Backbone = require('backbone');
const kdbxweb = require('kdbxweb');
const OpenConfigView = require('./open-config-view');
const AppSettingsModel = require('../models/app-settings-model');
const Keys = require('../const/keys');
const Alerts = require('../comp/alerts');
const SecureInput = require('../comp/secure-input');
@ -94,21 +93,6 @@ const OpenView = Backbone.View.extend({
});
this.inputEl = this.$el.find('.open__pass-input');
this.passwordInput.setElement(this.inputEl);
if (!this.versionWarningShown) {
// TODO: remove in v1.5
this.versionWarningShown = AppSettingsModel.instance.get('versionWarningShown');
if (!this.versionWarningShown) {
AppSettingsModel.instance.set('versionWarningShown', true);
this.versionWarningShown = true;
if (this.model.fileInfos.length) {
Alerts.info({
header: 'KeeWeb updated',
body: 'There was a major update of KeeWeb. Please make sure you have a backup of your password files!'
});
}
}
}
return this;
},

View File

@ -185,6 +185,7 @@
height: $details-field-line-height;
width: 100%;
@include th { color: text-color(); }
.chrome & { padding-bottom: 1px; } // TODO: find a better cross-browser way to do it
}
}
&-value {
@ -240,6 +241,9 @@
height: 20px;
.details__field--protected & { font-family: $monospace-font-family; }
}
>input {
.chrome & { padding-bottom: 1px; } // TODO: find a better cross-browser way to do it
}
>textarea {
display: block;
resize: none;
@ -527,6 +531,12 @@
display: inline-block;
word-break: break-all;
@include area-selectable(bottom);
&--selected {
@include th {
background-color: secondary-background-color();
border-bottom: selected-hover-border();
}
}
}
}
}

View File

@ -26,12 +26,12 @@
"baron": "2.2.2",
"bourbon": "4.2.7",
"dropbox": "keeweb/dropbox-js#0ac0efdc2711eece73f6ac044459e1fd0d5e9390",
"font-awesome": "4.6.3",
"kdbxweb": "a4d58631f2c98667e0de2f46915db2dd79bddd07",
"normalize.css": "4.2.0",
"pikaday": "1.4.0",
"font-awesome": "4.7.0",
"kdbxweb": "1.0.0",
"normalize.css": "5.0.0",
"pikaday": "1.5.1",
"FileSaver.js": "eligrey/FileSaver.js",
"jquery": "3.1.0",
"jquery": "3.1.1",
"jsqrcode": "antelle/jsqrcode#0.1.3",
"argon2-browser": "0.0.5"
}

View File

@ -2,6 +2,11 @@ Release notes
-------------
##### v1.5.0 (TBD)
`+` file path hint in recent files list
`+` cacheConfigSettings config option
`+` keyboard-accessible autocomplete
`+` entry auto-type context menu
`+` `kw.require` now provides access to modules
`+` showOnlyFilesFromConfig config option
##### v1.4.0 (2017-02-04)
KDBX4 format support and minor improvements

View File

@ -38,12 +38,15 @@
"gdriveClientId": null,
"onedrive": true,
"onedriveClientId": null
"onedriveClientId": null,
"cacheConfigSettings": false
},
"files": [{
"storage": "webdav",
"name": "My file",
"path": "webdav-url",
"options": { "user": "", "password": "" }
}]
}],
"showOnlyFilesFromConfig": false
}