Import files from disk

This commit is contained in:
benweet 2013-06-16 11:47:35 +01:00
parent b3edbdd0c2
commit d334dfe2f8
26 changed files with 627 additions and 882 deletions

View File

@ -2,12 +2,10 @@
@page { @page {
margin: 25mm 25mm 25mm 25mm; margin: 25mm 25mm 25mm 25mm;
} }
#wmd-preview { #wmd-preview {
padding: 0px; padding: 0px;
margin: 0px; margin: 0px;
} }
#navbar { #navbar {
display: none; display: none;
} }
@ -60,48 +58,29 @@ div, span, a, ul, li, textarea, input, button {
border-bottom-color: #ddd !important; border-bottom-color: #ddd !important;
} }
input, input,select,textarea,.input-prepend .btn,.input-prepend .add-on {
select,
textarea,
.input-prepend .btn,
.input-prepend .add-on {
border: 1px solid #ddd !important; border: 1px solid #ddd !important;
} }
.modal textarea:focus, .modal textarea:focus,input[type="text"]:focus,input[type="password"]:focus,input[type="datetime"]:focus,input[type="datetime-local"]:focus,input[type="date"]:focus,input[type="month"]:focus,input[type="time"]:focus,input[type="week"]:focus,input[type="number"]:focus,input[type="email"]:focus,input[type="url"]:focus,input[type="search"]:focus,input[type="tel"]:focus,input[type="color"]:focus,.uneditable-input:focus
input[type="text"]:focus,
input[type="password"]:focus,
input[type="datetime"]:focus,
input[type="datetime-local"]:focus,
input[type="date"]:focus,
input[type="month"]:focus,
input[type="time"]:focus,
input[type="week"]:focus,
input[type="number"]:focus,
input[type="email"]:focus,
input[type="url"]:focus,
input[type="search"]:focus,
input[type="tel"]:focus,
input[type="color"]:focus,
.uneditable-input:focus
{ {
-webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(128, 128, 128, 0.6) !important; -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px
-moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(128, 128, 128, 0.6) !important; rgba(128, 128, 128, 0.6) !important;
box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(128, 128, 128, 0.6) !important; -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px
rgba(128, 128, 128, 0.6) !important;
box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px
rgba(128, 128, 128, 0.6) !important;
} }
input:-moz-placeholder, input:-moz-placeholder,textarea:-moz-placeholder {
textarea:-moz-placeholder {
color: #ccc; color: #ccc;
} }
input:-ms-input-placeholder, input:-ms-input-placeholder,textarea:-ms-input-placeholder {
textarea:-ms-input-placeholder {
color: #ccc; color: #ccc;
} }
input::-webkit-input-placeholder, input::-webkit-input-placeholder,textarea::-webkit-input-placeholder {
textarea::-webkit-input-placeholder {
color: #ccc; color: #ccc;
} }
@ -111,30 +90,28 @@ textarea::-webkit-input-placeholder {
line-height: 17px; line-height: 17px;
} }
.modal textarea.error, .modal textarea.error,.modal input.error {
.modal input.error {
border-color: #ff8661 !important; border-color: #ff8661 !important;
-webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(255, 134, 97, 0.6) !important; -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px
-moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(255, 134, 97, 0.6) !important; rgba(255, 134, 97, 0.6) !important;
box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(255, 134, 97, 0.6) !important; -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px
rgba(255, 134, 97, 0.6) !important;
box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px
rgba(255, 134, 97, 0.6) !important;
} }
.navbar-inner .btn { .navbar-inner .btn {
background-color: #ddd; background-color: #ddd;
} }
.navbar-inner .btn:hover, .navbar-inner .btn:hover,.navbar-inner .btn:focus,.navbar-inner .btn:active,.navbar-inner .btn.active,.btn-group.open .btn.dropdown-toggle
.navbar-inner .btn:focus, {
.navbar-inner .btn:active,
.navbar-inner .btn.active,
.btn-group.open .btn.dropdown-toggle {
color: #333333; color: #333333;
background-color: #eee; background-color: #eee;
} }
.nav .dropdown-toggle .caret, .nav .dropdown-toggle .caret,.nav .dropdown-toggle:hover .caret,.nav .dropdown-toggle:focus .caret
.nav .dropdown-toggle:hover .caret, {
.nav .dropdown-toggle:focus .caret {
border-top-color: #000; border-top-color: #000;
border-bottom-color: #000; border-bottom-color: #000;
} }
@ -143,27 +120,20 @@ textarea::-webkit-input-placeholder {
display: none; display: none;
} }
.navbar-inner .btn.disabled, .navbar-inner .btn.disabled,.navbar-inner .btn[disabled] {
.navbar-inner .btn[disabled] {
color: #333333; color: #333333;
background-color: #ddd; background-color: #ddd;
opacity: 0.3; opacity: 0.3;
filter: alpha(opacity = 30); filter: alpha(opacity = 30);
} }
.dropdown-menu > li > a:hover, .dropdown-menu>li>a:hover,.dropdown-menu>li>a:focus,.dropdown-submenu:hover>a,.dropdown-submenu:focus>a,.dropdown-menu>.active>a,.dropdown-menu>.active>a:hover,.dropdown-menu>.active>a:focus
.dropdown-menu > li > a:focus, {
.dropdown-submenu:hover > a,
.dropdown-submenu:focus > a,
.dropdown-menu > .active > a,
.dropdown-menu > .active > a:hover,
.dropdown-menu > .active > a:focus {
background-color: #888; background-color: #888;
} }
.dropdown-menu > .disabled > a, .dropdown-menu>.disabled>a,.dropdown-menu>.disabled>a:hover,.dropdown-menu>.disabled>a:focus
.dropdown-menu > .disabled > a:hover, {
.dropdown-menu > .disabled > a:focus {
color: #bbb; color: #bbb;
} }
@ -171,7 +141,8 @@ textarea::-webkit-input-placeholder {
background-color: #777; background-color: #777;
} }
input[disabled], select[disabled], textarea[disabled], .input-prepend .add-on { input[disabled],select[disabled],textarea[disabled],.input-prepend .add-on
{
background-color: #f5f5f5; background-color: #f5f5f5;
} }
@ -180,13 +151,8 @@ input[readonly], select[readonly], textarea[readonly] {
cursor: text; cursor: text;
} }
.btn-primary:hover, .btn-primary:hover,.btn-primary:focus,.btn-primary:active,.btn-primary.active,.btn-primary.disabled,.btn-primary[disabled],.btn-group.open .btn.btn-primary.dropdown-toggle
.btn-primary:focus, {
.btn-primary:active,
.btn-primary.active,
.btn-primary.disabled,
.btn-primary[disabled],
.btn-group.open .btn.btn-primary.dropdown-toggle {
color: #fff; color: #fff;
background-color: #888; background-color: #888;
} }
@ -208,6 +174,7 @@ input[readonly], select[readonly], textarea[readonly] {
-moz-border-radius: 0; -moz-border-radius: 0;
border-radius: 0; border-radius: 0;
} }
#extension-buttons>.btn-group:first-child>.btn { #extension-buttons>.btn-group:first-child>.btn {
-webkit-border-radius: 4px 0 0 4px; -webkit-border-radius: 4px 0 0 4px;
-moz-border-radius: 4px 0 0 4px; -moz-border-radius: 4px 0 0 4px;
@ -230,7 +197,11 @@ input[readonly], select[readonly], textarea[readonly] {
} }
code { code {
color: #333333 !important; color: #333333;
}
a code {
color: inherit;
} }
h1 { h1 {
@ -346,8 +317,7 @@ div.dropdown-menu {
padding: 5px 20px; padding: 5px 20px;
} }
div.dropdown-menu p, div.dropdown-menu p,div.dropdown-menu blockquote {
div.dropdown-menu blockquote {
margin: 10px 0; margin: 10px 0;
} }
@ -414,8 +384,7 @@ div.dropdown-menu i {
background-position: -37px 0; background-position: -37px 0;
} }
.icon-github, .icon-github,.icon-gist {
.icon-gist {
background-image: url("../img/icons.png") !important; background-image: url("../img/icons.png") !important;
width: 16px; width: 16px;
height: 16px; height: 16px;
@ -558,8 +527,8 @@ div.dropdown-menu i {
text-align: left; text-align: left;
} }
#modal-settings .accordion-inner .form-inline .label-text, #modal-settings .accordion-inner .form-inline .label-text,#modal-settings .accordion-inner .control-label
#modal-settings .accordion-inner .control-label { {
margin: 0 10px; margin: 0 10px;
} }
@ -573,19 +542,18 @@ div.dropdown-menu i {
margin: 20px 0 0; margin: 20px 0 0;
} }
.nav-tabs > .active > a, .nav-tabs > .active > a:hover, .nav-tabs > .active > a:focus { .nav-tabs>.active>a,.nav-tabs>.active>a:hover,.nav-tabs>.active>a:focus
{
color: #fff; color: #fff;
background-color: #777; background-color: #777;
border-color: #777; border-color: #777;
} }
.nav > li > a:hover, .nav>li>a:hover,.nav>li>a:focus {
.nav > li > a:focus {
background-color: #eee; background-color: #eee;
} }
.nav-tabs > li > a:hover, .nav-tabs>li>a:hover,.nav-tabs>li>a:focus {
.nav-tabs > li > a:focus {
border-color: #eee; border-color: #eee;
} }
@ -608,8 +576,7 @@ table {
margin-bottom: 20px; margin-bottom: 20px;
} }
table th, table th,table td {
table td {
padding: 8px; padding: 8px;
line-height: 20px; line-height: 20px;
text-align: left; text-align: left;
@ -625,12 +592,8 @@ table thead th {
vertical-align: bottom; vertical-align: bottom;
} }
table caption + thead tr:first-child th, table caption+thead tr:first-child th,table caption+thead tr:first-child td,table colgroup+thead tr:first-child th,table colgroup+thead tr:first-child td,table thead:first-child tr:first-child th,table thead:first-child tr:first-child td
table caption + thead tr:first-child td, {
table colgroup + thead tr:first-child th,
table colgroup + thead tr:first-child td,
table thead:first-child tr:first-child th,
table thead:first-child tr:first-child td {
border-top: 0; border-top: 0;
} }
@ -655,6 +618,23 @@ blockquote p {
line-height: 20px; line-height: 20px;
} }
input[type="file"] {
line-height: inherit;
height: inherit;
border: none !important;
}
.drop-zone {
border: 2px dashed #bbb;
-moz-border-radius: 5px;
-webkit-border-radius: 5px;
border-radius: 5px;
padding: 40px;
text-align: center;
font-size: 24px;
color: #bbb;
}
#md-section-helper { #md-section-helper {
position: absolute; position: absolute;
top: -100px; top: -100px;

