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

pull/2538/head
Rigel Kent 2020-03-07 13:50:26 +01:00 committed by Chocobozzz
parent 7b81edc854
commit 3b20bdd6dc
10 changed files with 102 additions and 30 deletions

View File

@ -4,10 +4,13 @@ import { RouteReuseStrategy, RouterModule, Routes } from '@angular/router'
import { PreloadSelectedModulesList } from './core' import { PreloadSelectedModulesList } from './core'
import { AppComponent } from '@app/app.component' import { AppComponent } from '@app/app.component'
import { CustomReuseStrategy } from '@app/core/routing/custom-reuse-strategy' import { CustomReuseStrategy } from '@app/core/routing/custom-reuse-strategy'
import { MenuGuards } from '@app/core/routing/menu-guard.service'
const routes: Routes = [ const routes: Routes = [
{ {
path: 'admin', path: 'admin',
canActivate: [ MenuGuards.close() ],
canDeactivate: [ MenuGuards.open() ],
loadChildren: () => import('./+admin/admin.module').then(m => m.AdminModule) loadChildren: () => import('./+admin/admin.module').then(m => m.AdminModule)
}, },
{ {
@ -54,6 +57,7 @@ const routes: Routes = [
}) })
], ],
providers: [ providers: [
MenuGuards.guards,
PreloadSelectedModulesList, PreloadSelectedModulesList,
{ provide: RouteReuseStrategy, useClass: CustomReuseStrategy } { provide: RouteReuseStrategy, useClass: CustomReuseStrategy }
], ],

View File

@ -5,8 +5,8 @@
<div [ngClass]="{ 'user-logged-in': isUserLoggedIn(), 'user-not-logged-in': !isUserLoggedIn() }"> <div [ngClass]="{ 'user-logged-in': isUserLoggedIn(), 'user-not-logged-in': !isUserLoggedIn() }">
<div class="header"> <div class="header">
<div class="top-left-block" [ngClass]="{ 'border-bottom': isMenuDisplayed === false }"> <div class="top-left-block" [ngClass]="{ 'border-bottom': menu.isMenuDisplayed === false }">
<span class="icon icon-menu" (click)="toggleMenu()"></span> <span class="icon icon-menu" (click)="menu.toggleMenu()"></span>
<a class="peertube-title" [routerLink]="defaultRoute" title="Homepage" i18n-title> <a class="peertube-title" [routerLink]="defaultRoute" title="Homepage" i18n-title>
<span class="icon icon-logo"></span> <span class="icon icon-logo"></span>
@ -14,15 +14,15 @@
</a> </a>
</div> </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> <my-header class="w-100 d-flex justify-content-end"></my-header>
</div> </div>
</div> </div>
<div class="sub-header-container"> <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"> <div class="main-row">
<router-outlet></router-outlet> <router-outlet></router-outlet>

View File

