mirror of https://github.com/keeweb/keeweb
fixed dropbox sync errors
parent
423e0a0ae6
commit
554794eb12
|
@ -1,6 +1,7 @@
|
|||
'use strict';
|
||||
|
||||
var Dropbox = require('dropbox');
|
||||
var Dropbox = require('dropbox'),
|
||||
Alerts = require('./alerts');
|
||||
|
||||
var DropboxKeys = {
|
||||
AppFolder: 'qp7ctun6qt5n9d6'
|
||||
|
@ -8,7 +9,7 @@ var DropboxKeys = {
|
|||
|
||||
var DropboxLink = {
|
||||
_getClient: function(complete) {
|
||||
if (this._dropboxClient) {
|
||||
if (this._dropboxClient && this._dropboxClient.isAuthenticated()) {
|
||||
complete(null, this._dropboxClient);
|
||||
return;
|
||||
}
|
||||
|
@ -22,41 +23,115 @@ var DropboxLink = {
|
|||
}).bind(this));
|
||||
},
|
||||
|
||||
_handleUiError: function(err, callback) {
|
||||
switch (err.status) {
|
||||
case Dropbox.ApiError.INVALID_TOKEN:
|
||||
Alerts.yesno({
|
||||
icon: 'dropbox',
|
||||
header: 'Dropbox Login',
|
||||
body: 'To continue, you have to sign in to Dropbox.',
|
||||
buttons: [{result: 'yes', title: 'Sign In'}, {result: '', title: 'Cancel'}],
|
||||
success: (function() {
|
||||
this.authenticate(function(err) { callback(!err); });
|
||||
}).bind(this),
|
||||
cancel: function() { callback(false); }
|
||||
});
|
||||
return;
|
||||
case Dropbox.ApiError.NOT_FOUND:
|
||||
Alerts.error({
|
||||
header: 'Dropbox Sync Error',
|
||||
body: 'The file was not found. Has it been removed from another computer?'
|
||||
});
|
||||
break;
|
||||
case Dropbox.ApiError.OVER_QUOTA:
|
||||
Alerts.error({
|
||||
header: 'Dropbox Full',
|
||||
body: 'Your Dropbox is full, there\'s no space left anymore.'
|
||||
});
|
||||
break;
|
||||
case Dropbox.ApiError.RATE_LIMITED:
|
||||
Alerts.error({
|
||||
header: 'Dropbox Sync Error',
|
||||
body: 'Too many requests to Dropbox have been made by this app. Please, try again later.'
|
||||
});
|
||||
break;
|
||||
case Dropbox.ApiError.NETWORK_ERROR:
|
||||
Alerts.error({
|
||||
header: 'Dropbox Sync Network Error',
|
||||
body: 'Network error occured during Dropbox sync. Please, check your connection and try again.'
|
||||
});
|
||||
break;
|
||||
case Dropbox.ApiError.INVALID_PARAM:
|
||||
case Dropbox.ApiError.OAUTH_ERROR:
|
||||
case Dropbox.ApiError.INVALID_METHOD:
|
||||
Alerts.error({
|
||||
header: 'Dropbox Sync Error',
|
||||
body: 'Something went wrong during Dropbox sync. Please, try again later. Error code: ' + err.status
|
||||
});
|
||||
break;
|
||||
default:
|
||||
Alerts.error({
|
||||
header: 'Dropbox Sync Error',
|
||||
body: 'Something went wrong during Dropbox sync. Please, try again later. Error: ' + err
|
||||
});
|
||||
break;
|
||||
}
|
||||
callback(false);
|
||||
},
|
||||
|
||||
_callAndHandleError: function(callName, args, callback) {
|
||||
var that = this;
|
||||
this._getClient(function(err, client) {
|
||||
if (err) {
|
||||
return callback(err);
|
||||
}
|
||||
client[callName].apply(client, args.concat(function(err, res) {
|
||||
if (err) {
|
||||
that._handleUiError(err, function(repeat) {
|
||||
if (repeat) {
|
||||
that._callAndHandleError(callName, args, callback);
|
||||
} else {
|
||||
callback(err);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
callback(err, res);
|
||||
}
|
||||
}));
|
||||
});
|
||||
},
|
||||
|
||||
authenticate: function(copmlete) {
|
||||
this._getClient(function(err) { copmlete(err); });
|
||||
},
|
||||
|
||||
receive: function() {
|
||||
Dropbox.AuthDriver.Popup.oauthReceiver();
|
||||
},
|
||||
|
||||
saveFile: function(fileName, data, overwrite, complete) {
|
||||
this._getClient(function(err, client) {
|
||||
if (err) { return complete(err); }
|
||||
if (!overwrite) {
|
||||
client.readdir('', function(err, files) {
|
||||
if (err) { return complete(err); }
|
||||
var exists = files.some(function(file) { return file.toLowerCase() === fileName.toLowerCase(); });
|
||||
if (exists) { return complete({ exists: true }); }
|
||||
client.writeFile(fileName, data, complete);
|
||||
});
|
||||
} else {
|
||||
client.writeFile(fileName, data, complete);
|
||||
}
|
||||
});
|
||||
if (overwrite) {
|
||||
this._callAndHandleError('writeFile', [fileName, data], complete);
|
||||
} else {
|
||||
this.getFileList((function(err, files) {
|
||||
if (err) { return complete(err); }
|
||||
var exists = files.some(function(file) { return file.toLowerCase() === fileName.toLowerCase(); });
|
||||
if (exists) { return complete({ exists: true }); }
|
||||
this._callAndHandleError('writeFile', [fileName, data], complete);
|
||||
}).bind(this));
|
||||
}
|
||||
},
|
||||
|
||||
openFile: function(fileName, complete) {
|
||||
this._getClient(function(err, client) {
|
||||
if (err) { return complete(err); }
|
||||
client.readFile(fileName, { blob: true }, complete);
|
||||
});
|
||||
this._callAndHandleError('readFile', [fileName, { blob: true }], complete);
|
||||
},
|
||||
|
||||
getFileList: function(complete) {
|
||||
this._getClient(function(err, client) {
|
||||
if (err) { return complete(err); }
|
||||
client.readdir('', function(err, files) {
|
||||
if (err) { return complete(err); }
|
||||
this._callAndHandleError('readdir', [''], function(err, files) {
|
||||
if (files) {
|
||||
files = files.filter(function(f) { return /\.kdbx$/i.test(f); });
|
||||
complete(null, files);
|
||||
});
|
||||
}
|
||||
complete(err, files);
|
||||
});
|
||||
}
|
||||
};
|
||||
|
|
|
@ -181,41 +181,52 @@ var OpenFileView = Backbone.View.extend({
|
|||
},
|
||||
|
||||
openFromDropbox: function() {
|
||||
this.dropboxLoading = 'opening';
|
||||
this.render();
|
||||
DropboxLink.getFileList((function(err, files) {
|
||||
this.dropboxLoading = null;
|
||||
if (err) { return; }
|
||||
var buttons = [];
|
||||
files.forEach(function(file) {
|
||||
buttons.push({ result: file, title: file.replace(/\.kdbx/i, '') });
|
||||
});
|
||||
if (!buttons.length) {
|
||||
this.dropboxLoading = null;
|
||||
this.render();
|
||||
Alerts.error({
|
||||
header: 'Nothing found',
|
||||
body: 'You have no files in your Dropbox which could be opened. Files are searched in your Dropbox app folder: Apps/KeeWeb'
|
||||
});
|
||||
if (this.dropboxLoading) {
|
||||
return;
|
||||
}
|
||||
DropboxLink.authenticate((function(err) {
|
||||
if (err) {
|
||||
return;
|
||||
}
|
||||
buttons.push({ result: '', title: 'Cancel' });
|
||||
Alerts.alert({
|
||||
header: 'Select a file',
|
||||
body: 'Select a file from your Dropbox which you would like to open',
|
||||
icon: 'dropbox',
|
||||
buttons: buttons,
|
||||
esc: '',
|
||||
click: '',
|
||||
success: this.openDropboxFile.bind(this),
|
||||
cancel: this.cancelOpenDropboxFile.bind(this)
|
||||
});
|
||||
this.dropboxLoading = 'file list';
|
||||
this.render();
|
||||
DropboxLink.getFileList((function(err, files) {
|
||||
this.dropboxLoading = null;
|
||||
if (err) {
|
||||
this.render();
|
||||
return;
|
||||
}
|
||||
var buttons = [];
|
||||
files.forEach(function(file) {
|
||||
buttons.push({ result: file, title: file.replace(/\.kdbx/i, '') });
|
||||
});
|
||||
if (!buttons.length) {
|
||||
this.dropboxLoading = null;
|
||||
this.render();
|
||||
Alerts.error({
|
||||
header: 'Nothing found',
|
||||
body: 'You have no files in your Dropbox which could be opened. Files are searched in your Dropbox app folder: Apps/KeeWeb'
|
||||
});
|
||||
return;
|
||||
}
|
||||
buttons.push({ result: '', title: 'Cancel' });
|
||||
Alerts.alert({
|
||||
header: 'Select a file',
|
||||
body: 'Select a file from your Dropbox which you would like to open',
|
||||
icon: 'dropbox',
|
||||
buttons: buttons,
|
||||
esc: '',
|
||||
click: '',
|
||||
success: this.openDropboxFile.bind(this),
|
||||
cancel: this.cancelOpenDropboxFile.bind(this)
|
||||
});
|
||||
}).bind(this));
|
||||
}).bind(this));
|
||||
},
|
||||
|
||||
openDropboxFile: function(file) {
|
||||
var fileName = file.replace(/\.kdbx/i, '');
|
||||
this.dropboxLoading = 'opening ' + fileName;
|
||||
this.dropboxLoading = fileName;
|
||||
this.render();
|
||||
DropboxLink.openFile(file, (function(err, data) {
|
||||
this.dropboxLoading = null;
|
||||
|
|
|
@ -44,6 +44,7 @@ var SettingsAboutView = Backbone.View.extend({
|
|||
name: this.model.get('name'),
|
||||
path: this.model.get('path'),
|
||||
storage: this.model.get('storage'),
|
||||
syncing: this.model.get('syncing'),
|
||||
password: PasswordGenerator.present(this.model.get('passwordLength')),
|
||||
defaultUser: this.model.get('defaultUser'),
|
||||
recycleBinEnabled: this.model.get('recycleBinEnabled'),
|
||||
|
@ -86,9 +87,7 @@ var SettingsAboutView = Backbone.View.extend({
|
|||
Alerts.error({
|
||||
header: 'Empty password',
|
||||
body: 'Please, enter the password. You will use it the next time you open this file.',
|
||||
complete: (function() {
|
||||
this.$el.find('#settings__file-master-pass').focus();
|
||||
}).bind(this)
|
||||
complete: (function() { this.$el.find('#settings__file-master-pass').focus(); }).bind(this)
|
||||
});
|
||||
return false;
|
||||
}
|
||||
|
@ -115,7 +114,9 @@ var SettingsAboutView = Backbone.View.extend({
|
|||
var blob = new Blob([data], {type: 'application/octet-stream'});
|
||||
FileSaver.saveAs(blob, fileName);
|
||||
this.passwordChanged = false;
|
||||
this.model.saved();
|
||||
if (this.model.get('storage') !== 'dropbox') {
|
||||
this.model.saved();
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
|
@ -151,12 +152,13 @@ var SettingsAboutView = Backbone.View.extend({
|
|||
},
|
||||
|
||||
saveToDropbox: function(overwrite) {
|
||||
if (!this.validate()) {
|
||||
if (this.model.get('syncing') || !this.validate()) {
|
||||
return;
|
||||
}
|
||||
var data = this.model.getData();
|
||||
var fileName = this.model.get('name') + '.kdbx';
|
||||
this.model.set('syncing', true);
|
||||
this.render();
|
||||
DropboxLink.saveFile(fileName, data, overwrite, (function(err) {
|
||||
if (err) {
|
||||
this.model.set('syncing', false);
|
||||
|
@ -169,7 +171,8 @@ var SettingsAboutView = Backbone.View.extend({
|
|||
esc: '',
|
||||
click: '',
|
||||
enter: 'yes',
|
||||
success: this.saveToDropbox.bind(this, true)
|
||||
success: this.saveToDropbox.bind(this, true),
|
||||
cancel: (function() { this.$el.find('#settings__file-name').focus(); }).bind(this)
|
||||
});
|
||||
} else {
|
||||
Alerts.error({
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
<div class="footer__db footer__db-item <%= file.get('open') ? '' : 'footer__db--dimmed' %>" data-file-id="<%= file.cid %>">
|
||||
<i class="fa fa-<%= file.get('open') ? 'unlock' : 'lock' %>"></i> <%- file.get('name') %>
|
||||
<% if (file.get('modified') && !file.get('syncing')) { %><i class="fa fa-circle footer__db-sign"></i><% } %>
|
||||
<% if (file.get('syncing')) { %><i class="fa fa-refresh fa-spin footer__db-sign"></i><% } %>
|
||||
</div>
|
||||
<% }); %>
|
||||
<div class="footer__db footer__db--dimmed footer__db--expanded footer__db-open"><i class="fa fa-plus"></i> Open / New</div>
|
||||
|
|
|
@ -13,10 +13,10 @@
|
|||
<a class="open__file-link-name muted-color" <%= opening ? 'disabled' : '' %>>Open another</a>
|
||||
<% } else { %>
|
||||
<a class="open__file-link-open muted-color" <%= opening ? 'disabled' : '' %>>Open</a> / <a
|
||||
class="open__file-link-new muted-color" <%= opening ? 'disabled' : '' %>>New</a><% if (supportsDropbox) { %> / <a
|
||||
class="open__file-link-new muted-color" <%= opening ? 'disabled' : '' %>>New</a> / <a
|
||||
class="open__file-link-demo muted-color" <%= opening ? 'disabled' : '' %>>Demo</a><% if (supportsDropbox) { %> / <a
|
||||
class="open__file-link-dropbox muted-color" <%= (opening || dropboxLoading) ? 'disabled' : '' %>
|
||||
>Dropbox<%= dropboxLoading ? ' (' + dropboxLoading + '...)' : '' %></a><% } %> / <a
|
||||
class="open__file-link-demo muted-color" <%= opening ? 'disabled' : '' %>>Demo</a>
|
||||
>Dropbox<%= dropboxLoading ? ' (loading ' + dropboxLoading + '...)' : '' %></a><% } %>
|
||||
<% } %>
|
||||
</div>
|
||||
<div class="open__file-warning muted-color hide"><i class="fa fa-exclamation-triangle"></i> Caps Lock is on</div>
|
||||
|
|
|
@ -15,12 +15,11 @@
|
|||
<% } %>
|
||||
|
||||
<div class="settings__file-buttons">
|
||||
<% if (storage !== 'dropbox') { %>
|
||||
<button class="settings__file-button-save-file btn-silent">Save to file</button>
|
||||
<% } %>
|
||||
<button class="settings__file-button-export-xml btn-silent">Export to XML</button>
|
||||
<% if (supportsDropbox) { %>
|
||||
<button class="settings__file-button-save-dropbox btn-silent">Sync with Dropbox</button>
|
||||
<button class="settings__file-button-save-dropbox btn-silent" <%= syncing ? 'disabled' : '' %>>
|
||||
Sync with Dropbox <%= syncing ? '(working...)' : '' %></button>
|
||||
<% } %>
|
||||
</div>
|
||||
|
||||
|
|
Loading…
Reference in New Issue