Merge branch 'release-1.12'

This commit is contained in:
antelle 2019-11-03 12:26:29 +01:00
commit 5d5913233b
15 changed files with 91 additions and 72 deletions

View File

@ -12,7 +12,7 @@ Timeline: [Release Notes](release-notes.md), [TODO](https://github.com/keeweb/ke
On one page: [Features](https://keeweb.info/#features), [FAQ](https://github.com/keeweb/keeweb/wiki/FAQ) On one page: [Features](https://keeweb.info/#features), [FAQ](https://github.com/keeweb/keeweb/wiki/FAQ)
Website: [keeweb.info](https://keeweb.info) Website: [keeweb.info](https://keeweb.info)
Twitter: [kee_web](https://twitter.com/kee_web) Twitter: [kee_web](https://twitter.com/kee_web)
Donate: [OpenCollective](https://opencollective.com/keeweb#support) Donate: [OpenCollective](https://opencollective.com/keeweb#support), [GitHub](https://github.com/sponsors/antelle)
# Status # Status
@ -71,6 +71,8 @@ KeeWeb is not free to develop. It takes time, requires paid code signing certifi
You can help the project or say "thank you" with this button: You can help the project or say "thank you" with this button:
[<img src="https://opencollective.com/keeweb/tiers/backer.svg?avatarHeight=42&width=880" alt="OpenCollective">](https://opencollective.com/keeweb#support) [<img src="https://opencollective.com/keeweb/tiers/backer.svg?avatarHeight=42&width=880" alt="OpenCollective">](https://opencollective.com/keeweb#support)
You can also sponsor the developer directly [on GitHub](https://github.com/sponsors/antelle).
Please note: donation does not imply any type of service contract. Please note: donation does not imply any type of service contract.

View File

@ -1,4 +1,4 @@
import { EntryCollection } from 'collections/entry-collection'; import { SearchResultCollection } from 'collections/search-result-collection';
import { Ranking } from 'util/data/ranking'; import { Ranking } from 'util/data/ranking';
const urlPartsRegex = /^(\w+:\/\/)?(?:(?:www|wwws|secure)\.)?([^\/]+)\/?(.*)/; const urlPartsRegex = /^(\w+:\/\/)?(?:(?:www|wwws|secure)\.)?([^\/]+)\/?(.*)/;
@ -25,7 +25,7 @@ AutoTypeFilter.prototype.getEntries = function() {
x[1] === y[1] ? x[0].title.localeCompare(y[0].title) : y[1] - x[1] x[1] === y[1] ? x[0].title.localeCompare(y[0].title) : y[1] - x[1]
); );
entries = entries.map(p => p[0]); entries = entries.map(p => p[0]);
return new EntryCollection(entries, { comparator: 'none' }); return new SearchResultCollection(entries, { comparator: 'none' });
}; };
AutoTypeFilter.prototype.hasWindowInfo = function() { AutoTypeFilter.prototype.hasWindowInfo = function() {

View File

@ -1,52 +1,8 @@
import { Collection } from 'framework/collection'; import { Collection } from 'framework/collection';
import { EntryModel } from 'models/entry-model'; import { EntryModel } from 'models/entry-model';
import { Comparators } from 'util/data/comparators';
class EntryCollection extends Collection { class EntryCollection extends Collection {
static model = EntryModel; static model = EntryModel;
comparators = {
'none': null,
'title': Comparators.stringComparator('title', true),
'-title': Comparators.stringComparator('title', false),
'website': Comparators.stringComparator('url', true),
'-website': Comparators.stringComparator('url', false),
'user': Comparators.stringComparator('user', true),
'-user': Comparators.stringComparator('user', false),
'created': Comparators.dateComparator('created', true),
'-created': Comparators.dateComparator('created', false),
'updated': Comparators.dateComparator('updated', true),
'-updated': Comparators.dateComparator('updated', false),
'-attachments': (x, y) => {
return this.attachmentSortVal(x).localeCompare(this.attachmentSortVal(y));
},
'-rank': Comparators.rankComparator().bind(this)
};
defaultComparator = 'title';
entryFilter = null;
constructor(models, options) {
super(models);
const comparatorName = (options && options.comparator) || this.defaultComparator;
this.comparator = this.comparators[comparatorName];
}
sortEntries(comparator, filter) {
this.entryFilter = filter;
this.comparator = this.comparators[comparator] || this.comparators[this.defaultComparator];
this.sort();
}
attachmentSortVal(entry) {
const att = entry.attachments;
let str = att.length ? String.fromCharCode(64 + att.length) : 'Z';
if (att[0]) {
str += att[0].title;
}
return str;
}
} }
export { EntryCollection }; export { EntryCollection };

View File

@ -0,0 +1,52 @@
import { Collection } from 'framework/collection';
import { Model } from 'framework/model';
import { Comparators } from 'util/data/comparators';
class SearchResultCollection extends Collection {
static model = Model;
comparators = {
'none': null,
'title': Comparators.stringComparator('title', true),
'-title': Comparators.stringComparator('title', false),
'website': Comparators.stringComparator('url', true),
'-website': Comparators.stringComparator('url', false),
'user': Comparators.stringComparator('user', true),
'-user': Comparators.stringComparator('user', false),
'created': Comparators.dateComparator('created', true),
'-created': Comparators.dateComparator('created', false),
'updated': Comparators.dateComparator('updated', true),
'-updated': Comparators.dateComparator('updated', false),
'-attachments': (x, y) => {
return this.attachmentSortVal(x).localeCompare(this.attachmentSortVal(y));
},
'-rank': Comparators.rankComparator().bind(this)
};
defaultComparator = 'title';
entryFilter = null;
constructor(models, options) {
super(models);
const comparatorName = (options && options.comparator) || this.defaultComparator;
this.comparator = this.comparators[comparatorName];
}
sortEntries(comparator, filter) {
this.entryFilter = filter;
this.comparator = this.comparators[comparator] || this.comparators[this.defaultComparator];
this.sort();
}
attachmentSortVal(entry) {
const att = entry.attachments;
let str = att.length ? String.fromCharCode(64 + att.length) : 'Z';
if (att[0]) {
str += att[0].title;
}
return str;
}
}
export { SearchResultCollection };

View File

@ -196,7 +196,7 @@ const Launcher = {
resolveProxy(url, callback) { resolveProxy(url, callback) {
const window = this.getMainWindow(); const window = this.getMainWindow();
const session = window.webContents.session; const session = window.webContents.session;
session.resolveProxy(url, proxy => { session.resolveProxy(url).then(proxy => {
const match = /^proxy\s+([\w\.]+):(\d+)+\s*/i.exec(proxy); const match = /^proxy\s+([\w\.]+):(\d+)+\s*/i.exec(proxy);
proxy = match && match[1] ? { host: match[1], port: +match[2] } : null; proxy = match && match[1] ? { host: match[1], port: +match[2] } : null;
callback(proxy); callback(proxy);

View File

@ -1,7 +1,7 @@
import { Events } from 'framework/events'; import { Events } from 'framework/events';
import { AutoType } from 'auto-type'; import { AutoType } from 'auto-type';
import { Storage } from 'storage'; import { Storage } from 'storage';
import { EntryCollection } from 'collections/entry-collection'; import { SearchResultCollection } from 'collections/search-result-collection';
import { FileCollection } from 'collections/file-collection'; import { FileCollection } from 'collections/file-collection';
import { FileInfoCollection } from 'collections/file-info-collection'; import { FileInfoCollection } from 'collections/file-info-collection';
import { RuntimeInfo } from 'comp/app/runtime-info'; import { RuntimeInfo } from 'comp/app/runtime-info';
@ -307,7 +307,7 @@ class AppModel {
getEntriesByFilter(filter) { getEntriesByFilter(filter) {
const preparedFilter = this.prepareFilter(filter); const preparedFilter = this.prepareFilter(filter);
const entries = new EntryCollection(); const entries = new SearchResultCollection();
this.files.forEach(file => { this.files.forEach(file => {
file.forEachEntry(preparedFilter, entry => entries.push(entry)); file.forEachEntry(preparedFilter, entry => entries.push(entry));
}); });

View File

@ -1,18 +1,7 @@
import { Model } from 'framework/model'; import { Model } from 'framework/model';
import { pick } from 'util/fn';
class FileInfoModel extends Model { const DefaultProperties = {
constructor(data) {
data = { ...data };
for (const [key, val] of Object.entries(data)) {
if (/Date$/.test(key)) {
data[key] = val ? new Date(val) : null;
}
}
super(data);
}
}
FileInfoModel.defineModelProperties({
id: '', id: '',
name: '', name: '',
storage: null, storage: null,
@ -28,6 +17,20 @@ FileInfoModel.defineModelProperties({
opts: null, opts: null,
backup: null, backup: null,
fingerprint: null fingerprint: null
}); };
class FileInfoModel extends Model {
constructor(data) {
data = pick({ ...data }, Object.keys(DefaultProperties));
for (const [key, val] of Object.entries(data)) {
if (/Date$/.test(key)) {
data[key] = val ? new Date(val) : null;
}
}
super(data);
}
}
FileInfoModel.defineModelProperties(DefaultProperties);
export { FileInfoModel }; export { FileInfoModel };

View File

@ -193,7 +193,7 @@ class AutoTypeSelectView extends View {
itemClicked(e) { itemClicked(e) {
const itemEl = $(e.target).closest('.at-select__item'); const itemEl = $(e.target).closest('.at-select__item');
const optionsClicked = $(e.target).closest('.at-select__item-options'); const optionsClicked = $(e.target).closest('.at-select__item-options').length;
if (optionsClicked) { if (optionsClicked) {
this.showItemOptions(itemEl, e); this.showItemOptions(itemEl, e);

View File

@ -1,6 +1,6 @@
import { View } from 'framework/views/view'; import { View } from 'framework/views/view';
import { Events } from 'framework/events'; import { Events } from 'framework/events';
import { EntryCollection } from 'collections/entry-collection'; import { SearchResultCollection } from 'collections/search-result-collection';
import { DragDropInfo } from 'comp/app/drag-drop-info'; import { DragDropInfo } from 'comp/app/drag-drop-info';
import { Alerts } from 'comp/ui/alerts'; import { Alerts } from 'comp/ui/alerts';
import { AppSettingsModel } from 'models/app-settings-model'; import { AppSettingsModel } from 'models/app-settings-model';
@ -67,7 +67,7 @@ class ListView extends View {
this.readTableColumnsEnabled(); this.readTableColumnsEnabled();
this.items = new EntryCollection(); this.items = new SearchResultCollection();
} }
render() { render() {

View File

@ -339,7 +339,7 @@ class SettingsGeneralView extends View {
const storage = Storage[$(e.target).data('storage')]; const storage = Storage[$(e.target).data('storage')];
if (storage) { if (storage) {
storage.setEnabled(e.target.checked); storage.setEnabled(e.target.checked);
AppSettingsModel.storage.name = storage.enabled; AppSettingsModel[storage.name] = storage.enabled;
this.$el this.$el
.find('.settings__general-' + storage.name) .find('.settings__general-' + storage.name)
.toggleClass('hide', !e.target.checked); .toggleClass('hide', !e.target.checked);

View File

@ -1,6 +1,6 @@
{ {
"name": "KeeWeb", "name": "KeeWeb",
"version": "1.12.1", "version": "1.12.2",
"lockfileVersion": 1, "lockfileVersion": 1,
"requires": true, "requires": true,
"dependencies": { "dependencies": {

View File

@ -1,6 +1,6 @@
{ {
"name": "KeeWeb", "name": "KeeWeb",
"version": "1.12.1", "version": "1.12.2",
"description": "Free cross-platform password manager compatible with KeePass", "description": "Free cross-platform password manager compatible with KeePass",
"main": "main.js", "main": "main.js",
"homepage": "https://keeweb.info", "homepage": "https://keeweb.info",

2
package-lock.json generated
View File

@ -1,6 +1,6 @@
{ {
"name": "keeweb", "name": "keeweb",
"version": "1.12.1", "version": "1.12.2",
"lockfileVersion": 1, "lockfileVersion": 1,
"requires": true, "requires": true,
"dependencies": { "dependencies": {

View File

@ -1,6 +1,6 @@
{ {
"name": "keeweb", "name": "keeweb",
"version": "1.12.1", "version": "1.12.2",
"description": "Free cross-platform password manager compatible with KeePass", "description": "Free cross-platform password manager compatible with KeePass",
"main": "Gruntfile.js", "main": "Gruntfile.js",
"private": true, "private": true,

View File

@ -1,5 +1,11 @@
Release notes Release notes
------------- -------------
##### v1.12.2 (2019-11-03)
`-` fixed non-working updater
`-` fix #1336: saving disabled storage option
`-` fix #1333: item selection in the auto-type pop-up
`-` fix #1337: displaying groups in trash
##### v1.12.1 (2019-10-27) ##### v1.12.1 (2019-10-27)
`-` fix #1324: duplicated shortcut editor in settings `-` fix #1324: duplicated shortcut editor in settings
`-` fix #1313: disabled code signing for macOS dmg `-` fix #1313: disabled code signing for macOS dmg