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)
},
{
})
],
providers: [
+ MenuGuards.guards,
PreloadSelectedModulesList,
{ provide: RouteReuseStrategy, useClass: CustomReuseStrategy }
],
<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>
</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>
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',
@ViewChild('welcomeModal') welcomeModal: WelcomeModalComponent
@ViewChild('instanceConfigWarningModal') instanceConfigWarningModal: InstanceConfigWarningModalComponent
- isMenuDisplayed = true
- isMenuChangedByUser = false
-
customCSS: SafeHtml
private serverConfig: ServerConfig
private themeService: ThemeService,
private hooks: HooksService,
private location: PlatformLocation,
- private modalService: NgbModal
+ private modalService: NgbModal,
+ public menu: MenuService
) { }
get instanceName () {
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()
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
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 () {
}, 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')),
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'
ConfirmService,
ServerService,
ThemeService,
+ MenuService,
LoginGuard,
UserRightGuard,
UnloggedGuard,
--- /dev/null
+export * from './menu.service'
--- /dev/null
+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
+ }
+}
export * from './user-right-guard.service'
export * from './preload-selected-modules-list'
export * from './redirect.service'
+export * from './menu-guard.service'
--- /dev/null
+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
+ }
+}
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 {
return this.getWindowInnerWidth() < 800
}
+ isInMediumView () {
+ return this.getWindowInnerWidth() < 1100
+ }
+
isInMobileView () {
return this.getWindowInnerWidth() < 500
}