mirror of
https://github.com/ksyasuda/SubMiner.git
synced 2026-09-19 05:16:27 -07:00
feat(stats): add TMDB metadata for live-action dramas in the Library
Anime covers come from AniList, which has no live-action titles, so dramas and movies showed blank cards with no description and split across season folders. Library entries now carry a media kind plus a TMDB link, and the cover-art fetcher falls back to TMDB when AniList has no match, accepting only a Japanese non-animated title whose TMDB names match the parsed title exactly. Entries that resolve to the same TMDB title merge into one card regardless of season, and a Link to TMDB action in the detail view covers anything the automatic match missed. Release builds bundle a project-owned TMDB key injected from the SUBMINER_TMDB_API_KEY secret at build time; tmdb.apiKey/apiKeyCommand override it and are required when running from source. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
@@ -6,6 +6,7 @@ interface AnimeHeaderProps {
|
||||
anilistEntries: AnilistEntry[];
|
||||
coverRetryToken?: number;
|
||||
onChangeAnilist?: () => void;
|
||||
onChangeTmdb?: () => void;
|
||||
onDeleteAnime?: () => void;
|
||||
isDeletingAnime?: boolean;
|
||||
}
|
||||
@@ -34,6 +35,7 @@ export function AnimeHeader({
|
||||
anilistEntries,
|
||||
coverRetryToken = 0,
|
||||
onChangeAnilist,
|
||||
onChangeTmdb,
|
||||
onDeleteAnime,
|
||||
isDeletingAnime = false,
|
||||
}: AnimeHeaderProps) {
|
||||
@@ -43,7 +45,12 @@ export function AnimeHeader({
|
||||
const uniqueAltTitles = [...new Set(altTitles)];
|
||||
|
||||
const hasMultipleEntries = anilistEntries.length > 1;
|
||||
const coverCacheToken = (detail.anilistId ?? 0) * 1_000_000 + coverRetryToken;
|
||||
const isLiveAction = detail.mediaKind === 'live_action';
|
||||
const tmdbUrl =
|
||||
detail.tmdbId && detail.tmdbType
|
||||
? `https://www.themoviedb.org/${detail.tmdbType}/${detail.tmdbId}`
|
||||
: null;
|
||||
const coverCacheToken = (detail.anilistId ?? detail.tmdbId ?? 0) * 1_000_000 + coverRetryToken;
|
||||
|
||||
return (
|
||||
<div className="flex gap-4">
|
||||
@@ -60,11 +67,28 @@ export function AnimeHeader({
|
||||
{uniqueAltTitles.join(' · ')}
|
||||
</div>
|
||||
)}
|
||||
<div className="text-sm text-ctp-subtext0 mt-2">
|
||||
{detail.episodeCount} episode{detail.episodeCount !== 1 ? 's' : ''}
|
||||
<div className="text-sm text-ctp-subtext0 mt-2 flex items-center gap-2">
|
||||
<span>
|
||||
{detail.episodeCount} episode{detail.episodeCount !== 1 ? 's' : ''}
|
||||
</span>
|
||||
{isLiveAction && (
|
||||
<span className="px-1.5 py-0.5 rounded text-[10px] uppercase tracking-wide bg-ctp-peach/15 text-ctp-peach">
|
||||
{detail.tmdbType === 'movie' ? 'Movie' : 'Live action'}
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
<div className="flex flex-wrap gap-1.5 mt-2">
|
||||
{anilistEntries.length > 0 ? (
|
||||
{tmdbUrl && (
|
||||
<a
|
||||
href={tmdbUrl}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className="inline-flex items-center gap-1 px-2 py-1 text-xs rounded bg-ctp-surface1 text-ctp-blue hover:bg-ctp-surface2 hover:text-ctp-sapphire transition-colors"
|
||||
>
|
||||
View on TMDB <span className="text-[10px]">{'\u2197'}</span>
|
||||
</a>
|
||||
)}
|
||||
{isLiveAction ? null : anilistEntries.length > 0 ? (
|
||||
hasMultipleEntries ? (
|
||||
anilistEntries.map((entry) => <AnilistButton key={entry.anilistId} entry={entry} />)
|
||||
) : (
|
||||
@@ -99,6 +123,16 @@ export function AnimeHeader({
|
||||
: 'Link to AniList'}
|
||||
</button>
|
||||
)}
|
||||
{onChangeTmdb && (
|
||||
<button
|
||||
type="button"
|
||||
onClick={onChangeTmdb}
|
||||
title="Search TMDB and link this title to a live-action drama or movie"
|
||||
className="inline-flex items-center gap-1 px-2 py-1 text-xs rounded bg-ctp-surface1 text-ctp-overlay2 hover:bg-ctp-surface2 hover:text-ctp-subtext0 transition-colors"
|
||||
>
|
||||
{tmdbUrl ? 'Change TMDB Title' : 'Link to TMDB'}
|
||||
</button>
|
||||
)}
|
||||
{onDeleteAnime && (
|
||||
<button
|
||||
type="button"
|
||||
|
||||
Reference in New Issue
Block a user