mirror of https://github.com/keeweb/keeweb.git
fix #50: notification on password copy
This commit is contained in:
parent
3b4153ba8a
commit
44c5516041
|
@ -51,6 +51,7 @@ var CopyPaste = {
|
|||
}).bind(null, Launcher.getClipboardText()), clipboardSeconds * 1000);
|
||||
}, 0);
|
||||
}
|
||||
return clipboardSeconds;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
'use strict';
|
||||
|
||||
var Timeouts = {
|
||||
AutoSync: 30 * 1000 * 60
|
||||
AutoSync: 30 * 1000 * 60,
|
||||
CopyTip: 1500
|
||||
};
|
||||
|
||||
module.exports = Timeouts;
|
||||
|
|
|
@ -127,6 +127,8 @@ var Locale = {
|
|||
detDelFromTrash: 'Delete from trash?',
|
||||
detDelFromTrashBody: 'You will not be able to put it back.',
|
||||
detDelFromTrashBodyHint: 'To quickly remove all items from trash, click empty icon in Trash menu.',
|
||||
detPassCopied: 'Password copied',
|
||||
detPassCopiedTime: 'Password copied for {} seconds',
|
||||
|
||||
appSecWarn: 'Not Secure!',
|
||||
appSecWarnBody1: 'You have loaded this app with insecure connection. ' +
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
'use strict';
|
||||
|
||||
var Tip = function(el) {
|
||||
var Tip = function(el, config) {
|
||||
this.el = el;
|
||||
this.title = el.attr('title');
|
||||
this.title = config && config.title || el.attr('title');
|
||||
this.placement = config && config.placement || el.attr('tip-placement');
|
||||
this.tipEl = null;
|
||||
this.showTimeout = null;
|
||||
this.hideTimeout = null;
|
||||
this.init();
|
||||
};
|
||||
|
||||
Tip.prototype.init = function() {
|
||||
|
@ -14,6 +14,49 @@ Tip.prototype.init = function() {
|
|||
this.el.mouseenter(this.mouseenter.bind(this)).mouseleave(this.mouseleave.bind(this));
|
||||
};
|
||||
|
||||
Tip.prototype.show = function() {
|
||||
if (this.tipEl) {
|
||||
this.tipEl.remove();
|
||||
if (this.hideTimeout) {
|
||||
clearTimeout(this.hideTimeout);
|
||||
this.hideTimeout = null;
|
||||
}
|
||||
}
|
||||
var tipEl = this.tipEl = $('<div></div>').addClass('tip').appendTo('body').html(this.title);
|
||||
var rect = this.el[0].getBoundingClientRect(),
|
||||
tipRect = this.tipEl[0].getBoundingClientRect();
|
||||
var placement = this.placement || this.getAutoPlacement(rect, tipRect);
|
||||
tipEl.addClass('tip--' + placement);
|
||||
var top, left;
|
||||
var offset = 10;
|
||||
switch (placement) {
|
||||
case 'top':
|
||||
top = rect.top - tipRect.height - offset;
|
||||
left = rect.left + rect.width / 2 - tipRect.width / 2;
|
||||
break;
|
||||
case 'bottom':
|
||||
top = rect.bottom + offset;
|
||||
left = rect.left + rect.width / 2 - tipRect.width / 2;
|
||||
break;
|
||||
case 'left':
|
||||
top = rect.top + rect.height / 2 - tipRect.height / 2;
|
||||
left = rect.left - tipRect.width - offset;
|
||||
break;
|
||||
case 'right':
|
||||
top = rect.top + rect.height / 2 - tipRect.height / 2;
|
||||
left = rect.right + offset;
|
||||
break;
|
||||
}
|
||||
tipEl.css({ top: top, left: left });
|
||||
};
|
||||
|
||||
Tip.prototype.hide = function() {
|
||||
if (this.tipEl) {
|
||||
this.tipEl.remove();
|
||||
this.tipEl = null;
|
||||
}
|
||||
};
|
||||
|
||||
Tip.prototype.mouseenter = function() {
|
||||
var that = this;
|
||||
if (this.showTimeout) {
|
||||
|
@ -21,39 +64,7 @@ Tip.prototype.mouseenter = function() {
|
|||
}
|
||||
this.showTimeout = setTimeout(function() {
|
||||
that.showTimeout = null;
|
||||
if (that.tipEl) {
|
||||
that.tipEl.remove();
|
||||
if (that.hideTimeout) {
|
||||
clearTimeout(that.hideTimeout);
|
||||
that.hideTimeout = null;
|
||||
}
|
||||
}
|
||||
var tipEl = that.tipEl = $('<div></div>').addClass('tip').appendTo('body').html(that.title);
|
||||
var rect = that.el[0].getBoundingClientRect(),
|
||||
tipRect = that.tipEl[0].getBoundingClientRect();
|
||||
var placement = that.el.attr('tip-placement') || that.getAutoPlacement(rect, tipRect);
|
||||
tipEl.addClass('tip--' + placement);
|
||||
var top, left;
|
||||
var offset = 10;
|
||||
switch (placement) {
|
||||
case 'top':
|
||||
top = rect.top - tipRect.height - offset;
|
||||
left = rect.left + rect.width / 2 - tipRect.width / 2;
|
||||
break;
|
||||
case 'bottom':
|
||||
top = rect.bottom + offset;
|
||||
left = rect.left + rect.width / 2 - tipRect.width / 2;
|
||||
break;
|
||||
case 'left':
|
||||
top = rect.top + rect.height / 2 - tipRect.height / 2;
|
||||
left = rect.left - tipRect.width - offset;
|
||||
break;
|
||||
case 'right':
|
||||
top = rect.top + rect.height / 2 - tipRect.height / 2;
|
||||
left = rect.right + offset;
|
||||
break;
|
||||
}
|
||||
tipEl.css({ top: top, left: left });
|
||||
that.show();
|
||||
}, 200);
|
||||
};
|
||||
|
||||
|
@ -63,10 +74,7 @@ Tip.prototype.mouseleave = function() {
|
|||
that.tipEl.addClass('tip--hide');
|
||||
this.hideTimeout = setTimeout(function () {
|
||||
that.hideTimeout = null;
|
||||
if (that.tipEl) {
|
||||
that.tipEl.remove();
|
||||
that.tipEl = null;
|
||||
}
|
||||
that.hide();
|
||||
}, 500);
|
||||
}
|
||||
if (this.showTimeout) {
|
||||
|
@ -104,7 +112,9 @@ Tip.prototype.getAutoPlacement = function(rect, tipRect) {
|
|||
Tip.createTips = function(container) {
|
||||
container.find('[title]').each(function(ix, el) {
|
||||
if (!el._tip) {
|
||||
el._tip = new Tip($(el));
|
||||
var tip = new Tip($(el));
|
||||
tip.init();
|
||||
el._tip = tip;
|
||||
}
|
||||
});
|
||||
};
|
||||
|
|
|
@ -20,6 +20,7 @@ var Backbone = require('backbone'),
|
|||
Format = require('../../util/format'),
|
||||
Locale = require('../../util/locale'),
|
||||
Tip = require('../../util/tip'),
|
||||
Timeouts = require('../../const/timeouts'),
|
||||
FileSaver = require('filesaver'),
|
||||
baron = require('baron'),
|
||||
kdbxweb = require('kdbxweb');
|
||||
|
@ -31,6 +32,8 @@ var DetailsView = Backbone.View.extend({
|
|||
|
||||
fieldViews: null,
|
||||
views: null,
|
||||
passEditView: null,
|
||||
passCopyTip: null,
|
||||
|
||||
events: {
|
||||
'click .details__colors-popup-item': 'selectColor',
|
||||
|
@ -67,6 +70,10 @@ var DetailsView = Backbone.View.extend({
|
|||
removeFieldViews: function() {
|
||||
this.fieldViews.forEach(function(fieldView) { fieldView.remove(); });
|
||||
this.fieldViews = [];
|
||||
if (this.passCopyTip) {
|
||||
this.passCopyTip.hide();
|
||||
this.passCopyTip = null;
|
||||
}
|
||||
},
|
||||
|
||||
render: function () {
|
||||
|
@ -111,8 +118,9 @@ var DetailsView = Backbone.View.extend({
|
|||
var model = this.model;
|
||||
this.fieldViews.push(new FieldViewText({ model: { name: '$UserName', title: Locale.detUser,
|
||||
value: function() { return model.user; } } }));
|
||||
this.fieldViews.push(new FieldViewText({ model: { name: '$Password', title: Locale.detPassword, canGen: true,
|
||||
value: function() { return model.password; } } }));
|
||||
this.passEditView = new FieldViewText({ model: { name: '$Password', title: Locale.detPassword, canGen: true,
|
||||
value: function() { return model.password; } } });
|
||||
this.fieldViews.push(this.passEditView);
|
||||
this.fieldViews.push(new FieldViewUrl({ model: { name: '$URL', title: Locale.detWebsite,
|
||||
value: function() { return model.url; } } }));
|
||||
this.fieldViews.push(new FieldViewText({ model: { name: '$Notes', title: Locale.detNotes, multiline: 'true',
|
||||
|
@ -273,7 +281,20 @@ var DetailsView = Backbone.View.extend({
|
|||
var pw = this.model.password;
|
||||
var password = pw.getText ? pw.getText() : pw;
|
||||
CopyPaste.createHiddenInput(password);
|
||||
CopyPaste.copied();
|
||||
var clipboardTime = CopyPaste.copied();
|
||||
if (!this.passCopyTip) {
|
||||
var passLabel = this.passEditView.labelEl;
|
||||
var msg = clipboardTime ? Locale.detPassCopiedTime.replace('{}', clipboardTime)
|
||||
: Locale.detPassCopied;
|
||||
var tip = new Tip(passLabel, { title: msg, placement: 'right' });
|
||||
this.passCopyTip = tip;
|
||||
tip.show();
|
||||
var that = this;
|
||||
setTimeout(function() {
|
||||
tip.hide();
|
||||
that.passCopyTip = null;
|
||||
}, Timeouts.CopyTip);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
|
|
|
@ -4,6 +4,7 @@ Release notes
|
|||
Improvements
|
||||
`+` more reliable binaries management
|
||||
`+` string resources globalization
|
||||
`+` #50: notification on password copy
|
||||
`-` #74: select all in search field
|
||||
|
||||
##### v0.5.1 (2015-12-15)
|
||||
|
|
Loading…
Reference in New Issue