Files
NewTube/src/app/shared/components/video-card/video-card.component.ts
T

90 lines
3.2 KiB
TypeScript

import { Component, Input } from '@angular/core';
import { VideoItem } from '../../models/video-item.model';
import { CommonModule } from '@angular/common';
import { RouterLink } from '@angular/router';
import { DurationPipe } from '../../pipes/duration.pipe';
import { ProviderBadgeComponent } from '../provider-badge/provider-badge.component';
import { SubscribeButtonComponent } from '../subscribe-button/subscribe-button.component';
import { ChannelIdentityComponent } from '../channel-identity/channel-identity.component';
import type { ChannelMeta, ProviderId } from '../../models/channel.model';
@Component({
selector: 'app-video-card',
templateUrl: './video-card.component.html',
styleUrls: ['./video-card.component.scss'],
standalone: true,
imports: [CommonModule, RouterLink, DurationPipe, ProviderBadgeComponent, SubscribeButtonComponent, ChannelIdentityComponent],
})
export class VideoCardComponent {
@Input() video!: VideoItem;
buildQueryParams(v: VideoItem): Record<string, any> {
const qp: any = { p: v.provider };
if (v.provider === 'odysee' && v.slug) qp.slug = v.slug;
// Twitch : chaînes/lives via ?channel=<login>, clips via ?clip=<slug>.
if (v.provider === 'twitch') {
const kind = String((v as any)?.type || '').toLowerCase();
const clipKind = String((v as any)?.kind || '').toLowerCase();
if (clipKind === 'clip') qp.clip = v.id;
else if ((kind === 'live' || kind === 'channel') && v.channel) qp.channel = v.channel;
}
return qp;
}
get isTwitchLive(): boolean {
const v: any = this.video;
return v?.provider === 'twitch' && (v?.isLive === true || String(v?.type || '').toLowerCase() === 'live');
}
get isTwitchChannel(): boolean {
const v: any = this.video;
return v?.provider === 'twitch' && String(v?.type || '').toLowerCase() === 'channel' && v?.isLive !== true;
}
get isTwitchClip(): boolean {
const v: any = this.video;
return v?.provider === 'twitch' && String(v?.kind || '').toLowerCase() === 'clip';
}
get showDuration(): boolean {
const d = Number((this.video as any)?.durationSec ?? NaN);
return Number.isFinite(d) && d > 0;
}
get providerId(): string {
return String((this.video as any)?.provider || '');
}
get channelProviderId(): ProviderId | null {
const map: Record<VideoItem['provider'], ProviderId> = {
youtube: 'yt',
dailymotion: 'dm',
twitch: 'tw',
peertube: 'pt',
odysee: 'od',
rumble: 'ru',
};
return map[this.video.provider] || null;
}
channelExternalId(): string | null {
return this.video.channelMeta?.externalId ?? this.video.channelExternalId ?? null;
}
channelAvatarUrl(): string | null {
return this.video.channelMeta?.avatarUrl ?? this.video.channelAvatarUrl ?? null;
}
channelDisplayName(channel?: ChannelMeta | null, fallback?: string | null): string {
const preferred = (channel?.title || channel?.handle || fallback || '').toString().trim();
if (preferred.length > 0) {
return preferred;
}
return (channel?.externalId || '').trim();
}
get showSubscribe(): boolean {
return Boolean(this.video.channelMeta && this.channelProviderId && this.channelExternalId());
}
}