@ -18,6 +18,7 @@ import { InstanceConfigWarningModalComponent } from '@app/modal/instance-config-
import { ServerConfig, UserRole } from '@shared/models' import { ServerConfig, UserRole } from '@shared/models'
import { User } from '@app/shared' import { User } from '@app/shared'
import { InstanceService } from '@app/shared/instance/instance.service' import { InstanceService } from '@app/shared/instance/instance.service'
import { MenuService } from './core/menu/menu.service'
@Component({ @Component({
selector: 'my-app', selector: 'my-app',
@ -28,9 +29,6 @@ export class AppComponent implements OnInit {
@ViewChild('welcomeModal') welcomeModal: WelcomeModalComponent @ViewChild('welcomeModal') welcomeModal: WelcomeModalComponent
@ViewChild('instanceConfigWarningModal') instanceConfigWarningModal: InstanceConfigWarningModalComponent @ViewChild('instanceConfigWarningModal') instanceConfigWarningModal: InstanceConfigWarningModalComponent
isMenuDisplayed = true
isMenuChangedByUser = false
customCSS: SafeHtml customCSS: SafeHtml
private serverConfig: ServerConfig private serverConfig: ServerConfig
@ -50,7 +48,8 @@ export class AppComponent implements OnInit {
private themeService: ThemeService, private themeService: ThemeService,
private hooks: HooksService, private hooks: HooksService,
private location: PlatformLocation, private location: PlatformLocation,
private modalService: NgbModal private modalService: NgbModal,
public menu: MenuService
) { } ) { }
get instanceName () { get instanceName () {
@ -78,21 +77,12 @@ export class AppComponent implements OnInit {
this.authService.refreshUserInformation() this.authService.refreshUserInformation()
} }
// Do not display menu on small screens
if (this.screenService.isInSmallView()) {
this.isMenuDisplayed = false
}
this.initRouteEvents() this.initRouteEvents()
this.injectJS() this.injectJS()
this.injectCSS() this.injectCSS()
this.initHotkeys() this.initHotkeys()
fromEvent(window, 'resize')
.pipe(debounceTime(200))
.subscribe(() => this.onResize())
this.location.onPopState(() => this.modalService.dismissAll(POP_STATE_MODAL_DISMISS)) this.location.onPopState(() => this.modalService.dismissAll(POP_STATE_MODAL_DISMISS))
this.openModalsIfNeeded() this.openModalsIfNeeded()
@ -102,15 +92,6 @@ export class AppComponent implements OnInit {
return this.authService.isLoggedIn() return this.authService.isLoggedIn()
} }
toggleMenu () {
this.isMenuDisplayed = !this.isMenuDisplayed
this.isMenuChangedByUser = true
}
onResize () {
this.isMenuDisplayed = window.innerWidth >= 800 && !this.isMenuChangedByUser
}
private initRouteEvents () { private initRouteEvents () {
let resetScroll = true let resetScroll = true
const eventsObs = this.router.events const eventsObs = this.router.events
@ -176,7 +157,7 @@ export class AppComponent implements OnInit {
eventsObs.pipe( eventsObs.pipe(
filter((e: Event): e is GuardsCheckStart => e instanceof GuardsCheckStart), filter((e: Event): e is GuardsCheckStart => e instanceof GuardsCheckStart),
filter(() => this.screenService.isInSmallView()) 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 () { private injectJS () {
@ -249,7 +230,7 @@ export class AppComponent implements OnInit {
}, undefined, this.i18n('Focus the search bar')), }, undefined, this.i18n('Focus the search bar')),
new Hotkey('b', (event: KeyboardEvent): boolean => { new Hotkey('b', (event: KeyboardEvent): boolean => {
this.toggleMenu() this.menu.toggleMenu()
return false return false
}, undefined, this.i18n('Toggle the left menu')), }, undefined, this.i18n('Toggle the left menu')),

View File

@ -13,6 +13,7 @@ import { throwIfAlreadyLoaded } from './module-import-guard'
import { LoginGuard, RedirectService, UserRightGuard } from './routing' import { LoginGuard, RedirectService, UserRightGuard } from './routing'
import { ServerService } from './server' import { ServerService } from './server'
import { ThemeService } from './theme' import { ThemeService } from './theme'
import { MenuService } from './menu'
import { HotkeyModule } from 'angular2-hotkeys' import { HotkeyModule } from 'angular2-hotkeys'
import { CheatSheetComponent } from './hotkeys' import { CheatSheetComponent } from './hotkeys'
import { ToastModule } from 'primeng/toast' import { ToastModule } from 'primeng/toast'
@ -59,6 +60,7 @@ import { HooksService } from '@app/core/plugins/hooks.service'
ConfirmService, ConfirmService,
ServerService, ServerService,
ThemeService, ThemeService,
MenuService,
LoginGuard, LoginGuard,
UserRightGuard, UserRightGuard,
UnloggedGuard, UnloggedGuard,

View File

@ -0,0 +1 @@
export * from './menu.service'

View File

@ -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
}
}

View File

@ -2,3 +2,4 @@ export * from './login-guard.service'
export * from './user-right-guard.service' export * from './user-right-guard.service'
export * from './preload-selected-modules-list' export * from './preload-selected-modules-list'
export * from './redirect.service' export * from './redirect.service'
export * from './menu-guard.service'

View File

@ -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
}
}

View File

@ -8,7 +8,6 @@ import { first } from 'rxjs/operators'
import { User } from '@app/shared/users/user.model' import { User } from '@app/shared/users/user.model'
import { UserService } from '@app/shared/users/user.service' import { UserService } from '@app/shared/users/user.service'
import { LocalStorageService } from '@app/shared/misc/storage.service' import { LocalStorageService } from '@app/shared/misc/storage.service'
import { peertubeLocalStorage } from '@app/shared/misc/peertube-web-storage'
@Injectable() @Injectable()
export class ThemeService { export class ThemeService {

View File

@ -14,6 +14,10 @@ export class ScreenService {
return this.getWindowInnerWidth() < 800 return this.getWindowInnerWidth() < 800
} }
isInMediumView () {
return this.getWindowInnerWidth() < 1100
}
isInMobileView () { isInMobileView () {
return this.getWindowInnerWidth() < 500 return this.getWindowInnerWidth() < 500
} }