more stable reload after db operations

This commit is contained in:
Antelle 2015-12-05 16:04:09 +03:00
parent f11cf25dbe
commit db062cec27
6 changed files with 108 additions and 69 deletions

View File

@ -44,9 +44,18 @@ var AppModel = Backbone.Model.extend({
file: file
});
this.refresh();
this.listenTo(file, 'reload', this.reloadFile);
return true;
},
reloadFile: function(file) {
this.menu.groupsSection.removeByFile(file, true);
file.get('groups').forEach(function (group) {
this.menu.groupsSection.addItem(group);
}, this);
this.updateTags();
},
_addTags: function(group) {
var tagsHash = {};
this.tags.forEach(function(tag) {

View File

@ -16,15 +16,18 @@ var EntryModel = Backbone.Model.extend({
},
setEntry: function(entry, group, file) {
this.set({ id: entry.uuid.id }, {silent: true});
this.entry = entry;
this.group = group;
this.file = file;
if (this.id === entry.uuid.id) {
this._checkUpdatedEntry();
}
this._fillByEntry();
},
_fillByEntry: function() {
var entry = this.entry;
this.set({id: entry.uuid.id}, {silent: true});
this.fileName = this.file.db.meta.name;
this.title = entry.fields.Title || '';
this.password = entry.fields.Password || kdbxweb.ProtectedValue.fromString('');
@ -48,6 +51,15 @@ var EntryModel = Backbone.Model.extend({
this._buildSearchColor();
},
_checkUpdatedEntry: function() {
if (this.isJustCreated) {
this.isJustCreated = false;
}
if (this.unsaved && +this.updated !== +this.entry.times.lastModTime) {
this.unsaved = false;
}
},
_buildSearchText: function() {
var text = '';
_.forEach(this.entry.fields, function(value) {
@ -114,7 +126,8 @@ var EntryModel = Backbone.Model.extend({
},
matches: function(filter) {
return (!filter.tagLower || this.searchTags.indexOf(filter.tagLower) >= 0) &&
return !filter ||
(!filter.tagLower || this.searchTags.indexOf(filter.tagLower) >= 0) &&
(!filter.textLower || this.searchText.indexOf(filter.textLower) >= 0) &&
(!filter.color || filter.color === true && this.searchColor || this.searchColor === filter.color);
},
@ -190,7 +203,7 @@ var EntryModel = Backbone.Model.extend({
deleteHistory: function(historyEntry) {
var ix = this.entry.history.indexOf(historyEntry);
if (ix >= 0) {
this.entry.history.splice(ix, 1);
this.entry.removeHistory(ix);
}
this._fillByEntry();
},
@ -211,9 +224,10 @@ var EntryModel = Backbone.Model.extend({
},
discardUnsaved: function() {
if (this.unsaved) {
if (this.unsaved && this.entry.history.length) {
this.unsaved = false;
var historyEntry = this.entry.history.pop();
var historyEntry = this.entry.history[this.entry.history.length - 1];
this.entry.removeHistory(this.entry.history.length - 1);
this.entry.fields = {};
this.entry.binaries = {};
this.entry.copyFrom(historyEntry);
@ -227,18 +241,13 @@ var EntryModel = Backbone.Model.extend({
this.isJustCreated = false;
}
this.file.db.remove(this.entry);
this.group.removeEntry(this);
var trashGroup = this.file.getTrashGroup();
if (trashGroup) {
trashGroup.addEntry(this);
this.group = trashGroup;
}
this.file.reload();
},
deleteFromTrash: function() {
this.file.setModified();
this.file.db.move(this.entry, null);
this.group.removeEntry(this);
this.file.reload();
},
removeWithoutHistory: function() {
@ -246,7 +255,7 @@ var EntryModel = Backbone.Model.extend({
if (ix >= 0) {
this.group.group.entries.splice(ix, 1);
}
this.group.removeEntry(this);
this.file.reload();
}
});

View File

@ -35,8 +35,12 @@ var FileModel = Backbone.Model.extend({
db: null,
data: null,
entryMap: null,
groupMap: null,
initialize: function() {
this.entryMap = {};
this.groupMap = {};
},
open: function(password, fileData, keyFileData) {
@ -152,13 +156,38 @@ var FileModel = Backbone.Model.extend({
historyMaxSize: this.db.meta.historyMaxSize,
keyEncryptionRounds: this.db.header.keyEncryptionRounds
}, { silent: true });
this.db.groups.forEach(function(group, index) {
var groupModel = GroupModel.fromGroup(group, this);
if (index === 0 && topGroupTitle) {
this.db.groups.forEach(function(group) {
var groupModel = this.getGroup(group.uuid.id);
if (groupModel) {
groupModel.setGroup(group, this);
} else {
groupModel = GroupModel.fromGroup(group, this);
}
if (topGroupTitle) {
groupModel.set({title: topGroupTitle});
}
groups.add(groupModel);
}, this);
this.buildObjectMap();
},
buildObjectMap: function() {
var entryMap = {};
var groupMap = {};
this.forEachGroup(function(group) {
groupMap[group.id] = group;
group.forEachOwnEntry(null, function(entry) {
entryMap[entry.id] = entry;
});
}, true);
this.entryMap = entryMap;
this.groupMap = groupMap;
},
reload: function() {
this.buildObjectMap();
this.readModel(this.get('name'));
this.trigger('reload', this);
},
close: function() {
@ -177,17 +206,12 @@ var FileModel = Backbone.Model.extend({
});
},
getEntry: function(id) {
return this.entryMap[id];
},
getGroup: function(id) {
var found = null;
if (id) {
this.forEachGroup(function (group) {
if (group.get('id') === id) {
found = group;
return false;
}
}, true);
}
return found;
return this.groupMap[id];
},
forEachEntry: function(filter, callback) {

View File

@ -22,28 +22,43 @@ var GroupModel = MenuItemModel.extend({
initialize: function() {
if (!GroupCollection) { GroupCollection = require('../collections/group-collection'); }
if (!EntryCollection) { EntryCollection = require('../collections/entry-collection'); }
this.set('entries', new EntryCollection());
},
setFromGroup: function(group, file) {
setGroup: function(group, file, parentGroup) {
var isRecycleBin = file.db.meta.recycleBinUuid && file.db.meta.recycleBinUuid.id === group.uuid.id;
this.set({
id: group.uuid.id,
expanded: true,
expanded: group.expanded,
visible: !isRecycleBin,
items: new GroupCollection(),
filterValue: group.uuid.id
entries: new EntryCollection(),
filterValue: group.uuid.id,
top: !parentGroup,
drag: !!parentGroup
}, { silent: true });
this.group = group;
this.file = file;
this.parentGroup = parentGroup;
this._fillByGroup(true);
var items = this.get('items'),
entries = this.get('entries');
group.groups.forEach(function(subGroup) {
items.add(GroupModel.fromGroup(subGroup, file, this));
var existing = file.getGroup(subGroup.uuid);
if (existing) {
existing.setGroup(subGroup, file, this);
items.add(existing);
} else {
items.add(GroupModel.fromGroup(subGroup, file, this));
}
}, this);
group.entries.forEach(function(entry) {
entries.add(EntryModel.fromEntry(entry, this, file));
var existing = file.getEntry(entry.uuid);
if (existing) {
existing.setEntry(entry, this, file);
entries.add(existing);
} else {
entries.add(EntryModel.fromEntry(entry, this, file));
}
}, this);
},
@ -102,22 +117,12 @@ var GroupModel = MenuItemModel.extend({
return this.group.groups;
},
removeEntry: function(entry) {
this.get('entries').remove(entry);
},
addEntry: function(entry) {
this.get('entries').add(entry);
},
removeGroup: function(group) {
this.get('items').remove(group);
this.trigger('remove', group);
},
addGroup: function(group) {
this.get('items').add(group);
this.trigger('insert', group);
},
setName: function(name) {
@ -139,21 +144,21 @@ var GroupModel = MenuItemModel.extend({
this._fillByGroup();
},
setExpanded: function(expanded) {
this._groupModified();
this.group.expanded = expanded;
this.set('expanded', expanded);
},
moveToTrash: function() {
this.file.setModified();
this.file.db.remove(this.group);
this.parentGroup.removeGroup(this);
var trashGroup = this.file.getTrashGroup();
if (trashGroup) {
trashGroup.addGroup(this);
this.parentGroup = trashGroup;
}
this.trigger('delete');
this.file.reload();
},
deleteFromTrash: function() {
this.file.db.move(this.group, null);
this.parentGroup.removeGroup(this);
this.file.reload();
},
removeWithoutHistory: function() {
@ -161,8 +166,7 @@ var GroupModel = MenuItemModel.extend({
if (ix >= 0) {
this.parentGroup.group.groups.splice(ix, 1);
}
this.parentGroup.removeGroup(this);
this.trigger('delete');
this.file.reload();
},
moveHere: function(object) {
@ -175,42 +179,32 @@ var GroupModel = MenuItemModel.extend({
return;
}
this.file.db.move(object.group, this.group);
object.parentGroup.removeGroup(object);
object.trigger('delete');
this.addGroup(object);
this.file.reload();
} else if (object instanceof EntryModel) {
if (this.group.entries.indexOf(object.entry) >= 0) {
return;
}
this.file.db.move(object.entry, this.group);
object.group.removeEntry(object);
this.addEntry(object);
object.group = this;
this.file.reload();
}
}
});
GroupModel.fromGroup = function(group, file, parentGroup) {
var model = new GroupModel();
model.setFromGroup(group, file);
if (parentGroup) {
model.parentGroup = parentGroup;
} else {
model.set({ top: true, drag: false }, { silent: true });
}
model.setGroup(group, file, parentGroup);
return model;
};
GroupModel.newGroup = function(group, file) {
var model = new GroupModel();
var grp = file.db.createGroup(group.group);
model.setFromGroup(grp, file);
model.setGroup(grp, file, group);
model.group.times.update();
model.parentGroup = group;
model.unsaved = true;
model.isJustCreated = true;
group.addGroup(model);
file.setModified();
file.reload();
return model;
};

View File

@ -27,7 +27,7 @@ var MenuItemModel = Backbone.Model.extend({
this.trigger('change-items');
},
removeByFile: function(file) {
removeByFile: function(file, skipEvent) {
var items = this.get('items');
var toRemove;
items.each(function(item) {
@ -38,7 +38,9 @@ var MenuItemModel = Backbone.Model.extend({
if (toRemove) {
items.remove(toRemove);
}
this.trigger('change-items');
if (!skipEvent) {
this.trigger('change-items');
}
},
setItems: function(items) {

View File

@ -96,6 +96,7 @@ var MenuItemView = Backbone.View.extend({
changeExpanded: function(model, expanded) {
this.$el.toggleClass('menu__item--collapsed', !expanded);
this.model.setExpanded(expanded);
},
changeCls: function(model, cls) {