summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAaron Parecki <aaron@parecki.com>2016-12-19 10:39:23 -0800
committerAaron Parecki <aaron@parecki.com>2016-12-19 10:39:23 -0800
commit4aa06023f0c25a10d5eaeafaeb30034e0a4f2e95 (patch)
treee4a694fad5254166d01934aed9f344fc2903a2df
parent53964f2622828bc5b67546dbc24bb455e4d165cb (diff)
clean up note UI, show reply context
* shows reply context of the URL you're replying to * autocomplete nicknames from the post when replying * moved debug info to the settings screen to clean up the UI
-rw-r--r--composer.json5
-rw-r--r--composer.lock160
-rw-r--r--controllers/auth.php20
-rw-r--r--controllers/controllers.php71
-rw-r--r--lib/helpers.php43
-rw-r--r--public/css/style.css29
-rw-r--r--views/new-post.php164
-rw-r--r--views/settings.php28
8 files changed, 397 insertions, 123 deletions
diff --git a/composer.json b/composer.json
index 1a61c65..fc6ad33 100644
--- a/composer.json
+++ b/composer.json
@@ -9,9 +9,10 @@
"indieauth/client": ">=0.1.11",
"mpratt/relativetime": ">=1.0",
"firebase/php-jwt": "2.*",
- "ruudk/twitter-oauth": "dev-master",
+ "abraham/twitteroauth": "*",
"andreyco/instagram": "3.*",
- "p3k/multipart": "*"
+ "p3k/multipart": "*",
+ "tantek/cassis": "*"
},
"autoload": {
"files": [
diff --git a/composer.lock b/composer.lock
index fef94a8..169e3ff 100644
--- a/composer.lock
+++ b/composer.lock
@@ -4,20 +4,75 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file",
"This file is @generated automatically"
],
- "hash": "66741248756ed56d19ea2afd34809fe2",
+ "hash": "4756e7ef0035b8f768f07d252adbdc17",
+ "content-hash": "f4709cc6bd166e3759fbedbfbaa7752e",
"packages": [
{
+ "name": "abraham/twitteroauth",
+ "version": "0.7.2",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/abraham/twitteroauth.git",
+ "reference": "119d5a83478a2d21c09cd27980ab67eba11c8fe1"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/abraham/twitteroauth/zipball/119d5a83478a2d21c09cd27980ab67eba11c8fe1",
+ "reference": "119d5a83478a2d21c09cd27980ab67eba11c8fe1",
+ "shasum": ""
+ },
+ "require": {
+ "ext-curl": "*",
+ "php": "^5.6 || ^7.0"
+ },
+ "require-dev": {
+ "phpmd/phpmd": "~2.4",
+ "phpunit/phpunit": "~5.6",
+ "squizlabs/php_codesniffer": "~2.7"
+ },
+ "type": "library",
+ "autoload": {
+ "psr-4": {
+ "Abraham\\TwitterOAuth\\": "src"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Abraham Williams",
+ "email": "abraham@abrah.am",
+ "homepage": "https://abrah.am",
+ "role": "Developer"
+ }
+ ],
+ "description": "The most popular PHP library for use with the Twitter OAuth REST API.",
+ "homepage": "https://twitteroauth.com",
+ "keywords": [
+ "Twitter API",
+ "Twitter oAuth",
+ "api",
+ "oauth",
+ "rest",
+ "social",
+ "twitter"
+ ],
+ "time": "2016-12-12 17:42:13"
+ },
+ {
"name": "andreyco/instagram",
- "version": "v3.2",
+ "version": "3.4.0",
"source": {
"type": "git",
"url": "https://github.com/Andreyco/Instagram-for-PHP.git",
- "reference": "726e724c51301410873d9bae9c659a0597ca47e4"
+ "reference": "8c1b98f601a68142095461c0b8a9498375145e0d"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/Andreyco/Instagram-for-PHP/zipball/726e724c51301410873d9bae9c659a0597ca47e4",
- "reference": "726e724c51301410873d9bae9c659a0597ca47e4",
+ "url": "https://api.github.com/repos/Andreyco/Instagram-for-PHP/zipball/8c1b98f601a68142095461c0b8a9498375145e0d",
+ "reference": "8c1b98f601a68142095461c0b8a9498375145e0d",
"shasum": ""
},
"require": {
@@ -42,12 +97,12 @@
}
],
"description": "An easy-to-use PHP Class for accessing Instagram's API.",
- "homepage": "https://github.com/Andreyco/Instagram",
+ "homepage": "https://github.com/Andreyco/Instagram-for-PHP",
"keywords": [
"api",
"instagram"
],
- "time": "2014-07-14 19:53:19"
+ "time": "2016-07-17 23:42:10"
},
{
"name": "barnabywalters/mf-cleaner",
@@ -135,16 +190,16 @@
},
{
"name": "indieauth/client",
- "version": "0.1.11",
+ "version": "0.1.13",
"source": {
"type": "git",
"url": "https://github.com/indieweb/indieauth-client-php.git",
- "reference": "6504ed0d4714084e9955f639d6e5cf4e976f9038"
+ "reference": "d438bb03db15b4ccc6c63228be16de7870b6ab99"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/indieweb/indieauth-client-php/zipball/6504ed0d4714084e9955f639d6e5cf4e976f9038",
- "reference": "6504ed0d4714084e9955f639d6e5cf4e976f9038",
+ "url": "https://api.github.com/repos/indieweb/indieauth-client-php/zipball/d438bb03db15b4ccc6c63228be16de7870b6ab99",
+ "reference": "d438bb03db15b4ccc6c63228be16de7870b6ab99",
"shasum": ""
},
"require": {
@@ -170,20 +225,20 @@
}
],
"description": "IndieAuth Client Library",
- "time": "2015-08-30 22:29:40"
+ "time": "2016-02-08 23:56:31"
},
{
"name": "indieweb/date-formatter",
- "version": "0.1.5",
+ "version": "0.1.6",
"source": {
"type": "git",
"url": "https://github.com/indieweb/date-formatter-php.git",
- "reference": "f0dc028ba53da4da2718d2a263300396b1c14203"
+ "reference": "9c12e0fda95f4b3119fcaf271d141305870c4350"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/indieweb/date-formatter-php/zipball/f0dc028ba53da4da2718d2a263300396b1c14203",
- "reference": "f0dc028ba53da4da2718d2a263300396b1c14203",
+ "url": "https://api.github.com/repos/indieweb/date-formatter-php/zipball/9c12e0fda95f4b3119fcaf271d141305870c4350",
+ "reference": "9c12e0fda95f4b3119fcaf271d141305870c4350",
"shasum": ""
},
"require": {
@@ -213,7 +268,7 @@
"microformats",
"microformats2"
],
- "time": "2013-10-27 23:46:11"
+ "time": "2015-10-28 00:32:39"
},
{
"name": "indieweb/link-rel-parser",
@@ -413,16 +468,16 @@
},
{
"name": "mpratt/relativetime",
- "version": "1.5.1",
+ "version": "1.5.4",
"source": {
"type": "git",
"url": "https://github.com/mpratt/RelativeTime.git",
- "reference": "219e6568fa3e7b181244f93be493fbab4c89c056"
+ "reference": "3dc1efd96c8edbd0fe9e5cdb423ca31428b9dbb7"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/mpratt/RelativeTime/zipball/219e6568fa3e7b181244f93be493fbab4c89c056",
- "reference": "219e6568fa3e7b181244f93be493fbab4c89c056",
+ "url": "https://api.github.com/repos/mpratt/RelativeTime/zipball/3dc1efd96c8edbd0fe9e5cdb423ca31428b9dbb7",
+ "reference": "3dc1efd96c8edbd0fe9e5cdb423ca31428b9dbb7",
"shasum": ""
},
"require": {
@@ -457,7 +512,7 @@
"time",
"time-ago"
],
- "time": "2015-05-28 14:13:23"
+ "time": "2015-12-24 12:43:04"
},
{
"name": "p3k/multipart",
@@ -496,41 +551,6 @@
"time": "2015-07-16 19:28:02"
},
{
- "name": "ruudk/twitter-oauth",
- "version": "dev-master",
- "source": {
- "type": "git",
- "url": "https://github.com/ruudk/twitteroauth.git",
- "reference": "7f5a94eaa1572ddbc7f0a32ba3b865b8ac23712a"
- },
- "dist": {
- "type": "zip",
- "url": "https://api.github.com/repos/ruudk/twitteroauth/zipball/7f5a94eaa1572ddbc7f0a32ba3b865b8ac23712a",
- "reference": "7f5a94eaa1572ddbc7f0a32ba3b865b8ac23712a",
- "shasum": ""
- },
- "require": {
- "php": ">=5.3.0"
- },
- "type": "library",
- "autoload": {
- "classmap": [
- "src"
- ]
- },
- "notification-url": "https://packagist.org/downloads/",
- "authors": [
- {
- "name": "Ruud Kamphuis",
- "email": "ruud@1plus1media.nl",
- "role": "Developer"
- }
- ],
- "description": "PHP 5.3 version of abraham/twitteroauth",
- "homepage": "http://github.com/ruudk/twitteroauth",
- "time": "2014-06-10 18:17:38"
- },
- {
"name": "saltybeagle/savant3",
"version": "dev-master",
"source": {
@@ -607,14 +627,36 @@
"router"
],
"time": "2012-12-13 02:15:50"
+ },
+ {
+ "name": "tantek/cassis",
+ "version": "v0.2.16895",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/tantek/cassis.git",
+ "reference": "357e30ad12017b4d67cac5f4400e8f371cd2f504"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/tantek/cassis/zipball/357e30ad12017b4d67cac5f4400e8f371cd2f504",
+ "reference": "357e30ad12017b4d67cac5f4400e8f371cd2f504",
+ "shasum": ""
+ },
+ "type": "library",
+ "autoload": {
+ "files": [
+ "cassis.php"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "time": "2016-04-04 15:31:04"
}
],
"packages-dev": [],
"aliases": [],
"minimum-stability": "stable",
"stability-flags": {
- "saltybeagle/savant3": 20,
- "ruudk/twitter-oauth": 20
+ "saltybeagle/savant3": 20
},
"prefer-stable": false,
"prefer-lowest": false,
diff --git a/controllers/auth.php b/controllers/auth.php
index fb8b6da..baf5c2f 100644
--- a/controllers/auth.php
+++ b/controllers/auth.php
@@ -1,4 +1,5 @@
<?php
+use Abraham\TwitterOAuth\TwitterOAuth;
function buildRedirectURI() {
return Config::$base_url . 'auth/callback';
@@ -260,9 +261,11 @@ $app->post('/auth/twitter', function() use($app) {
});
function getTwitterLoginURL(&$twitter) {
- $request_token = $twitter->getRequestToken(Config::$base_url . 'auth/twitter/callback');
+ $request_token = $twitter->oauth('oauth/request_token', [
+ 'oauth_callback' => Config::$base_url . 'auth/twitter/callback'
+ ]);
$_SESSION['twitter_auth'] = $request_token;
- return $twitter->getAuthorizeURL($request_token['oauth_token']);
+ return $twitter->url('oauth/authorize', ['oauth_token' => $request_token['oauth_token']]);
}
$app->get('/auth/twitter', function() use($app) {
@@ -272,15 +275,16 @@ $app->get('/auth/twitter', function() use($app) {
// If there is an existing Twitter token, check if it is valid
// Otherwise, generate a Twitter login link
$twitter_login_url = false;
- $twitter = new \TwitterOAuth\Api(Config::$twitterClientID, Config::$twitterClientSecret,
- $user->twitter_access_token, $user->twitter_token_secret);
if(array_key_exists('login', $params)) {
- $twitter = new \TwitterOAuth\Api(Config::$twitterClientID, Config::$twitterClientSecret);
+ $twitter = new TwitterOAuth(Config::$twitterClientID, Config::$twitterClientSecret);
$twitter_login_url = getTwitterLoginURL($twitter);
} else {
+ $twitter = new TwitterOAuth(Config::$twitterClientID, Config::$twitterClientSecret,
+ $user->twitter_access_token, $user->twitter_token_secret);
+
if($user->twitter_access_token) {
- if ($twitter->get('account/verify_credentials')) {
+ if($twitter->get('account/verify_credentials')) {
$app->response()['Content-type'] = 'application/json';
$app->response()->body(json_encode(array(
'result' => 'ok'
@@ -312,9 +316,9 @@ $app->get('/auth/twitter/callback', function() use($app) {
if($user=require_login($app)) {
$params = $app->request()->params();
- $twitter = new \TwitterOAuth\Api(Config::$twitterClientID, Config::$twitterClientSecret,
+ $twitter = new TwitterOAuth(Config::$twitterClientID, Config::$twitterClientSecret,
$_SESSION['twitter_auth']['oauth_token'], $_SESSION['twitter_auth']['oauth_token_secret']);
- $credentials = $twitter->getAccessToken($params['oauth_verifier']);
+ $credentials = $twitter->oauth('oauth/access_token', ['oauth_verifier' => $params['oauth_verifier']]);
$user->twitter_access_token = $credentials['oauth_token'];
$user->twitter_token_secret = $credentials['oauth_token_secret'];
diff --git a/controllers/controllers.php b/controllers/controllers.php
index 09133cf..a9bc0ab 100644
--- a/controllers/controllers.php
+++ b/controllers/controllers.php
@@ -1,4 +1,5 @@
<?php
+use Abraham\TwitterOAuth\TwitterOAuth;
function require_login(&$app, $redirect=true) {
$params = $app->request()->params();
@@ -336,7 +337,7 @@ function create_favorite(&$user, $url) {
// POSSE favorites to Twitter
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,
+ $twitter = new TwitterOAuth(Config::$twitterClientID, Config::$twitterClientSecret,
$user->twitter_access_token, $user->twitter_token_secret);
$result = $twitter->post('favorites/create', array(
'id' => $tweet_id
@@ -356,7 +357,7 @@ function create_repost(&$user, $url) {
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,
+ $twitter = new TwitterOAuth(Config::$twitterClientID, Config::$twitterClientSecret,
$user->twitter_access_token, $user->twitter_token_secret);
$result = $twitter->post('statuses/retweet/'.$tweet_id);
}
@@ -392,6 +393,72 @@ $app->post('/repost', function() use($app) {
}
});
+$app->get('/reply/preview', function() use($app) {
+ if($user=require_login($app)) {
+ $params = $app->request()->params();
+
+ $reply_url = trim($params['url']);
+
+ if(preg_match('/twtr\.io\/([0-9a-z]+)/i', $reply_url, $match)) {
+ $twtr = 'https://twitter.com/_/status/' . sxg_to_num($match[1]);
+ $ch = curl_init($twtr);
+ curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
+ curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
+ curl_exec($ch);
+ $expanded_url = curl_getinfo($ch, CURLINFO_EFFECTIVE_URL);
+ if($expanded_url) $reply_url = $expanded_url;
+ }
+
+ $entry = false;
+ // Convert Tweets to h-entry
+ if(preg_match('/twitter\.com\/(?:[^\/]+)\/statuse?s?\/(.+)/', $reply_url, $match)) {
+ $tweet_id = $match[1];
+ if($user->twitter_access_token) {
+ $twitter = new TwitterOAuth(Config::$twitterClientID, Config::$twitterClientSecret,
+ $user->twitter_access_token, $user->twitter_token_secret);
+ } else {
+ $twitter = new TwitterOAuth(Config::$twitterClientID, Config::$twitterClientSecret);
+ }
+ $tweet = $twitter->get('statuses/show/'.$tweet_id);
+ $entry = tweet_to_h_entry($tweet);
+ } else {
+ // Pass to X-Ray to see if it can expand the entry
+ $ch = curl_init('https://xray.p3k.io/parse?url='.urlencode($reply_url));
+ curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
+ $response = curl_exec($ch);
+ $data = @json_decode($response, true);
+ if($data && $data['data']['type'] == 'entry') {
+ $entry = $data['data'];
+ // Create a nickname based on the author URL
+ if($entry['author']['url']) {
+ $entry['author']['nickname'] = display_url($entry['author']['url']);
+ }
+ }
+ }
+
+ $mentions = [];
+ if($entry) {
+ // Find all @-names in the post, as well as the author name
+ $mentions[] = $entry['author']['nickname'];
+
+ if(preg_match_all('/(^|(?<=[\s\/]))@([a-z0-9_]+([a-z0-9_\.]*)?)/i', $entry['content']['text'], $matches)) {
+ foreach($matches[0] as $nick) {
+ if(trim($nick,'@') != $user->twitter_username && trim($nick,'@') != display_url($user->url))
+ $mentions[] = trim($nick,'@');
+ }
+ }
+
+ }
+
+ $app->response()['Content-type'] = 'application/json';
+ $app->response()->body(json_encode([
+ 'canonical_reply_url' => $reply_url,
+ 'entry' => $entry,
+ 'mentions' => $mentions
+ ]));
+ }
+});
+
$app->get('/micropub/syndications', function() use($app) {
if($user=require_login($app)) {
$data = get_micropub_config($user, ['q'=>'syndicate-to']);
diff --git a/lib/helpers.php b/lib/helpers.php
index 3a71d90..8948f92 100644
--- a/lib/helpers.php
+++ b/lib/helpers.php
@@ -396,3 +396,46 @@ function correct_photo_rotation($filename) {
}
}
+function tweet_to_h_entry($tweet) {
+ // Converts to XRay's h-entry format
+
+ $entry = [
+ 'type' => 'entry',
+ 'url' => 'https://twitter.com/'.$tweet->user->screen_name.'/status/'.$tweet->id_str,
+ ];
+
+ $published = strtotime($tweet->created_at);
+ $entry['published'] = date('c', $published);
+
+ $entry['content'] = [
+ 'text' => $tweet->text
+ ];
+
+ if($tweet->entities->urls) {
+ foreach($tweet->entities->urls as $url) {
+ $entry['content']['text'] = str_replace($url->url, $url->expanded_url, $entry['content']['text']);
+ }
+ }
+
+ $entry['author'] = [
+ 'type' => 'card',
+ 'url' => 'https://twitter.com/'.$tweet->user->screen_name,
+ 'name' => $tweet->user->name,
+ 'nickname' => $tweet->user->screen_name,
+ 'photo' => $tweet->user->profile_image_url_https
+ ];
+
+ if($tweet->user->url) {
+ $entry['author']['url'] = $tweet->user->entities->url->urls[0]->expanded_url;
+ }
+
+ if($tweet->entities->hashtags) {
+ $entry['category'] = [];
+ foreach($tweet->entities->hashtags as $tag) {
+ $entry['category'][] = $tag->text;
+ }
+ }
+
+ return $entry;
+}
+
diff --git a/public/css/style.css b/public/css/style.css
index 5e6556c..7984fe5 100644
--- a/public/css/style.css
+++ b/public/css/style.css
@@ -200,4 +200,31 @@ body {
.notice-pad {
margin-top: 20px;
- } \ No newline at end of file
+ }
+
+
+
+.glyphicon-spin {
+ -webkit-animation: spin 1000ms infinite linear;
+ animation: spin 1000ms infinite linear;
+}
+@-webkit-keyframes spin {
+ 0% {
+ -webkit-transform: rotate(0deg);
+ transform: rotate(0deg);
+ }
+ 100% {
+ -webkit-transform: rotate(359deg);
+ transform: rotate(359deg);
+ }
+}
+@keyframes spin {
+ 0% {
+ -webkit-transform: rotate(0deg);
+ transform: rotate(0deg);
+ }
+ 100% {
+ -webkit-transform: rotate(359deg);
+ transform: rotate(359deg);
+ }
+}
diff --git a/views/new-post.php b/views/new-post.php
index 21571ec..68460d0 100644
--- a/views/new-post.php
+++ b/views/new-post.php
@@ -3,29 +3,45 @@
<form role="form" style="margin-top: 20px;" id="note_form">
- <div class="form-group">
- <div id="note_content_remaining" class="pcheck206"><img src="/images/twitter.ico"> <span>140</span></div>
- <label for="note_content"><code>content</code></label>
- <textarea id="note_content" value="" class="form-control" style="height: 4em;"></textarea>
+ <div id="reply">
+ <div class="reply-section hidden">
+ <div class="form-group has-feedback">
+ <label for="note_in_reply_to">Reply To (a URL you are replying to)</label>
+ <input type="text" id="note_in_reply_to" value="<?= $this->in_reply_to ?>" class="form-control">
+ <span class="loading hidden glyphicon glyphicon-refresh glyphicon-spin form-control-feedback"></span>
+ </div>
+ <div class="reply-context hidden">
+ <div>
+ <img src="" width="48" class="author-img">
+ </div>
+ <div>
+ <img src="" class="post-img hidden">
+ <div class="author"><span class="name"></span> <span class="url"></span></div>
+ <span class="content"></span>
+ </div>
+ </div>
+ </div>
+ <a href="" id="expand-reply" class="btn btn-xs btn-info">Reply</a>
</div>
<div class="form-group">
- <label for="note_in_reply_to"><code>in-reply-to</code> (a URL you are replying to)</label>
- <input type="text" id="note_in_reply_to" value="<?= $this->in_reply_to ?>" class="form-control">
+ <div id="note_content_remaining" class="pcheck206"><img src="/images/twitter.ico"> <span>140</span></div>
+ <label for="note_content">Content</label>
+ <textarea id="note_content" value="" class="form-control" style="height: 4em;"></textarea>
</div>
- <div class="form-group">
- <label for="note_category"><code>category</code> (comma-separated list of tags, will be posted as an array)</label>
+ <div class="form-group" id="form_tags">
+ <label for="note_category">Tags (comma-separated list)</label>
<input type="text" id="note_category" value="" class="form-control" placeholder="e.g. web, personal">
</div>
- <div class="form-group">
- <label for="note_slug"><code>slug</code></label>
+ <div class="form-group" id="form_slug">
+ <label for="note_slug">Slug</label>
<input type="text" id="note_slug" value="" class="form-control">
</div>
<div class="form-group">
- <label for="note_photo"><code>photo</code></label>
+ <label for="note_photo">Photo</label>
<input type="file" name="note_photo" id="note_photo" accept="image/*">
<a href="javascript:switchToManualPhotoURL();" id="note_manual_photo">enter photo url</a>
<a href="javascript:addPhotoURL();" class="hidden" id="add_photo">add photo</a>
@@ -39,7 +55,7 @@
</div>
<div class="form-group">
- <label for="note_syndicate-to"><code>syndicate-to</code> <a href="javascript:reload_syndications()">(refresh)</a></label>
+ <label for="note_syndicate-to">Syndicate <a href="javascript:reload_syndications()">(refresh list)</a></label>
<div id="syndication-container">
<?php
if($this->syndication_targets) {
@@ -62,7 +78,7 @@
</div>
<div class="form-group">
- <label for="note_location"><code>location</code></label>
+ <label for="note_location">Location</label>
<input type="checkbox" id="note_location_chk" value="">
<img src="/images/spinner.gif" id="note_location_loading" style="display: none;">
@@ -93,36 +109,6 @@
<?php endif; ?>
<pre id="test_response" class="<?= $this->test_response ? '' : 'hidden' ?>" style="width: 100%; min-height: 240px;"><?= htmlspecialchars($this->test_response) ?></pre>
-
- <div class="callout">
- <p>Clicking "Post" will post this note to your Micropub endpoint. Below is some information about the request that will be made.</p>
-
- <table class="table table-condensed">
- <tr>
- <td>me</td>
- <td><code><?= session('me') ?></code> (should be your URL)</td>
- </tr>
- <tr>
- <td>scope</td>
- <td><code><?= $this->micropub_scope ?></code> (should be a space-separated list of permissions including "post")</td>
- </tr>
- <tr>
- <td>micropub endpoint</td>
- <td><code><?= $this->micropub_endpoint ?></code> (should be a URL)</td>
- </tr>
- <?php if($this->media_endpoint): ?>
- <tr>
- <td>media endpoint</td>
- <td><code><?= $this->media_endpoint ?></code> (should be a URL)</td>
- </tr>
- <?php endif; ?>
- <tr>
- <td>access token</td>
- <td>String of length <b><?= strlen($this->micropub_access_token) ?></b><?= (strlen($this->micropub_access_token) > 0) ? (', ending in <code>' . substr($this->micropub_access_token, -7) . '</code>') : '' ?> (should be greater than length 0)</td>
- </tr>
- </table>
- </div>
-
<hr>
<div style="text-align: right;">
<a href="/add-to-home?start">Add to Home Screen</a>
@@ -131,6 +117,10 @@
<style type="text/css">
+#reply {
+ margin-bottom: 1em;
+}
+
#note_content_remaining {
float: right;
font-size: 0.8em;
@@ -142,6 +132,33 @@
.pcheck200,.pcheck208 { color: #59cb3a; } /* exactly fits 140 chars, both with or without RT */
.pcheck413 { color: #a73b3b; } /* over max tweet length */
+.reply-context {
+ display: flex;
+ flex-direction: row;
+ padding: 4px;
+ margin: 0 3em;
+ border: 1px #ccc solid;
+ border-radius: 4px;
+ background: #f4f4f4;
+}
+.reply-context img.author-img {
+ border-radius: 4px;
+ width: 48px;
+ margin-right: 4px;
+}
+.reply-context .author {
+ color: #777;
+ font-weight: bold;
+ font-size: 0.9em;
+}
+.reply-context .author .url {
+ color: #aaa;
+}
+.reply-context img.post-img {
+ float: right;
+ width: 200px;
+}
+
</style>
<script>
@@ -170,7 +187,9 @@ function restoreNoteState() {
if(note.photo) {
replacePhotoWithPhotoURL(note.photo);
}
- console.log(note.syndications)
+ if(note.inReplyTo) {
+ expandReplySection();
+ }
$("#syndication-container button").each(function(i,btn){
if($(btn).data('syndicate-to') in note.syndications) {
$(btn).addClass('btn-info');
@@ -208,6 +227,11 @@ function addPhotoURL() {
}
}
+function expandReplySection() {
+ $("#expand-reply").click();
+ $("#note_in_reply_to").change();
+}
+
$(function(){
var userHasSetCategory = false;
@@ -218,6 +242,12 @@ $(function(){
saveNoteState();
})
+ $("#expand-reply").click(function(){
+ $('.reply-section').removeClass('hidden');
+ $(this).addClass('hidden');
+ return false;
+ });
+
// Preview the photo when one is chosen
$("#photo_preview_container").addClass("hidden");
$("#note_photo").on("change", function(e){
@@ -279,9 +309,43 @@ $(function(){
});
$("#note_in_reply_to").on('change', function(){
- if(match=$("#note_in_reply_to").val().match(/twitter\.com\/([^\/]+)\/status/)) {
- $("#note_content").val( "@"+match[1]+" "+$("#note_content").val() );
- }
+ var reply_to = $("#note_in_reply_to").val();
+ $(".reply-section .loading").removeClass("hidden");
+ $.get("/reply/preview", {url:reply_to}, function(data){
+
+ if(data.canonical_reply_url != reply_to) {
+ $("#note_in_reply_to").val(data.canonical_reply_url);
+ }
+ var category = csv_to_array($("#note_category").val());
+ for(var i in data.entry.category) {
+ if($.inArray(data.entry.category[i], category) == -1) {
+ category.push(data.entry.category[i]);
+ }
+ }
+ $("#note_category").val(category.join(", "));
+
+ if($("#note_content").val() == "" && data.mentions) {
+ var mentions = '';
+ for(var i in data.mentions) {
+ mentions += '@'+data.mentions[i]+' ';
+ }
+ console.log(mentions);
+ $("#note_content").val(mentions);
+ }
+
+ $(".reply-context .content").text(data.entry.content.text);
+ $(".reply-context .name").text(data.entry.author.name);
+ $(".reply-context .url").text(data.entry.author.url);
+ $(".reply-context img.author-img").attr('src', data.entry.author.photo);
+ if(data.entry.photo) {
+ $(".reply-context img.post-img").attr('src', data.entry.photo[0]).removeClass('hidden');
+ } else {
+ $(".reply-context img.post-img").addClass('hidden');
+ }
+
+ $(".reply-section .loading").addClass("hidden");
+ $(".reply-context").removeClass("hidden");
+ });
});
$("#note_category").on('keydown keyup', function(){
@@ -293,6 +357,12 @@ $(function(){
}
});
+ // When the reply URL is in the query string, or loads from localstorage, make sure
+ // to run the event handlers to expand the reply section
+ if($("#note_in_reply_to").val() != "") {
+ expandReplySection();
+ }
+
$("#btn_post").click(function(){
// Collect all the syndication buttons that are pressed
diff --git a/views/settings.php b/views/settings.php
index 46df0bf..5acc7dd 100644
--- a/views/settings.php
+++ b/views/settings.php
@@ -2,13 +2,33 @@
<?= partial('partials/header') ?>
<h2>Signed In As</h2>
- <code><?= session('me') ?></code>
- <h3>Access Token</h3>
- <input type="text" class="form-control" readonly="readonly" value="<?= $this->user->micropub_access_token ?>">
+ <table class="table table-condensed">
+ <tr>
+ <td>me</td>
+ <td><code><?= $this->user->url; ?></code> (should be your URL)</td>
+ </tr>
+ <tr>
+ <td>scope</td>
+ <td><code><?= $this->user->micropub_scope ?></code> (should be a space-separated list of permissions including "create")</td>
+ </tr>
+ <tr>
+ <td>micropub endpoint</td>
+ <td><code><?= $this->user->micropub_endpoint ?></code> (should be a URL)</td>
+ </tr>
+ <tr>
+ <td>media endpoint</td>
+ <td><?= $this->user->media_endpoint ? '<code>'.$this->user->media_endpoint.'</code>' : '<a href="https://www.w3.org/TR/micropub/#media-endpoint">no media endpoint</a>' ?></td>
+ </tr>
+ <tr>
+ <td width="140">access token</td>
+ <td><code style="word-break: break-word; white-space: pre-wrap;"><?= $this->user->micropub_access_token ?></code></td>
+ </tr>
+ </table>
+
<h3>Twitter</h3>
- <p>Connecting a Twitter account will automatically "favorite" tweets on Twitter when you favorite a Twitter URL in Quill.</p>
+ <p>Connecting a Twitter account will automatically "favorite" and "retweet" tweets on Twitter when you favorite and retweet a Twitter URL in Quill.</p>
<input type="button" id="twitter-button" value="Checking" class="btn">
</div>