Support for Dropbox publishing

This commit is contained in:
benweet 2013-04-16 16:02:24 +01:00
parent 7667b91873
commit 51ba5930af
8 changed files with 315 additions and 270 deletions

View File

@ -88,6 +88,8 @@
<ul class="dropdown-menu"> <ul class="dropdown-menu">
<li><a href="#" class="action-publish-blogger"><i <li><a href="#" class="action-publish-blogger"><i
class="icon-blogger"></i> Blogger</a></li> class="icon-blogger"></i> Blogger</a></li>
<li><a href="#" class="action-publish-dropbox"><i
class="icon-dropbox"></i> Dropbox</a></li>
<li><a href="#" class="action-publish-github"><i <li><a href="#" class="action-publish-github"><i
class="icon-github"></i> GitHub</a></li> class="icon-github"></i> GitHub</a></li>
</ul></li> </ul></li>
@ -269,7 +271,7 @@
<div class="modal-header"> <div class="modal-header">
<button type="button" class="close" data-dismiss="modal" <button type="button" class="close" data-dismiss="modal"
aria-hidden="true">&times;</button> aria-hidden="true">&times;</button>
<h3 class="modal-publish-github">Publish on GitHub</h3> <h3>Publish on <span class="publish-provider-name"></span></h3>
</div> </div>
<div class="modal-body"> <div class="modal-body">
<div class="form-horizontal"> <div class="form-horizontal">
@ -311,6 +313,13 @@
placeholder="Post ID"> placeholder="Post ID">
</div> </div>
</div> </div>
<div class="control-group modal-publish-dropbox">
<label class="control-label" for="input-publish-dropbox-path">File path</label>
<div class="controls">
<input type="text" id="input-publish-dropbox-path"
placeholder="/path/to/My Document.html">
</div>
</div>
<div class="control-group"> <div class="control-group">
<div class="control-label">Format</div> <div class="control-label">Format</div>
<div class="controls"> <div class="controls">

View File

@ -106,10 +106,16 @@ define(["underscore"], function() {
asyncTaskRunner.runTask(); asyncTaskRunner.runTask();
}; };
// Change current task timeout
asyncTaskRunner.setCurrentTaskTimeout = function(timeout) {
if(currentTask !== undefined) {
currentTask.timeout = timeout;
}
};
asyncTaskRunner.init = function(coreModule) { asyncTaskRunner.init = function(coreModule) {
core = coreModule; core = coreModule;
}; };
return asyncTaskRunner; return asyncTaskRunner;
}); });

View File

@ -15,8 +15,9 @@ var USER_IDLE_THRESHOLD = 300000;
var SYNC_PROVIDER_GDRIVE = "sync.gdrive."; var SYNC_PROVIDER_GDRIVE = "sync.gdrive.";
var SYNC_PROVIDER_DROPBOX = "sync.dropbox."; var SYNC_PROVIDER_DROPBOX = "sync.dropbox.";
var PROVIDER_TYPE_PUBLISH_FLAG = 1; var PROVIDER_TYPE_PUBLISH_FLAG = 1;
var PROVIDER_GITHUB = "github";
var PROVIDER_BLOGGER = "blogger"; var PROVIDER_BLOGGER = "blogger";
var PROVIDER_DROPBOX = "dropbox";
var PROVIDER_GITHUB = "github";
// Use by Google's client.js // Use by Google's client.js
var delayedFunction = undefined; var delayedFunction = undefined;

View File

