Better error management

This commit is contained in:
benweet 2013-04-28 00:16:38 +01:00
parent df2109206a
commit 0adeb3a349
13 changed files with 212 additions and 153 deletions

View File

@ -1 +1 @@
CACHE MANIFEST # v14 CACHE: index.html css/main-min.css js/main-min.js js/require.js img/ajax-loader.gif img/glyphicons-halflings.png img/glyphicons-halflings-white.png img/icons.png img/stackedit-32.ico img/stackedit-promo.png NETWORK: * CACHE MANIFEST # v15 CACHE: index.html css/main-min.css js/main-min.js js/require.js img/ajax-loader.gif img/glyphicons-halflings.png img/glyphicons-halflings-white.png img/icons.png img/stackedit-32.ico img/stackedit-promo.png NETWORK: *

7
css/main-min.css vendored
View File

@ -5565,13 +5565,16 @@ hr {
height: 16px; height: 16px;
background-position: -109px 0; background-position: -109px 0;
} }
.icon-spinner { .working-indicator {
background-image: url("../img/ajax-loader.gif"); background-image: none;
width: 43px; width: 43px;
height: 11px; height: 11px;
background-position: 0 0; background-position: 0 0;
margin: 14px 15px 0; margin: 14px 15px 0;
} }
.working-indicator.show {
background-image: url("../img/ajax-loader.gif");
}
.ui-layout-toggler-north .caret, .ui-layout-toggler-south .caret { .ui-layout-toggler-north .caret, .ui-layout-toggler-south .caret {
margin-top: 5px; margin-top: 5px;
} }

View File

@ -274,14 +274,18 @@ hr {
background-position: -109px 0; background-position: -109px 0;
} }
.icon-spinner { .working-indicator {
background-image: url("../img/ajax-loader.gif"); background-image: none;
width: 43px; width: 43px;
height: 11px; height: 11px;
background-position: 0 0; background-position: 0 0;
margin: 14px 15px 0; margin: 14px 15px 0;
} }
.working-indicator.show {
background-image: url("../img/ajax-loader.gif");
}
.ui-layout-toggler-north .caret, .ui-layout-toggler-south .caret { .ui-layout-toggler-north .caret, .ui-layout-toggler-south .caret {
margin-top: 5px; margin-top: 5px;
} }

View File

