diff --git a/src/app/modules/presentation/remote/remote.component.ts b/src/app/modules/presentation/remote/remote.component.ts index e5db898..8efa0c4 100644 --- a/src/app/modules/presentation/remote/remote.component.ts +++ b/src/app/modules/presentation/remote/remote.component.ts @@ -83,31 +83,40 @@ export class RemoteComponent implements OnDestroy { globalSettingsService: GlobalSettingsService, private cRef: ChangeDetectorRef ) { - globalSettingsService.get$ + const currentShowId$ = globalSettingsService.get$ .pipe( filter((settings): settings is NonNullable => !!settings), map(_ => _.currentShow), filter((showId): showId is string => !!showId), distinctUntilChanged(), - switchMap(showId => - combineLatest([this.showService.read$(showId), this.showSongService.list$(showId)]).pipe( - map(([show, list]) => { - const presentationSongs = list.map(song => ({ - id: song.id, - title: song.title, - sections: this.textRenderingService.parse(song.text, null, false), - })); - return {show, list, presentationSongs}; - }) - ) - ), takeUntil(this.destroy$) - ) - .subscribe(({show, list, presentationSongs}) => { - this.showSongs = list; + ); + + const show$ = currentShowId$.pipe( + switchMap(showId => this.showService.read$(showId)), + takeUntil(this.destroy$) + ); + + const parsedSongs$ = currentShowId$.pipe( + switchMap(showId => this.showSongService.list$(showId)), + map(list => ({ + list, + parsed: list.map(song => ({ + id: song.id, + title: song.title, + sections: this.textRenderingService.parse(song.text, null, false), + })), + })), + takeUntil(this.destroy$) + ); + + combineLatest([show$, parsedSongs$]) + .pipe(takeUntil(this.destroy$)) + .subscribe(([show, parsedSongs]) => { + this.showSongs = parsedSongs.list; this.show = show; const order = show?.order ?? []; - const presentationSongsById = new Map(presentationSongs.map(song => [song.id, song] as const)); + const presentationSongsById = new Map(parsedSongs.parsed.map(song => [song.id, song] as const)); this.presentationSongs = order.map(id => presentationSongsById.get(id) ?? null).filter((s): s is PresentationSong => !!s); this.cRef.markForCheck(); }); diff --git a/src/app/modules/shows/show/show.component.html b/src/app/modules/shows/show/show.component.html index 474da1d..e8eadc8 100644 --- a/src/app/modules/shows/show/show.component.html +++ b/src/app/modules/shows/show/show.component.html @@ -60,12 +60,14 @@ - + + + diff --git a/src/app/modules/shows/show/show.component.ts b/src/app/modules/shows/show/show.component.ts index 75df8b6..910cb22 100644 --- a/src/app/modules/shows/show/show.component.ts +++ b/src/app/modules/shows/show/show.component.ts @@ -1,8 +1,8 @@ import {ChangeDetectorRef, Component, CUSTOM_ELEMENTS_SCHEMA, HostListener, OnDestroy, OnInit} from '@angular/core'; -import {filter, map, switchMap, tap} from 'rxjs/operators'; +import {filter, map, shareReplay, switchMap, tap} from 'rxjs/operators'; import {ActivatedRoute, Router} from '@angular/router'; import {ShowService} from '../services/show.service'; -import {Observable, Subscription} from 'rxjs'; +import {Observable, of, Subscription} from 'rxjs'; import {Show} from '../services/show'; import {SongService} from '../../songs/services/song.service'; import {Song} from '../../songs/services/song'; @@ -83,7 +83,7 @@ import {ShowTypePipe} from '../../../widget-modules/pipes/show-type-translater/s }) export class ShowComponent implements OnInit, OnDestroy { public show$: Observable | null = null; - public songs: Song[] | null = null; + public songs$: Observable | null = null; public showSongs: ShowSong[] | null = null; public showId: string | null = null; public showText = false; @@ -128,7 +128,11 @@ export class ShowComponent implements OnInit, OnDestroy { map(param => param as {showId: string}), map(param => param.showId), tap((_: string) => (this.showId = _)), - switchMap((showId: string) => this.showService.read$(showId)) + switchMap((showId: string) => this.showService.read$(showId)), + shareReplay({ + bufferSize: 1, + refCount: true, + }) ); this.subs.push( this.activatedRoute.params @@ -141,15 +145,16 @@ export class ShowComponent implements OnInit, OnDestroy { .subscribe(_ => { this.showSongs = _; this.cRef.markForCheck(); - }), - this.songService - .list$() - .pipe(filter(_ => !!_)) - .subscribe(_ => { - this.songs = _; - this.cRef.markForCheck(); }) ); + + this.songs$ = this.show$.pipe( + switchMap(show => (show && !show.published ? this.songService.list$() : of(null))), + shareReplay({ + bufferSize: 1, + refCount: true, + }) + ); } public ngOnDestroy(): void { @@ -217,7 +222,8 @@ export class ShowComponent implements OnInit, OnDestroy { public orderedShowSongs(show: Show): ShowSong[] { const list = this.showSongs; if (!list) return []; - return show.order.map(_ => list.filter(f => f.id === _)[0]); + const byId = new Map(list.map(item => [item.id, item] as const)); + return show.order.map(id => byId.get(id)).filter((song): song is ShowSong => !!song); } public trackBy = (_: number, show: ShowSong) => show?.id; diff --git a/src/app/modules/songs/song/new/new.component.ts b/src/app/modules/songs/song/new/new.component.ts index de07dbc..22ea5d8 100644 --- a/src/app/modules/songs/song/new/new.component.ts +++ b/src/app/modules/songs/song/new/new.component.ts @@ -5,6 +5,7 @@ import {SongService} from '../../services/song.service'; import {Song} from '../../services/song'; import {Router} from '@angular/router'; import {Subscription} from 'rxjs'; +import {take} from 'rxjs/operators'; import {CardComponent} from '../../../../widget-modules/components/card/card.component'; import {MatFormField, MatLabel} from '@angular/material/form-field'; import {MatInput} from '@angular/material/input'; @@ -34,7 +35,7 @@ export class NewComponent implements OnInit, OnDestroy { this.form.reset(); this.subs.push( - this.songService.list$().subscribe(songs => { + this.songService.list$().pipe(take(1)).subscribe(songs => { const freeSongnumber = this.getFreeSongNumber(songs); this.form.controls.number.setValue(freeSongnumber); }) diff --git a/src/app/services/user/user.service.ts b/src/app/services/user/user.service.ts index 824d959..31144de 100644 --- a/src/app/services/user/user.service.ts +++ b/src/app/services/user/user.service.ts @@ -23,6 +23,7 @@ export class UserService { public users$ = this.db.col$('users').pipe(shareReplay({bufferSize: 1, refCount: true})); private iUserId$ = new BehaviorSubject(null); private iUser$ = new BehaviorSubject(null); + private userByIdCache = new Map>(); public constructor( private afAuth: AngularFireAuth, @@ -52,7 +53,16 @@ export class UserService { public currentUser = async (): Promise => firstValueFrom(this.user$); public getUserbyId = (userId: string): Promise => firstValueFrom(this.getUserbyId$(userId)); - public getUserbyId$ = (userId: string): Observable => this.users$.pipe(map(_ => _.find(f => f.id === userId) || null)); + public getUserbyId$ = (userId: string): Observable => { + const cached = this.userByIdCache.get(userId); + if (cached) { + return cached; + } + + const user$ = this.db.doc$(`users/${userId}`).pipe(shareReplay({bufferSize: 1, refCount: true})); + this.userByIdCache.set(userId, user$); + return user$; + }; public async login(user: string, password: string): Promise { const aUser = await this.afAuth.signInWithEmailAndPassword(user, password);