View File

@ -21,7 +21,12 @@
if(theme) { if(theme) {
document.write('<link href="themes/' + theme + '/' + theme + '.css" rel="stylesheet">'); document.write('<link href="themes/' + theme + '/' + theme + '.css" rel="stylesheet">');
} }
var require = { baseUrl : "js", deps : [ "main" + suffix ] }; var require = {
baseUrl: "js",
deps: [
"main" + suffix
]
};
var viewerMode = false; var viewerMode = false;
</script> </script>
<script src="js/libs/require.js"></script> <script src="js/libs/require.js"></script>
@ -34,8 +39,7 @@
<li><div id="wmd-button-bar"></div></li> <li><div id="wmd-button-bar"></div></li>
</ul> </ul>
<ul class="nav pull-right hide" id="menu-bar"> <ul class="nav pull-right hide" id="menu-bar">
<li id="extension-buttons"> <li id="extension-buttons"></li>
</li>
<li class="btn-group"><button class="btn action-create-file" <li class="btn-group"><button class="btn action-create-file"
title="New local document"> title="New local document">
<i class="icon-file"></i> <i class="icon-file"></i>
@ -62,13 +66,27 @@
</button> </button>
<ul class="dropdown-menu"> <ul class="dropdown-menu">
<li><a href="viewer.html" title="StackEdit Viewer"><i <li><a href="viewer.html" title="StackEdit Viewer"><i
class="icon-fullscreen"></i> Open viewer</a></li> class="icon-fullscreen"></i> StackEdit Viewer</a></li>
<li><a class="action-download-md" href="#"><i <li class="dropdown-submenu"><a href="#"><i
class="icon-download-alt"></i> Save as Markdown</a></li> class="icon-hdd"></i> Open from...</a>
<li><a class="action-download-html" href="#"><i <ul class="dropdown-menu">
class="icon-download-alt"></i> Save as HTML</a></li> <li><a data-toggle="modal"
<li><a class="action-download-template" href="#"><i data-target="#modal-import-harddrive-markdown" class="action-reset-input"
class="icon-download-alt"></i> Save using template</a></li> href="#">Import from hard drive</a></li>
<li><a data-toggle="modal"
data-target="#modal-import-harddrive-html" class="action-reset-input"
href="#">Convert HTML to Markdown</a></li>
</ul></li>
<li class="dropdown-submenu"><a href="#"><i
class="icon-hdd"></i> Save as...</a>
<ul class="dropdown-menu">
<li><a class="action-download-md" href="#">Save as
Markdown</a></li>
<li><a class="action-download-html" href="#">Save as
HTML</a></li>
<li><a class="action-download-template" href="#">Save
using template</a></li>
</ul></li>
<li class="divider with-text">synchronize</li> <li class="divider with-text">synchronize</li>
<li class="dropdown-submenu"><a href="#"><i <li class="dropdown-submenu"><a href="#"><i
class="icon-gdrive"></i> Google Drive</a> class="icon-gdrive"></i> Google Drive</a>
@ -134,9 +152,8 @@
</div> </div>
</div> </div>
<div class="modal-footer"> <div class="modal-footer">
<a href="#" class="btn" data-dismiss="modal">Cancel</a> <a href="#" class="btn" data-dismiss="modal">Cancel</a> <a href="#"
<a href="#" class="btn btn-primary action-insert-link" class="btn btn-primary action-insert-link" data-dismiss="modal">OK</a>
data-dismiss="modal">OK</a>
</div> </div>
</div> </div>
@ -155,9 +172,10 @@
</div> </div>
</div> </div>
<div class="modal-footer"> <div class="modal-footer">
<a href="#" class="btn action-import-image-gplus" data-dismiss="modal"><i class="icon-gplus"></i> Import from Google+</a> <a href="#" class="btn action-import-image-gplus"
<a href="#" class="btn" data-dismiss="modal">Cancel</a> data-dismiss="modal"><i class="icon-gplus"></i> Import from
<a href="#" class="btn btn-primary action-insert-image" Google+</a> <a href="#" class="btn" data-dismiss="modal">Cancel</a> <a
href="#" class="btn btn-primary action-insert-image"
data-dismiss="modal">OK</a> data-dismiss="modal">OK</a>
</div> </div>
</div> </div>
@ -176,25 +194,26 @@
</div> </div>
</div> </div>
<div class="control-group"> <div class="control-group">
<label class="control-label" for="input-import-image-title">Title (optional)</label> <label class="control-label" for="input-import-image-title">Title
(optional)</label>
<div class="controls"> <div class="controls">
<input type="text" id="input-import-image-title" <input type="text" id="input-import-image-title"
placeholder="Image title"> placeholder="Image title">
</div> </div>
</div> </div>
<div class="control-group"> <div class="control-group">
<label class="control-label" for="input-import-image-size">Size limit <label class="control-label" for="input-import-image-size">Size
(optional)</label> limit (optional)</label>
<div class="controls"> <div class="controls">
<input type="text" id="input-import-image-size" placeholder="345" class="input-mini"><span class="help-inline">px</span> <input type="text" id="input-import-image-size" placeholder="345"
class="input-mini"><span class="help-inline">px</span>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
<div class="modal-footer"> <div class="modal-footer">
<a href="#" class="btn" data-dismiss="modal">Cancel</a> <a href="#" class="btn" data-dismiss="modal">Cancel</a> <a href="#"
<a href="#" class="btn btn-primary action-import-image" class="btn btn-primary action-import-image" data-dismiss="modal">OK</a>
data-dismiss="modal">OK</a>
</div> </div>
</div> </div>
@ -218,6 +237,40 @@
</div> </div>
</div> </div>
<div id="modal-import-harddrive-markdown" class="modal hide">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal"
aria-hidden="true">&times;</button>
<h3>Import from hard drive</h3>
</div>
<div class="modal-body">
<p>Please select the Markdown files to import:</p>
<p><input type="file" id="input-file-import-harddrive-markdown" multiple /></p>
<p>Or drag and drop the Markdown files here:</p>
<div id="dropzone-import-harddrive-markdown" class="drop-zone">Drop zone</div>
</div>
<div class="modal-footer">
<a href="#" class="btn btn-primary" data-dismiss="modal">Close</a>
</div>
</div>
<div id="modal-import-harddrive-html" class="modal hide">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal"
aria-hidden="true">&times;</button>
<h3>Import from hard drive</h3>
</div>
<div class="modal-body">
<p>Please select the HTML files to import:</p>
<p><input type="file" id="input-file-import-harddrive-html" multiple /></p>
<p>Or drag and drop the HTML files here:</p>
<div id="dropzone-import-harddrive-html" class="drop-zone">Drop zone</div>
</div>
<div class="modal-footer">
<a href="#" class="btn btn-primary" data-dismiss="modal">Close</a>
</div>
</div>
<div id="modal-upload-gdrive" class="modal hide"> <div id="modal-upload-gdrive" class="modal hide">
<div class="modal-header"> <div class="modal-header">
<button type="button" class="close" data-dismiss="modal" <button type="button" class="close" data-dismiss="modal"
@ -442,7 +495,11 @@
site</label> site</label>
<div class="controls"> <div class="controls">
<input type="text" id="input-publish-wordpress-site" <input type="text" id="input-publish-wordpress-site"
placeholder="exemple.wordpress.com"> placeholder="exemple.wordpress.com"> <span
class="help-block"> <a target="_blank"
href="http://jetpack.me/">Jetpack plugin</a> is required for
self-hosted sites.
</span>
</div> </div>
</div> </div>
<div <div
@ -647,12 +704,14 @@
<div class="tab-pane" id="tabpane-settings-utils"> <div class="tab-pane" id="tabpane-settings-utils">
<div class="tab-pane-button-container"> <div class="tab-pane-button-container">
<a href="#" class="btn btn-block btn-primary action-welcome-file" <a href="#" class="btn btn-block btn-primary action-welcome-file"
data-dismiss="modal"><i class="icon-info-sign icon-white"></i> Welcome document</a> <a href="#" data-dismiss="modal"><i class="icon-info-sign icon-white"></i>
Welcome document</a> <a href="#"
class="btn btn-block btn-primary action-default-settings" class="btn btn-block btn-primary action-default-settings"
data-dismiss="modal"><i class="icon-wrench icon-white"></i> Load default settings</a> <a href="#" data-dismiss="modal"><i class="icon-wrench icon-white"></i>
Load default settings</a> <a href="#"
class="btn btn-block btn-primary" data-dismiss="modal" class="btn btn-block btn-primary" data-dismiss="modal"
data-toggle="modal" data-target="#modal-app-reset"><i class="icon-fire icon-white"></i> Reset data-toggle="modal" data-target="#modal-app-reset"><i
application</a> class="icon-fire icon-white"></i> Reset application</a>
</div> </div>
</div> </div>
</div> </div>
@ -670,8 +729,7 @@
aria-hidden="true">&times;</button> aria-hidden="true">&times;</button>
<img src="img/stackedit-promo.png" /> <img src="img/stackedit-promo.png" />
</div> </div>
<div class="modal-body"> <div class="modal-body"></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 btn-primary" data-dismiss="modal">Close</a>
</div> </div>