@ -111,7 +111,7 @@
</ul></li> </ul></li>
</ul> </ul>
<ul class="nav pull-right"> <ul class="nav pull-right">
<li><i class="working-indicator icon-spinner hide"></i></li> <li><i class="working-indicator icon-none"></i></li>
<li><a class="brand" id="file-title" href="#" <li><a class="brand" id="file-title" href="#"
title="Rename current document"> </a></li> title="Rename current document"> </a></li>
<li class="navbar-form"><input id="file-title-input" <li class="navbar-form"><input id="file-title-input"
@ -321,7 +321,8 @@
</div> </div>
</div> </div>
<div class="control-group modal-publish-blogger"> <div class="control-group modal-publish-blogger">
<label class="control-label" for="input-publish-blogger-labels">Labels (comma separated)</label> <label class="control-label" for="input-publish-blogger-labels">Labels
(comma separated)</label>
<div class="controls"> <div class="controls">
<input type="text" id="input-publish-blogger-labels" <input type="text" id="input-publish-blogger-labels"
placeholder="Label1, Label2"> placeholder="Label1, Label2">
@ -344,23 +345,21 @@
</div> </div>
</div> </div>
<div class="control-group modal-publish-gdrive"> <div class="control-group modal-publish-gdrive">
<div class="controls muted"> <div class="controls muted">If no file ID is supplied, the
If no file ID is supplied, the file will be created file will be created into your Google Drive root folder. You can
into your Google Drive root folder. You can move the file afterwards within move the file afterwards within Google Drive.</div>
Google Drive.
</div>
</div> </div>
<div class="control-group modal-publish-gdrive"> <div class="control-group modal-publish-gdrive">
<label class="control-label" for="input-publish-gdrive-filename">Force file name (optional)</label> <label class="control-label" for="input-publish-gdrive-filename">Force
file name (optional)</label>
<div class="controls"> <div class="controls">
<input type="text" id="input-publish-gdrive-filename" <input type="text" id="input-publish-gdrive-filename"
placeholder="File name"> placeholder="File name">
</div> </div>
</div> </div>
<div class="control-group modal-publish-gdrive"> <div class="control-group modal-publish-gdrive">
<div class="controls muted"> <div class="controls muted">If no file name is supplied, the
If no file name is supplied, the document title will be used. document title will be used.</div>
</div>
</div> </div>
<div class="control-group"> <div class="control-group">
@ -435,8 +434,9 @@
</div> </div>
</div> </div>
<div class="control-group"> <div class="control-group">
<label class="control-label" for="input-settings-scroll-link">Scroll Link <a <label class="control-label" for="input-settings-scroll-link">Scroll
href="#" class="tooltip-scroll-link">(?)</a></label> Link <a href="#" class="tooltip-scroll-link">(?)</a>
</label>
<div class="controls"> <div class="controls">
<input type="checkbox" id="input-settings-scroll-link" /> <input type="checkbox" id="input-settings-scroll-link" />
</div> </div>
@ -540,7 +540,9 @@
<a target="_blank" href="http://twitter.github.io/bootstrap/">Bootstrap</a> <a target="_blank" href="http://twitter.github.io/bootstrap/">Bootstrap</a>
</dd> </dd>
<dd> <dd>
<a target="_blank" href="https://github.com/rafaelp/css_browser_selector/">CSS Browser Selector</a> <a target="_blank"
href="https://github.com/rafaelp/css_browser_selector/">CSS
Browser Selector</a>
</dd> </dd>
<dd> <dd>
<a target="_blank" href="https://github.com/dropbox/dropbox-js">Dropbox-js</a> <a target="_blank" href="https://github.com/dropbox/dropbox-js">Dropbox-js</a>
@ -587,13 +589,14 @@
href="http://www.apache.org/licenses/LICENSE-2.0">Apache License</a></p> href="http://www.apache.org/licenses/LICENSE-2.0">Apache License</a></p>
</div> </div>
<div class="modal-footer"> <div class="modal-footer">
<a href="#" class="btn btn-primary" data-dismiss="modal">Close</a> <a href="#" class="btn action-welcome-file" data-dismiss="modal">Welcome
document</a> <a href="#" class="btn btn-primary" data-dismiss="modal">Close</a>
</div> </div>
</div> </div>
<div id="modal-non-unique" class="modal hide"> <div id="modal-non-unique" class="modal hide">
<div class="modal-header"> <div class="modal-header">
<h3>Stopped...</h3> <h3>Whoops...</h3>
</div> </div>
<div class="modal-body"> <div class="modal-body">
<p>StackEdit has stopped because another instance was running in <p>StackEdit has stopped because another instance was running in

View File

@ -470,6 +470,7 @@
Markdown.Extra.prototype.all = function(text) { Markdown.Extra.prototype.all = function(text) {
text = this.tables(text); text = this.tables(text);
text = this.fencedCodeBlocks(text); text = this.fencedCodeBlocks(text);
text = this.definitionLists(text);
return text; return text;
}; };

View File

