From 3b20bdd6dc7402b0723e038c57f0606131e20e54 Mon Sep 17 00:00:00 2001 From: Rigel Kent Date: Sat, 7 Mar 2020 13:50:26 +0100 Subject: [PATCH] Servicify menu, close menu on admin for small and medium screens --- client/src/app/app-routing.module.ts | 4 ++ client/src/app/app.component.html | 10 ++-- client/src/app/app.component.ts | 29 ++--------- client/src/app/core/core.module.ts | 2 + client/src/app/core/menu/index.ts | 1 + client/src/app/core/menu/menu.service.ts | 32 +++++++++++++ client/src/app/core/routing/index.ts | 1 + .../app/core/routing/menu-guard.service.ts | 48 +++++++++++++++++++ client/src/app/core/theme/theme.service.ts | 1 - client/src/app/shared/misc/screen.service.ts | 4 ++ 10 files changed, 102 insertions(+), 30 deletions(-) create mode 100644 client/src/app/core/menu/index.ts create mode 100644 client/src/app/core/menu/menu.service.ts create mode 100644 client/src/app/core/routing/menu-guard.service.ts 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 @@
-
- + -
+
- + -
+
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 { + 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 }