fix reactions, remove details button
All checks were successful
Android Build / publish (push) Successful in 55s
Linux Build / publish (push) Successful in 58s

This commit is contained in:
olcxja 2026-07-23 19:02:03 +02:00
commit 9968e7fd20
8 changed files with 128 additions and 126 deletions

View file

@ -1303,10 +1303,17 @@ async function switchRoomContent(title, content, showRoomBar, icon = "", skipMob
}
let detailsBtnHtml = showRoomBar ? detailsBtn : '';
let pinCallBtns = showRoomBar ? `${pinBtnHtml}${callBtnHtml}` : '';
roomsTopBarTransition.innerHTML = `${backBtnHtml}${icon}<space></space><inherit>${processBlah(title)}</inherit><div class="flex-spacer"></div>${pinCallBtns}${detailsBtnHtml}`;
let clickableContent = showRoomBar ?
`<button id="room-topbar-clickable" class="inherit" onclick="mobileNavDetails();" style="cursor: pointer; display: flex; align-items: center; border-radius: 0.65rem; background: transparent; outline: none; height: 100%; text-align: left;">
${icon ? icon + '<space></space>' : ''}<inherit>${processBlah(title)}</inherit>
</button>` :
`<inherit style="display: flex; align-items: center; height: 100%;">
${icon ? icon + '<space></space>' : ''}<inherit>${processBlah(title)}</inherit>
</inherit>`;
roomsTopBarTransition.innerHTML = `${backBtnHtml}${clickableContent}<div class="flex-spacer"></div>${pinCallBtns}`;
roomDetailsBar.style.display = showRoomBar ? "flex" : "none";
let parser = new DOMParser();
@ -1488,7 +1495,7 @@ document.addEventListener("click", (e) => {
if (mainScreen && mainScreen.classList.contains('mobile-details')) {
const rem = parseFloat(getComputedStyle(document.documentElement).fontSize);
if (window.innerWidth <= 55 * rem) {
if (!roomDetailsBar.contains(e.target) && !e.target.closest('.mobile-nav-btn.right') && !e.target.closest('.profile-popup-container')) {
if (!roomDetailsBar.contains(e.target) && !e.target.closest('#room-topbar-clickable') && !e.target.closest('.profile-popup-container')) {
mobileNavBack();
}
}
@ -1752,17 +1759,17 @@ async function renderInvites(res, type) {
desc = `:desc.invite.dm.received:${username};${onlyId}`;
actions = `
<button class="icon-button" style="background-color: var(--big-green);" onclick="acceptInvite('${id}')">
${ICONS.check({ fill: "#fff", width: "24", height: "24" })}
${ICONS.check({ fill: "#fff", width: "1.5rem", height: "1.5rem" })}
</button>
<button class="icon-button" style="background-color: var(--big-red);" onclick="declineInvite('${id}')">
${ICONS.close({ fill: "#fff", width: "24", height: "24" })}
${ICONS.close({ fill: "#fff", width: "1.5rem", height: "1.5rem" })}
</button>
`;
} else {
desc = `:desc.invite.dm.sent:${username};${onlyId}`;
actions = `
<button class="icon-button" style="background-color: var(--big-red);" onclick="revokeInvite('${id}')">
${ICONS.close({ fill: "#fff", width: "24", height: "24" })}
${ICONS.close({ fill: "#fff", width: "1.5rem", height: "1.5rem" })}
</button>
`;
}
@ -2062,11 +2069,12 @@ document.addEventListener('touchend', async (e) => {
}
}
let elapsed = Date.now() - pressDate; //nie pomoglo ale zostawie
let elapsed = Date.now() - pressDate; //najgorszy fix swiata
if (elapsed < 100) {
const remaining = 100 - elapsed;
await delay(remaining);
}
activeTouchButton.classList.remove('is-pressed');
activeTouchButton = null;
@ -2351,7 +2359,6 @@ async function renderMessages(messages, isPrepend = false) {
try {
let dmKeyBytes = await sha256Bytes(base64ToUint8(currentDmKey));
content = await decryptAesGcmFromBase64(content, dmKeyBytes);
if (reactions) reactions = await decryptAesGcmFromBase64(reactions, dmKeyBytes);
decrypted = true;
} catch (e) {
content = `<span style="color:var(--big-red)"><blah>error:messages.decrypt.failed</blah></span>`;
@ -2363,7 +2370,7 @@ async function renderMessages(messages, isPrepend = false) {
let isRedacted = msg.type === "larp.redacted";
let redactedStyle = isRedacted ? ` opacity: 0.5; font-style: italic;` : ``;
let redactedIcon = isRedacted ? `${ICONS.delete({ fill: "currentColor", width: "24", height: "1rem", style: "vertical-align: -0.165em; margin-right: 0.2rem;" })}` : ``;
let redactedIcon = isRedacted ? `${ICONS.delete({ fill: "currentColor", width: "1.5rem", height: "1rem", style: "vertical-align: -0.165em; margin-right: 0.2rem;" })}` : ``;
let attachmentsHtml = "";
if (msg.attachment && msg.attachment !== "") {
@ -2378,8 +2385,8 @@ async function renderMessages(messages, isPrepend = false) {
let sizeStr = att.size ? formatBytes(att.size) : "";
let displayName = truncateFilename(att.name, 25);
let iconSvg = isMedia
? `${ICONS.image({ width: "24", height: "24", stroke: "currentColor" })}`
: `${ICONS.download({ width: "24", height: "24", stroke: "currentColor" })}`;
? `${ICONS.image({ width: "1.5rem", height: "1.5rem", stroke: "currentColor" })}`
: `${ICONS.download({ width: "1.5rem", height: "1.5rem", stroke: "currentColor" })}`;
attachmentsHtml += `<div id="${attContainerId}" class="attachment-box" style="position: relative; min-width: 120px; max-width: 300px; min-height: 100px; max-height: 300px; background: rgba(0,0,0,0.2); border: 1px solid var(--border-color); border-radius: 8px; display: flex; align-items: center; justify-content: center; cursor: pointer; overflow: hidden;" onclick="downloadAndRenderAttachment('${msgId}', '${att.id}', '${escapeHtml(att.type)}', '${escapeHtml(att.name)}')">
<div style="padding: 1rem; text-align: center; color: var(--text-color);">
@ -2532,12 +2539,19 @@ async function renderMessages(messages, isPrepend = false) {
if (rxArr.length > 0) {
let rxCounts = {};
for (let rx of rxArr) {
let parts = rx.split(':');
if (parts.length < 2) continue;
let rxVal = parts.slice(1).join(':');
if (!rxCounts[rxVal]) rxCounts[rxVal] = {count: 0, me: false};
let rxVal = rx.r;
if (msg.key && msg.key !== "") {
try {
let dmKeyBytes = await sha256Bytes(base64ToUint8(currentDmKey));
rxVal = await decryptAesGcmFromBase64(rxVal, dmKeyBytes);
} catch(e) {}
}
if (!rxCounts[rxVal]) rxCounts[rxVal] = {count: 0, me: false, myReactionId: null};
rxCounts[rxVal].count++;
if (parts[0] === id) rxCounts[rxVal].me = true;
if (rx.u === id) {
rxCounts[rxVal].me = true;
rxCounts[rxVal].myReactionId = rx.id;
}
}
let rxKeys = Object.keys(rxCounts);
@ -3290,52 +3304,41 @@ async function reactMessagePrompt(msgId, quickReaction = null) {
showNotification(processBlah("error.message.already.deleted"), "error");
return;
}
let existingReactions = [];
let myReactionId = null;
if (currentMsg && currentMsg.reactions) {
let rxStr = currentMsg.reactions;
if (currentMsg.key && currentMsg.key !== "") {
let dmKeyBytes = await sha256Bytes(base64ToUint8(currentDmKey));
try {
rxStr = await decryptAesGcmFromBase64(rxStr, dmKeyBytes);
} catch (e) {
}
}
try {
existingReactions = JSON.parse(rxStr);
let rxArr = JSON.parse(currentMsg.reactions);
for (let rx of rxArr) {
let rxVal = rx.r;
if (currentMsg.key && currentMsg.key !== "") {
try {
let dmKeyBytes = await sha256Bytes(base64ToUint8(currentDmKey));
rxVal = await decryptAesGcmFromBase64(rxVal, dmKeyBytes);
} catch(e) {}
}
if (rx.u === id && rxVal === reaction) {
myReactionId = rx.id;
break;
}
}
} catch (e) {
}
}
let targetEntry = id + ":" + reaction;
let index = existingReactions.indexOf(targetEntry);
if (index > -1) {
existingReactions.splice(index, 1);
} else {
existingReactions.push(targetEntry);
}
let isAdding = (myReactionId === null);
let dmKeyBytes = await sha256Bytes(base64ToUint8(currentDmKey));
let encryptedReactions = await encryptAesGcmToBase64(JSON.stringify(existingReactions), dmKeyBytes);
let originalReactionsEncrypted = "";
if (currentMsg) {
originalReactionsEncrypted = currentMsg.reactions || "";
currentMsg.reactions = encryptedReactions;
renderMessages(loadedMessages);
}
let encryptedReaction = await encryptAesGcmToBase64(reaction, dmKeyBytes);
let endpoint = isAdding ? "dm/message/react/add" : "dm/message/react/remove";
let msgPayload = {
string1: currentDmId,
string2: msgId,
string3: encryptedReactions
string3: isAdding ? encryptedReaction : myReactionId
};
let res = await fetchEncrypted("dm/message/react", JSON.stringify(msgPayload));
let res = await fetchEncrypted(endpoint, JSON.stringify(msgPayload));
if (res && res.startsWith("error:")) {
showBlahNotification(res);
if (currentMsg) {
currentMsg.reactions = originalReactionsEncrypted;
renderMessages(loadedMessages);
}
}
} catch (e) {
showBlahNotification("error:message.react.failed");