Add fetching invites

This commit is contained in:
olcxja 2026-05-21 11:02:02 +02:00
commit 81e222250d
10 changed files with 690 additions and 262 deletions

View file

@ -406,6 +406,7 @@ function showNotification(message, type = 'info', duration = 3500) {
notif.addEventListener('transitionend', () => {
notif.remove();
});
setTimeout(() => notif.remove(), 300);
}, duration);
}
@ -419,7 +420,7 @@ function showAction(message, actionid) {
}
const notif = document.createElement('div');
notif.className = `notification action`;
notif.className = `notification`;
notif.textContent = processBlah(message);
notif.id = `notification-${actionid}`;
@ -438,9 +439,10 @@ function clearAction(actionid) {
notifications.forEach(notif => {
notif.classList.remove('show');
notif.addEventListener('transitionend', () => {
notif.addEventListener('transitionend', async () => {
notif.remove();
}, { once: true });
setTimeout(() => notif.remove(), 300);
});
}
@ -596,13 +598,27 @@ async function initBlahs() {
}
}
function splitLimit(str, separator, limit) {
const parts = str.split(separator);
if (parts.length <= limit) {
return parts;
}
return [
...parts.slice(0, limit - 1),
parts.slice(limit - 1).join(separator)
];
}
function processBlah(blahmessage) {
try {
if (!blahmessage.includes(":")) {
blahmessage = `:${blahmessage}`;
}
let split = blahmessage.split(":");
let split = splitLimit(blahmessage, ":", 3);
let values = [];
try {
values = split[2].split(";");
@ -614,6 +630,11 @@ function processBlah(blahmessage) {
let valueslist = "";
for (let i = 0; i < values.length; i++) {
let value = processBlah(values[i]);
if (value.startsWith(":"))
{
value = value.substring(1);
}
valueslist+=`${value}, `;
message = message.replaceAll(`{${i}}`, value);
@ -964,60 +985,153 @@ function setActiveRoombarItem(itemId) {
}
}
async function renderInvites(res, type) {
let container = document.getElementById("invites-container");
if (!container) return;
if (res && res != "") {
res = JSON.parse(res);
let invites = [
...Object.entries(res.dms).map(([id, value]) => ({
id,
type: "dm",
...value
})),
...Object.entries(res.groups).map(([id, value]) => ({
id,
type: "group",
...value
}))
].sort((a, b) => b.timestamp - a.timestamp);
container.classList.remove("empty");
let html = "";
let count = 0;
for (let i = 0; i < invites.length; i++) {
let invite = invites[i];
if (invite.type === "dm") {
let id = invite.id;
if (!id.includes(":")) {
id += `:${host}`;
}
let username = await fetchAsync(`${url}/idtoname?id=${id}`);
if (!(username && username.trim() !== "")) return;
count++;
let pfp = await getAvatarUrl(username);
let actions = "";
let desc = "";
if (type === "received") {
desc = `:desc.invite.dm.received:${username};${id}`;
actions = `
<button class="icon-button" style="background-color: var(--big-green); border-color: transparent;" onclick="acceptInvite('${id}')">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 -960 960 960" fill="#fff"><path d="M382-240 154-468l57-57 171 171 367-367 57 57-424 424Z"/></svg>
</button>
<button class="icon-button" style="background-color: var(--big-red); border-color: transparent;" onclick="declineInvite('${id}')">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 -960 960 960" fill="#fff"><path d="m256-200-56-56 224-224-224-224 56-56 224 224 224-224 56 56-224 224 224 224-56 56-224-224-224 224Z"/></svg>
</button>
`;
} else {
desc = `:desc.invite.dm.sent:${username};${id}`;
actions = `
<button class="icon-button" style="background-color: var(--big-red); border-color: transparent;" onclick="revokeInvite('${id}')">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 -960 960 960" fill="#fff"><path d="m256-200-56-56 224-224-224-224 56-56 224 224 224-224 56 56-224 224 224 224-56 56-224-224-224 224Z"/></svg>
</button>
`;
}
let entry = invitesEntry
.replaceAll("{username}", username.split(':')[0])
.replaceAll("{pfp}", pfp)
.replaceAll("{desc}", desc)
.replaceAll("{actions}", actions);
html += entry;
}
}
if (count > 0) {
container.innerHTML = html;
} else {
container.classList.add("empty");
container.innerHTML = invitesEmptyState;
}
} else {
container.classList.add("empty");
container.innerHTML = invitesEmptyState;
}
let blahTags = container.getElementsByTagName("blah");
for (let i = 0; i < blahTags.length; i++) {
blahTags[i].innerHTML = processBlah(blahTags[i].innerHTML);
}
}
async function loadInvites(tab) {
try {
showAction(`action.fetching.invites.${tab === 'received' ? 'recv' : 'sent'}`, `fetching.invites.${tab}`);
let res = await fetchEncrypted(`user/invites/${tab}`);
await renderInvites(res, tab);
} catch (e) {
showBlahNotification("error:something.wrong");
console.error(e);
await renderInvites("", tab);
}
clearAction(`fetching.invites.${tab}`);
}
async function switchInvitesTab(tab) {
if (!document.getElementById(`tab-invites-${tab}`).classList.contains('tab-inactive')) return;
document.getElementById('tab-invites-received').classList.add('tab-inactive');
document.getElementById('tab-invites-sent').classList.add('tab-inactive');
document.getElementById(`tab-invites-${tab}`).classList.remove('tab-inactive');
let container = document.getElementById("invites-container");
let innerString = "";
if (tab === "received")
{
try {
showAction("action.fetching.invites.recv", "fetching.invites.recv");
let res = await fetchEncrypted("user/invites/received");
if (res !== "")
{
if (res.includes(",")) {
console.log(res);
}
else
{
console.log(res);
container.innerHTML = invitesEntry;
}
}
}
catch (e) {
showBlahNotification("error:something.wrong");
console.error(e);
}
clearAction("fetching.invites.recv");
await loadInvites(tab);
}
async function acceptInvite(username) { //TODO
try {
showAction("action.invite.accepting", "invite.action");
let res = await fetchEncrypted("user/dm/create", username);
clearAction("invite.action");
showBlahNotification(res || "success:invite.accepted");
await loadInvites('received');
} catch (e) {
clearAction("invite.action");
showBlahNotification("error:something.wrong");
}
else if (tab === "sent")
{
try {
showAction("action.fetching.invites.sent", "fetching.invites.sent");
let res = await fetchEncrypted("user/invites/sent");
if (res !== "")
{
if (res.includes(",")) {
console.log(res);
}
else
{
console.log(res);
container.innerHTML = invitesEntry;
}
}
}
catch (e) {
showBlahNotification("error:something.wrong");
console.error(e);
}
clearAction("fetching.invites.sent");
}
async function declineInvite(username) { //TODO
try {
showAction("action.invite.declining", "invite.action");
let res = await fetchEncrypted("user/dm/decline", username);
clearAction("invite.action");
showBlahNotification(res || "success:invite.declined");
await loadInvites('received');
} catch (e) {
clearAction("invite.action");
showBlahNotification("error:something.wrong");
}
}
async function revokeInvite(username) { //TODO
try {
showAction("action.invite.revoking", "invite.action");
let res = await fetchEncrypted("user/dm/revoke", username);
clearAction("invite.action");
showBlahNotification(res || "success:invite.revoked");
await loadInvites('sent');
} catch (e) {
clearAction("invite.action");
showBlahNotification("error:something.wrong");
}
}