slightly improve popups

This commit is contained in:
olcxja 2026-08-09 13:21:57 +02:00
commit bb135bed65
14 changed files with 136 additions and 98 deletions

View file

@ -262,5 +262,10 @@
"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.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"
}

View file

@ -262,5 +262,10 @@
"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.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"
}

View file

@ -262,5 +262,10 @@
"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.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ę"
}

View file

@ -30,11 +30,10 @@ const ICONS = {
pin: (props) => ICONS._material(`<path d="m640-480 80 80v80H520v240l-40 40-40-40v-240H240v-80l80-80v-280h-40v-80h400v80h-40v280Zm-286 80h252l-46-46v-314H400v314l-46 46Zm126 0Z"/>`, props),
call: (props) => ICONS._material(`<path d="M798-120q-125 0-247-54.5T329-329Q229-429 174.5-551T120-798q0-18 12-30t30-12h162q14 0 25 9.5t13 22.5l26 140q2 16-1 27t-11 19l-97 98q20 37 47.5 71.5T387-386q31 31 65 57.5t72 48.5l94-94q9-9 23.5-13.5T670-390l138 28q14 4 23 14.5t9 23.5v162q0 18-12 30t-30 12ZM241-600l66-66-17-94h-89q5 41 14 81t26 79Zm358 358q39 17 79.5 27t81.5 13v-88l-94-19-67 67ZM241-600Zm358 358Z"/>`, props),
account: (props) => ICONS._material(`<path d="M200-200h560v-560H200v560Zm0 80q-33 0-56.5-23.5T120-200v-560q0-33 23.5-56.5T200-840h560q33 0 56.5 23.5T840-760v560q0 33-23.5 56.5T760-120H200Zm40-160h480L570-480 450-320l-90-120-120 160Zm-40 80v-560 560Z"/>`, props),
settings: (props) => ICONS._material(`<path d="M480-80q-82 0-155-31.5t-127.5-86Q143-252 111.5-325T80-480q0-83 31.5-156t86-127Q252-817 325-848.5T480-880q83 0 156 31.5T763-763q54 54 85.5 127T880-480q0 167-116.5 283.5T480-80Zm0-157q102 0 174-72t72-174q0-102-72-174t-174-72q-102 0-174 72t-72 174q0 102 72 174t174 72Zm0-80q-68 0-116.5-48.5T315-482q0-68 48.5-116.5T480-647q68 0 116.5 48.5T645-482q0 68-48.5 116.5T480-317Zm0-60q43 0 74-31t31-74q0-43-31-74t-74-31q-43 0-74 31t-31 74q0 43 31 74t74 31Zm0-105Z"/>`, props),
profile: (props) => ICONS._material(`<path d="M480-480q-66 0-113-47t-47-113q0-66 47-113t113-47q66 0 113 47t47 113q0 66-47 113t-113 47ZM160-160v-112q0-34 17.5-62.5T224-378q62-31 126-46.5T480-440q66 0 130 15.5T736-378q29 15 46.5 43.5T800-272v112H160Zm80-80h480v-32q0-11-5.5-20T700-306q-54-27-109-40.5T480-360q-56 0-111 13.5T260-306q-9 5-14.5 14t-5.5 20v32Zm240-320q33 0 56.5-23.5T560-640q0-33-23.5-56.5T480-720q-33 0-56.5 23.5T400-640q0 33 23.5 56.5T480-560Zm0-80Zm0 400Z"/>`, props),
replyAction: (props) => ICONS._material(`<path d="M760-200v-160q0-50-35-85t-85-35H273l144 144-57 56-240-240 240-240 57 56-144 144h367q83 0 141.5 58.5T840-360v160h-80Z"/>`, props),
react: (props) => ICONS._material(`<path d="M480-260q70 0 126.5-40.5T682-400H278q19 59 75.5 99.5T480-260Zm-160-220q25 0 42.5-17.5T380-540q0-25-17.5-42.5T320-600q-25 0-42.5 17.5T260-540q0 25 17.5 42.5T320-480Zm320 0q25 0 42.5-17.5T700-540q0-25-17.5-42.5T640-600q-25 0-42.5 17.5T580-540q0 25 17.5 42.5T640-480ZM480-80q-83 0-156-31.5T197-197q-54-54-85.5-127T80-480q0-83 31.5-156T197-763q54-54 127-85.5T480-880q83 0 156 31.5T763-763q54 54 85.5 127T880-480q0 83-31.5 156T763-197q-54 54-127 85.5T480-80Zm0-80q134 0 227-93t93-227q0-134-93-227t-227-93q-134 0-227 93t-93 227q0 134 93 227t227 93Zm0-320Z"/>`, props),
settingsProfile: (props) => ICONS._material(`<path d="m370-80-16-128q-13-5-24.5-12T307-235l-119 50L78-375l103-78q-1-7-1-13.5v-27q0-6.5 1-13.5L78-585l110-190 119 50q11-8 23-15t24-12l16-128h220l16 128q13 5 24.5 12t22.5 15l119-50 110 190-103 78q1 7 1 13.5v27q0 6.5-2 13.5l103 78-110 190-118-50q-11 8-23 15t-24 12L590-80H370Zm70-80h79l14-106q31-8 57.5-23.5T639-327l99 41 39-68-86-65q5-14 7-29.5t2-31.5q0-16-2-31.5t-7-29.5l86-65-39-68-99 42q-22-23-48.5-38.5T533-694l-13-106h-79l-14 106q-31 8-57.5 23.5T321-633l-99-41-39 68 86 64q-5 15-7 30t-2 32q0 16 2 31t7 30l-86 65 39 68 99-42q22 23 48.5 38.5T427-266l13 106Zm42-180q58 0 99-41t41-99q0-58-41-99t-99-41q-59 0-99.5 41T342-480q0 58 40.5 99t99.5 41Zm-2-140Z"/>`, props),
settings: (props) => ICONS._material(`<path d="m370-80-16-128q-13-5-24.5-12T307-235l-119 50L78-375l103-78q-1-7-1-13.5v-27q0-6.5 1-13.5L78-585l110-190 119 50q11-8 23-15t24-12l16-128h220l16 128q13 5 24.5 12t22.5 15l119-50 110 190-103 78q1 7 1 13.5v27q0 6.5-2 13.5l103 78-110 190-118-50q-11 8-23 15t-24 12L590-80H370Zm70-80h79l14-106q31-8 57.5-23.5T639-327l99 41 39-68-86-65q5-14 7-29.5t2-31.5q0-16-2-31.5t-7-29.5l86-65-39-68-99 42q-22-23-48.5-38.5T533-694l-13-106h-79l-14 106q-31 8-57.5 23.5T321-633l-99-41-39 68 86 64q-5 15-7 30t-2 32q0 16 2 31t7 30l-86 65 39 68 99-42q22 23 48.5 38.5T427-266l13 106Zm42-180q58 0 99-41t41-99q0-58-41-99t-99-41q-59 0-99.5 41T342-480q0 58 40.5 99t99.5 41Zm-2-140Z"/>`, props),
download: (props) => ICONS._feather(`<path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"/><polyline points="7 10 12 15 17 10"/><line x1="12" y1="15" x2="12" y2="3"/>`, props),
camera: (props) => ICONS._feather(`<path d="M23 19a2 2 0 0 1-2 2H3a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h4l2-3h6l2 3h4a2 2 0 0 1 2 2z"></path><circle cx="12" cy="13" r="4"></circle>`, props),

View file

@ -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" : "popup-btn-confirm";
let confirmClass = isDestructive ? "popup-btn-danger" : "";
genericPopupCancelCallback = onCancel;
@ -449,10 +449,10 @@ function showConfirmPopup(titleKey, descHtml, confirmActionKey, cancelActionKey,
${descHtml}
</div>
<div style="display: flex; gap: 0.5rem; justify-content: center; width: 100%;">
<button class="profile-action-btn popup-btn-cancel" onclick="closeGenericPopup()">
<button class="profile-action-btn popup-action-btn popup-btn-cancel" onclick="closeGenericPopup()">
<blah>${cancelActionKey}</blah>
</button>
<button class="profile-action-btn ${confirmClass}" onclick="if(genericPopupConfirmCallback) genericPopupConfirmCallback()">
<button class="profile-action-btn popup-action-btn ${confirmClass}" onclick="if(genericPopupConfirmCallback) genericPopupConfirmCallback()">
<blah>${confirmActionKey}</blah>
</button>
</div>
@ -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" : "popup-btn-confirm";
let confirmClass = isDestructive ? "popup-btn-danger" : "";
genericPopupCancelCallback = onCancel;
@ -491,12 +491,15 @@ function showPromptPopup(titleKey, descHtml, placeholderKey, confirmActionKey, c
<div style="width: 100%; text-align: center; color: var(--text-color); opacity: 0.8; margin-top: 0.5rem; margin-bottom: 1rem;">
${descHtml}
</div>
<input type="text" id="generic-popup-input" class="forminput" placeholder="{blah(${placeholderKey})}" style="width: 100%; margin-bottom: 1rem; box-sizing: border-box;" onkeydown="if(arguments[0].key === 'Enter') { if(genericPopupConfirmCallback) genericPopupConfirmCallback(); }">
<div class="input-group" style="margin: 0 auto 1.5rem auto; width: 100%;">
<label for="generic-popup-input" style="margin-left: 0;"><blah>${placeholderKey}</blah></label>
<input type="text" id="generic-popup-input" class="forminput" placeholder="${processBlah(placeholderKey)}" style="margin-left: 0; margin-right: 0; width: 100%; box-sizing: border-box;" onkeydown="if(arguments[0].key === 'Enter') { if(genericPopupConfirmCallback) genericPopupConfirmCallback(); }">
</div>
<div style="display: flex; gap: 0.5rem; justify-content: center; width: 100%;">
<button class="profile-action-btn popup-btn-cancel" onclick="closeGenericPopup()">
<button class="profile-action-btn popup-action-btn popup-btn-cancel" onclick="closeGenericPopup()">
<blah>${cancelActionKey}</blah>
</button>
<button class="profile-action-btn ${confirmClass}" onclick="if(genericPopupConfirmCallback) genericPopupConfirmCallback()">
<button class="profile-action-btn popup-action-btn ${confirmClass}" onclick="if(genericPopupConfirmCallback) genericPopupConfirmCallback()">
<blah>${confirmActionKey}</blah>
</button>
</div>
@ -531,7 +534,7 @@ function closeRotationPopup() {
async function showRotationPopup(groupId, originalMessagePayload) {
pendingRotationMessagePayload = originalMessagePayload;
showAction("action.key.rotation", "key_rotation");
showAction("action.key.rotating", "key_rotation");
try {
let membersRaw = await fetchEncrypted("group/members", groupId);
@ -539,7 +542,7 @@ async function showRotationPopup(groupId, originalMessagePayload) {
let members = JSON.parse(membersRaw);
let descHtml = `<blah>desc.key.rotation.info</blah><br><br><b>${members.length} <blah>label.members</blah></b>`;
let descHtml = `<blah>desc.key.rotation.you</blah><br><br><b>${members.length} <blah>label.keys.to.encrypt</blah></b>`;
showConfirmPopup(
"title.key.rotation",
@ -557,6 +560,7 @@ async function showRotationPopup(groupId, originalMessagePayload) {
async function executeKeyRotation() {
closeRotationPopup();
clearAction("key_rotation");
showAction("action.key.rotating", "key_rotation_exec");
try {
@ -2742,7 +2746,7 @@ async function inviteToGroupPrompt(groupId) {
showPromptPopup(
"action.invite",
"",
"prompt.invite.username",
"title.username",
"action.invite",
"action.cancel",
async (targetUsername) => {
@ -4282,7 +4286,12 @@ async function changePassword() {
}
async function deleteAccount() {
if (!confirm(processBlah("desc.delete.account") + "\n\n" + processBlah("prompt.are.you.sure"))) return;
showConfirmPopup(
"title.delete.account",
"<blah>desc.delete.account</blah><br><br><blah>prompt.are.you.sure</blah>",
"action.delete.account",
"action.cancel",
async () => {
showAction("action.account.deleting", "accountdel");
let res = await fetchPostEnc(`${url}/deleteaccount?id=${window.id}`, "");
clearAction("accountdel");
@ -4293,6 +4302,10 @@ async function deleteAccount() {
} else {
showBlahNotification(text);
}
},
null,
true
);
}
async function saveProfile() {

View file

@ -211,7 +211,7 @@ var profileContextMenu = `
<span class="blah">title.profile</span>
</button>
<button onclick="gotoSettings()">
${ICONS.settingsProfile()}
${ICONS.settings()}
<span class="blah">title.settings</span>
</button>
<button onclick="logout()">
@ -327,7 +327,7 @@ var accountSettings = `
<div class="input-group">
<label style="color: var(--big-red);"><blah>title.delete.account</blah></label>
<p style="font-size: 0.85rem; opacity: 0.7; margin-bottom: 0.5rem; margin-left: 0.6rem;"><blah>desc.delete.account</blah></p>
<button class="submit-button blah" onclick="deleteAccount()" style="background: var(--big-red); color: white;">action.delete.account</button>
<button class="submit-button popup-btn-danger blah" onclick="deleteAccount()">action.delete.account</button>
</div>
</div>
`;

View file

@ -878,35 +878,27 @@ sidebarelement:has(.icon-button:active) indicator:not(.active) {
height: auto;
max-height: 85vh;
}
.popup-btn-cancel {
button.profile-action-btn.popup-action-btn {
flex: 1;
display: flex;
justify-content: center;
margin-top: 0;
}
button.profile-action-btn.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;
}
.popup-btn-cancel:hover {
button.profile-action-btn.popup-btn-cancel:hover {
background: rgba(255, 255, 255, 0.1);
}
.popup-btn-confirm {
background: var(--text-color);
color: var(--main-bg-color);
button.profile-action-btn.popup-btn-danger, button.submit-button.popup-btn-danger {
background: var(--big-red) !important;
color: white !important;
border: none;
flex: 1;
justify-content: center;
}
.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;
button.profile-action-btn.popup-btn-danger:hover, button.submit-button.popup-btn-danger:hover {
filter: brightness(0.85);
}
.profile-popup-container.show .profile-popup-content {
transform: scale(1);

View file

@ -262,5 +262,10 @@
"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.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"
}

View file

@ -262,5 +262,10 @@
"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.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"
}

View file

@ -262,5 +262,10 @@
"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.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ę"
}

View file

@ -30,11 +30,10 @@ const ICONS = {
pin: (props) => ICONS._material(`<path d="m640-480 80 80v80H520v240l-40 40-40-40v-240H240v-80l80-80v-280h-40v-80h400v80h-40v280Zm-286 80h252l-46-46v-314H400v314l-46 46Zm126 0Z"/>`, props),
call: (props) => ICONS._material(`<path d="M798-120q-125 0-247-54.5T329-329Q229-429 174.5-551T120-798q0-18 12-30t30-12h162q14 0 25 9.5t13 22.5l26 140q2 16-1 27t-11 19l-97 98q20 37 47.5 71.5T387-386q31 31 65 57.5t72 48.5l94-94q9-9 23.5-13.5T670-390l138 28q14 4 23 14.5t9 23.5v162q0 18-12 30t-30 12ZM241-600l66-66-17-94h-89q5 41 14 81t26 79Zm358 358q39 17 79.5 27t81.5 13v-88l-94-19-67 67ZM241-600Zm358 358Z"/>`, props),
account: (props) => ICONS._material(`<path d="M200-200h560v-560H200v560Zm0 80q-33 0-56.5-23.5T120-200v-560q0-33 23.5-56.5T200-840h560q33 0 56.5 23.5T840-760v560q0 33-23.5 56.5T760-120H200Zm40-160h480L570-480 450-320l-90-120-120 160Zm-40 80v-560 560Z"/>`, props),
settings: (props) => ICONS._material(`<path d="M480-80q-82 0-155-31.5t-127.5-86Q143-252 111.5-325T80-480q0-83 31.5-156t86-127Q252-817 325-848.5T480-880q83 0 156 31.5T763-763q54 54 85.5 127T880-480q0 167-116.5 283.5T480-80Zm0-157q102 0 174-72t72-174q0-102-72-174t-174-72q-102 0-174 72t-72 174q0 102 72 174t174 72Zm0-80q-68 0-116.5-48.5T315-482q0-68 48.5-116.5T480-647q68 0 116.5 48.5T645-482q0 68-48.5 116.5T480-317Zm0-60q43 0 74-31t31-74q0-43-31-74t-74-31q-43 0-74 31t-31 74q0 43 31 74t74 31Zm0-105Z"/>`, props),
profile: (props) => ICONS._material(`<path d="M480-480q-66 0-113-47t-47-113q0-66 47-113t113-47q66 0 113 47t47 113q0 66-47 113t-113 47ZM160-160v-112q0-34 17.5-62.5T224-378q62-31 126-46.5T480-440q66 0 130 15.5T736-378q29 15 46.5 43.5T800-272v112H160Zm80-80h480v-32q0-11-5.5-20T700-306q-54-27-109-40.5T480-360q-56 0-111 13.5T260-306q-9 5-14.5 14t-5.5 20v32Zm240-320q33 0 56.5-23.5T560-640q0-33-23.5-56.5T480-720q-33 0-56.5 23.5T400-640q0 33 23.5 56.5T480-560Zm0-80Zm0 400Z"/>`, props),
replyAction: (props) => ICONS._material(`<path d="M760-200v-160q0-50-35-85t-85-35H273l144 144-57 56-240-240 240-240 57 56-144 144h367q83 0 141.5 58.5T840-360v160h-80Z"/>`, props),
react: (props) => ICONS._material(`<path d="M480-260q70 0 126.5-40.5T682-400H278q19 59 75.5 99.5T480-260Zm-160-220q25 0 42.5-17.5T380-540q0-25-17.5-42.5T320-600q-25 0-42.5 17.5T260-540q0 25 17.5 42.5T320-480Zm320 0q25 0 42.5-17.5T700-540q0-25-17.5-42.5T640-600q-25 0-42.5 17.5T580-540q0 25 17.5 42.5T640-480ZM480-80q-83 0-156-31.5T197-197q-54-54-85.5-127T80-480q0-83 31.5-156T197-763q54-54 127-85.5T480-880q83 0 156 31.5T763-763q54 54 85.5 127T880-480q0 83-31.5 156T763-197q-54 54-127 85.5T480-80Zm0-80q134 0 227-93t93-227q0-134-93-227t-227-93q-134 0-227 93t-93 227q0 134 93 227t227 93Zm0-320Z"/>`, props),
settingsProfile: (props) => ICONS._material(`<path d="m370-80-16-128q-13-5-24.5-12T307-235l-119 50L78-375l103-78q-1-7-1-13.5v-27q0-6.5 1-13.5L78-585l110-190 119 50q11-8 23-15t24-12l16-128h220l16 128q13 5 24.5 12t22.5 15l119-50 110 190-103 78q1 7 1 13.5v27q0 6.5-2 13.5l103 78-110 190-118-50q-11 8-23 15t-24 12L590-80H370Zm70-80h79l14-106q31-8 57.5-23.5T639-327l99 41 39-68-86-65q5-14 7-29.5t2-31.5q0-16-2-31.5t-7-29.5l86-65-39-68-99 42q-22-23-48.5-38.5T533-694l-13-106h-79l-14 106q-31 8-57.5 23.5T321-633l-99-41-39 68 86 64q-5 15-7 30t-2 32q0 16 2 31t7 30l-86 65 39 68 99-42q22 23 48.5 38.5T427-266l13 106Zm42-180q58 0 99-41t41-99q0-58-41-99t-99-41q-59 0-99.5 41T342-480q0 58 40.5 99t99.5 41Zm-2-140Z"/>`, props),
settings: (props) => ICONS._material(`<path d="m370-80-16-128q-13-5-24.5-12T307-235l-119 50L78-375l103-78q-1-7-1-13.5v-27q0-6.5 1-13.5L78-585l110-190 119 50q11-8 23-15t24-12l16-128h220l16 128q13 5 24.5 12t22.5 15l119-50 110 190-103 78q1 7 1 13.5v27q0 6.5-2 13.5l103 78-110 190-118-50q-11 8-23 15t-24 12L590-80H370Zm70-80h79l14-106q31-8 57.5-23.5T639-327l99 41 39-68-86-65q5-14 7-29.5t2-31.5q0-16-2-31.5t-7-29.5l86-65-39-68-99 42q-22-23-48.5-38.5T533-694l-13-106h-79l-14 106q-31 8-57.5 23.5T321-633l-99-41-39 68 86 64q-5 15-7 30t-2 32q0 16 2 31t7 30l-86 65 39 68 99-42q22 23 48.5 38.5T427-266l13 106Zm42-180q58 0 99-41t41-99q0-58-41-99t-99-41q-59 0-99.5 41T342-480q0 58 40.5 99t99.5 41Zm-2-140Z"/>`, props),
download: (props) => ICONS._feather(`<path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"/><polyline points="7 10 12 15 17 10"/><line x1="12" y1="15" x2="12" y2="3"/>`, props),
camera: (props) => ICONS._feather(`<path d="M23 19a2 2 0 0 1-2 2H3a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h4l2-3h6l2 3h4a2 2 0 0 1 2 2z"></path><circle cx="12" cy="13" r="4"></circle>`, props),

View file

@ -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" : "popup-btn-confirm";
let confirmClass = isDestructive ? "popup-btn-danger" : "";
genericPopupCancelCallback = onCancel;
@ -449,10 +449,10 @@ function showConfirmPopup(titleKey, descHtml, confirmActionKey, cancelActionKey,
${descHtml}
</div>
<div style="display: flex; gap: 0.5rem; justify-content: center; width: 100%;">
<button class="profile-action-btn popup-btn-cancel" onclick="closeGenericPopup()">
<button class="profile-action-btn popup-action-btn popup-btn-cancel" onclick="closeGenericPopup()">
<blah>${cancelActionKey}</blah>
</button>
<button class="profile-action-btn ${confirmClass}" onclick="if(genericPopupConfirmCallback) genericPopupConfirmCallback()">
<button class="profile-action-btn popup-action-btn ${confirmClass}" onclick="if(genericPopupConfirmCallback) genericPopupConfirmCallback()">
<blah>${confirmActionKey}</blah>
</button>
</div>
@ -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" : "popup-btn-confirm";
let confirmClass = isDestructive ? "popup-btn-danger" : "";
genericPopupCancelCallback = onCancel;
@ -491,12 +491,15 @@ function showPromptPopup(titleKey, descHtml, placeholderKey, confirmActionKey, c
<div style="width: 100%; text-align: center; color: var(--text-color); opacity: 0.8; margin-top: 0.5rem; margin-bottom: 1rem;">
${descHtml}
</div>
<input type="text" id="generic-popup-input" class="forminput" placeholder="{blah(${placeholderKey})}" style="width: 100%; margin-bottom: 1rem; box-sizing: border-box;" onkeydown="if(arguments[0].key === 'Enter') { if(genericPopupConfirmCallback) genericPopupConfirmCallback(); }">
<div class="input-group" style="margin: 0 auto 1.5rem auto; width: 100%;">
<label for="generic-popup-input" style="margin-left: 0;"><blah>${placeholderKey}</blah></label>
<input type="text" id="generic-popup-input" class="forminput" placeholder="${processBlah(placeholderKey)}" style="margin-left: 0; margin-right: 0; width: 100%; box-sizing: border-box;" onkeydown="if(arguments[0].key === 'Enter') { if(genericPopupConfirmCallback) genericPopupConfirmCallback(); }">
</div>
<div style="display: flex; gap: 0.5rem; justify-content: center; width: 100%;">
<button class="profile-action-btn popup-btn-cancel" onclick="closeGenericPopup()">
<button class="profile-action-btn popup-action-btn popup-btn-cancel" onclick="closeGenericPopup()">
<blah>${cancelActionKey}</blah>
</button>
<button class="profile-action-btn ${confirmClass}" onclick="if(genericPopupConfirmCallback) genericPopupConfirmCallback()">
<button class="profile-action-btn popup-action-btn ${confirmClass}" onclick="if(genericPopupConfirmCallback) genericPopupConfirmCallback()">
<blah>${confirmActionKey}</blah>
</button>
</div>
@ -531,7 +534,7 @@ function closeRotationPopup() {
async function showRotationPopup(groupId, originalMessagePayload) {
pendingRotationMessagePayload = originalMessagePayload;
showAction("action.key.rotation", "key_rotation");
showAction("action.key.rotating", "key_rotation");
try {
let membersRaw = await fetchEncrypted("group/members", groupId);
@ -539,7 +542,7 @@ async function showRotationPopup(groupId, originalMessagePayload) {
let members = JSON.parse(membersRaw);
let descHtml = `<blah>desc.key.rotation.info</blah><br><br><b>${members.length} <blah>label.members</blah></b>`;
let descHtml = `<blah>desc.key.rotation.you</blah><br><br><b>${members.length} <blah>label.keys.to.encrypt</blah></b>`;
showConfirmPopup(
"title.key.rotation",
@ -557,6 +560,7 @@ async function showRotationPopup(groupId, originalMessagePayload) {
async function executeKeyRotation() {
closeRotationPopup();
clearAction("key_rotation");
showAction("action.key.rotating", "key_rotation_exec");
try {
@ -2742,7 +2746,7 @@ async function inviteToGroupPrompt(groupId) {
showPromptPopup(
"action.invite",
"",
"prompt.invite.username",
"title.username",
"action.invite",
"action.cancel",
async (targetUsername) => {
@ -4282,7 +4286,12 @@ async function changePassword() {
}
async function deleteAccount() {
if (!confirm(processBlah("desc.delete.account") + "\n\n" + processBlah("prompt.are.you.sure"))) return;
showConfirmPopup(
"title.delete.account",
"<blah>desc.delete.account</blah><br><br><blah>prompt.are.you.sure</blah>",
"action.delete.account",
"action.cancel",
async () => {
showAction("action.account.deleting", "accountdel");
let res = await fetchPostEnc(`${url}/deleteaccount?id=${window.id}`, "");
clearAction("accountdel");
@ -4293,6 +4302,10 @@ async function deleteAccount() {
} else {
showBlahNotification(text);
}
},
null,
true
);
}
async function saveProfile() {

View file

@ -211,7 +211,7 @@ var profileContextMenu = `
<span class="blah">title.profile</span>
</button>
<button onclick="gotoSettings()">
${ICONS.settingsProfile()}
${ICONS.settings()}
<span class="blah">title.settings</span>
</button>
<button onclick="logout()">
@ -327,7 +327,7 @@ var accountSettings = `
<div class="input-group">
<label style="color: var(--big-red);"><blah>title.delete.account</blah></label>
<p style="font-size: 0.85rem; opacity: 0.7; margin-bottom: 0.5rem; margin-left: 0.6rem;"><blah>desc.delete.account</blah></p>
<button class="submit-button blah" onclick="deleteAccount()" style="background: var(--big-red); color: white;">action.delete.account</button>
<button class="submit-button popup-btn-danger blah" onclick="deleteAccount()">action.delete.account</button>
</div>
</div>
`;

View file

@ -878,35 +878,27 @@ sidebarelement:has(.icon-button:active) indicator:not(.active) {
height: auto;
max-height: 85vh;
}
.popup-btn-cancel {
button.profile-action-btn.popup-action-btn {
flex: 1;
display: flex;
justify-content: center;
margin-top: 0;
}
button.profile-action-btn.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;
}
.popup-btn-cancel:hover {
button.profile-action-btn.popup-btn-cancel:hover {
background: rgba(255, 255, 255, 0.1);
}
.popup-btn-confirm {
background: var(--text-color);
color: var(--main-bg-color);
button.profile-action-btn.popup-btn-danger, button.submit-button.popup-btn-danger {
background: var(--big-red) !important;
color: white !important;
border: none;
flex: 1;
justify-content: center;
}
.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;
button.profile-action-btn.popup-btn-danger:hover, button.submit-button.popup-btn-danger:hover {
filter: brightness(0.85);
}
.profile-popup-container.show .profile-popup-content {
transform: scale(1);