chore: update Angular cache and TypeScript build info files
This commit is contained in:
@@ -58,6 +58,12 @@ export class WatchShortComponent {
|
||||
if (p === 'twitch' && v.videoId) {
|
||||
const parentsSet = new Set<string>([host, 'localhost', '127.0.0.1']);
|
||||
const parentParams = Array.from(parentsSet).map(h => `parent=${encodeURIComponent(h)}`).join('&');
|
||||
// If it's a clip, use the Clips embed endpoint
|
||||
if ((v as any).kind === 'clip') {
|
||||
const u = `https://clips.twitch.tv/embed?clip=${encodeURIComponent(v.videoId)}&${parentParams}&autoplay=true`;
|
||||
return this.sanitizer.bypassSecurityTrustResourceUrl(u);
|
||||
}
|
||||
// Otherwise treat it as a channel embed (live stream)
|
||||
const base = 'https://player.twitch.tv/';
|
||||
const qs = `?channel=${encodeURIComponent(v.videoId)}&${parentParams}&autoplay=false`;
|
||||
const u = base + qs;
|
||||
@@ -91,11 +97,14 @@ export class WatchShortComponent {
|
||||
|
||||
// Called when a query returns no usable items; falls back to Trending
|
||||
private afterNoResults(): void {
|
||||
// For Shorts page, do NOT fallback to trending; display an appropriate message instead.
|
||||
const p = this.provider();
|
||||
const hint = p === 'youtube'
|
||||
? 'Aucun Short trouvé. Assurez-vous de définir YOUTUBE_API_KEY dans assets/config.local.js (window.YOUTUBE_API_KEY = "...") ou changez de fournisseur.'
|
||||
: 'Aucun Short trouvé pour ce fournisseur.';
|
||||
this.loadFallbackTrending(hint);
|
||||
const unsupported = this.isProviderUnsupportedForShorts(p);
|
||||
if (unsupported) {
|
||||
this.error.set('Ce fournisseur ne supporte pas les shorts');
|
||||
} else {
|
||||
this.error.set('Aucun Short trouvé pour ce fournisseur.');
|
||||
}
|
||||
}
|
||||
|
||||
// Filter YouTube results to real Shorts using the Videos API to get durations.
|
||||
@@ -114,7 +123,7 @@ export class WatchShortComponent {
|
||||
}
|
||||
|
||||
constructor() {
|
||||
// Basic feed: search for "shorts"
|
||||
// Initialize feed for Shorts according to current provider
|
||||
this.loadFeed();
|
||||
}
|
||||
|
||||
@@ -127,6 +136,28 @@ export class WatchShortComponent {
|
||||
this.error.set(ready.reason || 'Provider not ready.');
|
||||
return;
|
||||
}
|
||||
const provider = this.provider();
|
||||
// Use provider-specific source for Shorts
|
||||
if (provider === 'twitch') {
|
||||
// Use Twitch Clips as Shorts
|
||||
this.api.searchTwitchClipsPage('')?.subscribe({
|
||||
next: (res: { items: Video[]; nextCursor?: string | null }) => {
|
||||
const raw: Video[] = (res.items || []).filter((v: Video) => !!v.videoId);
|
||||
const list: Video[] = raw.filter((v: Video) => this.isShort(v));
|
||||
this.items.set(list);
|
||||
this.index.set(0);
|
||||
this.nextCursor.set(res.nextCursor || null);
|
||||
if (list.length === 0) this.afterNoResults(); else this.error.set(null);
|
||||
this.loading.set(false);
|
||||
},
|
||||
error: () => {
|
||||
this.error.set('Failed to load Shorts.');
|
||||
this.loading.set(false);
|
||||
}
|
||||
});
|
||||
return;
|
||||
}
|
||||
// Default: search for shorts keywords via generic search
|
||||
this.api.searchVideosPage('shorts OR #shorts').subscribe({
|
||||
next: (res) => {
|
||||
const raw = (res.items || []).filter(v => !!v.videoId);
|
||||
@@ -134,7 +165,7 @@ export class WatchShortComponent {
|
||||
const p = this.provider();
|
||||
if (p === 'youtube' && raw.length) {
|
||||
this.filterYouTubeShorts(raw).then(list => {
|
||||
this.items.set(list);
|
||||
this.items.set(list.filter(v => this.isShort(v)));
|
||||
this.index.set(0);
|
||||
if (list.length === 0) this.afterNoResults();
|
||||
else this.error.set(null);
|
||||
@@ -142,21 +173,11 @@ export class WatchShortComponent {
|
||||
});
|
||||
return;
|
||||
}
|
||||
// Non-YouTube: take raw as-is
|
||||
const list = raw;
|
||||
// Non-YouTube: apply provider-specific minimal filtering
|
||||
const list = raw.filter(v => this.isShort(v));
|
||||
this.items.set(list);
|
||||
this.index.set(0);
|
||||
if (list.length === 0) {
|
||||
const p = this.provider();
|
||||
const hint = p === 'youtube'
|
||||
? 'Aucun Short trouvé. Assurez-vous de définir YOUTUBE_API_KEY dans assets/config.local.js (window.YOUTUBE_API_KEY = "...") ou changez de fournisseur.'
|
||||
: 'Aucun Short trouvé pour ce fournisseur.';
|
||||
// Essayez une retombée vers le fil des tendances
|
||||
this.loadFallbackTrending(hint);
|
||||
return;
|
||||
} else {
|
||||
this.error.set(null);
|
||||
}
|
||||
if (list.length === 0) this.afterNoResults(); else this.error.set(null);
|
||||
this.loading.set(false);
|
||||
},
|
||||
error: () => {
|
||||
@@ -166,46 +187,79 @@ export class WatchShortComponent {
|
||||
});
|
||||
}
|
||||
|
||||
private loadFallbackTrending(hint?: string): void {
|
||||
this.api.getTrendingPage().subscribe({
|
||||
next: (res) => {
|
||||
const list = (res.items || []).filter(v => !!v.videoId);
|
||||
this.items.set(list);
|
||||
this.index.set(0);
|
||||
this.nextCursor.set(res.nextCursor || null);
|
||||
if (list.length === 0) this.error.set(hint || 'Aucun contenu disponible.');
|
||||
else this.error.set(null);
|
||||
this.loading.set(false);
|
||||
},
|
||||
error: () => {
|
||||
this.error.set(hint || 'Impossible de charger du contenu.');
|
||||
this.loading.set(false);
|
||||
}
|
||||
});
|
||||
// Trending fallback removed for Shorts page to avoid showing non-short content
|
||||
private loadFallbackTrending(_hint?: string): void { this.error.set('Ce fournisseur ne supporte pas les shorts'); this.loading.set(false); }
|
||||
|
||||
// Generic Shorts check based on provider
|
||||
private isShort(v: Video): boolean {
|
||||
const p = (v as any).provider || this.provider();
|
||||
const url = (v as any).url || '';
|
||||
switch (p) {
|
||||
case 'youtube':
|
||||
return (v as any).isShort === true || (typeof url === 'string' && url.includes('/shorts/')) || ((v.duration ?? 0) > 0 && (v.duration ?? 0) <= 70);
|
||||
case 'dailymotion':
|
||||
return (v as any).isShort === true || (((v.duration ?? 0) <= 60) && ((v as any).isVertical === true));
|
||||
case 'twitch':
|
||||
return (v as any).kind === 'clip';
|
||||
case 'rumble':
|
||||
return (v as any).isShort === true;
|
||||
case 'odysee':
|
||||
return (v as any).isShort === true;
|
||||
case 'peertube':
|
||||
return (v as any).isShort === true || (((v.duration ?? 0) <= 60) && ((v as any).isVertical === true));
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private isProviderUnsupportedForShorts(p: string | undefined | null): boolean {
|
||||
switch (p) {
|
||||
case 'rumble':
|
||||
case 'odysee':
|
||||
return true; // Only if provider exposes isShort; otherwise unsupported
|
||||
case 'twitch':
|
||||
case 'youtube':
|
||||
return false;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private fetchNextPage(autoAdvance = false) {
|
||||
if (this.busyMore() || !this.nextCursor()) return;
|
||||
this.busyMore.set(true);
|
||||
const cursor = this.nextCursor();
|
||||
const provider = this.provider();
|
||||
const handle = (res: any) => {
|
||||
const raw: Video[] = (res.items || []).filter((v: Video) => !!v.videoId);
|
||||
const p = this.provider();
|
||||
const apply = (more: Video[]) => {
|
||||
const merged = this.items().concat(more);
|
||||
this.items.set(merged);
|
||||
this.nextCursor.set(res.nextCursor || null);
|
||||
if (autoAdvance && more.length > 0) {
|
||||
this.index.update(i => Math.min(i + 1, merged.length - 1));
|
||||
}
|
||||
this.busyMore.set(false);
|
||||
};
|
||||
if (p === 'youtube' && raw.length) {
|
||||
this.filterYouTubeShorts(raw).then((list: Video[]) => apply(list.filter((v: Video) => this.isShort(v)))).catch(() => { apply([]); });
|
||||
} else {
|
||||
apply(raw.filter((v: Video) => this.isShort(v)));
|
||||
}
|
||||
};
|
||||
|
||||
if (provider === 'twitch') {
|
||||
this.api.searchTwitchClipsPage('', cursor || undefined)?.subscribe({
|
||||
next: handle,
|
||||
error: () => { this.busyMore.set(false); }
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
this.api.searchVideosPage('shorts OR #shorts', cursor || undefined).subscribe({
|
||||
next: (res) => {
|
||||
const raw = (res.items || []).filter(v => !!v.videoId);
|
||||
const p = this.provider();
|
||||
const apply = (more: Video[]) => {
|
||||
const merged = this.items().concat(more);
|
||||
this.items.set(merged);
|
||||
this.nextCursor.set(res.nextCursor || null);
|
||||
if (autoAdvance && more.length > 0) {
|
||||
this.index.update(i => Math.min(i + 1, merged.length - 1));
|
||||
}
|
||||
this.busyMore.set(false);
|
||||
};
|
||||
if (p === 'youtube' && raw.length) {
|
||||
this.filterYouTubeShorts(raw).then(apply).catch(() => { apply([]); });
|
||||
} else {
|
||||
apply(raw);
|
||||
}
|
||||
handle(res);
|
||||
},
|
||||
error: () => {
|
||||
this.busyMore.set(false);
|
||||
|
||||
Reference in New Issue
Block a user