View File

@ -1,198 +0,0 @@
/**
* Used to run asynchronous tasks sequentially (ajax mainly). An asynchronous
* task is composed of different callback types: onRun, onSuccess, onError
*/
define([
"underscore",
"core",
"utils",
"extensionMgr",
"libs/stacktrace",
], function(_, core, utils, extensionMgr) {
var asyncRunner = {};
var taskQueue = [];
var asyncRunning = false;
var currentTask = undefined;
var currentTaskRunning = false;
var currentTaskStartTime = 0;
asyncRunner.createTask = function() {
var task = {};
task.finished = false;
task.timeout = ASYNC_TASK_DEFAULT_TIMEOUT;
task.retryCounter = 0;
task.callPath = [];
/**
* onRun callbacks are called by chain(). These callbacks have to call
* chain() themselves to chain with next onRun callback or error() to
* throw an exception or retry() to restart the task.
*/
// Run callbacks
task.runCallbacks = [];
task.onRun = function(callback) {
task.runCallbacks.push(callback);
};
/**
* onSuccess callbacks are called when every onRun callbacks have
* succeed.
*/
task.successCallbacks = [];
task.onSuccess = function(callback) {
task.successCallbacks.push(callback);
};
/**
* onError callbacks are called when error() is called in a onRun
* callback.
*/
task.errorCallbacks = [];
task.onError = function(callback) {
task.errorCallbacks.push(callback);
};
/**
* chain() calls the next onRun callback or the onSuccess callbacks when
* finished. The optional callback parameter can be used to pass an
* onRun callback during execution.
*/
task.chain = function(callback) {
task.callPath.unshift(printStackTrace()[5]);
if(task.finished === true) {
return;
}
// If first execution
if(task.queue === undefined) {
// Create a copy of the onRun callbacks
task.queue = task.runCallbacks.slice();
}
// If a callback is passed as a parameter
if(callback !== undefined) {
callback();
return;
}
// If all callbacks have been run
if(task.queue.length === 0) {
// Run the onSuccess callbacks
runSafe(task, task.successCallbacks);
return;
}
// Run the next callback
var runCallback = task.queue.shift();
runCallback();
};
/**
* error() calls the onError callbacks passing the error parameter and
* ends the task by throwing an exception.
*/
task.error = function(error) {
task.callPath.unshift(printStackTrace()[5]);
if(task.finished === true) {
return;
}
error = error || new Error("Unknown error|\n" + task.callPath.join("\n"));
if(error.message) {
extensionMgr.onError(error);
}
runSafe(task, task.errorCallbacks, error);
// Exit the current call stack
throw error;
};
/**
* retry() can be called in an onRun callback to restart the task
*/
task.retry = function(error, maxRetryCounter) {
if(task.finished === true) {
return;
}
maxRetryCounter = maxRetryCounter || 5;
task.queue = undefined;
if(task.retryCounter >= maxRetryCounter) {
task.error(error);
return;
}
// Implement an exponential backoff
var delay = Math.pow(2, task.retryCounter++) * 1000;
currentTaskStartTime = utils.currentTime + delay;
currentTaskRunning = false;
task.callPath = [];
asyncRunner.runTask();
};
return task;
};
// Run the next task in the queue if any and no other running
asyncRunner.runTask = function() {
// Use defer to avoid stack overflow
_.defer(function() {
// If there is a task currently running
if(currentTaskRunning === true) {
// If the current task takes too long
if(currentTaskStartTime + currentTask.timeout < utils.currentTime) {
currentTask.error(new Error("A timeout occurred.|\n" + currentTask.callPath.join("\n")));
}
return;
}
if(currentTask === undefined) {
// If no task in the queue
if(taskQueue.length === 0) {
return;
}
// Dequeue an enqueued task
currentTask = taskQueue.shift();
currentTaskStartTime = utils.currentTime;
if(asyncRunning === false) {
asyncRunning = true;
extensionMgr.onAsyncRunning(true);
}
}
// Run the task
if(currentTaskStartTime <= utils.currentTime) {
currentTaskRunning = true;
currentTask.chain();
}
});
};
// Run runTask function periodically
core.addPeriodicCallback(asyncRunner.runTask);
function runSafe(task, callbacks, param) {
try {
_.each(callbacks, function(callback) {
callback(param);
});
}
finally {
task.finished = true;
if(currentTask === task) {
currentTask = undefined;
currentTaskRunning = false;
}
if(taskQueue.length === 0) {
asyncRunning = false;
extensionMgr.onAsyncRunning(false);
}
else {
asyncRunner.runTask();
}
}
}
// Add a task to the queue
asyncRunner.addTask = function(task) {
taskQueue.push(task);
asyncRunner.runTask();
};
// Change current task timeout
asyncRunner.setCurrentTaskTimeout = function(timeout) {
if(currentTask !== undefined) {
currentTask.timeout = timeout;
}
};
return asyncRunner;
});

View File

@ -18,6 +18,7 @@ var ASYNC_TASK_DEFAULT_TIMEOUT = 60000;
var ASYNC_TASK_LONG_TIMEOUT = 180000; var ASYNC_TASK_LONG_TIMEOUT = 180000;
var SYNC_PERIOD = 180000; var SYNC_PERIOD = 180000;
var USER_IDLE_THRESHOLD = 300000; var USER_IDLE_THRESHOLD = 300000;
var IMPORT_FILE_MAX_CONTENT_SIZE = 100000;
var TEMPORARY_FILE_INDEX = "file.tempIndex"; var TEMPORARY_FILE_INDEX = "file.tempIndex";
var WELCOME_DOCUMENT_TITLE = "Welcome document"; var WELCOME_DOCUMENT_TITLE = "Welcome document";
var DOWNLOAD_PROXY_URL = "http://stackedit-download-proxy.herokuapp.com/"; var DOWNLOAD_PROXY_URL = "http://stackedit-download-proxy.herokuapp.com/";

View File

@ -261,6 +261,7 @@ define([
var newDocumentContent = editorElt.val(); var newDocumentContent = editorElt.val();
if(documentContent !== undefined && documentContent != newDocumentContent) { if(documentContent !== undefined && documentContent != newDocumentContent) {
fileDesc.content = newDocumentContent; fileDesc.content = newDocumentContent;
extensionMgr.onContentChanged(fileDesc);
} }
documentContent = newDocumentContent; documentContent = newDocumentContent;
} }

View File

