From: Rigel Kent <sendmemail@rigelk.eu>
Date: Sat, 7 Mar 2020 12:50:26 +0000 (+0100)
Subject: Servicify menu, close menu on admin for small and medium screens
X-Git-Tag: v2.2.0-rc.1~388
X-Git-Url: https://git.librecmc.org/?a=commitdiff_plain;h=3b20bdd6dc7402b0723e038c57f0606131e20e54;p=oweals%2Fpeertube.git

Servicify menu, close menu on admin for small and medium screens
---

diff --git a/client/src/app/app-routing.module.ts b/client/src/app/app-routing.module.ts
index b5a677d15..a87f4ce1b 100644
--- a/client/src/app/app-routing.module.ts
+++ b/client/src/app/app-routing.module.ts
@@ -4,10 +4,13 @@ import { RouteReuseStrategy, RouterModule, Routes } from '@angular/router'
 import { PreloadSelectedModulesList } from './core'
 import { AppComponent } from '@app/app.component'
 import { CustomReuseStrategy } from '@app/core/routing/custom-reuse-strategy'
+import { MenuGuards } from '@app/core/routing/menu-guard.service'
 
 const routes: Routes = [
   {
     path: 'admin',
+    canActivate: [ MenuGuards.close() ],
+    canDeactivate: [ MenuGuards.open() ],
     loadChildren: () => import('./+admin/admin.module').then(m => m.AdminModule)
   },
   {
@@ -54,6 +57,7 @@ const routes: Routes = [
     })
   ],
   providers: [
+    MenuGuards.guards,
     PreloadSelectedModulesList,
     { provide: RouteReuseStrategy, useClass: CustomReuseStrategy }
   ],
diff --git a/client/src/app/app.component.html b/client/src/app/app.component.html
index 54b320f79..d5fec61e6 100644
--- a/client/src/app/app.component.html
+++ b/client/src/app/app.component.html
@@ -5,8 +5,8 @@
 <div [ngClass]="{ 'user-logged-in': isUserLoggedIn(), 'user-not-logged-in': !isUserLoggedIn() }">
   <div class="header">
 
-    <div class="top-left-block" [ngClass]="{ 'border-bottom': isMenuDisplayed === false }">
-      <span class="icon icon-menu" (click)="toggleMenu()"></span>
+    <div class="top-left-block" [ngClass]="{ 'border-bottom': menu.isMenuDisplayed === false }">
+      <span class="icon icon-menu" (click)="menu.toggleMenu()"></span>
 
       <a class="peertube-title" [routerLink]="defaultRoute" title="Homepage" i18n-title>
         <span class="icon icon-logo"></span>
@@ -14,15 +14,15 @@
       </a>
     </div>
 
-    <div class="header-right" [ngClass]="{ 'border-bottom': isMenuDisplayed === false }">
+    <div class="header-right" [ngClass]="{ 'border-bottom': menu.isMenuDisplayed === false }">
       <my-header class="w-100 d-flex justify-content-end"></my-header>
     </div>
   </div>
 
   <div class="sub-header-container">
-    <my-menu *ngIf="isMenuDisplayed"></my-menu>
+    <my-menu *ngIf="menu.isMenuDisplayed"></my-menu>
 
-    <div id="content" tabindex="-1" class="main-col container-fluid" [ngClass]="{ expanded: isMenuDisplayed === false }">
+    <div id="content" tabindex="-1" class="main-col container-fluid" [ngClass]="{ expanded: menu.isMenuDisplayed === false }">
 
       <div class="main-row">
         <router-outlet></router-outlet>
diff --git a/client/src/app/app.component.ts b/client/src/app/app.component.ts
index 59966243b..629549ef2 100644
--- a/client/src/app/app.component.ts
+++ b/client/src/app/app.component.ts
@@ -18,6 +18,7 @@ import { InstanceConfigWarningModalComponent } from '@app/modal/instance-config-
 import { ServerConfig, UserRole } from '@shared/models'
 import { User } from '@app/shared'
 import { InstanceService } from '@app/shared/instance/instance.service'
