mirror of
https://git.sr.ht/~cadence/bibliogram
synced 2024-09-28 23:07:30 +00:00
126 lines
3.1 KiB
JavaScript
126 lines
3.1 KiB
JavaScript
|
import {q, ElemJS} from "./elemjs/elemjs.js"
|
||
|
|
||
|
/** @type {PostOverlay[]} */
|
||
|
const postOverlays = []
|
||
|
const titleHistory = []
|
||
|
titleHistory.push(document.title)
|
||
|
const shortcodeDataMap = new Map()
|
||
|
|
||
|
window.addEventListener("popstate", event => {
|
||
|
// console.log(event.state, postOverlays.length)
|
||
|
if (event.state) {
|
||
|
if (event.state.view === "post_overlay") {
|
||
|
loadPostOverlay(event.state.shortcode, false)
|
||
|
}
|
||
|
} else { // event.state === null which means back to originally loaded page, so pop overlay
|
||
|
setTimeout(() => { // make sure document is entirely loaded
|
||
|
if (titleHistory.length === 1) {
|
||
|
document.title = titleHistory[0]
|
||
|
} else if (titleHistory.length >= 2) {
|
||
|
titleHistory.pop()
|
||
|
document.title = titleHistory.slice(-1)[0]
|
||
|
}
|
||
|
if (postOverlays.length) {
|
||
|
popOverlay()
|
||
|
} else {
|
||
|
window.location.reload()
|
||
|
}
|
||
|
})
|
||
|
}
|
||
|
})
|
||
|
|
||
|
function pushOverlay(overlay) {
|
||
|
postOverlays.push(overlay)
|
||
|
document.body.style.overflowY = "hidden"
|
||
|
}
|
||
|
|
||
|
function popOverlay() {
|
||
|
const top = postOverlays.pop()
|
||
|
if (top) {
|
||
|
top.pop()
|
||
|
}
|
||
|
if (postOverlays.length === 0) document.body.style.overflowY = "auto"
|
||
|
}
|
||
|
|
||
|
class PostOverlay extends ElemJS {
|
||
|
constructor() {
|
||
|
super("div")
|
||
|
this.class("post-overlay")
|
||
|
this.event("click", event => {
|
||
|
if (event.target === event.currentTarget) history.back()
|
||
|
})
|
||
|
this.loaded = false
|
||
|
this.available = true
|
||
|
setTimeout(() => {
|
||
|
if (!this.loaded) {
|
||
|
this.class("loading")
|
||
|
this.child(
|
||
|
new ElemJS("div").class("loading-inner").text("Loading...")
|
||
|
)
|
||
|
}
|
||
|
}, 0)
|
||
|
}
|
||
|
|
||
|
setContent(html) {
|
||
|
this.html(html)
|
||
|
this.loaded = true
|
||
|
this.removeClass("loading")
|
||
|
}
|
||
|
|
||
|
showError() {
|
||
|
this.loaded = true
|
||
|
this.class("loading")
|
||
|
this.clearChildren()
|
||
|
this.child(
|
||
|
new ElemJS("div").class("loading-inner").text("Request failed.")
|
||
|
)
|
||
|
}
|
||
|
|
||
|
pop() {
|
||
|
this.element.remove()
|
||
|
this.available = false
|
||
|
}
|
||
|
}
|
||
|
|
||
|
const timeline = q("#timeline")
|
||
|
if (timeline) {
|
||
|
timeline.addEventListener("click", event => {
|
||
|
/** @type {HTMLElement[]} */
|
||
|
//@ts-ignore
|
||
|
const path = event.composedPath()
|
||
|
const postLink = path.find(element => element.classList && element.classList.contains("sized-link") && element.hasAttribute("data-shortcode"))
|
||
|
if (postLink) {
|
||
|
event.preventDefault()
|
||
|
const shortcode = postLink.getAttribute("data-shortcode")
|
||
|
loadPostOverlay(shortcode, true)
|
||
|
}
|
||
|
})
|
||
|
}
|
||
|
|
||
|
function fetchShortcodeFragment(shortcode) {
|
||
|
if (shortcodeDataMap.has(shortcode)) return Promise.resolve(shortcodeDataMap.get(shortcode))
|
||
|
else return fetch(`/fragment/post/${shortcode}`).then(res => res.json())
|
||
|
}
|
||
|
|
||
|
function loadPostOverlay(shortcode, shouldPushState) {
|
||
|
const overlay = new PostOverlay()
|
||
|
document.body.appendChild(overlay.element)
|
||
|
pushOverlay(overlay)
|
||
|
if (shouldPushState) history.pushState({view: "post_overlay", shortcode: shortcode}, "", `/p/${shortcode}`)
|
||
|
const fetcher = fetchShortcodeFragment(shortcode)
|
||
|
fetcher.then(root => {
|
||
|
shortcodeDataMap.set(shortcode, root)
|
||
|
if (overlay.available) {
|
||
|
const {title, html} = root
|
||
|
overlay.setContent(html)
|
||
|
if (overlay.available) {
|
||
|
document.title = title
|
||
|
}
|
||
|
}
|
||
|
})
|
||
|
fetcher.catch(error => {
|
||
|
console.error(error)
|
||
|
overlay.showError()
|
||
|
})
|
||
|
}
|