diff --git a/android/app/src/main/assets/public/blah/en-cat.json b/android/app/src/main/assets/public/blah/en-cat.json
index a5e5a89f..f06e9ea5 100644
--- a/android/app/src/main/assets/public/blah/en-cat.json
+++ b/android/app/src/main/assets/public/blah/en-cat.json
@@ -262,10 +262,5 @@
"action.leaving.group": "Leaving group, meow...",
"action.key.rotating": "Rotating keys, meow...",
"action.key.rotation": "Key rotation, meow",
- "desc.leave.group.confirm": "Are you sure you want to leave this group, meow?",
- "desc.key.rotation.you": "You will generate a new encryption key for this group, meow.",
- "label.keys.to.encrypt": "keys to encrypt, meow",
- "action.group.creating": "Creating group, meow...",
- "title.group.settings": "Group settings, meow",
- "title.leave.group": "Leave group, meow"
+ "desc.leave.group.confirm": "Are you sure you want to leave this group, meow?"
}
\ No newline at end of file
diff --git a/android/app/src/main/assets/public/blah/en-us.json b/android/app/src/main/assets/public/blah/en-us.json
index d9ccd071..effa6346 100644
--- a/android/app/src/main/assets/public/blah/en-us.json
+++ b/android/app/src/main/assets/public/blah/en-us.json
@@ -249,13 +249,6 @@
"group.user.joined": "Joined group",
"prompt.invite.username": "Enter username to invite:",
"desc.failed.load.members": "Failed to load members",
- "title.group.settings": "Group Settings",
- "title.group.name": "Group Name",
- "title.group.history.visible": "History visible to newcomers",
- "desc.group.history.visible": "New group members will be able to see older messages (disables key rotation)",
- "history.visible": "enabled",
- "history.hidden": "disabled",
- "group.history.changed.by": "{0} changed history visibility to: {1}",
"prompt.are.you.sure": "Are you sure?",
"title.unknown.group": "Unknown Group",
"title.unknown": "Unknown",
@@ -269,10 +262,5 @@
"action.leaving.group": "Leaving group...",
"action.key.rotating": "Rotating keys...",
"action.key.rotation": "Key rotation",
- "desc.leave.group.confirm": "Are you sure you want to leave this group?",
- "desc.key.rotation.you": "You will generate a new encryption key for this group.",
- "label.keys.to.encrypt": "keys to encrypt",
- "action.group.creating": "Creating group...",
- "title.group.settings": "Group settings",
- "title.leave.group": "Leave group"
+ "desc.leave.group.confirm": "Are you sure you want to leave this group?"
}
\ No newline at end of file
diff --git a/android/app/src/main/assets/public/blah/pl-pl.json b/android/app/src/main/assets/public/blah/pl-pl.json
index 1476621b..3a00a975 100644
--- a/android/app/src/main/assets/public/blah/pl-pl.json
+++ b/android/app/src/main/assets/public/blah/pl-pl.json
@@ -248,13 +248,6 @@
"group.user.joined": "Dołączono do grupy",
"prompt.invite.username": "Podaj nazwę użytkownika, aby zaprosić:",
"desc.failed.load.members": "Nie udało się załadować członków",
- "title.group.settings": "Ustawienia grupy",
- "title.group.name": "Nazwa grupy",
- "title.group.history.visible": "Historia widoczna dla nowych",
- "desc.group.history.visible": "Nowi członkowie grupy będą mogli zobaczyć starsze wiadomości (wyłącza rotację kluczy)",
- "history.visible": "włączona",
- "history.hidden": "wyłączona",
- "group.history.changed.by": "{0} zmienił widoczność historii na: {1}",
"prompt.are.you.sure": "Czy na pewno?",
"title.unknown.group": "Nieznana grupa",
"title.unknown": "Nieznany",
@@ -269,10 +262,5 @@
"action.leaving.group": "Opuszczanie grupy...",
"action.key.rotating": "Obracanie kluczy...",
"action.key.rotation": "Rotacja kluczy",
- "desc.leave.group.confirm": "Czy na pewno chcesz opuścić tę grupę?",
- "desc.key.rotation.you": "Wygenerujesz nowy klucz szyfrujący dla tej grupy.",
- "label.keys.to.encrypt": "kluczy do zaszyfrowania",
- "action.group.creating": "Tworzenie grupy...",
- "title.group.settings": "Ustawienia grupy",
- "title.leave.group": "Opuść grupę"
+ "desc.leave.group.confirm": "Czy na pewno chcesz opuścić tę grupę?"
}
\ No newline at end of file
diff --git a/android/app/src/main/assets/public/icons.js b/android/app/src/main/assets/public/icons.js
index ae3b562c..06596908 100644
--- a/android/app/src/main/assets/public/icons.js
+++ b/android/app/src/main/assets/public/icons.js
@@ -30,10 +30,11 @@ const ICONS = {
pin: (props) => ICONS._material(``, props),
call: (props) => ICONS._material(``, props),
account: (props) => ICONS._material(``, props),
+ settings: (props) => ICONS._material(``, props),
profile: (props) => ICONS._material(``, props),
replyAction: (props) => ICONS._material(``, props),
react: (props) => ICONS._material(``, props),
- settings: (props) => ICONS._material(``, props),
+ settingsProfile: (props) => ICONS._material(``, props),
download: (props) => ICONS._feather(``, props),
camera: (props) => ICONS._feather(``, props),
diff --git a/android/app/src/main/assets/public/index.html b/android/app/src/main/assets/public/index.html
index ace3372d..9156be42 100644
--- a/android/app/src/main/assets/public/index.html
+++ b/android/app/src/main/assets/public/index.html
@@ -256,12 +256,9 @@
const roomKey = randomRoomKey256Chars();
const selfWrapped = await wrapRoomKeyForSelf(roomKey);
- let historyVisible = document.getElementById("creategroup-history") ? document.getElementById("creategroup-history").checked.toString() : "false";
-
let payload = JSON.stringify({
string1: groupName,
- string2: selfWrapped,
- string3: historyVisible
+ string2: selfWrapped
});
let res = await fetchEncrypted("group/create", payload);
diff --git a/android/app/src/main/assets/public/main.js b/android/app/src/main/assets/public/main.js
index 3cd1e385..7a90b060 100644
--- a/android/app/src/main/assets/public/main.js
+++ b/android/app/src/main/assets/public/main.js
@@ -432,7 +432,7 @@ function showConfirmPopup(titleKey, descHtml, confirmActionKey, cancelActionKey,
let popupContainer = document.getElementById("generic-popup-container");
let popupInner = document.getElementById("generic-popup-inner");
- let confirmClass = isDestructive ? "popup-btn-danger" : "";
+ let confirmClass = isDestructive ? "popup-btn-danger" : "popup-btn-confirm";
genericPopupCancelCallback = onCancel;
@@ -449,10 +449,10 @@ function showConfirmPopup(titleKey, descHtml, confirmActionKey, cancelActionKey,
${descHtml}
-
@@ -474,7 +474,7 @@ function showPromptPopup(titleKey, descHtml, placeholderKey, confirmActionKey, c
let popupContainer = document.getElementById("generic-popup-container");
let popupInner = document.getElementById("generic-popup-inner");
- let confirmClass = isDestructive ? "popup-btn-danger" : "";
+ let confirmClass = isDestructive ? "popup-btn-danger" : "popup-btn-confirm";
genericPopupCancelCallback = onCancel;
@@ -491,15 +491,12 @@ function showPromptPopup(titleKey, descHtml, placeholderKey, confirmActionKey, c
${descHtml}
-
-
-
-
+
-
@@ -534,7 +531,7 @@ function closeRotationPopup() {
async function showRotationPopup(groupId, originalMessagePayload) {
pendingRotationMessagePayload = originalMessagePayload;
- showAction("action.key.rotating", "key_rotation");
+ showAction("action.key.rotation", "key_rotation");
try {
let membersRaw = await fetchEncrypted("group/members", groupId);
@@ -542,7 +539,7 @@ async function showRotationPopup(groupId, originalMessagePayload) {
let members = JSON.parse(membersRaw);
- let descHtml = `desc.key.rotation.you
${members.length} label.keys.to.encrypt`;
+ let descHtml = `desc.key.rotation.info
${members.length} label.members`;
showConfirmPopup(
"title.key.rotation",
@@ -560,7 +557,6 @@ async function showRotationPopup(groupId, originalMessagePayload) {
async function executeKeyRotation() {
closeRotationPopup();
- clearAction("key_rotation");
showAction("action.key.rotating", "key_rotation_exec");
try {
@@ -617,12 +613,29 @@ async function executeKeyRotation() {
clearAction("key_rotation_exec");
showBlahNotification("success:key.rotated");
+ // Retry sending the message!
+ if(pendingRotationMessagePayload) {
+ let p = pendingRotationMessagePayload;
+ p.string5 = newIndex;
+ let dmKeyBytes = await sha256Bytes(base64ToUint8(roomKey));
+ p.string2 = await encryptAesGcmToBase64(p.rawPlainContent, dmKeyBytes); // we need to save rawPlainContent for retry
+
+ showAction("action.message.sending", "msgsending");
+ let resSend = await fetchEncrypted("group/message/send", JSON.stringify(p));
+ clearAction("msgsending");
+
+ if(resSend && resSend.startsWith("error:")) {
+ showBlahNotification(resSend);
+ } else if(resSend && resSend.startsWith("success:")) {
+ loadDmMessages(currentDmId);
+ }
+ }
pendingRotationMessagePayload = null;
} catch(e) {
clearAction("key_rotation_exec");
- showBlahNotification(e.message || e);
- pendingRotationMessagePayload = null;
+ console.error(e);
+ showBlahNotification(e.message && e.message.startsWith("error:") ? e.message : "error:something.wrong");
}
}
@@ -2128,7 +2141,7 @@ async function renderInvites(res, type) {
let actions = "";
let desc = "";
- let displayName = username || onlyId;
+ let displayName = username.split(':')[0] || onlyId;
if (type === "received") {
desc = `:desc.invite.dm.received:${displayName};${onlyId}`;
actions = `
@@ -2182,7 +2195,7 @@ async function renderInvites(res, type) {
let actions = "";
let desc = "";
- let displayName = username || onlyId;
+ let displayName = username.split(':')[0] || onlyId;
let val1 = `${displayName}`;
let val2 = `${onlyId}`;
@@ -2386,13 +2399,6 @@ function gotoJoinSpace() {
}
async function gotoHome(splash = true) {
- if (dmMessagePollInterval) {
- clearInterval(dmMessagePollInterval);
- dmMessagePollInterval = null;
- }
- currentDmId = null;
- window.currentRoomType = null;
-
if (roomsBarContainer) roomsBarContainer.style.display = ""; //show roombar
setActiveSidebarIndicator(sidebarHomeIndicator);
if (splash) {
@@ -2585,8 +2591,6 @@ async function renderDms(res) {
let safeTargetUsername = encodeURIComponent(targetUsername).replace(/'/g, "%27");
- let unreadBadge = ``;
-
html += `
`;
count++;
@@ -2648,8 +2651,6 @@ async function renderGroups(res) {
let safeGroupName = encodeURIComponent(groupName).replace(/'/g, "%27");
let pfp = await getGroupAvatarUrl(groupId, groupName);
- let unreadBadge = ``;
-
html += `
`;
count++;
@@ -2742,7 +2742,7 @@ async function inviteToGroupPrompt(groupId) {
showPromptPopup(
"action.invite",
"",
- "title.username",
+ "prompt.invite.username",
"action.invite",
"action.cancel",
async (targetUsername) => {
@@ -2762,63 +2762,9 @@ async function inviteToGroupPrompt(groupId) {
try {
showAction("action.invite.sending", "invite.action");
- let keysPayload = "";
- try {
- let infoRes = await fetchEncrypted("group/info", groupId);
- if (infoRes && !infoRes.startsWith("error:")) {
- let info = JSON.parse(infoRes);
- if (info.string6 === "true") { // historyVisible
- let lastKeyIndex = parseInt(info.string4);
- if (!isNaN(lastKeyIndex)) {
- let publicKeysRaw = await fetchAsync(`${url}/user/key/getpublic?id=${targetId}`);
- if (publicKeysRaw && publicKeysRaw.length > 10) {
- let publicKeys = JSON.parse(publicKeysRaw);
- let hybrid = await deriveHybridKeyToUser(publicKeys);
- let myPublicKeysRaw = await fetchAsync(`${url}/user/key/getpublic?id=${window.id}`);
- let keysDict = {};
- let allKeysSuccess = true;
-
- for (let i = 0; i <= lastKeyIndex; i++) {
- let roomKey = await getGroupKey(groupId, i.toString());
- if (!roomKey) {
- allKeysSuccess = false;
- break;
- }
- let encForMember = await encryptAesGcmToBase64(roomKey, hybrid.aesKeyBytes);
- let setupPayloadJson = JSON.stringify({
- v: 1,
- alg: "hybrid-x25519-mlkem768",
- ctMlKem: hybrid.ciphertextMlKemBase64,
- enc: encForMember
- });
- keysDict[i.toString()] = `SETUP:${myPublicKeysRaw};${setupPayloadJson}`;
- }
-
- if (!allKeysSuccess) {
- clearAction("invite.action");
- showBlahNotification("error:failed.to.prepare.keys");
- return;
- }
- keysPayload = JSON.stringify(keysDict);
- } else {
- clearAction("invite.action");
- showBlahNotification("error:failed.to.prepare.keys");
- return;
- }
- }
- }
- }
- } catch (e) {
- console.error("Error generating keys payload for invite", e);
- clearAction("invite.action");
- showBlahNotification("error:failed.to.prepare.keys");
- return;
- }
-
let payload = JSON.stringify({
string1: groupId,
- string2: targetId,
- string3: keysPayload
+ string2: targetId
});
let res = await fetchEncrypted("group/invite", payload);
@@ -2911,10 +2857,10 @@ async function openDm(dmId, username, targetId, type = 'dms') {
let iconHtml = "";
if (type === 'dms') {
let pfp = await getAvatarUrl(targetId, username);
- iconHtml = `
`;
+ iconHtml = `
`;
} else {
let pfp = await getGroupAvatarUrl(dmId, username);
- iconHtml = `
`;
+ iconHtml = `
`;
}
if (currentRoomsBarTitle !== "title.home") {
@@ -3072,27 +3018,8 @@ async function generateMessagesHtml(entries, isPinnedContext = false) {
if (atts.length > 0) {
attachmentsHtml += ``;
for (let att of atts) {
- if (att.enc && att.enc.startsWith("ENC:")) {
- try {
- if (keyToUse) {
- let keyBytes = await sha256Bytes(base64ToUint8(keyToUse));
- let decStr = await decryptAesGcmFromBase64(att.enc.substring(4), keyBytes);
- let metadata = JSON.parse(decStr);
- att.name = metadata.name || "unknown";
- att.type = metadata.type || "application/octet-stream";
- att.size = metadata.size || 0;
- } else {
- att.name = processBlah("error:messages.decrypt.failed");
- att.type = "application/octet-stream";
- }
- } catch(e) {
- att.name = processBlah("error:messages.decrypt.failed");
- att.type = "application/octet-stream";
- }
- }
-
let attContainerId = `att-container-${msgId}-${att.id}`;
- let isMedia = att.type && (att.type.startsWith("image/") || att.type.startsWith("video/"));
+ let isMedia = att.type.startsWith("image/") || att.type.startsWith("video/");
let sizeStr = att.size ? formatBytes(att.size) : "";
let displayName = truncateFilename(att.name, 25);
let iconSvg = isMedia
@@ -3133,7 +3060,7 @@ async function generateMessagesHtml(entries, isPinnedContext = false) {
content = processBlah(content);
if (msg.type && msg.type.startsWith("larp.info")) {
- if (msg.type === "larp.info.pin" || msg.type === "larp.info.unpin" || msg.type === "larp.info.join" || msg.type === "larp.info.leave" || msg.type === "larp.info.create" || msg.type === "larp.info.history") {
+ if (msg.type === "larp.info.pin" || msg.type === "larp.info.unpin" || msg.type === "larp.info.join" || msg.type === "larp.info.leave" || msg.type === "larp.info.create") {
let authorName = processBlah("title.unknown");
if (msg.author && msg.author !== "0") {
if (!dmUsernameCache[msg.author]) {
@@ -3156,7 +3083,6 @@ async function generateMessagesHtml(entries, isPinnedContext = false) {
else if (msg.type === "larp.info.join") actionStr = "group.user.joined.by";
else if (msg.type === "larp.info.leave") actionStr = "group.user.left.by";
else if (msg.type === "larp.info.create") actionStr = "group.created.by";
- else if (msg.type === "larp.info.history") actionStr = "group.history.changed.by";
let clickableAuthor = `
${authorName}`;
@@ -3164,8 +3090,6 @@ async function generateMessagesHtml(entries, isPinnedContext = false) {
if (msg.type.endsWith(".pin") || msg.type.endsWith(".unpin")) {
let clickableMsg = `
${processBlah('title.message.lowercase')}`;
content = textStr.replace("{0}", clickableAuthor).replace("{1}", clickableMsg);
- } else if (msg.type === "larp.info.history") {
- content = textStr.replace("{0}", clickableAuthor).replace("{1}", content);
} else {
content = textStr.replace("{0}", clickableAuthor);
}
@@ -3597,10 +3521,7 @@ async function downloadAndRenderAttachment(container, msgId, attId, type, name,
}
} catch (e) {
console.error(e);
- if (window.currentRoomType === 'groups' && window.groupKeysCache[currentDmId]) {
- delete window.groupKeysCache[currentDmId][keyIndex];
- }
- container.innerHTML = `
Error loading - click to retry
`;
+ container.innerHTML = `
Error loading
`;
container.dataset.loading = "false";
}
}
@@ -3727,17 +3648,12 @@ async function sendMessage(sendbutton = document.getElementById("chat-sendmessag
}
if (decText && decText.startsWith("success:")) {
- let metadataObj = {
- type: file.type,
- name: file.name,
- size: file.size
- };
- let encMetadata = "ENC:" + await encryptAesGcmToBase64(JSON.stringify(metadataObj), dmKeyBytes);
-
attachmentsPayload.push({
id: i,
- staging_id: decText.split(":")[1],
- enc: encMetadata
+ type: file.type,
+ name: file.name,
+ size: file.size,
+ staging_id: decText.split(":")[1]
});
} else {
throw new Error(decText && decText.startsWith("error:") ? decText : "error:message.send.failed");
@@ -3755,11 +3671,9 @@ async function sendMessage(sendbutton = document.getElementById("chat-sendmessag
if (window.currentRoomType === 'groups') {
msgPayload.string5 = window.currentGroupKeyIndex || "0";
+ msgPayload.rawPlainContent = content; // for retry
}
- let savedContentForRestore = content;
- let savedAttachmentsForRestore = [...currentDraftAttachments];
-
input.value = "";
input.style.height = '2.5rem';
sendbutton.style.height = '2.5rem';
@@ -3779,13 +3693,7 @@ async function sendMessage(sendbutton = document.getElementById("chat-sendmessag
if (res && res.startsWith("error:key.rotation.required") && window.currentRoomType === 'groups') {
let pElem = document.getElementById(pendingMsgId);
if (pElem) pElem.remove();
-
- // Restore input and attachments for the user to retry manually
- input.value = savedContentForRestore;
- currentDraftAttachments = savedAttachmentsForRestore;
- renderAttachmentsPreview();
-
- showRotationPopup(currentDmId, null);
+ showRotationPopup(currentDmId, msgPayload);
} else if (res && res.startsWith("error:")) {
showBlahNotification(res);
let pElem = document.getElementById(pendingMsgId);
@@ -4374,26 +4282,17 @@ async function changePassword() {
}
async function deleteAccount() {
- showConfirmPopup(
- "title.delete.account",
- "
desc.delete.accountprompt.are.you.sure",
- "action.delete.account",
- "action.cancel",
- async () => {
- showAction("action.account.deleting", "accountdel");
- let res = await fetchPostEnc(`${url}/deleteaccount?id=${window.id}`, "");
- clearAction("accountdel");
- let text = res;
- if (text.startsWith("success:")) {
- alert(processBlah(text));
- logout();
- } else {
- showBlahNotification(text);
- }
- },
- null,
- true
- );
+ if (!confirm(processBlah("desc.delete.account") + "\n\n" + processBlah("prompt.are.you.sure"))) return;
+ showAction("action.account.deleting", "accountdel");
+ let res = await fetchPostEnc(`${url}/deleteaccount?id=${window.id}`, "");
+ clearAction("accountdel");
+ let text = res;
+ if (text.startsWith("success:")) {
+ alert(processBlah(text));
+ logout();
+ } else {
+ showBlahNotification(text);
+ }
}
async function saveProfile() {
@@ -4450,8 +4349,8 @@ function initCropper() {
let zoomSlider = document.getElementById('cropper-zoom');
// Set aspect ratio
- let targetWidth = cropperType === 'avatar' || cropperType === 'group-avatar' ? 512 : 494;
- let targetHeight = cropperType === 'avatar' || cropperType === 'group-avatar' ? targetWidth : 200;
+ let targetWidth = cropperType === 'avatar' ? 512 : 494;
+ let targetHeight = cropperType === 'avatar' ? targetWidth : 200;
let aspectRatio = targetWidth / targetHeight;
container.style.height = 'auto';
@@ -4519,8 +4418,8 @@ async function confirmCropper() {
let zoom = parseFloat(document.getElementById('cropper-zoom').value);
let container = document.getElementById('cropper-viewport-container');
- let targetWidth = cropperType === 'avatar' || cropperType === 'group-avatar' ? 512 : 988;
- let targetHeight = cropperType === 'avatar' || cropperType === 'group-avatar' ? 512 : 400;
+ let targetWidth = cropperType === 'avatar' ? 512 : 988;
+ let targetHeight = cropperType === 'avatar' ? 512 : 400;
let scaleRatio = targetWidth / container.clientWidth;
let drawX = cropperPosX * scaleRatio;
let drawY = cropperPosY * scaleRatio;
@@ -4691,20 +4590,10 @@ async function confirmCropper() {
newSrc = 'data:image/webp;base64,' + b64;
}
- let payloadKey = (cropperType === 'avatar' || cropperType === 'group-avatar') ? 'larp.profile.pfp' : 'larp.profile.banner';
+ let payloadKey = cropperType === 'avatar' ? 'larp.profile.pfp' : 'larp.profile.banner';
+ let fileBytes = base64ToUint8(b64);
showAction("action.uploading", "uploadmedia");
- let res;
- if (cropperType === 'group-avatar') {
- let payload = JSON.stringify({
- string1: window.currentSettingsGroupId,
- string2: payloadKey,
- string3: b64
- });
- res = await fetchEncrypted("group/storage/public/update", payload);
- } else {
- let fileBytes = base64ToUint8(b64);
- res = await fetchEncryptedUpload(payloadKey, fileBytes);
- }
+ let res = await fetchEncryptedUpload(payloadKey, fileBytes);
clearAction("uploadmedia");
if (res && res.startsWith("error:")) {
showBlahNotification(res);
@@ -4714,14 +4603,8 @@ async function confirmCropper() {
// Update all matching images on the page instantly
document.querySelectorAll('img').forEach(img => {
- if (cropperType === 'group-avatar') {
- if (img.src.includes(`id=${window.currentSettingsGroupId}&e=${payloadKey}`) || img.id === 'group-settings-avatar-preview') {
- img.src = newSrc;
- }
- } else {
- if (img.src.includes(`id=${window.id}&e=${payloadKey}`) || img.id === `settings-${cropperType}-preview` || (cropperType === 'avatar' && (img.id === 'my-avatar-img' || img.id === 'sidebar-pfp'))) {
- img.src = newSrc;
- }
+ if (img.src.includes(`id=${window.id}&e=${payloadKey}`) || img.id === `settings-${cropperType}-preview` || (cropperType === 'avatar' && (img.id === 'my-avatar-img' || img.id === 'sidebar-pfp'))) {
+ img.src = newSrc;
}
});
}
@@ -4790,11 +4673,6 @@ function updateDmListUI(roomId, isRead, type = 'dms', timestamp = null) {
if (nameSpan) {
nameSpan.style.opacity = isRead ? "0.8" : "1";
}
- let badge = btn.querySelector('.unread-badge');
- if (badge) {
- if (isRead) badge.classList.remove("show");
- else badge.classList.add("show");
- }
if (timestamp) {
container.prepend(btn);
}
@@ -4827,11 +4705,6 @@ function updateDmListUI(roomId, isRead, type = 'dms', timestamp = null) {
if (nameSpan) {
nameSpan.style.opacity = isRead ? "0.8" : "1";
}
- let badge = btn.querySelector('.unread-badge');
- if (badge) {
- if (isRead) badge.classList.remove("show");
- else badge.classList.add("show");
- }
if (timestamp) {
container.prepend(btn);
}
@@ -5054,48 +4927,9 @@ function handleGroupContextMenu(e, groupId) {
fixedContextMenu.style.top = `${newTop}px`;
}
-async function gotoGroupSettings(groupId) {
+function gotoGroupSettings(groupId) {
if (fixedContextMenu) fixedContextMenu.classList.remove("show");
-
- window.currentSettingsGroupId = groupId;
-
- let infoStr = await fetchEncrypted("group/info", groupId);
- if (!infoStr.startsWith("error:")) {
- let info = JSON.parse(infoStr);
- await switchRoomContent("title.group.settings", groupSettingsScreen, false);
-
- document.getElementById('group-settings-name').value = info.string2;
-
- let pfpUrl = await getGroupAvatarUrl(groupId, info.string2);
- document.getElementById('group-settings-avatar-preview').src = pfpUrl;
-
- document.getElementById('group-settings-history').checked = (info.string6 === "true");
- } else {
- showBlahNotification(infoStr);
- }
-}
-
-async function saveGroupSettings() {
- let groupId = window.currentSettingsGroupId;
- let name = document.getElementById('group-settings-name').value;
- let historyVisible = document.getElementById('group-settings-history').checked.toString();
-
- let payload = JSON.stringify({
- string1: groupId,
- string2: name,
- string3: historyVisible
- });
-
- showAction("action.saving", "savegroup");
- let res = await fetchEncrypted("group/settings/update", payload);
- clearAction("savegroup");
-
- if (res === "success") {
- showBlahNotification("success:group.settings.saved");
- refreshGroups(0, false);
- } else {
- showBlahNotification(res);
- }
+ // Not implemented yet
}
function leaveGroupPrompt(groupId) {
diff --git a/android/app/src/main/assets/public/screens.js b/android/app/src/main/assets/public/screens.js
index 02580348..8f1f7e04 100644
--- a/android/app/src/main/assets/public/screens.js
+++ b/android/app/src/main/assets/public/screens.js
@@ -31,18 +31,8 @@ var createGroupScreen = `
+
@@ -221,7 +211,7 @@ var profileContextMenu = `
title.profile
- ${ICONS.settings()}
+ ${ICONS.settingsProfile()}
title.settings
@@ -337,7 +327,7 @@ var accountSettings = `
`;
@@ -378,36 +368,6 @@ var profileSettings = `
`;
-var groupSettingsScreen = `
-
-`;
var appearanceSettings = `
diff --git a/webroot/style.css b/webroot/style.css
index 94ec00ed..d9c8260e 100644
--- a/webroot/style.css
+++ b/webroot/style.css
@@ -366,7 +366,6 @@ herotitle {
gap: 0.2rem;
width: 90%;
max-width: 30rem;
- margin: 0 auto;
}
.input-group label {
font-size: 0.75rem;
@@ -879,27 +878,35 @@ sidebarelement:has(.icon-button:active) indicator:not(.active) {
height: auto;
max-height: 85vh;
}
-button.profile-action-btn.popup-action-btn {
- flex: 1;
- display: flex;
- justify-content: center;
- margin-top: 0;
-}
-button.profile-action-btn.popup-btn-cancel {
+.popup-btn-cancel {
background: rgba(255, 255, 255, 0.05);
color: var(--text-color);
border: var(--border-width) solid var(--light-border-color);
+ flex: 1;
+ justify-content: center;
}
-button.profile-action-btn.popup-btn-cancel:hover {
+.popup-btn-cancel:hover {
background: rgba(255, 255, 255, 0.1);
}
-button.profile-action-btn.popup-btn-danger, button.submit-button.popup-btn-danger {
- background: var(--big-red) !important;
- color: white !important;
+.popup-btn-confirm {
+ background: var(--text-color);
+ color: var(--main-bg-color);
border: none;
+ flex: 1;
+ justify-content: center;
}
-button.profile-action-btn.popup-btn-danger:hover, button.submit-button.popup-btn-danger:hover {
- filter: brightness(0.85);
+.popup-btn-confirm:hover {
+ background: white;
+}
+.popup-btn-danger {
+ background: var(--big-red);
+ color: white;
+ border: none;
+ flex: 1;
+ justify-content: center;
+}
+.popup-btn-danger:hover {
+ background: #ff5252;
}
.profile-popup-container.show .profile-popup-content {
transform: scale(1);
@@ -1065,106 +1072,3 @@ body.hide-topbar-pin #roomdetailsbar roomtopbar .room-action-pin { display: flex
body.hide-topbar-call roomcontent roomtopbar .room-action-call { display: none !important; }
body.hide-topbar-call #roomdetailsbar roomtopbar .room-action-call { display: flex !important; }
-
-/* Toggle Switch */
-.toggle-switch {
- position: relative;
- display: inline-block;
- width: 3.4rem;
- height: 1.8rem;
- margin: var(--button-margin);
- flex-shrink: 0;
-
-}
-label.toggle-switch {
- opacity: 0.8;
-}
-.toggle-switch input {
- opacity: 0;
- width: 0;
- height: 0;
-}
-.toggle-slider {
- position: absolute;
- cursor: pointer;
- top: 0;
- left: 0;
- right: 0;
- bottom: 0;
- background-color: rgba(255, 255, 255, 0.1);
- transition: .4s;
- border-radius: 1.8rem;
- border: var(--border-width) solid var(--light-border-color);
-}
-.toggle-slider:before {
- position: absolute;
- content: "";
- height: 1.2rem;
- width: 1.2rem;
- left: 0.25rem;
- top: 50%;
- transform: translateY(-50%);
- background-color: var(--text-color);
- transition: .4s;
- border-radius: 50%;
-}
-input:checked + .toggle-slider {
- background-color: var(--text-color) !important;
- border-color: var(--text-color) !important;
-
-}
-input:checked + .toggle-slider:before {
- transform: translate(1.6rem, -50%);
- background-color: var(--main-bg-color) !important;
-}
-.setting-row {
- display: flex;
- justify-content: space-between;
- align-items: center;
- width: auto;
- box-sizing: border-box;
- margin: var(--button-margin);
- padding: 0.5rem;
- border-radius: 0.8rem;
- background-color: rgba(255, 255, 255, 0.02);
-}
-.setting-row:hover {
- background-color: rgba(255, 255, 255, 0.04);
-}
-.setting-info {
- display: flex;
- flex-direction: column;
- justify-content: center;
-}
-.setting-title {
- font-size: 1.1rem;
- font-weight: bold;
-}
-.setting-desc {
- font-size: 0.85rem;
- color: var(--darker-text-color);
- margin-top: 0.2rem;
-}
-
-.unread-badge {
- width: 0.65rem;
- height: 0.65rem;
- min-width: 0.65rem;
- min-height: 0.65rem;
- background-color: var(--big-red);
- border-radius: 50%;
- flex-shrink: 0;
- margin-right: 0.5rem;
- transition: transform 0.2s cubic-bezier(0.175, 0.885, 0.32, 1.275);
- transform: scale(0);
-}
-
-.unread-badge.show {
- transform: scale(1);
- animation: badge-appear 0.2s cubic-bezier(0.175, 0.885, 0.32, 1.275);
-}
-
-@keyframes badge-appear {
- 0% { transform: scale(0); }
- 100% { transform: scale(1); }
-}