Рекомендуемая оперативная память
diff --git a/src/shared/api/contracts/profiles/ProfileBaseEntity.ts b/src/shared/api/contracts/profiles/ProfileBaseEntity.ts
index 1f04e82..6afa5bb 100644
--- a/src/shared/api/contracts/profiles/ProfileBaseEntity.ts
+++ b/src/shared/api/contracts/profiles/ProfileBaseEntity.ts
@@ -1,5 +1,7 @@
import { EntityState } from '@/shared/enums';
import { PlayerBaseEntity } from '@/shared/api/contracts';
+import { ProfileJavaVendor } from '@/shared/enums/profile-java-vendor';
+import { JavaMajorVersion } from '@/shared/enums/java-major-version';
export type ProfileBaseEntity = {
name: string;
@@ -32,6 +34,8 @@ export type ProfileExtendedBaseEntity = {
gameArguments: string;
hasUpdate: boolean;
isEnabled: boolean;
+ profileJavaVendor: ProfileJavaVendor;
+ javaMajorVersion: JavaMajorVersion;
state: EntityState;
loader: number;
files: ProfileFileBaseEntity[];
diff --git a/src/shared/api/contracts/profiles/zod.ts b/src/shared/api/contracts/profiles/zod.ts
index 66b2700..b3ed52b 100644
--- a/src/shared/api/contracts/profiles/zod.ts
+++ b/src/shared/api/contracts/profiles/zod.ts
@@ -1,37 +1,40 @@
import { z } from 'zod';
+import { ProfileJavaVendor } from '@/shared/enums/profile-java-vendor';
+import { JavaMajorVersion } from '@/shared/enums/java-major-version';
+
export const ModDetailsEntitySchema = z.object({
title: z
- .string()
- .min(2, { message: 'Название мода должно быть больше 2 символов' })
- .max(100, { message: 'Название мода не должно быть больше 100 символов' }),
+ .string()
+ .min(2, { message: 'Название мода должно быть больше 2 символов' })
+ .max(100, { message: 'Название мода не должно быть больше 100 символов' }),
description: z
- .string()
- .min(2, { message: 'Описание мода должно быть больше 2 символов' })
- .max(1000, { message: 'Описание мода не должно быть больше 1000 символов' }),
+ .string()
+ .min(2, { message: 'Описание мода должно быть больше 2 символов' })
+ .max(1000, { message: 'Описание мода не должно быть больше 1000 символов' }),
});
export const CreateProfileSchema = z.object({
name: z
- .string()
- .min(1, { message: 'Обязательное поле' })
- .regex(/^[a-zA-Z0-9-]*$/, {
- message: 'Название профиля может содержать только английские буквы, цифры и тире',
- })
- .min(2, { message: 'Длина имени должна быть от 2 до 100 символов' })
- .max(100, { message: 'Длина имени должна быть от 2 до 100 символов' }),
+ .string()
+ .min(1, { message: 'Обязательное поле' })
+ .regex(/^[a-zA-Z0-9-]*$/, {
+ message: 'Название профиля может содержать только английские буквы, цифры и тире',
+ })
+ .min(2, { message: 'Длина имени должна быть от 2 до 100 символов' })
+ .max(100, { message: 'Длина имени должна быть от 2 до 100 символов' }),
displayName: z
- .string()
- .min(1, { message: 'Обязательное поле' })
- .min(2, { message: 'Длина имени должна быть больше 2 символов' })
- .max(100, { message: 'Длина имени не должна быть больше 100 символов' }),
+ .string()
+ .min(1, { message: 'Обязательное поле' })
+ .min(2, { message: 'Длина имени должна быть больше 2 символов' })
+ .max(100, { message: 'Длина имени не должна быть больше 100 символов' }),
description: z
- .string()
- .min(1, { message: 'Обязательное поле' })
- .min(2, { message: 'Длина описания должна быть больше 2 символов' })
- .max(1000, {
- message: 'Длина описания не должна быть больше 1000 символов',
- }),
+ .string()
+ .min(1, { message: 'Обязательное поле' })
+ .min(2, { message: 'Длина описания должна быть больше 2 символов' })
+ .max(1000, {
+ message: 'Длина описания не должна быть больше 1000 символов',
+ }),
version: z.string({
errorMap: () => ({
message: 'Не выбрана версия игры',
@@ -44,22 +47,24 @@ export const CreateProfileSchema = z.object({
export const EditProfileSchema = z.object({
name: z
- .string()
- .min(2, { message: 'Длина имени должна быть больше 2 символов' })
- .max(100, { message: 'Длина имени не должна быть больше 100 символов' }),
+ .string()
+ .min(2, { message: 'Длина имени должна быть больше 2 символов' })
+ .max(100, { message: 'Длина имени не должна быть больше 100 символов' }),
displayName: z
- .string()
- .min(2, { message: 'Длина имени должна быть больше 2 символов' })
- .max(100, { message: 'Длина имени не должна быть больше 100 символов' }),
+ .string()
+ .min(2, { message: 'Длина имени должна быть больше 2 символов' })
+ .max(100, { message: 'Длина имени не должна быть больше 100 символов' }),
description: z
- .string()
- .min(2, { message: 'Длина описания должна быть больше 2 символов' })
- .max(255, {
- message: 'Длина описания не должна быть больше 255 символов',
- }),
+ .string()
+ .min(2, { message: 'Длина описания должна быть больше 2 символов' })
+ .max(255, {
+ message: 'Длина описания не должна быть больше 255 символов',
+ }),
jvmArguments: z.string().optional(),
gameArguments: z.string().optional(),
priority: z.coerce.number().optional(),
+ profileJavaVendor: z.nativeEnum(ProfileJavaVendor).optional(),
+ javaMajorVersion: z.union([z.nativeEnum(JavaMajorVersion), z.literal('0')]).optional(),
recommendedRam: z.coerce.number().default(50).optional(),
icon: z.any(),
isEnabled: z.boolean().default(true).optional(),
diff --git a/src/shared/enums/entity-state.ts b/src/shared/enums/entity-state.ts
index 859be47..471d4b6 100644
--- a/src/shared/enums/entity-state.ts
+++ b/src/shared/enums/entity-state.ts
@@ -5,7 +5,8 @@ export enum EntityState {
ENTITY_STATE_INITIALIZE = 3, // Подготовка профиля
ENTITY_STATE_ERROR = 4, // Ошибка при работе с профилем
ENTITY_STATE_NEED_COMPILE = 5, // Необходима сборка профиля
- ENTITY_STATE_PACKING = 6, // Необходима сборка профиля
+ ENTITY_STATE_PACKING = 6, // Сборка профиля
+ ENTITY_STATE_NEED_DOWNLOAD = 7, // Упаковывается
ENTITY_STATE_DISABLED = 99999, // Профиль выключен
}
@@ -18,5 +19,6 @@ export enum EntityStateOption {
'OPTION_4' = 'Ошибка', // Ошибка при работе с профилем
'OPTION_5' = 'Необходима сборка', // Необходима сборка профиля
'OPTION_6' = 'Сборка', // Сборка профиля
+ 'OPTION_7' = 'Необходимо дозагрузить', // Сборка профиля
'OPTION_99999' = 'Недоступен', // Профиль выключен
}
diff --git a/src/shared/enums/java-major-version.ts b/src/shared/enums/java-major-version.ts
new file mode 100644
index 0000000..efb3ba9
--- /dev/null
+++ b/src/shared/enums/java-major-version.ts
@@ -0,0 +1,10 @@
+import { ValueOf } from '@/shared/lib/helpers';
+
+export type JavaMajorVersion = ValueOf
;
+export const JavaMajorVersion = {
+ VERSION_8: '8',
+ VERSION_11: '11',
+ VERSION_17: '17',
+ VERSION_21: '21',
+ VERSION_25: '25',
+} as const;
diff --git a/src/shared/enums/profile-java-vendor.ts b/src/shared/enums/profile-java-vendor.ts
new file mode 100644
index 0000000..a88070f
--- /dev/null
+++ b/src/shared/enums/profile-java-vendor.ts
@@ -0,0 +1,7 @@
+import { ValueOf } from '@/shared/lib/helpers';
+
+export type ProfileJavaVendor = ValueOf;
+export const ProfileJavaVendor = {
+ DEFAULT: 0,
+ AZUL: 1,
+} as const;
diff --git a/src/shared/ui/select.tsx b/src/shared/ui/select.tsx
index 765a1e0..409c8b4 100644
--- a/src/shared/ui/select.tsx
+++ b/src/shared/ui/select.tsx
@@ -1,152 +1,174 @@
'use client';
-
-import { ComponentPropsWithoutRef, ElementRef, forwardRef } from 'react';
+import * as React from 'react';
import * as SelectPrimitive from '@radix-ui/react-select';
-import { Check, ChevronDown, ChevronUp } from 'lucide-react';
+import { CheckIcon, ChevronDownIcon, ChevronUpIcon } from 'lucide-react';
import { cn } from '@/shared/lib/utils';
-const Select = SelectPrimitive.Root;
-const SelectGroup = SelectPrimitive.Group;
-const SelectValue = SelectPrimitive.Value;
-
-const SelectTrigger = forwardRef<
- ElementRef,
- ComponentPropsWithoutRef
->(({ className, children, ...props }, ref) => (
- span]:line-clamp-1',
- className,
- )}
- {...props}
- >
- {children}
-
-
-
-
-));
-SelectTrigger.displayName = SelectPrimitive.Trigger.displayName;
+function Select({ ...props }: React.ComponentProps) {
+ return ;
+}
-const SelectScrollUpButton = forwardRef<
- ElementRef,
- ComponentPropsWithoutRef
->(({ className, ...props }, ref) => (
-
-
-
-));
-SelectScrollUpButton.displayName = SelectPrimitive.ScrollUpButton.displayName;
+function SelectGroup({ ...props }: React.ComponentProps) {
+ return ;
+}
-const SelectScrollDownButton = forwardRef<
- ElementRef,
- ComponentPropsWithoutRef
->(({ className, ...props }, ref) => (
-
-
-
-));
-SelectScrollDownButton.displayName = SelectPrimitive.ScrollDownButton.displayName;
+function SelectValue({ ...props }: React.ComponentProps) {
+ return ;
+}
-const SelectContent = forwardRef<
- ElementRef,
- ComponentPropsWithoutRef
->(({ className, children, position = 'popper', ...props }, ref) => (
-
- & {
+ size?: 'sm' | 'default';
+}) {
+ return (
+
-
-
+
+
+
+ );
+}
+
+function SelectContent({
+ className,
+ children,
+ position = 'item-aligned',
+ align = 'center',
+ ...props
+}: React.ComponentProps) {
+ return (
+
+
- {children}
-
-
-
-
-));
-SelectContent.displayName = SelectPrimitive.Content.displayName;
+
+
+ {children}
+
+
+
+
+ );
+}
-const SelectLabel = forwardRef<
- ElementRef,
- ComponentPropsWithoutRef
->(({ className, ...props }, ref) => (
-
-));
-SelectLabel.displayName = SelectPrimitive.Label.displayName;
+function SelectLabel({ className, ...props }: React.ComponentProps) {
+ return (
+
+ );
+}
-const SelectItem = forwardRef<
- ElementRef,
- ComponentPropsWithoutRef
->(({ className, children, ...props }, ref) => (
-
-
-
-
-
-
-
- {children}
-
-
-));
-SelectItem.displayName = SelectPrimitive.Item.displayName;
+function SelectItem({
+ className,
+ children,
+ ...props
+}: React.ComponentProps) {
+ return (
+
+
+
+
+
+
+ {children}
+
+ );
+}
-const SelectSeparator = forwardRef<
- ElementRef,
- ComponentPropsWithoutRef
->(({ className, ...props }, ref) => (
-
-));
-SelectSeparator.displayName = SelectPrimitive.Separator.displayName;
+function SelectSeparator({
+ className,
+ ...props
+}: React.ComponentProps) {
+ return (
+
+ );
+}
+
+function SelectScrollUpButton({
+ className,
+ ...props
+}: React.ComponentProps) {
+ return (
+
+
+
+ );
+}
+
+function SelectScrollDownButton({
+ className,
+ ...props
+}: React.ComponentProps) {
+ return (
+
+
+
+ );
+}
export {
Select,
- SelectGroup,
- SelectValue,
- SelectTrigger,
SelectContent,
- SelectLabel,
+ SelectGroup,
SelectItem,
- SelectSeparator,
- SelectScrollUpButton,
+ SelectLabel,
SelectScrollDownButton,
+ SelectScrollUpButton,
+ SelectSeparator,
+ SelectTrigger,
+ SelectValue,
};
diff --git a/src/widgets/client-hub/ui/ClientState.tsx b/src/widgets/client-hub/ui/ClientState.tsx
index 5bd45d4..e87d840 100644
--- a/src/widgets/client-hub/ui/ClientState.tsx
+++ b/src/widgets/client-hub/ui/ClientState.tsx
@@ -15,6 +15,7 @@ const stateColorMap: Record = {
[EntityState.ENTITY_STATE_ERROR]: 'bg-red-500',
[EntityState.ENTITY_STATE_NEED_COMPILE]: 'bg-blue-500',
[EntityState.ENTITY_STATE_PACKING]: 'bg-orange-500',
+ [EntityState.ENTITY_STATE_NEED_DOWNLOAD]: 'bg-blue-500',
};
export function ClientState({ state }: ClientStateProps) {
diff --git a/src/widgets/client-hub/ui/DownloadClientHub.tsx b/src/widgets/client-hub/ui/DownloadClientHub.tsx
index 20c34a8..78e78e7 100644
--- a/src/widgets/client-hub/ui/DownloadClientHub.tsx
+++ b/src/widgets/client-hub/ui/DownloadClientHub.tsx
@@ -3,20 +3,21 @@
import React, { useEffect, useRef, useState } from 'react';
import { Ubuntu_Mono } from 'next/font/google';
import { SubmitHandler, useForm } from 'react-hook-form';
-import { ArrowBigDownDash, ChevronsUpDown, Package2Icon } from 'lucide-react';
+import { ArrowBigDownDash, Package2Icon } from 'lucide-react';
import { useConnectionHub } from '../lib/useConnectionHub';
-import { JavaVersionBaseEntity, ProfileExtendedBaseEntity, RestoreProfileSchemaType, } from '@/shared/api/contracts';
+import {
+ JavaVersionBaseEntity,
+ ProfileExtendedBaseEntity,
+ RestoreProfileSchemaType,
+} from '@/shared/api/contracts';
import { cn } from '@/shared/lib/utils';
import { Button } from '@/shared/ui/button';
import { Progress } from '@/shared/ui/progress';
import { Textarea } from '@/shared/ui/textarea';
import { Icons } from '@/shared/ui/icons';
-import { Form, FormControl, FormField, FormItem, FormLabel, FormMessage } from '@/shared/ui/form';
-import { Command, CommandEmpty, CommandGroup, CommandInput, CommandItem, CommandList, } from '@/shared/ui/command';
-import { Separator } from '@/shared/ui/separator';
-import { Popover, PopoverContent, PopoverTrigger } from '@/shared/ui/popover';
+import { Form } from '@/shared/ui/form';
interface DownloadClientHubProps {
profile?: ProfileExtendedBaseEntity;
@@ -76,8 +77,7 @@ export function DownloadClientHub(props: DownloadClientHubProps) {
Управление
{!isConnected && Подключение к консоли...}
-
+
-
+
Шаг второй
@@ -196,8 +118,8 @@ export function DownloadClientHub(props: DownloadClientHubProps) {
onClick={onBuildDistributive}
disabled={!isConnected || isDisable || !props.profile || !props.profile.hasUpdate}
>
- {isDisable && }
-
+ {isDisable && }
+
Собрать
@@ -239,8 +161,8 @@ export function DownloadClientHub(props: DownloadClientHubProps) {
Общий прогресс: {percentAllStages}%
diff --git a/src/widgets/game-mods/ui/GameMods.tsx b/src/widgets/game-mods/ui/GameMods.tsx
index 5a639db..c685d13 100644
--- a/src/widgets/game-mods/ui/GameMods.tsx
+++ b/src/widgets/game-mods/ui/GameMods.tsx
@@ -15,7 +15,7 @@ import { Button } from '@/shared/ui/button';
import { EntityState, ModType } from '@/shared/enums';
import { Card, CardContent, CardHeader } from '@/shared/ui/card';
import { GameModItem } from '@/widgets/game-mods/ui/GameModItem';
-import { useProfileCardStore } from "@/entities/ProfileCard/lib/store";
+import { useProfileCardStore } from '@/entities/ProfileCard/lib/store';
interface GameServersParams {
profile: ProfileExtendedBaseEntity;
@@ -64,6 +64,7 @@ export const GameMods = ({ profile }: GameServersParams) => {
EntityState.ENTITY_STATE_ERROR,
EntityState.ENTITY_STATE_PACKING,
EntityState.ENTITY_STATE_DISABLED,
+ EntityState.ENTITY_STATE_NEED_DOWNLOAD,
].includes(state || EntityState.ENTITY_STATE_ACTIVE);
const removeMod = async (fileName: string) => {
@@ -101,7 +102,7 @@ export const GameMods = ({ profile }: GameServersParams) => {