add group context menu
This commit is contained in:
parent
ab99a84579
commit
891f39e5b1
4 changed files with 236 additions and 2 deletions
|
|
@ -1554,6 +1554,9 @@ async function switchDetailsContent(title, content, showBack = false, backAction
|
|||
|
||||
|
||||
let pinCallBtns = showBack ? `${callBtnHtml}` : `${pinBtnHtml}${callBtnHtml}`;
|
||||
if (window.currentRoomType === 'groups' && !showBack) {
|
||||
pinCallBtns = `${groupMenuBtnHtml}${pinCallBtns}`;
|
||||
}
|
||||
let backBtn = showBack ? `<button class="topbar-action-btn" onclick="${backAction}" style="margin-right: 0.5rem">${ICONS.arrowBack({ width: "1.5rem", height: "1.5rem" })}</button>` : "";
|
||||
roomsTopBarTransition.innerHTML = `<inherit style="display: flex; align-items: center;">${backBtn}<inherit>${processBlah(title)}</inherit></inherit><div class="flex-spacer"></div>${pinCallBtns}`;
|
||||
|
||||
|
|
@ -2542,7 +2545,7 @@ async function renderGroups(res) {
|
|||
let pfp = await getGroupAvatarUrl(groupId, groupName);
|
||||
|
||||
html += `
|
||||
<button class="room-entry" id="group-btn-${groupId}" onclick="openDm('${groupId}', decodeURIComponent('${safeGroupName}'), '${groupId}', 'groups')">
|
||||
<button class="room-entry" id="group-btn-${groupId}" onclick="openDm('${groupId}', decodeURIComponent('${safeGroupName}'), '${groupId}', 'groups')" oncontextmenu="handleGroupContextMenu(event, '${groupId}')">
|
||||
<img src="${pfp}" class="room-pfp">
|
||||
<div style="display: flex; flex-direction: column; text-align: left; overflow: hidden; width: 100%; margin-left: 0.37rem;">
|
||||
<span class="room-name" style="${nameStyle}">${groupName}</span>
|
||||
|
|
@ -4761,3 +4764,106 @@ if (typeof roomTopBar !== 'undefined' && roomTopBar) {
|
|||
topbarMutationObserver.observe(roomTopBar.children.item(0), { childList: true, subtree: true });
|
||||
}
|
||||
}
|
||||
|
||||
var currentContextMenuGroupId = null;
|
||||
|
||||
function handleGroupContextMenu(e, groupId) {
|
||||
if (e) {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
}
|
||||
if (typeof clearContextMenuStyles === "function") clearContextMenuStyles();
|
||||
currentContextMenuGroupId = groupId;
|
||||
|
||||
let btn = e ? (e.currentTarget || e.target) : null;
|
||||
let rect;
|
||||
if (e && e.type === "click") {
|
||||
rect = btn.getBoundingClientRect();
|
||||
showFixedContextMenu({top: rect.top, right: rect.left, bottom: rect.bottom, left: rect.left}, groupContextMenu);
|
||||
} else if (e) {
|
||||
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}, groupContextMenu);
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
|
||||
let menuRect = fixedContextMenu.getBoundingClientRect();
|
||||
let newLeft = e ? (e.clientX !== undefined ? e.clientX : (e.touches && e.touches.length > 0 ? e.touches[0].clientX : 0)) + 10 : 0;
|
||||
let newTop = e ? (e.clientY !== undefined ? e.clientY : (e.touches && e.touches.length > 0 ? e.touches[0].clientY : 0)) : 0;
|
||||
|
||||
if (e && e.type === "click") {
|
||||
newLeft = rect.left + 10;
|
||||
newTop = rect.bottom;
|
||||
}
|
||||
|
||||
if (newLeft + menuRect.width > window.innerWidth) {
|
||||
newLeft = window.innerWidth - menuRect.width - 10;
|
||||
}
|
||||
if (newTop + menuRect.height > window.innerHeight) {
|
||||
newTop = window.innerHeight - menuRect.height - 10;
|
||||
}
|
||||
|
||||
fixedContextMenu.style.left = `${newLeft}px`;
|
||||
fixedContextMenu.style.top = `${newTop}px`;
|
||||
}
|
||||
|
||||
function gotoGroupSettings(groupId) {
|
||||
if (fixedContextMenu) fixedContextMenu.classList.remove("show");
|
||||
// Not implemented yet
|
||||
}
|
||||
|
||||
function leaveGroupPrompt(groupId) {
|
||||
if (fixedContextMenu) fixedContextMenu.classList.remove("show");
|
||||
|
||||
let popupContainer = document.getElementById("profile-popup-container");
|
||||
let popupInner = document.getElementById("profile-popup-inner");
|
||||
|
||||
let html = `
|
||||
<div style="text-align: center; margin-bottom: 1rem;">
|
||||
<h3 style="margin-bottom: 0.5rem;"><blah>title.leave.group</blah></h3>
|
||||
<p style="opacity: 0.7; font-size: 0.9rem;"><blah>desc.leave.group.confirm</blah></p>
|
||||
</div>
|
||||
<div style="display: flex; gap: 0.5rem; justify-content: center; width: 100%;">
|
||||
<button class="profile-action-btn" style="background: var(--light-border-color); color: var(--text-color); flex: 1;" onclick="closeProfile()">
|
||||
<blah>action.cancel</blah>
|
||||
</button>
|
||||
<button class="profile-action-btn" style="background: var(--big-red); color: white; border: none; flex: 1;" onclick="confirmLeaveGroup('${groupId}')">
|
||||
<blah>title.leave.group</blah>
|
||||
</button>
|
||||
</div>
|
||||
`;
|
||||
|
||||
popupInner.innerHTML = html;
|
||||
|
||||
let blahTags = popupInner.getElementsByTagName("blah");
|
||||
for (let i = 0; i < blahTags.length; i++) {
|
||||
blahTags[i].innerHTML = processBlah(blahTags[i].innerHTML);
|
||||
}
|
||||
|
||||
popupContainer.style.display = "flex";
|
||||
popupContainer.offsetHeight; // trigger reflow
|
||||
popupContainer.classList.add("show");
|
||||
isProfileOpen = true;
|
||||
}
|
||||
|
||||
async function confirmLeaveGroup(groupId) {
|
||||
closeProfile();
|
||||
showAction("action.leaving.group", "leavegroup");
|
||||
try {
|
||||
let payload = JSON.stringify({ string1: groupId });
|
||||
let res = await fetchEncrypted("group/leave", payload);
|
||||
if (res === "success") {
|
||||
if (currentDmId === groupId) {
|
||||
gotoHome();
|
||||
}
|
||||
refreshGroups(0, false);
|
||||
} else if (res.startsWith("error:")) {
|
||||
showBlahNotification(res);
|
||||
}
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
showBlahNotification("error:something.wrong");
|
||||
}
|
||||
clearAction("leavegroup");
|
||||
}
|
||||
|
|
|
|||
|
|
@ -250,6 +250,16 @@ var addSpaceMenu = `
|
|||
${ICONS.createSpace()}
|
||||
<span class="blah">title.create.space</span>
|
||||
</button>`
|
||||
var groupContextMenu = `
|
||||
<button onclick="gotoGroupSettings(currentContextMenuGroupId)">
|
||||
${ICONS.settings()}
|
||||
<span class="blah">title.group.settings</span>
|
||||
</button>
|
||||
<button onclick="leaveGroupPrompt(currentContextMenuGroupId)">
|
||||
${ICONS.delete({ fill: "var(--big-red)" })}
|
||||
<span class="blah" style="color: var(--big-red)">title.leave.group</span>
|
||||
</button>
|
||||
`;
|
||||
var messageContextMenu = `
|
||||
<button onclick="replyMessage(currentContextMenuMsgId)">
|
||||
${ICONS.replyAction()}
|
||||
|
|
@ -270,6 +280,7 @@ var messageContextMenu = `
|
|||
var backBtnHtml = `<button class="mobile-nav-btn" onclick="mobileNavBack()">${ICONS.arrowBack({ width: "1.5rem", height: "1.5rem" })}</button>`;
|
||||
var pinBtnHtml = `<button class="topbar-action-btn room-action-pin right" onclick="showPinnedMessages()">${ICONS.pin({ width: "1.5rem", height: "1.5rem" })}</button>`;
|
||||
var callBtnHtml = `<button class="topbar-action-btn room-action-call right">${ICONS.call({ width: "1.5rem", height: "1.5rem" })}</button>`;
|
||||
var groupMenuBtnHtml = `<button class="topbar-action-btn right" onclick="handleGroupContextMenu(arguments[0], currentDmId)">${ICONS.menu({ width: "1.5rem", height: "1.5rem" })}</button>`;
|
||||
|
||||
var settingsBar = `
|
||||
<div class="sidebar-section-header">
|
||||
|
|
|
|||
108
webroot/main.js
108
webroot/main.js
|
|
@ -1554,6 +1554,9 @@ async function switchDetailsContent(title, content, showBack = false, backAction
|
|||
|
||||
|
||||
let pinCallBtns = showBack ? `${callBtnHtml}` : `${pinBtnHtml}${callBtnHtml}`;
|
||||
if (window.currentRoomType === 'groups' && !showBack) {
|
||||
pinCallBtns = `${groupMenuBtnHtml}${pinCallBtns}`;
|
||||
}
|
||||
let backBtn = showBack ? `<button class="topbar-action-btn" onclick="${backAction}" style="margin-right: 0.5rem">${ICONS.arrowBack({ width: "1.5rem", height: "1.5rem" })}</button>` : "";
|
||||
roomsTopBarTransition.innerHTML = `<inherit style="display: flex; align-items: center;">${backBtn}<inherit>${processBlah(title)}</inherit></inherit><div class="flex-spacer"></div>${pinCallBtns}`;
|
||||
|
||||
|
|
@ -2542,7 +2545,7 @@ async function renderGroups(res) {
|
|||
let pfp = await getGroupAvatarUrl(groupId, groupName);
|
||||
|
||||
html += `
|
||||
<button class="room-entry" id="group-btn-${groupId}" onclick="openDm('${groupId}', decodeURIComponent('${safeGroupName}'), '${groupId}', 'groups')">
|
||||
<button class="room-entry" id="group-btn-${groupId}" onclick="openDm('${groupId}', decodeURIComponent('${safeGroupName}'), '${groupId}', 'groups')" oncontextmenu="handleGroupContextMenu(event, '${groupId}')">
|
||||
<img src="${pfp}" class="room-pfp">
|
||||
<div style="display: flex; flex-direction: column; text-align: left; overflow: hidden; width: 100%; margin-left: 0.37rem;">
|
||||
<span class="room-name" style="${nameStyle}">${groupName}</span>
|
||||
|
|
@ -4761,3 +4764,106 @@ if (typeof roomTopBar !== 'undefined' && roomTopBar) {
|
|||
topbarMutationObserver.observe(roomTopBar.children.item(0), { childList: true, subtree: true });
|
||||
}
|
||||
}
|
||||
|
||||
var currentContextMenuGroupId = null;
|
||||
|
||||
function handleGroupContextMenu(e, groupId) {
|
||||
if (e) {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
}
|
||||
if (typeof clearContextMenuStyles === "function") clearContextMenuStyles();
|
||||
currentContextMenuGroupId = groupId;
|
||||
|
||||
let btn = e ? (e.currentTarget || e.target) : null;
|
||||
let rect;
|
||||
if (e && e.type === "click") {
|
||||
rect = btn.getBoundingClientRect();
|
||||
showFixedContextMenu({top: rect.top, right: rect.left, bottom: rect.bottom, left: rect.left}, groupContextMenu);
|
||||
} else if (e) {
|
||||
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}, groupContextMenu);
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
|
||||
let menuRect = fixedContextMenu.getBoundingClientRect();
|
||||
let newLeft = e ? (e.clientX !== undefined ? e.clientX : (e.touches && e.touches.length > 0 ? e.touches[0].clientX : 0)) + 10 : 0;
|
||||
let newTop = e ? (e.clientY !== undefined ? e.clientY : (e.touches && e.touches.length > 0 ? e.touches[0].clientY : 0)) : 0;
|
||||
|
||||
if (e && e.type === "click") {
|
||||
newLeft = rect.left + 10;
|
||||
newTop = rect.bottom;
|
||||
}
|
||||
|
||||
if (newLeft + menuRect.width > window.innerWidth) {
|
||||
newLeft = window.innerWidth - menuRect.width - 10;
|
||||
}
|
||||
if (newTop + menuRect.height > window.innerHeight) {
|
||||
newTop = window.innerHeight - menuRect.height - 10;
|
||||
}
|
||||
|
||||
fixedContextMenu.style.left = `${newLeft}px`;
|
||||
fixedContextMenu.style.top = `${newTop}px`;
|
||||
}
|
||||
|
||||
function gotoGroupSettings(groupId) {
|
||||
if (fixedContextMenu) fixedContextMenu.classList.remove("show");
|
||||
// Not implemented yet
|
||||
}
|
||||
|
||||
function leaveGroupPrompt(groupId) {
|
||||
if (fixedContextMenu) fixedContextMenu.classList.remove("show");
|
||||
|
||||
let popupContainer = document.getElementById("profile-popup-container");
|
||||
let popupInner = document.getElementById("profile-popup-inner");
|
||||
|
||||
let html = `
|
||||
<div style="text-align: center; margin-bottom: 1rem;">
|
||||
<h3 style="margin-bottom: 0.5rem;"><blah>title.leave.group</blah></h3>
|
||||
<p style="opacity: 0.7; font-size: 0.9rem;"><blah>desc.leave.group.confirm</blah></p>
|
||||
</div>
|
||||
<div style="display: flex; gap: 0.5rem; justify-content: center; width: 100%;">
|
||||
<button class="profile-action-btn" style="background: var(--light-border-color); color: var(--text-color); flex: 1;" onclick="closeProfile()">
|
||||
<blah>action.cancel</blah>
|
||||
</button>
|
||||
<button class="profile-action-btn" style="background: var(--big-red); color: white; border: none; flex: 1;" onclick="confirmLeaveGroup('${groupId}')">
|
||||
<blah>title.leave.group</blah>
|
||||
</button>
|
||||
</div>
|
||||
`;
|
||||
|
||||
popupInner.innerHTML = html;
|
||||
|
||||
let blahTags = popupInner.getElementsByTagName("blah");
|
||||
for (let i = 0; i < blahTags.length; i++) {
|
||||
blahTags[i].innerHTML = processBlah(blahTags[i].innerHTML);
|
||||
}
|
||||
|
||||
popupContainer.style.display = "flex";
|
||||
popupContainer.offsetHeight; // trigger reflow
|
||||
popupContainer.classList.add("show");
|
||||
isProfileOpen = true;
|
||||
}
|
||||
|
||||
async function confirmLeaveGroup(groupId) {
|
||||
closeProfile();
|
||||
showAction("action.leaving.group", "leavegroup");
|
||||
try {
|
||||
let payload = JSON.stringify({ string1: groupId });
|
||||
let res = await fetchEncrypted("group/leave", payload);
|
||||
if (res === "success") {
|
||||
if (currentDmId === groupId) {
|
||||
gotoHome();
|
||||
}
|
||||
refreshGroups(0, false);
|
||||
} else if (res.startsWith("error:")) {
|
||||
showBlahNotification(res);
|
||||
}
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
showBlahNotification("error:something.wrong");
|
||||
}
|
||||
clearAction("leavegroup");
|
||||
}
|
||||
|
|
|
|||
|
|
@ -250,6 +250,16 @@ var addSpaceMenu = `
|
|||
${ICONS.createSpace()}
|
||||
<span class="blah">title.create.space</span>
|
||||
</button>`
|
||||
var groupContextMenu = `
|
||||
<button onclick="gotoGroupSettings(currentContextMenuGroupId)">
|
||||
${ICONS.settings()}
|
||||
<span class="blah">title.group.settings</span>
|
||||
</button>
|
||||
<button onclick="leaveGroupPrompt(currentContextMenuGroupId)">
|
||||
${ICONS.delete({ fill: "var(--big-red)" })}
|
||||
<span class="blah" style="color: var(--big-red)">title.leave.group</span>
|
||||
</button>
|
||||
`;
|
||||
var messageContextMenu = `
|
||||
<button onclick="replyMessage(currentContextMenuMsgId)">
|
||||
${ICONS.replyAction()}
|
||||
|
|
@ -270,6 +280,7 @@ var messageContextMenu = `
|
|||
var backBtnHtml = `<button class="mobile-nav-btn" onclick="mobileNavBack()">${ICONS.arrowBack({ width: "1.5rem", height: "1.5rem" })}</button>`;
|
||||
var pinBtnHtml = `<button class="topbar-action-btn room-action-pin right" onclick="showPinnedMessages()">${ICONS.pin({ width: "1.5rem", height: "1.5rem" })}</button>`;
|
||||
var callBtnHtml = `<button class="topbar-action-btn room-action-call right">${ICONS.call({ width: "1.5rem", height: "1.5rem" })}</button>`;
|
||||
var groupMenuBtnHtml = `<button class="topbar-action-btn right" onclick="handleGroupContextMenu(arguments[0], currentDmId)">${ICONS.menu({ width: "1.5rem", height: "1.5rem" })}</button>`;
|
||||
|
||||
var settingsBar = `
|
||||
<div class="sidebar-section-header">
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue