From a3c9717f9ea17e83c04dd006be5addc6dd72a172 Mon Sep 17 00:00:00 2001 From: kazachilo Date: Thu, 20 Mar 2025 15:56:52 +0300 Subject: [PATCH] =?UTF-8?q?=D0=BB=D1=83=D1=87=D1=88=D0=B5=D0=BD=D0=B8?= =?UTF-8?q?=D1=8F=20=D0=B2=20=D0=BF=D1=80=D0=B8=D0=BB=D0=BE=D0=B6=D0=B5?= =?UTF-8?q?=D0=BD=D0=B8=D0=B8:=201.=20=D0=BE=D0=B1=D0=B0=D0=B2=D0=BB=D0=B5?= =?UTF-8?q?=D0=BD=D1=8B=20=D1=80=D0=B5=D0=B0=D0=BB=D1=8C=D0=BD=D1=8B=D0=B5?= =?UTF-8?q?=20=D1=81=D1=81=D1=8B=D0=BB=D0=BA=D0=B8=20=D0=BD=D0=B0=20=D0=BF?= =?UTF-8?q?=D0=BE=D0=BB=D0=B8=D1=82=D0=B8=D0=BA=D1=83=20=D0=BA=D0=BE=D0=BD?= =?UTF-8?q?=D1=84=D0=B8=D0=B4=D0=B5=D0=BD=D1=86=D0=B8=D0=B0=D0=BB=D1=8C?= =?UTF-8?q?=D0=BD=D0=BE=D1=81=D1=82=D0=B8=20=D0=B8=20=D0=BF=D0=BE=D0=BB?= =?UTF-8?q?=D1=8C=D0=B7=D0=BE=D0=B2=D0=B0=D1=82=D0=B5=D0=BB=D1=8C=D1=81?= =?UTF-8?q?=D0=BA=D0=BE=D0=B5=20=D1=81=D0=BE=D0=B3=D0=BB=D0=B0=D1=88=D0=B5?= =?UTF-8?q?=D0=BD=D0=B8=D0=B5=202.=20=D0=BB=D1=83=D1=87=D1=88=D0=B5=D0=BD?= =?UTF-8?q?=D0=B0=20=D0=BB=D0=BE=D0=B3=D0=B8=D0=BA=D0=B0=20=D0=BF=D1=80?= =?UTF-8?q?=D0=BE=D0=B2=D0=B5=D1=80=D0=BA=D0=B8=20=D0=BF=D0=B5=D1=80=D0=B5?= =?UTF-8?q?=D0=B4=20=D0=B3=D0=B5=D0=BD=D0=B5=D1=80=D0=B0=D1=86=D0=B8=D0=B5?= =?UTF-8?q?=D0=B9=20=D1=81=D1=82=D0=B8=D0=BA=D0=B5=D1=80=D0=BE=D0=B2:=20?= =?UTF-8?q?=D0=B4=D0=BE=D0=B1=D0=B0=D0=B2=D0=BB=D0=B5=D0=BD=D1=8B=20=D0=BF?= =?UTF-8?q?=D1=80=D0=BE=D0=B2=D0=B5=D1=80=D0=BA=D0=B8=20=D0=B2=D1=8B=D0=B1?= =?UTF-8?q?=D0=BE=D1=80=D0=B0=20=D0=BF=D1=80=D0=B5=D1=81=D0=B5=D1=82=D0=B0?= =?UTF-8?q?=20=D0=B8=20=D0=B2=D0=B2=D0=BE=D0=B4=D0=B0=20=D1=82=D0=B5=D0=BA?= =?UTF-8?q?=D1=81=D1=82=D0=B0,=20=D0=B7=D0=B0=D0=BF=D1=80=D0=B5=D1=82=20?= =?UTF-8?q?=D0=BD=D0=B0=20=D0=BF=D0=BE=D0=B2=D1=82=D0=BE=D1=80=D0=BD=D1=83?= =?UTF-8?q?=D1=8E=20=D0=B3=D0=B5=D0=BD=D0=B5=D1=80=D0=B0=D1=86=D0=B8=D1=8E?= =?UTF-8?q?=20=D0=BE=D0=B4=D0=BD=D0=BE=D0=B9=20=D0=B8=20=D1=82=D0=BE=D0=B9?= =?UTF-8?q?=20=D0=B6=D0=B5=20=D0=BA=D0=BE=D0=BC=D0=B1=D0=B8=D0=BD=D0=B0?= =?UTF-8?q?=D1=86=D0=B8=D0=B8=20=D0=BF=D0=B0=D1=80=D0=B0=D0=BC=D0=B5=D1=82?= =?UTF-8?q?=D1=80=D0=BE=D0=B2=20=D0=BF=D0=BE=D0=B4=D1=80=D1=8F=D0=B4,=20?= =?UTF-8?q?=D0=BE=D1=82=D0=BB=D0=B0=D0=B4=D0=BE=D1=87=D0=BD=D0=BE=D0=B5=20?= =?UTF-8?q?=D0=BB=D0=BE=D0=B3=D0=B8=D1=80=D0=BE=D0=B2=D0=B0=D0=BD=D0=B8?= =?UTF-8?q?=D0=B5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- API_DOCUMENTATION.md | 263 +++++++----------- src/assets/index.ts | 4 +- src/assets/token_ico.png | Bin 0 -> 27402 bytes .../blocks/ScrollableButtonsBlock.module.css | 5 +- src/components/blocks/SquareButton.module.css | 6 +- src/components/layout/Header.module.css | 9 + src/components/layout/Header.tsx | 5 +- src/constants/baseWorkflow.ts | 2 +- src/screens/Home.tsx | 78 +++++- src/screens/onboarding/TermsAndConditions.tsx | 18 +- src/services/stickerService.ts | 6 +- workflow_stickerV1_base64_ws.json | 2 +- 12 files changed, 222 insertions(+), 176 deletions(-) create mode 100644 src/assets/token_ico.png diff --git a/API_DOCUMENTATION.md b/API_DOCUMENTATION.md index e0ee309..10cb3fb 100644 --- a/API_DOCUMENTATION.md +++ b/API_DOCUMENTATION.md @@ -4,7 +4,7 @@ API предоставляет функциональность для работы со стикерами в Telegram, включая генерацию изображений, создание стикерпаков и управление ими. Также API поддерживает отслеживание позиций задач в очереди. -Базовый URL: `http://localhost:8001` +Базовый URL: `https://stickerserver.gymnasticstuff.uk` ## Эндпоинты @@ -14,11 +14,9 @@ API предоставляет функциональность для рабо Проверяет работоспособность API. -**Ответ:** -```json -{ - "status": "ok" -} +**Ответ (200 OK):** +``` +"string" ``` ### Управление пользователями @@ -54,7 +52,7 @@ API предоставляет функциональность для рабо ``` **Ошибки:** -- 400 Bad Request: Пользователь с таким chat_id уже существует +- 422 Validation Error: Ошибка валидации данных #### GET /users/{user_id} @@ -75,6 +73,7 @@ API предоставляет функциональность для рабо **Ошибки:** - 404 Not Found: Пользователь не найден +- 422 Validation Error: Ошибка валидации данных ### Генерация изображений и управление очередью @@ -85,32 +84,26 @@ API предоставляет функциональность для рабо **Тело запроса:** ```json { + "tag": "image_generation", "user_id": 123456789, "workflow": { // Объект workflow для ComfyUI - }, - "tag": "image_generation" + } } ``` **Параметры:** +- `tag` (string, обязательный): Тег для типа задачи (допустимое значение: "image_generation") - `user_id` (integer, обязательный): ID пользователя - `workflow` (object, обязательный): Объект workflow для ComfyUI -- `tag` (string, обязательный): Тег для типа задачи (допустимое значение: "image_generation") **Ответ (200 OK):** -```json -{ - "message": "Ваше изображение генерируется, пожалуйста подождите, готовое изображение будет у вас в галереи", - "Task_ID": "123", - "queue_position": 5 -} +``` +"string" ``` **Ошибки:** -- 400 Bad Request: Недопустимый тег -- 404 Not Found: Пользователь не найден -- 500 Internal Server Error: Ошибка при создании задачи или отправке сообщения +- 422 Validation Error: Ошибка валидации данных #### GET /user_pending_tasks/{user_id} @@ -120,30 +113,12 @@ API предоставляет функциональность для рабо - `user_id` (integer, обязательный): ID пользователя **Ответ (200 OK):** -```json -[ - { - "task_id": 123, - "prompt_id": "prompt_id_from_comfyui", - "status": "PENDING", - "created_at": "2025-03-13T11:15:00", - "queue_position": 3, - "updated_at": "2025-03-13T11:20:00" - }, - { - "task_id": 124, - "prompt_id": "prompt_id_from_comfyui_2", - "status": "STARTED", - "created_at": "2025-03-13T11:10:00", - "queue_position": null, - "updated_at": "2025-03-13T11:20:00" - } -] +``` +"string" ``` **Ошибки:** -- 404 Not Found: Пользователь не найден -- 500 Internal Server Error: Внутренняя ошибка сервера +- 422 Validation Error: Ошибка валидации данных #### GET /task_position/{task_id} @@ -153,17 +128,12 @@ API предоставляет функциональность для рабо - `task_id` (integer, обязательный): ID задачи **Ответ (200 OK):** -```json -{ - "task_id": 123, - "status": "PENDING", - "queue_position": 3 -} +``` +"string" ``` **Ошибки:** -- 404 Not Found: Задача не найдена -- 500 Internal Server Error: Внутренняя ошибка сервера +- 422 Validation Error: Ошибка валидации данных #### GET /images_links/{user_id} @@ -188,6 +158,7 @@ API предоставляет функциональность для рабо **Ошибки:** - 404 Not Found: Пользователь не найден +- 422 Validation Error: Ошибка валидации данных ### Управление стикерами @@ -209,13 +180,11 @@ API предоставляет функциональность для рабо **Ответ (200 OK):** ```json -{ - "file_id": "file_id_from_telegram" -} +{} ``` **Ошибки:** -- 500 Internal Server Error: Ошибка при загрузке файла на сервер Telegram +- 422 Validation Error: Ошибка валидации данных #### POST /create_sticker_set @@ -244,15 +213,12 @@ API предоставляет функциональность для рабо - `is_video` (boolean, опциональный, по умолчанию false): Флаг видео-стикера **Ответ (200 OK):** -```json -{ - "message": "Новый набор стикеров успешно создан!", - "name": "example_set_by_bot_name" -} +``` +"string" ``` **Ошибки:** -- 500 Internal Server Error: Ошибка при создании набора стикеров +- 422 Validation Error: Ошибка валидации данных #### POST /add_sticker_to_set @@ -263,6 +229,7 @@ API предоставляет функциональность для рабо { "user_id": 123456789, "sticker_set_name": "example_set", + "title": "Example Sticker Set", "file_id": "file_id_from_telegram", "emojis": "😀", "is_animated": false, @@ -273,20 +240,19 @@ API предоставляет функциональность для рабо **Параметры:** - `user_id` (integer, обязательный): ID пользователя - `sticker_set_name` (string, обязательный): Название набора стикеров (без суффикса _by_bot) +- `title` (string, обязательный): Заголовок набора стикеров - `file_id` (string, обязательный): File_id загруженного стикера - `emojis` (string, обязательный): Список эмодзи для стикера - `is_animated` (boolean, опциональный, по умолчанию false): Флаг анимированного стикера - `is_video` (boolean, опциональный, по умолчанию false): Флаг видео-стикера **Ответ (200 OK):** -```json -{ - "message": "Стикер успешно добавлен в набор!" -} +``` +"string" ``` **Ошибки:** -- 500 Internal Server Error: Ошибка при добавлении стикера в набор +- 422 Validation Error: Ошибка валидации данных #### GET /check_sticker_set_name/{sticker_set_name} @@ -296,14 +262,12 @@ API предоставляет функциональность для рабо - `sticker_set_name` (string, обязательный): Название набора стикеров **Ответ (200 OK):** -```json -{ - "exists": true -} +``` +"string" ``` **Ошибки:** -- 500 Internal Server Error: Ошибка при проверке существования набора стикеров +- 422 Validation Error: Ошибка валидации данных #### POST /delete_sticker_from_set @@ -320,14 +284,12 @@ API предоставляет функциональность для рабо - `file_id` (string, обязательный): File_id стикера **Ответ (200 OK):** -```json -{ - "message": "Стикер успешно удален из набора!" -} +``` +"string" ``` **Ошибки:** -- 500 Internal Server Error: Ошибка при удалении стикера из набора +- 422 Validation Error: Ошибка валидации данных #### POST /set_sticker_position_in_set @@ -336,24 +298,22 @@ API предоставляет функциональность для рабо **Тело запроса:** ```json { - "sticker_file_id": "file_id_from_telegram", + "file_id": "file_id_from_telegram", "position": 0 } ``` **Параметры:** -- `sticker_file_id` (string, обязательный): File_id стикера +- `file_id` (string, обязательный): File_id стикера - `position` (integer, обязательный): Новая позиция стикера (0 - первая позиция) **Ответ (200 OK):** -```json -{ - "message": "Позиция стикера успешно изменена!" -} +``` +"string" ``` **Ошибки:** -- 500 Internal Server Error: Ошибка при изменении позиции стикера +- 422 Validation Error: Ошибка валидации данных #### POST /delete_sticker_set @@ -370,14 +330,12 @@ API предоставляет функциональность для рабо - `sticker_set_name` (string, обязательный): Полное название набора стикеров (включая суффикс _by_bot) **Ответ (200 OK):** -```json -{ - "message": "Набор стикеров успешно удален!" -} +``` +"string" ``` **Ошибки:** -- 500 Internal Server Error: Ошибка при удалении набора стикеров +- 422 Validation Error: Ошибка валидации данных #### POST /create_sticker_set_db @@ -405,9 +363,7 @@ API предоставляет функциональность для рабо ``` **Ошибки:** -- 404 Not Found: Пользователь не найден -- 400 Bad Request: Ошибка валидации -- 500 Internal Server Error: Внутренняя ошибка сервера +- 422 Validation Error: Ошибка валидации данных #### GET /user_sticker_sets/{user_id} @@ -428,8 +384,7 @@ API предоставляет функциональность для рабо ``` **Ошибки:** -- 404 Not Found: Пользователь не найден -- 500 Internal Server Error: Внутренняя ошибка сервера +- 422 Validation Error: Ошибка валидации данных ### Прокси для Telegram API @@ -442,23 +397,12 @@ API предоставляет функциональность для рабо **Ответ (200 OK):** ```json -{ - "name": "example_set_by_bot_name", - "title": "Example Sticker Set", - "sticker_type": "regular", - "thumbnail_url": "http://localhost:8001/stickers/proxy/sticker/file_id_from_telegram", - "share_url": "https://t.me/addstickers/example_set_by_bot_name", - "stickers": [ - { - "file_id": "file_id_from_telegram", - "emoji": "😀", - "position": 0, - "file_url": "http://localhost:8001/stickers/proxy/sticker/file_id_from_telegram" - } - ] -} +{} ``` +**Ошибки:** +- 422 Validation Error: Ошибка валидации данных + #### GET /stickers/proxy/sticker/{file_id} Прокси для получения изображения стикера без раскрытия токена бота. @@ -467,14 +411,12 @@ API предоставляет функциональность для рабо - `file_id` (string, обязательный): File ID стикера **Ответ (200 OK):** -Изображение стикера в формате WebP с заголовками: -- Content-Type: image/webp -- Content-Disposition: inline -- Cache-Control: public, max-age=86400 +``` +"string" +``` **Ошибки:** -- 404 Not Found: Стикер не найден -- 500 Internal Server Error: Ошибка при получении стикера +- 422 Validation Error: Ошибка валидации данных #### POST /stickers/test/upload @@ -485,67 +427,63 @@ API предоставляет функциональность для рабо - `image_url` (string, обязательный): URL изображения для загрузки **Ответ (200 OK):** -```json -{ - "success": true, - "file_id": "file_id_from_telegram", - "file_url": "http://localhost:8001/stickers/proxy/sticker/file_id_from_telegram" -} +``` +"string" ``` **Ошибки:** -- 500 Internal Server Error: Ошибка при загрузке изображения +- 422 Validation Error: Ошибка валидации данных ## Модели данных ### UserBase ```json { - "user_id": 123456789, - "username": "example_user", + "user_id": 1, + "username": "john_doe", "chat_id": 123456789, - "balance": 0 + "balance": 100 } ``` ### UserCreate ```json { - "user_id": 123456789, - "username": "example_user", + "user_id": 1, + "username": "john_doe", "chat_id": 123456789, - "balance": 0 + "balance": 100 } ``` ### ImageBase ```json { - "id": 1, - "link": "file_id_from_telegram", - "prompt_id": "prompt_id_from_comfyui", - "status": "COMPLETED", - "created_at": "2025-03-12T12:00:00", - "sticker_set_id": null + "id": 0, + "link": "string", + "prompt_id": "string", + "status": "string", + "created_at": "2025-03-19T12:15:53.248Z", + "sticker_set_id": 0 } ``` ### StickerUploadRequest ```json { - "user_id": 123456789, - "link": "https://example.com/image.png" + "user_id": 0, + "link": "string" } ``` ### StickerSetRequest ```json { - "user_id": 123456789, - "sticker_set_name": "example_set", - "title": "Example Sticker Set", - "file_id": "file_id_from_telegram", - "emojis": "😀", + "user_id": 0, + "sticker_set_name": "string", + "title": "string", + "file_id": "string", + "emojis": "string", "is_animated": false, "is_video": false } @@ -554,14 +492,14 @@ API предоставляет функциональность для рабо ### StickerFileID ```json { - "file_id": "file_id_from_telegram" + "file_id": "string" } ``` ### StickerSetPosition ```json { - "sticker_file_id": "file_id_from_telegram", + "file_id": "string", "position": 0 } ``` @@ -569,7 +507,7 @@ API предоставляет функциональность для рабо ### StickerSetName ```json { - "sticker_set_name": "example_set_by_bot_name" + "sticker_set_name": "string" } ``` @@ -577,46 +515,51 @@ API предоставляет функциональность для рабо ```json { "tag": "image_generation", - "user_id": 123456789, - "workflow": { - // Объект workflow для ComfyUI - } + "user_id": 0, + "workflow": {} } ``` ### CreateStickerSetDBRequest ```json { - "user_id": 123456789, - "sticker_set_name": "example_set_by_bot_name" + "user_id": 0, + "sticker_set_name": "string" } ``` ### StickerSetResponse ```json { - "id": 1, - "set_name": "example_set_by_bot_name", - "user_id": 123456789 + "id": 0, + "set_name": "string", + "user_id": 0 } ``` -### TaskPosition +### HTTPValidationError ```json { - "task_id": 123, - "status": "PENDING", - "queue_position": 3 + "detail": [ + { + "loc": [ + "string", + 0 + ], + "msg": "string", + "type": "string" + } + ] } ``` -### PendingTask +### ValidationError ```json { - "task_id": 123, - "prompt_id": "prompt_id_from_comfyui", - "status": "PENDING", - "created_at": "2025-03-13T11:15:00", - "queue_position": 3, - "updated_at": "2025-03-13T11:20:00" + "loc": [ + "string", + 0 + ], + "msg": "string", + "type": "string" } diff --git a/src/assets/index.ts b/src/assets/index.ts index 76ebd76..c6366b0 100644 --- a/src/assets/index.ts +++ b/src/assets/index.ts @@ -32,6 +32,7 @@ import umbrella from './umbrella250x.png'; import defaultAvatar from './default-avatar.svg'; import shieldIcon from './shield-icon.png'; import reactLogo from './react.svg'; +import tokenIcon from './token_ico.png'; export const images = { ahareBot, @@ -67,5 +68,6 @@ export const images = { umbrella, defaultAvatar, shieldIcon, - reactLogo + reactLogo, + tokenIcon }; diff --git a/src/assets/token_ico.png b/src/assets/token_ico.png new file mode 100644 index 0000000000000000000000000000000000000000..4213c5eacc98b7c5897fdeeb57bf415700aea54d GIT binary patch literal 27402 zcmcG!byOTr*Di_&4;I|r-JQWLz~B~i7~BTe;K75tySqCC4<6hl5Zod7<@bH>``)we zI``b~pF3;1ySjVVQ%~)^Yj;)e4p;pwi-t^y3P~S^h|sxDELt;4ILL9WhFr~2Rl|1a|crptB0NAyYzcCF%L%*GaHZ# zxhV*2WiLW`-qAxzZe=b)sm-IzuIwlYvb2)(at5h;ebzAZvN01drxX(<7xoZ*2e1RV zn2>we+1f({Jwzz~3s>;H{Lf`JO7i~_aj_Ahl=!DXavfz=a!Chg5V-&=2a6dyJ104x z0ILaynK=ii1v5D(J0~|A2gm!Lg+oA)onMffm;7Hp%J=4+%`F6hQZoN)?EOrH($dAn zQIL(z-QAtlor~4M8O+8ZARxfT&dJ8f$?`720`atWG4Wurhfw_+K?(#hbGCAHv2w5{ z{|C{;)WOw7gz}y0fA_)8@jtNkkbmjvU1Mw>CXQ?ztnB~v>ED9N%Kv9kJG=i#LtLcY z-dp(>-~TNzM8ne�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 literal 0 HcmV?d00001 diff --git a/src/components/blocks/ScrollableButtonsBlock.module.css b/src/components/blocks/ScrollableButtonsBlock.module.css index c815067..9a710f6 100644 --- a/src/components/blocks/ScrollableButtonsBlock.module.css +++ b/src/components/blocks/ScrollableButtonsBlock.module.css @@ -1,6 +1,6 @@ .container { width: 100%; - overflow: hidden; + overflow: visible; position: relative; margin: 0 calc(-1 * var(--spacing-medium)); padding: var(--spacing-medium); @@ -16,6 +16,7 @@ -ms-overflow-style: none; /* IE and Edge */ scroll-snap-type: x mandatory; gap: calc(var(--spacing-medium) * 0.75); + padding-left: 3px; /* Отступ для обводки первых кнопок */ padding-bottom: var(--spacing-small); /* Для градиента */ padding-right: var(--spacing-medium); /* Отступ для последнего элемента */ margin-right: calc(-1 * var(--spacing-medium)); /* Компенсация отступа контейнера */ @@ -32,7 +33,7 @@ display: flex; align-items: center; justify-content: center; - width: 120px; /* Фиксированная ширина для кнопок */ + width: 120px; /* Уменьшенная ширина для кнопок */ } /* Добавляем градиент-индикатор скролла справа */ diff --git a/src/components/blocks/SquareButton.module.css b/src/components/blocks/SquareButton.module.css index 78acde3..7e52aa7 100644 --- a/src/components/blocks/SquareButton.module.css +++ b/src/components/blocks/SquareButton.module.css @@ -35,7 +35,6 @@ .selected { border-color: var(--color-primary); border-width: 3px; /* Увеличиваем толщину с 2px до 3px */ - transform: translateY(-2px); /* Добавляем эффект приподнятия */ box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1); /* Добавляем тень как при hover */ } @@ -51,7 +50,6 @@ border-color: var(--color-primary); border-width: 3px; box-shadow: 0 0 0 3px var(--color-primary), 0 4px 12px rgba(0, 0, 0, 0.1); - transform: translateY(-2px); } } @@ -61,9 +59,9 @@ background-position: center; } -/* Предотвращаем двойное приподнятие при наведении на выбранную кнопку */ +/* Стиль для наведения на выбранную кнопку */ .selected:hover { - transform: translateY(-2px); /* Оставляем то же приподнятие */ + transform: none; /* Убираем эффект приподнятия */ } .button:active { diff --git a/src/components/layout/Header.module.css b/src/components/layout/Header.module.css index 9376cde..ef0108f 100644 --- a/src/components/layout/Header.module.css +++ b/src/components/layout/Header.module.css @@ -102,6 +102,15 @@ .balanceIcon { font-size: 1.25rem; color: var(--color-primary); + display: flex; + align-items: center; + justify-content: center; +} + +.tokenImage { + width: 20px; + height: 20px; + object-fit: contain; } .balanceValue { diff --git a/src/components/layout/Header.tsx b/src/components/layout/Header.tsx index 352869d..baaf734 100644 --- a/src/components/layout/Header.tsx +++ b/src/components/layout/Header.tsx @@ -2,6 +2,7 @@ import React, { useState, useEffect } from 'react'; import { Link } from 'react-router-dom'; import { MOCK_USER } from '../../constants/mock'; import { getUserInfo, isTelegramWebAppAvailable } from '../../constants/user'; +import { images } from '../../assets'; import styles from './Header.module.css'; const Header: React.FC = () => { @@ -50,7 +51,9 @@ const Header: React.FC = () => { onClick={() => alert('Пополнить баланс')} title="Нажмите чтобы пополнить баланс" > - 💎 + + Токены + {user.balance} diff --git a/src/constants/baseWorkflow.ts b/src/constants/baseWorkflow.ts index 38085aa..5190c82 100644 --- a/src/constants/baseWorkflow.ts +++ b/src/constants/baseWorkflow.ts @@ -1,7 +1,7 @@ export const baseWorkflow = { "305": { "inputs": { - "ckpt_name": "SDXL\\dreamshaperXL_lightningDPMSDE.safetensors" + "ckpt_name": "dreamshaperXL_lightningDPMSDE.safetensors" }, "class_type": "CheckpointLoaderSimple", "_meta": { diff --git a/src/screens/Home.tsx b/src/screens/Home.tsx index 8197d0d..89c2dbc 100644 --- a/src/screens/Home.tsx +++ b/src/screens/Home.tsx @@ -8,6 +8,14 @@ import { stylePresets } from '../config/stylePresets'; import apiService from '../services/api'; import NotificationModal from '../components/shared/NotificationModal'; +// Интерфейс для хранения данных о последней генерации +interface LastGenerationData { + imageData?: string; + style?: string; + presetId?: string; + customPrompt?: string; +} + const Home: React.FC = () => { const navigate = useNavigate(); @@ -35,6 +43,9 @@ const Home: React.FC = () => { const [isLoading, setIsLoading] = useState(false); const [promptText, setPromptText] = useState(''); + // Состояние для хранения данных о последней успешной генерации + const [lastGenerationData, setLastGenerationData] = useState({}); + // Обработчики для модального окна const handleGalleryClick = useCallback(() => { setIsNotificationVisible(false); @@ -63,8 +74,63 @@ const Home: React.FC = () => { if (actionType === 'function') { if (actionValue === 'startGeneration') { + // Проверка наличия изображения if (!imageData) { - alert('Сначала загрузите изображение'); + setNotificationTitle('Внимание'); + setNotificationMessage('Сначала загрузите изображение'); + setIsLoading(false); + setIsNotificationVisible(true); + return; + } + + // Проверка выбора пресета промпта + if (!selectedPresetId) { + setNotificationTitle('Внимание'); + setNotificationMessage('Выберите образ для генерации'); + setIsLoading(false); + setIsNotificationVisible(true); + return; + } + + // Проверка ввода текста, если выбран "Свой промпт" + if (selectedPresetId === 'customPrompt' && !customPrompt.trim()) { + setNotificationTitle('Внимание'); + setNotificationMessage('Введите текст промпта'); + setIsLoading(false); + setIsNotificationVisible(true); + return; + } + + // Добавляем логирование для отладки + console.log('Comparing generations:', { + current: { + imageDataLength: imageData?.length, + style: selectedStyle, + presetId: selectedPresetId, + customPrompt + }, + last: { + imageDataLength: lastGenerationData.imageData?.length, + style: lastGenerationData.style, + presetId: lastGenerationData.presetId, + customPrompt: lastGenerationData.customPrompt + } + }); + + // Проверка на повторную генерацию той же комбинации + const isSameGeneration = + lastGenerationData.imageData === imageData && + lastGenerationData.style === selectedStyle && + lastGenerationData.presetId === selectedPresetId && + (selectedPresetId !== 'customPrompt' || lastGenerationData.customPrompt === customPrompt); + + console.log('Is same generation:', isSameGeneration); + + if (isSameGeneration) { + setNotificationTitle('Внимание'); + setNotificationMessage('Нельзя отправить одну и ту же комбинацию изображения и образа подряд. Пожалуйста, измените изображение или выберите другой образ.'); + setIsLoading(false); + setIsNotificationVisible(true); return; } @@ -83,6 +149,14 @@ const Home: React.FC = () => { const response = await apiService.generateImage(imageData, selectedStyle, selectedPresetId, userPrompt); console.log('Generation response:', response); + // Сохраняем данные о текущей генерации + setLastGenerationData({ + imageData, + style: selectedStyle, + presetId: selectedPresetId, + customPrompt: userPrompt + }); + // Проверяем, была ли ошибка перевода if (response.translationFailed) { setNotificationTitle('Недопустимый промпт'); @@ -157,7 +231,7 @@ const Home: React.FC = () => { // Если выбрана любая другая кнопка, скрываем поле ввода setIsInputVisible(false); - }, [navigate, imageData, selectedStyle, selectedPresetId, customPrompt]); + }, [navigate, imageData, selectedStyle, selectedPresetId, customPrompt, lastGenerationData]); // Эффект для обновления window.history.state при загрузке из localStorage useEffect(() => { diff --git a/src/screens/onboarding/TermsAndConditions.tsx b/src/screens/onboarding/TermsAndConditions.tsx index 7fde93f..16c9d63 100644 --- a/src/screens/onboarding/TermsAndConditions.tsx +++ b/src/screens/onboarding/TermsAndConditions.tsx @@ -34,8 +34,22 @@ const TermsAndConditions: React.FC = () => {

diff --git a/src/services/stickerService.ts b/src/services/stickerService.ts index cebf262..d9a883f 100644 --- a/src/services/stickerService.ts +++ b/src/services/stickerService.ts @@ -90,7 +90,8 @@ export class StickerService { file_id: firstSticker, emojis: firstEmoji, is_animated: false, - is_video: false + is_video: false, + format: "static" // Добавляем поле format для соответствия требованиям API }; // Логируем данные запроса @@ -203,7 +204,8 @@ export class StickerService { file_id: fileId, emojis: emoji, is_animated: false, - is_video: false + is_video: false, + format: "static" // Добавляем поле format для соответствия требованиям API }; // Логируем данные запроса diff --git a/workflow_stickerV1_base64_ws.json b/workflow_stickerV1_base64_ws.json index 7cb0d27..5b7d5ac 100644 --- a/workflow_stickerV1_base64_ws.json +++ b/workflow_stickerV1_base64_ws.json @@ -1,7 +1,7 @@ { "305": { "inputs": { - "ckpt_name": "SDXL\\dreamshaperXL_lightningDPMSDE.safetensors" + "ckpt_name": "dreamshaperXL_lightningDPMSDE.safetensors" }, "class_type": "CheckpointLoaderSimple", "_meta": {