diff --git a/frontend/src/app/core/main-menu/main-menu-toggle.service.ts b/frontend/src/app/core/main-menu/main-menu-toggle.service.ts index 6db9707b6dca..f98505cc2413 100644 --- a/frontend/src/app/core/main-menu/main-menu-toggle.service.ts +++ b/frontend/src/app/core/main-menu/main-menu-toggle.service.ts @@ -66,12 +66,18 @@ export class MainMenuToggleService { private changeData = new BehaviorSubject({}); public changeData$ = this.changeData.asObservable(); + private wasHiddenDueToResize = false; + + private wasCollapsedByUser = false; constructor( protected I18n:I18nService, public injector:Injector, readonly deviceService:DeviceService, ) { + this.initializeMenu(); + // Add resize event listener + window.addEventListener('resize', this.onWindowResize.bind(this)); } public initializeMenu():void { @@ -80,45 +86,57 @@ export class MainMenuToggleService { } this.elementWidth = parseInt(window.OpenProject.guardedLocalStorage(this.localStorageKey) as string); - const menuCollapsed = window.OpenProject.guardedLocalStorage(this.localStorageStateKey) as string; + const menuCollapsed = window.OpenProject.guardedLocalStorage(this.localStorageStateKey) === 'true'; + + // Set the initial value of the collapse tracking flag + this.wasCollapsedByUser = menuCollapsed; if (!this.elementWidth) { this.saveWidth(this.mainMenu.offsetWidth); - } else if (menuCollapsed && JSON.parse(menuCollapsed)) { + } else if (menuCollapsed) { this.closeMenu(); } else { this.setWidth(); } - const currentProject:CurrentProjectService = this.injector.get(CurrentProjectService); - if (jQuery(document.body).hasClass('controller-my') && this.elementWidth === 0 || currentProject.id === null) { - this.saveWidth(this.defaultWidth); - } + this.adjustMenuVisibility(); + } - // small desktop version default: hide menu on initialization - this.closeWhenOnSmallDesktop(); + private onWindowResize():void { + this.adjustMenuVisibility(); + } + + private adjustMenuVisibility():void { + if (window.innerWidth >= 1012) { + // On larger screens, reopen the menu if it was hidden only due to screen resizing + if (this.wasHiddenDueToResize && !this.wasCollapsedByUser) { + this.setWidth(this.defaultWidth); + this.wasHiddenDueToResize = false; // Reset the flag since the menu is now shown + } + } else if (this.showNavigation) { + this.closeMenu(); + this.wasHiddenDueToResize = true; // Indicate that the menu was hidden due to resize + } } - // click on arrow or hamburger icon public toggleNavigation(event?:JQuery.TriggeredEvent|Event):void { if (event) { event.stopPropagation(); event.preventDefault(); } - if (!this.showNavigation) { // sidebar is hidden -> show menu - if (this.deviceService.isSmallDesktop) { // small desktop version - this.setWidth(window.innerWidth); - } else { // desktop version - const savedWidth = parseInt(window.OpenProject.guardedLocalStorage(this.localStorageKey) as string); - const widthToSave = savedWidth >= this.elementMinWidth ? savedWidth : this.defaultWidth; + // Update the user collapse flag and clear `wasHiddenDueToResize` + this.wasCollapsedByUser = this.showNavigation; + this.wasHiddenDueToResize = false; // Reset because a manual toggle overrides any resize behavior - this.saveWidth(widthToSave); - } - } else { // sidebar is expanded -> close menu + if (this.showNavigation) { this.closeMenu(); + } else { + this.openMenu(); } + // Save the collapsed state in localStorage + window.OpenProject.guardedLocalStorage(this.localStorageStateKey, String(!this.showNavigation)); // Set focus on first visible main menu item. // This needs to be called after AngularJS has rendered the menu, which happens some when after(!) we leave this // method here. So we need to set the focus after a timeout. @@ -129,48 +147,43 @@ export class MainMenuToggleService { public closeMenu():void { this.setWidth(0); - window.OpenProject.guardedLocalStorage(this.localStorageStateKey, 'true'); jQuery('.searchable-menu--search-input').blur(); } - public closeWhenOnSmallDesktop():void { - if (this.deviceService.isSmallDesktop) { - this.closeMenu(); - window.OpenProject.guardedLocalStorage(this.localStorageStateKey, 'false'); - } - } - - public saveWidth(width?:number):void { - this.setWidth(width); - window.OpenProject.guardedLocalStorage(this.localStorageKey, String(this.elementWidth)); - window.OpenProject.guardedLocalStorage(this.localStorageStateKey, String(this.elementWidth === 0)); + public openMenu():void { + this.setWidth(this.defaultWidth); } - public setWidth(width?:any):void { + public setWidth(width?:number):void { if (width !== undefined) { - // Leave a minimum amount of space for space for the content - const maxMenuWidth = this.deviceService.isSmallDesktop ? window.innerWidth - 120 : window.innerWidth - 520; - if (width > maxMenuWidth) { - this.elementWidth = maxMenuWidth; - } else { - this.elementWidth = width as number; - } + this.elementWidth = width; } + // Apply the width directly to the main menu + this.mainMenu.style.width = `${this.elementWidth}px`; + + // Apply to root CSS variable for any related layout adjustments + this.htmlNode.style.setProperty('--main-menu-width', `${this.elementWidth}px`); + + // Check if menu is open or closed and apply CSS class if needed + this.toggleClassHidden(); this.snapBack(); this.setToggleTitle(); - this.toggleClassHidden(); - this.global.showNavigation = this.showNavigation; - this.htmlNode.style.setProperty('--main-menu-width', `${this.elementWidth}px`); + // Save the width if it's open + if (this.elementWidth > 0) { + window.OpenProject.guardedLocalStorage(this.localStorageKey, String(this.elementWidth)); + } + } - // Send change event when size of menu is changing (menu toggled or resized) - const changeEvent = jQuery.Event('change'); - this.changeData.next(changeEvent); + public saveWidth(width?:number):void { + this.setWidth(width); + window.OpenProject.guardedLocalStorage(this.localStorageKey, String(this.elementWidth)); + window.OpenProject.guardedLocalStorage(this.localStorageStateKey, String(this.elementWidth === 0)); } public get showNavigation():boolean { - return (this.elementWidth >= this.elementMinWidth); + return this.elementWidth >= this.elementMinWidth; } private snapBack():void { @@ -189,6 +202,7 @@ export class MainMenuToggleService { } private toggleClassHidden():void { - this.hideElements.toggleClass('hidden-navigation', !this.showNavigation); + const isHidden = this.elementWidth < this.elementMinWidth; + this.hideElements.toggleClass('hidden-navigation', isHidden); } }