Stackedit/js/dropbox-helper.js

320 lines
8.4 KiB
JavaScript
Raw Normal View History

2013-04-21 00:07:27 +00:00
define(["jquery", "core", "async-runner"], function($, core, asyncRunner) {
2013-04-07 15:22:13 +00:00
var client = undefined;
var authenticated = false;
2013-04-09 07:58:06 +00:00
var dropboxHelper = {};
2013-04-07 15:22:13 +00:00
// Try to connect dropbox by downloading client.js
2013-04-20 00:14:20 +00:00
function connect(task) {
task.onRun(function() {
if(core.isOffline === true) {
client = undefined;
core.showMessage("Operation not available in offline mode.");
task.error();
return;
}
if (client !== undefined) {
task.chain();
return;
}
$.ajax({
url : "lib/dropbox.min.js",
dataType : "script", timeout : AJAX_TIMEOUT
}).done(function() {
client = new Dropbox.Client({
key: DROPBOX_APP_KEY,
secret: DROPBOX_APP_SECRET
});
client.authDriver(new Dropbox.Drivers.Popup({
receiverUrl: BASE_URL + "dropbox-oauth-receiver.html",
rememberUser: true
}));
task.chain();
}).fail(function() {
core.setOffline();
2013-04-21 00:51:07 +00:00
task.error(new Error("Network timeout|stopPublish"));
2013-04-07 15:22:13 +00:00
});
2013-04-16 15:02:24 +00:00
});
2013-04-07 15:22:13 +00:00
}
// Try to authenticate with Oauth
2013-04-20 00:14:20 +00:00
function authenticate(task) {
task.onRun(function() {
2013-04-16 15:02:24 +00:00
if (authenticated === true) {
2013-04-20 00:14:20 +00:00
task.chain();
2013-04-07 15:22:13 +00:00
return;
}
2013-04-20 00:14:20 +00:00
var immediate = true;
function localAuthenticate() {
if (immediate === false) {
core.showMessage("Please make sure the Dropbox authorization popup is not blocked by your browser.");
// If not immediate we add time for user to enter his credentials
task.timeout = ASYNC_TASK_LONG_TIMEOUT;
2013-04-07 15:22:13 +00:00
}
2013-04-20 00:14:20 +00:00
client.reset();
client.authenticate({interactive: !immediate}, function(error, client) {
// Success
if (client.authState === Dropbox.Client.DONE) {
authenticated = true;
task.chain();
return;
}
// If immediate did not work retry without immediate flag
if (immediate === true) {
immediate = false;
task.chain(localAuthenticate);
return;
}
// Error
var errorMsg = "Access to Dropbox account is not authorized.";
core.showError(errorMsg);
task.error(new Error(errorMsg));
});
}
task.chain(localAuthenticate);
2013-04-07 15:22:13 +00:00
});
}
2013-04-09 07:58:06 +00:00
dropboxHelper.upload = function(path, content, callback) {
2013-04-07 15:22:13 +00:00
callback = callback || core.doNothing;
2013-04-20 00:14:20 +00:00
var result = undefined;
var task = asyncRunner.createTask();
connect(task);
authenticate(task);
task.onRun(function() {
client.writeFile(path, content, function(error, stat) {
if (!error) {
result = stat;
task.chain();
2013-04-16 15:02:24 +00:00
return;
}
2013-04-20 00:14:20 +00:00
// Handle error
if(error.status === Dropbox.ApiError.INVALID_PARAM) {
error = 'Could not upload document into path "' + path + '".';
}
handleError(error, task, callback);
2013-04-16 15:02:24 +00:00
});
2013-04-20 00:14:20 +00:00
});
task.onSuccess(function() {
callback(undefined, result);
});
task.onError(function(error) {
callback(error);
});
asyncRunner.addTask(task);
2013-04-07 15:22:13 +00:00
};
2013-04-20 17:40:05 +00:00
dropboxHelper.checkChanges = function(lastChangeId, callback) {
2013-04-07 15:22:13 +00:00
callback = callback || core.doNothing;
2013-04-16 15:02:24 +00:00
var changes = [];
var newChangeId = lastChangeId || 0;
2013-04-20 00:14:20 +00:00
var task = asyncRunner.createTask();
connect(task);
authenticate(task);
task.onRun(function() {
function retrievePageOfChanges() {
client.pullChanges(newChangeId, function(error, pullChanges) {
2013-04-16 15:02:24 +00:00
if (error) {
2013-04-20 00:14:20 +00:00
handleError(error, task, callback);
2013-04-16 15:02:24 +00:00
return;
}
2013-04-20 00:14:20 +00:00
// Retrieve success
newChangeId = pullChanges.cursor();
if(pullChanges.changes !== undefined) {
2013-04-20 17:40:05 +00:00
changes = changes.concat(pullChanges.changes);
2013-04-20 00:14:20 +00:00
}
if (pullChanges.shouldPullAgain) {
task.chain(retrievePageOfChanges);
} else {
task.chain();
}
2013-04-16 15:02:24 +00:00
});
2013-04-07 15:22:13 +00:00
}
2013-04-20 00:14:20 +00:00
task.chain(retrievePageOfChanges);
});
task.onSuccess(function() {
2013-04-16 15:02:24 +00:00
callback(undefined, changes, newChangeId);
2013-04-20 00:14:20 +00:00
});
task.onError(function(error) {
callback(error);
});
asyncRunner.addTask(task);
2013-04-07 15:22:13 +00:00
};
2013-04-16 15:02:24 +00:00
dropboxHelper.downloadMetadata = function(paths, callback) {
2013-04-07 15:22:13 +00:00
callback = callback || core.doNothing;
2013-04-20 00:14:20 +00:00
var result = [];
var task = asyncRunner.createTask();
connect(task);
authenticate(task);
task.onRun(function() {
2013-04-16 15:02:24 +00:00
function recursiveDownloadMetadata() {
if(paths.length === 0) {
2013-04-20 00:14:20 +00:00
task.chain();
2013-04-16 15:02:24 +00:00
return;
}
2013-04-20 00:14:20 +00:00
var path = paths.pop();
client.stat(path, function(error, stat) {
if(stat) {
result.push(stat);
task.chain(recursiveDownloadMetadata);
2013-04-07 15:22:13 +00:00
return;
}
2013-04-20 00:14:20 +00:00
handleError(error, task, callback);
2013-04-07 15:22:13 +00:00
});
2013-04-16 15:02:24 +00:00
}
2013-04-20 00:14:20 +00:00
task.chain(recursiveDownloadMetadata);
});
task.onSuccess(function() {
2013-04-16 15:02:24 +00:00
callback(undefined, result);
2013-04-20 00:14:20 +00:00
});
task.onError(function(error) {
callback(error);
});
asyncRunner.addTask(task);
2013-04-07 15:22:13 +00:00
};
2013-04-20 00:14:20 +00:00
dropboxHelper.downloadContent = function(objects, callback) {
2013-04-07 15:22:13 +00:00
callback = callback || core.doNothing;
2013-04-20 00:14:20 +00:00
var result = [];
var task = asyncRunner.createTask();
connect(task);
authenticate(task);
task.onRun(function() {
2013-04-16 15:02:24 +00:00
function recursiveDownloadContent() {
if(objects.length === 0) {
2013-04-20 00:14:20 +00:00
task.chain();
2013-04-16 15:02:24 +00:00
return;
}
var object = objects.pop();
result.push(object);
var file = undefined;
// object may be a file
if(object.isFile === true) {
file = object;
}
// object may be a change
else if(object.wasRemoved !== undefined) {
file = object.stat;
}
if(!file) {
2013-04-20 00:14:20 +00:00
task.chain(recursiveDownloadContent);
2013-04-16 15:02:24 +00:00
return;
}
2013-04-20 00:14:20 +00:00
client.readFile(file.path, function(error, data) {
if(data) {
file.content = data;
recursiveDownloadContent();
2013-04-07 15:22:13 +00:00
return;
}
2013-04-20 00:14:20 +00:00
handleError(error, task, callback);
2013-04-07 15:22:13 +00:00
});
2013-04-16 15:02:24 +00:00
}
2013-04-20 00:14:20 +00:00
task.chain(recursiveDownloadContent);
});
task.onSuccess(function() {
2013-04-16 15:02:24 +00:00
callback(undefined, result);
2013-04-20 00:14:20 +00:00
});
task.onError(function(error) {
callback(error);
});
asyncRunner.addTask(task);
2013-04-07 15:22:13 +00:00
};
2013-04-20 00:14:20 +00:00
function handleError(error, task, callback) {
var errorMsg = true;
2013-04-07 15:22:13 +00:00
if (error) {
2013-04-13 18:11:54 +00:00
console.error(error);
2013-04-07 15:22:13 +00:00
// Try to analyze the error
if (typeof error === "string") {
errorMsg = error;
} else if (error.status === Dropbox.ApiError.INVALID_TOKEN
|| error.status === Dropbox.ApiError.OAUTH_ERROR) {
authenticated = false;
2013-04-20 00:14:20 +00:00
task.retry();
return;
} else if(error.status === Dropbox.ApiError.INVALID_PARAM && error.responseText
.indexOf("oauth_nonce") !== -1) {
// A bug I guess...
_.each(_.keys(localStorage), function(key) {
// We have to remove the Oauth cache from the localStorage
if(key.indexOf("dropbox-auth") === 0) {
localStorage.removeItem(key);
}
});
authenticated = false;
task.retry();
return;
2013-04-07 15:22:13 +00:00
} else if (error.status === Dropbox.ApiError.NETWORK_ERROR) {
client = undefined;
authenticated = false;
core.setOffline();
2013-04-21 00:51:07 +00:00
errorMsg = "|stopPublish";
2013-04-07 15:22:13 +00:00
} else {
errorMsg = "Dropbox error ("
+ error.status + ").";
}
2013-04-20 00:14:20 +00:00
core.showError(errorMsg);
2013-04-07 15:22:13 +00:00
}
2013-04-20 00:14:20 +00:00
task.error(new Error(errorMsg));
2013-04-07 15:22:13 +00:00
}
var pickerLoaded = false;
2013-04-20 00:14:20 +00:00
function loadPicker(task) {
task.onRun(function() {
if (pickerLoaded === true) {
task.chain();
2013-04-07 15:22:13 +00:00
return;
}
2013-04-16 15:02:24 +00:00
$.ajax({
url : "https://www.dropbox.com/static/api/1/dropbox.js",
dataType : "script", timeout : AJAX_TIMEOUT
}).done(function() {
2013-04-07 15:22:13 +00:00
pickerLoaded = true;
2013-04-20 00:14:20 +00:00
task.chain();
2013-04-16 15:02:24 +00:00
}).fail(function() {
2013-04-20 00:14:20 +00:00
core.setOffline();
task.error();
2013-04-16 15:02:24 +00:00
});
2013-04-07 15:22:13 +00:00
});
}
2013-04-09 07:58:06 +00:00
dropboxHelper.picker = function(callback) {
2013-04-07 15:22:13 +00:00
callback = callback || core.doNothing;
2013-04-16 15:02:24 +00:00
var paths = [];
2013-04-20 00:14:20 +00:00
var task = asyncRunner.createTask();
// Add some time for user to choose his files
task.timeout = ASYNC_TASK_LONG_TIMEOUT;
connect(task);
loadPicker(task);
task.onRun(function() {
var options = {};
options.multiselect = true;
options.linkType = "direct";
options.success = function(files) {
for(var i=0; i<files.length; i++) {
var path = files[i].link;
path = path.replace(/.*\/view\/[^\/]*/, "");
paths.push(decodeURI(path));
2013-04-07 15:22:13 +00:00
}
2013-04-20 00:14:20 +00:00
task.chain();
};
options.cancel = function() {
task.chain();
};
Dropbox.choose(options);
core.showMessage("Please make sure the Dropbox chooser popup is not blocked by your browser.");
});
task.onSuccess(function() {
2013-04-16 15:02:24 +00:00
callback(undefined, paths);
2013-04-07 15:22:13 +00:00
});
2013-04-20 00:14:20 +00:00
task.onError(function(error) {
callback(error);
});
asyncRunner.addTask(task);
2013-04-07 15:22:13 +00:00
};
2013-04-09 07:58:06 +00:00
return dropboxHelper;
2013-04-07 15:22:13 +00:00
});