Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
147 changes: 145 additions & 2 deletions src/components/sidebar/index.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import toast from "components/toast";
import "./style.scss";
import Ref from "html-tag-js/ref";
import actionStack from "lib/actionStack";
import auth, { loginEvents } from "lib/auth";
import constants from "lib/constants";

let $sidebar;
Expand Down Expand Up @@ -33,6 +35,8 @@ function create($container, $toggler) {
const MIN_WIDTH = 200; //Min width of the side bar
const MAX_WIDTH = () => innerWidth * 0.7; //Max width of the side bar
const resizeBar = new Ref();
const userAvatar = new Ref();
const userContextMenu = new Ref();

$container = $container || app;
let mode = innerWidth > 600 ? "tab" : "phone";
Expand All @@ -41,13 +45,34 @@ function create($container, $toggler) {
const eventOptions = { passive: false };
const $el = (
<div id="sidebar" className={mode}>
<div className="apps"></div>
<div className="apps">
<div className="app-icons-container"></div>
<div
ref={userAvatar}
className="user-icon-container"
onclick={handleUserIconClick}
>
<span className="icon account_circle"></span>
</div>
</div>
<div className="container"></div>
<div
className="resize-bar w-resize"
onmousedown={onresize}
ontouchstart={onresize}
></div>

<div ref={userContextMenu} className="user-menu">
<div className="user-menu-header">
<div className="user-menu-name"></div>
<div className="user-menu-email"></div>
</div>
{/* <div className="user-menu-separator"></div> */}
<div className="user-menu-item" onclick={handleLogout}>
<span className="icon logout"></span>
{strings.logout}
</div>
</div>
</div>
);
const mask = <span className="mask" onclick={hide}></span>;
Expand All @@ -72,6 +97,113 @@ function create($container, $toggler) {
show();
}

loginEvents.on(() => {
updateSidebarAvatar();
});

async function handleUserIconClick(e) {
try {
const isLoggedIn = await auth.isLoggedIn();

if (!isLoggedIn) {
auth.openLoginUrl();
} else {
toggleUserMenu();
}
} catch (error) {
console.error("Error checking login status:", error);
toast("Error checking login status", 3000);
}
}

function toggleUserMenu() {
const menu = userContextMenu.el;
const isActive = menu.classList.toggle("active");

if (isActive) {
// Populate user info
updateUserMenuInfo();

// Add click outside listener
setTimeout(() => {
document.addEventListener("click", handleClickOutside);
}, 10);
} else {
document.removeEventListener("click", handleClickOutside);
}
}

function handleClickOutside(e) {
if (
!userContextMenu.el.contains(e.target) &&
e.target !== userAvatar.el &&
!userAvatar.el.contains(e.target)
) {
userContextMenu.el.classList.remove("active");
document.removeEventListener("click", handleClickOutside);
}
}

async function updateUserMenuInfo() {
try {
const userInfo = await auth.getUserInfo();
if (userInfo) {
const menuName = userContextMenu.el.querySelector(".user-menu-name");
const menuEmail = userContextMenu.el.querySelector(".user-menu-email");
menuName.textContent = userInfo.name || "Anonymous";
if (userInfo.isAdmin) {
menuName.innerHTML += ' <span class="badge">Admin</span>';
}
menuEmail.textContent = userInfo.email || "";
}
} catch (error) {
console.error("Error fetching user info:", error);
}
}

async function handleLogout() {
try {
const success = await auth.logout();
if (success) {
userContextMenu.el.classList.remove("active");
document.removeEventListener("click", handleClickOutside);
toast("Logged out successfully");
updateSidebarAvatar();
} else {
toast("Failed to logout");
}
} catch (error) {
console.error("Error during logout:", error);
}
}

async function updateSidebarAvatar() {
const avatarUrl = await auth.getAvatar();
// Remove existing icon or avatar
const existingIcon = userAvatar.el.querySelector(".icon");
const existingAvatar = userAvatar.el.querySelector(".avatar");

if (existingIcon) {
existingIcon.remove();
}
if (existingAvatar) {
existingAvatar.remove();
}

if (avatarUrl?.startsWith("data:") || avatarUrl?.startsWith("http")) {
// Create and add avatar image
const avatarImg = document.createElement("img");
avatarImg.className = "avatar";
avatarImg.src = avatarUrl;
userAvatar.append(avatarImg);
} else {
// Fallback to default icon
const defaultIcon = document.createElement("span");
defaultIcon.className = "icon account_circle";
userAvatar.append(defaultIcon);
}
}

function onWindowResize() {
clearTimeout(resizeTimeout);
resizeTimeout = setTimeout(() => {
Expand Down Expand Up @@ -148,9 +280,20 @@ function create($container, $toggler) {
openedFolders = [];
}

function onshow() {
async function onshow() {
if ($el.onshow) $el.onshow.call($el);
events.show.forEach((fn) => fn());

// try {
// if (await auth.isLoggedIn()) {
// const avatar = await auth.getAvatar();
// if (avatar) {
// auth.updateSidebarAvatar(avatar);
// }
// }
// } catch (error) {
// console.error("Error updating avatar:", error);
// }
}

function onhide() {
Expand Down
103 changes: 102 additions & 1 deletion src/components/sidebar/style.scss
Original file line number Diff line number Diff line change
Expand Up @@ -59,9 +59,47 @@ body.no-animation {
min-width: 45px;
height: 100%;
background-color: rgba(0, 0, 0, 0.2);
overflow: auto;
padding: 10px 0;
display: flex;
flex-direction: column;
position: relative;
.app-icons-container {
flex: 1;
overflow-y: auto;
padding: 10px 0;
}
.user-icon-container {
position: sticky;
bottom: 0;
width: 100%;
padding: 10px 0;
display: flex;
justify-content: center;
border-top: 1px solid var(--border-color);
.avatar {
display: block;
height: 35px;
width: 35px;
border-radius: 50%;
object-fit: cover;
object-position: center;
}
.icon {
height: 40px;
width: 40px;
color: currentColor;
font-size: 1.6em;
border-radius: 12px;
opacity: 0.5;
transition: all 0.2s ease;
margin: 0 auto;
cursor: pointer;

&.active {
opacity: 1;
}
}
}
.icon {
height: 35px;
width: 35px;
Expand Down Expand Up @@ -210,3 +248,66 @@ body.no-animation {
}
}
}

.user-menu {
position: absolute;
bottom: 55px;
left: 30px;
width: 200px;
background-color: var(--popup-background-color);
border: 1px solid var(--border-color);
border-radius: 6px;
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.2);
display: none;
z-index: 1000;
overflow: hidden;
&.active {
display: block;
}
.user-menu-header {
padding: 12px;
border-bottom: 1px solid var(--border-color);

.user-menu-name {
font-weight: 500;
margin-bottom: 4px;

.badge {
display: inline-flex;
align-items: center;
background-color: color-mix(
in srgb,
var(--error-text-color) 20%,
transparent
);
color: var(--error-text-color);
padding: 2px 6px;
border-radius: 4px;
font-size: 12px;
font-weight: 500;
margin-left: 8px;
}
}

.user-menu-email {
font-size: 12px;
color: color-mix(in srgb, var(--popup-text-color) 70%, transparent);
}
}

.user-menu-item {
padding: 10px 12px;
cursor: pointer;
display: flex;
align-items: center;
gap: 8px;
&:hover {
background-color: var(--active-icon-color);
}
}
.user-menu-separator {
height: 1px;
background-color: var(--border-color);
margin: 4px 0;
}
}
Loading