feature: reactions
This commit is contained in:
parent
b8467ec870
commit
7046bb0389
11 changed files with 371 additions and 133 deletions
|
|
@ -53,7 +53,8 @@ export async function GET(request: Request, meta: Record<string, any>): Promise<
|
||||||
|
|
||||||
const options: FSDB_SEARCH_OPTIONS<EVENT> = {
|
const options: FSDB_SEARCH_OPTIONS<EVENT> = {
|
||||||
...(meta.query ?? {}),
|
...(meta.query ?? {}),
|
||||||
limit: Math.min(parseInt(meta.query?.limit ?? '10'), 1_000),
|
limit: Math.min(parseInt(meta.query?.limit ?? '10', 10), 1_000),
|
||||||
|
offset: Math.max(parseInt(meta.query?.offset ?? '0', 10), 0),
|
||||||
sort,
|
sort,
|
||||||
filter: (entry: WALK_ENTRY<EVENT>) => {
|
filter: (entry: WALK_ENTRY<EVENT>) => {
|
||||||
const {
|
const {
|
||||||
|
|
@ -63,13 +64,11 @@ export async function GET(request: Request, meta: Record<string, any>): Promise<
|
||||||
}
|
}
|
||||||
} = /^.*\/events\/(?<event_type>.*?)\/.*\/(?<event_id>[A-Za-z-]+)\.json$/.exec(entry.path) ?? { groups: {} };
|
} = /^.*\/events\/(?<event_type>.*?)\/.*\/(?<event_id>[A-Za-z-]+)\.json$/.exec(entry.path) ?? { groups: {} };
|
||||||
|
|
||||||
const id = `${event_type}:${event_id}`;
|
if (meta.query.after_id && event_id <= meta.query.after_id) {
|
||||||
|
|
||||||
if (meta.query.after_id && id <= meta.query.after_id) {
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (meta.query.before_id && id >= meta.query.before_id) {
|
if (meta.query.before_id && event_id >= meta.query.before_id) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -93,7 +92,7 @@ export async function GET(request: Request, meta: Record<string, any>): Promise<
|
||||||
if (results.length === 0 && meta.query.wait) {
|
if (results.length === 0 && meta.query.wait) {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
function on_create(create_event: any) {
|
function on_create(create_event: any) {
|
||||||
if (meta.query.type && create_event.item.type !== meta.query.type) {
|
if (meta.query.type && !meta.query.type.split(',').includes(create_event.item.type)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -11,8 +11,8 @@
|
||||||
|
|
||||||
<link rel="stylesheet" href="./base.css"></link>
|
<link rel="stylesheet" href="./base.css"></link>
|
||||||
|
|
||||||
|
<script src="./js/_utils.js" type="text/javascript"></script>
|
||||||
<script src="./js/api.js" type="text/javascript"></script>
|
<script src="./js/api.js" type="text/javascript"></script>
|
||||||
|
|
||||||
<script src="./js/audioplayer.js" type="text/javascript"></script>
|
<script src="./js/audioplayer.js" type="text/javascript"></script>
|
||||||
<script src="./js/datetimeutils.js" type="text/javascript"></script>
|
<script src="./js/datetimeutils.js" type="text/javascript"></script>
|
||||||
<script src="./js/debounce.js" type="text/javascript"></script>
|
<script src="./js/debounce.js" type="text/javascript"></script>
|
||||||
|
|
@ -29,6 +29,7 @@
|
||||||
<script src="./js/embeds/vimeo.js" type="text/javascript"></script>
|
<script src="./js/embeds/vimeo.js" type="text/javascript"></script>
|
||||||
<script src="./js/embeds/youtube.js" type="text/javascript"></script>
|
<script src="./js/embeds/youtube.js" type="text/javascript"></script>
|
||||||
<script src="./js/emojis/en.js" type="text/javascript"></script>
|
<script src="./js/emojis/en.js" type="text/javascript"></script>
|
||||||
|
<script src="./js/eventactions.js" type="text/javascript"></script>
|
||||||
<script src="./js/htmlify.js" type="text/javascript"></script>
|
<script src="./js/htmlify.js" type="text/javascript"></script>
|
||||||
<script src="./js/locationchange.js" type="text/javascript"></script>
|
<script src="./js/locationchange.js" type="text/javascript"></script>
|
||||||
<script src="./js/notifications.js" type="text/javascript"></script>
|
<script src="./js/notifications.js" type="text/javascript"></script>
|
||||||
|
|
|
||||||
40
public/js/_utils.js
Normal file
40
public/js/_utils.js
Normal file
|
|
@ -0,0 +1,40 @@
|
||||||
|
function get_best_coords_for_popup(_options) {
|
||||||
|
const viewport_width = document.body.getBoundingClientRect().width;
|
||||||
|
const viewport_height = document.body.getBoundingClientRect().height;
|
||||||
|
|
||||||
|
const options = {
|
||||||
|
offset: {
|
||||||
|
x: 0,
|
||||||
|
y: 0,
|
||||||
|
},
|
||||||
|
popup: {
|
||||||
|
width: 200,
|
||||||
|
height: 200,
|
||||||
|
},
|
||||||
|
..._options,
|
||||||
|
};
|
||||||
|
|
||||||
|
const target = options.target ?? {
|
||||||
|
x:
|
||||||
|
options.target_element?.getBoundingClientRect().left ??
|
||||||
|
viewport_width / 2 - options.popup.width / 2,
|
||||||
|
y:
|
||||||
|
options.target_element?.getBoundingClientRect().top ??
|
||||||
|
viewport_height / 2 - options.popup.height / 2,
|
||||||
|
};
|
||||||
|
|
||||||
|
const best_coords = {
|
||||||
|
x: target.x + options.offset.x,
|
||||||
|
y: target.y + options.offset.y,
|
||||||
|
};
|
||||||
|
|
||||||
|
if (target.x + options.offset.x + options.popup.width + options.offset.x > viewport_width) {
|
||||||
|
best_coords.x = Math.max(0, target.x - options.popup.width + options.offset.x);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (target.y + options.offset.y + options.popup.height + options.offset.y > viewport_height) {
|
||||||
|
best_coords.y = Math.max(0, target.y - options.popup.height + options.offset.y);
|
||||||
|
}
|
||||||
|
|
||||||
|
return best_coords;
|
||||||
|
}
|
||||||
134
public/js/eventactions.js
Normal file
134
public/js/eventactions.js
Normal file
|
|
@ -0,0 +1,134 @@
|
||||||
|
const event_actions_popup_width = 100;
|
||||||
|
const event_actions_popup_height = 260;
|
||||||
|
|
||||||
|
const event_actions_popup_styling = `
|
||||||
|
#eventactionspopup {
|
||||||
|
position: fixed;
|
||||||
|
max-width: 90%;
|
||||||
|
overflow-x: auto;
|
||||||
|
z-index: 100;
|
||||||
|
background: inherit;
|
||||||
|
overflow: hidden;
|
||||||
|
border: 1px solid var(--border-normal);
|
||||||
|
padding: 0.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
#eventactionspopup .icon.close {
|
||||||
|
float: right;
|
||||||
|
margin: 0.1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
#eventactionspopup button.event-action {
|
||||||
|
display: block;
|
||||||
|
cursor: pointer;
|
||||||
|
width: 3rem;
|
||||||
|
height: 3rem;
|
||||||
|
vertical-align: top;
|
||||||
|
margin: 0.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
#eventactionspopup button .action-name {
|
||||||
|
display: block;
|
||||||
|
margin-top: 0.33rem;
|
||||||
|
text-transform: uppercase;
|
||||||
|
font-size: xx-small;
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
|
let event_actions_popup;
|
||||||
|
let event_actions_popup_form;
|
||||||
|
let event_actions_popup_search_input;
|
||||||
|
let event_actions_popup_parent_id_input;
|
||||||
|
let event_actions_popup_emojis_list;
|
||||||
|
let event_actions_popup_reaction_input;
|
||||||
|
|
||||||
|
function open_event_actions_popup(event) {
|
||||||
|
const event_id = event.target?.closest("[data-event_id]")?.dataset?.event_id;
|
||||||
|
|
||||||
|
const position = get_best_coords_for_popup({
|
||||||
|
target_element: event.target,
|
||||||
|
popup: {
|
||||||
|
width: event_actions_popup_width,
|
||||||
|
height: event_actions_popup_height,
|
||||||
|
},
|
||||||
|
offset: {
|
||||||
|
x: 4,
|
||||||
|
y: 4,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
event_actions_popup.dataset.current_event_id = event_id;
|
||||||
|
event_actions_popup.style.left = position.x + "px";
|
||||||
|
event_actions_popup.style.top = position.y + "px";
|
||||||
|
|
||||||
|
event_actions_popup.style.visibility = "visible";
|
||||||
|
event_actions_popup.style.opacity = "1";
|
||||||
|
event_actions_popup.style.display = "block";
|
||||||
|
}
|
||||||
|
|
||||||
|
function clear_event_actions_popup() {
|
||||||
|
if (!event_actions_popup) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
event_actions_popup.style.visibility = "hidden";
|
||||||
|
event_actions_popup.style.opacity = "0";
|
||||||
|
event_actions_popup.style.display = "none";
|
||||||
|
}
|
||||||
|
|
||||||
|
document.addEventListener("DOMContentLoaded", () => {
|
||||||
|
if (!document.getElementById("event-actions-styling")) {
|
||||||
|
const style = document.createElement("style");
|
||||||
|
style.id = "event-actions-styling";
|
||||||
|
style.innerHTML = event_actions_popup_styling;
|
||||||
|
document.head.appendChild(style);
|
||||||
|
}
|
||||||
|
|
||||||
|
event_actions_popup = document.createElement("div");
|
||||||
|
event_actions_popup.id = "eventactionspopup";
|
||||||
|
event_actions_popup.innerHTML = `
|
||||||
|
<div class="event-actions-container">
|
||||||
|
<button
|
||||||
|
class="event-action"
|
||||||
|
data-action="react"
|
||||||
|
data-reactions
|
||||||
|
data-smart
|
||||||
|
>
|
||||||
|
<i class="icon circle"></i><span class="action-name">React</span>
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
class="event-action"
|
||||||
|
data-action="reply"
|
||||||
|
>
|
||||||
|
<i class="icon reply"></i><span class="action-name">Reply</span>
|
||||||
|
</button>
|
||||||
|
<button class="event-action mockup" data-action="forward_copy">
|
||||||
|
<i class="icon forward-copy"></i
|
||||||
|
><span class="action-name">Copy Link</span>
|
||||||
|
</button>
|
||||||
|
<button class="event-action mockup" data-action="delete">
|
||||||
|
<i class="icon trash"></i><span class="action-name">Delete</span>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
`;
|
||||||
|
|
||||||
|
document.body.appendChild(event_actions_popup);
|
||||||
|
|
||||||
|
document.querySelector("body").addEventListener("click", (event) => {
|
||||||
|
const is_in_the_event_actions_popup = event?.target?.closest("#eventactionspopup");
|
||||||
|
if (is_in_the_event_actions_popup) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const is_an_event_actions_button =
|
||||||
|
event?.target?.matches("button[commandfor]") ||
|
||||||
|
event?.target?.closest("button[commandfor]");
|
||||||
|
if (!is_an_event_actions_button) {
|
||||||
|
clear_event_actions_popup();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
event.preventDefault();
|
||||||
|
open_event_actions_popup(event);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
@ -54,44 +54,50 @@ const reactions_popup_styling = `
|
||||||
background: inherit;
|
background: inherit;
|
||||||
}
|
}
|
||||||
|
|
||||||
`;
|
.reaction-container {
|
||||||
|
display: inline-block;
|
||||||
function get_best_coords_for_popup(target, offset = { x: 10, y: 10 }) {
|
border: 1px solid var(--border-subtle);
|
||||||
const target_x = target?.getBoundingClientRect().left ?? 0;
|
border-radius: var(--border-radius);
|
||||||
const target_y = target?.getBoundingClientRect().top ?? 0;
|
margin-right: 0.5rem;
|
||||||
|
padding: 0.25rem;
|
||||||
const viewport_width = document.body.getBoundingClientRect().width;
|
font-size: large;
|
||||||
const viewport_height = document.body.getBoundingClientRect().height;
|
|
||||||
|
|
||||||
const best_coords = {
|
|
||||||
x: target_x + offset.x,
|
|
||||||
y: target_y + offset.y,
|
|
||||||
};
|
|
||||||
|
|
||||||
if (target_x + offset.x + reactions_popup_width + offset.x > viewport_width) {
|
|
||||||
best_coords.x = Math.max(0, target_x - reactions_popup_width);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (target_y + offset.y + reactions_popup_height + offset.y > viewport_height) {
|
|
||||||
best_coords.y = Math.max(0, target_y - reactions_popup_height);
|
|
||||||
}
|
|
||||||
|
|
||||||
return best_coords;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@media screen and (max-width: 480px) {
|
||||||
|
#reactionspopup {
|
||||||
|
left: 0 !important;
|
||||||
|
right: 0 !important;
|
||||||
|
bottom: 0 !important;
|
||||||
|
top: auto !important;
|
||||||
|
width: 100% !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
`;
|
||||||
|
|
||||||
let reactions_popup;
|
let reactions_popup;
|
||||||
let reactions_popup_form;
|
let reactions_popup_form;
|
||||||
|
let reactions_popup_search_input;
|
||||||
let reactions_popup_parent_id_input;
|
let reactions_popup_parent_id_input;
|
||||||
let reactions_popup_emojis_list;
|
let reactions_popup_emojis_list;
|
||||||
let reactions_popup_reaction_input;
|
let reactions_popup_reaction_input;
|
||||||
|
|
||||||
function open_reactions_popup(event) {
|
function open_reactions_popup(event) {
|
||||||
const parent_event_id = event.target?.closest("[data-event_id]")?.dataset?.event_id;
|
const parent_event_id =
|
||||||
|
event.target?.closest("[data-current_event_id]")?.dataset?.current_event_id;
|
||||||
reactions_popup_parent_id_input.value = parent_event_id ?? "";
|
reactions_popup_parent_id_input.value = parent_event_id ?? "";
|
||||||
|
|
||||||
const position = get_best_coords_for_popup(event.target.closest("[data-reactions]"), {
|
const position = get_best_coords_for_popup({
|
||||||
x: 25,
|
target_element: event.target.closest("[data-reactions]"),
|
||||||
y: 25,
|
popup: {
|
||||||
|
width: reactions_popup_width,
|
||||||
|
height: reactions_popup_height,
|
||||||
|
},
|
||||||
|
offset: {
|
||||||
|
x: 25,
|
||||||
|
y: 25,
|
||||||
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
reactions_popup.style.left = position.x + "px";
|
reactions_popup.style.left = position.x + "px";
|
||||||
|
|
@ -100,6 +106,8 @@ function open_reactions_popup(event) {
|
||||||
reactions_popup.style.visibility = "visible";
|
reactions_popup.style.visibility = "visible";
|
||||||
reactions_popup.style.opacity = "1";
|
reactions_popup.style.opacity = "1";
|
||||||
reactions_popup.style.display = "block";
|
reactions_popup.style.display = "block";
|
||||||
|
|
||||||
|
reactions_popup_search_input.focus();
|
||||||
}
|
}
|
||||||
|
|
||||||
function clear_reactions_popup() {
|
function clear_reactions_popup() {
|
||||||
|
|
@ -129,8 +137,8 @@ document.addEventListener("DOMContentLoaded", () => {
|
||||||
id="reactions-selection-form"
|
id="reactions-selection-form"
|
||||||
data-smart="true"
|
data-smart="true"
|
||||||
method="POST"
|
method="POST"
|
||||||
on_reply="async (event) => { await document.querySelectorAll( '[data-feed]' ).forEach((feed) => feed.__render(event)); }"
|
on_reply="async (event) => { clear_reactions_popup(); await document.querySelectorAll( '[data-feed]' ).forEach((feed) => feed.__render(event)); }"
|
||||||
on_parsed="async (event) => { await document.querySelectorAll( '[data-feed]' ).forEach((feed) => feed.__render(event)); }"
|
on_parsed="async (event) => { clear_reactions_popup(); await document.querySelectorAll( '[data-feed]' ).forEach((feed) => feed.__render(event)); }"
|
||||||
>
|
>
|
||||||
<input id="reactions-search-input" name="search" type="text" placeholder="Search..." data-skip="true" />
|
<input id="reactions-search-input" name="search" type="text" placeholder="Search..." data-skip="true" />
|
||||||
|
|
||||||
|
|
@ -193,6 +201,7 @@ document.addEventListener("DOMContentLoaded", () => {
|
||||||
: "";
|
: "";
|
||||||
});
|
});
|
||||||
|
|
||||||
|
reactions_popup_search_input = document.getElementById("reactions-search-input");
|
||||||
reactions_popup_parent_id_input = reactions_popup_form.querySelector('[name="parent_id"]');
|
reactions_popup_parent_id_input = reactions_popup_form.querySelector('[name="parent_id"]');
|
||||||
reactions_popup_emojis_list = document.getElementById("reactions-emojis-list");
|
reactions_popup_emojis_list = document.getElementById("reactions-emojis-list");
|
||||||
reactions_popup_reaction_input = reactions_popup_form.querySelector('[name="data.reaction"]');
|
reactions_popup_reaction_input = reactions_popup_form.querySelector('[name="data.reaction"]');
|
||||||
|
|
@ -216,14 +225,14 @@ document.addEventListener("DOMContentLoaded", () => {
|
||||||
: "";
|
: "";
|
||||||
});
|
});
|
||||||
|
|
||||||
const reactions_popup_search = debounce((event) => {
|
const debounced_search = debounce((event) => {
|
||||||
const prompt = event.target?.value;
|
const prompt = event.target?.value;
|
||||||
const filtered = EMOJIS.autocomplete(prompt);
|
const filtered = EMOJIS.autocomplete(prompt);
|
||||||
|
|
||||||
delete emojis_list.dataset.filtered;
|
delete reactions_popup_emojis_list.dataset.filtered;
|
||||||
if (filtered.length) {
|
if (filtered.length) {
|
||||||
emojis_list.dataset.filtered = true;
|
reactions_popup_emojis_list.dataset.filtered = true;
|
||||||
emojis_list.querySelectorAll("li").forEach((li) => {
|
reactions_popup_emojis_list.querySelectorAll("li").forEach((li) => {
|
||||||
if (filtered.some((entry) => entry[0] === li.dataset.emoji)) {
|
if (filtered.some((entry) => entry[0] === li.dataset.emoji)) {
|
||||||
li.dataset.filtered = true;
|
li.dataset.filtered = true;
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -233,17 +242,16 @@ document.addEventListener("DOMContentLoaded", () => {
|
||||||
}
|
}
|
||||||
}, 200);
|
}, 200);
|
||||||
|
|
||||||
document
|
reactions_popup_search_input.addEventListener("input", debounced_search);
|
||||||
.getElementById("reactions-search-input")
|
reactions_popup_search_input.addEventListener("paste", debounced_search);
|
||||||
.addEventListener("input", reactions_popup_search);
|
reactions_popup_search_input.addEventListener("change", debounced_search);
|
||||||
document
|
|
||||||
.getElementById("reactions-search-input")
|
|
||||||
.addEventListener("paste", reactions_popup_search);
|
|
||||||
document
|
|
||||||
.getElementById("reactions-search-input")
|
|
||||||
.addEventListener("change", reactions_popup_search);
|
|
||||||
|
|
||||||
document.querySelector("body").addEventListener("click", (event) => {
|
document.querySelector("body").addEventListener("click", (event) => {
|
||||||
|
const is_in_the_reactions_form = event?.target?.closest("#reactionspopup");
|
||||||
|
if (is_in_the_reactions_form) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
const is_a_data_reactions_child = event?.target?.closest("[data-reactions]");
|
const is_a_data_reactions_child = event?.target?.closest("[data-reactions]");
|
||||||
if (!is_a_data_reactions_child) {
|
if (!is_a_data_reactions_child) {
|
||||||
clear_reactions_popup();
|
clear_reactions_popup();
|
||||||
|
|
|
||||||
|
|
@ -14,6 +14,10 @@ function smarten_feeds() {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
feed.__started = false;
|
||||||
|
feed.__newest_id = undefined;
|
||||||
|
feed.__oldest_id = undefined;
|
||||||
|
|
||||||
feed.__templates = feed
|
feed.__templates = feed
|
||||||
.querySelectorAll("template[data-for_type]")
|
.querySelectorAll("template[data-for_type]")
|
||||||
.values()
|
.values()
|
||||||
|
|
@ -76,6 +80,20 @@ function smarten_feeds() {
|
||||||
|
|
||||||
feed.__autoscroll_debounce_timeout = undefined;
|
feed.__autoscroll_debounce_timeout = undefined;
|
||||||
feed.__render = async (item) => {
|
feed.__render = async (item) => {
|
||||||
|
const [item_type, item_id] = item.id?.split(":", 2) ?? [];
|
||||||
|
|
||||||
|
feed.__newest_id =
|
||||||
|
typeof item_id === "string" && item_id > (feed.__newest_id ?? "")
|
||||||
|
? item_id
|
||||||
|
: feed.__newest_id;
|
||||||
|
feed.__oldest_id =
|
||||||
|
typeof item_id === "string" &&
|
||||||
|
item_id <
|
||||||
|
(feed.__oldest_id ??
|
||||||
|
"zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz")
|
||||||
|
? item_id
|
||||||
|
: feed.__oldest_id;
|
||||||
|
|
||||||
const template = feed.__templates[item.type];
|
const template = feed.__templates[item.type];
|
||||||
if (!template) {
|
if (!template) {
|
||||||
return;
|
return;
|
||||||
|
|
@ -96,18 +114,6 @@ function smarten_feeds() {
|
||||||
`[data-temp_id='${item.temp_id ?? item.meta?.temp_id ?? ""}']`,
|
`[data-temp_id='${item.temp_id ?? item.meta?.temp_id ?? ""}']`,
|
||||||
);
|
);
|
||||||
|
|
||||||
feed.__newest_id =
|
|
||||||
typeof item.id === "string" && item.id > (feed.__newest_id ?? "")
|
|
||||||
? item.id
|
|
||||||
: feed.__newest_id;
|
|
||||||
feed.__oldest_id =
|
|
||||||
typeof item.id === "string" &&
|
|
||||||
item.id <
|
|
||||||
(feed.__oldest_id ??
|
|
||||||
"zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz")
|
|
||||||
? item.id
|
|
||||||
: feed.__oldest_id;
|
|
||||||
|
|
||||||
if (existing_element) {
|
if (existing_element) {
|
||||||
if (
|
if (
|
||||||
existing_element.id !== item.id ||
|
existing_element.id !== item.id ||
|
||||||
|
|
|
||||||
|
|
@ -106,6 +106,13 @@
|
||||||
margin: 1rem 0;
|
margin: 1rem 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.blurb-container button[commandfor="eventactionspopover"] {
|
||||||
|
position: absolute;
|
||||||
|
bottom: 0.25rem;
|
||||||
|
right: 0.25rem;
|
||||||
|
border: none;
|
||||||
|
}
|
||||||
|
|
||||||
.blurb-container .new-blurb-container {
|
.blurb-container .new-blurb-container {
|
||||||
grid-area: newblurb;
|
grid-area: newblurb;
|
||||||
display: none;
|
display: none;
|
||||||
|
|
@ -142,7 +149,7 @@
|
||||||
id="blurbs-list"
|
id="blurbs-list"
|
||||||
data-feed
|
data-feed
|
||||||
data-precheck="!!document.body.dataset.user && document.body.dataset.user.indexOf( 'topics.blurbs.read' ) !== -1"
|
data-precheck="!!document.body.dataset.user && document.body.dataset.user.indexOf( 'topics.blurbs.read' ) !== -1"
|
||||||
data-source="/api/topics/${ document.body.dataset.topic }/events?type=blurb&limit=100&sort=newest&wait=true&after_id=${ feed.__newest_id ?? 'blurb:able-able-able-able-able-able-able-able-able-able' }"
|
data-source="/api/topics/${ document.body.dataset.topic }/events?type=blurb,reaction&limit=100&sort=newest&wait=true&after_id=${ feed.__newest_id ?? 'able-able-able-able-able-able-able-able-able-able' }"
|
||||||
data-longpolling="true"
|
data-longpolling="true"
|
||||||
data-reverse="true"
|
data-reverse="true"
|
||||||
data-insert="prepend"
|
data-insert="prepend"
|
||||||
|
|
@ -162,11 +169,31 @@
|
||||||
) ?? feed
|
) ?? feed
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
feed.__target_element = (item) => {
|
||||||
|
let target = feed;
|
||||||
|
switch (item.type) {
|
||||||
|
case "reaction":
|
||||||
|
target = document.querySelector(
|
||||||
|
`.blurb-container[data-event_id='${item.parent_id}'] > .reactions-container`,
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
case "blurb":
|
||||||
|
default:
|
||||||
|
target =
|
||||||
|
document.querySelector(
|
||||||
|
`.blurb-container[data-event_id='${item.parent_id}'] > .replies-container`,
|
||||||
|
) ?? feed;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return target;
|
||||||
|
};
|
||||||
|
|
||||||
feed.__context = async (item) => {
|
feed.__context = async (item) => {
|
||||||
const blurb_datetime = datetime_to_local(item.timestamps.created);
|
const blurb_datetime = datetime_to_local(item.timestamps.created);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
event: item,
|
||||||
blurb: item,
|
blurb: item,
|
||||||
creator: await USERS.get(item.creator_id),
|
creator: await USERS.get(item.creator_id),
|
||||||
blurb_datetime
|
blurb_datetime
|
||||||
|
|
@ -199,10 +226,23 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="content-container">${htmlify(md_to_html(context.blurb.data.blurb))}</div>
|
<div class="content-container">${htmlify(md_to_html(context.blurb.data.blurb))}</div>
|
||||||
|
<div class="reactions-container"></div>
|
||||||
|
<button class="icon more" commandfor="eventactionspopover"></button>
|
||||||
<!-- #include file="./new_blurb.html" -->
|
<!-- #include file="./new_blurb.html" -->
|
||||||
<div class="replies-container"></div>
|
<div class="replies-container"></div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
<template data-for_type="reaction">
|
||||||
|
<div
|
||||||
|
id="${context.event.id}"
|
||||||
|
class="reaction-container"
|
||||||
|
data-event_id="${context.event.id}"
|
||||||
|
data-creator_id="${context.creator.id}"
|
||||||
|
data-temp_id="${context.event.meta?.temp_id ?? ''}"
|
||||||
|
>
|
||||||
|
<span class="reaction">${ context.event.data.reaction }</span>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -30,14 +30,8 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
#chat #chat-entry-container form {
|
#chat #chat-entry-container form {
|
||||||
position: absolute;
|
|
||||||
top: 0;
|
|
||||||
left: 0;
|
|
||||||
right: 0;
|
|
||||||
bottom: 0;
|
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: row;
|
flex-direction: row;
|
||||||
padding: 0.75rem;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#chat #chat-entry-container form input[type="file"] {
|
#chat #chat-entry-container form input[type="file"] {
|
||||||
|
|
@ -144,16 +138,12 @@
|
||||||
opacity: 0.75;
|
opacity: 0.75;
|
||||||
}
|
}
|
||||||
|
|
||||||
#chat .message-container .message-actions-container {
|
#chat .message-container button[commandfor] {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 0.1rem;
|
top: 0.1rem;
|
||||||
right: 0.1rem;
|
right: 0.1rem;
|
||||||
display: flex;
|
|
||||||
flex-direction: row-reverse;
|
|
||||||
border: 1px solid;
|
|
||||||
border-color: rgba(0, 0, 0, 0);
|
|
||||||
border-radius: var(--border-radius);
|
|
||||||
color: rgb(from var(--text) r g b / 0.7);
|
color: rgb(from var(--text) r g b / 0.7);
|
||||||
|
border: none;
|
||||||
z-index: 10;
|
z-index: 10;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -237,6 +227,7 @@
|
||||||
#chat .message-container .message-media-container,
|
#chat .message-container .message-media-container,
|
||||||
#chat .message-container .reactions-container {
|
#chat .message-container .reactions-container {
|
||||||
padding-left: 8rem;
|
padding-left: 8rem;
|
||||||
|
overflow-x: auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
#chat .message-container .reactions-container:has(> .reaction-container) {
|
#chat .message-container .reactions-container:has(> .reaction-container) {
|
||||||
|
|
@ -244,15 +235,6 @@
|
||||||
margin-bottom: 0.25rem;
|
margin-bottom: 0.25rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
#chat .message-container .reactions-container .reaction-container {
|
|
||||||
display: inline-block;
|
|
||||||
border: 1px solid var(--border-subtle);
|
|
||||||
border-radius: var(--border-radius);
|
|
||||||
margin-right: 0.5rem;
|
|
||||||
padding: 0.25rem;
|
|
||||||
font-size: large;
|
|
||||||
}
|
|
||||||
|
|
||||||
#chat .embed-container {
|
#chat .embed-container {
|
||||||
position: relative;
|
position: relative;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
|
|
||||||
|
|
@ -22,7 +22,7 @@
|
||||||
id="chat-content"
|
id="chat-content"
|
||||||
data-feed
|
data-feed
|
||||||
data-precheck="!!document.body.dataset.user && document.body.dataset.user.indexOf( 'topics.chat.read' ) !== -1"
|
data-precheck="!!document.body.dataset.user && document.body.dataset.user.indexOf( 'topics.chat.read' ) !== -1"
|
||||||
data-source="/api/topics/${ document.body.dataset.topic }/events?type=chat,reaction&limit=100&sort=newest&wait=true&after_id=${ feed.__newest_id ?? 'chat:able-able-able-able-able-able-able-able-able-able' }"
|
data-source="/api/topics/${ document.body.dataset.topic }/events?type=chat,reaction&limit=100&sort=newest&wait=true&after_id=${ feed.__newest_id ?? 'able-able-able-able-able-able-able-able-able-able' }"
|
||||||
data-longpolling="true"
|
data-longpolling="true"
|
||||||
data-reverse="true"
|
data-reverse="true"
|
||||||
data-insert="append"
|
data-insert="append"
|
||||||
|
|
@ -107,42 +107,7 @@
|
||||||
data-creator_id="${context.creator.id}"
|
data-creator_id="${context.creator.id}"
|
||||||
data-temp_id="${context.event.meta?.temp_id ?? ''}"
|
data-temp_id="${context.event.meta?.temp_id ?? ''}"
|
||||||
>
|
>
|
||||||
<div class="message-actions-container">
|
<button class="icon more" commandfor="eventactionspopover"></button>
|
||||||
<input
|
|
||||||
type="checkbox"
|
|
||||||
id="show_message_actions-${context.event.id}"
|
|
||||||
class="message-actions-display-toggle"
|
|
||||||
/>
|
|
||||||
<label
|
|
||||||
class="message-actions-display-toggle-label"
|
|
||||||
for="show_message_actions-${context.event.id}"
|
|
||||||
>
|
|
||||||
<div class="icon more-borderless"></div>
|
|
||||||
</label>
|
|
||||||
|
|
||||||
<button
|
|
||||||
class="message-action"
|
|
||||||
data-action="react"
|
|
||||||
data-reactions
|
|
||||||
data-smart
|
|
||||||
>
|
|
||||||
<i class="icon circle"></i><span class="action-name">React</span>
|
|
||||||
</button>
|
|
||||||
<button
|
|
||||||
class="message-action"
|
|
||||||
data-action="reply"
|
|
||||||
onclick="document.getElementById( 'parent-id' ).value = '${context.event.id}';"
|
|
||||||
>
|
|
||||||
<i class="icon reply"></i><span class="action-name">Reply</span>
|
|
||||||
</button>
|
|
||||||
<button class="message-action mockup" data-action="forward_copy">
|
|
||||||
<i class="icon forward-copy"></i
|
|
||||||
><span class="action-name">Copy Link</span>
|
|
||||||
</button>
|
|
||||||
<button class="message-action mockup" data-action="delete">
|
|
||||||
<i class="icon trash"></i><span class="action-name">Delete</span>
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
<div class="info-container">
|
<div class="info-container">
|
||||||
<div class="avatar-container inline">
|
<div class="avatar-container inline">
|
||||||
<img
|
<img
|
||||||
|
|
|
||||||
|
|
@ -78,6 +78,13 @@
|
||||||
font-size: large;
|
font-size: large;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.essay-container button[commandfor="eventactionspopover"] {
|
||||||
|
position: absolute;
|
||||||
|
bottom: 0.25rem;
|
||||||
|
right: 0.25rem;
|
||||||
|
border: none;
|
||||||
|
}
|
||||||
|
|
||||||
.essay-container .new-essay-container {
|
.essay-container .new-essay-container {
|
||||||
grid-area: newessay;
|
grid-area: newessay;
|
||||||
display: none;
|
display: none;
|
||||||
|
|
@ -109,7 +116,7 @@
|
||||||
id="essays-list"
|
id="essays-list"
|
||||||
data-feed
|
data-feed
|
||||||
data-precheck="!!document.body.dataset.user && document.body.dataset.user.indexOf( 'topics.essays.read' ) !== -1"
|
data-precheck="!!document.body.dataset.user && document.body.dataset.user.indexOf( 'topics.essays.read' ) !== -1"
|
||||||
data-source="/api/topics/${ document.body.dataset.topic }/events?type=essay&limit=100&sort=newest&wait=true&after_id=${ feed.__newest_id ?? 'essay:able-able-able-able-able-able-able-able-able-able' }"
|
data-source="/api/topics/${ document.body.dataset.topic }/events?type=essay,reaction&limit=100&sort=newest&wait=true&after_id=${ feed.__newest_id ?? 'able-able-able-able-able-able-able-able-able-able' }"
|
||||||
data-longpolling="true"
|
data-longpolling="true"
|
||||||
data-reverse="true"
|
data-reverse="true"
|
||||||
data-insert="prepend"
|
data-insert="prepend"
|
||||||
|
|
@ -127,17 +134,27 @@
|
||||||
});
|
});
|
||||||
|
|
||||||
feed.__target_element = (item) => {
|
feed.__target_element = (item) => {
|
||||||
return (
|
let target = feed;
|
||||||
document.querySelector(
|
switch (item.type) {
|
||||||
`.essay-container[data-essay_id='${item.parent_id}'] > .replies-container`,
|
case "reaction":
|
||||||
) ?? feed
|
target = document.querySelector(
|
||||||
);
|
`.essay-container[data-event_id='${item.parent_id}'] > .reactions-container`,
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
case "essay":
|
||||||
|
default:
|
||||||
|
target = feed;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return target;
|
||||||
};
|
};
|
||||||
|
|
||||||
feed.__context = async (item) => {
|
feed.__context = async (item) => {
|
||||||
const essay_datetime = datetime_to_local(item.timestamps.created);
|
const essay_datetime = datetime_to_local(item.timestamps.created);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
event: item,
|
||||||
essay: item,
|
essay: item,
|
||||||
creator: await USERS.get(item.creator_id),
|
creator: await USERS.get(item.creator_id),
|
||||||
essay_datetime,
|
essay_datetime,
|
||||||
|
|
@ -180,6 +197,19 @@
|
||||||
<div class="content-container">
|
<div class="content-container">
|
||||||
${htmlify(md_to_html(context.essay.data.essay))}
|
${htmlify(md_to_html(context.essay.data.essay))}
|
||||||
</div>
|
</div>
|
||||||
|
<div class="reactions-container"></div>
|
||||||
|
<button class="icon more" commandfor="eventactionspopover"></button>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<template data-for_type="reaction">
|
||||||
|
<div
|
||||||
|
id="${context.event.id}"
|
||||||
|
class="reaction-container"
|
||||||
|
data-event_id="${context.event.id}"
|
||||||
|
data-creator_id="${context.creator.id}"
|
||||||
|
data-temp_id="${context.event.meta?.temp_id ?? ''}"
|
||||||
|
>
|
||||||
|
<span class="reaction">${ context.event.data.reaction }</span>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -14,7 +14,7 @@
|
||||||
". . content"
|
". . content"
|
||||||
". . newpost"
|
". . newpost"
|
||||||
". . replies";
|
". . replies";
|
||||||
max-height: 6rem;
|
max-height: 8rem;
|
||||||
padding: 1rem;
|
padding: 1rem;
|
||||||
border: 1px solid var(--border-subtle);
|
border: 1px solid var(--border-subtle);
|
||||||
overflow-y: hidden;
|
overflow-y: hidden;
|
||||||
|
|
@ -111,6 +111,13 @@
|
||||||
margin-top: 2rem;
|
margin-top: 2rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.post-container button[commandfor="eventactionspopover"] {
|
||||||
|
position: absolute;
|
||||||
|
bottom: 0.25rem;
|
||||||
|
right: 0.25rem;
|
||||||
|
border: none;
|
||||||
|
}
|
||||||
|
|
||||||
.post-container .new-post-container {
|
.post-container .new-post-container {
|
||||||
grid-area: newpost;
|
grid-area: newpost;
|
||||||
}
|
}
|
||||||
|
|
@ -139,7 +146,7 @@
|
||||||
id="posts-list"
|
id="posts-list"
|
||||||
data-feed
|
data-feed
|
||||||
data-precheck="!!document.body.dataset.user && document.body.dataset.user.indexOf( 'topics.essays.read' ) !== -1"
|
data-precheck="!!document.body.dataset.user && document.body.dataset.user.indexOf( 'topics.essays.read' ) !== -1"
|
||||||
data-source="/api/topics/${ document.body.dataset.topic }/events?type=post&limit=100&sort=newest&wait=true&after_id=${ feed.__newest_id ?? 'post:able-able-able-able-able-able-able-able-able-able' }"
|
data-source="/api/topics/${ document.body.dataset.topic }/events?type=post,reaction&limit=100&sort=newest&wait=true&after_id=${ feed.__newest_id ?? 'able-able-able-able-able-able-able-able-able-able' }"
|
||||||
data-longpolling="true"
|
data-longpolling="true"
|
||||||
data-reverse="true"
|
data-reverse="true"
|
||||||
data-insert="prepend"
|
data-insert="prepend"
|
||||||
|
|
@ -157,17 +164,30 @@
|
||||||
});
|
});
|
||||||
|
|
||||||
feed.__target_element = (item) => {
|
feed.__target_element = (item) => {
|
||||||
return (
|
let target = feed;
|
||||||
document.querySelector(
|
switch (item.type) {
|
||||||
`.post-container[data-post_id='${item.parent_id}'] > .replies-container`,
|
case "reaction":
|
||||||
) ?? feed
|
target = document.querySelector(
|
||||||
);
|
`.post-container[data-event_id='${item.parent_id}'] > .reactions-container`,
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
case "chat":
|
||||||
|
default:
|
||||||
|
target =
|
||||||
|
document.querySelector(
|
||||||
|
`.post-container[data-event_id='${item.parent_id}'] > .replies-container`,
|
||||||
|
) ?? feed;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return target;
|
||||||
};
|
};
|
||||||
|
|
||||||
feed.__context = async (item) => {
|
feed.__context = async (item) => {
|
||||||
const post_datetime = datetime_to_local(item.timestamps.created);
|
const post_datetime = datetime_to_local(item.timestamps.created);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
event: item,
|
||||||
post: item,
|
post: item,
|
||||||
creator: await USERS.get(item.creator_id),
|
creator: await USERS.get(item.creator_id),
|
||||||
post_datetime,
|
post_datetime,
|
||||||
|
|
@ -215,10 +235,23 @@
|
||||||
<div class="content-container">
|
<div class="content-container">
|
||||||
${htmlify(md_to_html(context.post.data.content))}
|
${htmlify(md_to_html(context.post.data.content))}
|
||||||
</div>
|
</div>
|
||||||
|
<div class="reactions-container"></div>
|
||||||
|
<button class="icon more" commandfor="eventactionspopover"></button>
|
||||||
<!-- #include file="./new_post.html" -->
|
<!-- #include file="./new_post.html" -->
|
||||||
<div class="replies-container"></div>
|
<div class="replies-container"></div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
<template data-for_type="reaction">
|
||||||
|
<div
|
||||||
|
id="${context.event.id}"
|
||||||
|
class="reaction-container"
|
||||||
|
data-event_id="${context.event.id}"
|
||||||
|
data-creator_id="${context.creator.id}"
|
||||||
|
data-temp_id="${context.event.meta?.temp_id ?? ''}"
|
||||||
|
>
|
||||||
|
<span class="reaction">${ context.event.data.reaction }</span>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- #include file="./new_post.html" -->
|
<!-- #include file="./new_post.html" -->
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue