"@ngx-loading-bar/core": "^5.0.0",
"@ngx-loading-bar/http-client": "^5.0.0",
"@ngx-loading-bar/router": "^5.0.0",
- "@ngx-meta/core": "^9.0.0",
"@types/chart.js": "^2.9.16",
"@types/core-js": "^2.5.2",
"@types/debug": "^4.1.5",
import { NgModule } from '@angular/core'
import { RouterModule, Routes } from '@angular/router'
-import { MetaGuard } from '@ngx-meta/core'
-import { AboutComponent } from './about.component'
-import { AboutInstanceComponent } from '@app/+about/about-instance/about-instance.component'
-import { AboutPeertubeComponent } from '@app/+about/about-peertube/about-peertube.component'
import { AboutFollowsComponent } from '@app/+about/about-follows/about-follows.component'
+import { AboutInstanceComponent } from '@app/+about/about-instance/about-instance.component'
import { AboutInstanceResolver } from '@app/+about/about-instance/about-instance.resolver'
+import { AboutPeertubeComponent } from '@app/+about/about-peertube/about-peertube.component'
+import { AboutComponent } from './about.component'
const aboutRoutes: Routes = [
{
path: '',
component: AboutComponent,
- canActivateChild: [ MetaGuard ],
children: [
{
path: '',
import { NgModule } from '@angular/core'
import { RouterModule, Routes } from '@angular/router'
-import { MetaGuard } from '@ngx-meta/core'
import { AccountSearchComponent } from './account-search/account-search.component'
import { AccountVideoChannelsComponent } from './account-video-channels/account-video-channels.component'
import { AccountVideosComponent } from './account-videos/account-videos.component'
{
path: ':accountId',
component: AccountsComponent,
- canActivateChild: [ MetaGuard ],
children: [
{
path: '',
import { ModerationRoutes } from '@app/+admin/moderation/moderation.routes'
import { PluginsRoutes } from '@app/+admin/plugins/plugins.routes'
import { SystemRoutes } from '@app/+admin/system'
-import { MetaGuard } from '@ngx-meta/core'
import { AdminComponent } from './admin.component'
import { FollowsRoutes } from './follows'
import { UsersRoutes } from './users'
{
path: '',
component: AdminComponent,
- canActivate: [ MetaGuard ],
- canActivateChild: [ MetaGuard ],
children: [
{
path: '',
import { NgModule } from '@angular/core'
import { RouterModule, Routes } from '@angular/router'
-import { MetaGuard } from '@ngx-meta/core'
-import { LoginComponent } from './login.component'
import { ServerConfigResolver } from '@app/core/routing/server-config-resolver.service'
+import { LoginComponent } from './login.component'
const loginRoutes: Routes = [
{
path: '',
component: LoginComponent,
- canActivate: [ MetaGuard ],
data: {
meta: {
title: $localize`Login`
import { NgModule } from '@angular/core'
import { RouterModule, Routes } from '@angular/router'
-import { MetaGuard } from '@ngx-meta/core'
import { LoginGuard } from '../core'
import { MyAccountAbusesListComponent } from './my-account-abuses/my-account-abuses-list.component'
+import { MyAccountApplicationsComponent } from './my-account-applications/my-account-applications.component'
import { MyAccountBlocklistComponent } from './my-account-blocklist/my-account-blocklist.component'
import { MyAccountServerBlocklistComponent } from './my-account-blocklist/my-account-server-blocklist.component'
import { MyAccountNotificationsComponent } from './my-account-notifications/my-account-notifications.component'
import { MyAccountSettingsComponent } from './my-account-settings/my-account-settings.component'
import { MyAccountComponent } from './my-account.component'
-import { MyAccountApplicationsComponent } from './my-account-applications/my-account-applications.component'
const myAccountRoutes: Routes = [
{
path: '',
component: MyAccountComponent,
- canActivateChild: [ MetaGuard, LoginGuard ],
+ canActivateChild: [ LoginGuard ],
children: [
{
path: '',
import { NgModule } from '@angular/core'
import { RouterModule, Routes } from '@angular/router'
-import { MetaGuard } from '@ngx-meta/core'
import { LoginGuard } from '../core'
import { MyHistoryComponent } from './my-history/my-history.component'
import { MyLibraryComponent } from './my-library.component'
{
path: '',
component: MyLibraryComponent,
- canActivateChild: [ MetaGuard, LoginGuard ],
+ canActivateChild: [ LoginGuard ],
children: [
{
path: '',
import { NgModule } from '@angular/core'
import { RouterModule, Routes } from '@angular/router'
-import { MetaGuard } from '@ngx-meta/core'
import { ResetPasswordComponent } from './reset-password.component'
const resetPasswordRoutes: Routes = [
{
path: '',
component: ResetPasswordComponent,
- canActivate: [ MetaGuard ],
data: {
meta: {
- title: `Reset password`
+ title: $localize`Reset password`
}
}
}
import { NgModule } from '@angular/core'
import { RouterModule, Routes } from '@angular/router'
-import { MetaGuard } from '@ngx-meta/core'
import { ChannelLazyLoadResolver } from './channel-lazy-load.resolver'
import { SearchComponent } from './search.component'
import { VideoLazyLoadResolver } from './video-lazy-load.resolver'
{
path: '',
component: SearchComponent,
- canActivate: [ MetaGuard ],
data: {
meta: {
title: $localize`Search`
{
path: 'lazy-load-video',
component: SearchComponent,
- canActivate: [ MetaGuard ],
resolve: {
data: VideoLazyLoadResolver
}
{
path: 'lazy-load-channel',
component: SearchComponent,
- canActivate: [ MetaGuard ],
resolve: {
data: ChannelLazyLoadResolver
}
import { forkJoin, of, Subscription } from 'rxjs'
import { Component, OnDestroy, OnInit } from '@angular/core'
import { ActivatedRoute, Router } from '@angular/router'
-import { AuthService, ComponentPagination, HooksService, Notifier, ServerService, User, UserService } from '@app/core'
+import { AuthService, ComponentPagination, HooksService, MetaService, Notifier, ServerService, User, UserService } from '@app/core'
import { immutableAssign } from '@app/helpers'
import { Video, VideoChannel } from '@app/shared/shared-main'
import { AdvancedSearch, SearchService } from '@app/shared/shared-search'
import { MiniatureDisplayOptions, VideoLinkType } from '@app/shared/shared-video-miniature'
-import { MetaService } from '@ngx-meta/core'
import { SearchTargetType, ServerConfig } from '@shared/models'
@Component({
}
private updateTitle () {
- const suffix = this.currentSearch ? ' ' + this.currentSearch : ''
+ const suffix = this.currentSearch
+ ? ' ' + this.currentSearch
+ : ''
+
this.metaService.setTitle($localize`Search` + suffix)
}
import { NgModule } from '@angular/core'
import { RouterModule, Routes } from '@angular/router'
import { ServerConfigResolver, UnloggedGuard } from '@app/core'
-import { MetaGuard } from '@ngx-meta/core'
import { RegisterComponent } from './register.component'
const registerRoutes: Routes = [
{
path: '',
component: RegisterComponent,
- canActivate: [ MetaGuard, UnloggedGuard ],
+ canActivate: [ UnloggedGuard ],
data: {
meta: {
title: $localize`Register`
import { NgModule } from '@angular/core'
import { RouterModule, Routes } from '@angular/router'
-import { MetaGuard } from '@ngx-meta/core'
-import { VerifyAccountEmailComponent } from './verify-account-email/verify-account-email.component'
import { VerifyAccountAskSendEmailComponent } from './verify-account-ask-send-email/verify-account-ask-send-email.component'
+import { VerifyAccountEmailComponent } from './verify-account-email/verify-account-email.component'
const verifyAccountRoutes: Routes = [
{
path: '',
- canActivateChild: [ MetaGuard ],
children: [
{
path: 'email',
import { NgModule } from '@angular/core'
import { RouterModule, Routes } from '@angular/router'
-import { MetaGuard } from '@ngx-meta/core'
import { VideoChannelPlaylistsComponent } from './video-channel-playlists/video-channel-playlists.component'
import { VideoChannelVideosComponent } from './video-channel-videos/video-channel-videos.component'
import { VideoChannelsComponent } from './video-channels.component'
{
path: ':videoChannelName',
component: VideoChannelsComponent,
- canActivateChild: [ MetaGuard ],
children: [
{
path: '',
import { NgModule } from '@angular/core'
import { RouterModule, Routes } from '@angular/router'
import { CanDeactivateGuard, LoginGuard } from '@app/core'
-import { MetaGuard } from '@ngx-meta/core'
import { VideoAddComponent } from './video-add.component'
const videoAddRoutes: Routes = [
{
path: '',
component: VideoAddComponent,
- canActivate: [ MetaGuard, LoginGuard ],
+ canActivate: [ LoginGuard ],
canDeactivate: [ CanDeactivateGuard ]
}
]
import { NgModule } from '@angular/core'
import { RouterModule, Routes } from '@angular/router'
import { CanDeactivateGuard, LoginGuard } from '@app/core'
-import { MetaGuard } from '@ngx-meta/core'
import { VideoUpdateComponent } from './video-update.component'
import { VideoUpdateResolver } from './video-update.resolver'
{
path: '',
component: VideoUpdateComponent,
- canActivate: [ MetaGuard, LoginGuard ],
+ canActivate: [ LoginGuard ],
canDeactivate: [ CanDeactivateGuard ],
resolve: {
videoData: VideoUpdateResolver
import { NgModule } from '@angular/core'
import { RouterModule, Routes } from '@angular/router'
-import { MetaGuard } from '@ngx-meta/core'
import { VideoWatchComponent } from './video-watch.component'
const videoWatchRoutes: Routes = [
{
path: 'playlist/:playlistId',
- component: VideoWatchComponent,
- canActivate: [ MetaGuard ]
+ component: VideoWatchComponent
},
{
path: ':videoId/comments/:commentId',
},
{
path: ':videoId',
- component: VideoWatchComponent,
- canActivate: [ MetaGuard ]
+ component: VideoWatchComponent
}
]
AuthUser,
ConfirmService,
MarkdownService,
+ MetaService,
Notifier,
PeerTubeSocket,
RestExtractor,
import { SubscribeButtonComponent } from '@app/shared/shared-user-subscription'
import { VideoActionsDisplayType, VideoDownloadComponent } from '@app/shared/shared-video-miniature'
import { VideoPlaylist, VideoPlaylistService } from '@app/shared/shared-video-playlist'
-import { MetaService } from '@ngx-meta/core'
import { peertubeLocalStorage } from '@root-helpers/peertube-web-storage'
import { HttpStatusCode } from '@shared/core-utils/miscs/http-error-codes'
import { ServerConfig, ServerErrorCode, UserVideoRateType, VideoCaption, VideoPrivacy, VideoState } from '@shared/models'
import { NgModule } from '@angular/core'
import { RouterModule, Routes } from '@angular/router'
import { LoginGuard } from '@app/core'
-import { MetaGuard } from '@ngx-meta/core'
import { VideoTrendingComponent } from './video-list'
import { VideoOverviewComponent } from './video-list/overview/video-overview.component'
import { VideoLocalComponent } from './video-list/video-local.component'
{
path: '',
component: VideosComponent,
- canActivateChild: [ MetaGuard ],
children: [
{
path: 'overview',
import { CustomReuseStrategy } from '@app/core/routing/custom-reuse-strategy'
import { MenuGuards } from '@app/core/routing/menu-guard.service'
import { POSSIBLE_LOCALES } from '@shared/core-utils/i18n'
-import { PreloadSelectedModulesList } from './core'
+import { MetaGuard, PreloadSelectedModulesList } from './core'
import { EmptyComponent } from './empty.component'
const routes: Routes = [
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),
+ canActivateChild: [ MetaGuard ]
},
{
path: 'home',
},
{
path: 'my-account',
- loadChildren: () => import('./+my-account/my-account.module').then(m => m.MyAccountModule)
+ loadChildren: () => import('./+my-account/my-account.module').then(m => m.MyAccountModule),
+ canActivateChild: [ MetaGuard ]
},
{
path: 'my-library',
- loadChildren: () => import('./+my-library/my-library.module').then(m => m.MyLibraryModule)
+ loadChildren: () => import('./+my-library/my-library.module').then(m => m.MyLibraryModule),
+ canActivateChild: [ MetaGuard ]
},
{
path: 'verify-account',
- loadChildren: () => import('./+signup/+verify-account/verify-account.module').then(m => m.VerifyAccountModule)
+ loadChildren: () => import('./+signup/+verify-account/verify-account.module').then(m => m.VerifyAccountModule),
+ canActivateChild: [ MetaGuard ]
},
{
path: 'accounts',
- loadChildren: () => import('./+accounts/accounts.module').then(m => m.AccountsModule)
+ loadChildren: () => import('./+accounts/accounts.module').then(m => m.AccountsModule),
+ canActivateChild: [ MetaGuard ]
},
{
path: 'video-channels',
- loadChildren: () => import('./+video-channels/video-channels.module').then(m => m.VideoChannelsModule)
+ loadChildren: () => import('./+video-channels/video-channels.module').then(m => m.VideoChannelsModule),
+ canActivateChild: [ MetaGuard ]
},
{
path: 'about',
- loadChildren: () => import('./+about/about.module').then(m => m.AboutModule)
+ loadChildren: () => import('./+about/about.module').then(m => m.AboutModule),
+ canActivateChild: [ MetaGuard ]
},
{
path: 'signup',
- loadChildren: () => import('./+signup/+register/register.module').then(m => m.RegisterModule)
+ loadChildren: () => import('./+signup/+register/register.module').then(m => m.RegisterModule),
+ canActivateChild: [ MetaGuard ]
},
{
path: 'reset-password',
- loadChildren: () => import('./+reset-password/reset-password.module').then(m => m.ResetPasswordModule)
+ loadChildren: () => import('./+reset-password/reset-password.module').then(m => m.ResetPasswordModule),
+ canActivateChild: [ MetaGuard ]
},
{
path: 'login',
- loadChildren: () => import('./+login/login.module').then(m => m.LoginModule)
+ loadChildren: () => import('./+login/login.module').then(m => m.LoginModule),
+ canActivateChild: [ MetaGuard ]
},
{
path: 'search',
- loadChildren: () => import('./+search/search.module').then(m => m.SearchModule)
+ loadChildren: () => import('./+search/search.module').then(m => m.SearchModule),
+ canActivateChild: [ MetaGuard ]
},
{
path: 'videos',
- loadChildren: () => import('./+videos/videos.module').then(m => m.VideosModule)
+ loadChildren: () => import('./+videos/videos.module').then(m => m.VideosModule),
+ canActivateChild: [ MetaGuard ]
},
{
path: 'remote-interaction',
- loadChildren: () => import('./+remote-interaction/remote-interaction.module').then(m => m.RemoteInteractionModule)
+ loadChildren: () => import('./+remote-interaction/remote-interaction.module').then(m => m.RemoteInteractionModule),
+ canActivateChild: [ MetaGuard ]
},
{
path: 'video-playlists/watch',
import { NgModule } from '@angular/core'
import { BrowserModule } from '@angular/platform-browser'
import { ServiceWorkerModule } from '@angular/service-worker'
-import { ServerService } from '@app/core'
import localeOc from '@app/helpers/locales/oc'
-import { MetaLoader, MetaModule, MetaStaticLoader, PageTitlePositioning } from '@ngx-meta/core'
import { AppRoutingModule } from './app-routing.module'
import { AppComponent } from './app.component'
import { CoreModule } from './core'
import { InstanceConfigWarningModalComponent } from './modal/instance-config-warning-modal.component'
import { QuickSettingsModalComponent } from './modal/quick-settings-modal.component'
import { WelcomeModalComponent } from './modal/welcome-modal.component'
+import { SharedActorImageModule } from './shared/shared-actor-image/shared-actor-image.module'
import { SharedFormModule } from './shared/shared-forms'
import { SharedGlobalIconModule } from './shared/shared-icons'
import { SharedInstanceModule } from './shared/shared-instance'
import { SharedMainModule } from './shared/shared-main'
import { SharedUserInterfaceSettingsModule } from './shared/shared-user-settings'
-import { SharedActorImageModule } from './shared/shared-actor-image/shared-actor-image.module'
registerLocaleData(localeOc, 'oc')
SharedInstanceModule,
SharedActorImageModule,
- MetaModule.forRoot({
- provide: MetaLoader,
- useFactory: (serverService: ServerService) => {
- return new MetaStaticLoader({
- pageTitlePositioning: PageTitlePositioning.PrependPageTitle,
- pageTitleSeparator: ' - ',
- get applicationName () { return serverService.getTmpConfig().instance.name },
- defaults: {
- get title () { return serverService.getTmpConfig().instance.name },
- get description () { return serverService.getTmpConfig().instance.shortDescription }
- }
- })
- },
- deps: [ ServerService ]
- }),
-
AppRoutingModule // Put it after all the module because it has the 404 route
],
import { Notifier } from './notification'
import { HtmlRendererService, LinkifierService, MarkdownService } from './renderer'
import { RestExtractor, RestService } from './rest'
-import { LoginGuard, RedirectService, UnloggedGuard, UserRightGuard } from './routing'
+import { LoginGuard, MetaGuard, MetaService, RedirectService, UnloggedGuard, UserRightGuard } from './routing'
import { CanDeactivateGuard } from './routing/can-deactivate-guard.service'
import { ServerConfigResolver } from './routing/server-config-resolver.service'
import { ScopedTokensService } from './scoped-tokens'
MessageService,
PeerTubeSocket,
ServerConfigResolver,
- CanDeactivateGuard
+ CanDeactivateGuard,
+
+ MetaService,
+ MetaGuard
]
})
export class CoreModule {
export * from './disable-for-reuse-hook'
export * from './login-guard.service'
export * from './menu-guard.service'
+export * from './meta-guard.service'
+export * from './meta.service'
export * from './preload-selected-modules-list'
export * from './redirect.service'
export * from './server-config-resolver.service'
--- /dev/null
+import { Injectable } from '@angular/core'
+import { ActivatedRouteSnapshot, CanActivate, CanActivateChild, RouterStateSnapshot } from '@angular/router'
+import { MetaService } from './meta.service'
+
+@Injectable()
+export class MetaGuard implements CanActivate, CanActivateChild {
+
+ constructor (private meta: MetaService) { }
+
+ canActivate (route: ActivatedRouteSnapshot): boolean {
+ const metaSettings = route.data?.meta
+
+ if (metaSettings) {
+ this.meta.update(metaSettings)
+ }
+
+ return true
+ }
+
+ canActivateChild (route: ActivatedRouteSnapshot): boolean {
+ return this.canActivate(route)
+ }
+}
--- /dev/null
+import { Injectable } from '@angular/core'
+import { Meta, Title } from '@angular/platform-browser'
+import { HTMLServerConfig } from '@shared/models/server'
+import { ServerService } from '../server'
+
+export interface MetaSettings {
+ title?: string
+}
+
+@Injectable()
+export class MetaService {
+ private config: HTMLServerConfig
+
+ constructor (
+ private titleService: Title,
+ private meta: Meta,
+ private server: ServerService
+ ) {
+ this.config = this.server.getTmpConfig()
+ this.server.getConfig()
+ .subscribe(config => this.config = config)
+ }
+
+ setTitle (subTitle?: string) {
+ let title = ''
+ if (subTitle) title += `${subTitle} - `
+
+ title += this.config.instance.name
+
+ this.titleService.setTitle(title)
+ }
+
+ setTag (name: string, value: string) {
+ this.meta.addTag({ name, content: value })
+ }
+
+ update (meta: MetaSettings) {
+ this.setTitle(meta.title)
+ }
+}
function proxify (instance: MemoryStorage) {
return new Proxy(instance, {
- set: function (obj, prop: string | number, value) {
+ set: function (obj, prop: string | symbol, value) {
if (MemoryStorage.prototype.hasOwnProperty(prop)) {
- instance[prop] = value
+ // FIXME: symbol typing issue https://github.com/microsoft/TypeScript/issues/1863
+ instance[prop as any] = value
} else {
instance.setItem(prop, value)
}
return true
},
- get: function (target, name: string | number) {
+ get: function (target, name: string | symbol | number) {
if (MemoryStorage.prototype.hasOwnProperty(name)) {
- return instance[name]
+ // FIXME: symbol typing issue https://github.com/microsoft/TypeScript/issues/1863
+ return instance[name as any]
}
if (valuesMap.has(name)) {
return instance.getItem(name)
})
}
-class MemoryStorage {
+class MemoryStorage implements Storage {
[key: string]: any
- [index: number]: string
getItem (key: any) {
const stringKey = String(key)
"declaration": false,
"moduleResolution": "node",
"module": "esnext",
- "emitDecoratorMetadata": true,
"experimentalDecorators": true,
"noImplicitAny": true,
"noImplicitThis": true,
dependencies:
tslib "^1.10.0"
-"@ngx-meta/core@^9.0.0":
- version "9.0.0"
- resolved "https://registry.yarnpkg.com/@ngx-meta/core/-/core-9.0.0.tgz#2c3b27bd32d41f7aaf0712d4007e0afed8e5dd3f"
- integrity sha512-WL/HyKM+4gJPS3TNTO0M+46LlIvGTSyofL//8hxoozAyRPsiMyR0xrwUvPBJkVqFyD6j0iI5FaNcQ9d0JCVJhg==
-
"@nodelib/fs.scandir@2.1.4":
version "2.1.4"
resolved "https://registry.yarnpkg.com/@nodelib/fs.scandir/-/fs.scandir-2.1.4.tgz#d4b3549a5db5de2683e0c1071ab4f140904bbf69"