1+ import toast from "components/toast" ;
12import "./style.scss" ;
23import Ref from "html-tag-js/ref" ;
34import actionStack from "lib/actionStack" ;
5+ import auth , { loginEvents } from "lib/auth" ;
46import constants from "lib/constants" ;
57
68let $sidebar ;
@@ -33,6 +35,8 @@ function create($container, $toggler) {
3335 const MIN_WIDTH = 200 ; //Min width of the side bar
3436 const MAX_WIDTH = ( ) => innerWidth * 0.7 ; //Max width of the side bar
3537 const resizeBar = new Ref ( ) ;
38+ const userAvatar = new Ref ( ) ;
39+ const userContextMenu = new Ref ( ) ;
3640
3741 $container = $container || app ;
3842 let mode = innerWidth > 600 ? "tab" : "phone" ;
@@ -41,13 +45,34 @@ function create($container, $toggler) {
4145 const eventOptions = { passive : false } ;
4246 const $el = (
4347 < div id = "sidebar" className = { mode } >
44- < div className = "apps" > </ div >
48+ < div className = "apps" >
49+ < div className = "app-icons-container" > </ div >
50+ < div
51+ ref = { userAvatar }
52+ className = "user-icon-container"
53+ onclick = { handleUserIconClick }
54+ >
55+ < span className = "icon account_circle" > </ span >
56+ </ div >
57+ </ div >
4558 < div className = "container" > </ div >
4659 < div
4760 className = "resize-bar w-resize"
4861 onmousedown = { onresize }
4962 ontouchstart = { onresize }
5063 > </ div >
64+
65+ < div ref = { userContextMenu } className = "user-menu" >
66+ < div className = "user-menu-header" >
67+ < div className = "user-menu-name" > </ div >
68+ < div className = "user-menu-email" > </ div >
69+ </ div >
70+ { /* <div className="user-menu-separator"></div> */ }
71+ < div className = "user-menu-item" onclick = { handleLogout } >
72+ < span className = "icon logout" > </ span >
73+ { strings . logout }
74+ </ div >
75+ </ div >
5176 </ div >
5277 ) ;
5378 const mask = < span className = "mask" onclick = { hide } > </ span > ;
@@ -72,6 +97,113 @@ function create($container, $toggler) {
7297 show ( ) ;
7398 }
7499
100+ loginEvents . on ( ( ) => {
101+ updateSidebarAvatar ( ) ;
102+ } ) ;
103+
104+ async function handleUserIconClick ( e ) {
105+ try {
106+ const isLoggedIn = await auth . isLoggedIn ( ) ;
107+
108+ if ( ! isLoggedIn ) {
109+ auth . openLoginUrl ( ) ;
110+ } else {
111+ toggleUserMenu ( ) ;
112+ }
113+ } catch ( error ) {
114+ console . error ( "Error checking login status:" , error ) ;
115+ toast ( "Error checking login status" , 3000 ) ;
116+ }
117+ }
118+
119+ function toggleUserMenu ( ) {
120+ const menu = userContextMenu . el ;
121+ const isActive = menu . classList . toggle ( "active" ) ;
122+
123+ if ( isActive ) {
124+ // Populate user info
125+ updateUserMenuInfo ( ) ;
126+
127+ // Add click outside listener
128+ setTimeout ( ( ) => {
129+ document . addEventListener ( "click" , handleClickOutside ) ;
130+ } , 10 ) ;
131+ } else {
132+ document . removeEventListener ( "click" , handleClickOutside ) ;
133+ }
134+ }
135+
136+ function handleClickOutside ( e ) {
137+ if (
138+ ! userContextMenu . el . contains ( e . target ) &&
139+ e . target !== userAvatar . el &&
140+ ! userAvatar . el . contains ( e . target )
141+ ) {
142+ userContextMenu . el . classList . remove ( "active" ) ;
143+ document . removeEventListener ( "click" , handleClickOutside ) ;
144+ }
145+ }
146+
147+ async function updateUserMenuInfo ( ) {
148+ try {
149+ const userInfo = await auth . getUserInfo ( ) ;
150+ if ( userInfo ) {
151+ const menuName = userContextMenu . el . querySelector ( ".user-menu-name" ) ;
152+ const menuEmail = userContextMenu . el . querySelector ( ".user-menu-email" ) ;
153+ menuName . textContent = userInfo . name || "Anonymous" ;
154+ if ( userInfo . isAdmin ) {
155+ menuName . innerHTML += ' <span class="badge">Admin</span>' ;
156+ }
157+ menuEmail . textContent = userInfo . email || "" ;
158+ }
159+ } catch ( error ) {
160+ console . error ( "Error fetching user info:" , error ) ;
161+ }
162+ }
163+
164+ async function handleLogout ( ) {
165+ try {
166+ const success = await auth . logout ( ) ;
167+ if ( success ) {
168+ userContextMenu . el . classList . remove ( "active" ) ;
169+ document . removeEventListener ( "click" , handleClickOutside ) ;
170+ toast ( "Logged out successfully" ) ;
171+ updateSidebarAvatar ( ) ;
172+ } else {
173+ toast ( "Failed to logout" ) ;
174+ }
175+ } catch ( error ) {
176+ console . error ( "Error during logout:" , error ) ;
177+ }
178+ }
179+
180+ async function updateSidebarAvatar ( ) {
181+ const avatarUrl = await auth . getAvatar ( ) ;
182+ // Remove existing icon or avatar
183+ const existingIcon = userAvatar . el . querySelector ( ".icon" ) ;
184+ const existingAvatar = userAvatar . el . querySelector ( ".avatar" ) ;
185+
186+ if ( existingIcon ) {
187+ existingIcon . remove ( ) ;
188+ }
189+ if ( existingAvatar ) {
190+ existingAvatar . remove ( ) ;
191+ }
192+
193+ if ( avatarUrl ?. startsWith ( "data:" ) || avatarUrl ?. startsWith ( "http" ) ) {
194+ // Create and add avatar image
195+ const avatarImg = document . createElement ( "img" ) ;
196+ avatarImg . className = "avatar" ;
197+ avatarImg . src = avatarUrl ;
198+ userAvatar . append ( avatarImg ) ;
199+ } else {
200+ // Fallback to default icon
201+ const defaultIcon = document . createElement ( "span" ) ;
202+ defaultIcon . className = "icon account_circle" ;
203+ userAvatar . append ( defaultIcon ) ;
204+ }
205+ }
206+
75207 function onWindowResize ( ) {
76208 clearTimeout ( resizeTimeout ) ;
77209 resizeTimeout = setTimeout ( ( ) => {
@@ -148,9 +280,20 @@ function create($container, $toggler) {
148280 openedFolders = [ ] ;
149281 }
150282
151- function onshow ( ) {
283+ async function onshow ( ) {
152284 if ( $el . onshow ) $el . onshow . call ( $el ) ;
153285 events . show . forEach ( ( fn ) => fn ( ) ) ;
286+
287+ // try {
288+ // if (await auth.isLoggedIn()) {
289+ // const avatar = await auth.getAvatar();
290+ // if (avatar) {
291+ // auth.updateSidebarAvatar(avatar);
292+ // }
293+ // }
294+ // } catch (error) {
295+ // console.error("Error updating avatar:", error);
296+ // }
154297 }
155298
156299 function onhide ( ) {
0 commit comments