@ -79,7 +79,10 @@ define([ "core", "underscore" ], function(core) {
if (task.finished === true) { if (task.finished === true) {
return; return;
} }
error = error || "Unknown error"; error = error || new Error("Unknown error");
if(error.message) {
core.showError(error.message);
}
runSafe(task, task.errorCallbacks, error); runSafe(task, task.errorCallbacks, error);
// Exit the current call stack // Exit the current call stack
throw error; throw error;
@ -87,13 +90,14 @@ define([ "core", "underscore" ], function(core) {
/** /**
* retry() can be called in an onRun callback to restart the task * retry() can be called in an onRun callback to restart the task
*/ */
task.retry = function() { task.retry = function(error, maxRetryCounter) {
if (task.finished === true) { if (task.finished === true) {
return; return;
} }
maxRetryCounter = maxRetryCounter || 5;
task.queue = undefined; task.queue = undefined;
if (task.retryCounter === 5) { if (task.retryCounter >= maxRetryCounter) {
task.error(new Error("Maximum retry number reached")); task.error(error);
return; return;
} }
// Implement an exponential backoff // Implement an exponential backoff
@ -112,9 +116,7 @@ define([ "core", "underscore" ], function(core) {
if (currentTaskRunning === true) { if (currentTaskRunning === true) {
// If the current task takes too long // If the current task takes too long
if (currentTaskStartTime + currentTask.timeout < core.currentTime) { if (currentTaskStartTime + currentTask.timeout < core.currentTime) {
var errorMsg = "A timeout occurred."; currentTask.error(new Error("A timeout occurred."));
core.showError(errorMsg);
currentTask.error(new Error(errorMsg));
} }
return; return;
} }

View File

@ -16,6 +16,7 @@ var PROVIDER_BLOGGER = "blogger";
var PROVIDER_DROPBOX = "dropbox"; var PROVIDER_DROPBOX = "dropbox";
var PROVIDER_GDRIVE = "gdrive"; var PROVIDER_GDRIVE = "gdrive";
var PROVIDER_GITHUB = "github"; var PROVIDER_GITHUB = "github";
var WELCOME_DOCUMENT_TITLE = "Welcome document";
// Use by Google's client.js // Use by Google's client.js
var delayedFunction = undefined; var delayedFunction = undefined;

View File

@ -127,10 +127,10 @@ define(
// Used by asyncRunner // Used by asyncRunner
core.showWorkingIndicator = function(show) { core.showWorkingIndicator = function(show) {
if (show === false) { if (show === false) {
$(".working-indicator").addClass("hide"); $(".working-indicator").removeClass("show");
$("body").removeClass("working"); $("body").removeClass("working");
} else { } else {
$(".working-indicator").removeClass("hide"); $(".working-indicator").addClass("show");
$("body").addClass("working"); $("body").addClass("working");
} }
}; };
@ -293,7 +293,7 @@ define(
var offset = 0, mdSectionOffset = 0; var offset = 0, mdSectionOffset = 0;
function addMdSection(sectionText) { function addMdSection(sectionText) {
var sectionHeight = padding; var sectionHeight = padding;
if(sectionText) { if(sectionText !== undefined) {
textareaElt.val(sectionText); textareaElt.val(sectionText);
sectionHeight += textareaElt.prop('scrollHeight'); sectionHeight += textareaElt.prop('scrollHeight');
} }
@ -313,7 +313,11 @@ define(
if(title) { if(title) {
// We just found a title which means end of the previous section // We just found a title which means end of the previous section
// Exclude last \n of the section // Exclude last \n of the section
addMdSection(text.substring(offset, matchOffset-1)); var sectionText = undefined;
if(matchOffset > offset) {
sectionText = text.substring(offset, matchOffset-1);
}
addMdSection(sectionText);
offset = matchOffset; offset = matchOffset;
} }
return ""; return "";
@ -358,8 +362,9 @@ define(
lastEditorScrollTop = -9; lastEditorScrollTop = -9;
lastPreviewScrollTop = -9; lastPreviewScrollTop = -9;
scrollLink(); scrollLink();
}, 800); }, 500);
// -9 is less than -5
var lastEditorScrollTop = -9; var lastEditorScrollTop = -9;
var lastPreviewScrollTop = -9; var lastPreviewScrollTop = -9;
var scrollLink = _.debounce(function() { var scrollLink = _.debounce(function() {
@ -379,11 +384,12 @@ define(
}); });
if(srcSection === undefined) { if(srcSection === undefined) {
// Something wrong in the algorithm... // Something wrong in the algorithm...
return 0; return -9;
} }
var posInSection = (srcScrollTop - srcSection.startOffset) / srcSection.height; var posInSection = (srcScrollTop - srcSection.startOffset) / srcSection.height;
var destSection = destSectionList[sectionIndex]; var destSection = destSectionList[sectionIndex];
var destScrollTop = destSection.startOffset + destSection.height * posInSection; var destScrollTop = destSection.startOffset + destSection.height * posInSection;
destScrollTop = _.min([destScrollTop, destElt.prop('scrollHeight') - destElt.outerHeight()]);
destElt.animate({scrollTop: destScrollTop}, 800, function() { destElt.animate({scrollTop: destScrollTop}, 800, function() {
lastEditorScrollTop = editorElt.scrollTop(); lastEditorScrollTop = editorElt.scrollTop();
lastPreviewScrollTop = previewElt.scrollTop(); lastPreviewScrollTop = previewElt.scrollTop();
@ -396,7 +402,7 @@ define(
else if(Math.abs(previewScrollTop - lastPreviewScrollTop) > 5) { else if(Math.abs(previewScrollTop - lastPreviewScrollTop) > 5) {
editorScrollTop = animate(previewScrollTop, htmlSectionList, editorElt, mdSectionList); editorScrollTop = animate(previewScrollTop, htmlSectionList, editorElt, mdSectionList);
} }
}, 1200); }, 1000);
// Create the layout // Create the layout
var layout = undefined; var layout = undefined;
@ -486,6 +492,11 @@ define(
// Modify scroll position of the preview not the editor // Modify scroll position of the preview not the editor
lastEditorScrollTop = -9; lastEditorScrollTop = -9;
buildSections(); buildSections();
// Preview may change if images are loading
$("#wmd-preview img").load(function() {
lastEditorScrollTop = -9;
buildSections();
});
}); });
} }
// Custom insert link dialog // Custom insert link dialog

View File

@ -10,8 +10,7 @@ define(["jquery", "core", "async-runner"], function($, core, asyncRunner) {
task.onRun(function() { task.onRun(function() {
if(core.isOffline === true) { if(core.isOffline === true) {
client = undefined; client = undefined;
core.showMessage("Operation not available in offline mode."); task.error(new Error("Operation not available in offline mode."));
task.error();
return; return;
} }
if (client !== undefined) { if (client !== undefined) {
@ -31,9 +30,12 @@ define(["jquery", "core", "async-runner"], function($, core, asyncRunner) {
rememberUser: true rememberUser: true
})); }));
task.chain(); task.chain();
}).fail(function() { }).fail(function(jqXHR) {
core.setOffline(); var error = {
task.error(new Error("Network timeout|stopPublish")); status: jqXHR.status,
responseText: jqXHR.statusText
};
handleError(error, task);
}); });
}); });
} }
@ -67,9 +69,7 @@ define(["jquery", "core", "async-runner"], function($, core, asyncRunner) {
return; return;
} }
// Error // Error
var errorMsg = "Access to Dropbox account is not authorized."; task.error(new Error("Access to Dropbox account is not authorized."));
core.showError(errorMsg);
task.error(new Error(errorMsg));
}); });
} }
task.chain(localAuthenticate); task.chain(localAuthenticate);
@ -93,7 +93,7 @@ define(["jquery", "core", "async-runner"], function($, core, asyncRunner) {
if(error.status === Dropbox.ApiError.INVALID_PARAM) { if(error.status === Dropbox.ApiError.INVALID_PARAM) {
error = 'Could not upload document into path "' + path + '".'; error = 'Could not upload document into path "' + path + '".';
} }
handleError(error, task, callback); handleError(error, task);
}); });
}); });
task.onSuccess(function() { task.onSuccess(function() {
@ -116,7 +116,7 @@ define(["jquery", "core", "async-runner"], function($, core, asyncRunner) {
function retrievePageOfChanges() { function retrievePageOfChanges() {
client.pullChanges(newChangeId, function(error, pullChanges) { client.pullChanges(newChangeId, function(error, pullChanges) {
if (error) { if (error) {
handleError(error, task, callback); handleError(error, task);
return; return;
} }
// Retrieve success // Retrieve success
@ -161,7 +161,7 @@ define(["jquery", "core", "async-runner"], function($, core, asyncRunner) {
task.chain(recursiveDownloadMetadata); task.chain(recursiveDownloadMetadata);
return; return;
} }
handleError(error, task, callback); handleError(error, task);
}); });
} }
task.chain(recursiveDownloadMetadata); task.chain(recursiveDownloadMetadata);
@ -208,7 +208,7 @@ define(["jquery", "core", "async-runner"], function($, core, asyncRunner) {
recursiveDownloadContent(); recursiveDownloadContent();
return; return;
} }
handleError(error, task, callback); handleError(error, task);
}); });
} }
task.chain(recursiveDownloadContent); task.chain(recursiveDownloadContent);
@ -222,17 +222,23 @@ define(["jquery", "core", "async-runner"], function($, core, asyncRunner) {
asyncRunner.addTask(task); asyncRunner.addTask(task);
}; };
function handleError(error, task, callback) { function handleError(error, task) {
var errorMsg = true; var errorMsg = true;
if (error) { if (error) {
console.error(error); console.error(error);
// Try to analyze the error // Try to analyze the error
if (typeof error === "string") { if (typeof error === "string") {
errorMsg = error; errorMsg = error;
} else if (error.status === Dropbox.ApiError.INVALID_TOKEN }
else {
errorMsg = "Dropbox error ("
+ error.status + ": " + error.responseText + ").";
if (error.status === Dropbox.ApiError.INVALID_TOKEN
|| error.status === Dropbox.ApiError.OAUTH_ERROR) { || error.status === Dropbox.ApiError.OAUTH_ERROR) {
authenticated = false; authenticated = false;
task.retry(); errorMsg = "Access to Dropbox account is not authorized.";
task.retry(new Error(errorMsg), 1);
return; return;
} else if(error.status === Dropbox.ApiError.INVALID_PARAM && error.responseText } else if(error.status === Dropbox.ApiError.INVALID_PARAM && error.responseText
.indexOf("oauth_nonce") !== -1) { .indexOf("oauth_nonce") !== -1) {
@ -244,18 +250,15 @@ define(["jquery", "core", "async-runner"], function($, core, asyncRunner) {
} }
}); });
authenticated = false; authenticated = false;
task.retry(); task.retry(new Error(errorMsg), 1);
return; return;
} else if (error.status === Dropbox.ApiError.NETWORK_ERROR) { } else if (error.status === Dropbox.ApiError.NETWORK_ERROR || error.status < 0) {
client = undefined; client = undefined;
authenticated = false; authenticated = false;
core.setOffline(); core.setOffline();
errorMsg = "|stopPublish"; errorMsg = "|stopPublish";
} else {
errorMsg = "Dropbox error ("
+ error.status + ").";
} }
core.showError(errorMsg); }
} }
task.error(new Error(errorMsg)); task.error(new Error(errorMsg));
} }
@ -273,9 +276,12 @@ define(["jquery", "core", "async-runner"], function($, core, asyncRunner) {
}).done(function() { }).done(function() {
pickerLoaded = true; pickerLoaded = true;
task.chain(); task.chain();
}).fail(function() { }).fail(function(jqXHR) {
core.setOffline(); var error = {
task.error(); status: jqXHR.status,
responseText: jqXHR.statusText
};
handleError(error, task);
}); });
}); });
} }

