refactor: move page model helpers out of components

This commit is contained in:
ShukeBta
2026-06-25 04:45:35 +08:00
parent 7efa5d20b0
commit 42ed6960a1
6 changed files with 88 additions and 85 deletions
+1 -63
View File
@@ -2,69 +2,7 @@ import type { ReactNode } from 'react'
import { ArrowDown, ArrowUp, Film, HardDrive, Rss, Trash2 } from 'lucide-react' import { ArrowDown, ArrowUp, Film, HardDrive, Rss, Trash2 } from 'lucide-react'
import { imageURL } from '../api/client' import { imageURL } from '../api/client'
import type { DownloadTask, QBitTorrent } from '../types' import type { DownloadCardItem } from './downloadTaskCardModel'
export type DownloadCardItem = {
id?: string
hash?: string
title: string
poster_url?: string
backdrop_url?: string
overview?: string
save_path?: string
status?: string
state?: string
progress: number
dlspeed?: number
upspeed?: number
num_seeds?: number
num_leechs?: number
size?: number
downloaded?: number
created_at?: string
updated_at?: string
}
export function toLiveCard(t: QBitTorrent): DownloadCardItem {
return {
hash: t.hash,
title: t.title || t.name || '下载任务',
poster_url: t.poster_url,
backdrop_url: t.backdrop_url,
overview: t.overview,
save_path: t.save_path,
state: t.state,
progress: t.progress,
dlspeed: t.dlspeed,
upspeed: t.upspeed,
num_seeds: t.num_seeds,
num_leechs: t.num_leechs,
size: t.size,
downloaded: t.downloaded,
}
}
export function toTaskCard(t: DownloadTask): DownloadCardItem {
return {
id: t.id,
title: t.title || '下载任务',
poster_url: t.poster_url,
backdrop_url: t.backdrop_url,
overview: t.overview,
save_path: t.save_path,
status: t.status,
state: t.state,
progress: t.progress,
dlspeed: t.dlspeed,
upspeed: t.upspeed,
num_seeds: t.num_seeds,
num_leechs: t.num_leechs,
size: t.size,
downloaded: t.downloaded,
created_at: t.created_at,
updated_at: t.updated_at,
}
}
export function DownloadTaskCard({ export function DownloadTaskCard({
item, item,
+2 -1
View File
@@ -7,7 +7,8 @@ import { downloadsAPI } from '../api/downloads'
import { useAuthStore } from '../stores/auth' import { useAuthStore } from '../stores/auth'
import { confirmAction } from '../components/confirmAction' import { confirmAction } from '../components/confirmAction'
import type { DownloadTask, QBitTorrent } from '../types' import type { DownloadTask, QBitTorrent } from '../types'
import { DownloadTaskCard, toLiveCard, toTaskCard } from './DownloadTaskCard' import { DownloadTaskCard } from './DownloadTaskCard'
import { toLiveCard, toTaskCard } from './downloadTaskCardModel'
export function DownloadsPage() { export function DownloadsPage() {
const role = useAuthStore((s) => s.user?.role) const role = useAuthStore((s) => s.user?.role)
+1 -2
View File
@@ -6,9 +6,8 @@ import {
LibrariesContent, LibrariesContent,
LibrariesEmptyState, LibrariesEmptyState,
LibrariesHeader, LibrariesHeader,
latestLibraryCards,
type LibraryPreview,
} from './LibrariesPageSections' } from './LibrariesPageSections'
import { latestLibraryCards, type LibraryPreview } from './librariesPageModel'
export function LibrariesPage() { export function LibrariesPage() {
const [previews, setPreviews] = useState<LibraryPreview[]>([]) const [previews, setPreviews] = useState<LibraryPreview[]>([])
+2 -19
View File
@@ -6,15 +6,8 @@ import { ArrowRight, Film, FolderOpen, Library as LibraryIcon, Music, PlayCircle
import { imageURL } from '../api/client' import { imageURL } from '../api/client'
import { EpisodeArtworkToggle } from '../components/EpisodeArtworkToggle' import { EpisodeArtworkToggle } from '../components/EpisodeArtworkToggle'
import { MediaCard } from '../components/MediaCard' import { MediaCard } from '../components/MediaCard'
import type { Library, Media } from '../types' import { artworkScore, seriesCardLink, type SeriesCard } from '../utils/groupSeries'
import { artworkScore, groupSeries, seriesCardLink, type SeriesCard } from '../utils/groupSeries' import { mediaTime, type LibraryPreview } from './librariesPageModel'
export type LibraryPreview = {
library: Library
items: Media[]
total: number
cards: SeriesCard[]
}
const TYPE_ICONS: Record<string, ReactNode> = { const TYPE_ICONS: Record<string, ReactNode> = {
movie: <Film size={18} />, movie: <Film size={18} />,
@@ -222,12 +215,6 @@ function LibraryShelf({ preview }: { preview: LibraryPreview }) {
) )
} }
export function latestLibraryCards(items: Media[]): SeriesCard[] {
return groupSeries(items)
.sort((a, b) => mediaTime(b.rep) - mediaTime(a.rep) || artworkScore(b.rep) - artworkScore(a.rep))
.slice(0, 10)
}
function libraryArtworkItems(cards: SeriesCard[]): Array<{ src: string; version?: string }> { function libraryArtworkItems(cards: SeriesCard[]): Array<{ src: string; version?: string }> {
return [...cards] return [...cards]
.sort((a, b) => artworkScore(b.rep) - artworkScore(a.rep) || mediaTime(b.rep) - mediaTime(a.rep)) .sort((a, b) => artworkScore(b.rep) - artworkScore(a.rep) || mediaTime(b.rep) - mediaTime(a.rep))
@@ -238,7 +225,3 @@ function libraryArtworkItems(cards: SeriesCard[]): Array<{ src: string; version?
.filter((item) => Boolean(item.src)) .filter((item) => Boolean(item.src))
.slice(0, 4) .slice(0, 4)
} }
function mediaTime(media: Media): number {
return Date.parse(media.updated_at || media.created_at || '') || 0
}
+63
View File
@@ -0,0 +1,63 @@
import type { DownloadTask, QBitTorrent } from '../types'
export type DownloadCardItem = {
id?: string
hash?: string
title: string
poster_url?: string
backdrop_url?: string
overview?: string
save_path?: string
status?: string
state?: string
progress: number
dlspeed?: number
upspeed?: number
num_seeds?: number
num_leechs?: number
size?: number
downloaded?: number
created_at?: string
updated_at?: string
}
export function toLiveCard(t: QBitTorrent): DownloadCardItem {
return {
hash: t.hash,
title: t.title || t.name || '下载任务',
poster_url: t.poster_url,
backdrop_url: t.backdrop_url,
overview: t.overview,
save_path: t.save_path,
state: t.state,
progress: t.progress,
dlspeed: t.dlspeed,
upspeed: t.upspeed,
num_seeds: t.num_seeds,
num_leechs: t.num_leechs,
size: t.size,
downloaded: t.downloaded,
}
}
export function toTaskCard(t: DownloadTask): DownloadCardItem {
return {
id: t.id,
title: t.title || '下载任务',
poster_url: t.poster_url,
backdrop_url: t.backdrop_url,
overview: t.overview,
save_path: t.save_path,
status: t.status,
state: t.state,
progress: t.progress,
dlspeed: t.dlspeed,
upspeed: t.upspeed,
num_seeds: t.num_seeds,
num_leechs: t.num_leechs,
size: t.size,
downloaded: t.downloaded,
created_at: t.created_at,
updated_at: t.updated_at,
}
}
+19
View File
@@ -0,0 +1,19 @@
import type { Library, Media } from '../types'
import { artworkScore, groupSeries, type SeriesCard } from '../utils/groupSeries'
export type LibraryPreview = {
library: Library
items: Media[]
total: number
cards: SeriesCard[]
}
export function latestLibraryCards(items: Media[]): SeriesCard[] {
return groupSeries(items)
.sort((a, b) => mediaTime(b.rep) - mediaTime(a.rep) || artworkScore(b.rep) - artworkScore(a.rep))
.slice(0, 10)
}
export function mediaTime(media: Media): number {
return Date.parse(media.updated_at || media.created_at || '') || 0
}