bring back reactions
This commit is contained in:
@@ -14,28 +14,28 @@ async function getHTML(endpoint, options = {}) {
|
||||
return { body: await res.text(), status: res.status };
|
||||
}
|
||||
|
||||
export const b = {
|
||||
bookmarksCollectionEndpoint: '/hyperapi/bookmarks/dropdown/',
|
||||
bookmarkMenuState: {},
|
||||
}
|
||||
export const b = {};
|
||||
|
||||
const BOOKMARKS_COLLECTION_ENDPOINT = '/hyperapi/bookmarks/dropdown/';
|
||||
let bookmarkMenuState = {};
|
||||
|
||||
export async function showBookmarkMenu(ev, sender, el) {
|
||||
if (b.bookmarkMenuState.state === undefined) {
|
||||
if (bookmarkMenuState.state === undefined) {
|
||||
el.addEventListener('toggle', e => {
|
||||
if (e.newState === 'closed') {
|
||||
b.bookmarkMenuState.state = 'closed';
|
||||
bookmarkMenuState.state = 'closed';
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// dismiss if open and last invoker is the same button that opened it
|
||||
if (b.bookmarkMenuState.state === 'open' && b.bookmarkMenuState.invoker === sender) {
|
||||
if (bookmarkMenuState.state === 'open' && bookmarkMenuState.invoker === sender) {
|
||||
el.hidePopover();
|
||||
return;
|
||||
}
|
||||
|
||||
b.bookmarkMenuState.invoker = sender;
|
||||
b.bookmarkMenuState.state = 'open';
|
||||
bookmarkMenuState.invoker = sender;
|
||||
bookmarkMenuState.state = 'open';
|
||||
b.send({ 'plain': 'Loading…' }, 'fillBookmarkMenu');
|
||||
el.showPopover();
|
||||
const bRect = sender.getBoundingClientRect();
|
||||
@@ -52,13 +52,13 @@ export async function showBookmarkMenu(ev, sender, el) {
|
||||
}
|
||||
el.style.top = `${bRect.bottom + scrollY}px`;
|
||||
|
||||
b.bookmarkMenuState.kind = sender.dataset.conceptKind;
|
||||
b.bookmarkMenuState.id = sender.dataset.conceptId;
|
||||
bookmarkMenuState.kind = sender.dataset.conceptKind;
|
||||
bookmarkMenuState.id = sender.dataset.conceptId;
|
||||
|
||||
const bookmarkCollections = await getHTML(b.bookmarksCollectionEndpoint, {
|
||||
const bookmarkCollections = await getHTML(BOOKMARKS_COLLECTION_ENDPOINT, {
|
||||
_query: {
|
||||
concept_kind: b.bookmarkMenuState.kind,
|
||||
concept_id: b.bookmarkMenuState.id,
|
||||
concept_kind: bookmarkMenuState.kind,
|
||||
concept_id: bookmarkMenuState.id,
|
||||
}
|
||||
});
|
||||
b.send({ 'html': bookmarkCollections.body }, 'fillBookmarkMenu');
|
||||
@@ -85,10 +85,10 @@ export async function bookmarkMenuSubmit(ev, _, el) {
|
||||
return;
|
||||
}
|
||||
|
||||
const newCollections = await getHTML(b.bookmarksCollectionEndpoint, {
|
||||
const newCollections = await getHTML(BOOKMARKS_COLLECTION_ENDPOINT, {
|
||||
_query: {
|
||||
concept_kind: b.bookmarkMenuState.kind,
|
||||
concept_id: b.bookmarkMenuState.id,
|
||||
concept_kind: bookmarkMenuState.kind,
|
||||
concept_id: bookmarkMenuState.id,
|
||||
saved: true,
|
||||
}
|
||||
});
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
export const b = {
|
||||
babycodePreviewEndpoint: '/api/babycode-preview/',
|
||||
init: 'babycodeEditorCharCountInit localizeTimestamps',
|
||||
}
|
||||
|
||||
const BABYCODE_PREVIEW_ENDPOINT = '/api/babycode-preview/';
|
||||
|
||||
const getThreadId = () => {
|
||||
const scheme = window.location.pathname.split("/");
|
||||
if (scheme[1] !== 'threads' || scheme[2] === 'new') {
|
||||
@@ -158,7 +159,7 @@ export async function babycodePreview(payload, _, el) {
|
||||
}),
|
||||
}
|
||||
|
||||
const f = await fetch(b.babycodePreviewEndpoint, options);
|
||||
const f = await fetch(BABYCODE_PREVIEW_ENDPOINT, options);
|
||||
try {
|
||||
if (!f.ok) {
|
||||
console.error(f);
|
||||
|
||||
Reference in New Issue
Block a user