Files
cozsweet-frontend-nextjs/src/app/chat/image/[messageId]/chat-image-viewer-screen.tsx
T

173 lines
4.5 KiB
TypeScript

"use client";
import { useEffect } from "react";
import { useRouter } from "next/navigation";
import { MobileShell } from "@/app/_components/core";
import { ROUTE_BUILDERS, ROUTES } from "@/router/routes";
import { useAuthState } from "@/stores/auth/auth-context";
import { useChatDispatch, useChatState } from "@/stores/chat/chat-context";
import { useUserState } from "@/stores/user/user-context";
import {
consumePendingChatUnlock,
peekPendingChatUnlock,
savePendingChatUnlock,
} from "@/lib/navigation/chat_unlock_session";
import { getInsufficientCreditsSubscriptionType } from "../../chat-screen.helpers";
import { FullscreenImageViewer, HistoryUnlockDialog } from "../../components";
import styles from "./chat-image-viewer-screen.module.css";
export interface ChatImageViewerScreenProps {
messageId: string;
}
export function ChatImageViewerScreen({
messageId,
}: ChatImageViewerScreenProps) {
const router = useRouter();
const authState = useAuthState();
const userState = useUserState();
const chatState = useChatState();
const chatDispatch = useChatDispatch();
const returnUrl = ROUTE_BUILDERS.chatImage(messageId);
const isAuthenticatedUser =
authState.loginStatus !== "notLoggedIn" &&
authState.loginStatus !== "guest";
const message = chatState.messages.find(
(item) => item.id === messageId && item.imageUrl,
);
useEffect(() => {
if (!chatState.historyLoaded || !isAuthenticatedUser) return;
const pending = peekPendingChatUnlock();
if (
!pending ||
pending.kind !== "image" ||
pending.messageId !== messageId ||
pending.returnUrl !== returnUrl
) {
return;
}
const consumed = consumePendingChatUnlock();
if (!consumed) return;
chatDispatch({
type: "ChatUnlockMessageRequested",
messageId: consumed.messageId,
kind: consumed.kind,
});
}, [
chatDispatch,
chatState.historyLoaded,
isAuthenticatedUser,
messageId,
returnUrl,
]);
useEffect(() => {
const request = chatState.unlockPaywallRequest;
if (!request || request.kind !== "image" || request.messageId !== messageId) {
return;
}
savePendingChatUnlock({
messageId: request.messageId,
kind: request.kind,
returnUrl,
stage: "payment",
});
chatDispatch({ type: "ChatUnlockPaywallNavigationConsumed" });
router.push(
ROUTE_BUILDERS.subscription(
getInsufficientCreditsSubscriptionType(userState.isVip),
{ returnTo: "chat" },
),
);
}, [
chatDispatch,
chatState.unlockPaywallRequest,
messageId,
returnUrl,
router,
userState.isVip,
]);
const handleClose = () => {
router.push(ROUTES.chat);
};
const handleUnlockImagePaywall = () => {
if (!isAuthenticatedUser) {
savePendingChatUnlock({
messageId,
kind: "image",
returnUrl,
stage: "auth",
});
router.push(ROUTE_BUILDERS.authWithRedirect(returnUrl));
return;
}
chatDispatch({
type: "ChatUnlockMessageRequested",
messageId,
kind: "image",
});
};
const historyUnlockDialog = (
<HistoryUnlockDialog
open={chatState.unlockHistoryPromptVisible}
lockedCount={chatState.lockedHistoryCount}
isLoading={chatState.isUnlockingHistory}
errorMessage={chatState.unlockHistoryError}
onClose={() => chatDispatch({ type: "ChatUnlockHistoryDismissed" })}
onConfirm={() => chatDispatch({ type: "ChatUnlockHistoryConfirmed" })}
/>
);
if (!message) {
return (
<>
<MobileShell background="#0d0b14">
<main className={styles.emptyScreen}>
<button
type="button"
className={styles.backButton}
onClick={handleClose}
>
Back to chat
</button>
<p className={styles.emptyText}>
{chatState.historyLoaded ? "Image not found." : "Loading image..."}
</p>
</main>
</MobileShell>
{historyUnlockDialog}
</>
);
}
return (
<>
<MobileShell background="#000000">
<FullscreenImageViewer
messageId={messageId}
imageUrl={message.imageUrl ?? ""}
imagePaywalled={message.imagePaywalled === true}
isUnlockingImagePaywall={
chatState.isUnlockingMessage &&
chatState.unlockingMessageId === messageId
}
onUnlockImagePaywall={handleUnlockImagePaywall}
onClose={handleClose}
/>
</MobileShell>
{historyUnlockDialog}
</>
);
}