Add profile context menu & test profile popup
This commit is contained in:
parent
d587aed92c
commit
516bdf5186
12 changed files with 602 additions and 14 deletions
|
|
@ -139,5 +139,10 @@
|
|||
"larp.redacted": "this meow was hissed away.",
|
||||
"placeholder.invitation.code": "invitation code meow",
|
||||
"info.messages.loading.older": "Loading older meowsages...",
|
||||
"error:message.not.found": "Meowsage not found"
|
||||
"error:message.not.found": "Meowsage not found",
|
||||
"title.profile": "cat profile",
|
||||
"title.settings": "cat settings",
|
||||
"title.logout": "log out",
|
||||
"action.edit.profile": "edit cat profile",
|
||||
"action.open.dm": "open direct meowchat"
|
||||
}
|
||||
|
|
@ -139,5 +139,10 @@
|
|||
"larp.redacted": "This message was deleted.",
|
||||
"placeholder.invitation.code": "invitation code",
|
||||
"info.messages.loading.older": "Loading older messages...",
|
||||
"error:message.not.found": "Message not found"
|
||||
"error:message.not.found": "Message not found",
|
||||
"title.profile": "Profile",
|
||||
"title.settings": "Settings",
|
||||
"title.logout": "Log out",
|
||||
"action.edit.profile": "Edit profile",
|
||||
"action.open.dm": "Open DM"
|
||||
}
|
||||
|
|
@ -49,7 +49,7 @@
|
|||
<sidebarelement id="sidebar-profile">
|
||||
<indicator>
|
||||
</indicator>
|
||||
<button class="icon-button" onclick="gotoSideProfilePopup()">
|
||||
<button class="icon-button">
|
||||
<img id="sidebar-pfp">
|
||||
</button>
|
||||
</sidebarelement>
|
||||
|
|
@ -79,6 +79,16 @@
|
|||
<div id="fixed-context-menu" class="context-menu">
|
||||
|
||||
</div>
|
||||
|
||||
<div id="profile-popup-container" class="profile-popup-container" style="display: none;">
|
||||
<div class="profile-popup-bg" onclick="closeProfile()"></div>
|
||||
<div class="profile-popup-content">
|
||||
<button class="profile-popup-close-btn" onclick="closeProfile()">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 -960 960 960" fill="var(--text-color)"><path d="m256-200-56-56 224-224-224-224 56-56 224 224 224-224 56 56-224 224 224 224-56 56-224-224-224 224Z"/></svg>
|
||||
</button>
|
||||
<div id="profile-popup-inner"></div>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
<script src="screens.js"></script>
|
||||
|
|
|
|||
|
|
@ -1411,6 +1411,10 @@ if (App) {
|
|||
}
|
||||
|
||||
function popstate() {
|
||||
if (isProfileOpen) {
|
||||
closeProfile();
|
||||
return;
|
||||
}
|
||||
if (!mainScreen.classList.contains('mobile-content') && !mainScreen.classList.contains('mobile-details')) {
|
||||
history.back();
|
||||
if (App) {
|
||||
|
|
@ -1421,8 +1425,108 @@ function popstate() {
|
|||
}
|
||||
|
||||
|
||||
function gotoSideProfilePopup() {
|
||||
|
||||
sidebarProfileButton.addEventListener("click", (e) => {
|
||||
e.stopPropagation();
|
||||
history.pushState({trap: true}, "", location.href);
|
||||
|
||||
if (fixedContextMenu.classList.contains("show")) {
|
||||
fixedContextMenu.classList.remove("show");
|
||||
if (typeof clearContextMenuStyles === "function") clearContextMenuStyles();
|
||||
setActiveSidebarIndicator(currentMainIndicator);
|
||||
} else {
|
||||
setActiveSidebarIndicator(sidebarProfileIndicator, true);
|
||||
const rect = sidebarProfileButton.getBoundingClientRect();
|
||||
showFixedContextMenu({top: rect.top, right: rect.right, bottom: rect.bottom, left: rect.left}, profileContextMenu);
|
||||
}
|
||||
});
|
||||
|
||||
function logout() {
|
||||
localStorage.clear();
|
||||
window.location.href = "login/index.html";
|
||||
}
|
||||
|
||||
function gotoSettings() {
|
||||
if (fixedContextMenu.classList.contains("show")) {
|
||||
fixedContextMenu.classList.remove("show");
|
||||
if (typeof clearContextMenuStyles === "function") clearContextMenuStyles();
|
||||
setActiveSidebarIndicator(currentMainIndicator);
|
||||
}
|
||||
}
|
||||
|
||||
let isProfileOpen = false;
|
||||
|
||||
async function openProfile(accountId) {
|
||||
if (fixedContextMenu.classList.contains("show")) {
|
||||
fixedContextMenu.classList.remove("show");
|
||||
if (typeof clearContextMenuStyles === "function") clearContextMenuStyles();
|
||||
setActiveSidebarIndicator(currentMainIndicator);
|
||||
}
|
||||
|
||||
let popupContainer = document.getElementById("profile-popup-container");
|
||||
let popupInner = document.getElementById("profile-popup-inner");
|
||||
|
||||
//show loading
|
||||
popupInner.innerHTML = '<div style="display: flex; justify-content: center; align-items: center; height: 100%;"><p>Loading profile...</p></div>';
|
||||
popupContainer.style.display = "flex";
|
||||
|
||||
//force reflow
|
||||
popupContainer.offsetHeight;
|
||||
|
||||
popupContainer.classList.add("show");
|
||||
isProfileOpen = true;
|
||||
|
||||
try {
|
||||
if (!accountId) accountId = window.id; //var fallback
|
||||
let nameWithHost = await fetchAsync(`${url}/idtoname?id=${accountId}`);
|
||||
if (nameWithHost.startsWith("error:")) nameWithHost = accountId; //api fallback
|
||||
|
||||
let nameParts = nameWithHost.split(":");
|
||||
let profileName = nameParts[0] || accountId;
|
||||
let profileHost = nameParts.slice(1).join(":") || host;
|
||||
|
||||
let pfpUrl = await getAvatarUrl(accountId, nameWithHost);
|
||||
|
||||
let bannerUrl = `${url}/user/storage/public/getentry?id=${accountId}&e=larp.profile.banner`;
|
||||
let bannerHtml = `<img src="${bannerUrl}" class="profile-banner" onerror="this.outerHTML='<div class=\\'profile-banner\\'></div>'">`;
|
||||
|
||||
let bio = await fetchAsync(`${url}/user/storage/public/getentry?id=${accountId}&e=larp.profile.bio`);
|
||||
if (bio.startsWith("error:")) bio = "";
|
||||
|
||||
let bioHtml = bio && bio.trim() !== "" ? `<div class="profile-bio">${bio.replace(/</g, "<").replace(/>/g, ">")}</div>` : "";
|
||||
|
||||
let isOwnProfile = accountId === id;
|
||||
let actionBtnHtml = isOwnProfile ?
|
||||
`<button class="profile-action-btn">Edit Profile</button>` :
|
||||
`<button class="profile-action-btn">Open DM</button>`;
|
||||
|
||||
popupInner.innerHTML = `
|
||||
${bannerHtml}
|
||||
<div class="profile-avatar-container">
|
||||
<img src="${pfpUrl}" class="profile-avatar">
|
||||
</div>
|
||||
<div class="profile-info">
|
||||
<div>
|
||||
<div class="profile-name">${profileName}</div>
|
||||
<div class="profile-id-host">${profileName}:${profileHost} (${accountId})</div>
|
||||
</div>
|
||||
${bioHtml}
|
||||
${actionBtnHtml}
|
||||
</div>
|
||||
`;
|
||||
} catch (e) {
|
||||
popupInner.innerHTML = '<div style="display: flex; justify-content: center; align-items: center; height: 100%;"><p>Failed to load profile.</p></div>';
|
||||
console.error(e);
|
||||
}
|
||||
}
|
||||
|
||||
function closeProfile() {
|
||||
let popupContainer = document.getElementById("profile-popup-container");
|
||||
popupContainer.classList.remove("show");
|
||||
isProfileOpen = false;
|
||||
setTimeout(() => {
|
||||
popupContainer.style.display = "none";
|
||||
}, 300);
|
||||
}
|
||||
|
||||
function setActiveRoombarItem(itemId) {
|
||||
|
|
|
|||
|
|
@ -217,6 +217,20 @@ var inboxRoomBar = `
|
|||
|
||||
|
||||
//context menus
|
||||
var profileContextMenu = `
|
||||
<button onclick="openProfile(window.id)">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="1.4rem" viewBox="0 -960 960 960" fill="var(--text-color)"><path d="M367-527q-47-47-47-113t47-113q47-47 113-47t113 47q47 47 47 113t-47 113q-47 47-113 47t-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 20v32Zm296.5-343.5Q560-607 560-640t-23.5-56.5Q513-720 480-720t-56.5 23.5Q400-673 400-640t23.5 56.5Q447-560 480-560t56.5-23.5ZM480-640Zm0 400Z"/></svg>
|
||||
<span class="blah">title.profile</span>
|
||||
</button>
|
||||
<button onclick="gotoSettings()">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="1.4rem" viewBox="0 -960 960 960" fill="var(--text-color)"><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"/></svg>
|
||||
<span class="blah">title.settings</span>
|
||||
</button>
|
||||
<button onclick="logout()">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="1.4rem" viewBox="0 -960 960 960" fill="var(--big-red)"><path d="M200-120q-33 0-56.5-23.5T120-200v-560q0-33 23.5-56.5T200-840h280v80H200v560h280v80H200Zm440-160-55-58 102-102H360v-80h327L585-622l55-58 200 200-200 200Z"/></svg>
|
||||
<span class="blah" style="color: var(--big-red)">title.logout</span>
|
||||
</button>
|
||||
`;
|
||||
var addSpaceMenu = `
|
||||
<button onclick="gotoJoinSpace()">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="1.4rem" viewBox="0 -960 960 960" fill="var(--text-color)"><path d="M440-280H280q-83 0-141.5-58.5T80-480q0-83 58.5-141.5T280-680h160v80H280q-50 0-85 35t-35 85q0 50 35 85t85 35h160v80ZM320-440v-80h320v80H320Zm200 160v-80h160q50 0 85-35t35-85q0-50-35-85t-85-35H520v-80h160q83 0 141.5 58.5T880-480q0 83-58.5 141.5T680-280H520Z"/></svg>
|
||||
|
|
|
|||
|
|
@ -111,6 +111,14 @@ input, textarea {
|
|||
-webkit-user-select: text !important;
|
||||
}
|
||||
|
||||
.chat-message-text, .chat-message-author, .chat-message-timestamp,
|
||||
.profile-name, .profile-bio, .profile-id-host,
|
||||
.dm-username, .group-name, .room-name {
|
||||
user-select: text !important;
|
||||
-webkit-user-select: text !important;
|
||||
cursor: auto;
|
||||
}
|
||||
|
||||
|
||||
indicator {
|
||||
content: "";
|
||||
|
|
@ -706,7 +714,7 @@ space{
|
|||
button:hover, input:hover, textarea:hover {
|
||||
background-color: rgba(255, 255, 255, 0.1);
|
||||
}
|
||||
.submit-button:hover {
|
||||
.submit-button:hover, .profile-action-btn:hover {
|
||||
background-color: rgba(255, 255, 255, 0.5);
|
||||
}
|
||||
.add-action-button:hover {
|
||||
|
|
@ -730,7 +738,7 @@ button:active, button.is-pressed, input:active, input.is-pressed, textarea:activ
|
|||
button.active, input.active, textarea.active {
|
||||
background-color: rgba(255, 255, 255, 0.1);
|
||||
}
|
||||
.submit-button:active, .submit-button.is-pressed {
|
||||
.submit-button:active, .submit-button.is-pressed, .profile-action-btn:active, .profile-action-btn.is-pressed {
|
||||
background-color: rgba(255, 255, 255, 0.5);
|
||||
}
|
||||
.add-action-button:active, .add-action-button.is-pressed {
|
||||
|
|
@ -758,3 +766,151 @@ sidebarelement:has(.icon-button:active) indicator:not(.active) {
|
|||
background-color: rgba(255, 255, 255, 0.06);
|
||||
background: rgba(255, 255, 255, 0.08);
|
||||
}
|
||||
|
||||
.profile-popup-container {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100vw;
|
||||
height: 100vh;
|
||||
z-index: 3000;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
pointer-events: none;
|
||||
}
|
||||
.profile-popup-container.show {
|
||||
pointer-events: auto;
|
||||
}
|
||||
.profile-popup-bg {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background: rgba(0, 0, 0, 0);
|
||||
backdrop-filter: blur(0);
|
||||
-webkit-backdrop-filter: blur(0);
|
||||
transition: background 0.3s ease, backdrop-filter 0.3s ease, -webkit-backdrop-filter 0.3s ease;
|
||||
}
|
||||
.profile-popup-container.show .profile-popup-bg {
|
||||
background: rgba(0, 0, 0, 0.4);
|
||||
backdrop-filter: blur(0.25rem);
|
||||
-webkit-backdrop-filter: blur(0.25rem);
|
||||
}
|
||||
.profile-popup-content {
|
||||
position: relative;
|
||||
width: 90vw;
|
||||
max-width: 31rem;
|
||||
height: 85vh;
|
||||
max-height: 44rem;
|
||||
background: var(--main-bg-color);
|
||||
border: var(--border-width) solid var(--light-border-color);
|
||||
border-radius: 0.9rem;
|
||||
overflow: hidden;
|
||||
box-shadow: 0 1rem 3rem rgba(0, 0, 0, 0.5);
|
||||
opacity: 0;
|
||||
transform: scale(0.6);
|
||||
transition: transform 0.2s cubic-bezier(0.4, -0.3, 0.7, 1), opacity 0.2s ease;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
.profile-popup-container.show .profile-popup-content {
|
||||
transform: scale(1);
|
||||
opacity: 1;
|
||||
transition: transform 0.25s cubic-bezier(0.2, 1.15, 0.4, 1), opacity 0.25s ease;
|
||||
}
|
||||
.profile-popup-close-btn {
|
||||
position: absolute;
|
||||
top: 1rem;
|
||||
right: 1rem;
|
||||
z-index: 10;
|
||||
background: rgba(0, 0, 0, 0.4);
|
||||
backdrop-filter: blur(0.25rem);
|
||||
-webkit-backdrop-filter: blur(0.25rem);
|
||||
border: none;
|
||||
width: 2.5rem;
|
||||
height: 2.5rem;
|
||||
border-radius: 0.8rem;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
cursor: pointer;
|
||||
}
|
||||
.profile-popup-close-btn svg {
|
||||
width: 1.5rem;
|
||||
height: 1.5rem;
|
||||
}
|
||||
.profile-popup-close-btn:hover {
|
||||
background: rgba(255, 255, 255, 0.2);
|
||||
}
|
||||
#profile-popup-inner {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
overflow-y: auto;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
.profile-banner {
|
||||
width: 100%;
|
||||
height: 12.5rem;
|
||||
background: linear-gradient(135deg, rgba(255,255,255,0.05), rgba(255,255,255,0.1));
|
||||
object-fit: cover;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
.profile-avatar-container {
|
||||
position: relative;
|
||||
margin-top: -3.75rem;
|
||||
margin-left: 2rem;
|
||||
width: 7.5rem;
|
||||
height: 7.5rem;
|
||||
}
|
||||
.profile-avatar {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
border-radius: 0.8rem;
|
||||
border: var(--border-width) solid rgba(255, 255, 255, 0.2);
|
||||
object-fit: cover;
|
||||
background: var(--main-bg-color);
|
||||
}
|
||||
.profile-info {
|
||||
padding: 1rem 2rem 2rem 2rem;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 1rem;
|
||||
}
|
||||
.profile-name {
|
||||
font-size: 2rem;
|
||||
font-weight: 800;
|
||||
line-height: 1.1;
|
||||
margin-bottom: 0.2rem;
|
||||
word-break: break-word;
|
||||
}
|
||||
.profile-id-host {
|
||||
font-size: 1rem;
|
||||
opacity: 0.6;
|
||||
font-weight: 600;
|
||||
}
|
||||
.profile-bio {
|
||||
font-size: 1.05rem;
|
||||
line-height: 1.5;
|
||||
white-space: pre-wrap;
|
||||
background: rgba(255, 255, 255, 0.03);
|
||||
padding: 1rem;
|
||||
border-radius: 0.8rem;
|
||||
border: var(--border-width) solid var(--light-border-color);
|
||||
word-break: break-word;
|
||||
}
|
||||
.profile-action-btn {
|
||||
align-self: flex-start;
|
||||
padding: 0.6rem 1.5rem;
|
||||
font-weight: 700;
|
||||
background: var(--text-color);
|
||||
color: var(--main-bg-color);
|
||||
border-radius: 0.8rem;
|
||||
margin-top: 0.5rem;
|
||||
margin-left: 0;
|
||||
height: auto;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -139,5 +139,10 @@
|
|||
"larp.redacted": "this meow was hissed away.",
|
||||
"placeholder.invitation.code": "invitation code meow",
|
||||
"info.messages.loading.older": "Loading older meowsages...",
|
||||
"error:message.not.found": "Meowsage not found"
|
||||
"error:message.not.found": "Meowsage not found",
|
||||
"title.profile": "cat profile",
|
||||
"title.settings": "cat settings",
|
||||
"title.logout": "log out",
|
||||
"action.edit.profile": "edit cat profile",
|
||||
"action.open.dm": "open direct meowchat"
|
||||
}
|
||||
|
|
@ -139,5 +139,10 @@
|
|||
"larp.redacted": "This message was deleted.",
|
||||
"placeholder.invitation.code": "invitation code",
|
||||
"info.messages.loading.older": "Loading older messages...",
|
||||
"error:message.not.found": "Message not found"
|
||||
"error:message.not.found": "Message not found",
|
||||
"title.profile": "Profile",
|
||||
"title.settings": "Settings",
|
||||
"title.logout": "Log out",
|
||||
"action.edit.profile": "Edit profile",
|
||||
"action.open.dm": "Open DM"
|
||||
}
|
||||
|
|
@ -49,7 +49,7 @@
|
|||
<sidebarelement id="sidebar-profile">
|
||||
<indicator>
|
||||
</indicator>
|
||||
<button class="icon-button" onclick="gotoSideProfilePopup()">
|
||||
<button class="icon-button">
|
||||
<img id="sidebar-pfp">
|
||||
</button>
|
||||
</sidebarelement>
|
||||
|
|
@ -79,6 +79,16 @@
|
|||
<div id="fixed-context-menu" class="context-menu">
|
||||
|
||||
</div>
|
||||
|
||||
<div id="profile-popup-container" class="profile-popup-container" style="display: none;">
|
||||
<div class="profile-popup-bg" onclick="closeProfile()"></div>
|
||||
<div class="profile-popup-content">
|
||||
<button class="profile-popup-close-btn" onclick="closeProfile()">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 -960 960 960" fill="var(--text-color)"><path d="m256-200-56-56 224-224-224-224 56-56 224 224 224-224 56 56-224 224 224 224-56 56-224-224-224 224Z"/></svg>
|
||||
</button>
|
||||
<div id="profile-popup-inner"></div>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
<script src="screens.js"></script>
|
||||
|
|
|
|||
106
webroot/main.js
106
webroot/main.js
|
|
@ -1411,6 +1411,10 @@ if (App) {
|
|||
}
|
||||
|
||||
function popstate() {
|
||||
if (isProfileOpen) {
|
||||
closeProfile();
|
||||
return;
|
||||
}
|
||||
if (!mainScreen.classList.contains('mobile-content') && !mainScreen.classList.contains('mobile-details')) {
|
||||
history.back();
|
||||
if (App) {
|
||||
|
|
@ -1421,8 +1425,108 @@ function popstate() {
|
|||
}
|
||||
|
||||
|
||||
function gotoSideProfilePopup() {
|
||||
|
||||
sidebarProfileButton.addEventListener("click", (e) => {
|
||||
e.stopPropagation();
|
||||
history.pushState({trap: true}, "", location.href);
|
||||
|
||||
if (fixedContextMenu.classList.contains("show")) {
|
||||
fixedContextMenu.classList.remove("show");
|
||||
if (typeof clearContextMenuStyles === "function") clearContextMenuStyles();
|
||||
setActiveSidebarIndicator(currentMainIndicator);
|
||||
} else {
|
||||
setActiveSidebarIndicator(sidebarProfileIndicator, true);
|
||||
const rect = sidebarProfileButton.getBoundingClientRect();
|
||||
showFixedContextMenu({top: rect.top, right: rect.right, bottom: rect.bottom, left: rect.left}, profileContextMenu);
|
||||
}
|
||||
});
|
||||
|
||||
function logout() {
|
||||
localStorage.clear();
|
||||
window.location.href = "login/index.html";
|
||||
}
|
||||
|
||||
function gotoSettings() {
|
||||
if (fixedContextMenu.classList.contains("show")) {
|
||||
fixedContextMenu.classList.remove("show");
|
||||
if (typeof clearContextMenuStyles === "function") clearContextMenuStyles();
|
||||
setActiveSidebarIndicator(currentMainIndicator);
|
||||
}
|
||||
}
|
||||
|
||||
let isProfileOpen = false;
|
||||
|
||||
async function openProfile(accountId) {
|
||||
if (fixedContextMenu.classList.contains("show")) {
|
||||
fixedContextMenu.classList.remove("show");
|
||||
if (typeof clearContextMenuStyles === "function") clearContextMenuStyles();
|
||||
setActiveSidebarIndicator(currentMainIndicator);
|
||||
}
|
||||
|
||||
let popupContainer = document.getElementById("profile-popup-container");
|
||||
let popupInner = document.getElementById("profile-popup-inner");
|
||||
|
||||
//show loading
|
||||
popupInner.innerHTML = '<div style="display: flex; justify-content: center; align-items: center; height: 100%;"><p>Loading profile...</p></div>';
|
||||
popupContainer.style.display = "flex";
|
||||
|
||||
//force reflow
|
||||
popupContainer.offsetHeight;
|
||||
|
||||
popupContainer.classList.add("show");
|
||||
isProfileOpen = true;
|
||||
|
||||
try {
|
||||
if (!accountId) accountId = window.id; //var fallback
|
||||
let nameWithHost = await fetchAsync(`${url}/idtoname?id=${accountId}`);
|
||||
if (nameWithHost.startsWith("error:")) nameWithHost = accountId; //api fallback
|
||||
|
||||
let nameParts = nameWithHost.split(":");
|
||||
let profileName = nameParts[0] || accountId;
|
||||
let profileHost = nameParts.slice(1).join(":") || host;
|
||||
|
||||
let pfpUrl = await getAvatarUrl(accountId, nameWithHost);
|
||||
|
||||
let bannerUrl = `${url}/user/storage/public/getentry?id=${accountId}&e=larp.profile.banner`;
|
||||
let bannerHtml = `<img src="${bannerUrl}" class="profile-banner" onerror="this.outerHTML='<div class=\\'profile-banner\\'></div>'">`;
|
||||
|
||||
let bio = await fetchAsync(`${url}/user/storage/public/getentry?id=${accountId}&e=larp.profile.bio`);
|
||||
if (bio.startsWith("error:")) bio = "";
|
||||
|
||||
let bioHtml = bio && bio.trim() !== "" ? `<div class="profile-bio">${bio.replace(/</g, "<").replace(/>/g, ">")}</div>` : "";
|
||||
|
||||
let isOwnProfile = accountId === id;
|
||||
let actionBtnHtml = isOwnProfile ?
|
||||
`<button class="profile-action-btn">Edit Profile</button>` :
|
||||
`<button class="profile-action-btn">Open DM</button>`;
|
||||
|
||||
popupInner.innerHTML = `
|
||||
${bannerHtml}
|
||||
<div class="profile-avatar-container">
|
||||
<img src="${pfpUrl}" class="profile-avatar">
|
||||
</div>
|
||||
<div class="profile-info">
|
||||
<div>
|
||||
<div class="profile-name">${profileName}</div>
|
||||
<div class="profile-id-host">${profileName}:${profileHost} (${accountId})</div>
|
||||
</div>
|
||||
${bioHtml}
|
||||
${actionBtnHtml}
|
||||
</div>
|
||||
`;
|
||||
} catch (e) {
|
||||
popupInner.innerHTML = '<div style="display: flex; justify-content: center; align-items: center; height: 100%;"><p>Failed to load profile.</p></div>';
|
||||
console.error(e);
|
||||
}
|
||||
}
|
||||
|
||||
function closeProfile() {
|
||||
let popupContainer = document.getElementById("profile-popup-container");
|
||||
popupContainer.classList.remove("show");
|
||||
isProfileOpen = false;
|
||||
setTimeout(() => {
|
||||
popupContainer.style.display = "none";
|
||||
}, 300);
|
||||
}
|
||||
|
||||
function setActiveRoombarItem(itemId) {
|
||||
|
|
|
|||
|
|
@ -217,6 +217,20 @@ var inboxRoomBar = `
|
|||
|
||||
|
||||
//context menus
|
||||
var profileContextMenu = `
|
||||
<button onclick="openProfile(window.id)">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="1.4rem" viewBox="0 -960 960 960" fill="var(--text-color)"><path d="M367-527q-47-47-47-113t47-113q47-47 113-47t113 47q47 47 47 113t-47 113q-47 47-113 47t-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 20v32Zm296.5-343.5Q560-607 560-640t-23.5-56.5Q513-720 480-720t-56.5 23.5Q400-673 400-640t23.5 56.5Q447-560 480-560t56.5-23.5ZM480-640Zm0 400Z"/></svg>
|
||||
<span class="blah">title.profile</span>
|
||||
</button>
|
||||
<button onclick="gotoSettings()">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="1.4rem" viewBox="0 -960 960 960" fill="var(--text-color)"><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"/></svg>
|
||||
<span class="blah">title.settings</span>
|
||||
</button>
|
||||
<button onclick="logout()">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="1.4rem" viewBox="0 -960 960 960" fill="var(--big-red)"><path d="M200-120q-33 0-56.5-23.5T120-200v-560q0-33 23.5-56.5T200-840h280v80H200v560h280v80H200Zm440-160-55-58 102-102H360v-80h327L585-622l55-58 200 200-200 200Z"/></svg>
|
||||
<span class="blah" style="color: var(--big-red)">title.logout</span>
|
||||
</button>
|
||||
`;
|
||||
var addSpaceMenu = `
|
||||
<button onclick="gotoJoinSpace()">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="1.4rem" viewBox="0 -960 960 960" fill="var(--text-color)"><path d="M440-280H280q-83 0-141.5-58.5T80-480q0-83 58.5-141.5T280-680h160v80H280q-50 0-85 35t-35 85q0 50 35 85t85 35h160v80ZM320-440v-80h320v80H320Zm200 160v-80h160q50 0 85-35t35-85q0-50-35-85t-85-35H520v-80h160q83 0 141.5 58.5T880-480q0 83-58.5 141.5T680-280H520Z"/></svg>
|
||||
|
|
|
|||
|
|
@ -111,6 +111,14 @@ input, textarea {
|
|||
-webkit-user-select: text !important;
|
||||
}
|
||||
|
||||
.chat-message-text, .chat-message-author, .chat-message-timestamp,
|
||||
.profile-name, .profile-bio, .profile-id-host,
|
||||
.dm-username, .group-name, .room-name {
|
||||
user-select: text !important;
|
||||
-webkit-user-select: text !important;
|
||||
cursor: auto;
|
||||
}
|
||||
|
||||
|
||||
indicator {
|
||||
content: "";
|
||||
|
|
@ -706,7 +714,7 @@ space{
|
|||
button:hover, input:hover, textarea:hover {
|
||||
background-color: rgba(255, 255, 255, 0.1);
|
||||
}
|
||||
.submit-button:hover {
|
||||
.submit-button:hover, .profile-action-btn:hover {
|
||||
background-color: rgba(255, 255, 255, 0.5);
|
||||
}
|
||||
.add-action-button:hover {
|
||||
|
|
@ -730,7 +738,7 @@ button:active, button.is-pressed, input:active, input.is-pressed, textarea:activ
|
|||
button.active, input.active, textarea.active {
|
||||
background-color: rgba(255, 255, 255, 0.1);
|
||||
}
|
||||
.submit-button:active, .submit-button.is-pressed {
|
||||
.submit-button:active, .submit-button.is-pressed, .profile-action-btn:active, .profile-action-btn.is-pressed {
|
||||
background-color: rgba(255, 255, 255, 0.5);
|
||||
}
|
||||
.add-action-button:active, .add-action-button.is-pressed {
|
||||
|
|
@ -758,3 +766,151 @@ sidebarelement:has(.icon-button:active) indicator:not(.active) {
|
|||
background-color: rgba(255, 255, 255, 0.06);
|
||||
background: rgba(255, 255, 255, 0.08);
|
||||
}
|
||||
|
||||
.profile-popup-container {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100vw;
|
||||
height: 100vh;
|
||||
z-index: 3000;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
pointer-events: none;
|
||||
}
|
||||
.profile-popup-container.show {
|
||||
pointer-events: auto;
|
||||
}
|
||||
.profile-popup-bg {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background: rgba(0, 0, 0, 0);
|
||||
backdrop-filter: blur(0);
|
||||
-webkit-backdrop-filter: blur(0);
|
||||
transition: background 0.3s ease, backdrop-filter 0.3s ease, -webkit-backdrop-filter 0.3s ease;
|
||||
}
|
||||
.profile-popup-container.show .profile-popup-bg {
|
||||
background: rgba(0, 0, 0, 0.4);
|
||||
backdrop-filter: blur(0.25rem);
|
||||
-webkit-backdrop-filter: blur(0.25rem);
|
||||
}
|
||||
.profile-popup-content {
|
||||
position: relative;
|
||||
width: 90vw;
|
||||
max-width: 31rem;
|
||||
height: 85vh;
|
||||
max-height: 44rem;
|
||||
background: var(--main-bg-color);
|
||||
border: var(--border-width) solid var(--light-border-color);
|
||||
border-radius: 0.9rem;
|
||||
overflow: hidden;
|
||||
box-shadow: 0 1rem 3rem rgba(0, 0, 0, 0.5);
|
||||
opacity: 0;
|
||||
transform: scale(0.6);
|
||||
transition: transform 0.2s cubic-bezier(0.4, -0.3, 0.7, 1), opacity 0.2s ease;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
.profile-popup-container.show .profile-popup-content {
|
||||
transform: scale(1);
|
||||
opacity: 1;
|
||||
transition: transform 0.25s cubic-bezier(0.2, 1.15, 0.4, 1), opacity 0.25s ease;
|
||||
}
|
||||
.profile-popup-close-btn {
|
||||
position: absolute;
|
||||
top: 1rem;
|
||||
right: 1rem;
|
||||
z-index: 10;
|
||||
background: rgba(0, 0, 0, 0.4);
|
||||
backdrop-filter: blur(0.25rem);
|
||||
-webkit-backdrop-filter: blur(0.25rem);
|
||||
border: none;
|
||||
width: 2.5rem;
|
||||
height: 2.5rem;
|
||||
border-radius: 0.8rem;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
cursor: pointer;
|
||||
}
|
||||
.profile-popup-close-btn svg {
|
||||
width: 1.5rem;
|
||||
height: 1.5rem;
|
||||
}
|
||||
.profile-popup-close-btn:hover {
|
||||
background: rgba(255, 255, 255, 0.2);
|
||||
}
|
||||
#profile-popup-inner {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
overflow-y: auto;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
.profile-banner {
|
||||
width: 100%;
|
||||
height: 12.5rem;
|
||||
background: linear-gradient(135deg, rgba(255,255,255,0.05), rgba(255,255,255,0.1));
|
||||
object-fit: cover;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
.profile-avatar-container {
|
||||
position: relative;
|
||||
margin-top: -3.75rem;
|
||||
margin-left: 2rem;
|
||||
width: 7.5rem;
|
||||
height: 7.5rem;
|
||||
}
|
||||
.profile-avatar {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
border-radius: 0.8rem;
|
||||
border: var(--border-width) solid rgba(255, 255, 255, 0.2);
|
||||
object-fit: cover;
|
||||
background: var(--main-bg-color);
|
||||
}
|
||||
.profile-info {
|
||||
padding: 1rem 2rem 2rem 2rem;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 1rem;
|
||||
}
|
||||
.profile-name {
|
||||
font-size: 2rem;
|
||||
font-weight: 800;
|
||||
line-height: 1.1;
|
||||
margin-bottom: 0.2rem;
|
||||
word-break: break-word;
|
||||
}
|
||||
.profile-id-host {
|
||||
font-size: 1rem;
|
||||
opacity: 0.6;
|
||||
font-weight: 600;
|
||||
}
|
||||
.profile-bio {
|
||||
font-size: 1.05rem;
|
||||
line-height: 1.5;
|
||||
white-space: pre-wrap;
|
||||
background: rgba(255, 255, 255, 0.03);
|
||||
padding: 1rem;
|
||||
border-radius: 0.8rem;
|
||||
border: var(--border-width) solid var(--light-border-color);
|
||||
word-break: break-word;
|
||||
}
|
||||
.profile-action-btn {
|
||||
align-self: flex-start;
|
||||
padding: 0.6rem 1.5rem;
|
||||
font-weight: 700;
|
||||
background: var(--text-color);
|
||||
color: var(--main-bg-color);
|
||||
border-radius: 0.8rem;
|
||||
margin-top: 0.5rem;
|
||||
margin-left: 0;
|
||||
height: auto;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue