mirror of
https://github.com/ksyasuda/SubMiner.git
synced 2026-03-23 00:11:28 -07:00
fix(ci): add changelog fragment for immersion changes
This commit is contained in:
74
stats/src/lib/media-library-grouping.ts
Normal file
74
stats/src/lib/media-library-grouping.ts
Normal file
@@ -0,0 +1,74 @@
|
||||
import { BASE_URL } from './api-client';
|
||||
import type { MediaLibraryItem } from '../types/stats';
|
||||
|
||||
export interface MediaLibraryGroup {
|
||||
key: string;
|
||||
title: string;
|
||||
subtitle: string | null;
|
||||
imageUrl: string | null;
|
||||
channelUrl: string | null;
|
||||
items: MediaLibraryItem[];
|
||||
totalActiveMs: number;
|
||||
totalCards: number;
|
||||
lastWatchedMs: number;
|
||||
}
|
||||
|
||||
export function resolveMediaArtworkUrl(
|
||||
item: Pick<MediaLibraryItem, 'videoThumbnailUrl' | 'channelThumbnailUrl'>,
|
||||
kind: 'video' | 'channel',
|
||||
): string | null {
|
||||
if (kind === 'channel') {
|
||||
return item.channelThumbnailUrl ?? null;
|
||||
}
|
||||
return item.videoThumbnailUrl ?? null;
|
||||
}
|
||||
|
||||
export function resolveMediaCoverApiUrl(videoId: number): string {
|
||||
return `${BASE_URL}/api/stats/media/${videoId}/cover`;
|
||||
}
|
||||
|
||||
export function groupMediaLibraryItems(items: MediaLibraryItem[]): MediaLibraryGroup[] {
|
||||
const groups = new Map<string, MediaLibraryGroup>();
|
||||
|
||||
for (const item of items) {
|
||||
const key = item.channelId?.trim() || `video:${item.videoId}`;
|
||||
const title =
|
||||
item.channelName?.trim() ||
|
||||
item.uploaderId?.trim() ||
|
||||
item.videoTitle?.trim() ||
|
||||
item.canonicalTitle;
|
||||
const subtitle =
|
||||
item.channelId?.trim() != null && item.channelId?.trim() !== ''
|
||||
? `${item.channelId}`
|
||||
: item.videoTitle?.trim() && item.videoTitle !== item.canonicalTitle
|
||||
? item.videoTitle
|
||||
: null;
|
||||
const existing = groups.get(key);
|
||||
if (existing) {
|
||||
existing.items.push(item);
|
||||
existing.totalActiveMs += item.totalActiveMs;
|
||||
existing.totalCards += item.totalCards;
|
||||
existing.lastWatchedMs = Math.max(existing.lastWatchedMs, item.lastWatchedMs);
|
||||
continue;
|
||||
}
|
||||
|
||||
groups.set(key, {
|
||||
key,
|
||||
title,
|
||||
subtitle,
|
||||
imageUrl: resolveMediaArtworkUrl(item, 'channel') ?? resolveMediaArtworkUrl(item, 'video'),
|
||||
channelUrl: item.channelUrl ?? null,
|
||||
items: [item],
|
||||
totalActiveMs: item.totalActiveMs,
|
||||
totalCards: item.totalCards,
|
||||
lastWatchedMs: item.lastWatchedMs,
|
||||
});
|
||||
}
|
||||
|
||||
return [...groups.values()]
|
||||
.map((group) => ({
|
||||
...group,
|
||||
items: [...group.items].sort((a, b) => b.lastWatchedMs - a.lastWatchedMs),
|
||||
}))
|
||||
.sort((a, b) => b.lastWatchedMs - a.lastWatchedMs);
|
||||
}
|
||||
Reference in New Issue
Block a user