diff --git a/.idea/encodings.xml b/.idea/encodings.xml
new file mode 100644
index 00000000..97626ba4
--- /dev/null
+++ b/.idea/encodings.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/scripts/comp/dropbox-link.js b/app/scripts/comp/dropbox-link.js
index d26d8698..82ec252d 100644
--- a/app/scripts/comp/dropbox-link.js
+++ b/app/scripts/comp/dropbox-link.js
@@ -121,6 +121,7 @@ DropboxChooser.prototype.readFile = function(url) {
};
var DropboxLink = {
+ ERROR_CONFLICT: Dropbox.ApiError.CONFLICT,
_getClient: function(complete) {
if (this._dropboxClient && this._dropboxClient.isAuthenticated()) {
complete(null, this._dropboxClient);
@@ -199,6 +200,8 @@ var DropboxLink = {
body: 'Something went wrong during Dropbox sync. Please, try again later. Error code: ' + err.status
});
break;
+ case Dropbox.ApiError.CONFLICT:
+ break;
default:
alertCallback({
header: 'Dropbox Sync Error',
@@ -241,7 +244,7 @@ var DropboxLink = {
saveFile: function(fileName, data, rev, complete) {
if (rev) {
- var opts = typeof rev === 'string' ? { lastVersionTag: rev } : undefined;
+ var opts = typeof rev === 'string' ? { lastVersionTag: rev, noOverwrite: true, noAutoRename: true } : undefined;
this._callAndHandleError('writeFile', [fileName, data, opts], complete);
} else {
this.getFileList((function(err, files) {
diff --git a/app/scripts/models/app-model.js b/app/scripts/models/app-model.js
index 1b0d07ee..c900e8b4 100644
--- a/app/scripts/models/app-model.js
+++ b/app/scripts/models/app-model.js
@@ -322,7 +322,10 @@ var AppModel = Backbone.Model.extend({
file.setLocalEditState(fileInfo.get('editState'));
}
file.set('modified', true);
- setTimeout(this.syncFile.bind(this, file), 0);
+ setTimeout(that.syncFile.bind(that, file), 0);
+ }
+ if (fileInfo) {
+ file.set('syncDate', fileInfo.get('syncDate'));
}
var cacheId = fileInfo && fileInfo.id || IdGenerator.uuid();
if (updateCacheOnSuccess && params.storage !== 'file') {
@@ -350,7 +353,7 @@ var AppModel = Backbone.Model.extend({
modified: file.get('modified'),
editState: file.getLocalEditState(),
rev: rev,
- pullDate: dt,
+ syncDate: file.get('syncDate') || dt,
openDate: dt
});
this.fileInfos.remove(id);
@@ -365,6 +368,10 @@ var AppModel = Backbone.Model.extend({
},
syncFile: function(file, options, callback) {
+ var that = this;
+ if (file.get('demo')) {
+ return callback && callback();
+ }
if (file.get('syncing')) {
return callback && callback('Sync in progress');
}
@@ -382,12 +389,13 @@ var AppModel = Backbone.Model.extend({
modified: file.get('modified'),
editState: null,
rev: null,
- pullDate: dt,
+ syncDate: dt,
openDate: dt
});
}
- var storage = Storage[options.storage || file.get('storage')];
+ var storage = options.storage || file.get('storage');
var path = options.path || file.get('path');
+ file.setSyncProgress();
var complete = function(err, savedToCache) {
if (!err) { savedToCache = true; }
file.setSyncComplete(path, storage, err ? err.toString() : null, savedToCache);
@@ -395,12 +403,13 @@ var AppModel = Backbone.Model.extend({
storage: storage,
path: path,
modified: file.get('modified'),
- editState: file.getLocalEditState()
+ editState: file.getLocalEditState(),
+ syncDate: file.get('syncDate')
});
- if (!this.fileInfos.get(id)) {
- this.fileInfos.unshift(fileInfo);
+ if (!that.fileInfos.get(fileInfo.id)) {
+ that.fileInfos.unshift(fileInfo);
}
- this.fileInfos.save();
+ that.fileInfos.save();
if (callback) { callback(err); }
};
if (!storage) {
@@ -419,16 +428,22 @@ var AppModel = Backbone.Model.extend({
if (++loadLoops === maxLoadLoops) {
return complete('Too many load attempts, please try again later');
}
- storage.load(path, function(err, data, stat) {
+ Storage[storage].load(path, function(err, data, stat) {
if (err) { return complete(err); }
file.mergeOrUpdate(data, function(err) {
if (err) { return complete(err); }
if (stat && stat.rev) {
fileInfo.set('rev', stat.rev);
}
- fileInfo.set('pullDate', new Date());
+ file.set('syncDate', new Date());
if (file.get('modified')) {
saveToCacheAndStorage();
+ } else if (file.get('dirty') && storage !== 'file') {
+ Storage.cache.save(fileInfo.id, data, function (err) {
+ if (err) { return complete(err); }
+ file.set('dirty', false);
+ complete();
+ });
} else {
complete();
}
@@ -438,7 +453,7 @@ var AppModel = Backbone.Model.extend({
var saveToCacheAndStorage = function() {
file.getData(function(data, err) {
if (err) { return complete(err); }
- if (!file.get('dirty') || storage === Storage.file) {
+ if (!file.get('dirty') || storage === 'file') {
saveToStorage(data);
} else {
Storage.cache.save(fileInfo.id, data, function (err) {
@@ -450,31 +465,40 @@ var AppModel = Backbone.Model.extend({
});
};
var saveToStorage = function(data) {
- storage.save(path, data, function(err) {
+ Storage[storage].save(path, data, function(err) {
if (err && err.revConflict) {
loadFromStorageAndMerge();
} else if (err) {
complete(err);
} else {
- if (storage === Storage.file) {
+ if (storage === 'file') {
Storage.cache.remove(fileInfo.id);
}
+ file.set('syncDate', new Date());
complete();
}
}, fileInfo.get('rev'));
};
if (options.reload) {
loadFromStorageAndMerge();
- } else if (storage === Storage.file) {
+ } else if (storage === 'file') {
if (file.get('modified')) {
saveToCacheAndStorage();
} else {
complete();
}
} else {
- storage.stat(path, function (err, stat) {
+ Storage[storage].stat(path, function (err, stat) {
+ if (err) {
+ // TODO: save to cache if storage save failed
+ return complete(err);
+ }
if (stat.rev === fileInfo.get('rev')) {
- saveToCacheAndStorage();
+ if (file.get('modified')) {
+ saveToCacheAndStorage();
+ } else {
+ complete();
+ }
} else {
loadFromStorageAndMerge();
}
diff --git a/app/scripts/models/file-info-model.js b/app/scripts/models/file-info-model.js
index 4b75d5d6..9ef05483 100644
--- a/app/scripts/models/file-info-model.js
+++ b/app/scripts/models/file-info-model.js
@@ -11,7 +11,7 @@ var FileInfoModel = Backbone.Model.extend({
modified: false,
editState: null,
rev: null,
- pullDate: null,
+ syncDate: null,
openDate: null
},
diff --git a/app/scripts/models/file-model.js b/app/scripts/models/file-model.js
index f25f56bb..01c94b55 100644
--- a/app/scripts/models/file-model.js
+++ b/app/scripts/models/file-model.js
@@ -26,7 +26,8 @@ var FileModel = Backbone.Model.extend({
passwordChanged: false,
keyFileChanged: false,
syncing: false,
- syncError: null
+ syncError: null,
+ syncDate: null
},
db: null,
diff --git a/app/scripts/storage/storage-dropbox.js b/app/scripts/storage/storage-dropbox.js
index 5ad01695..2009c81b 100644
--- a/app/scripts/storage/storage-dropbox.js
+++ b/app/scripts/storage/storage-dropbox.js
@@ -19,7 +19,13 @@ var StorageDropbox = {
},
save: function(path, data, callback, rev) {
- DropboxLink.saveFile(path, data, rev, callback || _.noop);
+ DropboxLink.saveFile(path, data, rev, function(err) {
+ if (!callback) { return; }
+ if (err && err.status === DropboxLink.ERROR_CONFLICT) {
+ err = { revConflict: true };
+ }
+ callback(err);
+ });
}
};
diff --git a/app/scripts/views/app-view.js b/app/scripts/views/app-view.js
index f1d6c8bb..b32eccdc 100644
--- a/app/scripts/views/app-view.js
+++ b/app/scripts/views/app-view.js
@@ -323,7 +323,7 @@ var AppView = Backbone.View.extend({
}
},
- saveAndLock: function(autoInit) {
+ saveAndLock: function(/*autoInit*/) {
var pendingCallbacks = 0,
errorFiles = [],
that = this;
diff --git a/app/scripts/views/settings/settings-file-view.js b/app/scripts/views/settings/settings-file-view.js
index a0296bcf..3bb212eb 100644
--- a/app/scripts/views/settings/settings-file-view.js
+++ b/app/scripts/views/settings/settings-file-view.js
@@ -183,7 +183,7 @@ var SettingsAboutView = Backbone.View.extend({
that.render();
return;
}
- this.save({ storage: 'dropbox' });
+ that.save({ storage: 'dropbox' });
});
},
diff --git a/bower.json b/bower.json
index 67fee6b0..c9956bbd 100644
--- a/bower.json
+++ b/bower.json
@@ -26,7 +26,7 @@
"backbone": "~1.2.3",
"baron": "~1.0.1",
"bourbon": "~4.2.5",
- "dropbox": "antelle/dropbox-js#0.10.5",
+ "dropbox": "antelle/dropbox-js#0.10.6",
"font-awesome": "~4.4.0",
"install": "~1.0.4",
"kdbxweb": "~0.3.1",
diff --git a/keeweb.iml b/keeweb.iml
index 785b6491..0892b3c4 100644
--- a/keeweb.iml
+++ b/keeweb.iml
@@ -10,6 +10,5 @@
-
\ No newline at end of file