@ -12,28 +12,20 @@ define(["jquery", "async-runner"], function($, asyncTaskRunner) {
// Try to connect dropbox by downloading client.js // Try to connect dropbox by downloading client.js
function connect(callback) { function connect(callback) {
callback = callback || core.doNothing; callback = callback || core.doNothing;
var asyncTask = {};
asyncTask.run = function() {
if(core.isOffline === true) { if(core.isOffline === true) {
client = undefined; client = undefined;
core.showMessage("Operation not available in offline mode."); core.showMessage("Operation not available in offline mode.");
asyncTask.error(); callback(true);
return; return;
} }
if (client !== undefined) { if (client !== undefined) {
asyncTask.success(); callback();
return; return;
} }
$.ajax({ $.ajax({
url : "lib/dropbox.min.js", url : "lib/dropbox.min.js",
dataType : "script", timeout : AJAX_TIMEOUT dataType : "script", timeout : AJAX_TIMEOUT
}).done(function() { }).done(function() {
asyncTask.success();
}).fail(function() {
asyncTask.error();
});
};
asyncTask.onSuccess = function() {
client = new Dropbox.Client({ client = new Dropbox.Client({
key: DROPBOX_APP_KEY, key: DROPBOX_APP_KEY,
secret: DROPBOX_APP_SECRET secret: DROPBOX_APP_SECRET
@ -43,12 +35,10 @@ define(["jquery", "async-runner"], function($, asyncTaskRunner) {
rememberUser: true rememberUser: true
})); }));
callback(); callback();
}; }).fail(function() {
asyncTask.onError = function() {
core.setOffline(); core.setOffline();
callback(); callback(true);
}; });
asyncTaskRunner.addTask(asyncTask);
} }
// Try to authenticate with Oauth // Try to authenticate with Oauth
@ -57,61 +47,51 @@ define(["jquery", "async-runner"], function($, asyncTaskRunner) {
if (immediate === undefined) { if (immediate === undefined) {
immediate = true; immediate = true;
} }
connect(function() { connect(function(error) {
if (client === undefined) { if (error) {
callback(); callback(error);
return; return;
} }
var asyncTask = {};
asyncTask.run = function() {
if (authenticated === true) { if (authenticated === true) {
asyncTask.success(); callback();
return; return;
} }
if (immediate === false) { if (immediate === false) {
core.showMessage("Please make sure the Dropbox authorization popup is not blocked by your browser."); core.showMessage("Please make sure the Dropbox authorization popup is not blocked by your browser.");
asyncTaskRunner.setCurrentTaskTimeout(AUTH_POPUP_TIMEOUT);
} }
client.authenticate({interactive: !immediate}, function(error, client) { client.authenticate({interactive: !immediate}, function(error, client) {
if (client.authState !== Dropbox.Client.DONE) { if (client.authState === Dropbox.Client.DONE) {
// Handle error callback();
asyncTask.error();
return; return;
} }
asyncTask.success();
});
};
asyncTask.onSuccess = function() {
callback();
};
asyncTask.onError = function() {
// If immediate did not work retry without immediate flag // If immediate did not work retry without immediate flag
if (client !== undefined && immediate === true) { if (client !== undefined && immediate === true) {
authenticate(callback, false); authenticate(callback, false);
return; return;
} }
callback(); // Notify error
}; callback(true);
asyncTaskRunner.addTask(asyncTask); });
}); });
} }
dropboxHelper.upload = function(path, content, callback) { dropboxHelper.upload = function(path, content, callback) {
callback = callback || core.doNothing; callback = callback || core.doNothing;
authenticate(function() { var syncIndex = undefined;
if (client === undefined) { var asyncTask = {};
callback(); asyncTask.run = function() {
authenticate(function(error) {
if (error) {
handleError(error, asyncTask, callback);
return; return;
} }
var fileSyncIndex = undefined;
var asyncTask = {};
asyncTask.run = function() {
client.writeFile(path, content, function(error, stat) { client.writeFile(path, content, function(error, stat) {
if (!error) { if (!error) {
fileSyncIndex = SYNC_PROVIDER_DROPBOX + encodeURIComponent(stat.path.toLowerCase()); syncIndex = SYNC_PROVIDER_DROPBOX + encodeURIComponent(stat.path.toLowerCase());
localStorage[fileSyncIndex + ".version"] = stat.versionTag; localStorage[syncIndex + ".version"] = stat.versionTag;
asyncTask.success(); asyncTask.success();
return; return;
} }
@ -121,36 +101,41 @@ define(["jquery", "async-runner"], function($, asyncTaskRunner) {
} }
handleError(error, asyncTask, callback); handleError(error, asyncTask, callback);
}); });
});
}; };
asyncTask.onSuccess = function() { asyncTask.onSuccess = function() {
callback(fileSyncIndex); callback(undefined, syncIndex);
}; };
asyncTask.onError = function() { asyncTask.onError = function() {
callback(); callback(true);
}; };
asyncTaskRunner.addTask(asyncTask); asyncTaskRunner.addTask(asyncTask);
});
}; };
dropboxHelper.checkUpdates = function(lastChangeId, callback) { dropboxHelper.checkUpdates = function(lastChangeId, callback) {
callback = callback || core.doNothing; callback = callback || core.doNothing;
authenticate(function() { var changes = [];
if (client === undefined) { var newChangeId = lastChangeId || 0;
callback(); var asyncTask = {};
asyncTask.run = function() {
function retrievePageOfChanges(changeId) {
if(asyncTask.finished === true) {
return;
}
authenticate(function(error) {
if (error) {
handleError(error, asyncTask, callback);
return; return;
} }
var changes = [];
var newChangeId = lastChangeId || 0;
function retrievePageOfChanges(changeId) {
var shouldPullAgain = false;
var asyncTask = {};
asyncTask.run = function() {
client.pullChanges(changeId, function(error, pullChanges) { client.pullChanges(changeId, function(error, pullChanges) {
if (pullChanges && pullChanges.cursorTag) { if (error) {
handleError(error, asyncTask, callback);
return;
}
// Retrieve success // Retrieve success
newChangeId = pullChanges.cursor(); newChangeId = pullChanges.cursor();
shouldPullAgain = pullChanges.shouldPullAgain;
if(pullChanges.changes !== undefined) { if(pullChanges.changes !== undefined) {
for(var i=0; i<pullChanges.changes.length; i++) { for(var i=0; i<pullChanges.changes.length; i++) {
var item = pullChanges.changes[i]; var item = pullChanges.changes[i];
@ -161,70 +146,80 @@ define(["jquery", "async-runner"], function($, asyncTaskRunner) {
} }
} }
} }
asyncTask.success(); if (pullChanges.shouldPullAgain) {
return;
}
// Handle error
handleError(error, asyncTask, callback);
});
};
asyncTask.onSuccess = function() {
if (shouldPullAgain === true) {
retrievePageOfChanges(newChangeId); retrievePageOfChanges(newChangeId);
} else { } else {
callback(changes, newChangeId); asyncTask.success();
} }
}; });
asyncTask.onError = function() { });
callback();
};
asyncTaskRunner.addTask(asyncTask);
} }
retrievePageOfChanges(newChangeId); retrievePageOfChanges(newChangeId);
}); };
asyncTask.onSuccess = function() {
callback(undefined, changes, newChangeId);
};
asyncTask.onError = function() {
callback(true);
};
asyncTaskRunner.addTask(asyncTask);
}; };
dropboxHelper.downloadMetadata = function(paths, callback, result) { dropboxHelper.downloadMetadata = function(paths, callback) {
callback = callback || core.doNothing; callback = callback || core.doNothing;
result = result || []; result = result || [];
if(paths.length === 0) {
callback(result);
return;
}
authenticate(function() {
if (client === undefined) {
callback();
return;
}
var path = paths.pop(); var path = paths.pop();
var asyncTask = {}; var asyncTask = {};
asyncTask.run = function() { asyncTask.run = function() {
function recursiveDownloadMetadata() {
if(asyncTask.finished === true) {
return;
}
if(paths.length === 0) {
asyncTask.success();
return;
}
authenticate(function(error) {
if (error) {
handleError(error, asyncTask, callback);
return;
}
client.stat(path, function(error, stat) { client.stat(path, function(error, stat) {
if(stat) { if(stat) {
result.push(stat); result.push(stat);
asyncTask.success(); recursiveDownloadMetadata();
return; return;
} }
handleError(error, asyncTask, callback); handleError(error, asyncTask, callback);
}); });
});
}
recursiveDownloadMetadata();
}; };
asyncTask.onSuccess = function() { asyncTask.onSuccess = function() {
dropboxHelper.downloadMetadata(paths, callback, result); callback(undefined, result);
}; };
asyncTask.onError = function() { asyncTask.onError = function() {
callback(); callback(true);
}; };
asyncTaskRunner.addTask(asyncTask); asyncTaskRunner.addTask(asyncTask);
});
}; };
dropboxHelper.downloadContent = function(objects, callback, result) { dropboxHelper.downloadContent = function(objects, callback, result) {
callback = callback || core.doNothing; callback = callback || core.doNothing;
result = result || []; result = result || [];
var asyncTask = {};
asyncTask.run = function() {
function recursiveDownloadContent() {
if(asyncTask.finished === true) {
return;
}
if(objects.length === 0) { if(objects.length === 0) {
callback(result); asyncTask.success();
return; return;
} }
@ -240,35 +235,34 @@ define(["jquery", "async-runner"], function($, asyncTaskRunner) {
file = object.stat; file = object.stat;
} }
if(!file) { if(!file) {
this.downloadContent(objects, callback, result); recursiveDownloadContent();
return;
}
authenticate(function(error) {
if (error) {
handleError(error, asyncTask, callback);
return; return;
} }
authenticate(function() {
if (client === undefined) {
callback();
return;
}
var asyncTask = {};
asyncTask.run = function() {
client.readFile(file.path, function(error, data) { client.readFile(file.path, function(error, data) {
if(data) { if(data) {
file.content = data; file.content = data;
asyncTask.success(); recursiveDownloadContent();
return; return;
} }
handleError(error, asyncTask, callback); handleError(error, asyncTask, callback);
}); });
});
}
recursiveDownloadContent();
}; };
asyncTask.onSuccess = function() { asyncTask.onSuccess = function() {
dropboxHelper.downloadContent(objects, callback, result); callback(undefined, result);
}; };
asyncTask.onError = function() { asyncTask.onError = function() {
callback(); callback(true);
}; };
asyncTaskRunner.addTask(asyncTask); asyncTaskRunner.addTask(asyncTask);
});
}; };
function handleError(error, asyncTask, callback) { function handleError(error, asyncTask, callback) {
@ -277,7 +271,7 @@ define(["jquery", "async-runner"], function($, asyncTaskRunner) {
if (errorMsg !== undefined) { if (errorMsg !== undefined) {
core.showError(errorMsg); core.showError(errorMsg);
} }
callback(); callback(errorMsg);
}; };
if (error) { if (error) {
console.error(error); console.error(error);
@ -302,83 +296,83 @@ define(["jquery", "async-runner"], function($, asyncTaskRunner) {
var pickerLoaded = false; var pickerLoaded = false;
function loadPicker(callback) { function loadPicker(callback) {
connect(function() { if (pickerLoaded === true) {
if (client === undefined) {
pickerLoaded = false;
callback(); callback();
return; return;
} }
connect(function(error) {
var asyncTask = {}; if (error) {
asyncTask.run = function() { pickerLoaded = false;
if (pickerLoaded === true) { callback(error);
asyncTask.success();
return; return;
} }
$.ajax({ $.ajax({
url : "https://www.dropbox.com/static/api/1/dropbox.js", url : "https://www.dropbox.com/static/api/1/dropbox.js",
dataType : "script", timeout : AJAX_TIMEOUT dataType : "script", timeout : AJAX_TIMEOUT
}).done(function() { }).done(function() {
asyncTask.success();
}).fail(function() {
asyncTask.error();
});
};
asyncTask.onSuccess = function() {
pickerLoaded = true; pickerLoaded = true;
callback(); callback();
}; }).fail(function() {
asyncTask.onError = function() { callback(true);
core.setOffline(); });
callback();
};
asyncTaskRunner.addTask(asyncTask);
}); });
} }
dropboxHelper.picker = function(callback) { dropboxHelper.picker = function(callback) {
callback = callback || core.doNothing; callback = callback || core.doNothing;
loadPicker(function() { var paths = [];
if (pickerLoaded === false) {
callback(); var asyncTask = {};
asyncTask.run = function() {
loadPicker(function(error) {
if (error) {
handleError(error, asyncTask, callback);
return; return;
} }
var options = {}; var options = {};
options.multiselect = true; options.multiselect = true;
options.linkType = "direct"; options.linkType = "direct";
options.success = function(files) { options.success = function(files) {
var paths = [];
for(var i=0; i<files.length; i++) { for(var i=0; i<files.length; i++) {
var path = files[i].link; var path = files[i].link;
path = path.replace(/.*\/view\/[^\/]*/, ""); path = path.replace(/.*\/view\/[^\/]*/, "");
paths.push(decodeURI(path)); paths.push(decodeURI(path));
} }
callback(paths); asyncTask.success();
}; };
options.cancel = function() { options.cancel = function() {
callback(); asyncTask.error();
}; };
Dropbox.choose(options); Dropbox.choose(options);
core.showMessage("Please make sure the Dropbox chooser popup is not blocked by your browser."); core.showMessage("Please make sure the Dropbox chooser popup is not blocked by your browser.");
}); });
}; };
asyncTask.onSuccess = function() {
callback(undefined, paths);
};
asyncTask.onError = function() {
callback(true);
};
asyncTaskRunner.addTask(asyncTask);
};
dropboxHelper.importFiles = function(paths) { dropboxHelper.importFiles = function(paths) {
dropboxHelper.downloadMetadata(paths, function(result) { dropboxHelper.downloadMetadata(paths, function(error, result) {
if(result === undefined) { if(error) {
return; return;
} }
dropboxHelper.downloadContent(result, function(result) { dropboxHelper.downloadContent(result, function(error, result) {
if(result === undefined) { if(error) {
return; return;
} }
for(var i=0; i<result.length; i++) { for(var i=0; i<result.length; i++) {
var file = result[i]; var file = result[i];
fileSyncIndex = SYNC_PROVIDER_DROPBOX + encodeURIComponent(file.path.toLowerCase()); syncIndex = SYNC_PROVIDER_DROPBOX + encodeURIComponent(file.path.toLowerCase());
localStorage[fileSyncIndex + ".version"] = file.versionTag; localStorage[syncIndex + ".version"] = file.versionTag;
var contentCRC = core.crc32(file.content); var contentCRC = core.crc32(file.content);
localStorage[fileSyncIndex + ".contentCRC"] = contentCRC; localStorage[syncIndex + ".contentCRC"] = contentCRC;
var fileIndex = fileManager.createFile(file.name, file.content, [fileSyncIndex]); var fileIndex = fileManager.createFile(file.name, file.content, [syncIndex]);
fileManager.selectFile(fileIndex); fileManager.selectFile(fileIndex);
core.showMessage('"' + file.name + '" imported successfully from Dropbox.'); core.showMessage('"' + file.name + '" imported successfully from Dropbox.');
} }

36
js/dropbox-provider.js Normal file
View File

@ -0,0 +1,36 @@
define(["jquery", "dropbox-helper"], function($, dropboxHelper) {
// Dependencies
var core = undefined;
var dropboxProvider = {
providerType: PROVIDER_TYPE_PUBLISH_FLAG,
providerId: PROVIDER_DROPBOX,
providerName: "Dropbox",
defaultPublishFormat: "template"
};
dropboxProvider.publish = function(publishAttributes, title, content, callback) {
var path = dropboxHelper.checkPath(publishAttributes.path);
if(path === undefined) {
callback(true);
return;
}
dropboxHelper.upload(path, content, callback);
};
dropboxProvider.newPublishAttributes = function(event) {
var publishAttributes = {};
publishAttributes.path = core.getInputValue($("#input-publish-dropbox-path"), event);
if(event.isPropagationStopped()) {
return undefined;
}
return publishAttributes;
};
dropboxProvider.init = function(coreModule) {
core = coreModule;
};
return dropboxProvider;
});

View File

@ -301,8 +301,8 @@ define(["jquery", "google-helper", "dropbox-helper", "github-helper", "synchroni
var fileIndex = fileManager.getCurrentFileIndex(); var fileIndex = fileManager.getCurrentFileIndex();
var content = localStorage[fileIndex + ".content"]; var content = localStorage[fileIndex + ".content"];
var title = localStorage[fileIndex + ".title"]; var title = localStorage[fileIndex + ".title"];
dropboxHelper.upload(path, content, function(syncIndex) { dropboxHelper.upload(path, content, function(error, syncIndex) {
if (syncIndex === undefined) { if (error) {
return; return;
} }
var contentCRC = core.crc32(content); var contentCRC = core.crc32(content);
@ -315,8 +315,8 @@ define(["jquery", "google-helper", "dropbox-helper", "github-helper", "synchroni
}); });
} }
function importDropbox(paths) { function importDropbox(error, paths) {
if(paths === undefined) { if(error) {
return; return;
} }
var importPaths = []; var importPaths = [];

View File

@ -1,4 +1,4 @@
define(["jquery", "github-provider", "blogger-provider", "underscore"], function($) { define(["jquery", "github-provider", "blogger-provider", "dropbox-provider", "underscore"], function($) {
// Dependencies // Dependencies
var core = undefined; var core = undefined;
@ -131,6 +131,7 @@ define(["jquery", "github-provider", "blogger-provider", "underscore"], function
function initNewLocation(provider) { function initNewLocation(provider) {
var defaultPublishFormat = provider.defaultPublishFormat || "markdown"; var defaultPublishFormat = provider.defaultPublishFormat || "markdown";
newLocationProvider = provider; newLocationProvider = provider;
$(".publish-provider-name").text(provider.providerName);
// Show/hide controls depending on provider // Show/hide controls depending on provider
$('div[class*=" modal-publish-"]').hide().filter(".modal-publish-" + provider.providerId).show(); $('div[class*=" modal-publish-"]').hide().filter(".modal-publish-" + provider.providerId).show();

View File

@ -89,16 +89,14 @@ define(["jquery", "google-helper", "dropbox-helper"], function($, googleHelper,
} else if (fileSyncIndex.indexOf(SYNC_PROVIDER_DROPBOX) === 0) { } else if (fileSyncIndex.indexOf(SYNC_PROVIDER_DROPBOX) === 0) {
var path = fileSyncIndex.substring(SYNC_PROVIDER_DROPBOX.length); var path = fileSyncIndex.substring(SYNC_PROVIDER_DROPBOX.length);
path = decodeURIComponent(path); path = decodeURIComponent(path);
dropboxHelper.upload(path, uploadContent, function(result) { dropboxHelper.upload(path, uploadContent, function(error, result) {
if (result !== undefined) { if (error) {
localStorage[fileSyncIndex + ".contentCRC"] = uploadContentCRC; // If error we abort the synchronization (retry later)
locationUp(callback); callback(error);
return; return;
} }
localStorage[fileSyncIndex + ".contentCRC"] = uploadContentCRC;
// If error we abort the synchronization (retry later) locationUp(callback);
callback("abort");
return;
}); });
} else { } else {
// This should never happen // This should never happen
@ -236,14 +234,14 @@ define(["jquery", "google-helper", "dropbox-helper"], function($, googleHelper,
return; return;
} }
var lastChangeId = localStorage[SYNC_PROVIDER_DROPBOX + "lastChangeId"]; var lastChangeId = localStorage[SYNC_PROVIDER_DROPBOX + "lastChangeId"];
dropboxHelper.checkUpdates(lastChangeId, function(changes, newChangeId) { dropboxHelper.checkUpdates(lastChangeId, function(error, changes, newChangeId) {
if (changes === undefined) { if (error) {
callback("error"); callback(error);
return; return;
} }
dropboxHelper.downloadContent(changes, function(changes) { dropboxHelper.downloadContent(changes, function(error, changes) {
if (changes === undefined) { if (error) {
callback("error"); callback(error);
return; return;
} }
var updateFileTitles = false; var updateFileTitles = false;