@@ -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);
}