-
-
-
-
desc.no.notifications
+
+ ${notifisEmptyState}
+
+
+`;
+
+var invitesEntry = `
+
+
+

+
+ {username}
+ {desc}
+
+
+
+ {actions}
`;
@@ -171,5 +199,3 @@ var addSpaceMenu = `
//elements
var detailsBtn = `
`;
var backBtnHtml = `
`;
-
-var invitesEntry = `???`;
\ No newline at end of file
diff --git a/android/app/src/main/assets/public/style.css b/android/app/src/main/assets/public/style.css
index f60e7de1..5ad2a2f2 100644
--- a/android/app/src/main/assets/public/style.css
+++ b/android/app/src/main/assets/public/style.css
@@ -13,10 +13,10 @@
--icon-button-height: 3.4rem;
--button-height: 2.4rem;
--border-width: 0.09rem;
-
- --big-default: rgb(207 207 207);
- --big-red: rgb(202 0 0);
- --big-green: rgb(25 189 0);
+
+ --big-default: rgb(207, 207, 207);
+ --big-red: rgb(195, 75, 75);
+ --big-green: rgb(75, 165, 95);
}
*:focus {
outline: none;
@@ -76,7 +76,7 @@ button, input {
background-color: rgba(255, 255, 255, 0.05);
margin: var(--button-margin);
padding: var(--button-margin);
-
+
height: var(--button-height);
display: flex;
cursor: pointer;
@@ -148,12 +148,13 @@ indicator.active {
width: calc(var(--icon-button-height) - (var(--border-width) * 2));
height: calc(var(--icon-button-height) - (var(--border-width) * 2));
pointer-events: none !important;
+ border-radius: 0.6rem;
}
roomcontent {
display: flex;
flex-direction: column;
-
+
height: 100%;
flex-grow: 1;
border-right: var(--border-width) solid var(--light-border-color);
@@ -161,7 +162,7 @@ roomcontent {
roomcontent2 {
display: flex;
flex-direction: column;
-
+
height: calc(100% - (var(--button-height) * 1.5));
width: 100%;
}
@@ -169,7 +170,7 @@ roomcontent2 {
sidebar {
display: flex;
flex-direction: column;
-
+
height: 100%;
width: calc(var(--icon-button-height) + (var(--button-margin) * 2) + var(--border-width));
border-right: var(--border-width) solid var(--light-border-color);
@@ -252,11 +253,11 @@ hr {
box-shadow: 0 0.5rem 2rem rgba(0, 0, 0, 0.4);
opacity: 0;
- transform: translateY(-1rem);
+ transform: translateY(-2rem);
transition:
- opacity 0.3s ease,
- transform 0.4s cubic-bezier(0.175, 0.885, 0.32, 1.275),
- background-color 0.2s ease;
+ opacity 0.2s ease,
+ transform 0.25s cubic-bezier(0.175, 0.885, 0.32, 1.275),
+ background-color 0.15s ease;
}
.notification.show {
opacity: 1;
@@ -290,8 +291,8 @@ roomtopbar {
sidebar.second#roomdetailsbar {
height: 100%;
display: flex;
- flex-direction: column;
- border-left: var(--border-width) solid var(--light-border-color);
+ flex-direction: column;
+ border-left: var(--border-width) solid var(--light-border-color);
}
fullcontainer {
width: 100%;
@@ -330,52 +331,7 @@ herotitle {
.bottom-element {
margin-top: auto;
}
-@media (hover: hover) {
- sidebarelement:hover indicator:not(.active) {
- content: "";
- position: absolute;
- width: 0;
- height: 1.2rem;
- left: -0.08rem;
- border: 0.15rem solid var(--text-color);
- border-radius: 0.8rem;
- transform: translateY(calc( ( var(--icon-button-height) + (var(--button-margin) * 2) ) / 2 - 0.6rem));
- }
- button:hover, input:hover {
- background-color: rgba(255, 255, 255, 0.1);
- }
- .submit-button:hover {
- background-color: rgba(255, 255, 255, 0.5);
- }
- .add-action-button:hover {
- background-color: rgba(255, 255, 255, 0.1);
- color: var(--text-color);
- }
-}
-button:active, button.is-pressed, input:active, input.is-pressed {
- background-color: rgba(255, 255, 255, 0.1);
- transform: var(--press-scale);
-}
-button.active, input.active {
- background-color: rgba(255, 255, 255, 0.1);
-}
-.submit-button:active, .submit-button.is-pressed {
- background-color: rgba(255, 255, 255, 0.5);
-}
-.add-action-button:active, .add-action-button.is-pressed {
- background-color: rgba(255, 255, 255, 0.1);
- color: var(--text-color);
-}
-sidebarelement:has(.icon-button:active) indicator:not(.active) {
- content: "";
- position: absolute;
- width: 0;
- height: 1.2rem;
- left: -0.08rem;
- border: 0.15rem solid var(--text-color);
- border-radius: 0.8rem;
- transform: translateY(calc( ( var(--icon-button-height) + (var(--button-margin) * 2) ) / 2 - 0.6rem));
-}
+
blah, inherit, .inherit {
all: inherit;
padding: 0;
@@ -419,9 +375,7 @@ space{
gap: 0.5rem;
font-weight: 600;
}
-.context-menu button:hover {
- background-color: rgba(255, 255, 255, 0.08);
-}
+
.mobile-nav-btn {
display: none;
background: transparent;
@@ -466,7 +420,7 @@ space{
sidebar, sidebar.second, roomcontent {
position: absolute !important;
height: 100%;
- transition: transform 0.3s cubic-bezier(0.25, 1, 0.5, 1);
+ transition: all 0.25s cubic-bezier(0.25, 1, 0.5, 1);
}
sidebar {
@@ -492,13 +446,13 @@ space{
}
#roomdetailsbar {
- left: auto !important;
+ left: auto !important;
right: 0;
- width: 90vw !important;
+ width: 90vw !important;
min-width: unset !important;
max-width: none !important;
- transform: translateX(100vw);
- z-index: 10;
+ transform: translateX(100vw);
+ z-index: 10;
background-color: var(--main-bg-color);
}
@@ -537,7 +491,7 @@ space{
opacity: 0;
pointer-events: none;
- transition: opacity 0.3s cubic-bezier(0.25, 1, 0.5, 1);
+ transition: all 0.25s cubic-bezier(0.25, 1, 0.5, 1);
}
main.mobile-details roomcontent::after {
@@ -553,4 +507,115 @@ space{
.submit-button.tab-inactive {
background-color: transparent;
color: var(--text-color);
+}
+
+.list-container {
+ flex-grow: 1;
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ padding: 1rem;
+ overflow-y: auto;
+ gap: 0.5rem;
+}
+.list-container.empty {
+ justify-content: center;
+ text-align: center;
+ opacity: 0.5;
+}
+
+.invite-entry {
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ padding: 0.8rem 1rem;
+ border: var(--border-width) solid var(--light-border-color);
+ border-radius: 0.8rem;
+ width: 100%;
+ background: rgba(255, 255, 255, 0.02);
+ flex-shrink: 0;
+}
+.invite-info {
+ display: flex;
+ align-items: center;
+ gap: 1rem;
+}
+.invite-pfp {
+ width: 2.8rem;
+ height: 2.8rem;
+ border-radius: 0.8rem;
+ object-fit: cover;
+}
+.invite-details {
+ display: flex;
+ flex-direction: column;
+ text-align: left;
+}
+.invite-name {
+ font-weight: 700;
+ font-size: 1.05rem;
+}
+.invite-desc {
+ font-size: 0.85rem;
+ opacity: 0.6;
+}
+.invite-actions {
+ display: flex;
+ gap: 0.5rem;
+}
+.invite-actions button {
+ margin: 0;
+}
+
+@media (hover: hover) {
+ sidebarelement:hover indicator:not(.active) {
+ content: "";
+ position: absolute;
+ width: 0;
+ height: 1.2rem;
+ left: -0.08rem;
+ border: 0.15rem solid var(--text-color);
+ border-radius: 0.8rem;
+ transform: translateY(calc( ( var(--icon-button-height) + (var(--button-margin) * 2) ) / 2 - 0.6rem));
+ }
+ button:hover, input:hover {
+ background-color: rgba(255, 255, 255, 0.1);
+ }
+ .submit-button:hover {
+ background-color: rgba(255, 255, 255, 0.5);
+ }
+ .add-action-button:hover {
+ background-color: rgba(255, 255, 255, 0.1);
+ color: var(--text-color);
+ }
+ .context-menu button:hover {
+ background-color: rgba(255, 255, 255, 0.08);
+ }
+}
+button:active, button.is-pressed, input:active, input.is-pressed {
+ background-color: rgba(255, 255, 255, 0.1);
+ transform: var(--press-scale);
+}
+button.active, input.active {
+ background-color: rgba(255, 255, 255, 0.1);
+}
+.submit-button:active, .submit-button.is-pressed {
+ background-color: rgba(255, 255, 255, 0.5);
+}
+.add-action-button:active, .add-action-button.is-pressed {
+ background-color: rgba(255, 255, 255, 0.1);
+ color: var(--text-color);
+}
+.context-menu button:active, .context-menu button.is-pressed {
+ background-color: rgba(255, 255, 255, 0.08);
+}
+sidebarelement:has(.icon-button:active) indicator:not(.active) {
+ content: "";
+ position: absolute;
+ width: 0;
+ height: 1.2rem;
+ left: -0.08rem;
+ border: 0.15rem solid var(--text-color);
+ border-radius: 0.8rem;
+ transform: translateY(calc( ( var(--icon-button-height) + (var(--button-margin) * 2) ) / 2 - 0.6rem));
}
\ No newline at end of file
diff --git a/webroot/blah/en-us.json b/webroot/blah/en-us.json
index f7cac081..056f4a5e 100644
--- a/webroot/blah/en-us.json
+++ b/webroot/blah/en-us.json
@@ -74,12 +74,21 @@
"title.unread": "Unread",
"desc.no.invites": "No invites found",
"desc.no.notifications": "No notifications found",
+ "desc.fetching.invites": "Fetching invites...",
+ "desc.fetching.notifications": "Fetching notifications...",
+ "desc.invite.dm.received": "{0} ({1}) invited you to chat",
+ "desc.invite.dm.sent": "You invited {0} ({1}) to chat",
+ "desc.invite.group.received": "{0} ({1}) invited you to a group",
+ "desc.invite.group.sent": "You invited {0} ({1}) to a group",
"action.fetching.invites.sent": "Fetching sent invites...",
"action.fetching.invites.recv": "Fetching received invites...",
"action.dm.fetch": "Fetching dms...",
- "action.dm.adding": "Adding...",
"action.auth": "Authenticating...",
+ "action.dm.adding": "Adding...",
+ "action.invite.revoking": "Revoking invite...",
+ "action.invite.accepting": "Accepting invite...",
+ "action.invite.declining": "Declining invite...",
"title.sign.up": "Sign Up",
"title.sign.in": "Sign In",
diff --git a/webroot/index.html b/webroot/index.html
index 046a1a58..d8662375 100644
--- a/webroot/index.html
+++ b/webroot/index.html
@@ -94,7 +94,7 @@
{
await updateProtocolAndUrl(window.location.hostname);
}
- sidebarPfp.src = await getAvatarUrl(username);
+ sidebarPfp.src = await getAvatarUrl(`${username}:${host}`);
showAction("action.auth", "startauth");
let res = await Auth(username, password);
diff --git a/webroot/main.js b/webroot/main.js
index 0bb3ee6a..49d76e4b 100644
--- a/webroot/main.js
+++ b/webroot/main.js
@@ -406,6 +406,7 @@ function showNotification(message, type = 'info', duration = 3500) {
notif.addEventListener('transitionend', () => {
notif.remove();
});
+ setTimeout(() => notif.remove(), 300);
}, duration);
}
@@ -419,7 +420,7 @@ function showAction(message, actionid) {
}
const notif = document.createElement('div');
- notif.className = `notification action`;
+ notif.className = `notification`;
notif.textContent = processBlah(message);
notif.id = `notification-${actionid}`;
@@ -438,9 +439,10 @@ function clearAction(actionid) {
notifications.forEach(notif => {
notif.classList.remove('show');
- notif.addEventListener('transitionend', () => {
+ notif.addEventListener('transitionend', async () => {
notif.remove();
}, { once: true });
+ setTimeout(() => notif.remove(), 300);
});
}
@@ -596,13 +598,27 @@ async function initBlahs() {
}
}
+function splitLimit(str, separator, limit) {
+ const parts = str.split(separator);
+
+ if (parts.length <= limit) {
+ return parts;
+ }
+
+ return [
+ ...parts.slice(0, limit - 1),
+ parts.slice(limit - 1).join(separator)
+ ];
+}
+
function processBlah(blahmessage) {
try {
if (!blahmessage.includes(":")) {
blahmessage = `:${blahmessage}`;
}
- let split = blahmessage.split(":");
+ let split = splitLimit(blahmessage, ":", 3);
+
let values = [];
try {
values = split[2].split(";");
@@ -614,6 +630,11 @@ function processBlah(blahmessage) {
let valueslist = "";
for (let i = 0; i < values.length; i++) {
let value = processBlah(values[i]);
+ if (value.startsWith(":"))
+ {
+ value = value.substring(1);
+ }
+
valueslist+=`${value}, `;
message = message.replaceAll(`{${i}}`, value);
@@ -964,60 +985,153 @@ function setActiveRoombarItem(itemId) {
}
}
+async function renderInvites(res, type) {
+ let container = document.getElementById("invites-container");
+ if (!container) return;
+
+ if (res && res != "") {
+
+ res = JSON.parse(res);
+
+ let invites = [
+ ...Object.entries(res.dms).map(([id, value]) => ({
+ id,
+ type: "dm",
+ ...value
+ })),
+
+ ...Object.entries(res.groups).map(([id, value]) => ({
+ id,
+ type: "group",
+ ...value
+ }))
+ ].sort((a, b) => b.timestamp - a.timestamp);
+
+ container.classList.remove("empty");
+ let html = "";
+ let count = 0;
+
+ for (let i = 0; i < invites.length; i++) {
+ let invite = invites[i];
+
+
+ if (invite.type === "dm") {
+ let id = invite.id;
+ if (!id.includes(":")) {
+ id += `:${host}`;
+ }
+ let username = await fetchAsync(`${url}/idtoname?id=${id}`);
+ if (!(username && username.trim() !== "")) return;
+ count++;
+
+ let pfp = await getAvatarUrl(username);
+
+ let actions = "";
+ let desc = "";
+
+ if (type === "received") {
+ desc = `:desc.invite.dm.received:${username};${id}`;
+ actions = `
+
+
+ `;
+ } else {
+ desc = `:desc.invite.dm.sent:${username};${id}`;
+ actions = `
+
+ `;
+ }
+
+ let entry = invitesEntry
+ .replaceAll("{username}", username.split(':')[0])
+ .replaceAll("{pfp}", pfp)
+ .replaceAll("{desc}", desc)
+ .replaceAll("{actions}", actions);
+
+ html += entry;
+ }
+ }
+
+ if (count > 0) {
+ container.innerHTML = html;
+ } else {
+ container.classList.add("empty");
+ container.innerHTML = invitesEmptyState;
+ }
+ } else {
+ container.classList.add("empty");
+ container.innerHTML = invitesEmptyState;
+ }
+
+ let blahTags = container.getElementsByTagName("blah");
+ for (let i = 0; i < blahTags.length; i++) {
+ blahTags[i].innerHTML = processBlah(blahTags[i].innerHTML);
+ }
+}
+
+async function loadInvites(tab) {
+ try {
+ showAction(`action.fetching.invites.${tab === 'received' ? 'recv' : 'sent'}`, `fetching.invites.${tab}`);
+ let res = await fetchEncrypted(`user/invites/${tab}`);
+ await renderInvites(res, tab);
+ } catch (e) {
+ showBlahNotification("error:something.wrong");
+ console.error(e);
+ await renderInvites("", tab);
+ }
+ clearAction(`fetching.invites.${tab}`);
+}
+
async function switchInvitesTab(tab) {
if (!document.getElementById(`tab-invites-${tab}`).classList.contains('tab-inactive')) return;
document.getElementById('tab-invites-received').classList.add('tab-inactive');
document.getElementById('tab-invites-sent').classList.add('tab-inactive');
document.getElementById(`tab-invites-${tab}`).classList.remove('tab-inactive');
- let container = document.getElementById("invites-container");
- let innerString = "";
-
- if (tab === "received")
- {
- try {
- showAction("action.fetching.invites.recv", "fetching.invites.recv");
- let res = await fetchEncrypted("user/invites/received");
- if (res !== "")
- {
- if (res.includes(",")) {
- console.log(res);
- }
- else
- {
- console.log(res);
- container.innerHTML = invitesEntry;
- }
- }
- }
- catch (e) {
- showBlahNotification("error:something.wrong");
- console.error(e);
- }
- clearAction("fetching.invites.recv");
+ await loadInvites(tab);
+}
+async function acceptInvite(username) { //TODO
+ try {
+ showAction("action.invite.accepting", "invite.action");
+ let res = await fetchEncrypted("user/dm/create", username);
+ clearAction("invite.action");
+ showBlahNotification(res || "success:invite.accepted");
+ await loadInvites('received');
+ } catch (e) {
+ clearAction("invite.action");
+ showBlahNotification("error:something.wrong");
}
- else if (tab === "sent")
- {
- try {
- showAction("action.fetching.invites.sent", "fetching.invites.sent");
- let res = await fetchEncrypted("user/invites/sent");
- if (res !== "")
- {
- if (res.includes(",")) {
- console.log(res);
- }
- else
- {
- console.log(res);
- container.innerHTML = invitesEntry;
- }
- }
- }
- catch (e) {
- showBlahNotification("error:something.wrong");
- console.error(e);
- }
- clearAction("fetching.invites.sent");
+}
+
+async function declineInvite(username) { //TODO
+ try {
+ showAction("action.invite.declining", "invite.action");
+ let res = await fetchEncrypted("user/dm/decline", username);
+ clearAction("invite.action");
+ showBlahNotification(res || "success:invite.declined");
+ await loadInvites('received');
+ } catch (e) {
+ clearAction("invite.action");
+ showBlahNotification("error:something.wrong");
+ }
+}
+
+async function revokeInvite(username) { //TODO
+ try {
+ showAction("action.invite.revoking", "invite.action");
+ let res = await fetchEncrypted("user/dm/revoke", username);
+ clearAction("invite.action");
+ showBlahNotification(res || "success:invite.revoked");
+ await loadInvites('sent');
+ } catch (e) {
+ clearAction("invite.action");
+ showBlahNotification("error:something.wrong");
}
}
diff --git a/webroot/screens.js b/webroot/screens.js
index 8a0c7085..94a426fd 100644
--- a/webroot/screens.js
+++ b/webroot/screens.js
@@ -73,30 +73,58 @@ var joinSpaceScreen = `
-
-
-
-
desc.no.invites
+
+ ${invitesLoadingState}
`;
+var notifisEmptyState = `
+
+
+
desc.no.notifications
+`;
+
var notifisScreen = `
-
-
-
-
desc.no.notifications
+
+ ${notifisEmptyState}
+
+
+`;
+
+var invitesEntry = `
+
+
+

+
+ {username}
+ {desc}
+
+
+
+ {actions}
`;
@@ -171,5 +199,3 @@ var addSpaceMenu = `
//elements
var detailsBtn = `
`;
var backBtnHtml = `
`;
-
-var invitesEntry = `???`;
\ No newline at end of file
diff --git a/webroot/style.css b/webroot/style.css
index f60e7de1..5ad2a2f2 100644
--- a/webroot/style.css
+++ b/webroot/style.css
@@ -13,10 +13,10 @@
--icon-button-height: 3.4rem;
--button-height: 2.4rem;
--border-width: 0.09rem;
-
- --big-default: rgb(207 207 207);
- --big-red: rgb(202 0 0);
- --big-green: rgb(25 189 0);
+
+ --big-default: rgb(207, 207, 207);
+ --big-red: rgb(195, 75, 75);
+ --big-green: rgb(75, 165, 95);
}
*:focus {
outline: none;
@@ -76,7 +76,7 @@ button, input {
background-color: rgba(255, 255, 255, 0.05);
margin: var(--button-margin);
padding: var(--button-margin);
-
+
height: var(--button-height);
display: flex;
cursor: pointer;
@@ -148,12 +148,13 @@ indicator.active {
width: calc(var(--icon-button-height) - (var(--border-width) * 2));
height: calc(var(--icon-button-height) - (var(--border-width) * 2));
pointer-events: none !important;
+ border-radius: 0.6rem;
}
roomcontent {
display: flex;
flex-direction: column;
-
+
height: 100%;
flex-grow: 1;
border-right: var(--border-width) solid var(--light-border-color);
@@ -161,7 +162,7 @@ roomcontent {
roomcontent2 {
display: flex;
flex-direction: column;
-
+
height: calc(100% - (var(--button-height) * 1.5));
width: 100%;
}
@@ -169,7 +170,7 @@ roomcontent2 {
sidebar {
display: flex;
flex-direction: column;
-
+
height: 100%;
width: calc(var(--icon-button-height) + (var(--button-margin) * 2) + var(--border-width));
border-right: var(--border-width) solid var(--light-border-color);
@@ -252,11 +253,11 @@ hr {
box-shadow: 0 0.5rem 2rem rgba(0, 0, 0, 0.4);
opacity: 0;
- transform: translateY(-1rem);
+ transform: translateY(-2rem);
transition:
- opacity 0.3s ease,
- transform 0.4s cubic-bezier(0.175, 0.885, 0.32, 1.275),
- background-color 0.2s ease;
+ opacity 0.2s ease,
+ transform 0.25s cubic-bezier(0.175, 0.885, 0.32, 1.275),
+ background-color 0.15s ease;
}
.notification.show {
opacity: 1;
@@ -290,8 +291,8 @@ roomtopbar {
sidebar.second#roomdetailsbar {
height: 100%;
display: flex;
- flex-direction: column;
- border-left: var(--border-width) solid var(--light-border-color);
+ flex-direction: column;
+ border-left: var(--border-width) solid var(--light-border-color);
}
fullcontainer {
width: 100%;
@@ -330,52 +331,7 @@ herotitle {
.bottom-element {
margin-top: auto;
}
-@media (hover: hover) {
- sidebarelement:hover indicator:not(.active) {
- content: "";
- position: absolute;
- width: 0;
- height: 1.2rem;
- left: -0.08rem;
- border: 0.15rem solid var(--text-color);
- border-radius: 0.8rem;
- transform: translateY(calc( ( var(--icon-button-height) + (var(--button-margin) * 2) ) / 2 - 0.6rem));
- }
- button:hover, input:hover {
- background-color: rgba(255, 255, 255, 0.1);
- }
- .submit-button:hover {
- background-color: rgba(255, 255, 255, 0.5);
- }
- .add-action-button:hover {
- background-color: rgba(255, 255, 255, 0.1);
- color: var(--text-color);
- }
-}
-button:active, button.is-pressed, input:active, input.is-pressed {
- background-color: rgba(255, 255, 255, 0.1);
- transform: var(--press-scale);
-}
-button.active, input.active {
- background-color: rgba(255, 255, 255, 0.1);
-}
-.submit-button:active, .submit-button.is-pressed {
- background-color: rgba(255, 255, 255, 0.5);
-}
-.add-action-button:active, .add-action-button.is-pressed {
- background-color: rgba(255, 255, 255, 0.1);
- color: var(--text-color);
-}
-sidebarelement:has(.icon-button:active) indicator:not(.active) {
- content: "";
- position: absolute;
- width: 0;
- height: 1.2rem;
- left: -0.08rem;
- border: 0.15rem solid var(--text-color);
- border-radius: 0.8rem;
- transform: translateY(calc( ( var(--icon-button-height) + (var(--button-margin) * 2) ) / 2 - 0.6rem));
-}
+
blah, inherit, .inherit {
all: inherit;
padding: 0;
@@ -419,9 +375,7 @@ space{
gap: 0.5rem;
font-weight: 600;
}
-.context-menu button:hover {
- background-color: rgba(255, 255, 255, 0.08);
-}
+
.mobile-nav-btn {
display: none;
background: transparent;
@@ -466,7 +420,7 @@ space{
sidebar, sidebar.second, roomcontent {
position: absolute !important;
height: 100%;
- transition: transform 0.3s cubic-bezier(0.25, 1, 0.5, 1);
+ transition: all 0.25s cubic-bezier(0.25, 1, 0.5, 1);
}
sidebar {
@@ -492,13 +446,13 @@ space{
}
#roomdetailsbar {
- left: auto !important;
+ left: auto !important;
right: 0;
- width: 90vw !important;
+ width: 90vw !important;
min-width: unset !important;
max-width: none !important;
- transform: translateX(100vw);
- z-index: 10;
+ transform: translateX(100vw);
+ z-index: 10;
background-color: var(--main-bg-color);
}
@@ -537,7 +491,7 @@ space{
opacity: 0;
pointer-events: none;
- transition: opacity 0.3s cubic-bezier(0.25, 1, 0.5, 1);
+ transition: all 0.25s cubic-bezier(0.25, 1, 0.5, 1);
}
main.mobile-details roomcontent::after {
@@ -553,4 +507,115 @@ space{
.submit-button.tab-inactive {
background-color: transparent;
color: var(--text-color);
+}
+
+.list-container {
+ flex-grow: 1;
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ padding: 1rem;
+ overflow-y: auto;
+ gap: 0.5rem;
+}
+.list-container.empty {
+ justify-content: center;
+ text-align: center;
+ opacity: 0.5;
+}
+
+.invite-entry {
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ padding: 0.8rem 1rem;
+ border: var(--border-width) solid var(--light-border-color);
+ border-radius: 0.8rem;
+ width: 100%;
+ background: rgba(255, 255, 255, 0.02);
+ flex-shrink: 0;
+}
+.invite-info {
+ display: flex;
+ align-items: center;
+ gap: 1rem;
+}
+.invite-pfp {
+ width: 2.8rem;
+ height: 2.8rem;
+ border-radius: 0.8rem;
+ object-fit: cover;
+}
+.invite-details {
+ display: flex;
+ flex-direction: column;
+ text-align: left;
+}
+.invite-name {
+ font-weight: 700;
+ font-size: 1.05rem;
+}
+.invite-desc {
+ font-size: 0.85rem;
+ opacity: 0.6;
+}
+.invite-actions {
+ display: flex;
+ gap: 0.5rem;
+}
+.invite-actions button {
+ margin: 0;
+}
+
+@media (hover: hover) {
+ sidebarelement:hover indicator:not(.active) {
+ content: "";
+ position: absolute;
+ width: 0;
+ height: 1.2rem;
+ left: -0.08rem;
+ border: 0.15rem solid var(--text-color);
+ border-radius: 0.8rem;
+ transform: translateY(calc( ( var(--icon-button-height) + (var(--button-margin) * 2) ) / 2 - 0.6rem));
+ }
+ button:hover, input:hover {
+ background-color: rgba(255, 255, 255, 0.1);
+ }
+ .submit-button:hover {
+ background-color: rgba(255, 255, 255, 0.5);
+ }
+ .add-action-button:hover {
+ background-color: rgba(255, 255, 255, 0.1);
+ color: var(--text-color);
+ }
+ .context-menu button:hover {
+ background-color: rgba(255, 255, 255, 0.08);
+ }
+}
+button:active, button.is-pressed, input:active, input.is-pressed {
+ background-color: rgba(255, 255, 255, 0.1);
+ transform: var(--press-scale);
+}
+button.active, input.active {
+ background-color: rgba(255, 255, 255, 0.1);
+}
+.submit-button:active, .submit-button.is-pressed {
+ background-color: rgba(255, 255, 255, 0.5);
+}
+.add-action-button:active, .add-action-button.is-pressed {
+ background-color: rgba(255, 255, 255, 0.1);
+ color: var(--text-color);
+}
+.context-menu button:active, .context-menu button.is-pressed {
+ background-color: rgba(255, 255, 255, 0.08);
+}
+sidebarelement:has(.icon-button:active) indicator:not(.active) {
+ content: "";
+ position: absolute;
+ width: 0;
+ height: 1.2rem;
+ left: -0.08rem;
+ border: 0.15rem solid var(--text-color);
+ border-radius: 0.8rem;
+ transform: translateY(calc( ( var(--icon-button-height) + (var(--button-margin) * 2) ) / 2 - 0.6rem));
}
\ No newline at end of file