mirror of https://github.com/keeweb/keeweb.git
file dirty flag; further sync refactorint
This commit is contained in:
parent
a28067055d
commit
58aaec9938
|
@ -0,0 +1,7 @@
|
|||
'use strict';
|
||||
|
||||
var Timeouts = {
|
||||
AutoSync: 15000
|
||||
};
|
||||
|
||||
module.exports = Timeouts;
|
|
@ -321,7 +321,8 @@ var AppModel = Backbone.Model.extend({
|
|||
if (fileInfo.get('editState')) {
|
||||
file.setLocalEditState(fileInfo.get('editState'));
|
||||
}
|
||||
file.setModified();
|
||||
file.set('modified', true);
|
||||
setTimeout(this.syncFile.bind(this, file), 0);
|
||||
}
|
||||
var cacheId = fileInfo && fileInfo.id || IdGenerator.uuid();
|
||||
if (updateCacheOnSuccess && params.storage !== 'file') {
|
||||
|
@ -365,12 +366,11 @@ var AppModel = Backbone.Model.extend({
|
|||
|
||||
syncFile: function(file, options, callback) {
|
||||
if (file.get('syncing')) {
|
||||
return callback('Sync in progress');
|
||||
return callback && callback('Sync in progress');
|
||||
}
|
||||
if (!options) {
|
||||
options = {};
|
||||
}
|
||||
var complete = function(err) {
|
||||
// TODO: save file info
|
||||
callback(err);
|
||||
};
|
||||
var fileInfo = this.fileInfos.getMatch(file.get('storage'), file.get('name'), file.get('path'));
|
||||
if (!fileInfo) {
|
||||
var dt = new Date();
|
||||
|
@ -388,6 +388,21 @@ var AppModel = Backbone.Model.extend({
|
|||
}
|
||||
var storage = Storage[options.storage || file.get('storage')];
|
||||
var path = options.path || file.get('path');
|
||||
var complete = function(err, savedToCache) {
|
||||
if (!err) { savedToCache = true; }
|
||||
file.setSyncComplete(path, storage, err ? err.toString() : null, savedToCache);
|
||||
fileInfo.set({
|
||||
storage: storage,
|
||||
path: path,
|
||||
modified: file.get('modified'),
|
||||
editState: file.getLocalEditState()
|
||||
});
|
||||
if (!this.fileInfos.get(id)) {
|
||||
this.fileInfos.unshift(fileInfo);
|
||||
}
|
||||
this.fileInfos.save();
|
||||
if (callback) { callback(err); }
|
||||
};
|
||||
if (!storage) {
|
||||
if (!file.get('modified')) {
|
||||
return complete();
|
||||
|
@ -411,6 +426,7 @@ var AppModel = Backbone.Model.extend({
|
|||
if (stat && stat.rev) {
|
||||
fileInfo.set('rev', stat.rev);
|
||||
}
|
||||
fileInfo.set('pullDate', new Date());
|
||||
if (file.get('modified')) {
|
||||
saveToCacheAndStorage();
|
||||
} else {
|
||||
|
@ -422,11 +438,12 @@ var AppModel = Backbone.Model.extend({
|
|||
var saveToCacheAndStorage = function() {
|
||||
file.getData(function(data, err) {
|
||||
if (err) { return complete(err); }
|
||||
if (storage === Storage.file) {
|
||||
if (!file.get('dirty') || storage === Storage.file) {
|
||||
saveToStorage(data);
|
||||
} else {
|
||||
Storage.cache.save(fileInfo.id, data, function (err) {
|
||||
if (err) { return complete(err); }
|
||||
file.set('dirty', false);
|
||||
saveToStorage(data);
|
||||
});
|
||||
}
|
||||
|
|
|
@ -16,6 +16,7 @@ var FileModel = Backbone.Model.extend({
|
|||
path: '',
|
||||
storage: null,
|
||||
modified: false,
|
||||
dirty: false,
|
||||
open: false,
|
||||
created: false,
|
||||
demo: false,
|
||||
|
@ -164,6 +165,7 @@ var FileModel = Backbone.Model.extend({
|
|||
if (this.get('modified')) {
|
||||
try {
|
||||
this.db.merge(remoteDb);
|
||||
this.set('dirty', true);
|
||||
} catch (e) {
|
||||
console.error('File merge error', e);
|
||||
return callback(e);
|
||||
|
@ -185,15 +187,12 @@ var FileModel = Backbone.Model.extend({
|
|||
this.db.setLocalEditState(editState);
|
||||
},
|
||||
|
||||
removeLocalEditState: function() {
|
||||
this.db.removeLocalEditState();
|
||||
},
|
||||
|
||||
close: function() {
|
||||
this.set({
|
||||
keyFileName: '',
|
||||
passwordLength: 0,
|
||||
modified: false,
|
||||
dirty: false,
|
||||
open: false,
|
||||
created: false,
|
||||
groups: null,
|
||||
|
@ -244,7 +243,7 @@ var FileModel = Backbone.Model.extend({
|
|||
|
||||
setModified: function() {
|
||||
if (!this.get('demo')) {
|
||||
this.set('modified', true);
|
||||
this.set({ modified: true, dirty: true });
|
||||
}
|
||||
},
|
||||
|
||||
|
@ -270,13 +269,18 @@ var FileModel = Backbone.Model.extend({
|
|||
this.set({ syncing: true });
|
||||
},
|
||||
|
||||
setSyncComplete: function(path, storage, error) {
|
||||
setSyncComplete: function(path, storage, error, savedToCache) {
|
||||
if (!error) {
|
||||
this.db.removeLocalEditState();
|
||||
}
|
||||
var modified = this.get('modified') && !!error;
|
||||
var dirty = this.get('dirty') && !savedToCache;
|
||||
this.set({
|
||||
created: false,
|
||||
path: path || this.get('path'),
|
||||
storage: storage || this.get('storage'),
|
||||
modified: modified,
|
||||
dirty: dirty,
|
||||
syncing: false,
|
||||
syncError: error
|
||||
});
|
||||
|
|
|
@ -12,6 +12,7 @@ var Backbone = require('backbone'),
|
|||
SettingsView = require('../views/settings/settings-view'),
|
||||
Alerts = require('../comp/alerts'),
|
||||
Keys = require('../const/keys'),
|
||||
Timeouts = require('../const/timeouts'),
|
||||
KeyHandler = require('../comp/key-handler'),
|
||||
IdleTracker = require('../comp/idle-tracker'),
|
||||
Launcher = require('../comp/launcher'),
|
||||
|
@ -73,6 +74,8 @@ var AppView = Backbone.View.extend({
|
|||
|
||||
KeyHandler.onKey(Keys.DOM_VK_ESCAPE, this.escPressed, this);
|
||||
KeyHandler.onKey(Keys.DOM_VK_BACK_SPACE, this.backspacePressed, this);
|
||||
|
||||
setInterval(this.syncAllByTimer.bind(this), Timeouts.AutoSync);
|
||||
},
|
||||
|
||||
render: function () {
|
||||
|
@ -291,20 +294,18 @@ var AppView = Backbone.View.extend({
|
|||
if (this.model.settings.get('autoSave')) {
|
||||
this.saveAndLock(autoInit);
|
||||
} else {
|
||||
if (autoInit) {
|
||||
this.showVisualLock('Auto-save is disabled. Please, enable it, to allow auto-locking');
|
||||
return;
|
||||
}
|
||||
var message = autoInit ? 'The app cannot be locked because auto save is disabled.'
|
||||
: 'You have unsaved changes that will be lost. Continue?';
|
||||
Alerts.alert({
|
||||
icon: 'lock',
|
||||
header: 'Lock',
|
||||
body: 'You have unsaved changes that will be lost. Continue?',
|
||||
body: message,
|
||||
buttons: [
|
||||
{ result: 'save', title: 'Save changes' },
|
||||
{ result: 'discard', title: 'Discard changes', error: true },
|
||||
{ result: '', title: 'Cancel' }
|
||||
],
|
||||
checkbox: 'Auto save changes each time I lock the app',
|
||||
checkbox: 'Save changes automatically',
|
||||
success: function(result, autoSaveChecked) {
|
||||
if (result === 'save') {
|
||||
if (autoSaveChecked) {
|
||||
|
@ -323,27 +324,14 @@ var AppView = Backbone.View.extend({
|
|||
},
|
||||
|
||||
saveAndLock: function(autoInit) {
|
||||
// TODO: move to file manager
|
||||
var pendingCallbacks = 0,
|
||||
errorFiles = [],
|
||||
that = this;
|
||||
if (this.model.files.some(function(file) { return file.get('modified') && !file.get('path'); })) {
|
||||
this.showVisualLock('You have unsaved files, locking is not possible.');
|
||||
return;
|
||||
}
|
||||
this.model.files.forEach(function(file) {
|
||||
if (!file.get('modified')) {
|
||||
if (!file.get('dirty')) {
|
||||
return;
|
||||
}
|
||||
if (file.get('path')) {
|
||||
try {
|
||||
file.autoSave(fileSaved.bind(this, file));
|
||||
pendingCallbacks++;
|
||||
} catch (e) {
|
||||
console.error('Failed to auto-save file', file.get('path'), e);
|
||||
errorFiles.push(file);
|
||||
}
|
||||
}
|
||||
this.model.syncFile(file, null, fileSaved.bind(this, file));
|
||||
}, this);
|
||||
if (!pendingCallbacks) {
|
||||
this.closeAllFilesAndShowFirst();
|
||||
|
@ -354,9 +342,7 @@ var AppView = Backbone.View.extend({
|
|||
}
|
||||
if (--pendingCallbacks === 0) {
|
||||
if (errorFiles.length) {
|
||||
if (autoInit) {
|
||||
that.showVisualLock('Failed to save files: ' + errorFiles.join(', '));
|
||||
} else if (!Alerts.alertDisplayed) {
|
||||
if (!Alerts.alertDisplayed) {
|
||||
Alerts.error({
|
||||
header: 'Save Error',
|
||||
body: 'Failed to auto-save file' + (errorFiles.length > 1 ? 's: ' : '') + ' ' + errorFiles.join(', ')
|
||||
|
@ -381,21 +367,14 @@ var AppView = Backbone.View.extend({
|
|||
},
|
||||
|
||||
saveAll: function() {
|
||||
var fileId;
|
||||
this.model.files.forEach(function(file) {
|
||||
if (file.get('path')) {
|
||||
try {
|
||||
file.autoSave();
|
||||
} catch (e) {
|
||||
console.error('Failed to auto-save file', file.get('path'), e);
|
||||
fileId = file.cid;
|
||||
}
|
||||
} else if (!fileId) {
|
||||
fileId = file.cid;
|
||||
}
|
||||
});
|
||||
if (fileId) {
|
||||
this.showFileSettings({fileId: fileId});
|
||||
this.model.syncFile(file);
|
||||
}, this);
|
||||
},
|
||||
|
||||
syncAllByTimer: function() {
|
||||
if (this.model.settings.get('autoSave')) {
|
||||
this.saveAll();
|
||||
}
|
||||
},
|
||||
|
||||
|
|
Loading…
Reference in New Issue