// 业务专用类型 import { AlbumNeighborWindow, AlbumType, GalleryDisplayConfig, ImageType } from '~/types/index' export type AlbumDataProps = { data: AlbumType[] title?: string } export type HandleProps = { handle: () => Promise args: string } export type ImageServerHandleProps = { handle: (pageNum: number, tag: string, showStatus?: number, camera?: string, lens?: string) => Promise args: string totalHandle: (tag: string, showStatus?: number, camera?: string, lens?: string) => Promise } export type ImageHandleProps = { handle: (pageNum: number, album: string, camera?: string, lens?: string) => Promise args: string album: string totalHandle: (album: string, camera?: string, lens?: string) => Promise configHandle?: () => Promise // Variant CDN base resolved on the server (the same value `configHandle` will // return). Passed so the gallery has it on the very first client render, // before the client-side config SWR resolves — otherwise the grid briefly // sees an empty base, falls back to requesting `preview_url` thumbnails, then // swaps to AVIF once config arrives (a wasteful double-load that spiked mobile // memory). With this, the first render already serves AVIF variants. variantBaseUrl?: string } export type PreviewImageHandleProps = { data: ImageType args: string id: string configHandle?: () => Promise // Server-resolved neighbor window centered on `data`, so the detail view can // render an in-place prev/next carousel over the album without an extra // round-trip on open. Best-effort — falls back to a single-photo sequence. initialWindow?: AlbumNeighborWindow | null } export type ProgressiveImageProps = { imageUrl: string, // 原始图片 previewUrl: string, // 预览图 width?: number, height?: number, blurhash: string, alt?: string, showLightbox?:boolean onShowLightboxChange?: (value: boolean) => void // Variant fields so the high-res viewer can load the largest generated variant // (e.g. 2560 avif/webp) instead of the multi-MB original. Empty/missing → falls // back to imageUrl (the original). imageKey?: string readyMaxWidth?: number variantBaseUrl?: string // LRU eviction signal from the carousel. When it flips to false the kept-mounted // WebGL viewer is *unmounted*, which runs WebGLImageViewer's existing // destroy-on-unmount (loseContext) — reusing the verified #510 lifecycle rather // than imperatively destroying a still-mounted engine (which would strand // isInitialized=true over a dead context and re-trigger the #510 crash). So the // count of live GL contexts stays hard-capped. Defaults to kept-mounted. keepViewerMounted?: boolean } export type LinkProps = { handle: () => Promise args: string data: unknown } export type AlbumListProps = { data: AlbumType[] } export type ImageDataProps = { data: ImageType } export type ImageListDataProps = { data: ImageType[] } export type AnalysisDataProps = { data: { total: number; showTotal: number; tagsTotal: number; cameraStats: Array<{ camera: string; lens: string; count: number; }>; result: Array<{ name: string; value: string; total: number; show_total: number; }>; } }