+ onActiveLinkScrollToAnchor (link: HTMLAnchorElement) {
+ const linkURL = link.getAttribute('href')
+ const linkHash = link.getAttribute('fragment')
+
+ // On same url without fragment restore top scroll position
+ if (!linkHash && this.router.url.includes(linkURL)) {
+ scrollToTop('smooth')
+ }
+
+ // On same url with fragment restore anchor scroll position
+ if (linkHash && this.router.url === linkURL) {
+ this.viewportScroller.scrollToAnchor(linkHash)
+ }
+
+ if (this.screenService.isInSmallView()) {
+ this.menuService.toggleMenu()
+ }
+ }
+
+ // Lock menu scroll when menu scroll to avoid fleeing / detached dropdown
+ onMenuScrollEvent () {
+ document.querySelector('menu').scrollTo(0, 0)
+ }
+
+ onDropdownOpenChange (opened: boolean) {
+ if (this.screenService.isInMobileView()) return
+
+ // Close dropdown when window scroll to avoid dropdown quick jump for re-position
+ const onWindowScroll = () => {
+ this.dropdown?.close()
+ window.removeEventListener('scroll', onWindowScroll)
+ }
+
+ if (opened) {
+ window.addEventListener('scroll', onWindowScroll)
+ document.querySelector('menu').scrollTo(0, 0) // Reset menu scroll to easy lock
+ document.querySelector('menu').addEventListener('scroll', this.onMenuScrollEvent)
+ } else {
+ document.querySelector('menu').removeEventListener('scroll', this.onMenuScrollEvent)
+ }
+ }
+
+ private async buildMenuSections () {
+ const menuSections = []
+
+ if (this.isLoggedIn) {
+ menuSections.push(
+ this.menuService.buildLibraryLinks(this.user?.canSeeVideosLink)
+ )
+ }
+
+ menuSections.push(
+ this.menuService.buildCommonLinks(this.htmlServerConfig)
+ )
+
+ this.menuSections = await this.hooks.wrapObject(menuSections, 'common', 'filter:left-menu.links.create.result')
+ }
+