]> git.immae.eu Git - github/Chocobozzz/PeerTube.git/blame - client/src/app/shared/menu/top-menu-dropdown.component.ts
Fix displaying more dropdown on touchscreen
[github/Chocobozzz/PeerTube.git] / client / src / app / shared / menu / top-menu-dropdown.component.ts
CommitLineData
d363ef53
K
1import {
2 Component,
3 Input,
4 OnDestroy,
5 OnInit,
6 ViewChild
7} from '@angular/core'
ddb83e49 8import { filter, take } from 'rxjs/operators'
80bfd33c 9import { NavigationEnd, Router } from '@angular/router'
ddb83e49 10import { Subscription } from 'rxjs'
d363ef53 11import { NgbDropdown, NgbModal } from '@ng-bootstrap/ng-bootstrap'
a55052c9 12import { GlobalIconName } from '@app/shared/images/global-icon.component'
64545a83 13import { ScreenService } from '@app/shared/misc/screen.service'
ddb83e49
C
14
15export type TopMenuDropdownParam = {
16 label: string
17 routerLink?: string
18
19 children?: {
20 label: string
21 routerLink: string
a55052c9
C
22
23 iconName?: GlobalIconName
ddb83e49
C
24 }[]
25}
26
27@Component({
28 selector: 'my-top-menu-dropdown',
29 templateUrl: './top-menu-dropdown.component.html',
30 styleUrls: [ './top-menu-dropdown.component.scss' ]
31})
32export class TopMenuDropdownComponent implements OnInit, OnDestroy {
33 @Input() menuEntries: TopMenuDropdownParam[] = []
34
d363ef53
K
35 @ViewChild('modal', { static: true }) modal: NgbModal
36
ddb83e49 37 suffixLabels: { [ parentLabel: string ]: string }
a55052c9 38 hasIcons = false
64545a83 39 container: undefined | 'body' = undefined
d363ef53
K
40 isModalOpened = false
41 currentMenuEntryIndex: number
ddb83e49
C
42
43 private openedOnHover = false
44 private routeSub: Subscription
45
64545a83
C
46 constructor (
47 private router: Router,
d363ef53 48 private modalService: NgbModal,
64545a83 49 private screen: ScreenService
d363ef53
K
50 ) { }
51
52 get isInSmallView () {
53 return this.screen.isInSmallView()
54 }
ddb83e49
C
55
56 ngOnInit () {
57 this.updateChildLabels(window.location.pathname)
58
59 this.routeSub = this.router.events
d363ef53
K
60 .pipe(filter(event => event instanceof NavigationEnd))
61 .subscribe(() => this.updateChildLabels(window.location.pathname))
a55052c9
C
62
63 this.hasIcons = this.menuEntries.some(
64 e => e.children && e.children.some(c => !!c.iconName)
65 )
64545a83 66
d363ef53
K
67 // We have to set body for the container to avoid scroll overflow on mobile and small views
68 if (this.isInSmallView) {
64545a83
C
69 this.container = 'body'
70 }
ddb83e49
C
71 }
72
73 ngOnDestroy () {
74 if (this.routeSub) this.routeSub.unsubscribe()
75 }
76
77 openDropdownOnHover (dropdown: NgbDropdown) {
78 this.openedOnHover = true
79 dropdown.open()
80
81 // Menu was closed
82 dropdown.openChange
83 .pipe(take(1))
a55052c9 84 .subscribe(() => this.openedOnHover = false)
ddb83e49
C
85 }
86
80bfd33c
C
87 dropdownAnchorClicked (dropdown: NgbDropdown) {
88 if (this.openedOnHover) {
89 this.openedOnHover = false
90 return
91 }
92
93 return dropdown.toggle()
94 }
95
ddb83e49
C
96 closeDropdownIfHovered (dropdown: NgbDropdown) {
97 if (this.openedOnHover === false) return
98
99 dropdown.close()
100 this.openedOnHover = false
101 }
102
d363ef53
K
103 openModal (index: number) {
104 this.currentMenuEntryIndex = index
105 this.isModalOpened = true
106
107 this.modalService.open(this.modal, {
108 centered: true,
109 beforeDismiss: async () => {
110 this.onModalDismiss()
111 return true
112 }
113 })
114 }
115
116 onModalDismiss () {
117 this.isModalOpened = false
118 }
119
120 dismissOtherModals () {
121 this.modalService.dismissAll()
122 }
123
ddb83e49
C
124 private updateChildLabels (path: string) {
125 this.suffixLabels = {}
126
127 for (const entry of this.menuEntries) {
128 if (!entry.children) continue
129
130 for (const child of entry.children) {
131 if (path.startsWith(child.routerLink)) {
132 this.suffixLabels[entry.label] = child.label
133 }
134 }
135 }
136 }
137}