mirror of
https://github.com/truewhile/MeBox.git
synced 2026-09-30 11:46:36 +08:00
优化
This commit is contained in:
@@ -61,6 +61,9 @@ export const playbackAPI = {
|
||||
listFavourites: () =>
|
||||
api.get<{ items: Media[] }>('/favourites').then((r) => r.data.items),
|
||||
|
||||
listFavouriteIDs: () =>
|
||||
api.get<{ ids: string[] }>('/favourites', { params: { ids: 1 } }).then((r) => r.data.ids ?? []),
|
||||
|
||||
listPlaylists: () =>
|
||||
api.get<{ items: Playlist[] }>('/playlists').then((r) => r.data.items),
|
||||
|
||||
|
||||
@@ -10,10 +10,10 @@ export function useFavourites() {
|
||||
useEffect(() => {
|
||||
let cancelled = false
|
||||
playbackAPI
|
||||
.listFavourites()
|
||||
.listFavouriteIDs()
|
||||
.then((items) => {
|
||||
if (!cancelled) {
|
||||
setFavouriteIDs(new Set((items ?? []).map((item) => item.id)))
|
||||
setFavouriteIDs(new Set(items ?? []))
|
||||
}
|
||||
})
|
||||
.catch(() => {
|
||||
|
||||
@@ -8,6 +8,7 @@ import type { SeriesCard } from '../utils/groupSeries'
|
||||
import { fetchLibraries, peekLibraries } from '../utils/libraryCache'
|
||||
import { usePinnedLibraries } from '../hooks/usePinnedLibraries'
|
||||
import { sortByPinnedIds } from '../utils/pinnedLibraries'
|
||||
import { partitionPreviewIDs } from '../utils/remoteEmby'
|
||||
import {
|
||||
ContinueWatchingSection,
|
||||
ContinueWatchingSkeleton,
|
||||
@@ -18,7 +19,6 @@ import {
|
||||
HomeLoadingState,
|
||||
} from './HomePageSections'
|
||||
|
||||
const PREVIEW_BATCH_SIZE = 4
|
||||
const hasArtwork = (media?: Media | null) => !!(media?.poster_url || media?.backdrop_url)
|
||||
|
||||
export function HomePage() {
|
||||
@@ -102,12 +102,10 @@ export function HomePage() {
|
||||
if (targets.length === 0) return
|
||||
targets.forEach((id) => fetchingPreviewLimitsRef.current.set(id, limit))
|
||||
|
||||
const batches: string[][] = []
|
||||
for (let i = 0; i < targets.length; i += PREVIEW_BATCH_SIZE) {
|
||||
batches.push(targets.slice(i, i + PREVIEW_BATCH_SIZE))
|
||||
}
|
||||
// 本地库一次拉完(同一条窗口查询、缓存键稳定)。远程库单独一批,
|
||||
// 避免一个慢的 Emby 挂载拖住整页预览。
|
||||
const batches = partitionPreviewIDs(targets)
|
||||
|
||||
// 分批并发:一个慢库不再阻塞整页预览,先返回的批次立即渲染。
|
||||
await Promise.allSettled(
|
||||
batches.map(async (batch) => {
|
||||
let loaded = false
|
||||
|
||||
@@ -15,6 +15,7 @@ import type { Library } from '../types'
|
||||
import type { SeriesCard } from '../utils/groupSeries'
|
||||
import { fetchLibraries, invalidateLibraries, peekLibraries } from '../utils/libraryCache'
|
||||
import { sortLibraryPreviews } from '../utils/pinnedLibraries'
|
||||
import { partitionPreviewIDs } from '../utils/remoteEmby'
|
||||
|
||||
export function LibrariesPage() {
|
||||
const [libraries, setLibraries] = useState<Library[]>([])
|
||||
@@ -33,30 +34,33 @@ export function LibrariesPage() {
|
||||
if (targets.length === 0) return
|
||||
targets.forEach((id) => fetchingRef.current.add(id))
|
||||
|
||||
let loaded = false
|
||||
try {
|
||||
const rows = await libraryAPI.listPreviews(targets, 10)
|
||||
loaded = true
|
||||
setLibraryData((prev) => {
|
||||
const next = { ...prev }
|
||||
for (const row of rows) {
|
||||
next[row.id] = {
|
||||
cards: row.cards ?? [],
|
||||
total: row.total ?? 0,
|
||||
}
|
||||
const batches = partitionPreviewIDs(targets)
|
||||
await Promise.allSettled(
|
||||
batches.map(async (batch) => {
|
||||
let loaded = false
|
||||
try {
|
||||
const rows = await libraryAPI.listPreviews(batch, 10)
|
||||
loaded = true
|
||||
setLibraryData((prev) => {
|
||||
const next = { ...prev }
|
||||
for (const row of rows) {
|
||||
next[row.id] = {
|
||||
cards: row.cards ?? [],
|
||||
total: row.total ?? 0,
|
||||
}
|
||||
}
|
||||
return next
|
||||
})
|
||||
} catch {
|
||||
// 单个批次失败不影响其他批次。
|
||||
} finally {
|
||||
batch.forEach((id) => {
|
||||
if (loaded) fetchedLibIdsRef.current.add(id)
|
||||
fetchingRef.current.delete(id)
|
||||
})
|
||||
}
|
||||
return next
|
||||
})
|
||||
} catch {
|
||||
// 容错
|
||||
} finally {
|
||||
targets.forEach((id) => {
|
||||
if (loaded) {
|
||||
fetchedLibIdsRef.current.add(id)
|
||||
}
|
||||
fetchingRef.current.delete(id)
|
||||
})
|
||||
}
|
||||
}),
|
||||
)
|
||||
}, [])
|
||||
|
||||
const loadLibraries = useCallback(async (options?: { force?: boolean }) => {
|
||||
|
||||
@@ -3,4 +3,19 @@
|
||||
// embyremote~{accountID}~{remoteID}。
|
||||
export function isRemoteEmbyID(id?: string | null): boolean {
|
||||
return Boolean(id && id.startsWith('embyremote~'))
|
||||
}
|
||||
|
||||
// partitionPreviewIDs 把本地库和远程库拆开。混在一个预览请求里时,本地 SQL
|
||||
// 会等最慢的远程 Emby 回来才一起返回。
|
||||
export function partitionPreviewIDs(ids: string[]): string[][] {
|
||||
const local: string[] = []
|
||||
const remote: string[] = []
|
||||
for (const id of ids) {
|
||||
if (isRemoteEmbyID(id)) remote.push(id)
|
||||
else local.push(id)
|
||||
}
|
||||
const batches: string[][] = []
|
||||
if (local.length > 0) batches.push(local)
|
||||
if (remote.length > 0) batches.push(remote)
|
||||
return batches
|
||||
}
|
||||
Reference in New Issue
Block a user