'use client'; import { useParams } from "next/navigation"; import { useGetAIUserAlbumInfinite, useLikeAlbumImage, useUnlockAlbumImage, useUnlockImage } from "@/hooks/aiUser"; import { IAlbumItem, LikedStatus, LockStatus } from "@/services/user/types"; import Empty from "@/components/ui/empty"; import { toast } from "sonner"; import AlbumItem from "./AlbumItem"; import { InfiniteScrollList } from "@/components/ui/infinite-scroll-list"; import { ImageViewer, ImageViewerPaginationContent } from "@/components/ui/image-viewer"; import { useImageViewer } from "@/hooks/useImageViewer"; import { useMemo, useRef, useState } from "react"; import { useAIUser } from "../context/aiUser"; import AlbumImageViewerAction from "./AlbumImageViewerAction"; import Image from "next/image"; import { formatFromCents } from "@/utils/number"; // 专门的相册骨架屏组件 const AlbumSkeleton = () => (
); const AlbumList = () => { const { userId } = useParams(); const pageSize = 20; const unlockingAlbumIdsRef = useRef>(new Set()); const { data, isLoading, fetchNextPage, hasNextPage, isFetchingNextPage, } = useGetAIUserAlbumInfinite(Number(userId), pageSize); const likeMutation = useLikeAlbumImage(); const unlockMutation = useUnlockImage(); const { isOwner } = useAIUser(); const [tempList, setTempList] = useState([]); // 图片查看器 const { isOpen: isViewerOpen, currentIndex: viewerIndex, openViewer, closeViewer, handleIndexChange, } = useImageViewer(); // 展平所有页面的数据 const albumItems = useMemo(() => { if (!data?.pages) return []; return data.pages.flatMap(page => page.datas || []); }, [data?.pages]); const handleLike = (albumId: number, isLiked: boolean) => { likeMutation.mutate( { albumId, likedStatus: isLiked ? LikedStatus.Canceled : LikedStatus.Liked, aiId: Number(userId) }, ); }; const handleUnlock = async (imageId: number) => { await unlockMutation.mutateAsync( { aiId: Number(userId), albumId: imageId }, { onSuccess: () => { toast.success("Unlocked successfully!"); }, onError: (error) => { } } ); }; const handleImageClick = (item: IAlbumItem, index: number) => { // 获取所有图片URL const imageUrls = albumItems.map(albumItem => albumItem.imgUrl || albumItem.img3); setTempList(albumItems); // 打开图片查看器 openViewer(imageUrls, index); }; const viewerImages: IAlbumItem[] = useMemo(() => { return tempList.map((item) => { const { albumId } = item; const data = albumItems.find((item) => item.albumId === albumId) || {}; return data as IAlbumItem; }); }, [tempList, albumItems]); return ( <> items={albumItems} renderItem={(item, index) => ( handleImageClick(item, index)} /> )} getItemKey={(item) => item.albumId} hasNextPage={!!hasNextPage} isLoading={isLoading || isFetchingNextPage} fetchNextPage={fetchNextPage} columns={{ default: 2, sm: 3, md: 4, lg: 4, xl: 5 }} gap={4} LoadingSkeleton={AlbumSkeleton} EmptyComponent={() => (
)} threshold={300} enabled={true} /> {/* 图片查看器 */} albumItem.imgUrl || albumItem.img3)} currentIndex={viewerIndex} open={isViewerOpen} onClose={closeViewer} onIndexChange={handleIndexChange} showChooseButton={false} ActionComponent={() => { return ( { if (nextIndex === null) { // 删除后没有图片了 closeViewer(); return; } // 调整到新的索引,避免越界 handleIndexChange(nextIndex); }} /> ) }} OverlayComponent={() => { const findItem = albumItems.find((item, index) => index === viewerIndex); const { unlockPrice, lockStatus } = findItem || {}; if (isOwner || !lockStatus || lockStatus === LockStatus.Unlock) { return null; } return (
diamond
{`${formatFromCents(unlockPrice || 0)} to unlock`}
) }} PaginationComponent={() => { const currentIndex = viewerIndex + 1; const findItem = tempList.find((item, index) => index === viewerIndex); const { albumId } = findItem || {}; const { lockStatus } = albumItems.find((item) => item.albumId === albumId) || {}; if (isOwner) { if (lockStatus) { return ( {`${currentIndex}/${albumItems.length}`} ) } return ( {`${currentIndex}/${albumItems.length}`} ) } if (lockStatus === LockStatus.Lock) { return ( {`${currentIndex}/${albumItems.length}`} ) } if (lockStatus === LockStatus.Unlock) { return ( {`${currentIndex}/${albumItems.length}`} ) } return ( {`${currentIndex}/${albumItems.length}`} ) }} /> ); }; export default AlbumList;