chore: update Angular cache and TypeScript build info
This commit is contained in:
@@ -182,79 +182,21 @@ export class SearchComponent implements AfterViewInit {
|
||||
|
||||
// Helper computed: filtered list based on active tag
|
||||
filteredResults = computed(() => {
|
||||
const tag = this.filterTag();
|
||||
const list = this.allVideos();
|
||||
const provider = this.selectedProviderForView();
|
||||
if (!Array.isArray(list) || list.length === 0) return [];
|
||||
|
||||
if (provider === 'twitch') return list; // Not used for Twitch (separate sections)
|
||||
if (tag === 'all') return list;
|
||||
|
||||
const now = Date.now();
|
||||
const oneDay = 24 * 60 * 60 * 1000;
|
||||
const sevenDays = 7 * oneDay;
|
||||
const thirtyDays = 30 * oneDay;
|
||||
const oneYear = 365 * oneDay;
|
||||
|
||||
// Duration filters
|
||||
if (tag === 'short') return list.filter(v => {
|
||||
const d = Number(v.durationSec || 0);
|
||||
return d > 0 && d < 4 * 60;
|
||||
});
|
||||
if (tag === 'medium') return list.filter(v => {
|
||||
const d = Number(v.durationSec || 0);
|
||||
return d >= 4 * 60 && d < 20 * 60;
|
||||
});
|
||||
if (tag === 'long') return list.filter(v => {
|
||||
const d = Number(v.durationSec || 0);
|
||||
return d >= 20 * 60;
|
||||
});
|
||||
|
||||
// Date filters
|
||||
if (tag === 'today') return list.filter(v => {
|
||||
const uploadTime = v.publishedAt ? new Date(v.publishedAt).getTime() : 0;
|
||||
return uploadTime > 0 && (now - uploadTime) <= oneDay;
|
||||
});
|
||||
if (tag === 'this_week') return list.filter(v => {
|
||||
const uploadTime = v.publishedAt ? new Date(v.publishedAt).getTime() : 0;
|
||||
return uploadTime > 0 && (now - uploadTime) <= sevenDays;
|
||||
});
|
||||
if (tag === 'this_month') return list.filter(v => {
|
||||
const uploadTime = v.publishedAt ? new Date(v.publishedAt).getTime() : 0;
|
||||
return uploadTime > 0 && (now - uploadTime) <= thirtyDays;
|
||||
});
|
||||
if (tag === 'this_year') return list.filter(v => {
|
||||
const uploadTime = v.publishedAt ? new Date(v.publishedAt).getTime() : 0;
|
||||
return uploadTime > 0 && (now - uploadTime) <= oneYear;
|
||||
});
|
||||
|
||||
return list;
|
||||
const filtered = this.applyTagFilter(list);
|
||||
return this.sortVideos(filtered);
|
||||
});
|
||||
|
||||
// Filter each provider group separately for sectioned rendering
|
||||
filteredGroups = computed(() => {
|
||||
const tag = this.filterTag();
|
||||
const predicate = this.buildTagPredicate();
|
||||
const g = this.groups();
|
||||
const result: Record<string, any[]> = {};
|
||||
const now = Date.now();
|
||||
const oneDay = 24 * 60 * 60 * 1000;
|
||||
const sevenDays = 7 * oneDay;
|
||||
const thirtyDays = 30 * oneDay;
|
||||
const oneYear = 365 * oneDay;
|
||||
|
||||
const applyFilter = (list: any[]): any[] => {
|
||||
if (tag === 'all' || this.selectedProviderForView() === 'twitch') return list;
|
||||
if (tag === 'short') return list.filter(v => { const d = Number(v.durationSec || 0); return d > 0 && d < 4 * 60; });
|
||||
if (tag === 'medium') return list.filter(v => { const d = Number(v.durationSec || 0); return d >= 4 * 60 && d < 20 * 60; });
|
||||
if (tag === 'long') return list.filter(v => { const d = Number(v.durationSec || 0); return d >= 20 * 60; });
|
||||
if (tag === 'today') return list.filter(v => { const t = v.publishedAt ? new Date(v.publishedAt).getTime() : 0; return t > 0 && (now - t) <= oneDay; });
|
||||
if (tag === 'this_week') return list.filter(v => { const t = v.publishedAt ? new Date(v.publishedAt).getTime() : 0; return t > 0 && (now - t) <= sevenDays; });
|
||||
if (tag === 'this_month') return list.filter(v => { const t = v.publishedAt ? new Date(v.publishedAt).getTime() : 0; return t > 0 && (now - t) <= thirtyDays; });
|
||||
if (tag === 'this_year') return list.filter(v => { const t = v.publishedAt ? new Date(v.publishedAt).getTime() : 0; return t > 0 && (now - t) <= oneYear; });
|
||||
return list;
|
||||
};
|
||||
|
||||
Object.entries(g || {}).forEach(([pid, list]) => {
|
||||
result[pid] = Array.isArray(list) ? applyFilter(list) : [];
|
||||
result[pid] = Array.isArray(list) ? list.filter(predicate) : [];
|
||||
});
|
||||
return result;
|
||||
});
|
||||
@@ -431,6 +373,115 @@ export class SearchComponent implements AfterViewInit {
|
||||
|
||||
}
|
||||
|
||||
private durationSeconds(item: any): number {
|
||||
const raw = item?.durationSec ?? item?.duration ?? item?.length ?? 0;
|
||||
if (typeof raw === 'number') {
|
||||
return Number.isFinite(raw) ? raw : 0;
|
||||
}
|
||||
const parsed = Number(raw);
|
||||
return Number.isFinite(parsed) ? parsed : 0;
|
||||
}
|
||||
|
||||
private publishedTimestamp(item: any): number {
|
||||
const raw = item?.publishedAt ?? item?.uploadedDate ?? item?.uploadDate ?? item?.published_at ?? item?.uploaded ?? null;
|
||||
if (typeof raw === 'number') {
|
||||
return Number.isFinite(raw) ? raw : 0;
|
||||
}
|
||||
if (typeof raw === 'string' && raw.trim()) {
|
||||
const parsed = Date.parse(raw);
|
||||
if (!Number.isNaN(parsed)) {
|
||||
return parsed;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
private viewCount(item: any): number {
|
||||
const raw = item?.viewCount ?? item?.views ?? item?.stats?.views ?? item?.metrics?.views ?? 0;
|
||||
if (typeof raw === 'number') {
|
||||
return Number.isFinite(raw) ? raw : 0;
|
||||
}
|
||||
const parsed = Number(raw);
|
||||
return Number.isFinite(parsed) ? parsed : 0;
|
||||
}
|
||||
|
||||
private buildTagPredicate(): (item: any) => boolean {
|
||||
const tag = this.filterTag();
|
||||
const provider = this.selectedProviderForView();
|
||||
if (provider === 'twitch' || tag === 'all' || tag?.startsWith('twitch')) {
|
||||
return () => true;
|
||||
}
|
||||
|
||||
const now = Date.now();
|
||||
const oneDay = 24 * 60 * 60 * 1000;
|
||||
const sevenDays = 7 * oneDay;
|
||||
const thirtyDays = 30 * oneDay;
|
||||
const oneYear = 365 * oneDay;
|
||||
|
||||
switch (tag) {
|
||||
case 'short':
|
||||
return (item) => {
|
||||
const d = this.durationSeconds(item);
|
||||
return d > 0 && d < 4 * 60;
|
||||
};
|
||||
case 'medium':
|
||||
return (item) => {
|
||||
const d = this.durationSeconds(item);
|
||||
return d >= 4 * 60 && d < 20 * 60;
|
||||
};
|
||||
case 'long':
|
||||
return (item) => {
|
||||
const d = this.durationSeconds(item);
|
||||
return d >= 20 * 60;
|
||||
};
|
||||
case 'today':
|
||||
return (item) => {
|
||||
const ts = this.publishedTimestamp(item);
|
||||
return ts > 0 && (now - ts) <= oneDay;
|
||||
};
|
||||
case 'this_week':
|
||||
return (item) => {
|
||||
const ts = this.publishedTimestamp(item);
|
||||
return ts > 0 && (now - ts) <= sevenDays;
|
||||
};
|
||||
case 'this_month':
|
||||
return (item) => {
|
||||
const ts = this.publishedTimestamp(item);
|
||||
return ts > 0 && (now - ts) <= thirtyDays;
|
||||
};
|
||||
case 'this_year':
|
||||
return (item) => {
|
||||
const ts = this.publishedTimestamp(item);
|
||||
return ts > 0 && (now - ts) <= oneYear;
|
||||
};
|
||||
default:
|
||||
return () => true;
|
||||
}
|
||||
}
|
||||
|
||||
private applyTagFilter(list: any[]): any[] {
|
||||
const predicate = this.buildTagPredicate();
|
||||
return Array.isArray(list) ? list.filter(predicate) : [];
|
||||
}
|
||||
|
||||
private sortVideos(list: any[]): any[] {
|
||||
if (!Array.isArray(list)) {
|
||||
return [];
|
||||
}
|
||||
const mode = this.sortParam();
|
||||
if (mode === 'relevance') {
|
||||
return [...list];
|
||||
}
|
||||
|
||||
const arr = [...list];
|
||||
if (mode === 'date') {
|
||||
arr.sort((a, b) => this.publishedTimestamp(b) - this.publishedTimestamp(a));
|
||||
} else if (mode === 'views') {
|
||||
arr.sort((a, b) => this.viewCount(b) - this.viewCount(a));
|
||||
}
|
||||
return arr;
|
||||
}
|
||||
|
||||
|
||||
formatViews(views: number): string {
|
||||
if (views >= 1_000_000_000) return (views / 1_000_000_000).toFixed(1) + 'B';
|
||||
|
||||
Reference in New Issue
Block a user