Refactor client @actorName matcher with new API route

This commit is contained in:
Kimsible 2021-04-28 22:17:02 +02:00
parent 08ac081b37
commit 69e076ddb0
6 changed files with 102 additions and 46 deletions

View File

@ -1,41 +0,0 @@
import { Component, OnInit } from '@angular/core'
import { empty } from 'rxjs'
import { catchError } from 'rxjs/operators'
import { RestExtractor } from '@app/core'
import { ActivatedRoute, Router } from '@angular/router'
import { AccountService } from '@app/shared/shared-main/account'
@Component({
selector: 'my-actor',
template: ''
})
export class ActorsComponent implements OnInit {
constructor (
private accountService: AccountService,
private route: ActivatedRoute,
private restExtractor: RestExtractor,
private router: Router
) {
}
ngOnInit () {
const accountOrChannelName = this.route.snapshot.params['actorName'].replace('@', '')
this.accountService
.getAccount(accountOrChannelName)
.pipe(
catchError(res => {
if (res.status === 404 && res.message === 'Account not found') {
this.router.navigateByUrl(`/video-channels/${accountOrChannelName}`)
return empty()
}
return this.restExtractor.handleError(res)
})
)
.subscribe(() => {
this.router.navigateByUrl(`/accounts/${accountOrChannelName}`)
})
}
}

View File

@ -1,11 +1,11 @@
import { NgModule } from '@angular/core' import { NgModule } from '@angular/core'
import { RouteReuseStrategy, RouterModule, Routes } from '@angular/router' import { RouteReuseStrategy, RouterModule, Routes, UrlMatchResult, UrlSegment } from '@angular/router'
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' import { MenuGuards } from '@app/core/routing/menu-guard.service'
import { POSSIBLE_LOCALES } from '@shared/core-utils/i18n' import { POSSIBLE_LOCALES } from '@shared/core-utils/i18n'
import { PreloadSelectedModulesList } from './core' import { PreloadSelectedModulesList } from './core'
import { EmptyComponent } from './empty.component' import { EmptyComponent } from './empty.component'
import { ActorsComponent } from './+actors/actors.component' import { RootComponent } from './root.component'
const routes: Routes = [ const routes: Routes = [
{ {
@ -75,8 +75,20 @@ const routes: Routes = [
redirectTo: 'video-channels' redirectTo: 'video-channels'
}, },
{ {
path: ':actorName', matcher: (url): UrlMatchResult => {
component: ActorsComponent // Matches /@:actorName
if (url.length === 1 && url[0].path.match(/^@[\w]+$/gm)) {
return {
consumed: url,
posParams: {
actorName: new UrlSegment(url[0].path.substr(1), {})
}
}
}
return null
},
component: RootComponent
}, },
{ {
path: '', path: '',

View File

@ -0,0 +1,42 @@
import { Component, OnInit } from '@angular/core'
import { catchError, distinctUntilChanged, map, switchMap } from 'rxjs/operators'
import { ActivatedRoute, Router } from '@angular/router'
import { RestExtractor } from '@app/core'
import { ActorService } from '@app/shared/shared-main/account'
import { HttpStatusCode } from '@shared/core-utils/miscs/http-error-codes'
@Component({
selector: 'my-root',
template: ''
})
export class RootComponent implements OnInit {
constructor (
private actorService: ActorService,
private route: ActivatedRoute,
private restExtractor: RestExtractor,
private router: Router
) {
}
ngOnInit () {
this.route.params
.pipe(
map(params => params[ 'actorName' ]),
distinctUntilChanged(),
switchMap(actorName => this.actorService.getActor(actorName)),
catchError(err => this.restExtractor.redirectTo404IfNotFound(err, 'other', [
HttpStatusCode.BAD_REQUEST_400,
HttpStatusCode.NOT_FOUND_404
]))
)
.subscribe(actor => {
if (actor.constructor.name === 'Account') {
this.router.navigateByUrl(`/accounts/${actor.name}`)
}
if (actor.constructor.name === 'VideoChannel') {
this.router.navigateByUrl(`/video-channels/${actor.name}`)
}
})
}
}

View File

@ -0,0 +1,41 @@
import { Observable, ReplaySubject } from 'rxjs'
import { catchError, map, tap } from 'rxjs/operators'
import { HttpClient } from '@angular/common/http'
import { Injectable } from '@angular/core'
import { RestExtractor } from '@app/core'
import { Account as ServerAccount, VideoChannel as ServerVideoChannel } from '@shared/models'
import { environment } from '../../../../environments/environment'
import { Account } from './account.model'
import { VideoChannel } from '../video-channel/video-channel.model'
@Injectable()
export class ActorService {
static BASE_ACTOR_API_URL = environment.apiUrl + '/api/v1/actors/'
actorLoaded = new ReplaySubject<Account | VideoChannel>(1)
constructor (
private authHttp: HttpClient,
private restExtractor: RestExtractor
) {}
getActor (actorName: string): Observable<Account | VideoChannel> {
return this.authHttp.get<ServerAccount | ServerVideoChannel>(ActorService.BASE_ACTOR_API_URL + actorName)
.pipe(
map(actorHash => {
const isAccount = /\/accounts\/.+/.test(actorHash.url)
const isVideoChannel = /\/video-channels\/.+/.test(actorHash.url)
if (isAccount) {
return new Account(actorHash)
}
if (isVideoChannel) {
return new VideoChannel(actorHash)
}
}),
tap(actor => this.actorLoaded.next(actor)),
catchError(res => this.restExtractor.handleError(res))
)
}
}

View File

@ -1,3 +1,4 @@
export * from './account.model' export * from './account.model'
export * from './account.service' export * from './account.service'
export * from './actor.model' export * from './actor.model'
export * from './actor.service'

View File

@ -17,7 +17,7 @@ import {
import { LoadingBarModule } from '@ngx-loading-bar/core' import { LoadingBarModule } from '@ngx-loading-bar/core'
import { LoadingBarHttpClientModule } from '@ngx-loading-bar/http-client' import { LoadingBarHttpClientModule } from '@ngx-loading-bar/http-client'
import { SharedGlobalIconModule } from '../shared-icons' import { SharedGlobalIconModule } from '../shared-icons'
import { AccountService } from './account' import { AccountService, ActorService } from './account'
import { import {
AutofocusDirective, AutofocusDirective,
BytesPipe, BytesPipe,
@ -160,6 +160,7 @@ import { VideoChannelService } from './video-channel'
AUTH_INTERCEPTOR_PROVIDER, AUTH_INTERCEPTOR_PROVIDER,
AccountService, AccountService,
ActorService,
UserHistoryService, UserHistoryService,
UserNotificationService, UserNotificationService,