From 3d78d3e279bcf714bfc2bdc0e31d4117ea40f047 Mon Sep 17 00:00:00 2001 From: DIKER0K Date: Mon, 21 Jul 2025 08:27:35 +0500 Subject: [PATCH 1/7] feat: improved TopBar and empty registration page --- src/renderer/App.tsx | 2 ++ src/renderer/api.ts | 2 +- src/renderer/components/TopBar.tsx | 7 ++++--- src/renderer/pages/Registration.tsx | 3 +++ 4 files changed, 10 insertions(+), 4 deletions(-) create mode 100644 src/renderer/pages/Registration.tsx diff --git a/src/renderer/App.tsx b/src/renderer/App.tsx index d8d73ee..c9e45c5 100644 --- a/src/renderer/App.tsx +++ b/src/renderer/App.tsx @@ -17,6 +17,7 @@ import { VersionsExplorer } from './pages/VersionsExplorer'; import Profile from './pages/Profile'; import Shop from './pages/Shop'; import Marketplace from './pages/Marketplace'; +import { Registration } from './pages/Registration'; const AuthCheck = ({ children }: { children: ReactNode }) => { const [isAuthenticated, setIsAuthenticated] = useState(null); @@ -127,6 +128,7 @@ const App = () => { } /> + } /> (0); const [value, setValue] = useState(0); @@ -118,7 +119,7 @@ export default function TopBar({ onRegister, username }: TopBarProps) { marginLeft: '1vw', }} > - {isLaunchPage && ( + {(isLaunchPage || isRegistrationPage) && ( )} - {!isLaunchPage && ( + {!isLaunchPage && !isRegistrationPage && !isLoginPage && ( onRegister && onRegister()} + onClick={() => navigate('/registration')} sx={{ width: '10em', height: '3em', diff --git a/src/renderer/pages/Registration.tsx b/src/renderer/pages/Registration.tsx new file mode 100644 index 0000000..d8d8bcf --- /dev/null +++ b/src/renderer/pages/Registration.tsx @@ -0,0 +1,3 @@ +export const Registration = () => { + return
Registration
; +}; From 212b58c072645e1b3d54e1844e2e8fcfd9a7eedb Mon Sep 17 00:00:00 2001 From: DIKER0K Date: Mon, 21 Jul 2025 10:55:55 +0500 Subject: [PATCH 2/7] add: registration page --- assets/icons/popa-popa.png | Bin 0 -> 6895 bytes assets/icons/popa-popa.svg | 18 ++ package-lock.json | 19 ++ package.json | 1 + src/renderer/api.ts | 60 +++++ src/renderer/pages/Registration.tsx | 375 +++++++++++++++++++++++++++- 6 files changed, 472 insertions(+), 1 deletion(-) create mode 100644 assets/icons/popa-popa.png create mode 100644 assets/icons/popa-popa.svg diff --git a/assets/icons/popa-popa.png b/assets/icons/popa-popa.png new file mode 100644 index 0000000000000000000000000000000000000000..6dd5b8c68942f01029892a3b9501114e71a4ac6e GIT binary patch literal 6895 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 literal 0 HcmV?d00001 diff --git a/assets/icons/popa-popa.svg b/assets/icons/popa-popa.svg new file mode 100644 index 0000000..6000dfc --- /dev/null +++ b/assets/icons/popa-popa.svg @@ -0,0 +1,18 @@ + + + + + + + + + + + + + + + + + + diff --git a/package-lock.json b/package-lock.json index 0ea2738..ad8cceb 100644 --- a/package-lock.json +++ b/package-lock.json @@ -23,6 +23,7 @@ "find-java-home": "^2.0.0", "https-browserify": "^1.0.0", "path-browserify": "^1.0.1", + "qr-code-styling": "^1.9.2", "react": "^19.0.0", "react-dom": "^19.0.0", "react-router-dom": "^7.3.0", @@ -18136,6 +18137,24 @@ ], "license": "MIT" }, + "node_modules/qr-code-styling": { + "version": "1.9.2", + "resolved": "https://registry.npmjs.org/qr-code-styling/-/qr-code-styling-1.9.2.tgz", + "integrity": "sha512-RgJaZJ1/RrXJ6N0j7a+pdw3zMBmzZU4VN2dtAZf8ZggCfRB5stEQ3IoDNGaNhYY3nnZKYlYSLl5YkfWN5dPutg==", + "license": "MIT", + "dependencies": { + "qrcode-generator": "^1.4.4" + }, + "engines": { + "node": ">=18.18.0" + } + }, + "node_modules/qrcode-generator": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/qrcode-generator/-/qrcode-generator-1.5.2.tgz", + "integrity": "sha512-pItrW0Z9HnDBnFmgiNrY1uxRdri32Uh9EjNYLPVC2zZ3ZRIIEqBoDgm4DkvDwNNDHTK7FNkmr8zAa77BYc9xNw==", + "license": "MIT" + }, "node_modules/qs": { "version": "6.13.0", "resolved": "https://registry.npmjs.org/qs/-/qs-6.13.0.tgz", diff --git a/package.json b/package.json index 8e687ee..42fd2e2 100644 --- a/package.json +++ b/package.json @@ -117,6 +117,7 @@ "find-java-home": "^2.0.0", "https-browserify": "^1.0.0", "path-browserify": "^1.0.1", + "qr-code-styling": "^1.9.2", "react": "^19.0.0", "react-dom": "^19.0.0", "react-router-dom": "^7.3.0", diff --git a/src/renderer/api.ts b/src/renderer/api.ts index a240ac3..1f2caee 100644 --- a/src/renderer/api.ts +++ b/src/renderer/api.ts @@ -169,6 +169,66 @@ export interface OperationsResponse { operations: MarketplaceOperation[]; } +export interface RegisterUserResponse { + status: string; + uuid: string; +} + +export interface GenerateVerificationCodeResponse { + status: string; + code: string; +} + +export interface VerificationStatusResponse { + is_verified: boolean; +} + +export async function getVerificationStatus( + username: string, +): Promise { + const response = await fetch( + `${API_BASE_URL}/auth/verification_status/${username}`, + ); + if (!response.ok) { + throw new Error('Не удалось получить статус верификации'); + } + return await response.json(); +} + +export async function generateVerificationCode( + username: string, +): Promise { + const response = await fetch( + `${API_BASE_URL}/auth/generate_code?username=${username}`, + { + method: 'POST', + }, + ); + if (!response.ok) { + throw new Error('Не удалось сгенерировать код верификации'); + } + return await response.json(); +} +export async function registerUser( + username: string, + password: string, +): Promise { + const response = await fetch(`${API_BASE_URL}/auth/register`, { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify({ + username, + password, + }), + }); + if (!response.ok) { + throw new Error('Не удалось зарегистрировать пользователя'); + } + return await response.json(); +} + export async function getPlayerInventory( request_id: string, ): Promise { diff --git a/src/renderer/pages/Registration.tsx b/src/renderer/pages/Registration.tsx index d8d8bcf..5e747fd 100644 --- a/src/renderer/pages/Registration.tsx +++ b/src/renderer/pages/Registration.tsx @@ -1,3 +1,376 @@ +import Stepper from '@mui/material/Stepper'; +import Step from '@mui/material/Step'; +import StepLabel from '@mui/material/StepLabel'; +import { useEffect, useRef, useState } from 'react'; +import { + StepConnector, + stepConnectorClasses, + StepIconProps, + styled, + Typography, + Box, + TextField, + Button, + Snackbar, + CircularProgress, +} from '@mui/material'; +import LoginRoundedIcon from '@mui/icons-material/LoginRounded'; +import VerifiedRoundedIcon from '@mui/icons-material/VerifiedRounded'; +import AssignmentIndRoundedIcon from '@mui/icons-material/AssignmentIndRounded'; +import { + generateVerificationCode, + registerUser, + getVerificationStatus, +} from '../api'; +import QRCodeStyling from 'qr-code-styling'; +import popalogo from '../../../assets/icons/popa-popa.svg'; + +const ColorlibConnector = styled(StepConnector)(({ theme }) => ({ + [`&.${stepConnectorClasses.alternativeLabel}`]: { + top: 22, + }, + [`&.${stepConnectorClasses.active}`]: { + [`& .${stepConnectorClasses.line}`]: { + backgroundImage: + 'linear-gradient( 95deg,rgb(242,113,33) 0%,rgb(233,64,87) 50%,rgb(138,35,135) 100%)', + }, + }, + [`&.${stepConnectorClasses.completed}`]: { + [`& .${stepConnectorClasses.line}`]: { + backgroundImage: + 'linear-gradient( 95deg,rgb(242,113,33) 0%,rgb(233,64,87) 50%,rgb(138,35,135) 100%)', + }, + }, + [`& .${stepConnectorClasses.line}`]: { + height: 3, + border: 0, + backgroundColor: '#eaeaf0', + borderRadius: 1, + ...theme.applyStyles('dark', { + backgroundColor: theme.palette.grey[800], + }), + }, +})); + +const ColorlibStepIconRoot = styled('div')<{ + ownerState: { completed?: boolean; active?: boolean }; +}>(({ theme }) => ({ + backgroundColor: '#ccc', + zIndex: 1, + color: '#fff', + width: 50, + height: 50, + display: 'flex', + borderRadius: '50%', + justifyContent: 'center', + alignItems: 'center', + ...theme.applyStyles('dark', { + backgroundColor: theme.palette.grey[700], + }), + variants: [ + { + props: ({ ownerState }) => ownerState.active, + style: { + backgroundImage: + 'linear-gradient( 136deg, rgb(242,113,33) 0%, rgb(233,64,87) 50%, rgb(138,35,135) 100%)', + boxShadow: '0 4px 10px 0 rgba(0,0,0,.25)', + }, + }, + { + props: ({ ownerState }) => ownerState.completed, + style: { + backgroundImage: + 'linear-gradient( 136deg, rgb(242,113,33) 0%, rgb(233,64,87) 50%, rgb(138,35,135) 100%)', + }, + }, + ], +})); + +function ColorlibStepIcon(props: StepIconProps) { + const { active, completed, className } = props; + + const icons: { [index: string]: React.ReactElement } = { + 1: , + 2: , + 3: , + }; + + return ( + + {icons[String(props.icon)]} + + ); +} + +const qrCode = new QRCodeStyling({ + width: 300, + height: 300, + // image: popalogo, + shape: 'square', + margin: 10, + dotsOptions: { + gradient: { + type: 'linear', + colorStops: [ + { + offset: 0, + color: 'rgb(242,113,33)', + }, + { + offset: 1, + color: 'rgb(233,64,87)', + }, + ], + }, + type: 'rounded', + }, + imageOptions: { + crossOrigin: 'anonymous', + margin: 20, + imageSize: 0.5, + }, + backgroundOptions: { + color: 'transparent', + }, +}); + export const Registration = () => { - return
Registration
; + const [activeStep, setActiveStep] = useState(0); + const [username, setUsername] = useState(''); + const [password, setPassword] = useState(''); + const [open, setOpen] = useState(false); + const [message, setMessage] = useState(''); + const [verificationCode, setVerificationCode] = useState(null); + const ref = useRef(null); + const [url, setUrl] = useState(''); + const steps = ['Создание аккаунта', 'Верификация аккаунта в телеграмме']; + + useEffect(() => { + if (ref.current) { + qrCode.append(ref.current); + } + }, []); + + useEffect(() => { + qrCode.update({ + data: url, + }); + }, [url]); + + const handleCreateAccount = async () => { + const response = await registerUser(username, password); + if (response.status === 'success') { + setActiveStep(1); + } else { + setOpen(true); + setMessage(response.status); + } + }; + + const handleClose = () => { + setOpen(false); + }; + + useEffect(() => { + if (activeStep === 1) { + handleGenerateVerificationCode(username); + setUrl(`https://t.me/popa_popa_popa_bot?start=${username}`); + + const intervalId = setInterval(() => { + handleVerifyCode(); + }, 5000); + + return () => { + clearInterval(intervalId); + }; + } + }, [activeStep]); + + const handleGenerateVerificationCode = async (username: string) => { + console.log(username); + const response = await generateVerificationCode(username); + setVerificationCode(response.code); + }; + + const handleVerifyCode = async () => { + const response = await getVerificationStatus(username); + if (response.is_verified) { + window.location.href = '/login'; + } + }; + + const handleOpenBot = () => { + window.open(`https://t.me/popa_popa_popa_bot?start=${username}`, '_blank'); + }; + + return ( + + } + > + {steps.map((label) => ( + + + {label} + + + ))} + + {activeStep === 0 && ( + + Создание аккаунта + Введите ваш никнейм + setUsername(e.target.value)} + sx={{ + width: '100%', + // '& .MuiFormLabel-root': { + // color: 'white', + // }, + '& .MuiInputBase-input': { + color: 'white', + }, + '& .MuiInput-underline:after': { + borderBottomColor: '#B2BAC2', + }, + '& .MuiOutlinedInput-root': { + '& fieldset': { + borderColor: '#E0E3E7', + color: 'white', + }, + '&:hover fieldset': { + borderColor: '#B2BAC2', + }, + '&.Mui-focused fieldset': { + borderColor: '#6F7E8C', + }, + }, + }} + /> + Введите ваш пароль + setPassword(e.target.value)} + sx={{ + width: '100%', + // '& .MuiFormLabel-root': { + // color: 'white', + // }, + '& .MuiInputBase-input': { + color: 'white', + }, + '& .MuiInput-underline:after': { + borderBottomColor: '#B2BAC2', + }, + '& .MuiOutlinedInput-root': { + '& fieldset': { + borderColor: '#E0E3E7', + color: 'white', + }, + '&:hover fieldset': { + borderColor: '#B2BAC2', + }, + '&.Mui-focused fieldset': { + borderColor: '#6F7E8C', + }, + }, + }} + /> + + + )} + {activeStep === 1 && ( + + Откройте бота в телеграмме + +
+ + Введите код верификации в боте + + {verificationCode ? ( + <> + + {verificationCode} + + Ждем ответа от бота + + + ) : ( + + )} + + )} + + + ); }; From 932d8675051fcc5505255619e300f97c712a6647 Mon Sep 17 00:00:00 2001 From: aurinex Date: Mon, 21 Jul 2025 15:17:21 +0500 Subject: [PATCH 3/7] paint buttons / minor change --- assets/images/heart.svg | 22 ++++++-- src/main/minecraft-launcher.ts | 2 +- src/renderer/components/CapeCard.tsx | 10 ++++ src/renderer/components/TopBar.tsx | 75 ++++++++++++++++++++++++++-- src/renderer/pages/Marketplace.tsx | 13 ++++- src/renderer/pages/Profile.tsx | 38 ++++++++++++-- src/renderer/pages/Shop.tsx | 9 ++-- 7 files changed, 150 insertions(+), 19 deletions(-) diff --git a/assets/images/heart.svg b/assets/images/heart.svg index 0262800..a450b1c 100644 --- a/assets/images/heart.svg +++ b/assets/images/heart.svg @@ -1,11 +1,23 @@ - - - + + + + + + + + + + + + diff --git a/src/main/minecraft-launcher.ts b/src/main/minecraft-launcher.ts index 2689dc9..d9e3ed7 100644 --- a/src/main/minecraft-launcher.ts +++ b/src/main/minecraft-launcher.ts @@ -281,7 +281,7 @@ export async function findJava(): Promise { }); // Предпочитаем Java 21 или 17 для совместимости с authlib-injector - const preferredVersions = [21, 17, 11]; + const preferredVersions = [24, 21, 17, 11]; for (const preferredVersion of preferredVersions) { const preferred = javaVersions.find( diff --git a/src/renderer/components/CapeCard.tsx b/src/renderer/components/CapeCard.tsx index 3b24527..d03dd3c 100644 --- a/src/renderer/components/CapeCard.tsx +++ b/src/renderer/components/CapeCard.tsx @@ -107,6 +107,16 @@ export default function CapeCard({ color={actionButton.color as 'primary' | 'success' | 'error'} onClick={() => onAction(capeId)} disabled={actionDisabled} + sx={{ + borderRadius: '20px', + p: '5px 25px', + color: 'white', + backgroundColor: 'rgb(0, 134, 0)', + '&:hover': { + backgroundColor: 'rgba(0, 134, 0, 0.5)', + }, + fontFamily: 'Benzin-Bold', + }} > {actionButton.text} diff --git a/src/renderer/components/TopBar.tsx b/src/renderer/components/TopBar.tsx index 8a3898f..3e93800 100644 --- a/src/renderer/components/TopBar.tsx +++ b/src/renderer/components/TopBar.tsx @@ -34,6 +34,7 @@ export default function TopBar({ onRegister, username }: TopBarProps) { const navigate = useNavigate(); const [coins, setCoins] = useState(0); const [value, setValue] = useState(0); + const [activePage, setActivePage] = useState('versions'); const handleChange = (event: React.SyntheticEvent, newValue: number) => { setValue(newValue); @@ -60,7 +61,18 @@ export default function TopBar({ onRegister, username }: TopBarProps) { return 'Запуск'; } if (isVersionsExplorerPage) { - return 'Версии'; + if (activePage === 'versions') { + return 'Версии'; + } + if (activePage === 'profile') { + return 'Профиль'; + } + if (activePage === 'shop') { + return 'Магазин'; + } + if (activePage === 'marketplace') { + return 'Рынок'; + } } return 'Неизвестная страница'; }; @@ -122,7 +134,6 @@ export default function TopBar({ onRegister, username }: TopBarProps) { {(isLaunchPage || isRegistrationPage) && ( )} {!isLaunchPage && !isRegistrationPage && !isLoginPage && ( - + { + setActivePage('versions'); + }} sx={{ color: 'white', fontFamily: 'Benzin-Bold', fontSize: '0.7em', + '&.Mui-selected': { + color: 'rgba(255, 77, 77, 1)', + }, + '&:hover': { + color: 'rgb(199, 199, 199)', + }, + transition: 'all 0.3s ease', }} /> { + setActivePage('profile'); + }} sx={{ color: 'white', fontFamily: 'Benzin-Bold', fontSize: '0.7em', + '&.Mui-selected': { + color: 'rgba(255, 77, 77, 1)', + }, + '&:hover': { + color: 'rgb(199, 199, 199)', + }, + transition: 'all 0.3s ease', }} /> { + setActivePage('shop'); + }} sx={{ color: 'white', fontFamily: 'Benzin-Bold', fontSize: '0.7em', + '&.Mui-selected': { + color: 'rgba(255, 77, 77, 1)', + }, + '&:hover': { + color: 'rgb(199, 199, 199)', + }, + transition: 'all 0.3s ease', }} /> { + setActivePage('marketplace'); + }} sx={{ color: 'white', fontFamily: 'Benzin-Bold', fontSize: '0.7em', + '&.Mui-selected': { + color: 'rgba(255, 77, 77, 1)', + }, + '&:hover': { + color: 'rgb(199, 199, 199)', + }, + transition: 'all 0.3s ease', }} /> @@ -193,7 +257,10 @@ export default function TopBar({ onRegister, username }: TopBarProps) { WebkitAppRegion: 'drag', }} > - + {getPageTitle()} diff --git a/src/renderer/pages/Marketplace.tsx b/src/renderer/pages/Marketplace.tsx index e3e6496..b9f4edc 100644 --- a/src/renderer/pages/Marketplace.tsx +++ b/src/renderer/pages/Marketplace.tsx @@ -221,9 +221,18 @@ export default function Marketplace() { diff --git a/src/renderer/pages/Profile.tsx b/src/renderer/pages/Profile.tsx index c176ed2..c505be7 100644 --- a/src/renderer/pages/Profile.tsx +++ b/src/renderer/pages/Profile.tsx @@ -167,7 +167,9 @@ export default function Profile() { display: 'flex', flexDirection: 'row', alignItems: 'center', - gap: 2, + gap: '100px', + width: '100%', + justifyContent: 'center', }} > {loading ? ( @@ -185,6 +187,20 @@ export default function Profile() { }} > {/* Используем переработанный компонент SkinViewer */} + + {username} + - + - Shop {loading ? ( Загрузка... ) : ( @@ -93,9 +94,11 @@ export default function Shop() { sx={{ display: 'flex', flexDirection: 'column', + flexWrap: 'wrap', + alignContent: 'flex-start', + width: '90%', + height: '80%', gap: '2vw', - justifyContent: 'center', - alignItems: 'center', }} > Доступные плащи From a2f42346ae97c7f477bdb5b4127d9fe8785a1a5c Mon Sep 17 00:00:00 2001 From: DIKER0K Date: Mon, 21 Jul 2025 17:02:26 +0500 Subject: [PATCH 4/7] fix: qrcode --- src/renderer/pages/Registration.tsx | 51 +++++++++++++++++++++++++++-- 1 file changed, 48 insertions(+), 3 deletions(-) diff --git a/src/renderer/pages/Registration.tsx b/src/renderer/pages/Registration.tsx index 5e747fd..20766bb 100644 --- a/src/renderer/pages/Registration.tsx +++ b/src/renderer/pages/Registration.tsx @@ -108,7 +108,8 @@ function ColorlibStepIcon(props: StepIconProps) { const qrCode = new QRCodeStyling({ width: 300, height: 300, - // image: popalogo, + image: popalogo, + data: 'https://t.me/popa_popa_popa_bot?start=test', shape: 'square', margin: 10, dotsOptions: { @@ -125,7 +126,7 @@ const qrCode = new QRCodeStyling({ }, ], }, - type: 'rounded', + type: 'extra-rounded', }, imageOptions: { crossOrigin: 'anonymous', @@ -179,6 +180,45 @@ export const Registration = () => { handleGenerateVerificationCode(username); setUrl(`https://t.me/popa_popa_popa_bot?start=${username}`); + while (ref.current.firstChild) { + ref.current.removeChild(ref.current.firstChild); + } + + const newQrCode = new QRCodeStyling({ + width: 300, + height: 300, + image: popalogo, + data: 'https://t.me/popa_popa_popa_bot?start=test', + shape: 'square', + margin: 10, + dotsOptions: { + gradient: { + type: 'linear', + colorStops: [ + { + offset: 0, + color: 'rgb(242,113,33)', + }, + { + offset: 1, + color: 'rgb(233,64,87)', + }, + ], + }, + type: 'extra-rounded', + }, + imageOptions: { + crossOrigin: 'anonymous', + margin: 20, + imageSize: 0.5, + }, + backgroundOptions: { + color: 'transparent', + }, + }); + + newQrCode.append(ref.current); + const intervalId = setInterval(() => { handleVerifyCode(); }, 5000); @@ -340,7 +380,12 @@ export const Registration = () => { > Открыть бота -
+
Введите код верификации в боте From d38faccf6f18380bd8af6040992ee330940a03e7 Mon Sep 17 00:00:00 2001 From: aurinex Date: Mon, 21 Jul 2025 17:07:49 +0500 Subject: [PATCH 5/7] fix design marketplace --- src/renderer/components/PlayerInventory.tsx | 41 +++++-- src/renderer/components/TopBar.tsx | 8 +- src/renderer/pages/Marketplace.tsx | 121 +++++++++++++++++--- 3 files changed, 139 insertions(+), 31 deletions(-) diff --git a/src/renderer/components/PlayerInventory.tsx b/src/renderer/components/PlayerInventory.tsx index dfafb73..4d7d34c 100644 --- a/src/renderer/components/PlayerInventory.tsx +++ b/src/renderer/components/PlayerInventory.tsx @@ -183,13 +183,13 @@ export default function PlayerInventory({ }; return ( - + @@ -199,6 +199,18 @@ export default function PlayerInventory({ variant="outlined" onClick={fetchPlayerInventory} disabled={loading} + sx={{ + borderRadius: '20px', + p: '10px 25px', + color: 'white', + borderColor: 'rgba(255, 77, 77, 1)', + '&:hover': { + backgroundColor: 'rgba(255, 77, 77, 1)', + borderColor: 'rgba(255, 77, 77, 1)', + }, + fontFamily: 'Benzin-Bold', + fontSize: '1vw', + }} > Обновить @@ -235,28 +247,33 @@ export default function PlayerInventory({ cursor: 'pointer', transition: 'transform 0.2s', '&:hover': { transform: 'scale(1.03)' }, + borderRadius: '1vw', }} onClick={() => handleOpenSellDialog(item)} > - - {getItemDisplayName(item.material)} - - - x{item.amount} - + + + {getItemDisplayName(item.material)} + + + {item.amount > 1 ? `x${item.amount}` : ''} + + {Object.keys(item.enchants || {}).length > 0 && ( { + switch (server.name) { + case 'Server minecraft.hub.popa-popa.ru': + return 'Хаб'; + case 'Server survival.hub.popa-popa.ru': + return 'Выживание'; + case 'Server minecraft.minigames.popa-popa.ru': + return 'Миниигры'; + default: + return server.name; + } + }; + // Функция для проверки онлайн-статуса игрока и определения сервера const checkPlayerStatus = async () => { if (!username) return; @@ -241,32 +254,81 @@ export default function Marketplace() { } return ( - - - Рынок сервера {playerServer?.name || ''} - + + + + Рынок сервера{' '} + + + {translateServer(playerServer || { name: '' })} + + {/* Вкладки */} - + - - + + {/* Содержимое вкладки "Товары" */} {marketLoading ? ( - + ) : !marketItems || marketItems.items.length === 0 ? ( - + На данный момент на рынке нет предметов. @@ -285,14 +358,21 @@ export default function Marketplace() { {marketItems.items.map((item) => ( - + handleBuyItem(item.id)} > Купить From aae4261b53d86b248d0fb6fc998951cbcfaf0e25 Mon Sep 17 00:00:00 2001 From: DIKER0K Date: Mon, 21 Jul 2025 17:11:54 +0500 Subject: [PATCH 6/7] fix: qrcode --- src/renderer/pages/Registration.tsx | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/renderer/pages/Registration.tsx b/src/renderer/pages/Registration.tsx index 20766bb..1c9f52d 100644 --- a/src/renderer/pages/Registration.tsx +++ b/src/renderer/pages/Registration.tsx @@ -217,6 +217,12 @@ export const Registration = () => { }, }); + newQrCode.update({ + data: `https://t.me/popa_popa_popa_bot?start=${username}`, + }); + + setUrl(`https://t.me/popa_popa_popa_bot?start=${username}`); + newQrCode.append(ref.current); const intervalId = setInterval(() => { From 30c25452dc2bb518dbed299f79e0a2f6105bc1b2 Mon Sep 17 00:00:00 2001 From: DIKER0K Date: Mon, 21 Jul 2025 17:13:55 +0500 Subject: [PATCH 7/7] feat: default steve skin --- src/renderer/components/SkinViewer.tsx | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/renderer/components/SkinViewer.tsx b/src/renderer/components/SkinViewer.tsx index e73bbed..89278be 100644 --- a/src/renderer/components/SkinViewer.tsx +++ b/src/renderer/components/SkinViewer.tsx @@ -33,7 +33,9 @@ export default function SkinViewer({ canvas: canvasRef.current, width, height, - skin: skinUrl || undefined, + skin: + skinUrl || + 'https://static.planetminecraft.com/files/resource_media/skin/original-steve-15053860.png', model: 'auto-detect', cape: capeUrl || undefined, });