Add sharing support

This commit is contained in:
benweet 2013-05-02 01:02:57 +01:00
parent 5303ae8e74
commit cbdbcbda4a
10 changed files with 118 additions and 153 deletions

View File

@ -218,6 +218,33 @@ hr {
font-weight: bold; font-weight: bold;
} }
.dropdown-menu .divider.with-text {
height: auto;
margin-bottom: 2px;
background-color: transparent;
border-top: 1px solid #e5e5e5;
color: #ccc;
font-variant: small-caps;
font-weight: bold;
padding-left: 20px;
cursor: default;
}
div.dropdown-menu {
padding: 5px 20px;
width: 300px;
white-space: normal;
}
div.dropdown-menu p,
div.dropdown-menu blockquote {
margin: 10px 0;
}
.icon-link {
background-position: -72px -168px;
}
.icon-code { .icon-code {
width: 15px; width: 15px;
background-position: -384px -168px; background-position: -384px -168px;

View File

@ -34,13 +34,25 @@
</ul> </ul>
<ul class="pull-right hide" id="menu-bar"> <ul class="pull-right hide" id="menu-bar">
<li class="btn-group"> <li class="btn-group">
<button class="btn action-force-sync" <button class="btn action-force-sync" title="Synchronize">
title="Synchronize">
<i class="icon-refresh"></i> <i class="icon-refresh"></i>
</button> </button>
<button class="btn action-force-publish" title="Publish"> <button class="btn action-force-publish" title="Publish">
<i class="icon-share"></i> <i class="icon-share"></i>
</button></li> </button>
<button class="btn dropdown-toggle" data-toggle="dropdown"
title="Share this document">
<i class="icon-link"></i>
</button>
<div id="link-container" class="dropdown-menu">
<div class="link-list"></div>
<p class="no-link">
To share this document you need first to synchronize it or to publish it in Markdown format on
<a href="#" class="action-publish-gist">Gist</a>.
</p>
<blockquote class="muted">Please make sure the document is public.</blockquote>
</div>
</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>
@ -59,15 +71,15 @@
data-toggle="dropdown" href="#" title="Menu"><i data-toggle="dropdown" href="#" title="Menu"><i
class="icon-stackedit"></i>&nbsp;&nbsp;<b class="caret"></b></a> class="icon-stackedit"></i>&nbsp;&nbsp;<b class="caret"></b></a>
<ul class="dropdown-menu"> <ul class="dropdown-menu">
<li><a href="viewer.html"><i <li><a href="viewer.html"><i class="icon-fullscreen"></i>
class="icon-fullscreen"></i> Open in viewer</a></li> Open in viewer</a></li>
<li><a class="action-download-md" href="#"><i <li><a class="action-download-md" href="#"><i
class="icon-download-alt"></i> Save as Markdown</a></li> class="icon-download-alt"></i> Save as Markdown</a></li>
<li><a class="action-download-html" href="#"><i <li><a class="action-download-html" href="#"><i
class="icon-download-alt"></i> Save as HTML</a></li> class="icon-download-alt"></i> Save as HTML</a></li>
<li><a class="action-download-template" href="#"><i <li><a class="action-download-template" href="#"><i
class="icon-download-alt"></i> Save using template</a></li> class="icon-download-alt"></i> Save using template</a></li>
<li class="divider"></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>
<ul class="dropdown-menu"> <ul class="dropdown-menu">
@ -89,7 +101,7 @@
<li><a href="#" data-toggle="modal" <li><a href="#" data-toggle="modal"
data-target="#modal-manage-sync" class="action-reset-input"><i data-target="#modal-manage-sync" class="action-reset-input"><i
class="icon-refresh"></i> Manage synchronization</a></li> class="icon-refresh"></i> Manage synchronization</a></li>
<li class="divider"></li> <li class="divider with-text">publish</li>
<li class="dropdown-submenu"><a href="#"><i <li class="dropdown-submenu"><a href="#"><i
class="icon-share"></i> Publish on</a> class="icon-share"></i> Publish on</a>
<ul id="publish-menu" class="dropdown-menu"> <ul id="publish-menu" class="dropdown-menu">

View File

@ -1,9 +1,11 @@
var MAIN_URL = "http://benweet.github.io/stackedit/";
var GOOGLE_SCOPES = [ "https://www.googleapis.com/auth/drive.install", var GOOGLE_SCOPES = [ "https://www.googleapis.com/auth/drive.install",
"https://www.googleapis.com/auth/drive", "https://www.googleapis.com/auth/drive",
"https://www.googleapis.com/auth/blogger" ]; "https://www.googleapis.com/auth/blogger" ];
var GOOGLE_DRIVE_APP_ID = "241271498917"; var GOOGLE_DRIVE_APP_ID = "241271498917";
var DROPBOX_APP_KEY = "lq6mwopab8wskas"; var DROPBOX_APP_KEY = "lq6mwopab8wskas";
var DROPBOX_APP_SECRET = "851fgnucpezy84t"; var DROPBOX_APP_SECRET = "851fgnucpezy84t";
var BITLY_ACCESS_TOKEN = "317e033bfd48cf31155a68a536b1860013b09c4c";
var DEFAULT_FILE_TITLE = "Title"; var DEFAULT_FILE_TITLE = "Title";
var GDRIVE_DEFAULT_FILE_TITLE = "New Markdown document"; var GDRIVE_DEFAULT_FILE_TITLE = "New Markdown document";
var CHECK_ONLINE_PERIOD = 60000; var CHECK_ONLINE_PERIOD = 60000;
@ -37,7 +39,7 @@ var GATEKEEPER_URL = "http://stackedit-gatekeeper-localhost.herokuapp.com/";
var TUMBLR_PROXY_URL = "http://stackedit-tumblr-proxy-local.herokuapp.com/"; var TUMBLR_PROXY_URL = "http://stackedit-tumblr-proxy-local.herokuapp.com/";
if(location.hostname.indexOf("benweet.github.io") === 0) { if(location.hostname.indexOf("benweet.github.io") === 0) {
BASE_URL = "http://benweet.github.io/stackedit/"; BASE_URL = MAIN_URL;
GOOGLE_KEY = "AIzaSyB1Bc1wI_YUWkkOR-5Gri5BFuypgZl0Sxc"; GOOGLE_KEY = "AIzaSyB1Bc1wI_YUWkkOR-5Gri5BFuypgZl0Sxc";
GOOGLE_CLIENT_ID = '241271498917-jpto9lls9fqnem1e4h6ppds9uob8rpvu.apps.googleusercontent.com'; GOOGLE_CLIENT_ID = '241271498917-jpto9lls9fqnem1e4h6ppds9uob8rpvu.apps.googleusercontent.com';
GITHUB_CLIENT_ID = 'fa0d09514da8377ee32e'; GITHUB_CLIENT_ID = 'fa0d09514da8377ee32e';

View File

@ -1,5 +1,5 @@
define( define(
[ "jquery", "bootstrap", "jgrowl", "layout", "Markdown.Editor", "config", [ "jquery", "bootstrap", "jgrowl", "layout", "Markdown.Editor", "storage", "config",
"underscore", "FileSaver", "css_browser_selector" ], "underscore", "FileSaver", "css_browser_selector" ],
function($) { function($) {
@ -672,121 +672,6 @@ define(
return _.random(4294967296).toString(36); return _.random(4294967296).toString(36);
}; };
// Used to setup an empty localStorage or to upgrade an existing one
function setupLocalStorage() {
// Create the file system if not exist
if (localStorage["file.list"] === undefined) {
localStorage["file.list"] = ";";
}
// localStorage versioning
var version = localStorage["version"];
// Upgrade from v0 to v1
if(version === undefined) {
// Not used anymore
localStorage.removeItem("sync.queue");
localStorage.removeItem("sync.current");
localStorage.removeItem("file.counter");
var fileIndexList = _.compact(localStorage["file.list"].split(";"));
_.each(fileIndexList, function(fileIndex) {
localStorage[fileIndex + ".publish"] = ";";
var syncIndexList = _.compact(localStorage[fileIndex + ".sync"].split(";"));
_.each(syncIndexList, function(syncIndex) {
localStorage[syncIndex + ".contentCRC"] = "0";
// We store title CRC only for Google Drive synchronization
if(localStorage[syncIndex + ".etag"] !== undefined) {
localStorage[syncIndex + ".titleCRC"] = "0";
}
});
});
version = "v1";
}
// Upgrade from v1 to v2
if(version == "v1") {
var gdriveLastChangeId = localStorage["sync.gdrive.lastChangeId"];
if(gdriveLastChangeId) {
localStorage["gdrive.lastChangeId"] = gdriveLastChangeId;
localStorage.removeItem("sync.gdrive.lastChangeId");
}
var dropboxLastChangeId = localStorage["sync.dropbox.lastChangeId"];
if(dropboxLastChangeId) {
localStorage["dropbox.lastChangeId"] = dropboxLastChangeId;
localStorage.removeItem("sync.dropbox.lastChangeId");
}
var SYNC_PROVIDER_GDRIVE = "sync." + PROVIDER_GDRIVE + ".";
var SYNC_PROVIDER_DROPBOX = "sync." + PROVIDER_DROPBOX + ".";
var fileIndexList = _.compact(localStorage["file.list"].split(";"));
_.each(fileIndexList, function(fileIndex) {
var syncIndexList = _.compact(localStorage[fileIndex + ".sync"].split(";"));
_.each(syncIndexList, function(syncIndex) {
var syncAttributes = {};
if (syncIndex.indexOf(SYNC_PROVIDER_GDRIVE) === 0) {
syncAttributes.provider = PROVIDER_GDRIVE;
syncAttributes.id = syncIndex.substring(SYNC_PROVIDER_GDRIVE.length);
syncAttributes.etag = localStorage[syncIndex + ".etag"];
syncAttributes.contentCRC = localStorage[syncIndex + ".contentCRC"];
syncAttributes.titleCRC = localStorage[syncIndex + ".titleCRC"];
}
else if (syncIndex.indexOf(SYNC_PROVIDER_DROPBOX) === 0) {
syncAttributes.provider = PROVIDER_DROPBOX;
syncAttributes.path = decodeURIComponent(syncIndex.substring(SYNC_PROVIDER_DROPBOX.length));
syncAttributes.version = localStorage[syncIndex + ".version"];
syncAttributes.contentCRC = localStorage[syncIndex + ".contentCRC"];
}
localStorage[syncIndex] = JSON.stringify(syncAttributes);
localStorage.removeItem(syncIndex + ".etag");
localStorage.removeItem(syncIndex + ".version");
localStorage.removeItem(syncIndex + ".contentCRC");
localStorage.removeItem(syncIndex + ".titleCRC");
});
});
version = "v2";
}
// Upgrade from v2 to v3
if(version == "v2") {
var fileIndexList = _.compact(localStorage["file.list"].split(";"));
_.each(fileIndexList, function(fileIndex) {
if(!_.has(localStorage, fileIndex + ".sync")) {
localStorage.removeItem(fileIndex + ".title");
localStorage.removeItem(fileIndex + ".publish");
localStorage.removeItem(fileIndex + ".content");
localStorage["file.list"] = localStorage["file.list"].replace(";"
+ fileIndex + ";", ";");
}
});
version = "v3";
}
// Upgrade from v3 to v4
if(version == "v3") {
var currentFileIndex = localStorage["file.current"];
if(currentFileIndex !== undefined &&
localStorage["file.list"].indexOf(";" + currentFileIndex + ";") === -1)
{
localStorage.removeItem("file.current");
}
version = "v4";
}
// Upgrade from v4 to v5
if(version == "v4") {
// Recreate GitHub token
localStorage.removeItem("githubToken");
version = "v5";
}
localStorage["version"] = version;
}
// Setup the localStorage when starting
setupLocalStorage();
// Create an centered popup window // Create an centered popup window
core.popupWindow = function(url, title, w, h) { core.popupWindow = function(url, title, w, h) {
var left = (screen.width / 2) - (w / 2); var left = (screen.width / 2) - (w / 2);

View File

@ -1,5 +1,5 @@
define(["jquery", "core", "synchronizer", "publisher", "text!../WELCOME.md", "underscore"], define(["jquery", "core", "synchronizer", "publisher", "sharing", "text!../WELCOME.md", "underscore"],
function($, core, synchronizer, publisher, welcomeContent) { function($, core, synchronizer, publisher, sharing, welcomeContent) {
var fileManager = {}; var fileManager = {};
@ -13,8 +13,6 @@ define(["jquery", "core", "synchronizer", "publisher", "text!../WELCOME.md", "un
}; };
fileManager.setCurrentFileIndex = function(fileIndex) { fileManager.setCurrentFileIndex = function(fileIndex) {
currentFileIndex = fileIndex; currentFileIndex = fileIndex;
// Sanity check since we are going to modify current file in localStorage
core.checkWindowUnique();
if(fileIndex === undefined) { if(fileIndex === undefined) {
localStorage.removeItem("file.current"); localStorage.removeItem("file.current");
} }
@ -134,12 +132,22 @@ define(["jquery", "core", "synchronizer", "publisher", "text!../WELCOME.md", "un
} }
synchronizer.resetSyncFlags(); synchronizer.resetSyncFlags();
function composeTitle(fileIndex) { var links = [];
function composeTitle(fileIndex, generateLinks) {
var result = []; var result = [];
var providerIdList = synchronizer.getSyncProvidersFromFile(fileIndex); var syncAttributesList = synchronizer.getSyncAttributesFromFile(fileIndex);
providerIdList = providerIdList.concat(publisher.getPublishProvidersFromFile(fileIndex)); var publishAttributesList = publisher.getPublishAttributesFromFile(fileIndex);
_.each(providerIdList.sort(), function(providerId) { var attributesList = syncAttributesList.concat(publishAttributesList);
result.push('<i class="icon-' + providerId + '"></i>'); _.chain(attributesList).sortBy(function(attributes) {
return attributes.provider;
}).each(function(attributes) {
result.push('<i class="icon-' + attributes.provider + '"></i>');
if(generateLinks === true) {
var url = sharing.getLink(attributes);
if(url !== undefined) {
links.push(url);
}
}
}); });
result.push(" "); result.push(" ");
result.push(localStorage[fileIndex + ".title"]); result.push(localStorage[fileIndex + ".title"]);
@ -149,9 +157,18 @@ define(["jquery", "core", "synchronizer", "publisher", "text!../WELCOME.md", "un
// Update the file title // Update the file title
var title = localStorage[fileIndex + ".title"]; var title = localStorage[fileIndex + ".title"];
document.title = "StackEdit - " + title; document.title = "StackEdit - " + title;
$("#file-title").html(composeTitle(fileIndex)); $("#file-title").html(composeTitle(fileIndex, true));
$(".file-title").text(title); $(".file-title").text(title);
$("#file-title-input").val(title); $("#file-title-input").val(title);
var linkList = $(".link-list").empty();
if(links.length > 0) {
_.each(links, function(url) {
linkList.append($('<div><a href="' + url + '">' + url + '</a></div>'));
});
$("#link-container no-link").hide();
} else {
$("#link-container no-link").show();
}
// Update the file selector // Update the file selector
$("#file-selector").empty(); $("#file-selector").empty();

View File

@ -4,6 +4,7 @@ define(["jquery", "core", "google-helper", "underscore"], function($, core, goog
providerId: PROVIDER_GDRIVE, providerId: PROVIDER_GDRIVE,
providerName: "Google Drive", providerName: "Google Drive",
defaultPublishFormat: "template", defaultPublishFormat: "template",
sharingAttributes: ["id"],
useSync: false useSync: false
}; };
@ -214,7 +215,7 @@ define(["jquery", "core", "google-helper", "underscore"], function($, core, goog
gdriveProvider.publish = function(publishAttributes, title, content, callback) { gdriveProvider.publish = function(publishAttributes, title, content, callback) {
googleHelper.upload( googleHelper.upload(
publishAttributes.fileId, publishAttributes.id,
undefined, undefined,
publishAttributes.fileName || title, publishAttributes.fileName || title,
content, content,
@ -224,7 +225,7 @@ define(["jquery", "core", "google-helper", "underscore"], function($, core, goog
callback(error); callback(error);
return; return;
} }
publishAttributes.fileId = result.id; publishAttributes.id = result.id;
callback(); callback();
} }
); );
@ -232,7 +233,7 @@ define(["jquery", "core", "google-helper", "underscore"], function($, core, goog
gdriveProvider.newPublishAttributes = function(event) { gdriveProvider.newPublishAttributes = function(event) {
var publishAttributes = {}; var publishAttributes = {};
publishAttributes.fileId = $("#input-publish-gdrive-fileid").val() || undefined; publishAttributes.id = $("#input-publish-gdrive-fileid").val() || undefined;
publishAttributes.fileName = $("#input-publish-gdrive-filename").val() || undefined; publishAttributes.fileName = $("#input-publish-gdrive-filename").val() || undefined;
if(event.isPropagationStopped()) { if(event.isPropagationStopped()) {
return undefined; return undefined;

View File

@ -20,7 +20,7 @@ define(["jquery", "core", "github-helper"], function($, core, githubHelper) {
gistProvider.newPublishAttributes = function(event) { gistProvider.newPublishAttributes = function(event) {
var publishAttributes = {}; var publishAttributes = {};
publishAttributes.gistId = core.getInputValue($("#input-publish-gist-id")); publishAttributes.gistId = $("#input-publish-gist-id").val() || undefined;
publishAttributes.filename = core.getInputValue($("#input-publish-filename"), event); publishAttributes.filename = core.getInputValue($("#input-publish-filename"), event);
publishAttributes.isPublic = $("#input-publish-gist-public").is(":checked"); publishAttributes.isPublic = $("#input-publish-gist-public").is(":checked");
if(event.isPropagationStopped()) { if(event.isPropagationStopped()) {

View File

@ -208,14 +208,14 @@ define(["jquery", "core", "blogger-provider", "dropbox-provider", "gist-provider
}); });
}; };
publisher.getPublishProvidersFromFile = function(fileIndex) { publisher.getPublishAttributesFromFile = function(fileIndex) {
var publishIndexList = _.compact(localStorage[fileIndex + ".publish"].split(";")); var publishIndexList = _.compact(localStorage[fileIndex + ".publish"].split(";"));
var providerIdList = []; var attributesList = [];
_.each(publishIndexList, function(publishIndex) { _.each(publishIndexList, function(publishIndex) {
var publishAttributes = JSON.parse(localStorage[publishIndex]); var publishAttributes = JSON.parse(localStorage[publishIndex]);
providerIdList.push(publishAttributes.provider); attributesList.push(publishAttributes);
}); });
return providerIdList; return attributesList;
}; };
core.onReady(function() { core.onReady(function() {
@ -232,6 +232,10 @@ define(["jquery", "core", "blogger-provider", "dropbox-provider", "gist-provider
) )
) )
); );
// Action links (if any)
$(".action-publish-" + provider.providerId).click(function() {
initNewLocation(provider);
});
}); });
$(".action-process-publish").click(performNewLocation); $(".action-process-publish").click(performNewLocation);

View File

@ -224,15 +224,15 @@ define(["jquery", "core", "dropbox-provider", "gdrive-provider", "underscore"],
provider.useSync = false; provider.useSync = false;
}); });
}; };
synchronizer.getSyncProvidersFromFile = function(fileIndex) { synchronizer.getSyncAttributesFromFile = function(fileIndex) {
var syncIndexList = _.compact(localStorage[fileIndex + ".sync"].split(";")); var syncIndexList = _.compact(localStorage[fileIndex + ".sync"].split(";"));
var providerIdList = []; var attributesList = [];
_.each(syncIndexList, function(syncIndex) { _.each(syncIndexList, function(syncIndex) {
var syncAttributes = JSON.parse(localStorage[syncIndex]); var syncAttributes = JSON.parse(localStorage[syncIndex]);
providerIdList.push(syncAttributes.provider); attributesList.push(syncAttributes);
providerMap[syncAttributes.provider].useSync = true; providerMap[syncAttributes.provider].useSync = true;
}); });
return providerIdList; return attributesList;
}; };
core.onReady(function() { core.onReady(function() {

View File

@ -63,5 +63,22 @@
<div id="wmd-button-bar" class="hide"></div> <div id="wmd-button-bar" class="hide"></div>
<textarea id="wmd-input" class="hide"></textarea> <textarea id="wmd-input" class="hide"></textarea>
<div id="wmd-preview" class="well"></div> <div id="wmd-preview" class="well"></div>
<div id="modal-non-unique" class="modal hide">
<div class="modal-header">
<h3>Whoops...</h3>
</div>
<div class="modal-body">
<p>StackEdit has stopped because another instance was running in
the same browser.</p>
<blockquote class="muted">If you want to reopen
StackEdit, click on "Reload".</blockquote>
</div>
<div class="modal-footer">
<a href="javascript:window.location.reload();"
class="btn btn-primary">Reload</a>
</div>
</div>
</body> </body>
</html> </html>