181 lines
4.7 KiB
JavaScript
181 lines
4.7 KiB
JavaScript
export const b = {
|
|
init: 'activatePostImages getUserData',
|
|
}
|
|
|
|
const POST_IMAGES_SELECTOR = 'img.post-image:not(aside img.post-image)'
|
|
const WHOAMI_ENDPOINT = '/api/whoami/'
|
|
const THREAD_PERM_ENDPOINT = '/api/thread-permission/'
|
|
const TOGGLE_REACTION_ENDPOINT = '/api/toggle-reaction/'
|
|
const REPLACE_REACTIONS_ENDPOINT = '/hyperapi/reactions/'
|
|
|
|
const getThreadId = () => {
|
|
const scheme = window.location.pathname.split("/");
|
|
if (scheme[1] !== 'threads' || scheme[2] === 'new') {
|
|
return -1;
|
|
}
|
|
return parseInt(scheme[2]);
|
|
}
|
|
|
|
let images = [];
|
|
let currentIndex = 0;
|
|
let currentUser = null;
|
|
|
|
let reactionMenuState = {};
|
|
|
|
export function activatePostImages(_, __, ___) {
|
|
const images = document.querySelectorAll(POST_IMAGES_SELECTOR);
|
|
images.forEach(image => {
|
|
image.style.cursor = 'pointer';
|
|
image.dataset.s = 'collectImages';
|
|
});
|
|
}
|
|
|
|
export function collectImages(_, sender, el) {
|
|
if (!el.contains(sender)) return;
|
|
images = Array.from(el.querySelectorAll(POST_IMAGES_SELECTOR));
|
|
currentIndex = images.indexOf(sender);
|
|
b.trigger('showLightbox');
|
|
}
|
|
|
|
export function showLightbox(_, __, el) {
|
|
const originalImg = images[currentIndex];
|
|
const lightboxImg = el.querySelector('img');
|
|
const anchor = el.querySelector('a');
|
|
anchor.href = originalImg.src;
|
|
lightboxImg.src = originalImg.src;
|
|
lightboxImg.alt = originalImg.alt;
|
|
|
|
if (!el.open) {
|
|
el.showModal();
|
|
}
|
|
|
|
b.trigger('lightboxSetCounter');
|
|
}
|
|
|
|
export function closeLightbox(_, __, el) {
|
|
el.close();
|
|
}
|
|
|
|
export function lightboxSetCounter(_, __, el) {
|
|
el.innerText = `${currentIndex + 1}/${images.length}`;
|
|
}
|
|
|
|
export function lightboxNext(_, __, ___) {
|
|
if (images.length == 1) return;
|
|
currentIndex++;
|
|
if (currentIndex >= images.length) {
|
|
currentIndex = 0;
|
|
}
|
|
b.trigger('showLightbox');
|
|
}
|
|
|
|
export function lightboxPrevious(_, __, ___) {
|
|
if (images.length == 1) return;
|
|
currentIndex--;
|
|
if (currentIndex < 0) {
|
|
currentIndex = images.length - 1;
|
|
}
|
|
b.trigger('showLightbox');
|
|
}
|
|
|
|
export async function getUserData(_, __, ___) {
|
|
currentUser = await b.getData(WHOAMI_ENDPOINT);
|
|
b.trigger('highlightMentions');
|
|
const d = (await b.getData(`${THREAD_PERM_ENDPOINT}${getThreadId()}`)).can_post;
|
|
if (d) {
|
|
b.trigger('enableReactionMenuButton');
|
|
b.trigger('enableReactionButtons');
|
|
} else {
|
|
b.trigger('disableReactionMenuButton');
|
|
}
|
|
}
|
|
|
|
export function highlightMentions(_, __, el) {
|
|
if (!el) return;
|
|
|
|
if (el.dataset.username === currentUser.username) {
|
|
el.classList.add('me');
|
|
}
|
|
}
|
|
|
|
export function openReactionMenu(ev, sender, el) {
|
|
if (!el) return;
|
|
if (reactionMenuState.state === undefined) {
|
|
el.addEventListener('toggle', e => {
|
|
if (e.newState === 'closed') {
|
|
reactionMenuState.state = 'closed';
|
|
}
|
|
});
|
|
}
|
|
|
|
if (reactionMenuState.state === 'open' && reactionMenuState.invoker === sender) {
|
|
el.hidePopover();
|
|
return;
|
|
}
|
|
|
|
// TODO: [el, sender].prop(key) searches for ancestors with attr [data-${key}] if current element does not have `dataset[key]` but dataset transforms key names whereas css does not
|
|
reactionMenuState.post = sender.prop('postid');
|
|
|
|
reactionMenuState.invoker = sender;
|
|
reactionMenuState.state = 'open';
|
|
el.showPopover();
|
|
|
|
const bRect = sender.getBoundingClientRect();
|
|
const scrollY = window.scrollY;
|
|
|
|
el.style.left = `${bRect.left}px`;
|
|
el.style.top = `${bRect.bottom + scrollY}px`;
|
|
}
|
|
|
|
export function closeReactionMenu(_, __, el) {
|
|
el.hidePopover();
|
|
}
|
|
|
|
export async function toggleReaction(_, sender, __) {
|
|
const emoji = sender.dataset.emoji;
|
|
const post = sender.prop('postid') ? sender.prop('postid') : reactionMenuState.post;
|
|
|
|
const res = await fetch(TOGGLE_REACTION_ENDPOINT, {
|
|
method: 'POST',
|
|
body: JSON.stringify({ reaction: emoji, post: post }),
|
|
headers: {
|
|
'content-type': 'application/json',
|
|
},
|
|
});
|
|
if (res.status !== 200) {
|
|
return;
|
|
}
|
|
|
|
b.send({ postId: post }, 'replaceReactionButtons');
|
|
}
|
|
|
|
export async function replaceReactionButtons(payload, __, el) {
|
|
if (payload.postId !== el.prop('postid')) return;
|
|
const res = await fetch(`${REPLACE_REACTIONS_ENDPOINT}${payload.postId}`);
|
|
if (res.status !== 200) {
|
|
return;
|
|
}
|
|
const body = await res.text();
|
|
const p = new DOMParser();
|
|
const e = p.parseFromString(body, 'text/html').body;
|
|
el.replaceChildren(...e.children);
|
|
el.childNodes.forEach(b => {
|
|
if (!b instanceof HTMLButtonElement) return;
|
|
b.disabled = false;
|
|
})
|
|
}
|
|
|
|
export function disableReactionMenuButton(_, __, el) {
|
|
el.title = 'You do not have permission to add reactions to this post.';
|
|
}
|
|
|
|
export function enableReactionMenuButton(_, __, el) {
|
|
el.disabled = false;
|
|
el.title = '';
|
|
}
|
|
|
|
export function enableReactionButtons(_, __, el) {
|
|
if (!el) return;
|
|
el.disabled = false;
|
|
}
|