bring back reactions

This commit is contained in:
2026-06-07 23:01:58 +03:00
parent 5dfe477607
commit b63b6a1682
11 changed files with 248 additions and 35 deletions

View File

@@ -4,11 +4,24 @@ export const b = {
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 => {
@@ -68,6 +81,13 @@ export function lightboxPrevious(_, __, ___) {
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) {
@@ -77,3 +97,83 @@ export function highlightMentions(_, __, el) {
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) {
el.disabled = false;
}