"use client"; import { useEffect, useMemo, useRef } from "react"; import Image from "next/image"; import { useRouter, useSearchParams } from "next/navigation"; import { CharacterAvatar } from "@/app/_components"; import { AppBottomNav, FavoriteEntryButton, MobileShell, } from "@/app/_components/core"; import { buildGlobalPageUrl } from "@/router/global-route-context"; import { ROUTES } from "@/router/routes"; import { useAppNavigator } from "@/router/use-app-navigator"; import { useActiveCharacter, useActiveCharacterRoutes, } from "@/providers/character-provider"; import { isPrivateAlbumLocked } from "@/lib/private-zone/private_album"; import { useAuthDispatch, useAuthState } from "@/stores/auth/auth-context"; import { usePrivateZoneDispatch, usePrivateZoneState, } from "@/stores/private-zone"; import { PrivateAlbumCard, PrivateAlbumGallery, StatusCard, UnlockConfirmDialog, } from "./components"; import styles from "./private-zone-screen.module.css"; import { isPrivateZoneAuthRequired, usePrivateZoneBootstrapFlow, usePrivateZoneUnlockPaywallNavigation, usePrivateZoneUnlockSuccessRefresh, } from "./use-private-zone-flow"; import { buildPrivateAlbumGalleryUrl, buildPrivateZoneWithoutGalleryUrl, getPrivateAlbumGalleryState, } from "./private-album-gallery-url"; import { findPrivateAlbumDisplayImage } from "./private-album-images"; export function PrivateZoneScreen() { const router = useRouter(); const searchParams = useSearchParams(); const navigator = useAppNavigator(); const character = useActiveCharacter(); const characterRoutes = useActiveCharacterRoutes(); const authState = useAuthState(); const authDispatch = useAuthDispatch(); const state = usePrivateZoneState(); const dispatch = usePrivateZoneDispatch(); const openedGalleryInPageRef = useRef(false); const galleryState = useMemo( () => getPrivateAlbumGalleryState(searchParams), [searchParams], ); usePrivateZoneBootstrapFlow({ authDispatch, hasInitialized: authState.hasInitialized, isAuthLoading: authState.isLoading, loginStatus: authState.loginStatus, roomDispatch: dispatch, roomStatus: state.status, }); usePrivateZoneUnlockPaywallNavigation({ loginStatus: authState.loginStatus, roomDispatch: dispatch, unlockPaywallRequest: state.unlockPaywallRequest, }); usePrivateZoneUnlockSuccessRefresh(state.unlockSuccessNonce); const displayName = character.displayName; const avatarUrl = character.assets.avatar; const title = character.copy.privateZoneTitle; const subtitle = character.copy.privateZoneSubtitle; const pendingAlbum = useMemo( () => state.items.find( (album) => album.albumId === state.pendingConfirmAlbumId, ) ?? null, [state.items, state.pendingConfirmAlbumId], ); const galleryAlbum = useMemo( () => galleryState ? state.items.find((album) => album.albumId === galleryState.albumId) ?? null : null, [galleryState, state.items], ); const galleryImage = useMemo( () => galleryAlbum && galleryState ? findPrivateAlbumDisplayImage( galleryAlbum, galleryState.imageIndex, ) : null, [galleryAlbum, galleryState], ); useEffect(() => { if (!galleryState || state.isLoading) return; if ( !galleryAlbum || isPrivateAlbumLocked(galleryAlbum) || !galleryImage ) { router.replace( buildPrivateZoneWithoutGalleryUrl( searchParams, characterRoutes.privateZone, ), { scroll: false }, ); } }, [ characterRoutes.privateZone, galleryAlbum, galleryImage, galleryState, router, searchParams, state.isLoading, ]); const handleTopUpClick = () => { if (isPrivateZoneAuthRequired(authState.loginStatus)) { navigator.openAuth(characterRoutes.privateZone); return; } navigator.openSubscription({ type: "topup", returnTo: "private-zone", analytics: { entryPoint: "private_zone", triggerReason: "vip_cta", }, }); }; const handleOpenGallery = (albumId: string, imageIndex: number) => { openedGalleryInPageRef.current = true; router.push( buildPrivateAlbumGalleryUrl( albumId, imageIndex, characterRoutes.privateZone, ), { scroll: false }, ); }; const handleCloseGallery = () => { if (openedGalleryInPageRef.current) { openedGalleryInPageRef.current = false; router.back(); return; } router.replace( buildPrivateZoneWithoutGalleryUrl( searchParams, characterRoutes.privateZone, ), { scroll: false }, ); }; const handleGalleryIndexChange = (imageIndex: number) => { if (!galleryAlbum) return; router.replace( buildPrivateAlbumGalleryUrl( galleryAlbum.albumId, imageIndex, characterRoutes.privateZone, ), { scroll: false }, ); }; return (

{displayName}

Albums

Private albums

{state.items.length}
{state.errorMessage ? ( dispatch({ type: "PrivateZoneRefresh" })} /> ) : null} {state.isLoading && state.items.length === 0 ? ( ) : null} {!state.isLoading && state.items.length === 0 && !state.errorMessage ? ( dispatch({ type: "PrivateZoneRefresh" })} /> ) : null}
{state.items.map((album, index) => ( handleOpenGallery(album.albumId, imageIndex) } onUnlock={() => dispatch({ type: "PrivateZoneUnlockRequested", albumId: album.albumId, }) } /> ))}
navigator.push(characterRoutes.splash, { scroll: false }) } onPrivateZoneClick={() => undefined} onMenuClick={() => navigator.push( buildGlobalPageUrl(ROUTES.profile, characterRoutes.chat), { scroll: false }, ) } /> {pendingAlbum ? ( dispatch({ type: "PrivateZoneUnlockCancelled" })} onConfirm={() => dispatch({ type: "PrivateZoneUnlockConfirmed" })} /> ) : state.unlockErrorMessage ? (
{state.unlockErrorMessage}
) : null} {galleryAlbum && galleryState && !isPrivateAlbumLocked(galleryAlbum) && galleryImage ? ( ) : null}
); }