chore: update Angular cache and TypeScript build info

This commit is contained in:
2025-09-23 21:45:57 -04:00
parent d372b7d509
commit 9a3983a253
18 changed files with 664 additions and 169 deletions
@@ -104,8 +104,8 @@
<a [routerLink]="['/watch', v.videoId]" [queryParams]="watchQueryParams(v)" [state]="{ video: v }" class="block bg-slate-800/50 rounded-lg overflow-hidden hover:bg-slate-700/50 transition-all duration-300 transform hover:-translate-y-1 shadow-lg hover:shadow-xl">
<div class="relative">
<img [src]="v.thumbnail" [alt]="v.title" loading="lazy" decoding="async" class="w-full aspect-video object-cover transition-transform duration-300 group-hover:scale-105">
<div class="absolute bottom-2 right-2 bg-black/75 text-white text-xs px-2 py-1 rounded-md font-mono">
{{ v.duration | number:'1.0-0' }}:{{ (v.duration % 60) | number:'2.0-0' }}
<div *ngIf="v.duration && v.duration > 0" class="absolute bottom-2 right-2 bg-black/75 text-white text-xs px-2 py-1 rounded-md font-mono">
{{ v.duration | duration }}
</div>
<div class="absolute top-2 left-2">
<app-like-button [videoId]="v.videoId" [provider]="provider()" [title]="v.title" [thumbnail]="v.thumbnail"></app-like-button>
@@ -8,13 +8,42 @@ import { YoutubeApiService } from '../../services/youtube-api.service';
import { Video } from '../../models/video.model';
import { TranslatePipe } from '../../pipes/translate.pipe';
import { LikeButtonComponent } from '../shared/components/like-button/like-button.component';
import { DurationPipe } from '../../app/shared/pipes/duration.pipe';
import { map, of, switchMap } from 'rxjs';
const TWITCH_THEME_KEYWORDS: Record<string, string[]> = {
trending: ['just chatting', 'highlights'],
live: ['live', 'stream'],
gaming: ['gaming', 'playthrough'],
sports: ['sports', 'esports'],
'finance-crypto': ['finance', 'crypto'],
business: ['business', 'entrepreneur'],
tech: ['technology', 'coding'],
science: ['science', 'space'],
health: ['fitness', 'wellness'],
music: ['music', 'performance'],
podcasts: ['podcast', 'talk show'],
'movies-tv': ['movie review', 'tv discussion'],
education: ['education', 'tutorial'],
travel: ['travel vlog'],
food: ['cooking', 'food'],
'diy-makers': ['diy', 'maker'],
autos: ['car build', 'automotive'],
'nature-animals': ['outdoors', 'wildlife'],
comedy: ['comedy', 'standup'],
'art-design': ['art stream', 'drawing'],
vlogs: ['vlog', 'lifestyle'],
reviews: ['tech review', 'unboxing'],
documentary: ['history', 'documentary'],
'family-kids': ['family', 'kids'],
news: ['news', 'politics'],
};
@Component({
selector: 'app-provider-theme',
standalone: true,
templateUrl: './provider-theme-page.component.html',
changeDetection: ChangeDetectionStrategy.OnPush,
imports: [CommonModule, FormsModule, RouterLink, TranslatePipe, LikeButtonComponent]
imports: [CommonModule, FormsModule, RouterLink, TranslatePipe, LikeButtonComponent, DurationPipe]
})
export class ProviderThemePageComponent implements OnDestroy {
private route = inject(ActivatedRoute);
@@ -76,9 +105,21 @@ export class ProviderThemePageComponent implements OnDestroy {
this.loadMore();
}
private buildQuery(): string {
const tokens = this.themes.tokensFor(this.theme());
return tokens.join(' ').trim();
private buildQuery(provider: Provider): string {
const slug = this.theme();
const baseTokens = this.themes.tokensFor(slug);
if (provider === 'twitch') {
const twitchTokens = TWITCH_THEME_KEYWORDS[slug] || [];
const merged = [...new Set([...twitchTokens, ...baseTokens])];
const value = merged.join(' ').trim();
if (value) return value;
if (twitchTokens.length) return twitchTokens.join(' ');
return slug.replace(/-/g, ' ');
}
const value = baseTokens.join(' ').trim();
return value || slug.replace(/-/g, ' ');
}
loadMore() {
@@ -93,12 +134,33 @@ export class ProviderThemePageComponent implements OnDestroy {
this.loading.set(true);
this.error.set(null);
const snapshotVersion = this.version;
const query = this.buildQuery();
const provider = this.provider();
const query = this.buildQuery(provider);
const cursor = this.nextCursor();
const themeSlug = this.theme();
const isLiveTheme = themeSlug === 'live';
const apiCall = query
? this.api.searchVideosPage(query, this.nextCursor(), provider)
: this.api.getTrendingPage(this.nextCursor(), provider);
let apiCall;
if (provider === 'twitch') {
if (isLiveTheme) {
apiCall = this.api.searchTwitchChannelsPage(query || 'live', cursor || undefined);
} else {
apiCall = this.api.searchTwitchVodsPage(query, cursor || undefined).pipe(
switchMap((res) => {
if ((res?.items?.length || 0) >= 8) {
return of(res);
}
return this.api.searchTwitchClipsPage(query, cursor || undefined).pipe(
map((clips) => ({ ...clips, items: [...(res?.items || []), ...(clips.items || [])] }))
);
})
);
}
} else {
apiCall = query
? this.api.searchVideosPage(query, cursor, provider)
: this.api.getTrendingPage(cursor, provider);
}
apiCall.subscribe({
next: (res) => {