'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 (
{`${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;