+import { MenuService } from './core/menu/menu.service'
 
 @Component({
   selector: 'my-app',
@@ -28,9 +29,6 @@ export class AppComponent implements OnInit {
   @ViewChild('welcomeModal') welcomeModal: WelcomeModalComponent
   @ViewChild('instanceConfigWarningModal') instanceConfigWarningModal: InstanceConfigWarningModalComponent
 
-  isMenuDisplayed = true
-  isMenuChangedByUser = false
-
   customCSS: SafeHtml
 
   private serverConfig: ServerConfig
@@ -50,7 +48,8 @@ export class AppComponent implements OnInit {
     private themeService: ThemeService,
     private hooks: HooksService,
     private location: PlatformLocation,
-    private modalService: NgbModal
+    private modalService: NgbModal,
+    public menu: MenuService
   ) { }
 
   get instanceName () {
@@ -78,21 +77,12 @@ export class AppComponent implements OnInit {
       this.authService.refreshUserInformation()
     }
 
-    // Do not display menu on small screens
-    if (this.screenService.isInSmallView()) {
-      this.isMenuDisplayed = false
-    }
-
     this.initRouteEvents()
     this.injectJS()
     this.injectCSS()
 
     this.initHotkeys()
 
-    fromEvent(window, 'resize')
-      .pipe(debounceTime(200))
-      .subscribe(() => this.onResize())
-
     this.location.onPopState(() => this.modalService.dismissAll(POP_STATE_MODAL_DISMISS))
 
     this.openModalsIfNeeded()
@@ -102,15 +92,6 @@ export class AppComponent implements OnInit {
     return this.authService.isLoggedIn()
   }
 
-  toggleMenu () {
-    this.isMenuDisplayed = !this.isMenuDisplayed
-    this.isMenuChangedByUser = true
-  }
-
-  onResize () {
-    this.isMenuDisplayed = window.innerWidth >= 800 && !this.isMenuChangedByUser
-  }
-
   private initRouteEvents () {
     let resetScroll = true
     const eventsObs = this.router.events
@@ -176,7 +157,7 @@ export class AppComponent implements OnInit {
     eventsObs.pipe(
       filter((e: Event): e is GuardsCheckStart => e instanceof GuardsCheckStart),
       filter(() => this.screenService.isInSmallView())
-    ).subscribe(() => this.isMenuDisplayed = false) // User clicked on a link in the menu, change the page
+    ).subscribe(() => this.menu.isMenuDisplayed = false) // User clicked on a link in the menu, change the page
   }
 
   private injectJS () {
@@ -249,7 +230,7 @@ export class AppComponent implements OnInit {
       }, undefined, this.i18n('Focus the search bar')),
 
       new Hotkey('b', (event: KeyboardEvent): boolean => {
-        this.toggleMenu()
+        this.menu.toggleMenu()
         return false
       }, undefined, this.i18n('Toggle the left menu')),
 
diff --git a/client/src/app/core/core.module.ts b/client/src/app/core/core.module.ts
index 5943af4da..a1734ad80 100644
--- a/client/src/app/core/core.module.ts
+++ b/client/src/app/core/core.module.ts
@@ -13,6 +13,7 @@ import { throwIfAlreadyLoaded } from './module-import-guard'
 import { LoginGuard, RedirectService, UserRightGuard } from './routing'
 import { ServerService } from './server'
 import { ThemeService } from './theme'
+import { MenuService } from './menu'
 import { HotkeyModule } from 'angular2-hotkeys'
 import { CheatSheetComponent } from './hotkeys'
 import { ToastModule } from 'primeng/toast'
@@ -59,6 +60,7 @@ import { HooksService } from '@app/core/plugins/hooks.service'
     ConfirmService,
     ServerService,
     ThemeService,
+    MenuService,
     LoginGuard,
     UserRightGuard,
     UnloggedGuard,
diff --git a/client/src/app/core/menu/index.ts b/client/src/app/core/menu/index.ts
new file mode 100644
index 000000000..516a49aca
--- /dev/null
+++ b/client/src/app/core/menu/index.ts
@@ -0,0 +1 @@
+export * from './menu.service'
diff --git a/client/src/app/core/menu/menu.service.ts b/client/src/app/core/menu/menu.service.ts
new file mode 100644
index 000000000..46ef72e17
--- /dev/null
+++ b/client/src/app/core/menu/menu.service.ts
@@ -0,0 +1,32 @@
+import { Injectable } from '@angular/core'
+import { ScreenService } from '@app/shared/misc/screen.service'
+import { fromEvent } from 'rxjs'
+import { debounceTime } from 'rxjs/operators'
+
+@Injectable()
+export class MenuService {
+  isMenuDisplayed = true
+  isMenuChangedByUser = false
+
+  constructor(
+    private screenService: ScreenService
+  ) {
+    // Do not display menu on small screens
+    if (this.screenService.isInSmallView()) {
+      this.isMenuDisplayed = false
+    }
+
+    fromEvent(window, 'resize')
+      .pipe(debounceTime(200))
+      .subscribe(() => this.onResize())
+  }
+
+  toggleMenu () {
+    this.isMenuDisplayed = !this.isMenuDisplayed
+    this.isMenuChangedByUser = true
+  }
+
+  onResize () {
+    this.isMenuDisplayed = window.innerWidth >= 800 && !this.isMenuChangedByUser
+  }
+}
diff --git a/client/src/app/core/routing/index.ts b/client/src/app/core/routing/index.ts
index 9f0b4eac5..58b83bb2a 100644
--- a/client/src/app/core/routing/index.ts
+++ b/client/src/app/core/routing/index.ts
@@ -2,3 +2,4 @@ export * from './login-guard.service'
 export * from './user-right-guard.service'
 export * from './preload-selected-modules-list'
 export * from './redirect.service'
+export * from './menu-guard.service'
diff --git a/client/src/app/core/routing/menu-guard.service.ts b/client/src/app/core/routing/menu-guard.service.ts
new file mode 100644
index 000000000..907d145fd
--- /dev/null
+++ b/client/src/app/core/routing/menu-guard.service.ts
@@ -0,0 +1,48 @@
+import { Injectable } from '@angular/core'
+import { CanActivate, CanDeactivate } from '@angular/router'
+import { MenuService } from '@app/core/menu'
+import { ScreenService } from '@app/shared/misc/screen.service'
+
+abstract class MenuGuard implements CanActivate, CanDeactivate<any> {
+  display = true
+  canDeactivate = this.canActivate
+
+  constructor (protected menu: MenuService, protected screen: ScreenService, display: boolean) {
+    this.display = display
+  }
+
+  canActivate (): boolean {
+    // small screens already have the site-wide onResize from screenService
+    // > medium screens have enough space to fit the administrative menus
+    if (!this.screen.isInMobileView() && this.screen.isInMediumView()) {
+      this.menu.isMenuDisplayed = this.display
+    }
+    return true
+  }
+}
+
+@Injectable()
+export class OpenMenuGuard extends MenuGuard {
+  constructor (menu: MenuService, screen: ScreenService) { super(menu, screen, true) }
+}
+
+@Injectable()
+export class CloseMenuGuard extends MenuGuard {
+  constructor (menu: MenuService, screen: ScreenService) { super(menu, screen, false) }
+}
+
+@Injectable()
+export class MenuGuards {
+  public static guards = [
+    OpenMenuGuard,
+    CloseMenuGuard
+  ]
+
+  static open () {
+    return OpenMenuGuard
+  }
+
+  static close () {
+    return CloseMenuGuard
+  }
+}
diff --git a/client/src/app/core/theme/theme.service.ts b/client/src/app/core/theme/theme.service.ts
index 3c066ca74..c0189ad32 100644
--- a/client/src/app/core/theme/theme.service.ts
+++ b/client/src/app/core/theme/theme.service.ts
@@ -8,7 +8,6 @@ import { first } from 'rxjs/operators'
 import { User } from '@app/shared/users/user.model'
 import { UserService } from '@app/shared/users/user.service'
 import { LocalStorageService } from '@app/shared/misc/storage.service'
-import { peertubeLocalStorage } from '@app/shared/misc/peertube-web-storage'
 
 @Injectable()
 export class ThemeService {
diff --git a/client/src/app/shared/misc/screen.service.ts b/client/src/app/shared/misc/screen.service.ts
index 220d41d59..9c71a8c83 100644
--- a/client/src/app/shared/misc/screen.service.ts
+++ b/client/src/app/shared/misc/screen.service.ts
@@ -14,6 +14,10 @@ export class ScreenService {
     return this.getWindowInnerWidth() < 800
   }
 
+  isInMediumView () {
+    return this.getWindowInnerWidth() < 1100
+  }
+
   isInMobileView () {
     return this.getWindowInnerWidth() < 500
   }