From 9968e7fd205811befc768f41ff0f07f5cccb2503 Mon Sep 17 00:00:00 2001 From: olcxja Date: Thu, 23 Jul 2026 19:02:03 +0200 Subject: [PATCH] fix reactions, remove details button --- android/app/src/main/assets/public/icons.js | 4 +- android/app/src/main/assets/public/main.js | 99 ++++++++++--------- android/app/src/main/assets/public/screens.js | 17 ++-- android/app/src/main/assets/public/style.css | 7 +- webroot/icons.js | 4 +- webroot/main.js | 99 ++++++++++--------- webroot/screens.js | 17 ++-- webroot/style.css | 7 +- 8 files changed, 128 insertions(+), 126 deletions(-) diff --git a/android/app/src/main/assets/public/icons.js b/android/app/src/main/assets/public/icons.js index 706ff6bf..9d419cd5 100644 --- a/android/app/src/main/assets/public/icons.js +++ b/android/app/src/main/assets/public/icons.js @@ -47,12 +47,12 @@ const ICONS = { chevronDown: (props) => ICONS._feather(``, props), lockOpen: (props) => ICONS._feather(``, props), cornerUpLeft: (props) => ICONS._feather(``, props), - spinner: (props) => ICONS._create(``, { viewBox: "0 0 50 50", width: "24px", height: "24px", fill: "none", stroke: "none", className: "spinner" }, props), + spinner: (props) => ICONS._create(``, { viewBox: "0 0 50 50", width: "1.5rem", height: "1.5rem", fill: "none", stroke: "none", className: "spinner" }, props), video: (props) => ICONS._feather(``, props), file: (props) => ICONS._feather(``, props), - home: (props) => ICONS._create(``, { viewBox: "-1 -1 18 18", width: "24", height: "24", fill: "none", stroke: "none" }, props), + home: (props) => ICONS._create(``, { viewBox: "-1 -1 18 18", width: "1.5rem", height: "1.5rem", fill: "none", stroke: "none" }, props), inbox: (props) => ICONS._material(``, props), avatar: function(initials, color, size) { diff --git a/android/app/src/main/assets/public/main.js b/android/app/src/main/assets/public/main.js index 3e8a72e7..21860dfc 100644 --- a/android/app/src/main/assets/public/main.js +++ b/android/app/src/main/assets/public/main.js @@ -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}${processBlah(title)}
${pinCallBtns}${detailsBtnHtml}`; + let clickableContent = showRoomBar ? + `` : + ` + ${icon ? icon + '' : ''}${processBlah(title)} + `; + roomsTopBarTransition.innerHTML = `${backBtnHtml}${clickableContent}
${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 = ` `; } else { desc = `:desc.invite.dm.sent:${username};${onlyId}`; actions = ` `; } @@ -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 = `error:messages.decrypt.failed`; @@ -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 += `
@@ -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"); diff --git a/android/app/src/main/assets/public/screens.js b/android/app/src/main/assets/public/screens.js index 8073e2d4..e7994758 100644 --- a/android/app/src/main/assets/public/screens.js +++ b/android/app/src/main/assets/public/screens.js @@ -190,14 +190,14 @@ var homeRoomBar = ` var inboxRoomBar = ` @@ -266,27 +266,26 @@ var messageContextMenu = ` `; //elements -var detailsBtn = ``; -var backBtnHtml = ``; -var pinBtnHtml = ``; -var callBtnHtml = ``; +var backBtnHtml = ``; +var pinBtnHtml = ``; +var callBtnHtml = ``; var settingsBar = ` diff --git a/android/app/src/main/assets/public/style.css b/android/app/src/main/assets/public/style.css index 9de6967a..03bcfaa0 100644 --- a/android/app/src/main/assets/public/style.css +++ b/android/app/src/main/assets/public/style.css @@ -465,10 +465,6 @@ space{ background-color: rgba(255, 255, 255, 0.1); transform: var(--press-scale); } -.mobile-nav-btn.right { - margin-right: 0; - margin-left: 0.2rem; -} .mobile-nav-btn svg { width: 1.5rem; height: 1.5rem; @@ -777,6 +773,9 @@ button:active, button.is-pressed, input:active, input.is-pressed, textarea:activ background-color: rgba(255, 255, 255, 0.1); transform: var(--press-scale); } +#room-topbar-clickable { + transform: scale(1); +} .invite-actions button:active { filter: brightness(0.85); } diff --git a/webroot/icons.js b/webroot/icons.js index 706ff6bf..9d419cd5 100644 --- a/webroot/icons.js +++ b/webroot/icons.js @@ -47,12 +47,12 @@ const ICONS = { chevronDown: (props) => ICONS._feather(``, props), lockOpen: (props) => ICONS._feather(``, props), cornerUpLeft: (props) => ICONS._feather(``, props), - spinner: (props) => ICONS._create(``, { viewBox: "0 0 50 50", width: "24px", height: "24px", fill: "none", stroke: "none", className: "spinner" }, props), + spinner: (props) => ICONS._create(``, { viewBox: "0 0 50 50", width: "1.5rem", height: "1.5rem", fill: "none", stroke: "none", className: "spinner" }, props), video: (props) => ICONS._feather(``, props), file: (props) => ICONS._feather(``, props), - home: (props) => ICONS._create(``, { viewBox: "-1 -1 18 18", width: "24", height: "24", fill: "none", stroke: "none" }, props), + home: (props) => ICONS._create(``, { viewBox: "-1 -1 18 18", width: "1.5rem", height: "1.5rem", fill: "none", stroke: "none" }, props), inbox: (props) => ICONS._material(``, props), avatar: function(initials, color, size) { diff --git a/webroot/main.js b/webroot/main.js index 3e8a72e7..21860dfc 100644 --- a/webroot/main.js +++ b/webroot/main.js @@ -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}${processBlah(title)}
${pinCallBtns}${detailsBtnHtml}`; + let clickableContent = showRoomBar ? + `` : + ` + ${icon ? icon + '' : ''}${processBlah(title)} + `; + roomsTopBarTransition.innerHTML = `${backBtnHtml}${clickableContent}
${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 = ` `; } else { desc = `:desc.invite.dm.sent:${username};${onlyId}`; actions = ` `; } @@ -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 = `error:messages.decrypt.failed`; @@ -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 += `
@@ -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"); diff --git a/webroot/screens.js b/webroot/screens.js index 8073e2d4..e7994758 100644 --- a/webroot/screens.js +++ b/webroot/screens.js @@ -190,14 +190,14 @@ var homeRoomBar = ` var inboxRoomBar = ` @@ -266,27 +266,26 @@ var messageContextMenu = ` `; //elements -var detailsBtn = ``; -var backBtnHtml = ``; -var pinBtnHtml = ``; -var callBtnHtml = ``; +var backBtnHtml = ``; +var pinBtnHtml = ``; +var callBtnHtml = ``; var settingsBar = ` diff --git a/webroot/style.css b/webroot/style.css index 9de6967a..03bcfaa0 100644 --- a/webroot/style.css +++ b/webroot/style.css @@ -465,10 +465,6 @@ space{ background-color: rgba(255, 255, 255, 0.1); transform: var(--press-scale); } -.mobile-nav-btn.right { - margin-right: 0; - margin-left: 0.2rem; -} .mobile-nav-btn svg { width: 1.5rem; height: 1.5rem; @@ -777,6 +773,9 @@ button:active, button.is-pressed, input:active, input.is-pressed, textarea:activ background-color: rgba(255, 255, 255, 0.1); transform: var(--press-scale); } +#room-topbar-clickable { + transform: scale(1); +} .invite-actions button:active { filter: brightness(0.85); }