update viewContent page

This commit is contained in:
root 2025-10-11 22:12:38 +00:00
parent 33e0349a1b
commit 997fbb6985
1 changed files with 131 additions and 96 deletions

View File

@ -5,7 +5,7 @@ import { useWebApp } from '@vkruglikov/react-telegram-web-app';
import { Button } from '~/shared/ui/button';
import { usePurchaseContent, useViewContent } from '~/shared/services/content';
import { fromNanoTON } from '~/shared/utils';
import { useCallback, useEffect, useMemo, useState } from 'react';
import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
import { AudioPlayer } from '~/shared/ui/audio-player';
import { useAuth } from '~/shared/services/auth';
import { CongratsModal } from './components/congrats-modal';
@ -39,16 +39,16 @@ export const ViewContentPage = () => {
const statusState = content?.data?.status?.state ?? "uploaded";
const conversionState = content?.data?.conversion?.state;
const uploadState = content?.data?.upload?.state;
const statusLabel = useMemo(() => {
const statusMessage = useMemo(() => {
switch (statusState) {
case "ready":
return "Готово";
case "processing":
return "Обрабатывается";
return "Контент обрабатывается";
case "failed":
return "Ошибка";
return "Ошибка обработки";
case "ready":
return null;
default:
return "Загружено";
return "Файл загружен";
}
}, [statusState]);
@ -56,6 +56,16 @@ export const ViewContentPage = () => {
const isAudio = Boolean(content?.data?.content_type?.startsWith('audio'));
const isReady = Boolean(mediaUrl);
const metadataName = content?.data?.display_options?.metadata?.name;
const contentTitle = metadataName || content?.data?.encrypted?.title || 'Контент';
const processingDetails = useMemo(() => {
if (!statusMessage) {
return null;
}
return {
conversion: conversionState,
upload: uploadState,
};
}, [conversionState, statusMessage, uploadState]);
const handleBuyContentTON = useCallback(async () => {
if (!contentId) {
@ -175,13 +185,27 @@ export const ViewContentPage = () => {
}
}, [content, refetchContent]);
const haveLicense = useMemo(() => {
document.title = content?.data?.display_options?.metadata?.name;
return (
content?.data?.have_licenses?.includes('listen') ||
content?.data?.have_licenses?.includes('resale')
);
}, [content]);
const haveLicense = useMemo(() => (
content?.data?.have_licenses?.includes('listen') ||
content?.data?.have_licenses?.includes('resale')
), [content]);
const hadLicenseRef = useRef<boolean>(haveLicense);
useEffect(() => {
if (haveLicense && !hadLicenseRef.current) {
hadLicenseRef.current = true;
void refetchContent();
} else if (!haveLicense) {
hadLicenseRef.current = false;
}
}, [haveLicense, refetchContent]);
useEffect(() => {
if (contentTitle) {
document.title = contentTitle;
}
}, [contentTitle]);
useEffect(() => {
if (!contentId) {
@ -221,7 +245,7 @@ export const ViewContentPage = () => {
<main className={'min-h-screen flex w-full flex-col gap-[50px] px-4 '}>
{isCongratsModal && <CongratsModal onConfirm={handleConfirmCongrats} />}
{isErrorModal && <ErrorModal onConfirm={handleErrorModal} />}
{isAudio &&
{isReady && isAudio &&
content?.data?.display_options?.metadata?.image && (
<div className={'mt-[30px] h-[314px] w-full'}>
<img
@ -233,93 +257,104 @@ export const ViewContentPage = () => {
)}
{isReady ? (
isAudio ? (
<AudioPlayer src={mediaUrl ?? ''} />
) : (
<ReactPlayer
playsinline={true}
controls={true}
width="100%"
config={{
file: {
attributes: {
playsInline: true,
autoPlay: true,
poster: content?.data?.display_options?.metadata?.image || undefined,
<>
{isAudio ? (
<AudioPlayer src={mediaUrl ?? ''} />
) : (
<ReactPlayer
playsinline={true}
controls={true}
width="100%"
config={{
file: {
attributes: {
playsInline: true,
autoPlay: true,
poster: content?.data?.display_options?.metadata?.image || undefined,
},
},
},
}}
url={mediaUrl}
/>
)
) : (
<div className={'rounded-xl bg-slate-900/60 p-4 text-center text-sm text-slate-200'}>
<p>{statusLabel}. Конвертация может занять несколько минут.</p>
{conversionState && (
<p className={'mt-2 text-xs text-slate-400'}>
Статус конвертера: {conversionState}
</p>
)}
{uploadState && (
<p className={'mt-1 text-xs text-slate-400'}>
Загрузка: {uploadState}
</p>
)}
</div>
)}
<section className={'flex flex-col'}>
<h1 className={'text-[20px] font-bold'}>{metadataName}</h1>
<span className={'mt-1 text-xs text-slate-400'}>{statusLabel}</span>
{/*<h2>Russian</h2>*/}
{/*<h2>2022</h2>*/}
<p className={'mt-2 text-[12px]'}>
{content?.data?.display_options?.metadata?.description}
</p>
</section>
<div className="mt-auto pb-2">
{content?.data?.downloadable && (
<Button
onClick={() => handleDwnldContent()}
className={'h-[48px] mb-4'}
label={`Скачать контент`}
/>
)}
{!haveLicense && (
<div className="flex flex-row gap-4">
<Button
onClick={handleBuyContentTON}
className={'mb-4 h-[48px] px-2'}
label={`Купить за ${fromNanoTON(content?.data?.encrypted?.license?.resale?.price)} ТОН`}
includeArrows={content?.data?.invoice ? false : true}
}}
url={mediaUrl}
/>
{content?.data?.invoice && (
)}
<section className={'flex flex-col'}>
<h1 className={'text-[20px] font-bold'}>{metadataName}</h1>
<p className={'mt-2 text-[12px]'}>
{content?.data?.display_options?.metadata?.description}
</p>
</section>
<div className="mt-auto pb-2">
{content?.data?.downloadable && (
<Button
onClick={handleBuyContentStars}
className={'mb-4 h-[48px] px-2'}
label={`Купить за ${content?.data?.invoice?.amount} ⭐️`}
onClick={() => handleDwnldContent()}
className={'h-[48px] mb-4'}
label={`Скачать контент`}
/>
)}
{!haveLicense && (
<div className="flex flex-row gap-4">
<Button
onClick={handleBuyContentTON}
className={'mb-4 h-[48px] px-2'}
label={`Купить за ${fromNanoTON(content?.data?.encrypted?.license?.resale?.price)} ТОН`}
includeArrows={content?.data?.invoice ? false : true}
/>
{content?.data?.invoice && (
<Button
onClick={handleBuyContentStars}
className={'mb-4 h-[48px] px-2'}
label={`Купить за ${content?.data?.invoice?.amount} ⭐️`}
/>
)}
</div>
)}
<Button
onClick={() => {
WebApp.openTelegramLink(`https://t.me/MY_UploaderRobot`);
}}
className={'h-[48px] bg-darkred'}
label={`Загрузить свой контент`}
/>
{tonConnectUI.connected && (
<Button
onClick={() => {
tonConnectUI.disconnect();
}}
className={'h-[48px] bg-darkred mt-4'}
label={`Отключить кошелек`}
/>
)}
</div>
)}
<Button
onClick={() => {
WebApp.openTelegramLink(`https://t.me/MY_UploaderRobot`);
}}
className={'h-[48px] bg-darkred'}
label={`Загрузить свой контент`}
/>
{tonConnectUI.connected && (
<Button
onClick={() => {
tonConnectUI.disconnect();
}}
className={'h-[48px] bg-darkred mt-4'}
label={`Отключить кошелек`}
/>
)}
</div>
</>
) : (
<div className="flex flex-1 flex-col items-center justify-center py-16">
<div className="max-w-md rounded-2xl border border-slate-800 bg-slate-950/70 px-6 py-8 text-center shadow-lg shadow-black/30">
<h1 className="text-lg font-semibold text-slate-100">
Контент скоро будет здесь
</h1>
<p className="mt-3 text-sm text-slate-300">
Мы уже обрабатываем загруженный файл и обновим страницу автоматически, как только появится доступ к полному контенту.
</p>
{statusMessage && (
<p className="mt-4 text-[12px] text-slate-500">
Текущее состояние: {statusMessage}
</p>
)}
{processingDetails?.conversion && (
<p className="mt-2 text-[12px] text-slate-500">
Статус конвертера: {processingDetails.conversion}
</p>
)}
{processingDetails?.upload && (
<p className="mt-2 text-[12px] text-slate-500">
Загрузка: {processingDetails.upload}
</p>
)}
</div>
</div>
)}
</main>
);
};