Mastodon improvements

This commit is contained in:
Simon Detheridge 2023-10-17 14:18:00 +01:00
parent 90e8a3b2a5
commit 54dd6d2a17
Signed by: simon
GPG Key ID: 38640971DA1E704E
8 changed files with 117 additions and 54 deletions

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -1954,7 +1954,11 @@ Search LOGO Login Subscribe
.gh-about .gh-button { .gh-about .gh-button {
margin-top: 32px; margin-top: 32px;
} }
.tootlink-tip {
font-size: 0.9em;
padding: 1em;
padding-top: 0.3em;
}
.mastodon-comment { .mastodon-comment {
background-color: var(--background-color); background-color: var(--background-color);
border-radius: var(--card-border-radius); border-radius: var(--card-border-radius);
@ -1980,7 +1984,7 @@ Search LOGO Login Subscribe
white-space: nowrap; white-space: nowrap;
.mastodon-author-uid { .mastodon-author-uid {
font-size: 80%; font-size: 80%;
color: var(--ghost-accent-color); color: var(--color-secondary-text);
} }
} }
.toot-link { .toot-link {
@ -1990,12 +1994,38 @@ Search LOGO Login Subscribe
} }
.mastodon-comment-content { .mastodon-comment-content {
padding-top: 10px; padding-top: 10px;
.tootlink {
font-size: 50%;
}
} }
.disabled { .disabled {
color: var(--ghost-accent-color) color: var(--color-secondary-text)
}
}
span.tootlink {
font-size: 0.7em;
font-family: monospace;
padding: 0.2em 0.4em;
cursor: pointer;
border: 1px solid var(--background-secondary)
}
a.date {
font-size: 0.9em;
color: var(--color-secondary-text)
}
span.tootlink::after {
content: "\f0c5";
font-family: "Font Awesome 6 Free";
font-weight: 900;
padding-left: 4px;
}
.tootClick {
animation: tootClickFrames .6s linear;
}
@keyframes tootClickFrames {
0% {
background-color: var(--background-secondary);
}
100% {
background-color: var(--background-color);
} }
} }
.mastodon-emoji { .mastodon-emoji {
@ -2006,6 +2036,10 @@ Search LOGO Login Subscribe
.mastodon-comment-content p:first-child { .mastodon-comment-content p:first-child {
margin-top: 0; margin-top: 0;
} }
#toot-link-top {
color: var(--ghost-accent-color);
text-decoration: underline;
}
/* 14. Post/page /* 14. Post/page

View File

@ -4,7 +4,7 @@ const MASTODON_HOST = 'social.sd.ai'
async function copyElementTextToClipboard(e) async function copyElementTextToClipboard(e)
{ {
const text = e.textContent const text = e.textContent
await navigator.clipboard.write(text) await navigator.clipboard.writeText(text)
e.classList.add('tootClick'); e.classList.add('tootClick');
setTimeout(() => { setTimeout(() => {
@ -21,14 +21,17 @@ function escapeHtml(unsafe) {
.replace(/'/g, "'"); .replace(/'/g, "'");
} }
function renderMastodonContent(toots, parentElement) { function renderMastodonContent(toots, parentElement, showLink) {
parentElement.innerHTML = ''
if (!Array.isArray(toots) || toots.length === 0) { if (!Array.isArray(toots) || toots.length === 0) {
document.getElementById('mastodon-comments-list').innerHTML = "<div class='mastodon-comment'>No comments (yet)!</div>" document.getElementById('mastodon-comments-list').innerHTML = "<div class='mastodon-comment'>No comments (yet)!</div>"
return return
} }
for (const toot of toots) { for (const toot of toots) {
if (toot.sensitive) {
continue
}
toot.account.display_name = escapeHtml(toot.account.display_name) toot.account.display_name = escapeHtml(toot.account.display_name)
console.log(toot)
toot.account.emojis.forEach(emoji => { toot.account.emojis.forEach(emoji => {
toot.account.display_name = toot.account.display_name.replace(`:${emoji.shortcode}:`, toot.account.display_name = toot.account.display_name.replace(`:${emoji.shortcode}:`,
`<img src="${escapeHtml(emoji.static_url)}" alt="Emoji ${emoji.shortcode}" class="mastodon-emoji" />`); `<img src="${escapeHtml(emoji.static_url)}" alt="Emoji ${emoji.shortcode}" class="mastodon-emoji" />`);
@ -54,7 +57,7 @@ function renderMastodonContent(toots, parentElement) {
</div> </div>
</div> </div>
<div class="toot-link"> <div class="toot-link">
<a class="date" href="${toot.uri}" rel="nofollow"> <a class="date" href="${toot.uri}" rel="nofollow" target="_blank">
${toot.created_at.substring(0, 10)} ${toot.created_at.substring(0, 10)}
</a> </a>
<br/> <br/>
@ -62,24 +65,52 @@ function renderMastodonContent(toots, parentElement) {
</div> </div>
<div class="mastodon-comment-content"> <div class="mastodon-comment-content">
${toot.content} ${toot.content}
<span class="tootlink">${toot.uri}</span> <span class="tootlink" ${showLink ? '' : 'style="display: none;"'}>${toot.uri}</span>
</div> </div>
</div> </div>
</div>` </div>`
const child = DOMPurify.sanitize(comment, {'RETURN_DOM_FRAGMENT': true}); const child = DOMPurify.sanitize(comment, {'RETURN_DOM_FRAGMENT': true});
const links = child.querySelectorAll('.tootlink'); const links = child.querySelectorAll('.tootlink');
for (const link of links) { for (const link of links) {
link.onclick = function() { return copyToClipboard(this); } link.onclick = function() { return copyElementTextToClipboard(this); }
} }
parentElement.appendChild(child); parentElement.appendChild(child);
} }
} }
let MASTODON_POST_ID
document.addEventListener("DOMContentLoaded", async (event) => { document.addEventListener("DOMContentLoaded", async (event) => {
let url, isComments
const isBot = /bot|google|baidu|bing|msn|teoma|slurp|yandex/i
.test(navigator.userAgent)
if (document.getElementsByClassName('gh-sidebar').length > 0) { if (document.getElementsByClassName('gh-sidebar').length > 0) {
const element = document.getElementById('mastodon-comments-list') url = `https://${MASTODON_HOST}/api/v1/accounts/${MASTODON_ACCOUNT_ID}/statuses?exclude_replies=true&exclude_reblogs=true`
const response = await fetch(`https://${MASTODON_HOST}/api/v1/accounts/${MASTODON_ACCOUNT_ID}/statuses?exclude_replies=true&exclude_reblogs=true`) }
const content = await response.json() if (MASTODON_POST_ID && !isBot) {
return renderMastodonContent(content, element) url = `https://${MASTODON_HOST}/api/v1/statuses/${MASTODON_POST_ID}/context`
isComments = true
}
const element = document.getElementById('mastodon-comments-list')
if (url && element) {
const linkElement = document.getElementById('toot-link-top')
const clipElement = document.getElementById('toot-link-clip')
const tootUrl = `https://${MASTODON_HOST}/@s/${MASTODON_POST_ID}`
if (linkElement) {
linkElement.href = tootUrl
}
if (clipElement) {
clipElement.innerText = tootUrl
}
const response = await fetch(url)
let content = await response.json()
if (isComments) {
content = content.descendants
}
const header = document.getElementById('mastodon-comments-header')
if (header) {
header.style.display = ''
}
return renderMastodonContent(content, element, isComments)
} }
}) })

View File

@ -6,7 +6,11 @@
<title>{{meta_title}}</title> <title>{{meta_title}}</title>
<meta charset="utf-8"> <meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.2.1/css/all.min.css" integrity="sha512-MV7K8+y+gLIBoVD59lQIYicR65iaqukzvf/nwasF0nqhPay5w/9lJmVM2hMDcnK1OnMGCdVK+iQrJ7lzPJQd1w==" crossorigin="anonymous" referrerpolicy="no-referrer" />
<link rel="preload" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.2.1/webfonts/fa-brands-400.woff2" as="font" type="font/woff2" crossorigin>
<link rel="preload" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.2.1/webfonts/fa-solid-900.woff2" as="font" type="font/woff2" crossorigin>
{{!-- Preload main styles and scripts for better performance --}} {{!-- Preload main styles and scripts for better performance --}}
<link rel="preload" as="style" href="{{asset "built/screen.css"}}"> <link rel="preload" as="style" href="{{asset "built/screen.css"}}">
<link rel="preload" as="script" href="{{asset "built/source.js"}}"> <link rel="preload" as="script" href="{{asset "built/source.js"}}">
@ -14,27 +18,6 @@
{{!-- Theme assets - use the {{asset}} helper to reference styles & scripts, this will take care of caching and cache-busting automatically --}} {{!-- Theme assets - use the {{asset}} helper to reference styles & scripts, this will take care of caching and cache-busting automatically --}}
<link rel="stylesheet" type="text/css" href="{{asset "built/screen.css"}}"> <link rel="stylesheet" type="text/css" href="{{asset "built/screen.css"}}">
{{!-- Custom background color --}}
<style>
:root {
--background-color: {{@custom.site_background_color}}
}
</style>
<script>
/* The script for calculating the color contrast has been taken from
https://gomakethings.com/dynamically-changing-the-text-color-based-on-background-color-contrast-with-vanilla-js/ */
var accentColor = getComputedStyle(document.documentElement).getPropertyValue('--background-color');
accentColor = accentColor.trim().slice(1);
var r = parseInt(accentColor.substr(0, 2), 16);
var g = parseInt(accentColor.substr(2, 2), 16);
var b = parseInt(accentColor.substr(4, 2), 16);
var yiq = ((r * 299) + (g * 587) + (b * 114)) / 1000;
var textColor = (yiq >= 128) ? 'dark' : 'light';
document.documentElement.className = `has-${textColor}-text`;
</script>
{{!-- This tag outputs all your advanced SEO meta, structured data, and other important settings, it should always be the last tag before the closing head tag --}} {{!-- This tag outputs all your advanced SEO meta, structured data, and other important settings, it should always be the last tag before the closing head tag --}}
{{ghost_head}} {{ghost_head}}
@ -42,13 +25,13 @@
<body class="{{body_class}} has-{{#match @custom.title_font "Elegant serif"}}serif{{else match @custom.title_font "Consistent mono"}}mono{{else}}sans{{/match}}-title has-{{#match @custom.body_font "Elegant serif"}}serif{{else}}sans{{/match}}-body"> <body class="{{body_class}} has-{{#match @custom.title_font "Elegant serif"}}serif{{else match @custom.title_font "Consistent mono"}}mono{{else}}sans{{/match}}-title has-{{#match @custom.body_font "Elegant serif"}}serif{{else}}sans{{/match}}-body">
<div class="gh-viewport"> <div class="gh-viewport">
{{> "components/navigation" navigationLayout=@custom.navigation_layout}} {{> "components/navigation" navigationLayout=@custom.navigation_layout}}
{{{body}}} {{{body}}}
{{> "components/footer"}} {{> "components/footer"}}
</div> </div>
{{#is "post, page"}} {{#is "post, page"}}

View File

@ -50,6 +50,21 @@
</article> </article>
<section class="gh-comments gh-canvas">
<div id="mastodon-comments-header" style="display: none;">
<h2>Comments</h2>
<p>Comments powered by Mastodon. Reply to <a id="toot-link-top">this status</a> to comment.</p>
<div class="tootlink-tip">
<b>Tip:</b> paste this URL into the search bar of your Mastodon client:<br/>
<span id="toot-link-clip" class="tootlink" onclick="copyElementTextToClipboard(this)"></span> (click to copy)
</div>
</div>
<noscript><p>You need JavaScript to view the comments.</p></noscript>
<div id="mastodon-comments-list"></div>
</section>
{{#if comments}} {{#if comments}}
<div class="gh-comments gh-canvas"> <div class="gh-comments gh-canvas">
{{comments}} {{comments}}