2020-06-23 14:10:17 +02:00
|
|
|
import { HotkeysService } from 'angular2-hotkeys'
|
2020-07-28 15:18:38 +02:00
|
|
|
import * as debug from 'debug'
|
|
|
|
import { switchMap } from 'rxjs/operators'
|
2021-04-26 15:56:49 +02:00
|
|
|
import { ViewportScroller } from '@angular/common'
|
2018-06-28 13:59:48 +02:00
|
|
|
import { Component, OnInit, ViewChild } from '@angular/core'
|
2020-08-17 10:13:31 +02:00
|
|
|
import { Router } from '@angular/router'
|
2021-05-27 15:59:55 +02:00
|
|
|
import {
|
|
|
|
AuthService,
|
|
|
|
AuthStatus,
|
|
|
|
AuthUser,
|
2021-06-07 13:16:50 +02:00
|
|
|
HooksService,
|
|
|
|
MenuSection,
|
2021-05-27 15:59:55 +02:00
|
|
|
MenuService,
|
|
|
|
RedirectService,
|
|
|
|
ScreenService,
|
|
|
|
ServerService,
|
|
|
|
UserService
|
|
|
|
} from '@app/core'
|
2021-04-26 15:56:49 +02:00
|
|
|
import { scrollToTop } from '@app/helpers'
|
2018-06-28 13:59:48 +02:00
|
|
|
import { LanguageChooserComponent } from '@app/menu/language-chooser.component'
|
2020-02-28 13:52:21 +01:00
|
|
|
import { QuickSettingsModalComponent } from '@app/modal/quick-settings-modal.component'
|
2021-04-06 08:57:30 +02:00
|
|
|
import { PeertubeModalService } from '@app/shared/shared-main/peertube-modal/peertube-modal.service'
|
2021-04-26 15:56:49 +02:00
|
|
|
import { NgbDropdown } from '@ng-bootstrap/ng-bootstrap'
|
2021-12-03 17:04:47 +01:00
|
|
|
import { PluginsManager } from '@root-helpers/plugins-manager'
|
2021-06-04 13:31:41 +02:00
|
|
|
import { HTMLServerConfig, ServerConfig, UserRight, VideoConstant } from '@shared/models'
|
2016-08-12 16:52:10 +02:00
|
|
|
|
2020-07-28 15:18:38 +02:00
|
|
|
const logger = debug('peertube:menu:MenuComponent')
|
|
|
|
|
2016-08-12 16:52:10 +02:00
|
|
|
@Component({
|
|
|
|
selector: 'my-menu',
|
2017-04-21 11:06:33 +02:00
|
|
|
templateUrl: './menu.component.html',
|
2021-08-17 14:42:53 +02:00
|
|
|
styleUrls: [ './menu.component.scss' ]
|
2016-08-12 16:52:10 +02:00
|
|
|
})
|
|
|
|
export class MenuComponent implements OnInit {
|
2019-07-24 16:05:59 +02:00
|
|
|
@ViewChild('languageChooserModal', { static: true }) languageChooserModal: LanguageChooserComponent
|
2020-02-28 13:52:21 +01:00
|
|
|
@ViewChild('quickSettingsModal', { static: true }) quickSettingsModal: QuickSettingsModalComponent
|
2020-12-13 14:54:12 +01:00
|
|
|
@ViewChild('dropdown') dropdown: NgbDropdown
|
2018-06-28 13:59:48 +02:00
|
|
|
|
2020-07-28 15:18:38 +02:00
|
|
|
user: AuthUser
|
2017-06-16 14:32:15 +02:00
|
|
|
isLoggedIn: boolean
|
2020-02-28 13:52:21 +01:00
|
|
|
|
2017-10-27 16:55:03 +02:00
|
|
|
userHasAdminAccess = false
|
2018-09-26 14:23:10 +02:00
|
|
|
helpVisible = false
|
2017-10-27 16:55:03 +02:00
|
|
|
|
2020-03-11 16:41:38 +01:00
|
|
|
videoLanguages: string[] = []
|
2020-11-27 15:31:09 +01:00
|
|
|
nsfwPolicy: string
|
|
|
|
|
|
|
|
currentInterfaceLanguage: string
|
2020-03-11 16:41:38 +01:00
|
|
|
|
2021-06-07 13:16:50 +02:00
|
|
|
menuSections: MenuSection[] = []
|
2021-05-27 15:59:55 +02:00
|
|
|
|
2020-03-11 16:41:38 +01:00
|
|
|
private languages: VideoConstant<string>[] = []
|
2021-06-04 13:31:41 +02:00
|
|
|
|
|
|
|
private htmlServerConfig: HTMLServerConfig
|
2019-12-18 15:31:54 +01:00
|
|
|
private serverConfig: ServerConfig
|
2021-06-04 13:31:41 +02:00
|
|
|
|
2020-07-28 15:18:38 +02:00
|
|
|
private routesPerRight: { [role in UserRight]?: string } = {
|
2017-10-27 16:55:03 +02:00
|
|
|
[UserRight.MANAGE_USERS]: '/admin/users',
|
2017-11-16 17:16:42 +01:00
|
|
|
[UserRight.MANAGE_SERVER_FOLLOW]: '/admin/friends',
|
2020-07-01 16:05:30 +02:00
|
|
|
[UserRight.MANAGE_ABUSES]: '/admin/moderation/abuses',
|
2020-06-09 16:07:10 +02:00
|
|
|
[UserRight.MANAGE_VIDEO_BLACKLIST]: '/admin/moderation/video-blocks',
|
2018-09-19 09:53:49 +02:00
|
|
|
[UserRight.MANAGE_JOBS]: '/admin/jobs',
|
|
|
|
[UserRight.MANAGE_CONFIGURATION]: '/admin/config'
|
2017-10-27 16:55:03 +02:00
|
|
|
}
|
2016-08-12 16:52:10 +02:00
|
|
|
|
|
|
|
constructor (
|
2020-11-17 14:04:44 +01:00
|
|
|
private viewportScroller: ViewportScroller,
|
2016-08-12 16:52:10 +02:00
|
|
|
private authService: AuthService,
|
2020-02-28 13:52:21 +01:00
|
|
|
private userService: UserService,
|
2017-10-09 19:12:40 +02:00
|
|
|
private serverService: ServerService,
|
2018-09-04 23:14:31 +02:00
|
|
|
private redirectService: RedirectService,
|
2020-02-28 13:52:21 +01:00
|
|
|
private hotkeysService: HotkeysService,
|
2020-08-17 10:13:31 +02:00
|
|
|
private screenService: ScreenService,
|
|
|
|
private menuService: MenuService,
|
2021-04-06 08:57:30 +02:00
|
|
|
private modalService: PeertubeModalService,
|
2021-06-07 13:16:50 +02:00
|
|
|
private router: Router,
|
|
|
|
private hooks: HooksService
|
2021-04-26 15:56:49 +02:00
|
|
|
) { }
|
2020-12-13 14:54:12 +01:00
|
|
|
|
|
|
|
get isInMobileView () {
|
|
|
|
return this.screenService.isInMobileView()
|
|
|
|
}
|
|
|
|
|
|
|
|
get dropdownContainer () {
|
2021-04-26 15:56:49 +02:00
|
|
|
if (this.isInMobileView) return null
|
|
|
|
|
|
|
|
return 'body' as 'body'
|
2020-12-13 14:54:12 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
get language () {
|
|
|
|
return this.languageChooserModal.getCurrentLanguage()
|
|
|
|
}
|
2020-05-01 20:05:19 +02:00
|
|
|
|
2017-06-16 14:32:15 +02:00
|
|
|
ngOnInit () {
|
2021-06-04 13:31:41 +02:00
|
|
|
this.htmlServerConfig = this.serverService.getHTMLConfig()
|
2020-11-27 15:31:09 +01:00
|
|
|
this.currentInterfaceLanguage = this.languageChooserModal.getCurrentLanguage()
|
|
|
|
|
2021-06-07 17:38:31 +02:00
|
|
|
this.isLoggedIn = this.authService.isLoggedIn()
|
2021-06-07 13:16:50 +02:00
|
|
|
this.updateUserState()
|
|
|
|
this.buildMenuSections()
|
|
|
|
|
2016-08-12 16:52:10 +02:00
|
|
|
this.authService.loginChangedSource.subscribe(
|
|
|
|
status => {
|
|
|
|
if (status === AuthStatus.LoggedIn) {
|
2017-06-16 14:32:15 +02:00
|
|
|
this.isLoggedIn = true
|
2016-08-12 16:52:10 +02:00
|
|
|
} else if (status === AuthStatus.LoggedOut) {
|
2017-06-16 14:32:15 +02:00
|
|
|
this.isLoggedIn = false
|
2016-08-12 16:52:10 +02:00
|
|
|
}
|
2021-06-07 13:16:50 +02:00
|
|
|
|
|
|
|
this.updateUserState()
|
|
|
|
this.buildMenuSections()
|
2016-08-12 16:52:10 +02:00
|
|
|
}
|
2017-06-16 14:32:15 +02:00
|
|
|
)
|
2018-09-26 14:23:10 +02:00
|
|
|
|
2020-03-11 16:41:38 +01:00
|
|
|
this.hotkeysService.cheatSheetToggle
|
2020-07-28 15:18:38 +02:00
|
|
|
.subscribe(isOpen => this.helpVisible = isOpen)
|
2020-03-11 16:41:38 +01:00
|
|
|
|
|
|
|
this.serverService.getVideoLanguages()
|
2020-07-28 15:18:38 +02:00
|
|
|
.subscribe(languages => {
|
|
|
|
this.languages = languages
|
2020-02-28 13:52:21 +01:00
|
|
|
|
2020-07-28 15:18:38 +02:00
|
|
|
this.authService.userInformationLoaded
|
|
|
|
.subscribe(() => this.buildUserLanguages())
|
|
|
|
})
|
2021-04-06 08:57:30 +02:00
|
|
|
|
2021-07-20 13:49:46 +02:00
|
|
|
this.serverService.getConfig()
|
|
|
|
.subscribe(config => this.serverConfig = config)
|
|
|
|
|
2021-04-06 08:57:30 +02:00
|
|
|
this.modalService.openQuickSettingsSubject
|
|
|
|
.subscribe(() => this.openQuickSettings())
|
2020-02-28 13:52:21 +01:00
|
|
|
}
|
|
|
|
|
2021-12-03 17:04:47 +01:00
|
|
|
getExternalLoginHref () {
|
2021-12-08 11:32:45 +01:00
|
|
|
if (!this.serverConfig || this.serverConfig.client.menu.login.redirectOnSingleExternalAuth !== true) return undefined
|
2021-12-03 17:04:47 +01:00
|
|
|
|
|
|
|
const externalAuths = this.serverConfig.plugin.registeredExternalAuths
|
|
|
|
if (externalAuths.length !== 1) return undefined
|
|
|
|
|
|
|
|
return PluginsManager.getExternalAuthHref(externalAuths[0])
|
|
|
|
}
|
|
|
|
|
2017-07-25 20:17:28 +02:00
|
|
|
isRegistrationAllowed () {
|
2021-06-04 13:31:41 +02:00
|
|
|
if (!this.serverConfig) return false
|
|
|
|
|
2019-12-18 15:31:54 +01:00
|
|
|
return this.serverConfig.signup.allowed &&
|
2020-07-28 15:18:38 +02:00
|
|
|
this.serverConfig.signup.allowedForCurrentIP
|
2017-04-10 20:29:33 +02:00
|
|
|
}
|
|
|
|
|
2017-10-27 16:55:03 +02:00
|
|
|
getFirstAdminRightAvailable () {
|
|
|
|
const user = this.authService.getUser()
|
|
|
|
if (!user) return undefined
|
|
|
|
|
|
|
|
const adminRights = [
|
|
|
|
UserRight.MANAGE_USERS,
|
2017-11-16 17:16:42 +01:00
|
|
|
UserRight.MANAGE_SERVER_FOLLOW,
|
2020-07-01 16:05:30 +02:00
|
|
|
UserRight.MANAGE_ABUSES,
|
2020-06-09 16:07:10 +02:00
|
|
|
UserRight.MANAGE_VIDEO_BLACKLIST,
|
2018-09-19 09:53:49 +02:00
|
|
|
UserRight.MANAGE_JOBS,
|
|
|
|
UserRight.MANAGE_CONFIGURATION
|
2017-10-27 16:55:03 +02:00
|
|
|
]
|
|
|
|
|
|
|
|
for (const adminRight of adminRights) {
|
|
|
|
if (user.hasRight(adminRight)) {
|
|
|
|
return adminRight
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return undefined
|
|
|
|
}
|
|
|
|
|
|
|
|
getFirstAdminRouteAvailable () {
|
|
|
|
const right = this.getFirstAdminRightAvailable()
|
|
|
|
|
|
|
|
return this.routesPerRight[right]
|
2016-08-12 16:52:10 +02:00
|
|
|
}
|
|
|
|
|
2017-12-01 09:20:19 +01:00
|
|
|
logout (event: Event) {
|
|
|
|
event.preventDefault()
|
|
|
|
|
2017-06-16 14:32:15 +02:00
|
|
|
this.authService.logout()
|
2016-08-12 16:52:10 +02:00
|
|
|
// Redirect to home page
|
2018-06-04 16:21:17 +02:00
|
|
|
this.redirectService.redirectToHomepage()
|
2016-08-12 16:52:10 +02:00
|
|
|
}
|
2017-10-27 16:55:03 +02:00
|
|
|
|
2018-06-28 13:59:48 +02:00
|
|
|
openLanguageChooser () {
|
|
|
|
this.languageChooserModal.show()
|
|
|
|
}
|
|
|
|
|
2018-09-26 14:23:10 +02:00
|
|
|
openHotkeysCheatSheet () {
|
|
|
|
this.hotkeysService.cheatSheetToggle.next(!this.helpVisible)
|
|
|
|
}
|
|
|
|
|
2020-02-28 13:52:21 +01:00
|
|
|
openQuickSettings () {
|
|
|
|
this.quickSettingsModal.show()
|
|
|
|
}
|
|
|
|
|
|
|
|
toggleUseP2P () {
|
|
|
|
if (!this.user) return
|
2021-12-15 15:58:10 +01:00
|
|
|
this.user.p2pEnabled = !this.user.p2pEnabled
|
2020-03-11 16:41:38 +01:00
|
|
|
|
2021-12-15 15:58:10 +01:00
|
|
|
this.userService.updateMyProfile({ p2pEnabled: this.user.p2pEnabled })
|
2020-07-28 15:18:38 +02:00
|
|
|
.subscribe(() => this.authService.refreshUserInformation())
|
2020-02-28 13:52:21 +01:00
|
|
|
}
|
|
|
|
|
2020-02-28 13:54:31 +01:00
|
|
|
langForLocale (localeId: string) {
|
2020-08-12 10:40:04 +02:00
|
|
|
if (localeId === '_unknown') return $localize`Unknown`
|
2020-04-16 17:04:02 +02:00
|
|
|
|
2020-03-11 16:41:38 +01:00
|
|
|
return this.languages.find(lang => lang.id === localeId).label
|
|
|
|
}
|
|
|
|
|
2020-11-17 14:04:44 +01:00
|
|
|
onActiveLinkScrollToAnchor (link: HTMLAnchorElement) {
|
2020-08-17 10:13:31 +02:00
|
|
|
const linkURL = link.getAttribute('href')
|
|
|
|
const linkHash = link.getAttribute('fragment')
|
|
|
|
|
|
|
|
// On same url without fragment restore top scroll position
|
|
|
|
if (!linkHash && this.router.url.includes(linkURL)) {
|
2020-11-17 14:04:44 +01:00
|
|
|
scrollToTop('smooth')
|
2020-08-17 10:13:31 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// On same url with fragment restore anchor scroll position
|
|
|
|
if (linkHash && this.router.url === linkURL) {
|
2020-11-17 14:04:44 +01:00
|
|
|
this.viewportScroller.scrollToAnchor(linkHash)
|
2020-08-17 10:13:31 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
if (this.screenService.isInSmallView()) {
|
|
|
|
this.menuService.toggleMenu()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-12-13 14:54:12 +01:00
|
|
|
// Lock menu scroll when menu scroll to avoid fleeing / detached dropdown
|
|
|
|
onMenuScrollEvent () {
|
|
|
|
document.querySelector('menu').scrollTo(0, 0)
|
|
|
|
}
|
|
|
|
|
|
|
|
onDropdownOpenChange (opened: boolean) {
|
|
|
|
if (this.screenService.isInMobileView()) return
|
|
|
|
|
|
|
|
// Close dropdown when window scroll to avoid dropdown quick jump for re-position
|
|
|
|
const onWindowScroll = () => {
|
2021-01-14 15:35:03 +01:00
|
|
|
this.dropdown?.close()
|
2020-12-13 14:54:12 +01:00
|
|
|
window.removeEventListener('scroll', onWindowScroll)
|
|
|
|
}
|
|
|
|
|
|
|
|
if (opened) {
|
|
|
|
window.addEventListener('scroll', onWindowScroll)
|
|
|
|
document.querySelector('menu').scrollTo(0, 0) // Reset menu scroll to easy lock
|
|
|
|
document.querySelector('menu').addEventListener('scroll', this.onMenuScrollEvent)
|
|
|
|
} else {
|
|
|
|
document.querySelector('menu').removeEventListener('scroll', this.onMenuScrollEvent)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-06-07 13:16:50 +02:00
|
|
|
private async buildMenuSections () {
|
|
|
|
const menuSections = []
|
|
|
|
|
|
|
|
if (this.isLoggedIn) {
|
|
|
|
menuSections.push(
|
|
|
|
this.menuService.buildLibraryLinks(this.user?.canSeeVideosLink)
|
|
|
|
)
|
|
|
|
}
|
|
|
|
|
|
|
|
menuSections.push(
|
|
|
|
this.menuService.buildCommonLinks(this.htmlServerConfig)
|
|
|
|
)
|
|
|
|
|
|
|
|
this.menuSections = await this.hooks.wrapObject(menuSections, 'common', 'filter:left-menu.links.create.result')
|
2021-05-27 15:59:55 +02:00
|
|
|
}
|
|
|
|
|
2020-03-11 16:41:38 +01:00
|
|
|
private buildUserLanguages () {
|
|
|
|
if (!this.user) {
|
|
|
|
this.videoLanguages = []
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!this.user.videoLanguages) {
|
2021-06-07 13:16:50 +02:00
|
|
|
this.videoLanguages = [ $localize`any language` ]
|
2020-03-11 16:41:38 +01:00
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
this.videoLanguages = this.user.videoLanguages
|
2020-07-28 15:18:38 +02:00
|
|
|
.map(locale => this.langForLocale(locale))
|
|
|
|
.map(value => value === undefined ? '?' : value)
|
2020-02-28 13:52:21 +01:00
|
|
|
}
|
|
|
|
|
2020-07-28 15:18:38 +02:00
|
|
|
private computeAdminAccess () {
|
2017-10-27 16:55:03 +02:00
|
|
|
const right = this.getFirstAdminRightAvailable()
|
|
|
|
|
|
|
|
this.userHasAdminAccess = right !== undefined
|
|
|
|
}
|
2020-07-28 15:18:38 +02:00
|
|
|
|
|
|
|
private computeVideosLink () {
|
2021-06-07 13:16:50 +02:00
|
|
|
if (!this.isLoggedIn) return
|
|
|
|
|
2020-07-28 15:18:38 +02:00
|
|
|
this.authService.userInformationLoaded
|
|
|
|
.pipe(
|
|
|
|
switchMap(() => this.user.computeCanSeeVideosLink(this.userService.getMyVideoQuotaUsed()))
|
|
|
|
).subscribe(res => {
|
|
|
|
if (res === true) logger('User can see videos link.')
|
|
|
|
else logger('User cannot see videos link.')
|
|
|
|
})
|
|
|
|
}
|
2020-11-27 15:31:09 +01:00
|
|
|
|
|
|
|
private computeNSFWPolicy () {
|
|
|
|
if (!this.user) {
|
|
|
|
this.nsfwPolicy = null
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
switch (this.user.nsfwPolicy) {
|
|
|
|
case 'do_not_list':
|
|
|
|
this.nsfwPolicy = $localize`hide`
|
|
|
|
break
|
|
|
|
|
|
|
|
case 'blur':
|
|
|
|
this.nsfwPolicy = $localize`blur`
|
|
|
|
break
|
|
|
|
|
|
|
|
case 'display':
|
|
|
|
this.nsfwPolicy = $localize`display`
|
|
|
|
break
|
|
|
|
}
|
|
|
|
}
|
2021-06-07 13:16:50 +02:00
|
|
|
|
|
|
|
private updateUserState () {
|
|
|
|
this.user = this.isLoggedIn
|
|
|
|
? this.authService.getUser()
|
|
|
|
: undefined
|
|
|
|
|
|
|
|
this.computeAdminAccess()
|
|
|
|
this.computeNSFWPolicy()
|
|
|
|
this.computeVideosLink()
|
|
|
|
}
|
2016-08-12 16:52:10 +02:00
|
|
|
}
|