tried something different with a custom component
All checks were successful
/ weblog.lol (push) Successful in 12s
All checks were successful
/ weblog.lol (push) Successful in 12s
This commit is contained in:
parent
f0a0b5de75
commit
7615026a1f
3 changed files with 185 additions and 92 deletions
|
@ -14,6 +14,7 @@
|
||||||
<img class="avatar" src="https://cdn.some.pics/deathau/663da4619fdb6.svg" alt="My avatar — A pixelated self-portrait in the style of the 'bitizens' in the mobile game Tiny Tower" />
|
<img class="avatar" src="https://cdn.some.pics/deathau/663da4619fdb6.svg" alt="My avatar — A pixelated self-portrait in the style of the 'bitizens' in the mobile game Tiny Tower" />
|
||||||
<h1 class="weblog-title"><a href="{base-path}">{weblog-title}</a></h1>
|
<h1 class="weblog-title"><a href="{base-path}">{weblog-title}</a></h1>
|
||||||
{navigation}
|
{navigation}
|
||||||
|
<fedi-social></fedi-social>
|
||||||
</header>
|
</header>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@ -26,8 +27,8 @@
|
||||||
<i data-emoji="{emoji}"></i>
|
<i data-emoji="{emoji}"></i>
|
||||||
{body}
|
{body}
|
||||||
<aside class="post-info">
|
<aside class="post-info">
|
||||||
<a class="status_url" href="{status_url}"><i class="omg-icon omg-prami"></i> via status.lol</a>
|
<a class="status_url" href="{status_url}" target="_blank"><i class="omg-icon omg-prami"></i> via status.lol</a>
|
||||||
<a class="external_url" href="{external_url}"><i class="omg-icon omg-fediverse"></i> Interact on the Fediverse</a>
|
<a class="external_url" href="{external_url}" target="_blank"><i class="omg-icon omg-fediverse"></i> Interact on the Fediverse</a>
|
||||||
</aside>
|
</aside>
|
||||||
<aside class="post-tags">
|
<aside class="post-tags">
|
||||||
{tags}
|
{tags}
|
||||||
|
|
|
@ -6,102 +6,142 @@ Location: /fediverse.js
|
||||||
/**/
|
/**/
|
||||||
|
|
||||||
const SUBSCRIBE_LINK_REL = 'http://ostatus.org/schema/1.0/subscribe'
|
const SUBSCRIBE_LINK_REL = 'http://ostatus.org/schema/1.0/subscribe'
|
||||||
async function getSubscribeTemplate() {
|
const AVATAR_LINK_REL = 'http://webfinger.net/rel/avatar'
|
||||||
const input = prompt("Please enter your fediverse / mastodon handle (e.g. '@user@domain.social')", "@")
|
|
||||||
let handle = input.trim().replace(/^@/,'')
|
|
||||||
const split = handle.split('@')
|
|
||||||
if(split.length == 2) {
|
|
||||||
const resource = `acct:${handle}`
|
|
||||||
const domain = split[1]
|
|
||||||
|
|
||||||
// look up remote user via webfinger
|
class FediSocial extends HTMLElement {
|
||||||
const url = `https://${domain}/.well-known/webfinger?resource=${resource}`
|
constructor() {
|
||||||
return fetch(url, {headers: {
|
// Always call super first in constructor
|
||||||
'Content-Type': 'application/json'
|
super();
|
||||||
}}).then(async result => {
|
|
||||||
const json = await result.json()
|
|
||||||
const subscribe = json.links.find(link => link.rel && link.rel == SUBSCRIBE_LINK_REL)
|
|
||||||
let template = subscribe.template
|
|
||||||
return template
|
|
||||||
})
|
|
||||||
.catch(e => {
|
|
||||||
console.error(e)
|
|
||||||
alert(`Sorry, we couldn't find an uri for ${input}.\n\nTry searching for "${uri}" on ${domain} (or in your fediverse client of choice)`)
|
|
||||||
return null
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
else {
|
|
||||||
alert('Please enter your fediverse address in @user@domain.social format')
|
|
||||||
return null
|
|
||||||
}
|
|
||||||
return null
|
|
||||||
}
|
|
||||||
|
|
||||||
function linkToUrl(uri) {
|
connectedCallback() {
|
||||||
// window.open(uri, '_blank').focus()
|
const data = JSON.parse(localStorage.getItem('fedi-social') || '{}')
|
||||||
const link = document.createElement('a')
|
|
||||||
link.href = uri
|
|
||||||
link.target = "_blank"
|
|
||||||
link.click()
|
|
||||||
}
|
|
||||||
|
|
||||||
function noDataCick(href) {
|
let img;
|
||||||
return async (e) => {
|
if(data.avatar) {
|
||||||
e.preventDefault()
|
img = document.createElement('img')
|
||||||
let subscribe_template = await getSubscribeTemplate()
|
img.src = data.avatar || "https://upload.wikimedia.org/wikipedia/commons/9/93/Fediverse_logo_proposal.svg"
|
||||||
if(subscribe_template) {
|
|
||||||
localStorage.setItem('subscribe_template', subscribe_template)
|
|
||||||
const url = subscribe_template.replace("{uri}", href)
|
|
||||||
linkToUrl(url)
|
|
||||||
addSocialButtons(this, url)
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
linkToUrl(href)
|
img = document.createElement('i')
|
||||||
|
img.classList.add('omg-icon', 'omg-fediverse')
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const summary = document.createElement('summary')
|
||||||
|
summary.appendChild(img)
|
||||||
|
|
||||||
|
const details = document.createElement('details')
|
||||||
|
details.appendChild(summary)
|
||||||
|
|
||||||
|
// popup
|
||||||
|
const div = document.createElement('div')
|
||||||
|
div.classList.add('card', 'popover')
|
||||||
|
|
||||||
|
if(data.id) {
|
||||||
|
//logout
|
||||||
|
const p = document.createElement('p')
|
||||||
|
p.innerHTML = `Hey again, ${data.name} 👋`
|
||||||
|
div.appendChild(p)
|
||||||
|
|
||||||
|
const button = document.createElement('button')
|
||||||
|
button.innerText = "Forget me"
|
||||||
|
button.addEventListener('click', ev => { localStorage.clear(); window.location.reload() })
|
||||||
|
div.appendChild(button)
|
||||||
|
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
const p = document.createElement('p')
|
||||||
|
p.innerHTML = "Hey 👋, <br />please enter your fediverse / mastodon handle below. "
|
||||||
|
|
||||||
|
const form = document.createElement('form')
|
||||||
|
form.addEventListener('submit', this.login)
|
||||||
|
|
||||||
|
const input = document.createElement('input')
|
||||||
|
input.type = 'text'
|
||||||
|
input.name = 'handle'
|
||||||
|
input.placeholder = '@user@domain.social'
|
||||||
|
form.appendChild(input)
|
||||||
|
|
||||||
|
const button = document.createElement('input')
|
||||||
|
button.type = 'submit'
|
||||||
|
button.value = 'Submit'
|
||||||
|
form.appendChild(button)
|
||||||
|
|
||||||
|
div.appendChild(p)
|
||||||
|
div.appendChild(form)
|
||||||
|
}
|
||||||
|
|
||||||
|
details.appendChild(div)
|
||||||
|
this.appendChild(details)
|
||||||
|
}
|
||||||
|
|
||||||
|
login(ev) {
|
||||||
|
ev.preventDefault()
|
||||||
|
const input = this.elements['handle'].value
|
||||||
|
let handle = input.trim().replace(/^@/,'')
|
||||||
|
const split = handle.split('@')
|
||||||
|
if(split.length == 2) {
|
||||||
|
const resource = `acct:${handle}`
|
||||||
|
const domain = split[1]
|
||||||
|
|
||||||
|
// look up remote user via webfinger
|
||||||
|
const url = `https://${domain}/.well-known/webfinger?resource=${resource}`
|
||||||
|
return fetch(url, {headers: {
|
||||||
|
'Accept': 'application/json'
|
||||||
|
}}).then(async result => {
|
||||||
|
const json = await result.json()
|
||||||
|
console.log(json)
|
||||||
|
|
||||||
|
const template = json.links.find(link => link.rel && link.rel == SUBSCRIBE_LINK_REL)?.template
|
||||||
|
const avatar = json.links.find(link => link.rel && link.rel == AVATAR_LINK_REL)?.href
|
||||||
|
const id = json.links.find(link => link.rel && link.rel == "self" && link.type == "application/activity+json")?.href
|
||||||
|
|
||||||
|
const data = { id, template, avatar, name: input }
|
||||||
|
localStorage.setItem('fedi-social', JSON.stringify(data))
|
||||||
|
window.location.reload()
|
||||||
|
})
|
||||||
|
.catch(e => {
|
||||||
|
console.error(e)
|
||||||
|
this.parentElement.querySelector('p').innerHTML = `Sorry, we couldn't find details for ${input}.\n\nTo interact with posts, try searching for their url on ${domain} (or in your fediverse client of choice)`
|
||||||
|
return null
|
||||||
|
})
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
this.parentElement.querySelector('p').innerHTML = `Please enter your fediverse address in @user@domain.social format`
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
clicked(ev) {
|
||||||
|
ev.preventDefault()
|
||||||
|
console.log("Ow! You clicked me!")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function addSocialButtons(el, href) {
|
customElements.define('fedi-social', FediSocial)
|
||||||
// TODO: fetch the post from the fediverse to add in comment, like and retweet count
|
|
||||||
// the following fetches the activitypub object but has no reference to the likes, etc
|
|
||||||
// if I had the local id, I could use the mastodon API to get it, but friendica uses the diaspora:guid in the link
|
|
||||||
// const url = new URL(href).searchParams.get("uri")
|
|
||||||
// fetch(url, {
|
|
||||||
// headers: {
|
|
||||||
// 'Accept': 'application/json'
|
|
||||||
// }
|
|
||||||
// }).then(async result => {
|
|
||||||
// const json = await result.text()
|
|
||||||
// console.log(json)
|
|
||||||
// })
|
|
||||||
// .catch(e => {
|
|
||||||
// console.error(e)
|
|
||||||
// })
|
|
||||||
|
|
||||||
const innerHTML = `
|
|
||||||
<a href='${href}' target="_blank"><i class="fa fa-comment"></i></a>
|
|
||||||
<a href='${href}' target="_blank"><i class="fa fa-star"></i></a>
|
|
||||||
<a href='${href}' target="_blank"><i class="fa fa-retweet"></i></a>
|
|
||||||
`
|
|
||||||
|
|
||||||
const span = document.createElement('span')
|
|
||||||
span.classList.add('fediverse')
|
|
||||||
span.innerHTML = innerHTML
|
|
||||||
|
|
||||||
el.insertAdjacentElement('afterend', span)
|
|
||||||
el.remove()
|
|
||||||
}
|
|
||||||
|
|
||||||
function fediverse() {
|
function fediverse() {
|
||||||
let subscribe_template = localStorage.getItem('subscribe_template');
|
const data = JSON.parse(localStorage.getItem('fedi-social') || '{}')
|
||||||
|
document.querySelectorAll("a.external_url:not([href='{external_url}'])").forEach(el => {
|
||||||
|
if(data.template){
|
||||||
|
const innerHTML = `
|
||||||
|
<a href='${href}' target="_blank"><i class="fa fa-comment"></i></a>
|
||||||
|
<a href='${href}' target="_blank"><i class="fa fa-star"></i></a>
|
||||||
|
<a href='${href}' target="_blank"><i class="fa fa-retweet"></i></a>
|
||||||
|
`
|
||||||
|
|
||||||
document.querySelectorAll("a.external_url:not([href='{external_url}'])").forEach(el => {
|
const span = document.createElement('span')
|
||||||
if(subscribe_template) {
|
span.classList.add('fediverse')
|
||||||
console.log(subscribe_template.replace("{uri}", el.href))
|
span.innerHTML = innerHTML
|
||||||
addSocialButtons(el, subscribe_template.replace("{uri}", el.href))
|
|
||||||
}
|
el.insertAdjacentElement('afterend', span)
|
||||||
else {
|
el.remove()
|
||||||
el.addEventListener('click', noDataCick(el.href))
|
}
|
||||||
}
|
else {
|
||||||
})
|
el.addEventListener('click', ev =>{
|
||||||
|
ev.preventDefault()
|
||||||
|
window.scrollTo({ top: 0, behavior: 'smooth' })
|
||||||
|
document.querySelector('fedi-social summary').click()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
}
|
}
|
|
@ -59,7 +59,8 @@ body {
|
||||||
}
|
}
|
||||||
|
|
||||||
article,
|
article,
|
||||||
main.page {
|
main.page,
|
||||||
|
.card {
|
||||||
display: block;
|
display: block;
|
||||||
max-width: 42em;
|
max-width: 42em;
|
||||||
border-radius: 1em;
|
border-radius: 1em;
|
||||||
|
@ -336,3 +337,54 @@ th {
|
||||||
text-align: left;
|
text-align: left;
|
||||||
border: 1px solid var(--accent);
|
border: 1px solid var(--accent);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
fedi-social {
|
||||||
|
margin-left:auto;
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
fedi-social summary {
|
||||||
|
width: 48px;
|
||||||
|
height: 48px;
|
||||||
|
border-radius: 50%;
|
||||||
|
display: inline-block;
|
||||||
|
background-color: var(--accent);
|
||||||
|
text-align: center;
|
||||||
|
vertical-align: middle;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
fedi-social img {
|
||||||
|
width: 48px;
|
||||||
|
height: 48px;
|
||||||
|
border-radius: 50%;
|
||||||
|
}
|
||||||
|
|
||||||
|
fedi-social summary + * {
|
||||||
|
position:absolute;
|
||||||
|
}
|
||||||
|
|
||||||
|
fedi-social .popover {
|
||||||
|
max-width: 300px;
|
||||||
|
min-height: 100px;
|
||||||
|
font-size: 85%;
|
||||||
|
position: absolute;
|
||||||
|
right: 0;
|
||||||
|
top: 0;
|
||||||
|
z-index: 100;
|
||||||
|
border-radius: 1em 0 1em 1em;
|
||||||
|
}
|
||||||
|
|
||||||
|
fedi-social .popover p {
|
||||||
|
line-height: 1.2em;
|
||||||
|
}
|
||||||
|
|
||||||
|
fedi-social a {
|
||||||
|
background: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
fedi-social i::before {
|
||||||
|
font-size: 32px;
|
||||||
|
line-height: 48px;
|
||||||
|
}
|
Loading…
Reference in a new issue