View File

@ -1,5 +1,5 @@
define(["jquery", "core", "synchronizer", "publisher", "underscore"], define(["jquery", "core", "synchronizer", "publisher", "text!../WELCOME.md", "underscore"],
function($, core, synchronizer, publisher) { function($, core, synchronizer, publisher, welcomeContent) {
var fileManager = {}; var fileManager = {};
@ -28,7 +28,7 @@ define(["jquery", "core", "synchronizer", "publisher", "underscore"],
fileManager.selectFile = function(fileIndex) { fileManager.selectFile = function(fileIndex) {
// If no file create one // If no file create one
if (localStorage["file.list"].length === 1) { if (localStorage["file.list"].length === 1) {
fileIndex = this.createFile(); fileIndex = fileManager.createFile(WELCOME_DOCUMENT_TITLE, welcomeContent);
} }
if(fileIndex !== undefined) { if(fileIndex !== undefined) {
@ -272,6 +272,10 @@ define(["jquery", "core", "synchronizer", "publisher", "underscore"],
var title = localStorage[fileManager.getCurrentFileIndex() + ".title"]; var title = localStorage[fileManager.getCurrentFileIndex() + ".title"];
core.saveFile(content, title + ".txt"); core.saveFile(content, title + ".txt");
}); });
$(".action-welcome-file").click(function() {
var fileIndex = fileManager.createFile(WELCOME_DOCUMENT_TITLE, welcomeContent);
fileManager.selectFile(fileIndex);
});
}); });
core.setFileManager(fileManager); core.setFileManager(fileManager);

View File

@ -10,8 +10,7 @@ define(["jquery", "core", "async-runner"], function($, core, asyncRunner) {
task.onRun(function() { task.onRun(function() {
if(core.isOffline === true) { if(core.isOffline === true) {
connected = false; connected = false;
core.showMessage("Operation not available in offline mode."); task.error(new Error("Operation not available in offline mode."));
task.error();
return; return;
} }
if (connected === true) { if (connected === true) {
@ -24,9 +23,12 @@ define(["jquery", "core", "async-runner"], function($, core, asyncRunner) {
}).done(function() { }).done(function() {
connected = true; connected = true;
task.chain(); task.chain();
}).fail(function() { }).fail(function(jqXHR) {
core.setOffline(); var error = {
task.error(new Error("Network timeout|stopPublish")); error: jqXHR.status,
message: jqXHR.statusText
};
handleError(error, task);
}); });
}); });
} }
@ -50,6 +52,7 @@ define(["jquery", "core", "async-runner"], function($, core, asyncRunner) {
return; return;
} }
core.showMessage("Please make sure the Github authorization popup is not blocked by your browser."); core.showMessage("Please make sure the Github authorization popup is not blocked by your browser.");
var errorMsg = "Failed to retrieve a token from GitHub.";
// We add time for user to enter his credentials // We add time for user to enter his credentials
task.timeout = ASYNC_TASK_LONG_TIMEOUT; task.timeout = ASYNC_TASK_LONG_TIMEOUT;
var code = undefined; var code = undefined;
@ -66,7 +69,7 @@ define(["jquery", "core", "async-runner"], function($, core, asyncRunner) {
intervalId = undefined; intervalId = undefined;
code = localStorage["githubCode"]; code = localStorage["githubCode"];
if(code === undefined) { if(code === undefined) {
task.error(); task.error(new Error(errorMsg));
return; return;
} }
localStorage.removeItem("githubCode"); localStorage.removeItem("githubCode");
@ -86,7 +89,7 @@ define(["jquery", "core", "async-runner"], function($, core, asyncRunner) {
task.chain(); task.chain();
} }
else { else {
task.error(); task.error(new Error(errorMsg));
} }
}); });
} }
@ -113,7 +116,7 @@ define(["jquery", "core", "async-runner"], function($, core, asyncRunner) {
var user = github.getUser(); var user = github.getUser();
user.show(undefined, function(err, result) { user.show(undefined, function(err, result) {
if(err) { if(err) {
task.error(err); handleError(err, task);
return; return;
} }
userLogin = result.login; userLogin = result.login;
@ -124,7 +127,7 @@ define(["jquery", "core", "async-runner"], function($, core, asyncRunner) {
var repo = github.getRepo(userLogin, reponame); var repo = github.getRepo(userLogin, reponame);
repo.write(branch, path, content, commitMsg, function(err) { repo.write(branch, path, content, commitMsg, function(err) {
if(err) { if(err) {
task.error(err); handleError(err, task);
return; return;
} }
task.chain(); task.chain();
@ -135,27 +138,37 @@ define(["jquery", "core", "async-runner"], function($, core, asyncRunner) {
task.onSuccess(function() { task.onSuccess(function() {
callback(); callback();
}); });
task.onError(function(err) { task.onError(function(error) {
var errorMsg = "Could not publish on GitHub."; callback(error);
if(err !== undefined) {
console.error(err);
if(err.error === 401 || err.error === 403) {
github = undefined;
// Token must be renewed
localStorage.removeItem("githubToken");
errorMsg = "Access to GitHub is not authorized.";
}
else if(err.error === 0) {
connected = false;
github = undefined;
core.setOffline();
}
}
core.showError(errorMsg);
callback(errorMsg);
}); });
asyncRunner.addTask(task); asyncRunner.addTask(task);
}; };
function handleError(error, task) {
var errorMsg = undefined;
if (error) {
console.error(error);
// Try to analyze the error
if (typeof error === "string") {
errorMsg = error;
}
else {
errorMsg = "Could not publish on GitHub.";
if (error.error === 401 || error.error === 403) {
github = undefined;
errorMsg = "Access to GitHub account is not authorized.";
task.retry(new Error(errorMsg), 1);
return;
} else if (error.error <= 0) {
connected = false;
github = undefined;
core.setOffline();
errorMsg = "|stopPublish";
}
}
}
task.error(new Error(errorMsg));
}
return githubHelper; return githubHelper;
}); });

View File

@ -10,8 +10,7 @@ define(["jquery", "core", "async-runner"], function($, core, asyncRunner) {
task.onRun(function() { task.onRun(function() {
if(core.isOffline === true) { if(core.isOffline === true) {
connected = false; connected = false;
core.showMessage("Operation not available in offline mode."); task.error(new Error("Operation not available in offline mode."));
task.error();
return; return;
} }
if (connected === true) { if (connected === true) {
@ -25,9 +24,12 @@ define(["jquery", "core", "async-runner"], function($, core, asyncRunner) {
$.ajax({ $.ajax({
url : "https://apis.google.com/js/client.js?onload=runDelayedFunction", url : "https://apis.google.com/js/client.js?onload=runDelayedFunction",
dataType : "script", timeout : AJAX_TIMEOUT dataType : "script", timeout : AJAX_TIMEOUT
}).fail(function() { }).fail(function(jqXHR) {
core.setOffline(); var error = {
task.error(new Error("Network timeout|stopPublish")); code: jqXHR.status,
message: jqXHR.statusText
};
handleError(error, task);
}); });
}); });
} }
@ -58,9 +60,7 @@ define(["jquery", "core", "async-runner"], function($, core, asyncRunner) {
return; return;
} }
// Error // Error
var errorMsg = "Access to Google account is not authorized."; task.error(new Error("Access to Google account is not authorized."));
core.showError(errorMsg);
task.error(new Error(errorMsg));
return; return;
} }
// Success // Success
@ -137,7 +137,7 @@ define(["jquery", "core", "async-runner"], function($, core, asyncRunner) {
error = 'Conflict on file ID "' + fileId + '". Please restart the synchronization.'; error = 'Conflict on file ID "' + fileId + '". Please restart the synchronization.';
} }
} }
handleError(error, task, callback); handleError(error, task);
}); });
}); });
task.onSuccess(function() { task.onSuccess(function() {
@ -172,7 +172,7 @@ define(["jquery", "core", "async-runner"], function($, core, asyncRunner) {
request.execute(function(response) { request.execute(function(response) {
if (!response || !response.largestChangeId) { if (!response || !response.largestChangeId) {
// Handle error // Handle error
handleError(response.error, task, callback); handleError(response.error, task);
return; return;
} }
// Retrieve success // Retrieve success
@ -234,7 +234,7 @@ define(["jquery", "core", "async-runner"], function($, core, asyncRunner) {
if(error.code === 404) { if(error.code === 404) {
error = 'File ID "' + id + '" not found on Google Drive.'; error = 'File ID "' + id + '" not found on Google Drive.';
} }
handleError(error, task, callback); handleError(error, task);
}); });
} }
task.chain(recursiveDownloadMetadata); task.chain(recursiveDownloadMetadata);
@ -295,7 +295,7 @@ define(["jquery", "core", "async-runner"], function($, core, asyncRunner) {
message: jqXHR.statusText message: jqXHR.statusText
}; };
// Handle error // Handle error
handleError(error, task, callback); handleError(error, task);
}); });
} }
task.chain(recursiveDownloadContent); task.chain(recursiveDownloadContent);
@ -309,7 +309,7 @@ define(["jquery", "core", "async-runner"], function($, core, asyncRunner) {
asyncRunner.addTask(task); asyncRunner.addTask(task);
}; };
function handleError(error, task, callback) { function handleError(error, task) {
var errorMsg = undefined; var errorMsg = undefined;
if (error) { if (error) {
console.error(error); console.error(error);
@ -317,24 +317,25 @@ define(["jquery", "core", "async-runner"], function($, core, asyncRunner) {
if (typeof error === "string") { if (typeof error === "string") {
errorMsg = error; errorMsg = error;
} }
else if (error.code >= 500 && error.code < 600) { else {
errorMsg = "Google error (" + error.code + ": "
+ error.message + ").";
if (error.code >= 500 && error.code < 600) {
// Retry as described in Google's best practices // Retry as described in Google's best practices
task.retry(); task.retry(new Error(errorMsg));
return; return;
} else if (error.code === 401 || error.code === 403) { } else if (error.code === 401 || error.code === 403) {
authenticated = false; authenticated = false;
task.retry(); errorMsg = "Access to Google account is not authorized.";
task.retry(new Error(errorMsg), 1);
return; return;
} else if (error.code <= 0) { } else if (error.code <= 0) {
connected = false; connected = false;
authenticated = false; authenticated = false;
core.setOffline(); core.setOffline();
errorMsg = "|stopPublish"; errorMsg = "|stopPublish";
} else {
errorMsg = "Google error (" + error.code + ": "
+ error.message + ").";
} }
core.showError(errorMsg); }
} }
task.error(new Error(errorMsg)); task.error(new Error(errorMsg));
} }
@ -353,9 +354,12 @@ define(["jquery", "core", "async-runner"], function($, core, asyncRunner) {
}).done(function() { }).done(function() {
google.load('picker', '1', {callback: task.chain}); google.load('picker', '1', {callback: task.chain});
pickerLoaded = true; pickerLoaded = true;
}).fail(function() { }).fail(function(jqXHR) {
core.setOffline(); var error = {
task.error(new Error("Network timeout")); code: jqXHR.status,
message: jqXHR.statusText
};
handleError(error, task);
}); });
}); });
} }
@ -364,6 +368,12 @@ define(["jquery", "core", "async-runner"], function($, core, asyncRunner) {
callback = callback || core.doNothing; callback = callback || core.doNothing;
var ids = []; var ids = [];
var picker = undefined; var picker = undefined;
function hidePicker() {
if(picker !== undefined) {
picker.setVisible(false);
$(".modal-backdrop, .picker").remove();
}
}
var task = asyncRunner.createTask(); var task = asyncRunner.createTask();
connect(task); connect(task);
loadPicker(task); loadPicker(task);
@ -388,14 +398,13 @@ define(["jquery", "core", "async-runner"], function($, core, asyncRunner) {
ids.push(data.docs[i].id); ids.push(data.docs[i].id);
} }
} }
$(".modal-backdrop, .picker").remove(); hidePicker();
task.chain(); task.chain();
} }
}); });
picker = pickerBuilder.build(); picker = pickerBuilder.build();
$("body").append($("<div>").addClass("modal-backdrop").click(function() { $("body").append($("<div>").addClass("modal-backdrop").click(function() {
picker.setVisible(false); hidePicker();
$(".modal-backdrop, .picker").remove();
task.chain(); task.chain();
})); }));
picker.setVisible(true); picker.setVisible(true);
@ -404,11 +413,7 @@ define(["jquery", "core", "async-runner"], function($, core, asyncRunner) {
callback(undefined, ids); callback(undefined, ids);
}); });
task.onError(function(error) { task.onError(function(error) {
if(picker !== undefined) { hidePicker();
picker.setVisible(false);
$(".modal-backdrop, .picker").remove();
task.chain();
}
callback(error); callback(error);
}); });
asyncRunner.addTask(task); asyncRunner.addTask(task);
@ -459,7 +464,7 @@ define(["jquery", "core", "async-runner"], function($, core, asyncRunner) {
if(error.code === 404 && postId !== undefined) { if(error.code === 404 && postId !== undefined) {
error = 'Post ' + postId + ' not found on Blogger.|removePublish'; error = 'Post ' + postId + ' not found on Blogger.|removePublish';
} }
handleError(error, task, callback); handleError(error, task);
}); });
} }
function getBlogId() { function getBlogId() {
@ -485,7 +490,7 @@ define(["jquery", "core", "async-runner"], function($, core, asyncRunner) {
if(error.code === 404) { if(error.code === 404) {
error = 'Blog "' + blogUrl + '" not found on Blogger.|removePublish'; error = 'Blog "' + blogUrl + '" not found on Blogger.|removePublish';
} }
handleError(error, task, callback); handleError(error, task);
}); });
} }
task.chain(getBlogId); task.chain(getBlogId);

8
js/main-min.js vendored

File diff suppressed because one or more lines are too long