Compare commits

..

No commits in common. "master" and "medium" have entirely different histories.

10 changed files with 42 additions and 352 deletions

View file

@ -107,19 +107,12 @@ $app->get('/auth/start', function() use($app) {
$authorizationURL = false;
}
// If the user has already signed in before and has a micropub access token,
// and the endpoints are all the same, skip the debugging screens and redirect
// immediately to the auth endpoint.
// If the user has already signed in before and has a micropub access token, skip
// the debugging screens and redirect immediately to the auth endpoint.
// This will still generate a new access token when they finish logging in.
$user = ORM::for_table('users')->where('url', $me)->find_one();
if($user && $user->micropub_access_token
&& $user->micropub_endpoint == $micropubEndpoint
&& $user->token_endpoint == $tokenEndpoint
&& $user->authorization_endpoint == $authorizationEndpoint
&& !array_key_exists('restart', $params)) {
if($user && $user->micropub_access_token && !array_key_exists('restart', $params)) {
// TODO: fix this by caching the endpoints maybe in the session instead of writing them to the DB here.
// Then remove the line below that blanks out the access token
$user->micropub_endpoint = $micropubEndpoint;
$user->authorization_endpoint = $authorizationEndpoint;
$user->token_endpoint = $tokenEndpoint;
@ -136,7 +129,6 @@ $app->get('/auth/start', function() use($app) {
$user->micropub_endpoint = $micropubEndpoint;
$user->authorization_endpoint = $authorizationEndpoint;
$user->token_endpoint = $tokenEndpoint;
$user->micropub_access_token = ''; // blank out the access token if they attempt to sign in again
$user->save();
$html = render('auth_start', array(

View file

@ -127,24 +127,6 @@ $app->get('/favorite', function() use($app) {
}
});
$app->get('/repost', function() use($app) {
if($user=require_login($app)) {
$params = $app->request()->params();
$url = '';
if(array_key_exists('url', $params))
$url = $params['url'];
$html = render('new-repost', array(
'title' => 'New Repost',
'url' => $url,
'token' => generate_login_token()
));
$app->response()->body($html);
}
});
$app->post('/prefs', function() use($app) {
if($user=require_login($app)) {
$params = $app->request()->params();
@ -270,7 +252,7 @@ function create_favorite(&$user, $url) {
}
}
if($user->twitter_access_token && preg_match('/https?:\/\/(?:www\.)?twitter\.com\/[^\/]+\/status(?:es)?\/(\d+)/', $url, $match)) {
if(preg_match('/https?:\/\/(?:www\.)?twitter\.com\/[^\/]+\/status(?:es)?\/(\d+)/', $url, $match)) {
$tweet_id = $match[1];
$twitter = new \TwitterOAuth\Api(Config::$twitterClientID, Config::$twitterClientSecret,
$user->twitter_access_token, $user->twitter_token_secret);
@ -282,24 +264,6 @@ function create_favorite(&$user, $url) {
return $r;
}
function create_repost(&$user, $url) {
$micropub_request = array(
'repost-of' => $url
);
$r = micropub_post_for_user($user, $micropub_request);
$tweet_id = false;
if($user->twitter_access_token && preg_match('/https?:\/\/(?:www\.)?twitter\.com\/[^\/]+\/status(?:es)?\/(\d+)/', $url, $match)) {
$tweet_id = $match[1];
$twitter = new \TwitterOAuth\Api(Config::$twitterClientID, Config::$twitterClientSecret,
$user->twitter_access_token, $user->twitter_token_secret);
$result = $twitter->post('statuses/retweet/'.$tweet_id);
}
return $r;
}
$app->get('/favorite.js', function() use($app) {
$app->response()->header("Content-type", "text/javascript");
if($user=require_login($app, false)) {
@ -336,19 +300,6 @@ $app->post('/favorite', function() use($app) {
}
});
$app->post('/repost', function() use($app) {
if($user=require_login($app)) {
$params = $app->request()->params();
$r = create_repost($user, $params['url']);
$app->response()->body(json_encode(array(
'location' => $r['location'],
'error' => $r['error']
)));
}
});
$app->get('/micropub/syndications', function() use($app) {
if($user=require_login($app)) {
$data = get_syndication_targets($user);

View file

@ -21,8 +21,7 @@ $app->post('/editor/publish', function() use($app) {
$app->response()['Content-type'] = 'application/json';
$app->response()->body(json_encode([
'location' => $r['location'],
'response' => trim(htmlspecialchars($r['response']))
'location' => $r['location']
]));
}
});
@ -31,7 +30,7 @@ $app->post('/editor/upload', function() use($app) {
// Fake a file uploader by echo'ing back the data URI
$fn = $_FILES['files']['tmp_name'][0];
$imageData = base64_encode(file_get_contents($fn));
$src = 'data:'.mime_content_type($fn).';base64,'.$imageData;
$src = 'data: '.mime_content_type($fn).';base64,'.$imageData;
$app->response()['Content-type'] = 'application/json';
$app->response()->body(json_encode([
@ -61,9 +60,9 @@ $app->post('/editor/test-login', function() use($app) {
$app->response()->body(json_encode(['logged_in'=>$logged_in]));
});
$app->get('/appcache.manifest', function() use($app) {
$content = partial('partials/appcache');
// $app->get('/appcache.manifest', function() use($app) {
// $content = partial('partials/appcache');
$app->response()['Content-type'] = 'text/cache-manifest';
$app->response()->body($content);
});
// $app->response()['Content-type'] = 'text/cache-manifest';
// $app->response()->body($content);
// });

View file

@ -100,7 +100,7 @@ function micropub_post($endpoint, $params, $access_token) {
$post = http_build_query(array_merge(array(
'h' => 'entry'
), $params));
$post = preg_replace('/%5B[0-9]+%5D/', '%5B%5D', $post); // change [0] to []
$post = preg_replace('/%5B[0-9]+%5D/', '%5B%5D', $post);
curl_setopt($ch, CURLOPT_POSTFIELDS, $post);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HEADER, true);

View file

@ -1,6 +1,5 @@
var editor = new MediumEditor('.editable', {
buttons: ['bold', 'italic', 'anchor', 'header1', 'header2', 'quote', 'unorderedlist', 'pre'],
placeholder: 'Write something nice...',
paste: {
// This example includes the default options for paste, if nothing is passed this is what it used
forcePlainText: false,
@ -11,7 +10,7 @@ var editor = new MediumEditor('.editable', {
}
});
$(function() {
$(function () {
$('.editable').mediumInsert({
editor: editor,
beginning: true,
@ -27,82 +26,46 @@ $(function() {
}
}
});
$('.editable').focus(function(){
$('.placeholder').removeClass('placeholder');
});
$.post('/editor/test-login', {}, function(response) {
if(response.logged_in) {
$('.publish-dropdown .action-publish').removeClass('hidden');
$('.publish-dropdown .action-signin').addClass('hidden');
} else {
$('.publish-dropdown .action-publish').addClass('hidden');
$('.publish-dropdown .action-signin').removeClass('hidden');
}
$('#publish_btn').text(response.logged_in ? 'Publish' : 'Sign In');
});
$('#publish_btn').click(function(){
if($('.publish-dropdown').hasClass('hidden')) {
$('.publish-dropdown').removeClass('hidden');
if($('#publish_btn').text() == 'Publish') {
$.post('/editor/publish', {
name: $("#post-name").val(),
body: editor.serialize().content.value
}, function(response) {
if(response.location) {
reset_page().then(function(){
window.location = response.location;
});
}
});
} else {
$('.publish-dropdown').addClass('hidden');
var url = prompt("Enter your URL");
window.location = '/auth/start?me=' + encodeURIComponent(url) + '&redirect=/editor';
}
});
$('#new_btn').click(function(){
if(confirm('This will discard your current post. Are you sure?')) {
reset_page();
}
reset_page();
});
$('#signin-domain').on('keydown', function(e){
if(e.keyCode == 13) {
$('#signin-btn').click();
}
});
$('#signin-btn').click(function(){
window.location = '/auth/start?me=' + encodeURIComponent($('#signin-domain').val()) + '&redirect=/editor';
});
$('#publish-confirm').click(function(){
$('#publish-help').addClass('hidden');
$('#publish-in-progress').removeClass('hidden');
$.post('/editor/publish', {
name: $("#post-name").val(),
body: editor.serialize().content.value
}, function(response) {
if(response.location) {
reset_page().then(function(){
$('#publish-success-url').attr('href', response.location);
$('#publish-in-progress').addClass('hidden');
$('#publish-error-debug').html('').addClass('hidden');
$('#publish-error').addClass('hidden');
$('#publish-success').removeClass('hidden');
});
} else {
$('#publish-in-progress').addClass('hidden');
$('#publish-error-debug').html(response.response).removeClass('hidden');
$('#publish-error').removeClass('hidden');
$('#publish-success').addClass('hidden');
}
});
});
});
function reset_page() {
$("#post-name").val('');
$("#content").html('<p class="placeholder">Write something nice...</p>');
$("#draft-status").text("New");
return localforage.setItem('currentdraft', {});
}
function onUpdateReady() {
// Show the notice that says there is a new version of the app
$("#new_version_available").show();
}
window.applicationCache.addEventListener('updateready', onUpdateReady);
if(window.applicationCache.status === window.applicationCache.UPDATEREADY) {
onUpdateReady();
}
/* ************************************************ */
/* autosave loop */
var autosaveTimeout = false;

View file

@ -57,7 +57,7 @@ img { border: 0; }
clear: both;
}
.btn {
.toolbar .btn {
height: 38px;
-webkit-border-radius: 999px;
-moz-border-radius: 999px;
@ -69,115 +69,10 @@ img { border: 0; }
text-decoration: none;
text-align: center;
border: 1px #93dee5 solid;
color: #72c1c8;
color: #60b1b8;
vertical-align: middle;
cursor: pointer;
}
.btn:hover {
border-color: #61a7ae;
color: #51a1a8;
}
.btn.btn-medium {
height: 30px;
padding: 0 16px;
font-size: 13px;
}
.btn.btn-small {
height: 26px;
padding: 0 16px;
font-size: 13px;
-webkit-border-radius: 10px;
-moz-border-radius: 10px;
border-radius: 10px;
}
input.form-field-small {
height: 24px;
margin-top: 1px;
font-size: 13px;
color: #51a1a8;
padding: 0 10px;
-webkit-border-radius: 10px;
-moz-border-radius: 10px;
border-radius: 10px;
border: 1px #93dee5 solid;
}
.publish-dropdown {
position: absolute;
top: 62px;
right: 110px;
z-index: 1001;
background: white;
width: 280px;
min-height: 60px;
font-family: sans-serif;
font-size: 14px;
line-height: 18px;
border: 1px solid #dbdbdb;
-webkit-border-radius: 6px;
-moz-border-radius: 6px;
border-radius: 6px;
box-shadow: 0 0 9px rgba(0,0,0,0.07);
}
.publish-dropdown .arrow {
clip: rect(0 14px 14px -4px);
transform: rotate(45deg);
margin-top: -7px;
position: absolute;
right: 20px;
}
.publish-dropdown .arrow::after {
content: '';
height: 16px;
width: 16px;
background: white;
display: block;
border: #dbdbdb 1px solid;
}
.publish-dropdown .dropdown-content {
padding: 9px;
}
.publish-dropdown input {
font-family: sans-serif;
}
.publish-dropdown .helptext {
padding: 8px 4px 12px 4px;
color: #333;
}
pre#publish-error-debug {
overflow: scroll;
font-size: 11px;
line-height: 12px;
}
.hidden {
display: none;
}
/* ************************************** */
/* App Cache */
#new_version_available {
display: none;
position: fixed;
z-index: 1000;
bottom: 0;
left: 0;
right: 0;
background: rgba(246,206,217,0.3);
}
#new_version_available .inner {
padding: 10px;
width: 600px;
margin: 0 auto;
text-align: center;
font-weight: bold;
color: #cf224f;
font-size: 14px;
font-family: sans-serif;
}
/* ************************************** */
/* Editor CSS */
@ -213,10 +108,6 @@ body, input {
min-height: 300px;
}
.medium-editor-insert-plugin .medium-insert-buttons {
color: #bbb;
}
/* editor's h1 is actually h3 */
h3 {
font-weight: bold;

View file

@ -1,5 +1,5 @@
<!doctype html>
<html lang="en" manifest="appcache.manifest">
<html lang="en" manifest_="appcache.manifest">
<head>
<title>Quill Editor</title>
<meta charset="utf-8">
@ -15,12 +15,12 @@
we want to exclude it for iPhone 5 to allow full screen apps -->
<meta name="viewport" content="initial-scale=1.0,user-scalable=no,maximum-scale=1" media="(device-height: 568px)" />
<link rel="stylesheet" href="/editor/style.css">
<link rel="stylesheet" href="/editor/medium-editor/css/medium-editor.min.css">
<link rel="stylesheet" href="/editor/medium-editor/css/themes/default.min.css">
<link rel="stylesheet" href="/editor/medium-editor/css/medium-editor-insert-plugin.min.css">
<link rel="stylesheet" href="/editor/medium-editor/css/medium-editor-insert-plugin-frontend.min.css">
<link href="/editor/font-awesome/css/font-awesome.css" rel="stylesheet">
<link rel="stylesheet" href="/editor/style.css">
<script src="/editor/jquery-1.11.3.min.js"></script>
<script src="/editor/jquery-ui-1.11.4.custom/jquery-ui.min.js"></script>
@ -47,55 +47,15 @@
<span class="item text"><span id="draft-status">Draft</span></span>
</div>
<div class="toolbar-right">
<button class="btn" id="publish_btn">Publish <i class="fa fa-caret-down"></i></button>
<button class="btn" id="publish_btn">Publish</button>
<button class="btn" id="new_btn">New</button>
</div>
<div class="clear"></div>
</div>
<div class="publish-dropdown hidden">
<div class="arrow"></div>
<div class="dropdown-content action-publish">
<div style="float:right"><button class="btn btn-medium" id="publish-confirm">Publish Now</button></div>
<div style="clear:right;"></div>
<div class="helptext" id="publish-help">
<div>Clicking "Publish Now" will send a request to your Micropub endpoint.</div><br>
<div>The request will include two fields, "name" and "content", where the content will be the full HTML for this post.</div>
</div>
<div class="helptext hidden" id="publish-in-progress">
Posting... <!-- TODO replace this with a CSS animated spinner -->
</div>
<div class="helptext hidden" id="publish-success">
<div>It worked! The post is on your site!</div><br>
<div><a href="" id="publish-success-url">View your post</a></div>
</div>
<div class="helptext hidden" id="publish-error">
<div>Something went wrong! Below is the response from your Micropub endpoint.</div><br>
<pre id="publish-error-debug"></pre>
</div>
</div>
<div class="dropdown-content action-signin hidden">
<div class="helptext">You need to sign in before you can publish! Don't worry, your draft will still be here when you finish signing in.</div>
<input type="url" class="form-field-small" placeholder="yourdomain.com" id="signin-domain">
<button class="btn btn-small" id="signin-btn">Sign In</button>
</div>
</div>
<div class="container">
<input id="post-name" type="text" value="" placeholder="Title">
<div id="content" class="editable"></div>
</div>
<div id="new_version_available">
<div class="inner">
There is a new version available! Refresh to load the new version.
</div>
<div id="content" class="editable"><p class="placeholder">Write something nice...</p></div>
</div>
<script src="/editor/editor.js"></script>

View file

@ -62,8 +62,7 @@ if(property_exists($this, 'include_facebook')) {
<ul class="nav navbar-nav">
<? if(session('me')) { ?>
<li><a href="/editor">Editor</a></li>
<li><a href="/new">New Note</a></li>
<li><a href="/new">New Post</a></li>
<li><a href="/bookmark">Bookmark</a></li>
<li><a href="/favorite">Favorite</a></li>
<? } ?>

View file

@ -1,61 +0,0 @@
<div class="narrow">
<?= partial('partials/header') ?>
<div style="clear: both;">
<div class="alert alert-success hidden" id="test_success"><strong>Success! We found a Location header in the response!</strong><br>Your post should be on your website now!<br><a href="" id="post_href">View your post</a></div>
<div class="alert alert-danger hidden" id="test_error"><strong>Your endpoint did not return a Location header.</strong><br>See <a href="/creating-a-micropub-endpoint">Creating a Micropub Endpoint</a> for more information.</div>
</div>
<form role="form" style="margin-top: 20px;" id="note_form">
<div class="form-group">
<label for="note_url">URL to Repost (<code>repost-of</code>)</label>
<input type="text" id="note_url" value="<?= $this->url ?>" class="form-control">
</div>
<div style="float: right; margin-top: 6px;">
<button class="btn btn-success" id="btn_post">Post</button>
</div>
</form>
<div style="clear: both;"></div>
</div>
<script>
$(function(){
// ctrl-s to save
$(window).on('keydown', function(e){
if(e.keyCode == 83 && e.ctrlKey){
$("#btn_post").click();
}
});
$("#btn_post").click(function(){
$.post("/repost", {
url: $("#note_url").val()
}, function(data){
var response = JSON.parse(data);
if(response.location != false) {
$("#test_success").removeClass('hidden');
$("#test_error").addClass('hidden');
$("#post_href").attr("href", response.location);
window.location = response.location;
} else {
$("#test_success").addClass('hidden');
$("#test_error").removeClass('hidden');
}
});
return false;
});
});
</script>

View file

@ -1,6 +1,6 @@
CACHE MANIFEST
# v18
# v3
/editor
/editor/style.css
@ -18,10 +18,6 @@ CACHE MANIFEST
/editor/medium-editor/js/medium-editor-insert-plugin.min.js
/editor/localforage/localforage.js
/editor/quill-logo-36.png
# /editor/editor.js
/editor/font-awesome/fonts/fontawesome-webfont.woff2?v=4.3.0
/editor/font-awesome/fonts/fontawesome-webfont.woff?v=4.3.0
/editor/font-awesome/fonts/fontawesome-webfont.ttf?v=4.3.0
NETWORK:
*