]> git.immae.eu Git - github/Chocobozzz/PeerTube.git/commitdiff
Add restore scroll position on user-dropdown anchors links and scroll to top on activ...
authorKim <1877318+kimsible@users.noreply.github.com>
Mon, 17 Aug 2020 08:13:31 +0000 (10:13 +0200)
committerGitHub <noreply@github.com>
Mon, 17 Aug 2020 08:13:31 +0000 (10:13 +0200)
* Add restore scroll position on router same url

* Remove settings top anchor

* Add scrollToTop on active links fixed sub-menu

* Add restore scroll position on notification avatar links

* Toggle menu and close pophover when click on active dropdown menu-left link

* Add onSameUrlRestoreScrollPosition on user dropdown channels link

* Same behavior scrollTop and scroll to anchor everywhere

Co-authored-by: kimsible <kimsible@users.noreply.github.com>
client/src/app/+my-account/my-account-settings/my-account-settings.component.html
client/src/app/app.component.ts
client/src/app/menu/avatar-notification.component.html
client/src/app/menu/avatar-notification.component.ts
client/src/app/menu/menu.component.html
client/src/app/menu/menu.component.ts
client/src/app/shared/shared-main/misc/top-menu-dropdown.component.html
client/src/app/shared/shared-main/misc/top-menu-dropdown.component.ts

index de835385148bb6a9579688af57107a40e7a48745..2ad014f0161e072c1d88a0b9b30e80376aac3c43 100644 (file)
@@ -1,7 +1,5 @@
 <h1 class="sr-only" i18n>Settings</h1>
 <div class="form-row"> <!-- preview -->
-  <div class="anchor" id="top"></div> <!-- top anchor -->
-
   <div class="form-group col-12 col-lg-4 col-xl-3"></div>
 
   <div class="form-group form-group-right col-12 col-lg-8 col-xl-9">