@ -12,6 +12,7 @@ define([
"extensions/dialogAbout", "extensions/dialogAbout",
"extensions/dialogManagePublication", "extensions/dialogManagePublication",
"extensions/dialogManageSynchronization", "extensions/dialogManageSynchronization",
"extensions/dialogOpenHarddrive",
"extensions/documentSelector", "extensions/documentSelector",
"extensions/documentTitle", "extensions/documentTitle",
"extensions/workingIndicator", "extensions/workingIndicator",

View File

@ -10,9 +10,9 @@ define([
settingsBloc: '<p>Populates the "Manage publication" dialog box.</p>' settingsBloc: '<p>Populates the "Manage publication" dialog box.</p>'
}; };
var fileMgr = undefined; var extensionMgr = undefined;
dialogManagePublication.onFileMgrCreated = function(fileMgrParameter) { dialogManagePublication.onExtensionMgrCreated = function(extensionMgrParameter) {
fileMgr = fileMgrParameter; extensionMgr = extensionMgrParameter;
}; };
var fileDesc = undefined; var fileDesc = undefined;
@ -42,7 +42,8 @@ define([
publishDesc: publishDesc publishDesc: publishDesc
})); }));
lineElement.append($(removeButtonTemplate).click(function() { lineElement.append($(removeButtonTemplate).click(function() {
fileMgr.removePublish(publishAttributes); fileDesc.removePublishLocation(publishAttributes);
extensionMgr.onPublishRemoved(publishFileDesc, publishAttributes);
})); }));
publishList.append(lineElement); publishList.append(lineElement);
}); });

View File

@ -10,9 +10,9 @@ define([
settingsBloc: '<p>Populates the "Manage synchronization" dialog box.</p>' settingsBloc: '<p>Populates the "Manage synchronization" dialog box.</p>'
}; };
var fileMgr = undefined; var extensionMgr = undefined;
dialogManageSynchronization.onFileMgrCreated = function(fileMgrParameter) { dialogManageSynchronization.onExtensionMgrCreated = function(extensionMgrParameter) {
fileMgr = fileMgrParameter; extensionMgr = extensionMgrParameter;
}; };
var fileDesc = undefined; var fileDesc = undefined;
@ -38,7 +38,8 @@ define([
syncDesc: syncDesc syncDesc: syncDesc
})); }));
lineElement.append($(removeButtonTemplate).click(function() { lineElement.append($(removeButtonTemplate).click(function() {
fileMgr.removeSync(syncAttributes); fileDesc.removeSyncLocation(syncAttributes);
extensionMgr.onSyncRemoved(fileDesc, syncAttributes);
})); }));
syncList.append(lineElement); syncList.append(lineElement);
}); });

View File

@ -38,6 +38,7 @@ define([
var liMap = undefined; var liMap = undefined;
var liArray = undefined; var liArray = undefined;
var sortFunction = undefined; var sortFunction = undefined;
var selectFileDesc = undefined;
var buildSelector = function() { var buildSelector = function() {
function composeTitle(fileDesc) { function composeTitle(fileDesc) {
@ -68,23 +69,17 @@ define([
}); });
var li = $("<li>").append(a); var li = $("<li>").append(a);
liMap[fileDesc.fileIndex] = li; liMap[fileDesc.fileIndex] = li;
if(fileDesc === selectFileDesc) {
li.addClass("disabled");
}
$("#file-selector").append(li); $("#file-selector").append(li);
}); });
liArray = _.values(liMap); liArray = _.values(liMap);
}; };
var selectFileDesc = undefined;
documentSelector.onFileSelected = function(fileDesc) { documentSelector.onFileSelected = function(fileDesc) {
selectFileDesc = fileDesc; selectFileDesc = fileDesc;
buildSelector(); buildSelector();
$("#file-selector li:not(.stick)").removeClass("disabled");
var li = liMap[fileDesc.fileIndex];
if(li === undefined) {
// It means that we are showing a temporary file (not in the
// selector)
return;
}
li.addClass("disabled");
}; };
documentSelector.onFileCreated = buildSelector; documentSelector.onFileCreated = buildSelector;

View File

