feat(channel): page details chaine multi-providers avec onglets et infinite scroll
CI / build-and-test (push) Successful in 13m34s
CI / build-and-test (push) Successful in 13m34s
- Strategy Pattern front: ChannelProviderInterface + 6 providers (yt/dm/tw/pt/od/ru) + factory (ids longs/courts) - ChannelContentService: cache par onglet/tri/recherche (TTL 5min), pagination nextPage - ChannelPage: header (banniere/avatar/subs/description ...plus), tabs dynamiques par capabilities, grilles videos/shorts 9:16/playlists/live, recherche debounced, tri recent/populaire, infinite scroll IntersectionObserver, skeletons/empty/error - Backend: GET /api/channels/:provider/:id/content (videos/shorts/playlists/live) natif par provider
This commit is contained in:
@@ -1,9 +1,19 @@
|
||||
import { Component, Input } from '@angular/core';
|
||||
import { Component, Input, computed } from '@angular/core';
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { RouterLink } from '@angular/router';
|
||||
import type { ProviderId } from '../../app/core/providers/provider-registry';
|
||||
import { PROVIDERS, PROVIDER_MAP, type ProviderId } from '../../app/core/providers/provider-registry';
|
||||
import type { SuggestionItem } from '../../app/search/search.service';
|
||||
|
||||
interface SuggestionSection {
|
||||
id: ProviderId;
|
||||
name: string;
|
||||
shortLabel: string;
|
||||
colorClass: string;
|
||||
items: SuggestionItem[];
|
||||
supported: boolean;
|
||||
deepLinkProviders: string;
|
||||
}
|
||||
|
||||
@Component({
|
||||
selector: 'app-search-suggestions',
|
||||
standalone: true,
|
||||
@@ -15,4 +25,26 @@ export class SearchSuggestionsComponent {
|
||||
yt: [], dm: [], tw: [], pt: [], od: [], ru: []
|
||||
} as any;
|
||||
@Input() query: string = '';
|
||||
// Providers that were actually requested; drives which sections render and
|
||||
// which unsupported providers get an explicit row (Step 6)
|
||||
@Input() activeProviders: ProviderId[] | 'all' = 'all';
|
||||
|
||||
readonly sections = computed<SuggestionSection[]>(() => {
|
||||
const groups = this.groups || ({} as Record<ProviderId, SuggestionItem[]>);
|
||||
const active = this.activeProviders === 'all'
|
||||
? PROVIDERS.map(p => p.id)
|
||||
: (this.activeProviders || []).filter(id => PROVIDER_MAP.has(id));
|
||||
return active.map(id => {
|
||||
const spec = PROVIDER_MAP.get(id)!;
|
||||
return {
|
||||
id,
|
||||
name: spec.displayName,
|
||||
shortLabel: spec.shortLabel,
|
||||
colorClass: spec.colorClass,
|
||||
items: Array.isArray(groups[id]) ? groups[id] : [],
|
||||
supported: !!spec.supports?.search,
|
||||
deepLinkProviders: id,
|
||||
} as SuggestionSection;
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user