index ef0b1ae56efff122389b63638169bd570b238491..b8af4e2c7889dd2cb1bebbd637be6a7cfc2ebf16 100644 (file)
@@ -121,7 +121,7 @@ export class AppComponent implements OnInit, AfterViewInit {
       // scrollToAnchor first to preserve anchor position when using history navigation
       if (e.anchor) {
         setTimeout(() => {
-          this.viewportScroller.scrollToAnchor(e.anchor)
+          document.getElementById(e.anchor).scrollIntoView({ behavior: 'smooth', inline: 'nearest' })
         })
 
         return
index 7999b334649c79e3ca2afc3be5ba86db1acd94d9..b24bd030910ee0b864d96d2429016dd865c0e4d2 100644 (file)
@@ -21,6 +21,7 @@
         <a
           i18n-title title="Update your notification preferences" class="glyphicon glyphicon-cog"
           routerLink="/my-account/settings" fragment="notifications"
+          #settingsNotifications (click)="onNavigate(settingsNotifications)"
         ></a>
       </div>
     </div>
@@ -34,7 +35,7 @@
       [markAllAsReadSubject]="markAllAsReadSubject" (notificationsLoaded)="onNotificationLoaded()"
     ></my-user-notifications>
 
-    <a *ngIf="loaded" class="all-notifications" routerLink="/my-account/notifications">
+    <a *ngIf="loaded" class="all-notifications" routerLink="/my-account/notifications" #notifications (click)="onNavigate(notifications)">
       <my-global-icon class="mr-1" iconName="inbox-full" aria-hidden="true"></my-global-icon>
       <span i18n>See all your notifications</span>
     </a>
index 9a64faa6adf90c8a53c83dd4f59f40142ebdc3af..8b99550699b701d223d0d9bac08146052af92d56 100644 (file)
@@ -1,6 +1,6 @@
 import { Subject, Subscription } from 'rxjs'
 import { filter } from 'rxjs/operators'
-import { Component, Input, OnDestroy, OnInit, ViewChild } from '@angular/core'
+import { Component, EventEmitter, Input, Output, OnDestroy, OnInit, ViewChild } from '@angular/core'
 import { NavigationEnd, Router } from '@angular/router'
 import { Notifier, User, UserNotificationSocket } from '@app/core'
 import { UserNotificationService } from '@app/shared/shared-main'
@@ -15,6 +15,7 @@ export class AvatarNotificationComponent implements OnInit, OnDestroy {
   @ViewChild('popover', { static: true }) popover: NgbPopover
 
   @Input() user: User
+  @Output() navigate = new EventEmitter<HTMLAnchorElement>()
 
   unreadNotifications = 0
   loaded = false
@@ -65,6 +66,10 @@ export class AvatarNotificationComponent implements OnInit, OnDestroy {
     this.loaded = true
   }
 
+  onNavigate (link: HTMLAnchorElement) {
+    this.navigate.emit(link)
+  }
+
   markAllAsRead () {
     this.markAllAsReadSubject.next(true)
   }
index 7f83a6fb8fe459efec1f3614e741ea4d007d1f11..2011899d3eb646fc27850b5219798a4ad19eb52e 100644 (file)
@@ -2,7 +2,7 @@
   <menu [ngClass]="{ 'logged-in': isLoggedIn }">
     <div class="top-menu">
       <div *ngIf="isLoggedIn" class="logged-in-block">
-        <my-avatar-notification [user]="user"></my-avatar-notification>
+        <my-avatar-notification [user]="user" (navigate)="onSameUrlRestoreScrollPosition($event)"></my-avatar-notification>
 
         <div class="logged-in-info">
           <a *ngIf="user.account" [routerLink]="[ '/accounts', user.account.nameWithHost ]" class="logged-in-display-name">{{ user.account?.displayName }}</a>
 
             <div class="dropdown-divider"></div>
 
-            <a ngbDropdownItem ngbDropdownToggle class="dropdown-item" routerLink="/my-account/settings" fragment="top">
+            <a ngbDropdownItem ngbDropdownToggle class="dropdown-item" routerLink="/my-account/settings"
+              #settingsLink (click)="onSameUrlRestoreScrollPosition(settingsLink)">
               <my-global-icon iconName="user" aria-hidden="true"></my-global-icon> <ng-container i18n>Account settings</ng-container>
             </a>
 
-            <a ngbDropdownItem ngbDropdownToggle class="dropdown-item" routerLink="/my-account/video-channels">
+            <a ngbDropdownItem ngbDropdownToggle class="dropdown-item" routerLink="/my-account/video-channels"
+              #channelsLink (click)="onSameUrlRestoreScrollPosition(channelsLink)">
               <my-global-icon iconName="channel" aria-hidden="true"></my-global-icon> <ng-container i18n>Channels settings</ng-container>
             </a>
 
               <span class="ml-auto text-muted">{{ language }}</span>
             </a>
 
-            <a ngbDropdownItem ngbDropdownToggle class="dropdown-item" routerLink="/my-account/settings" fragment="video-languages-subtitles">
+            <a ngbDropdownItem ngbDropdownToggle class="dropdown-item" routerLink="/my-account/settings" fragment="video-languages-subtitles"
+              #settingsLanguagesSubtitles (click)="onSameUrlRestoreScrollPosition(settingsLanguagesSubtitles)">
               <my-global-icon iconName="video-lang" aria-hidden="true"></my-global-icon>
               <span i18n>Videos:</span>
               <span class="ml-auto text-muted">{{ videoLanguages.join(', ') }}</span>
             </a>
 
-            <a ngbDropdownItem ngbDropdownToggle class="dropdown-item" routerLink="/my-account/settings" fragment="video-sensitive-content-policy">
+            <a ngbDropdownItem ngbDropdownToggle class="dropdown-item" routerLink="/my-account/settings"
+              fragment="video-sensitive-content-policy" #settingsSensitiveContentPolicy
+              (click)="onSameUrlRestoreScrollPosition(settingsSensitiveContentPolicy)">
               <my-global-icon class="hover-display-toggle" [ngClass]="{ 'not-displayed': user.nsfwPolicy === 'display' }" iconName="sensitive" aria-hidden="true"></my-global-icon>
               <my-global-icon class="hover-display-toggle" [ngClass]="{ 'not-displayed': user.nsfwPolicy !== 'display' }" iconName="unsensitive" aria-hidden="true"></my-global-icon>
               <span i18n>Sensitive:</span>
@@ -56,7 +61,8 @@
               <input type="checkbox" [checked]="user.webTorrentEnabled"/><label class="ml-auto" for="switch">Toggle p2p</label>
             </a>
 
-            <a ngbDropdownItem ngbDropdownToggle class="dropdown-item" routerLink="/my-account/settings" fragment="top">
+            <a ngbDropdownItem ngbDropdownToggle class="dropdown-item" routerLink="/my-account/settings"
+              #settingsMoreLink (click)="onSameUrlRestoreScrollPosition(settingsMoreLink)">
               <my-global-icon iconName="more-horizontal" aria-hidden="true"></my-global-icon> <ng-container i18n>More account settings</ng-container>
             </a>
 
index 3d6cbda24a991492c791e2f3c61a9be102b7308f..f9a0a9f571ec0e7e69676d0b3b343910158923dc 100644 (file)
@@ -2,7 +2,8 @@ import { HotkeysService } from 'angular2-hotkeys'
 import * as debug from 'debug'
 import { switchMap } from 'rxjs/operators'
 import { Component, OnInit, ViewChild } from '@angular/core'
-import { AuthService, AuthStatus, AuthUser, RedirectService, ScreenService, ServerService, UserService } from '@app/core'
+import { Router } from '@angular/router'
+import { AuthService, AuthStatus, AuthUser, MenuService, RedirectService, ScreenService, ServerService, UserService } from '@app/core'
 import { LanguageChooserComponent } from '@app/menu/language-chooser.component'
 import { QuickSettingsModalComponent } from '@app/modal/quick-settings-modal.component'
 import { ServerConfig, UserRight, VideoConstant } from '@shared/models'
@@ -43,8 +44,10 @@ export class MenuComponent implements OnInit {
     private serverService: ServerService,
     private redirectService: RedirectService,
     private hotkeysService: HotkeysService,
-    private screenService: ScreenService
-    ) { }
+    private screenService: ScreenService,
+    private menuService: MenuService,
+    private router: Router
+  ) { }
 
   get isInMobileView () {
     return this.screenService.isInMobileView()
@@ -192,6 +195,30 @@ export class MenuComponent implements OnInit {
     return this.languages.find(lang => lang.id === localeId).label
   }
 
+  onSameUrlRestoreScrollPosition (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)) {
+      window.scrollTo({
+        left: 0,
+        top: 0,
+        behavior: 'smooth'
+      })
+    }
+
+    // On same url with fragment restore anchor scroll position
+    if (linkHash && this.router.url === linkURL) {
+      const anchor = document.getElementById(link.getAttribute('fragment'))
+      anchor.scrollIntoView({ behavior: 'smooth', inline: 'nearest' })
+    }
+
+    if (this.screenService.isInSmallView()) {
+      this.menuService.toggleMenu()
+    }
+  }
+
   private buildUserLanguages () {
     if (!this.user) {
       this.videoLanguages = []
index 416bd9bc806515e80fad80ec38716e8dc3fa71c3..ee3346ea9b2eb105fdb5c1b50e37ef4bd49cbbfd 100644 (file)
@@ -1,7 +1,7 @@
 <div class="sub-menu" [ngClass]="{ 'sub-menu-fixed': !isBroadcastMessageDisplayed, 'no-scroll': isModalOpened }">
   <ng-container *ngFor="let menuEntry of menuEntries; index as id">
 
-    <a *ngIf="menuEntry.routerLink && isDisplayed(menuEntry)" [routerLink]="menuEntry.routerLink" routerLinkActive="active" class="title-page title-page-settings">{{ menuEntry.label }}</a>
+    <a *ngIf="menuEntry.routerLink && isDisplayed(menuEntry)" [routerLink]="menuEntry.routerLink" routerLinkActive="active" class="title-page title-page-settings" #routerLink (click)="onActiveLinkScrollToTop(routerLink)">{{ menuEntry.label }}</a>
 
     <div *ngIf="!menuEntry.routerLink && isDisplayed(menuEntry)" ngbDropdown class="parent-entry"
       #dropdown="ngbDropdown" autoClose="true">
@@ -28,7 +28,8 @@
         <ng-container *ngFor="let menuChild of menuEntry.children">
           <a *ngIf="isDisplayed(menuChild)" class="dropdown-item"
             [ngClass]="{ icon: hasIcons }"
-            [routerLink]="menuChild.routerLink">
+            [routerLink]="menuChild.routerLink"
+            #routerLink (click)="onActiveLinkScrollToTop(routerLink)">
             <my-global-icon *ngIf="menuChild.iconName" [iconName]="menuChild.iconName" aria-hidden="true"></my-global-icon>
 
             {{ menuChild.label }}
@@ -46,7 +47,8 @@
         <ng-container *ngFor="let menuChild of menuEntry.children">
           <a *ngIf="isDisplayed(menuChild)"
             [ngClass]="{ icon: hasIcons }"
-            [routerLink]="menuChild.routerLink" routerLinkActive="active" (click)="dismissOtherModals()">
+            [routerLink]="menuChild.routerLink" routerLinkActive="active"
+            #routerLink (click)="dismissOtherModals(); onActiveLinkScrollToTop(routerLink)">
             <my-global-icon *ngIf="menuChild.iconName" [iconName]="menuChild.iconName" aria-hidden="true"></my-global-icon>
 
             {{ menuChild.label }}
index 043b647c9b3813f904cf9d97dbeae56623f4dfa6..ba55685956b3497a0b13f38a93eace996ace8701 100644 (file)
@@ -94,6 +94,16 @@ export class TopMenuDropdownComponent implements OnInit, OnDestroy {
     this.isModalOpened = false
   }
 
+  onActiveLinkScrollToTop (link: HTMLAnchorElement) {
+    if (!this.isBroadcastMessageDisplayed && this.router.url.includes(link.getAttribute('href'))) {
+      window.scrollTo({
+        left: 0,
+        top: 0,
+        behavior: 'smooth'
+      })
+    }
+  }
+
   dismissOtherModals () {
     this.modalService.dismissAll()
   }