From a7e266a5584e68c2ddec18fb90fac27639eae187 Mon Sep 17 00:00:00 2001 From: "Jocelyn Badgley (Twipped)" Date: Mon, 2 Mar 2020 20:27:00 -0800 Subject: [PATCH] Quoted tweets are now loaded recursively and displayed 2 layers deep --- build/lib/tweetparse.js | 20 ++++---------------- build/page-tweets.js | 32 ++++++++++++++++++++++---------- scss/_tweet.scss | 26 ++++++++++++++++++++------ templates/tweet.hbs | 27 ++++++++++++++++++++------- 4 files changed, 66 insertions(+), 39 deletions(-) diff --git a/build/lib/tweetparse.js b/build/lib/tweetparse.js index 051adbf..8c7d64b 100644 --- a/build/lib/tweetparse.js +++ b/build/lib/tweetparse.js @@ -12,15 +12,7 @@ const schema = { protected: true, }, html: true, - quoted_status: { - user: { - screen_name: true, - avatar: true, - name_html: true, - verified: true, - protected: true, - }, - }, + quoted_status_id_str: true, entities: { media: [ { type: true, media_url_https: true, @@ -51,13 +43,9 @@ var entityProcessors = { }, urls (urls, tweet) { - urls.forEach((urlObj) => { - var quotedTweetHtml = ''; - var indices = urlObj.indices; - var urlToReplace = (tweet.full_text || tweet.text).substring(indices[0], indices[1]); - - var finalText = quotedTweetHtml || urlObj.display_url.link(urlObj.expanded_url); - tweet.html = tweet.html.replace(urlToReplace, finalText); + urls.forEach(({ url, expanded_url, display_url }) => { + const className = (tweet.quoted_status_permalink && url === tweet.quoted_status_permalink.url) ? 'quoted-tweet' : 'url'; + tweet.html = tweet.html.replace(url, `${display_url}`); }); }, diff --git a/build/page-tweets.js b/build/page-tweets.js index a4b57a8..2524c67 100644 --- a/build/page-tweets.js +++ b/build/page-tweets.js @@ -28,17 +28,23 @@ module.exports = exports = async function tweets (pages) { /* Load Missing Tweets **************************************************/ - if (tweetsNeeded.length) { + while (tweetsNeeded.length) { log('Fetching tweets: ' + tweetsNeeded.join(', ')); const arriving = await Promise.all(chunk(tweetsNeeded, 99).map(twitter)); + const tweetsRequested = tweetsNeeded; + tweetsNeeded = []; const loaded = []; for (const tweet of arriving.flat(1)) { - if (!twitterBackup[tweet.id_str]) twitterBackup[tweet.id_str] = tweet; + if (tweet.quoted_status_id_str && !twitterCache[tweet.quoted_status_id_str]) { + tweetsNeeded.push(tweet.quoted_status_id_str); + } + // if (!twitterBackup[tweet.id_str]) twitterBackup[tweet.id_str] = tweet; + twitterBackup[tweet.id_str] = tweet; twitterCache[tweet.id_str] = tweetparse(tweet); loaded.push(tweet.id_str); } - const absent = difference(tweetsNeeded, loaded); + const absent = difference(tweetsRequested, loaded); for (const id of absent) { if (twitterBackup[id]) { log('Pulled tweet from backup ' + id); @@ -53,18 +59,24 @@ module.exports = exports = async function tweets (pages) { const twitterMedia = []; + function attachTweet (dict, tweetid) { + const tweet = twitterCache[tweetid]; + if (!tweet) { + log.error(`Tweet ${tweetid} is missing from the cache.`); + return; + } + dict[tweetid] = tweet; + twitterMedia.push( ...tweet.media ); + + if (tweet.quoted_status_id_str) attachTweet(dict, tweet.quoted_status_id_str); + } + // now loop through pages and substitute the tweet data for the ids for (const page of pages) { if (!page.tweets || !page.tweets.length) continue; page.tweets = page.tweets.reduce((dict, tweetid) => { - const tweet = twitterCache[tweetid]; - if (!tweet) { - log.error(`Tweet ${tweetid} is missing from the cache.`); - return dict; - } - dict[tweetid] = tweet; - twitterMedia.push( ...tweet.media ); + attachTweet(dict, tweetid); return dict; }, {}); } diff --git a/scss/_tweet.scss b/scss/_tweet.scss index be500b4..4c1d796 100644 --- a/scss/_tweet.scss +++ b/scss/_tweet.scss @@ -121,9 +121,10 @@ } } - .tweet-text { + .tweet-text, .tweet-quoted-text { line-height: 1.5em; p { margin-bottom: 0.5em; } + p:last-child { margin-bottom: 0; } a { color: $textHover; } } @@ -132,13 +133,21 @@ border: 1px solid $borderColor; border-radius: .35em; padding: 10px; - display: block; + display: inline-block; color: $textDark; - font-size: 14px; - margin-top: 10px; + font-size: 0.95em; + margin-top: 0.4em; + margin-bottom: 0.75em; + background: rgba(#ddd, 0.1); - &:hover { - border-color: $borderHover; + > a { + color: inherit; + display: block; + + &:hover { + color: $textHover; + text-decoration: none; + } } span { @@ -148,6 +157,10 @@ span, strong { line-height: 1; } + + p:last-child { + margin-bottom: 0; + } } .tweet-entities { @@ -157,6 +170,7 @@ overflow: hidden; max-width: 600px; max-height: 600px; + box-shadow: 0 0 3px rgba(#000, 0.3); .tweet-entities-inner { padding-bottom: 56.25%; diff --git a/templates/tweet.hbs b/templates/tweet.hbs index e0a4735..65090ba 100644 --- a/templates/tweet.hbs +++ b/templates/tweet.hbs @@ -12,17 +12,30 @@ @{{user.screen_name}} + {{#if quoted_status_id_str}}{{#with (lookup ../../tweets quoted_status_id_str)}} +
+ + {{{user.name_html}}} + @{{user.screen_name}} + + {{#if quoted_status_id_str}}{{#with (lookup ../../../tweets quoted_status_id_str)}} + + {{/with}}{{/if}} +
{{{html}}}
+
+ {{/with}}{{/if}}
{{{html}}}
- {{#if quoted_status}} - {{{quoted_status.user.name_html}}} - @{{quoted_status.user.screen_name}} -
{{{quoted_status.html}}}
-
{{/if}} {{#any extended_entities.media entities.media}} -
+