From 51951bd6ef728c2f7e40e402c5b02f0e0d42a013 Mon Sep 17 00:00:00 2001 From: olcxja Date: Mon, 17 Aug 2026 11:59:19 +0200 Subject: [PATCH] bug fixes --- .../src/main/assets/public/blah/en-cat.json | 25 ++- .../src/main/assets/public/blah/en-us.json | 28 ++- .../src/main/assets/public/blah/pl-pl.json | 26 ++- android/app/src/main/assets/public/main.js | 205 +++++++++++++++++- webroot/blah/en-cat.json | 25 ++- webroot/blah/en-us.json | 28 ++- webroot/blah/pl-pl.json | 26 ++- webroot/main.js | 205 +++++++++++++++++- 8 files changed, 540 insertions(+), 28 deletions(-) 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..ae56e047 100644 --- a/android/app/src/main/assets/public/blah/en-cat.json +++ b/android/app/src/main/assets/public/blah/en-cat.json @@ -267,5 +267,28 @@ "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" + "title.leave.group": "Leave group, meow", + "role.member": "Meowber", + "role.group_owner": "Big purr", + "role.Owner": "Big purr", + "action.kick": "Hiss and scratch from group", + "action.transfer_owner": "Give shiny toy", + "group.user.kicked.by": "{0} hissed at {1} and they ran away", + "group.owner.transferred.by": "{0} gave the shiny toy to {1}", + "group.user.kicked": "Kitty kicked", + "group.owner.transferred": "Shiny toy given", + "success:kicked": "Hissed away successfully", + "success:owner.transferred": "Toy transferred", + "error:cannot.kick.self": "You can't scratch yourself", + "action.saving": "Meowving...", + "desc.no.chat.selected": "No purr selected. Select a purr from the sidebar to start meowing.", + "failed.to.prepare.keys": "Failed to prepare meows", + "group.name.empty": "Purr name cannot be empty", + "group.refresh.failed": "Failed to refresh purr", + "group.settings.saved": "Purr settings saved successfully", + "kicked": "Bited successfully", + "message.delete.failed": "Failed to delete meow", + "message.react.failed": "Failed to react to meow", + "message.send.failed": "Failed to send meow", + "owner.transferred": "Purrship transferred successfully" } \ 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..15e60677 100644 --- a/android/app/src/main/assets/public/blah/en-us.json +++ b/android/app/src/main/assets/public/blah/en-us.json @@ -249,7 +249,7 @@ "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.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)", @@ -273,6 +273,28 @@ "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" + "title.leave.group": "Leave group", + "role.member": "Member", + "role.group_owner": "Group owner", + "role.Owner": "Owner", + "action.kick": "Kick from group", + "action.transfer_owner": "Transfer ownership", + "group.user.kicked.by": "{0} kicked {1} from the group", + "group.owner.transferred.by": "{0} transferred ownership to {1}", + "group.user.kicked": "User kicked", + "group.owner.transferred": "Ownership transferred", + "success:kicked": "User kicked successfully", + "success:owner.transferred": "Ownership transferred", + "error:cannot.kick.self": "You cannot kick yourself", + "action.saving": "Saving...", + "desc.no.chat.selected": "No chat selected. Select a chat from the sidebar to start messaging.", + "failed.to.prepare.keys": "Failed to prepare keys", + "group.name.empty": "Group name cannot be empty", + "group.refresh.failed": "Failed to refresh group", + "group.settings.saved": "Group settings saved successfully", + "kicked": "Kicked successfully", + "message.delete.failed": "Failed to delete message", + "message.react.failed": "Failed to react to message", + "message.send.failed": "Failed to send message", + "owner.transferred": "Ownership transferred successfully" } \ 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..1afbc3b1 100644 --- a/android/app/src/main/assets/public/blah/pl-pl.json +++ b/android/app/src/main/assets/public/blah/pl-pl.json @@ -273,6 +273,28 @@ "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ę" + "title.leave.group": "Opuść grupę", + "role.member": "Członek", + "role.group_owner": "Właściciel grupy", + "role.Owner": "Właściciel", + "action.kick": "Wyrzuć z grupy", + "action.transfer_owner": "Przekaż właściciela", + "group.user.kicked.by": "{0} wyrzucił/a {1} z grupy", + "group.owner.transferred.by": "{0} przekazał/a właściciela dla {1}", + "group.user.kicked": "Użytkownik wyrzucony", + "group.owner.transferred": "Właściciel przekazany", + "success:kicked": "Użytkownik wyrzucony pomyślnie", + "success:owner.transferred": "Właściciel przekazany pomyślnie", + "error:cannot.kick.self": "Nie możesz wyrzucić samego siebie", + "action.saving": "Zapisywanie...", + "desc.no.chat.selected": "Nie wybrano czatu. Wybierz czat z paska bocznego, aby rozpocząć pisanie.", + "failed.to.prepare.keys": "Nie udało się przygotować kluczy", + "group.name.empty": "Nazwa grupy nie może być pusta", + "group.refresh.failed": "Nie udało się odświeżyć grupy", + "group.settings.saved": "Ustawienia grupy zapisane pomyślnie", + "kicked": "Wyrzucono pomyślnie", + "message.delete.failed": "Nie udało się usunąć wiadomości", + "message.react.failed": "Nie udało się dodać reakcji", + "message.send.failed": "Nie udało się wysłać wiadomości", + "owner.transferred": "Własność przekazana pomyślnie" } \ No newline at end of file diff --git a/android/app/src/main/assets/public/main.js b/android/app/src/main/assets/public/main.js index 91fa2d52..8170cb93 100644 --- a/android/app/src/main/assets/public/main.js +++ b/android/app/src/main/assets/public/main.js @@ -1563,13 +1563,19 @@ async function switchRoomContent(title, content, showRoomBar, icon = "", skipMob roomsTopBarTransition.style.opacity = "0"; const rem = parseFloat(getComputedStyle(document.documentElement).fontSize); + let slideIn = false; if (window.innerWidth <= 55 * rem && !skipMobileSlide) { if (title != "title.splash") //do not show splash on mobile { + if (!mainScreen.classList.contains('mobile-content') && !mainScreen.classList.contains('mobile-details')) { + slideIn = true; + } mainScreen.classList.remove('mobile-details'); mainScreen.classList.add('mobile-content'); } - } else { + } + + if (!slideIn) { await delay(200); } @@ -1762,6 +1768,7 @@ function clearContextMenuStyles() { } document.addEventListener("click", (e) => { + if (touchContextMenuFired) return; history.pushState({trap: true}, "", location.href); if (fixedContextMenu.classList.contains("show")) { @@ -1778,7 +1785,11 @@ document.addEventListener("click", (e) => { const rem = parseFloat(getComputedStyle(document.documentElement).fontSize); if (window.innerWidth <= 55 * rem) { if (!roomDetailsBar.contains(e.target) && !e.target.closest('#room-topbar-clickable') && !e.target.closest('.profile-popup-container') && !e.target.closest('.room-action-pin')) { - mobileNavBack(); + if (currentRoomContentTitle === "title.group.settings") { + openDm(window.currentSettingsGroupId, document.getElementById('group-settings-name').value, window.currentSettingsGroupId, 'groups'); + } else { + mobileNavBack(); + } } } } @@ -1848,6 +1859,7 @@ function logout() { let isProfileOpen = false; async function openProfile(accountId) { + if (touchContextMenuFired) return; if (fixedContextMenu.classList.contains("show")) { fixedContextMenu.classList.remove("show"); if (typeof clearContextMenuStyles === "function") clearContextMenuStyles(); @@ -1969,6 +1981,19 @@ async function openProfile(accountId) { } } } + let roleHtml = ""; + if (window.currentDmId && window.currentRoomType && (window.currentRoomType === "groups" || window.currentRoomType === "dms" || window.currentRoomType === "spaces")) { + let payload = JSON.stringify({ + string1: window.currentRoomType, + string2: window.currentDmId, + string3: accountId + }); + let roleRes = await fetchEncrypted("room/role", payload); + if (roleRes && !roleRes.startsWith("error:")) { + let mappedRole = "role." + roleRes.replace(" ", "_"); + roleHtml = `
${mappedRole}
`; + } + } popupInner.innerHTML = ` ${bannerHtml} @@ -1979,6 +2004,7 @@ async function openProfile(accountId) {
${profileName}
${profileName}:${profileHost} (${accountId.split(':')[0].split(';')[0]})
+ ${roleHtml}
${bioHtml} ${actionBtnHtml} @@ -2423,6 +2449,11 @@ function setActiveSidebarIndicator(element, isTemporary = false) { } function mobileNavBack() { + if (currentRoomContentTitle === "title.group.settings") { + openDm(window.currentSettingsGroupId, document.getElementById('group-settings-name').value, window.currentSettingsGroupId, 'groups'); + return; + } + if (mainScreen.classList.contains('mobile-details')) { mainScreen.classList.remove('mobile-details'); mainScreen.classList.add('mobile-content'); @@ -2512,6 +2543,7 @@ document.addEventListener('touchend', async (e) => { } let elapsed = Date.now() - pressDate; //najgorszy fix swiata + if (elapsed < 100) { const remaining = 100 - elapsed; await delay(remaining); @@ -2861,7 +2893,7 @@ async function generateGroupMembersHtml(groupId, groupName) { let memberDisplayName = memberUsername.split(':')[0]; html += ` - + + `; + } + + if (html !== '') { + let clientX = e.clientX !== undefined ? e.clientX : (e.touches && e.touches.length > 0 ? e.touches[0].clientX : 0); + let clientY = e.clientY !== undefined ? e.clientY : (e.touches && e.touches.length > 0 ? e.touches[0].clientY : 0); + showFixedContextMenu({top: clientY, right: clientX, bottom: clientY, left: clientX}, html); + } +} + +async function kickFromGroup(groupId, memberId) { + if (fixedContextMenu.classList.contains("show")) { + fixedContextMenu.classList.remove("show"); + } + + showAction("action.processing", "kick.action"); + let payload = JSON.stringify({ + string1: groupId, + string2: memberId + }); + + let res = await fetchEncrypted("group/kick", payload); + clearAction("kick.action"); + + if (res && res.startsWith("success")) { + showBlahNotification("success:kicked"); + showGroupMembers(groupId).then(html => { + let container = document.getElementById("right-sidebar-container"); + if (container) { + container.innerHTML = html; + translate(container); + } + }); + } else { + showBlahNotification(res || "error:something.wrong"); + } +} + +async function transferGroupOwnership(groupId, memberId) { + if (fixedContextMenu.classList.contains("show")) { + fixedContextMenu.classList.remove("show"); + } + + showAction("action.processing", "transfer.action"); + let payload = JSON.stringify({ + string1: groupId, + string2: memberId + }); + + let res = await fetchEncrypted("group/transferowner", payload); + clearAction("transfer.action"); + + if (res && res.startsWith("success")) { + window.currentGroupOwner = memberId; + showBlahNotification("success:owner.transferred"); + showGroupMembers(groupId).then(html => { + let container = document.getElementById("right-sidebar-container"); + if (container) { + container.innerHTML = html; + translate(container); + } + }); + } else { + showBlahNotification(res || "error:something.wrong"); + } +} + function handleGroupContextMenu(e, groupId) { if (e) { e.preventDefault(); @@ -5020,6 +5184,10 @@ function handleGroupContextMenu(e, groupId) { } if (typeof clearContextMenuStyles === "function") clearContextMenuStyles(); currentContextMenuGroupId = groupId; + if (e && e.type === "contextmenu") { + touchContextMenuFired = true; + setTimeout(() => { touchContextMenuFired = false; }, 500); + } let btn = e ? (e.currentTarget || e.target) : null; let rect; @@ -5062,6 +5230,8 @@ async function gotoGroupSettings(groupId) { let infoStr = await fetchEncrypted("group/info", groupId); if (!infoStr.startsWith("error:")) { let info = JSON.parse(infoStr); + window.currentGroupOwner = info.string7; + await switchRoomContent("title.group.settings", groupSettingsScreen, false); document.getElementById('group-settings-name').value = info.string2; @@ -5070,6 +5240,19 @@ async function gotoGroupSettings(groupId) { document.getElementById('group-settings-avatar-preview').src = pfpUrl; document.getElementById('group-settings-history').checked = (info.string6 === "true"); + + let myIdStr = window.id + ";" + window.host; + let historyCheckbox = document.getElementById('group-settings-history'); + let historyContainer = historyCheckbox.closest('.setting-row'); + if (historyContainer) { + if (window.currentGroupOwner !== myIdStr) { + historyContainer.style.display = 'none'; + } else { + historyContainer.style.display = 'flex'; + } + } else { + historyCheckbox.disabled = (window.currentGroupOwner !== myIdStr); + } } else { showBlahNotification(infoStr); } @@ -5120,7 +5303,13 @@ async function confirmLeaveGroup(groupId) { let res = await fetchEncrypted("group/leave", payload); if (res === "success") { if (currentDmId === groupId) { - gotoHome(); + currentDmId = null; + const rem = parseFloat(getComputedStyle(document.documentElement).fontSize); + if (window.innerWidth <= 55 * rem) { + mobileNavBack(); + } else { + gotoHome(); + } } refreshGroups(0, false); } else if (res.startsWith("error:")) { diff --git a/webroot/blah/en-cat.json b/webroot/blah/en-cat.json index a5e5a89f..ae56e047 100644 --- a/webroot/blah/en-cat.json +++ b/webroot/blah/en-cat.json @@ -267,5 +267,28 @@ "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" + "title.leave.group": "Leave group, meow", + "role.member": "Meowber", + "role.group_owner": "Big purr", + "role.Owner": "Big purr", + "action.kick": "Hiss and scratch from group", + "action.transfer_owner": "Give shiny toy", + "group.user.kicked.by": "{0} hissed at {1} and they ran away", + "group.owner.transferred.by": "{0} gave the shiny toy to {1}", + "group.user.kicked": "Kitty kicked", + "group.owner.transferred": "Shiny toy given", + "success:kicked": "Hissed away successfully", + "success:owner.transferred": "Toy transferred", + "error:cannot.kick.self": "You can't scratch yourself", + "action.saving": "Meowving...", + "desc.no.chat.selected": "No purr selected. Select a purr from the sidebar to start meowing.", + "failed.to.prepare.keys": "Failed to prepare meows", + "group.name.empty": "Purr name cannot be empty", + "group.refresh.failed": "Failed to refresh purr", + "group.settings.saved": "Purr settings saved successfully", + "kicked": "Bited successfully", + "message.delete.failed": "Failed to delete meow", + "message.react.failed": "Failed to react to meow", + "message.send.failed": "Failed to send meow", + "owner.transferred": "Purrship transferred successfully" } \ No newline at end of file diff --git a/webroot/blah/en-us.json b/webroot/blah/en-us.json index d9ccd071..15e60677 100644 --- a/webroot/blah/en-us.json +++ b/webroot/blah/en-us.json @@ -249,7 +249,7 @@ "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.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)", @@ -273,6 +273,28 @@ "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" + "title.leave.group": "Leave group", + "role.member": "Member", + "role.group_owner": "Group owner", + "role.Owner": "Owner", + "action.kick": "Kick from group", + "action.transfer_owner": "Transfer ownership", + "group.user.kicked.by": "{0} kicked {1} from the group", + "group.owner.transferred.by": "{0} transferred ownership to {1}", + "group.user.kicked": "User kicked", + "group.owner.transferred": "Ownership transferred", + "success:kicked": "User kicked successfully", + "success:owner.transferred": "Ownership transferred", + "error:cannot.kick.self": "You cannot kick yourself", + "action.saving": "Saving...", + "desc.no.chat.selected": "No chat selected. Select a chat from the sidebar to start messaging.", + "failed.to.prepare.keys": "Failed to prepare keys", + "group.name.empty": "Group name cannot be empty", + "group.refresh.failed": "Failed to refresh group", + "group.settings.saved": "Group settings saved successfully", + "kicked": "Kicked successfully", + "message.delete.failed": "Failed to delete message", + "message.react.failed": "Failed to react to message", + "message.send.failed": "Failed to send message", + "owner.transferred": "Ownership transferred successfully" } \ No newline at end of file diff --git a/webroot/blah/pl-pl.json b/webroot/blah/pl-pl.json index 1476621b..1afbc3b1 100644 --- a/webroot/blah/pl-pl.json +++ b/webroot/blah/pl-pl.json @@ -273,6 +273,28 @@ "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ę" + "title.leave.group": "Opuść grupę", + "role.member": "Członek", + "role.group_owner": "Właściciel grupy", + "role.Owner": "Właściciel", + "action.kick": "Wyrzuć z grupy", + "action.transfer_owner": "Przekaż właściciela", + "group.user.kicked.by": "{0} wyrzucił/a {1} z grupy", + "group.owner.transferred.by": "{0} przekazał/a właściciela dla {1}", + "group.user.kicked": "Użytkownik wyrzucony", + "group.owner.transferred": "Właściciel przekazany", + "success:kicked": "Użytkownik wyrzucony pomyślnie", + "success:owner.transferred": "Właściciel przekazany pomyślnie", + "error:cannot.kick.self": "Nie możesz wyrzucić samego siebie", + "action.saving": "Zapisywanie...", + "desc.no.chat.selected": "Nie wybrano czatu. Wybierz czat z paska bocznego, aby rozpocząć pisanie.", + "failed.to.prepare.keys": "Nie udało się przygotować kluczy", + "group.name.empty": "Nazwa grupy nie może być pusta", + "group.refresh.failed": "Nie udało się odświeżyć grupy", + "group.settings.saved": "Ustawienia grupy zapisane pomyślnie", + "kicked": "Wyrzucono pomyślnie", + "message.delete.failed": "Nie udało się usunąć wiadomości", + "message.react.failed": "Nie udało się dodać reakcji", + "message.send.failed": "Nie udało się wysłać wiadomości", + "owner.transferred": "Własność przekazana pomyślnie" } \ No newline at end of file diff --git a/webroot/main.js b/webroot/main.js index 91fa2d52..8170cb93 100644 --- a/webroot/main.js +++ b/webroot/main.js @@ -1563,13 +1563,19 @@ async function switchRoomContent(title, content, showRoomBar, icon = "", skipMob roomsTopBarTransition.style.opacity = "0"; const rem = parseFloat(getComputedStyle(document.documentElement).fontSize); + let slideIn = false; if (window.innerWidth <= 55 * rem && !skipMobileSlide) { if (title != "title.splash") //do not show splash on mobile { + if (!mainScreen.classList.contains('mobile-content') && !mainScreen.classList.contains('mobile-details')) { + slideIn = true; + } mainScreen.classList.remove('mobile-details'); mainScreen.classList.add('mobile-content'); } - } else { + } + + if (!slideIn) { await delay(200); } @@ -1762,6 +1768,7 @@ function clearContextMenuStyles() { } document.addEventListener("click", (e) => { + if (touchContextMenuFired) return; history.pushState({trap: true}, "", location.href); if (fixedContextMenu.classList.contains("show")) { @@ -1778,7 +1785,11 @@ document.addEventListener("click", (e) => { const rem = parseFloat(getComputedStyle(document.documentElement).fontSize); if (window.innerWidth <= 55 * rem) { if (!roomDetailsBar.contains(e.target) && !e.target.closest('#room-topbar-clickable') && !e.target.closest('.profile-popup-container') && !e.target.closest('.room-action-pin')) { - mobileNavBack(); + if (currentRoomContentTitle === "title.group.settings") { + openDm(window.currentSettingsGroupId, document.getElementById('group-settings-name').value, window.currentSettingsGroupId, 'groups'); + } else { + mobileNavBack(); + } } } } @@ -1848,6 +1859,7 @@ function logout() { let isProfileOpen = false; async function openProfile(accountId) { + if (touchContextMenuFired) return; if (fixedContextMenu.classList.contains("show")) { fixedContextMenu.classList.remove("show"); if (typeof clearContextMenuStyles === "function") clearContextMenuStyles(); @@ -1969,6 +1981,19 @@ async function openProfile(accountId) { } } } + let roleHtml = ""; + if (window.currentDmId && window.currentRoomType && (window.currentRoomType === "groups" || window.currentRoomType === "dms" || window.currentRoomType === "spaces")) { + let payload = JSON.stringify({ + string1: window.currentRoomType, + string2: window.currentDmId, + string3: accountId + }); + let roleRes = await fetchEncrypted("room/role", payload); + if (roleRes && !roleRes.startsWith("error:")) { + let mappedRole = "role." + roleRes.replace(" ", "_"); + roleHtml = `
${mappedRole}
`; + } + } popupInner.innerHTML = ` ${bannerHtml} @@ -1979,6 +2004,7 @@ async function openProfile(accountId) {
${profileName}
${profileName}:${profileHost} (${accountId.split(':')[0].split(';')[0]})
+ ${roleHtml}
${bioHtml} ${actionBtnHtml} @@ -2423,6 +2449,11 @@ function setActiveSidebarIndicator(element, isTemporary = false) { } function mobileNavBack() { + if (currentRoomContentTitle === "title.group.settings") { + openDm(window.currentSettingsGroupId, document.getElementById('group-settings-name').value, window.currentSettingsGroupId, 'groups'); + return; + } + if (mainScreen.classList.contains('mobile-details')) { mainScreen.classList.remove('mobile-details'); mainScreen.classList.add('mobile-content'); @@ -2512,6 +2543,7 @@ document.addEventListener('touchend', async (e) => { } let elapsed = Date.now() - pressDate; //najgorszy fix swiata + if (elapsed < 100) { const remaining = 100 - elapsed; await delay(remaining); @@ -2861,7 +2893,7 @@ async function generateGroupMembersHtml(groupId, groupName) { let memberDisplayName = memberUsername.split(':')[0]; html += ` - + + `; + } + + if (html !== '') { + let clientX = e.clientX !== undefined ? e.clientX : (e.touches && e.touches.length > 0 ? e.touches[0].clientX : 0); + let clientY = e.clientY !== undefined ? e.clientY : (e.touches && e.touches.length > 0 ? e.touches[0].clientY : 0); + showFixedContextMenu({top: clientY, right: clientX, bottom: clientY, left: clientX}, html); + } +} + +async function kickFromGroup(groupId, memberId) { + if (fixedContextMenu.classList.contains("show")) { + fixedContextMenu.classList.remove("show"); + } + + showAction("action.processing", "kick.action"); + let payload = JSON.stringify({ + string1: groupId, + string2: memberId + }); + + let res = await fetchEncrypted("group/kick", payload); + clearAction("kick.action"); + + if (res && res.startsWith("success")) { + showBlahNotification("success:kicked"); + showGroupMembers(groupId).then(html => { + let container = document.getElementById("right-sidebar-container"); + if (container) { + container.innerHTML = html; + translate(container); + } + }); + } else { + showBlahNotification(res || "error:something.wrong"); + } +} + +async function transferGroupOwnership(groupId, memberId) { + if (fixedContextMenu.classList.contains("show")) { + fixedContextMenu.classList.remove("show"); + } + + showAction("action.processing", "transfer.action"); + let payload = JSON.stringify({ + string1: groupId, + string2: memberId + }); + + let res = await fetchEncrypted("group/transferowner", payload); + clearAction("transfer.action"); + + if (res && res.startsWith("success")) { + window.currentGroupOwner = memberId; + showBlahNotification("success:owner.transferred"); + showGroupMembers(groupId).then(html => { + let container = document.getElementById("right-sidebar-container"); + if (container) { + container.innerHTML = html; + translate(container); + } + }); + } else { + showBlahNotification(res || "error:something.wrong"); + } +} + function handleGroupContextMenu(e, groupId) { if (e) { e.preventDefault(); @@ -5020,6 +5184,10 @@ function handleGroupContextMenu(e, groupId) { } if (typeof clearContextMenuStyles === "function") clearContextMenuStyles(); currentContextMenuGroupId = groupId; + if (e && e.type === "contextmenu") { + touchContextMenuFired = true; + setTimeout(() => { touchContextMenuFired = false; }, 500); + } let btn = e ? (e.currentTarget || e.target) : null; let rect; @@ -5062,6 +5230,8 @@ async function gotoGroupSettings(groupId) { let infoStr = await fetchEncrypted("group/info", groupId); if (!infoStr.startsWith("error:")) { let info = JSON.parse(infoStr); + window.currentGroupOwner = info.string7; + await switchRoomContent("title.group.settings", groupSettingsScreen, false); document.getElementById('group-settings-name').value = info.string2; @@ -5070,6 +5240,19 @@ async function gotoGroupSettings(groupId) { document.getElementById('group-settings-avatar-preview').src = pfpUrl; document.getElementById('group-settings-history').checked = (info.string6 === "true"); + + let myIdStr = window.id + ";" + window.host; + let historyCheckbox = document.getElementById('group-settings-history'); + let historyContainer = historyCheckbox.closest('.setting-row'); + if (historyContainer) { + if (window.currentGroupOwner !== myIdStr) { + historyContainer.style.display = 'none'; + } else { + historyContainer.style.display = 'flex'; + } + } else { + historyCheckbox.disabled = (window.currentGroupOwner !== myIdStr); + } } else { showBlahNotification(infoStr); } @@ -5120,7 +5303,13 @@ async function confirmLeaveGroup(groupId) { let res = await fetchEncrypted("group/leave", payload); if (res === "success") { if (currentDmId === groupId) { - gotoHome(); + currentDmId = null; + const rem = parseFloat(getComputedStyle(document.documentElement).fontSize); + if (window.innerWidth <= 55 * rem) { + mobileNavBack(); + } else { + gotoHome(); + } } refreshGroups(0, false); } else if (res.startsWith("error:")) {