import { categoryCount, flattenAppItems, type Category } from '../../data/types'
import { AppGrid } from './AppGrid'
import { ArticleGrid } from './ArticleGrid'
import { Empty } from '@stash/ui'
import { PosterGrid } from './PosterGrid'
import { SectionCard } from './SectionCard'
import {
applySectionSettings,
sectionLimit,
sectionTitle,
type SectionSettings,
} from '../../settings'
/**
* 首页:把每个分类渲染成一张分区卡片。
*
* 每个分区只展示前若干条;标题、条数、顺序与显隐都可以在 `/admin`
* 的「首页卡片」里覆盖(见 settings.sections)。
*/
type HomeViewProps = {
categories: Category[]
sections: SectionSettings
onOpenDetail: (categoryId: string) => void
onOpenItem: (categoryId: string, itemId: string) => void
}
export function HomeView({ categories, sections, onOpenDetail, onOpenItem }: HomeViewProps) {
const cards = applySectionSettings(categories, sections)
return (
{cards.map((category) => (
onOpenDetail(category.id)}
>
{renderPreview(category, sections, onOpenItem)}
))}
)
}
/**
* 卡片右上角的数量角标。
*
* 配了「分组展示块」时,卡片实际展示的是那个分组,所以数量也应该只数它;
* 否则(电影 / 文章 / 本地服务)数整个分区。
*/
function cardCount(category: Category): number {
if (category.block !== undefined) {
const group = category.groups.find((item) => item.id === category.block?.nodeKey)
if (group !== undefined) return group.items.length
}
return categoryCount(category)
}
/** 某个分区配的「首页预览分组」;没配或找不到返回 undefined */
function blockGroup(category: { block?: { nodeKey?: string }; groups: { id: string; items: T[] }[] }) {
if (category.block?.nodeKey === undefined) return undefined
return category.groups.find((group) => group.id === category.block?.nodeKey)
}
/** 按分类类型输出对应的预览网格;应用类为空时给出提示文案 */
function renderPreview(
category: Category,
sections: SectionSettings,
onOpenItem: (categoryId: string, itemId: string) => void,
) {
if (category.kind === 'apps') {
// 配了展示块且指向分组时只展示该组;展示块指向分区本身(「整个分区」)时展示全部条目
const group = blockGroup(category)
const source = group !== undefined ? group.items : flattenAppItems(category)
const fallback = category.block?.previewLimit ?? category.previewLimit ?? 4
const limit = sectionLimit(category.id, fallback, sections)
const items = source.slice(0, limit)
if (items.length === 0) {
return
}
return onOpenItem(category.id, itemId)} />
}
if (category.kind === 'posters') {
const group = blockGroup(category)
const source = group
? group.items
: [...category.items, ...category.groups.flatMap((item) => item.items)]
return (
onOpenItem(category.id, itemId)}
/>
)
}
const group = blockGroup(category)
const source = group
? group.items
: [...category.items, ...category.groups.flatMap((item) => item.items)]
return (
onOpenItem(category.id, itemId)}
/>
)
}