Add Mastodon toots to main page

This commit is contained in:
Simon Detheridge 2023-10-17 10:17:37 +01:00
parent a84195497e
commit c7b9f9e67d
Signed by: simon
GPG Key ID: 38640971DA1E704E
10 changed files with 181 additions and 31 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

@ -69,6 +69,7 @@ production stylesheet in assets/built/screen.css
--container-width: 1320px; --container-width: 1320px;
--container-gap: clamp(24px, 1.7032rem + 1.9355vw, 48px); --container-gap: clamp(24px, 1.7032rem + 1.9355vw, 48px);
--grid-gap: 42px; --grid-gap: 42px;
--card-border-radius: 5px;
} }
:root.light-theme { :root.light-theme {
@ -1726,12 +1727,12 @@ Search LOGO Login Subscribe
/* 11.1. With sidebar */ /* 11.1. With sidebar */
.gh-container.has-sidebar .gh-main { .gh-container.has-sidebar .gh-main {
grid-column: 1 / span 12; grid-column: 1 / span 11;
position: relative; position: relative;
} }
.gh-container.has-sidebar .gh-sidebar { .gh-container.has-sidebar .gh-sidebar {
grid-column: 13 / -1; grid-column: 12 / -1;
} }
.gh-container.has-sidebar .gh-main::after { .gh-container.has-sidebar .gh-main::after {
@ -1954,6 +1955,59 @@ Search LOGO Login Subscribe
margin-top: 32px; margin-top: 32px;
} }
.mastodon-comment {
background-color: var(--background-color);
border-radius: var(--card-border-radius);
padding: 10px;
margin-bottom: 1rem;
display: flex;
border-top: 1px solid var(--background-secondary);
.mastodon-body {
flex-grow: 1;
}
.mastodon-avatar {
flex-shrink: 1;
}
.mastodon-avatar img {
margin-right: 1rem;
min-width: 60px;
}
.mastodon-meta {
padding-top: 0;
display: flex;
.mastodon-author {
flex-grow: 1;
white-space: nowrap;
.mastodon-author-uid {
font-size: 80%;
color: var(--ghost-accent-color);
}
}
.toot-link {
flex-shrink: 1;
text-align: right;
}
}
.mastodon-comment-content {
padding-top: 10px;
.tootlink {
font-size: 50%;
}
}
.disabled {
color: var(--ghost-accent-color)
}
}
.mastodon-emoji {
display: inline-block;
width: 1em;
height: 1em;
}
.mastodon-comment-content p:first-child {
margin-top: 0;
}
/* 14. Post/page /* 14. Post/page
/* ---------------------------------------------------------- */ /* ---------------------------------------------------------- */

3
assets/js/lib/purify.min.js vendored Normal file

File diff suppressed because one or more lines are too long

85
assets/js/mastodon.js Normal file
View File

@ -0,0 +1,85 @@
const MASTODON_ACCOUNT_ID = '109285376472065471'
const MASTODON_HOST = 'social.sd.ai'
async function copyElementTextToClipboard(e)
{
const text = e.textContent
await navigator.clipboard.write(text)
e.classList.add('tootClick');
setTimeout(() => {
e.classList.remove('tootClick');
}, 600);
}
function escapeHtml(unsafe) {
return unsafe
.replace(/&/g, "&")
.replace(/</g, "&lt;")
.replace(/>/g, "&gt;")
.replace(/"/g, "&quot;")
.replace(/'/g, "&#039;");
}
function renderMastodonContent(toots, parentElement) {
if (!Array.isArray(toots) || toots.length === 0) {
document.getElementById('mastodon-comments-list').innerHTML = "<div class='mastodon-comment'>No comments (yet)!</div>"
return
}
for (const toot of toots) {
toot.account.display_name = escapeHtml(toot.account.display_name)
console.log(toot)
toot.account.emojis.forEach(emoji => {
toot.account.display_name = toot.account.display_name.replace(`:${emoji.shortcode}:`,
`<img src="${escapeHtml(emoji.static_url)}" alt="Emoji ${emoji.shortcode}" class="mastodon-emoji" />`);
})
toot.emojis.forEach(emoji => {
toot.content = toot.content.replace(`:${emoji.shortcode}:`,
`<img src="${escapeHtml(emoji.static_url)}" alt="Emoji ${emoji.shortcode}" class="mastodon-emoji" />`);
})
const comment =
`<div class="mastodon-comment">
<div class="mastodon-avatar">
<img src="${escapeHtml(toot.account.avatar_static)}" height=60 width=60 alt="${escapeHtml(toot.account.display_name)}'s avatar">
</div>
<div class="mastodon-body">
<div class="mastodon-meta">
<div class="mastodon-author">
<div class="mastodon-author-link">
<a href="${toot.account.url}" rel="nofollow">
<span>${toot.account.display_name}</span>
</a>
<br/>
<span class="mastodon-author-uid">(@${escapeHtml(toot.account.acct === 's' ? 's@sd.ai' : toot.account.acct)})</span>
</div>
</div>
<div class="toot-link">
<a class="date" href="${toot.uri}" rel="nofollow">
${toot.created_at.substring(0, 10)}
</a>
<br/>
</div>
</div>
<div class="mastodon-comment-content">
${toot.content}
<span class="tootlink">${toot.uri}</span>
</div>
</div>
</div>`
const child = DOMPurify.sanitize(comment, {'RETURN_DOM_FRAGMENT': true});
const links = child.querySelectorAll('.tootlink');
for (const link of links) {
link.onclick = function() { return copyToClipboard(this); }
}
parentElement.appendChild(child);
}
}
document.addEventListener("DOMContentLoaded", async (event) => {
if (document.getElementsByClassName('gh-sidebar').length > 0) {
const element = document.getElementById('mastodon-comments-list')
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()
return renderMastodonContent(content, element)
}
})

View File

@ -18,7 +18,6 @@ function changeFavicon() {
} }
function changeTheme(useLight) { function changeTheme(useLight) {
console.log({ useLight })
document.documentElement.classList.remove('light-theme', 'dark-theme', 'has-light-text', 'has-dark-text') document.documentElement.classList.remove('light-theme', 'dark-theme', 'has-light-text', 'has-dark-text')
if (useLight) { if (useLight) {
document.documentElement.classList.add('light-theme', 'has-dark-text') document.documentElement.classList.add('light-theme', 'has-dark-text')
@ -39,8 +38,6 @@ themeToggle.addEventListener("click", () => {
changeTheme(document.documentElement.classList.contains('dark-theme')) changeTheme(document.documentElement.classList.contains('dark-theme'))
}); });
console.log({ localTheme, isOSLight })
if (localTheme === "light") { if (localTheme === "light") {
changeTheme(true) changeTheme(true)
} else { } else {

View File

@ -14,9 +14,11 @@
</nav> </nav>
<div class="gh-footer-copyright"> <div class="gh-footer-copyright">
Powered by <a href="https://ghost.org/" target="_blank" rel="noopener">Ghost</a> Powered by <a href="https://ghost.org/" target="_blank" rel="noopener">Ghost</a>
:
<a href="https://git.sd.ai/simon/ghost-theme-sd.ai" target="_blank" rel="noopener">Theme</a>
</div> </div>
</div> </div>
{{#if @site.members_enabled}} {{#if @site.members_enabled}}
{{#unless @member}} {{#unless @member}}
<section class="gh-footer-signup"> <section class="gh-footer-signup">

View File

@ -8,7 +8,7 @@
<section class="gh-container is-{{#match postFeedStyle "List"}}list{{else}}grid{{/match}}{{#if showSidebar}} has-sidebar{{/if}}{{#unless @custom.show_images_in_feed}} no-image{{/unless}} gh-outer"> <section class="gh-container is-{{#match postFeedStyle "List"}}list{{else}}grid{{/match}}{{#if showSidebar}} has-sidebar{{/if}}{{#unless @custom.show_images_in_feed}} no-image{{/unless}} gh-outer">
<div class="gh-container-inner gh-inner"> <div class="gh-container-inner gh-inner">
{{#if showTitle}} {{#if showTitle}}
<h2 class="gh-container-title"> <h2 class="gh-container-title">
{{#unless title}}Latest{{else}}{{title}}{{/unless}} {{#unless title}}Latest{{else}}{{title}}{{/unless}}
@ -81,26 +81,8 @@
{{#if showSidebar}} {{#if showSidebar}}
<aside class="gh-sidebar"> <aside class="gh-sidebar">
<section class="gh-about"> <h3 class="gh-card-title is-title"><a href="https://social.sd.ai/@s" target="_blank" rel="noopener">Latest From Mastodon</a></h3>
{{#if @site.icon}} <div id="mastodon-comments-list"></div>
<img class="gh-about-icon" src="{{@site.icon}}" alt="{{@site.title}}" loading="lazy">
{{/if}}
<h3 class="gh-about-title is-title">{{@site.title}}</h3>
{{#if @site.description}}
<p class="gh-about-description is-body">{{@site.description}}</p>
{{/if}}
{{#if @site.members_enabled}}
{{#unless @member}}
<button class="gh-button" data-portal="signup">Subscribe</button>
{{else}}
{{#if @site.paid_members_enabled}}
{{#unless @member.paid}}
<button class="gh-button" data-portal="upgrade">Upgrade</button>
{{/unless}}
{{/if}}
{{/unless}}
{{/if}}
</section>
</aside> </aside>
{{/if}} {{/if}}