file dirty flag; further sync refactorint

This commit is contained in:
Antelle 2015-12-11 20:50:44 +03:00
parent a28067055d
commit 58aaec9938
4 changed files with 58 additions and 51 deletions

View File

@ -0,0 +1,7 @@
'use strict';
var Timeouts = {
AutoSync: 15000
};
module.exports = Timeouts;

View File

@ -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);
});
}

View File

@ -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
});

View File

@ -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();
}
},