@ -6,93 +6,12 @@ define([
"settings", "settings",
"extensionMgr", "extensionMgr",
"fileSystem", "fileSystem",
"classes/FileDescriptor",
"text!../WELCOME.md" "text!../WELCOME.md"
], function($, _, core, utils, settings, extensionMgr, fileSystem, welcomeContent) { ], function($, _, core, utils, settings, extensionMgr, fileSystem, FileDescriptor, welcomeContent) {
var fileMgr = {}; var fileMgr = {};
// Defines a file descriptor (fileDesc objects)
function FileDescriptor(fileIndex, title, syncLocations, publishLocations) {
this.fileIndex = fileIndex;
this._title = title;
this._editorScrollTop = parseInt(localStorage[fileIndex + ".editorScrollTop"]) || 0;
this._editorStart = parseInt(localStorage[fileIndex + ".editorStart"]) || 0;
this._editorEnd = parseInt(localStorage[fileIndex + ".editorEnd"]) || 0;
this._previewScrollTop = parseInt(localStorage[fileIndex + ".previewScrollTop"]) || 0;
this._selectTime = parseInt(localStorage[fileIndex + ".selectTime"]) || 0;
this.syncLocations = syncLocations || {};
this.publishLocations = publishLocations || {};
Object.defineProperty(this, 'title', {
get: function() {
return this._title;
},
set: function(title) {
this._title = title;
localStorage[this.fileIndex + ".title"] = title;
extensionMgr.onTitleChanged(this);
}
});
Object.defineProperty(this, 'content', {
get: function() {
return localStorage[this.fileIndex + ".content"];
},
set: function(content) {
localStorage[this.fileIndex + ".content"] = content;
extensionMgr.onContentChanged(this);
}
});
Object.defineProperty(this, 'editorScrollTop', {
get: function() {
return this._editorScrollTop;
},
set: function(editorScrollTop) {
this._editorScrollTop = editorScrollTop;
localStorage[this.fileIndex + ".editorScrollTop"] = editorScrollTop;
}
});
Object.defineProperty(this, 'editorStart', {
get: function() {
return this._editorStart;
},
set: function(editorStart) {
this._editorStart = editorStart;
localStorage[this.fileIndex + ".editorStart"] = editorStart;
}
});
Object.defineProperty(this, 'editorEnd', {
get: function() {
return this._editorEnd;
},
set: function(editorEnd) {
this._editorEnd = editorEnd;
localStorage[this.fileIndex + ".editorEnd"] = editorEnd;
}
});
Object.defineProperty(this, 'previewScrollTop', {
get: function() {
return this._previewScrollTop;
},
set: function(previewScrollTop) {
this._previewScrollTop = previewScrollTop;
localStorage[this.fileIndex + ".previewScrollTop"] = previewScrollTop;
}
});
Object.defineProperty(this, 'selectTime', {
get: function() {
return this._selectTime;
},
set: function(selectTime) {
this._selectTime = selectTime;
localStorage[this.fileIndex + ".selectTime"] = selectTime;
}
});
}
// Retrieve file descriptors from localStorage and populate fileSystem
_.each(utils.retrieveIndexArray("file.list"), function(fileIndex) {
fileSystem[fileIndex] = new FileDescriptor(fileIndex, localStorage[fileIndex + ".title"]);
});
// Defines the current file // Defines the current file
var currentFile = undefined; var currentFile = undefined;
fileMgr.getCurrentFile = function() { fileMgr.getCurrentFile = function() {
@ -103,12 +22,6 @@ define([
}; };
fileMgr.setCurrentFile = function(fileDesc) { fileMgr.setCurrentFile = function(fileDesc) {
currentFile = fileDesc; currentFile = fileDesc;
if(fileDesc === undefined) {
localStorage.removeItem("file.current");
}
else if(fileDesc.fileIndex != TEMPORARY_FILE_INDEX) {
localStorage["file.current"] = fileDesc.fileIndex;
}
}; };
fileMgr.selectFile = function(fileDesc) { fileMgr.selectFile = function(fileDesc) {
@ -116,17 +29,15 @@ define([
if(fileDesc === undefined) { if(fileDesc === undefined) {
var fileSystemSize = _.size(fileSystem); var fileSystemSize = _.size(fileSystem);
// If fileSystem empty create one file
if(fileSystemSize === 0) { if(fileSystemSize === 0) {
// If fileSystem empty create one file
fileDesc = fileMgr.createFile(WELCOME_DOCUMENT_TITLE, welcomeContent); fileDesc = fileMgr.createFile(WELCOME_DOCUMENT_TITLE, welcomeContent);
} }
else { else {
var fileIndex = localStorage["file.current"]; // Select the last selected file
// If no file is selected take the last created fileDesc = _.max(fileSystem, function(fileDesc) {
if(fileIndex === undefined) { return fileDesc.selectTime || 0;
fileIndex = _.keys(fileSystem)[fileSystemSize - 1]; });
}
fileDesc = fileSystem[fileIndex];
} }
} }
@ -174,6 +85,7 @@ define([
// syncIndex associations // syncIndex associations
syncLocations = syncLocations || {}; syncLocations = syncLocations || {};
var sync = _.reduce(syncLocations, function(sync, syncAttributes) { var sync = _.reduce(syncLocations, function(sync, syncAttributes) {
utils.storeAttributes(syncAttributes);
return sync + syncAttributes.syncIndex + ";"; return sync + syncAttributes.syncIndex + ";";
}, ";"); }, ";");
@ -208,14 +120,14 @@ define([
fileMgr.selectFile(); fileMgr.selectFile();
} }
// Remove synchronized locations // Remove synchronized locations from localStorage
_.each(fileDesc.syncLocations, function(syncAttributes) { _.each(fileDesc.syncLocations, function(syncAttributes) {
fileMgr.removeSync(syncAttributes); localStorage.removeItem(syncAttributes.syncIndex);
}); });
// Remove publish locations // Remove publish locations from localStorage
_.each(fileDesc.publishLocations, function(publishAttributes) { _.each(fileDesc.publishLocations, function(publishAttributes) {
fileMgr.removePublish(publishAttributes); localStorage.removeItem(publishAttributes.publishIndex);
}); });
localStorage.removeItem(fileDesc.fileIndex + ".title"); localStorage.removeItem(fileDesc.fileIndex + ".title");
@ -226,26 +138,6 @@ define([
extensionMgr.onFileDeleted(fileDesc); extensionMgr.onFileDeleted(fileDesc);
}; };
// Add a synchronized location to a file
fileMgr.addSync = function(fileDesc, syncAttributes) {
utils.appendIndexToArray(fileDesc.fileIndex + ".sync", syncAttributes.syncIndex);
fileDesc.syncLocations[syncAttributes.syncIndex] = syncAttributes;
// addSync is only used for export, not for import
extensionMgr.onSyncExportSuccess(fileDesc, syncAttributes);
};
// Remove a synchronized location
fileMgr.removeSync = function(syncAttributes) {
var fileDesc = fileMgr.getFileFromSyncIndex(syncAttributes.syncIndex);
if(fileDesc !== undefined) {
utils.removeIndexFromArray(fileDesc.fileIndex + ".sync", syncAttributes.syncIndex);
delete fileDesc.syncLocations[syncAttributes.syncIndex];
extensionMgr.onSyncRemoved(fileDesc, syncAttributes);
}
// Remove sync attributes from localStorage
localStorage.removeItem(syncAttributes.syncIndex);
};
// Get the file descriptor associated to a syncIndex // Get the file descriptor associated to a syncIndex
fileMgr.getFileFromSyncIndex = function(syncIndex) { fileMgr.getFileFromSyncIndex = function(syncIndex) {
return _.find(fileSystem, function(fileDesc) { return _.find(fileSystem, function(fileDesc) {
@ -268,25 +160,6 @@ define([
}); });
}; };
// Add a publishIndex (publish location) to a file
fileMgr.addPublish = function(fileDesc, publishAttributes) {
utils.appendIndexToArray(fileDesc.fileIndex + ".publish", publishAttributes.publishIndex);
fileDesc.publishLocations[publishAttributes.publishIndex] = publishAttributes;
extensionMgr.onNewPublishSuccess(fileDesc, publishAttributes);
};
// Remove a publishIndex (publish location)
fileMgr.removePublish = function(publishAttributes) {
var fileDesc = fileMgr.getFileFromPublishIndex(publishAttributes.publishIndex);
if(fileDesc !== undefined) {
utils.removeIndexFromArray(fileDesc.fileIndex + ".publish", publishAttributes.publishIndex);
delete fileDesc.publishLocations[publishAttributes.publishIndex];
extensionMgr.onPublishRemoved(fileDesc, publishAttributes);
}
// Remove publish attributes from localStorage
localStorage.removeItem(publishAttributes.publishIndex);
};
// Get the file descriptor associated to a publishIndex // Get the file descriptor associated to a publishIndex
fileMgr.getFileFromPublishIndex = function(publishIndex) { fileMgr.getFileFromPublishIndex = function(publishIndex) {
return _.find(fileSystem, function(fileDesc) { return _.find(fileSystem, function(fileDesc) {
@ -327,6 +200,7 @@ define([
var fileDesc = fileMgr.getCurrentFile(); var fileDesc = fileMgr.getCurrentFile();
if(title && title != fileDesc.title) { if(title && title != fileDesc.title) {
fileDesc.title = title; fileDesc.title = title;
extensionMgr.onTitleChanged(fileDesc);
} }
input.val(fileDesc.title); input.val(fileDesc.title);
$("#wmd-input").focus(); $("#wmd-input").focus();

View File

@ -1,3 +1,16 @@
// The fileSystem module is empty when created. It's filled by fileMgr when loading. // The fileSystem module is empty when created. It's filled by fileMgr when loading.
// syncLocations and publishLocations are respectively loaded by synchronizer and publisher. // syncLocations and publishLocations are respectively loaded by synchronizer and publisher.
define({}); define([
"utils",
"classes/FileDescriptor",
"storage",
], function(utils, FileDescriptor) {
var fileSystem = {};
// Retrieve file descriptors from localStorage and populate fileSystem
_.each(utils.retrieveIndexArray("file.list"), function(fileIndex) {
fileSystem[fileIndex] = new FileDescriptor(fileIndex, localStorage[fileIndex + ".title"]);
});
return fileSystem;
});

View File

@ -3,8 +3,8 @@ define([
"underscore", "underscore",
"core", "core",
"extensionMgr", "extensionMgr",
"asyncRunner" "classes/AsyncTask"
], function($, _, core, extensionMgr, asyncRunner) { ], function($, _, core, extensionMgr, AsyncTask) {
var client = undefined; var client = undefined;
var authenticated = false; var authenticated = false;
@ -88,7 +88,7 @@ define([
dropboxHelper.upload = function(path, content, callback) { dropboxHelper.upload = function(path, content, callback) {
var result = undefined; var result = undefined;
var task = asyncRunner.createTask(); var task = new AsyncTask();
connect(task); connect(task);
authenticate(task); authenticate(task);
task.onRun(function() { task.onRun(function() {
@ -111,13 +111,13 @@ define([
task.onError(function(error) { task.onError(function(error) {
callback(error); callback(error);
}); });
asyncRunner.addTask(task); task.enqueue();
}; };
dropboxHelper.checkChanges = function(lastChangeId, callback) { dropboxHelper.checkChanges = function(lastChangeId, callback) {
var changes = []; var changes = [];
var newChangeId = lastChangeId || 0; var newChangeId = lastChangeId || 0;
var task = asyncRunner.createTask(); var task = new AsyncTask();
connect(task); connect(task);
authenticate(task); authenticate(task);
task.onRun(function() { task.onRun(function() {
@ -148,12 +148,12 @@ define([
task.onError(function(error) { task.onError(function(error) {
callback(error); callback(error);
}); });
asyncRunner.addTask(task); task.enqueue();
}; };
dropboxHelper.downloadMetadata = function(paths, callback) { dropboxHelper.downloadMetadata = function(paths, callback) {
var result = []; var result = [];
var task = asyncRunner.createTask(); var task = new AsyncTask();
connect(task); connect(task);
authenticate(task); authenticate(task);
task.onRun(function() { task.onRun(function() {
@ -181,12 +181,12 @@ define([
task.onError(function(error) { task.onError(function(error) {
callback(error); callback(error);
}); });
asyncRunner.addTask(task); task.enqueue();
}; };
dropboxHelper.downloadContent = function(objects, callback) { dropboxHelper.downloadContent = function(objects, callback) {
var result = []; var result = [];
var task = asyncRunner.createTask(); var task = new AsyncTask();
connect(task); connect(task);
authenticate(task); authenticate(task);
task.onRun(function() { task.onRun(function() {
@ -229,7 +229,7 @@ define([
task.onError(function(error) { task.onError(function(error) {
callback(error); callback(error);
}); });
asyncRunner.addTask(task); task.enqueue();
}; };
function handleError(error, task) { function handleError(error, task) {
@ -299,7 +299,7 @@ define([
dropboxHelper.picker = function(callback) { dropboxHelper.picker = function(callback) {
var paths = []; var paths = [];
var task = asyncRunner.createTask(); var task = new AsyncTask();
// Add some time for user to choose his files // Add some time for user to choose his files
task.timeout = ASYNC_TASK_LONG_TIMEOUT; task.timeout = ASYNC_TASK_LONG_TIMEOUT;
connect(task); connect(task);
@ -328,7 +328,7 @@ define([
task.onError(function(error) { task.onError(function(error) {
callback(error); callback(error);
}); });
asyncRunner.addTask(task); task.enqueue();
}; };
return dropboxHelper; return dropboxHelper;

View File

@ -3,8 +3,8 @@ define([
"core", "core",
"utils", "utils",
"extensionMgr", "extensionMgr",
"asyncRunner" "classes/AsyncTask"
], function($, core, utils, extensionMgr, asyncRunner) { ], function($, core, utils, extensionMgr, AsyncTask) {
var connected = undefined; var connected = undefined;
var github = undefined; var github = undefined;
@ -111,7 +111,7 @@ define([
} }
githubHelper.upload = function(reponame, branch, path, content, commitMsg, callback) { githubHelper.upload = function(reponame, branch, path, content, commitMsg, callback) {
var task = asyncRunner.createTask(); var task = new AsyncTask();
connect(task); connect(task);
authenticate(task); authenticate(task);
task.onRun(function() { task.onRun(function() {
@ -145,11 +145,11 @@ define([
task.onError(function(error) { task.onError(function(error) {
callback(error); callback(error);
}); });
asyncRunner.addTask(task); task.enqueue();
}; };
githubHelper.uploadGist = function(gistId, filename, isPublic, title, content, callback) { githubHelper.uploadGist = function(gistId, filename, isPublic, title, content, callback) {
var task = asyncRunner.createTask(); var task = new AsyncTask();
connect(task); connect(task);
authenticate(task); authenticate(task);
task.onRun(function() { task.onRun(function() {
@ -185,11 +185,11 @@ define([
task.onError(function(error) { task.onError(function(error) {
callback(error); callback(error);
}); });
asyncRunner.addTask(task); task.enqueue();
}; };
githubHelper.downloadGist = function(gistId, filename, callback) { githubHelper.downloadGist = function(gistId, filename, callback) {
var task = asyncRunner.createTask(); var task = new AsyncTask();
connect(task); connect(task);
// No need for authentication // No need for authentication
var title = undefined; var title = undefined;
@ -219,7 +219,7 @@ define([
task.onError(function(error) { task.onError(function(error) {
callback(error); callback(error);
}); });
asyncRunner.addTask(task); task.enqueue();
}; };
function handleError(error, task) { function handleError(error, task) {

View File

@ -3,8 +3,8 @@ define([
"core", "core",
"utils", "utils",
"extensionMgr", "extensionMgr",
"asyncRunner" "classes/AsyncTask"
], function($, core, utils, extensionMgr, asyncRunner) { ], function($, core, utils, extensionMgr, AsyncTask) {
var connected = false; var connected = false;
var authenticated = false; var authenticated = false;
@ -86,7 +86,7 @@ define([
googleHelper.upload = function(fileId, parentId, title, content, etag, callback) { googleHelper.upload = function(fileId, parentId, title, content, etag, callback) {
var result = undefined; var result = undefined;
var task = asyncRunner.createTask(); var task = new AsyncTask();
connect(task); connect(task);
authenticate(task); authenticate(task);
task.onRun(function() { task.onRun(function() {
@ -164,13 +164,13 @@ define([
task.onError(function(error) { task.onError(function(error) {
callback(error); callback(error);
}); });
asyncRunner.addTask(task); task.enqueue();
}; };
googleHelper.checkChanges = function(lastChangeId, callback) { googleHelper.checkChanges = function(lastChangeId, callback) {
var changes = []; var changes = [];
var newChangeId = lastChangeId || 0; var newChangeId = lastChangeId || 0;
var task = asyncRunner.createTask(); var task = new AsyncTask();
connect(task); connect(task);
authenticate(task); authenticate(task);
task.onRun(function() { task.onRun(function() {
@ -216,12 +216,12 @@ define([
task.onError(function(error) { task.onError(function(error) {
callback(error); callback(error);
}); });
asyncRunner.addTask(task); task.enqueue();
}; };
googleHelper.downloadMetadata = function(ids, callback, skipAuth) { googleHelper.downloadMetadata = function(ids, callback, skipAuth) {
var result = []; var result = [];
var task = asyncRunner.createTask(); var task = new AsyncTask();
connect(task); connect(task);
if(!skipAuth) { if(!skipAuth) {
authenticate(task); authenticate(task);
@ -270,12 +270,12 @@ define([
task.onError(function(error) { task.onError(function(error) {
callback(error); callback(error);
}); });
asyncRunner.addTask(task); task.enqueue();
}; };
googleHelper.downloadContent = function(objects, callback, skipAuth) { googleHelper.downloadContent = function(objects, callback, skipAuth) {
var result = []; var result = [];
var task = asyncRunner.createTask(); var task = new AsyncTask();
// Add some time for user to choose his files // Add some time for user to choose his files
task.timeout = ASYNC_TASK_LONG_TIMEOUT; task.timeout = ASYNC_TASK_LONG_TIMEOUT;
connect(task); connect(task);
@ -338,7 +338,7 @@ define([
task.onError(function(error) { task.onError(function(error) {
callback(error); callback(error);
}); });
asyncRunner.addTask(task); task.enqueue();
}; };
function handleError(error, task) { function handleError(error, task) {
@ -389,7 +389,9 @@ define([
timeout: AJAX_TIMEOUT timeout: AJAX_TIMEOUT
}).done(function() { }).done(function() {
google.load('picker', '1', { google.load('picker', '1', {
callback: task.chain callback: function() {
task.chain();
}
}); });
pickerLoaded = true; pickerLoaded = true;
}).fail(function(jqXHR) { }).fail(function(jqXHR) {
@ -411,7 +413,7 @@ define([
$(".modal-backdrop, .picker").remove(); $(".modal-backdrop, .picker").remove();
} }
} }
var task = asyncRunner.createTask(); var task = new AsyncTask();
connect(task); connect(task);
loadPicker(task); loadPicker(task);
task.onRun(function() { task.onRun(function() {
@ -451,11 +453,11 @@ define([
hidePicker(); hidePicker();
callback(error); callback(error);
}); });
asyncRunner.addTask(task); task.enqueue();
}; };
googleHelper.uploadBlogger = function(blogUrl, blogId, postId, labelList, title, content, callback) { googleHelper.uploadBlogger = function(blogUrl, blogId, postId, labelList, title, content, callback) {
var task = asyncRunner.createTask(); var task = new AsyncTask();
connect(task); connect(task);
authenticate(task); authenticate(task);
task.onRun(function() { task.onRun(function() {
@ -541,7 +543,7 @@ define([
task.onError(function(error) { task.onError(function(error) {
callback(error); callback(error);
}); });
asyncRunner.addTask(task); task.enqueue();
}; };
return googleHelper; return googleHelper;

View File

@ -1,8 +1,8 @@
define([ define([
"jquery", "jquery",
"core", "core",
"asyncRunner" "classes/AsyncTask"
], function($, core, asyncRunner) { ], function($, core, AsyncTask) {
var sshHelper = {}; var sshHelper = {};
@ -18,7 +18,7 @@ define([
} }
sshHelper.upload = function(host, port, username, password, path, title, content, callback) { sshHelper.upload = function(host, port, username, password, path, title, content, callback) {
var task = asyncRunner.createTask(); var task = new AsyncTask();
connect(task); connect(task);
task.onRun(function() { task.onRun(function() {
var url = SSH_PROXY_URL + "upload"; var url = SSH_PROXY_URL + "upload";
@ -57,7 +57,7 @@ define([
task.onError(function(error) { task.onError(function(error) {
callback(error); callback(error);
}); });
asyncRunner.addTask(task); task.enqueue();
}; };
function handleError(error, task) { function handleError(error, task) {

View File

@ -3,8 +3,8 @@ define([
"core", "core",
"utils", "utils",
"extensionMgr", "extensionMgr",
"asyncRunner" "classes/AsyncTask"
], function($, core, utils, extensionMgr, asyncRunner) { ], function($, core, utils, extensionMgr, AsyncTask) {
var oauthParams = undefined; var oauthParams = undefined;
@ -96,7 +96,7 @@ define([
} }
tumblrHelper.upload = function(blogHostname, postId, tags, format, title, content, callback) { tumblrHelper.upload = function(blogHostname, postId, tags, format, title, content, callback) {
var task = asyncRunner.createTask(); var task = new AsyncTask();
connect(task); connect(task);
authenticate(task); authenticate(task);
task.onRun(function() { task.onRun(function() {
@ -135,7 +135,7 @@ define([
task.onError(function(error) { task.onError(function(error) {
callback(error); callback(error);
}); });
asyncRunner.addTask(task); task.enqueue();
}; };
function handleError(error, task) { function handleError(error, task) {

View File

@ -3,8 +3,8 @@ define([
"core", "core",
"utils", "utils",
"extensionMgr", "extensionMgr",
"asyncRunner" "classes/AsyncTask"
], function($, core, utils, extensionMgr, asyncRunner) { ], function($, core, utils, extensionMgr, AsyncTask) {
var token = undefined; var token = undefined;
@ -80,7 +80,7 @@ define([
} }
wordpressHelper.upload = function(site, postId, tags, title, content, callback) { wordpressHelper.upload = function(site, postId, tags, title, content, callback) {
var task = asyncRunner.createTask(); var task = new AsyncTask();
connect(task); connect(task);
authenticate(task); authenticate(task);
task.onRun(function() { task.onRun(function() {
@ -133,7 +133,7 @@ define([
task.onError(function(error) { task.onError(function(error) {
callback(error); callback(error);
}); });
asyncRunner.addTask(task); task.enqueue();
}; };
function handleError(error, task) { function handleError(error, task) {

View File

@ -1,53 +1,43 @@
<blockquote>StackEdit is a free, open-source Markdown
editor based on PageDown, the Markdown library used by Stack Overflow
and the other Stack Exchange sites.</blockquote>
<dl> <dl>
<dt>About:</dt> <dt>About:</dt>
<dd> <dd>
<a target="_blank" href="https://github.com/benweet/stackedit/">GitHub <a target="_blank" href="https://github.com/benweet/stackedit/">GitHub
project</a> / <a target="_blank" project</a> / <a target="_blank"
href="https://github.com/benweet/stackedit/issues">issue tracker</a> href="https://github.com/benweet/stackedit/issues">issue tracker</a><br />
</dd>
<dd>
<a target="_blank" <a target="_blank"
href="https://chrome.google.com/webstore/detail/stackedit/iiooodelglhkcpgbajoejffhijaclcdg">Chrome href="https://chrome.google.com/webstore/detail/stackedit/iiooodelglhkcpgbajoejffhijaclcdg">Chrome
app</a> (thanks for your review!) app</a> (thanks for your review!)<br /> <a target="_blank"
</dd> href="https://twitter.com/stackedit/">Follow on Twitter</a><br /> <a
<dd> target="_blank" href="https://www.facebook.com/stackedit/">Follow
<a target="_blank" href="https://twitter.com/stackedit/">Follow on on Facebook</a><br /> <a target="_blank"
Twitter</a>
</dd>
<dd>
<a target="_blank" href="https://www.facebook.com/stackedit/">Follow
on Facebook</a>
</dd>
<dd>
<a target="_blank"
href="https://plus.google.com/110816046787593496375" rel="publisher">Follow href="https://plus.google.com/110816046787593496375" rel="publisher">Follow
on Google+</a> on Google+</a><br />
</dd> </dd>
</dl> </dl>
<dl> <dl>
<dt>Developers:</dt> <dt>Developers:</dt>
<dd> <dd>
<a target="_blank" href="http://www.benoitschweblin.com">Benoit <a target="_blank" href="http://www.benoitschweblin.com">Benoit
Schweblin</a><br /> Schweblin</a><br /> Pete Eigel (contributor)
</dd> </dd>
<dd>Pete Eigel (contributor)</dd>
</dl> </dl>
<dl> <dl>
<dt>Credit:</dt> <dt>Credit:</dt>
<% _.each(libraries, function(url, name) { %>
<dd> <dd>
<a target="_blank" href="<%= url %>"><%= name %></a> <% _.each(libraries, function(url, name) { %> <a target="_blank"
href="<%= url %>"><%= name %></a><br /> <% }); %>
</dd> </dd>
<% }); %>
</dl> </dl>
<dl> <dl>
<dt>Related projects:</dt> <dt>Related projects:</dt>
<% _.each(projects, function(url, name) { %>
<dd> <dd>
<a target="_blank" href="<%= url %>"><%= name %></a> <% _.each(projects, function(url, name) { %> <a target="_blank"
href="<%= url %>"><%= name %></a><br /> <% }); %>
</dd> </dd>
<% }); %>
</dl> </dl>
<p>Copyright 2013 <a target="_blank" <p>Copyright 2013 <a target="_blank"
href="http://www.benoitschweblin.com">Benoit Schweblin</a><br /> href="http://www.benoitschweblin.com">Benoit Schweblin</a><br />

View File

@ -6,6 +6,7 @@ requirejs.config({
"underscore": "libs/underscore", "underscore": "libs/underscore",
"jgrowl": "libs/jgrowl", "jgrowl": "libs/jgrowl",
"mousetrap": "libs/mousetrap", "mousetrap": "libs/mousetrap",
"toMarkdown": "libs/to-markdown",
"text": "libs/text", "text": "libs/text",
"libs/MathJax": '../lib/MathJax/MathJax.js?config=TeX-AMS_HTML' "libs/MathJax": '../lib/MathJax/MathJax.js?config=TeX-AMS_HTML'
}, },
@ -22,6 +23,12 @@ requirejs.config({
'mousetrap': { 'mousetrap': {
exports: 'Mousetrap' exports: 'Mousetrap'
}, },
'toMarkdown': {
deps: [
'jquery'
],
exports: 'toMarkdown'
},
'libs/jquery-ui': [ 'libs/jquery-ui': [
'jquery' 'jquery'
], ],

View File

@ -1,8 +1,8 @@
define([ define([
"jquery", "jquery",
"core", "core",
"asyncRunner" "classes/AsyncTask"
], function($, core, asyncRunner) { ], function($, core, AsyncTask) {
var PROVIDER_DOWNLOAD = "download"; var PROVIDER_DOWNLOAD = "download";
@ -14,9 +14,9 @@ define([
}; };
downloadProvider.importPublic = function(importParameters, callback) { downloadProvider.importPublic = function(importParameters, callback) {
var task = asyncRunner.createTask();
var title = undefined; var title = undefined;
var content = undefined; var content = undefined;
var task = new AsyncTask();
task.onRun(function() { task.onRun(function() {
var url = importParameters.url; var url = importParameters.url;
var slashUrl = url.lastIndexOf("/"); var slashUrl = url.lastIndexOf("/");
@ -43,7 +43,7 @@ define([
task.onError(function(error) { task.onError(function(error) {
callback(error); callback(error);
}); });
asyncRunner.addTask(task); task.enqueue();
}; };
return downloadProvider; return downloadProvider;

View File

@ -39,7 +39,6 @@ define([
syncAttributes.version = versionTag; syncAttributes.version = versionTag;
syncAttributes.contentCRC = utils.crc32(content); syncAttributes.contentCRC = utils.crc32(content);
syncAttributes.syncIndex = createSyncIndex(path); syncAttributes.syncIndex = createSyncIndex(path);
utils.storeAttributes(syncAttributes);
return syncAttributes; return syncAttributes;
} }
@ -184,7 +183,8 @@ define([
// File deleted // File deleted
if(change.wasRemoved === true) { if(change.wasRemoved === true) {
extensionMgr.onError('"' + localTitle + '" has been removed from Dropbox.'); extensionMgr.onError('"' + localTitle + '" has been removed from Dropbox.');
fileMgr.removeSync(syncAttributes); fileDesc.removeSyncLocation(syncAttributes);
extensionMgr.onSyncRemoved(fileDesc, syncAttributes);
return; return;
} }
var localContent = fileDesc.content; var localContent = fileDesc.content;
@ -201,6 +201,7 @@ define([
// If file content changed // If file content changed
if(fileContentChanged && remoteContentChanged === true) { if(fileContentChanged && remoteContentChanged === true) {
fileDesc.content = file.content; fileDesc.content = file.content;
extensionMgr.onContentChanged(fileDesc);
extensionMgr.onMessage('"' + localTitle + '" has been updated from Dropbox.'); extensionMgr.onMessage('"' + localTitle + '" has been updated from Dropbox.');
if(fileMgr.isCurrentFile(fileDesc)) { if(fileMgr.isCurrentFile(fileDesc)) {
fileMgr.selectFile(); // Refresh editor fileMgr.selectFile(); // Refresh editor

View File

@ -31,7 +31,6 @@ define([
syncAttributes.contentCRC = utils.crc32(content); syncAttributes.contentCRC = utils.crc32(content);
syncAttributes.titleCRC = utils.crc32(title); syncAttributes.titleCRC = utils.crc32(title);
syncAttributes.syncIndex = createSyncIndex(id); syncAttributes.syncIndex = createSyncIndex(id);
utils.storeAttributes(syncAttributes);
return syncAttributes; return syncAttributes;
} }
@ -179,7 +178,8 @@ define([
// File deleted // File deleted
if(change.deleted === true) { if(change.deleted === true) {
extensionMgr.onError('"' + localTitle + '" has been removed from Google Drive.'); extensionMgr.onError('"' + localTitle + '" has been removed from Google Drive.');
fileMgr.removeSync(syncAttributes); fileDesc.removeSyncLocation(syncAttributes);
extensionMgr.onSyncRemoved(fileDesc, syncAttributes);
return; return;
} }
var localTitleChanged = syncAttributes.titleCRC != utils.crc32(localTitle); var localTitleChanged = syncAttributes.titleCRC != utils.crc32(localTitle);
@ -200,11 +200,13 @@ define([
// If file title changed // If file title changed
if(fileTitleChanged && remoteTitleChanged === true) { if(fileTitleChanged && remoteTitleChanged === true) {
fileDesc.title = file.title; fileDesc.title = file.title;
extensionMgr.onTitleChanged(fileDesc);
extensionMgr.onMessage('"' + localTitle + '" has been renamed to "' + file.title + '" on Google Drive.'); extensionMgr.onMessage('"' + localTitle + '" has been renamed to "' + file.title + '" on Google Drive.');
} }
// If file content changed // If file content changed
if(fileContentChanged && remoteContentChanged === true) { if(fileContentChanged && remoteContentChanged === true) {
fileDesc.content = file.content; fileDesc.content = file.content;
extensionMgr.onContentChanged(fileDesc);
extensionMgr.onMessage('"' + file.title + '" has been updated from Google Drive.'); extensionMgr.onMessage('"' + file.title + '" has been updated from Google Drive.');
if(fileMgr.isCurrentFile(fileDesc)) { if(fileMgr.isCurrentFile(fileDesc)) {
fileMgr.selectFile(); // Refresh editor fileMgr.selectFile(); // Refresh editor

View File

@ -54,41 +54,41 @@ define([
}); });
// Apply template to the current document // Apply template to the current document
publisher.applyTemplate = function(publishAttributes) { publisher.applyTemplate = function(fileDesc, publishAttributes, html) {
var fileDesc = fileMgr.getCurrentFile();
try { try {
return _.template(settings.template, { return _.template(settings.template, {
documentTitle: fileDesc.title, documentTitle: fileDesc.title,
documentMarkdown: $("#wmd-input").val(), documentMarkdown: fileDesc.content,
documentHTML: $("#wmd-preview").html(), documentHTML: html,
publishAttributes: publishAttributes publishAttributes: publishAttributes
}); });
} }
catch(e) { catch(e) {
extensionMgr.onError(e); extensionMgr.onError(e);
throw e; return e.message;
} }
}; };
// Used to get content to publish // Used to get content to publish
function getPublishContent(publishAttributes) { function getPublishContent(fileDesc, publishAttributes, html) {
if(publishAttributes.format === undefined) { if(publishAttributes.format === undefined) {
publishAttributes.format = $("input:radio[name=radio-publish-format]:checked").prop("value"); publishAttributes.format = $("input:radio[name=radio-publish-format]:checked").prop("value");
} }
if(publishAttributes.format == "markdown") { if(publishAttributes.format == "markdown") {
return $("#wmd-input").val(); return fileDesc.content;
} }
else if(publishAttributes.format == "html") { else if(publishAttributes.format == "html") {
return $("#wmd-preview").html(); return html;
} }
else { else {
return publisher.applyTemplate(publishAttributes); return publisher.applyTemplate(fileDesc, publishAttributes, html);
} }
} }
// Recursive function to publish a file on multiple locations // Recursive function to publish a file on multiple locations
var publishAttributesList = []; var publishAttributesList = [];
var publishTitle = undefined; var publishFileDesc = undefined;
var publishHTML = undefined;
function publishLocation(callback, errorFlag) { function publishLocation(callback, errorFlag) {
// No more publish location for this document // No more publish location for this document
@ -99,14 +99,17 @@ define([
// Dequeue a synchronized location // Dequeue a synchronized location
var publishAttributes = publishAttributesList.pop(); var publishAttributes = publishAttributesList.pop();
var content = getPublishContent(publishAttributes);
// Format the content
var content = getPublishContent(publishFileDesc, publishAttributes, publishHTML);
// Call the provider // Call the provider
publishAttributes.provider.publish(publishAttributes, publishTitle, content, function(error) { publishAttributes.provider.publish(publishAttributes, publishFileDesc.title, content, function(error) {
if(error !== undefined) { if(error !== undefined) {
var errorMsg = error.toString(); var errorMsg = error.toString();
if(errorMsg.indexOf("|removePublish") !== -1) { if(errorMsg.indexOf("|removePublish") !== -1) {
fileMgr.removePublish(publishAttributes); publishFileDesc.removePublishLocation(publishAttributes);
extensionMgr.onPublishRemoved(publishFileDesc, publishAttributes);
} }
if(errorMsg.indexOf("|stopPublish") !== -1) { if(errorMsg.indexOf("|stopPublish") !== -1) {
callback(error); callback(error);
@ -126,14 +129,14 @@ define([
publishRunning = true; publishRunning = true;
extensionMgr.onPublishRunning(true); extensionMgr.onPublishRunning(true);
var fileDesc = fileMgr.getCurrentFile(); publishFileDesc = fileMgr.getCurrentFile();
publishTitle = fileDesc.title; publishHTML = $("#wmd-preview").html();
publishAttributesList = _.values(fileDesc.publishLocations); publishAttributesList = _.values(publishFileDesc.publishLocations);
publishLocation(function(errorFlag) { publishLocation(function(errorFlag) {
publishRunning = false; publishRunning = false;
extensionMgr.onPublishRunning(false); extensionMgr.onPublishRunning(false);
if(errorFlag === undefined) { if(errorFlag === undefined) {
extensionMgr.onPublishSuccess(fileDesc); extensionMgr.onPublishSuccess(publishFileDesc);
} }
}); });
}; };
@ -145,8 +148,8 @@ define([
publishIndex = "publish." + utils.randomString(); publishIndex = "publish." + utils.randomString();
} while (_.has(localStorage, publishIndex)); } while (_.has(localStorage, publishIndex));
publishAttributes.publishIndex = publishIndex; publishAttributes.publishIndex = publishIndex;
utils.storeAttributes(publishAttributes); fileDesc.addPublishLocation(publishAttributes);
fileMgr.addPublish(fileDesc, publishAttributes); extensionMgr.onNewPublishSuccess(fileDesc, publishAttributes);
} }
// Initialize the "New publication" dialog // Initialize the "New publication" dialog
@ -186,9 +189,9 @@ define([
// Perform provider's publishing // Perform provider's publishing
var fileDesc = fileMgr.getCurrentFile(); var fileDesc = fileMgr.getCurrentFile();
var title = fileDesc.title; var html = $("#wmd-preview").html();
var content = getPublishContent(publishAttributes); var content = getPublishContent(fileDesc, publishAttributes, html);
provider.publish(publishAttributes, title, content, function(error) { provider.publish(publishAttributes, fileDesc.title, content, function(error) {
if(error === undefined) { if(error === undefined) {
publishAttributes.provider = provider; publishAttributes.provider = provider;
sharing.createLink(publishAttributes, function() { sharing.createLink(publishAttributes, function() {
@ -235,9 +238,10 @@ define([
utils.saveAs(content, title + ".html"); utils.saveAs(content, title + ".html");
}); });
$(".action-download-template").click(function() { $(".action-download-template").click(function() {
var content = publisher.applyTemplate(); var fileDesc = fileMgr.getCurrentFile();
var title = fileMgr.getCurrentFile().title; var html = $("#wmd-preview").html();
utils.saveAs(content, title + (settings.template.indexOf("documentHTML") === -1 ? ".md" : ".html")); var content = publisher.applyTemplate(fileDesc, undefined, html);
utils.saveAs(content, fileDesc.title + (settings.template.indexOf("documentHTML") === -1 ? ".md" : ".html"));
}); });
}); });

View File

@ -5,10 +5,10 @@ define([
"utils", "utils",
"extensionMgr", "extensionMgr",
"fileMgr", "fileMgr",
"asyncRunner", "classes/AsyncTask",
"providers/downloadProvider", "providers/downloadProvider",
"providers/gistProvider" "providers/gistProvider"
], function($, _, core, utils, extensionMgr, fileMgr, asyncRunner) { ], function($, _, core, utils, extensionMgr, fileMgr, AsyncTask) {
var sharing = {}; var sharing = {};
@ -30,7 +30,7 @@ define([
callback(); callback();
return; return;
} }
var task = asyncRunner.createTask(); var task = new AsyncTask();
var shortUrl = undefined; var shortUrl = undefined;
task.onRun(function() { task.onRun(function() {
if(core.isOffline === true) { if(core.isOffline === true) {
@ -69,7 +69,7 @@ define([
} }
task.onSuccess(onFinish); task.onSuccess(onFinish);
task.onError(onFinish); task.onError(onFinish);
asyncRunner.addTask(task); task.enqueue();
}; };
core.onReady(function() { core.onReady(function() {

View File

@ -121,5 +121,15 @@ define([
version = "v6"; version = "v6";
} }
// Upgrade from v6 to v7
if(version == "v6") {
var currentFileIndex = localStorage["file.current"];
if(currentFileIndex !== undefined) {
localStorage[currentFileIndex + ".selectTime"] = new Date().getTime();
localStorage.removeItem("file.current");
}
version = "v7";
}
localStorage["version"] = version; localStorage["version"] = version;
}); });

View File

@ -223,7 +223,8 @@ define([
if(error) { if(error) {
return; return;
} }
fileMgr.addSync(fileDesc, syncAttributes); fileDesc.addSyncLocation(syncAttributes);
extensionMgr.onSyncExportSuccess(fileDesc, syncAttributes);
}); });
// Store input values as preferences for next time we open the // Store input values as preferences for next time we open the
@ -241,7 +242,8 @@ define([
if(error) { if(error) {
return; return;
} }
fileMgr.addSync(fileDesc, syncAttributes); fileDesc.addSyncLocation(syncAttributes);
extensionMgr.onSyncExportSuccess(fileDesc, syncAttributes);
}); });
}); });
}); });