mirror of
https://github.com/truewhile/MeBox.git
synced 2026-09-30 11:46:36 +08:00
fix: show latest discover posters
This commit is contained in:
@@ -65,34 +65,53 @@ function DiscoverCard({
|
||||
onSelect: (item: DiscoverItem) => void
|
||||
}) {
|
||||
const source = discoverItemSource(item)
|
||||
const imageCandidates = useMemo(
|
||||
() =>
|
||||
[item.poster_url, item.backdrop_url]
|
||||
.map((value) => value?.trim())
|
||||
.filter((value, index, values): value is string => Boolean(value) && values.indexOf(value) === index),
|
||||
[item.poster_url, item.backdrop_url],
|
||||
)
|
||||
const [imageIndex, setImageIndex] = useState(0)
|
||||
const [posterRetry, setPosterRetry] = useState(0)
|
||||
const [posterUnavailable, setPosterUnavailable] = useState(false)
|
||||
const posterVersion = [imageVersion, posterRetry > 0 ? `r${posterRetry}` : ''].filter(Boolean).join('-')
|
||||
const activeImage = imageCandidates[imageIndex] ?? ''
|
||||
const shouldRefreshCache = Boolean(
|
||||
(imageVersion && refreshImageVersion === imageVersion) || posterRetry > 0,
|
||||
)
|
||||
const posterSrc = useMemo(
|
||||
() =>
|
||||
imageURL(item.poster_url, posterVersion, {
|
||||
imageURL(activeImage, posterVersion, {
|
||||
refreshCache: shouldRefreshCache,
|
||||
retryFailed: true,
|
||||
}),
|
||||
[item.poster_url, posterVersion, shouldRefreshCache],
|
||||
[activeImage, posterVersion, shouldRefreshCache],
|
||||
)
|
||||
|
||||
useEffect(() => {
|
||||
setImageIndex(0)
|
||||
setPosterRetry(0)
|
||||
setPosterUnavailable(false)
|
||||
}, [item.poster_url])
|
||||
}, [item.poster_url, item.backdrop_url, imageVersion])
|
||||
|
||||
useEffect(() => {
|
||||
if (!posterUnavailable || posterRetry >= 3) return
|
||||
if (!posterUnavailable) return
|
||||
if (imageIndex + 1 < imageCandidates.length) {
|
||||
const timer = window.setTimeout(() => {
|
||||
setImageIndex((current) => Math.min(current + 1, imageCandidates.length - 1))
|
||||
setPosterRetry(0)
|
||||
setPosterUnavailable(false)
|
||||
}, 150)
|
||||
return () => window.clearTimeout(timer)
|
||||
}
|
||||
if (posterRetry >= 3) return
|
||||
const timer = window.setTimeout(() => {
|
||||
setPosterRetry((current) => current + 1)
|
||||
setPosterUnavailable(false)
|
||||
}, 1200 * (posterRetry + 1))
|
||||
return () => window.clearTimeout(timer)
|
||||
}, [posterRetry, posterUnavailable])
|
||||
}, [imageCandidates.length, imageIndex, posterRetry, posterUnavailable])
|
||||
|
||||
const markPosterUnavailable = () => setPosterUnavailable(true)
|
||||
|
||||
|
||||
@@ -8,6 +8,7 @@ import {
|
||||
defaultSections,
|
||||
discoverStorageKey,
|
||||
readSavedSections,
|
||||
serializeSavedSections,
|
||||
} from './discoverPageModel'
|
||||
|
||||
export function DiscoverPage() {
|
||||
@@ -74,7 +75,7 @@ export function DiscoverPage() {
|
||||
}
|
||||
return next
|
||||
})
|
||||
window.localStorage.setItem(discoverStorageKey, JSON.stringify(selected))
|
||||
window.localStorage.setItem(discoverStorageKey, serializeSavedSections(selected))
|
||||
|
||||
let pending = selected.length
|
||||
const markDone = () => {
|
||||
|
||||
@@ -2,15 +2,21 @@ import type { DiscoverItem, DiscoverSection } from '../api/discover'
|
||||
|
||||
export const defaultSections = [
|
||||
'tmdb_trending_day',
|
||||
'tmdb_latest_movie',
|
||||
'tmdb_latest_tv',
|
||||
'douban_hot_movie',
|
||||
'douban_hot_tv',
|
||||
'bangumi_calendar',
|
||||
]
|
||||
|
||||
export const discoverStorageKey = 'mediastation.discover.sections'
|
||||
const discoverStorageVersion = 2
|
||||
const legacyDefaultAdditions = ['tmdb_latest_movie', 'tmdb_latest_tv']
|
||||
|
||||
export const defaultSectionDefs: DiscoverSection[] = [
|
||||
{ key: 'tmdb_trending_day', label: 'TMDb 今日趋势', provider: 'tmdb' },
|
||||
{ key: 'tmdb_latest_movie', label: 'TMDb 最新电影', provider: 'tmdb' },
|
||||
{ key: 'tmdb_latest_tv', label: 'TMDb 最新剧集', provider: 'tmdb' },
|
||||
{ key: 'tmdb_popular_movie', label: 'TMDb 热门电影', provider: 'tmdb' },
|
||||
{ key: 'douban_hot_movie', label: '豆瓣热门电影', provider: 'douban' },
|
||||
{ key: 'douban_hot_tv', label: '豆瓣热门剧集', provider: 'douban' },
|
||||
@@ -26,14 +32,44 @@ export function readSavedSections(sections: DiscoverSection[]): string[] {
|
||||
const raw = window.localStorage.getItem(discoverStorageKey)
|
||||
if (!raw) return []
|
||||
const parsed = JSON.parse(raw)
|
||||
if (!Array.isArray(parsed)) return []
|
||||
const allowed = new Set(sections.map((section) => section.key))
|
||||
return parsed.filter((key) => typeof key === 'string' && allowed.has(key))
|
||||
if (Array.isArray(parsed)) {
|
||||
return orderSectionKeys(addLegacyDefaults(parsed, allowed), sections)
|
||||
}
|
||||
if (!parsed || !Array.isArray(parsed.selected)) return []
|
||||
const selected = sanitizeSectionKeys(parsed.selected, allowed)
|
||||
if (parsed.version === discoverStorageVersion) {
|
||||
return orderSectionKeys(selected, sections)
|
||||
}
|
||||
return orderSectionKeys(addLegacyDefaults(selected, allowed), sections)
|
||||
} catch {
|
||||
return []
|
||||
}
|
||||
}
|
||||
|
||||
export function serializeSavedSections(selected: string[]): string {
|
||||
return JSON.stringify({ version: discoverStorageVersion, selected })
|
||||
}
|
||||
|
||||
function sanitizeSectionKeys(keys: unknown[], allowed: Set<string>): string[] {
|
||||
return keys.filter((key): key is string => typeof key === 'string' && allowed.has(key))
|
||||
}
|
||||
|
||||
function addLegacyDefaults(keys: unknown[], allowed: Set<string>): string[] {
|
||||
const out = sanitizeSectionKeys(keys, allowed)
|
||||
for (const key of legacyDefaultAdditions) {
|
||||
if (allowed.has(key) && !out.includes(key)) {
|
||||
out.push(key)
|
||||
}
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
function orderSectionKeys(keys: string[], sections: DiscoverSection[]): string[] {
|
||||
const selected = new Set(keys)
|
||||
return sections.map((section) => section.key).filter((key) => selected.has(key))
|
||||
}
|
||||
|
||||
export function buildSubscribeKeyword(item: DiscoverItem): string {
|
||||
return [item.title, item.year && item.year > 0 ? item.year : ''].filter(Boolean).join(' ')
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user