лучшения в приложении: 1. обавлены реальные ссылки на политику конфиденциальности и пользовательское соглашение 2. лучшена логика проверки перед генерацией стикеров: добавлены проверки выбора пресета и ввода текста, запрет на повторную генерацию одной и той же комбинации параметров подряд, отладочное логирование

This commit is contained in:
kazachilo 2025-03-20 15:56:52 +03:00
parent 0e586e693a
commit a3c9717f9e
12 changed files with 222 additions and 176 deletions

View File

@ -4,7 +4,7 @@
API предоставляет функциональность для работы со стикерами в Telegram, включая генерацию изображений, создание стикерпаков и управление ими. Также API поддерживает отслеживание позиций задач в очереди. API предоставляет функциональность для работы со стикерами в Telegram, включая генерацию изображений, создание стикерпаков и управление ими. Также API поддерживает отслеживание позиций задач в очереди.
Базовый URL: `http://localhost:8001` Базовый URL: `https://stickerserver.gymnasticstuff.uk`
## Эндпоинты ## Эндпоинты
@ -14,11 +14,9 @@ API предоставляет функциональность для рабо
Проверяет работоспособность API. Проверяет работоспособность API.
**Ответ:** **Ответ (200 OK):**
```json ```
{ "string"
"status": "ok"
}
``` ```
### Управление пользователями ### Управление пользователями
@ -54,7 +52,7 @@ API предоставляет функциональность для рабо
``` ```
**Ошибки:** **Ошибки:**
- 400 Bad Request: Пользователь с таким chat_id уже существует - 422 Validation Error: Ошибка валидации данных
#### GET /users/{user_id} #### GET /users/{user_id}
@ -75,6 +73,7 @@ API предоставляет функциональность для рабо
**Ошибки:** **Ошибки:**
- 404 Not Found: Пользователь не найден - 404 Not Found: Пользователь не найден
- 422 Validation Error: Ошибка валидации данных
### Генерация изображений и управление очередью ### Генерация изображений и управление очередью
@ -85,32 +84,26 @@ API предоставляет функциональность для рабо
**Тело запроса:** **Тело запроса:**
```json ```json
{ {
"tag": "image_generation",
"user_id": 123456789, "user_id": 123456789,
"workflow": { "workflow": {
// Объект workflow для ComfyUI // Объект workflow для ComfyUI
}, }
"tag": "image_generation"
} }
``` ```
**Параметры:** **Параметры:**
- `tag` (string, обязательный): Тег для типа задачи (допустимое значение: "image_generation")
- `user_id` (integer, обязательный): ID пользователя - `user_id` (integer, обязательный): ID пользователя
- `workflow` (object, обязательный): Объект workflow для ComfyUI - `workflow` (object, обязательный): Объект workflow для ComfyUI
- `tag` (string, обязательный): Тег для типа задачи (допустимое значение: "image_generation")
**Ответ (200 OK):** **Ответ (200 OK):**
```json ```
{ "string"
"message": "Ваше изображение генерируется, пожалуйста подождите, готовое изображение будет у вас в галереи",
"Task_ID": "123",
"queue_position": 5
}
``` ```
**Ошибки:** **Ошибки:**
- 400 Bad Request: Недопустимый тег - 422 Validation Error: Ошибка валидации данных
- 404 Not Found: Пользователь не найден
- 500 Internal Server Error: Ошибка при создании задачи или отправке сообщения
#### GET /user_pending_tasks/{user_id} #### GET /user_pending_tasks/{user_id}
@ -120,30 +113,12 @@ API предоставляет функциональность для рабо
- `user_id` (integer, обязательный): ID пользователя - `user_id` (integer, обязательный): ID пользователя
**Ответ (200 OK):** **Ответ (200 OK):**
```json ```
[ "string"
{
"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"
}
]
``` ```
**Ошибки:** **Ошибки:**
- 404 Not Found: Пользователь не найден - 422 Validation Error: Ошибка валидации данных
- 500 Internal Server Error: Внутренняя ошибка сервера
#### GET /task_position/{task_id} #### GET /task_position/{task_id}
@ -153,17 +128,12 @@ API предоставляет функциональность для рабо
- `task_id` (integer, обязательный): ID задачи - `task_id` (integer, обязательный): ID задачи
**Ответ (200 OK):** **Ответ (200 OK):**
```json ```
{ "string"
"task_id": 123,
"status": "PENDING",
"queue_position": 3
}
``` ```
**Ошибки:** **Ошибки:**
- 404 Not Found: Задача не найдена - 422 Validation Error: Ошибка валидации данных
- 500 Internal Server Error: Внутренняя ошибка сервера
#### GET /images_links/{user_id} #### GET /images_links/{user_id}
@ -188,6 +158,7 @@ API предоставляет функциональность для рабо
**Ошибки:** **Ошибки:**
- 404 Not Found: Пользователь не найден - 404 Not Found: Пользователь не найден
- 422 Validation Error: Ошибка валидации данных
### Управление стикерами ### Управление стикерами
@ -209,13 +180,11 @@ API предоставляет функциональность для рабо
**Ответ (200 OK):** **Ответ (200 OK):**
```json ```json
{ {}
"file_id": "file_id_from_telegram"
}
``` ```
**Ошибки:** **Ошибки:**
- 500 Internal Server Error: Ошибка при загрузке файла на сервер Telegram - 422 Validation Error: Ошибка валидации данных
#### POST /create_sticker_set #### POST /create_sticker_set
@ -244,15 +213,12 @@ API предоставляет функциональность для рабо
- `is_video` (boolean, опциональный, по умолчанию false): Флаг видео-стикера - `is_video` (boolean, опциональный, по умолчанию false): Флаг видео-стикера
**Ответ (200 OK):** **Ответ (200 OK):**
```json ```
{ "string"
"message": "Новый набор стикеров успешно создан!",
"name": "example_set_by_bot_name"
}
``` ```
**Ошибки:** **Ошибки:**
- 500 Internal Server Error: Ошибка при создании набора стикеров - 422 Validation Error: Ошибка валидации данных
#### POST /add_sticker_to_set #### POST /add_sticker_to_set
@ -263,6 +229,7 @@ API предоставляет функциональность для рабо
{ {
"user_id": 123456789, "user_id": 123456789,
"sticker_set_name": "example_set", "sticker_set_name": "example_set",
"title": "Example Sticker Set",
"file_id": "file_id_from_telegram", "file_id": "file_id_from_telegram",
"emojis": "😀", "emojis": "😀",
"is_animated": false, "is_animated": false,
@ -273,20 +240,19 @@ API предоставляет функциональность для рабо
**Параметры:** **Параметры:**
- `user_id` (integer, обязательный): ID пользователя - `user_id` (integer, обязательный): ID пользователя
- `sticker_set_name` (string, обязательный): Название набора стикеров (без суффикса _by_bot) - `sticker_set_name` (string, обязательный): Название набора стикеров (без суффикса _by_bot)
- `title` (string, обязательный): Заголовок набора стикеров
- `file_id` (string, обязательный): File_id загруженного стикера - `file_id` (string, обязательный): File_id загруженного стикера
- `emojis` (string, обязательный): Список эмодзи для стикера - `emojis` (string, обязательный): Список эмодзи для стикера
- `is_animated` (boolean, опциональный, по умолчанию false): Флаг анимированного стикера - `is_animated` (boolean, опциональный, по умолчанию false): Флаг анимированного стикера
- `is_video` (boolean, опциональный, по умолчанию false): Флаг видео-стикера - `is_video` (boolean, опциональный, по умолчанию false): Флаг видео-стикера
**Ответ (200 OK):** **Ответ (200 OK):**
```json ```
{ "string"
"message": "Стикер успешно добавлен в набор!"
}
``` ```
**Ошибки:** **Ошибки:**
- 500 Internal Server Error: Ошибка при добавлении стикера в набор - 422 Validation Error: Ошибка валидации данных
#### GET /check_sticker_set_name/{sticker_set_name} #### GET /check_sticker_set_name/{sticker_set_name}
@ -296,14 +262,12 @@ API предоставляет функциональность для рабо
- `sticker_set_name` (string, обязательный): Название набора стикеров - `sticker_set_name` (string, обязательный): Название набора стикеров
**Ответ (200 OK):** **Ответ (200 OK):**
```json ```
{ "string"
"exists": true
}
``` ```
**Ошибки:** **Ошибки:**
- 500 Internal Server Error: Ошибка при проверке существования набора стикеров - 422 Validation Error: Ошибка валидации данных
#### POST /delete_sticker_from_set #### POST /delete_sticker_from_set
@ -320,14 +284,12 @@ API предоставляет функциональность для рабо
- `file_id` (string, обязательный): File_id стикера - `file_id` (string, обязательный): File_id стикера
**Ответ (200 OK):** **Ответ (200 OK):**
```json ```
{ "string"
"message": "Стикер успешно удален из набора!"
}
``` ```
**Ошибки:** **Ошибки:**
- 500 Internal Server Error: Ошибка при удалении стикера из набора - 422 Validation Error: Ошибка валидации данных
#### POST /set_sticker_position_in_set #### POST /set_sticker_position_in_set
@ -336,24 +298,22 @@ API предоставляет функциональность для рабо
**Тело запроса:** **Тело запроса:**
```json ```json
{ {
"sticker_file_id": "file_id_from_telegram", "file_id": "file_id_from_telegram",
"position": 0 "position": 0
} }
``` ```
**Параметры:** **Параметры:**
- `sticker_file_id` (string, обязательный): File_id стикера - `file_id` (string, обязательный): File_id стикера
- `position` (integer, обязательный): Новая позиция стикера (0 - первая позиция) - `position` (integer, обязательный): Новая позиция стикера (0 - первая позиция)
**Ответ (200 OK):** **Ответ (200 OK):**
```json ```
{ "string"
"message": "Позиция стикера успешно изменена!"
}
``` ```
**Ошибки:** **Ошибки:**
- 500 Internal Server Error: Ошибка при изменении позиции стикера - 422 Validation Error: Ошибка валидации данных
#### POST /delete_sticker_set #### POST /delete_sticker_set
@ -370,14 +330,12 @@ API предоставляет функциональность для рабо
- `sticker_set_name` (string, обязательный): Полное название набора стикеров (включая суффикс _by_bot) - `sticker_set_name` (string, обязательный): Полное название набора стикеров (включая суффикс _by_bot)
**Ответ (200 OK):** **Ответ (200 OK):**
```json ```
{ "string"
"message": "Набор стикеров успешно удален!"
}
``` ```
**Ошибки:** **Ошибки:**
- 500 Internal Server Error: Ошибка при удалении набора стикеров - 422 Validation Error: Ошибка валидации данных
#### POST /create_sticker_set_db #### POST /create_sticker_set_db
@ -405,9 +363,7 @@ API предоставляет функциональность для рабо
``` ```
**Ошибки:** **Ошибки:**
- 404 Not Found: Пользователь не найден - 422 Validation Error: Ошибка валидации данных
- 400 Bad Request: Ошибка валидации
- 500 Internal Server Error: Внутренняя ошибка сервера
#### GET /user_sticker_sets/{user_id} #### GET /user_sticker_sets/{user_id}
@ -428,8 +384,7 @@ API предоставляет функциональность для рабо
``` ```
**Ошибки:** **Ошибки:**
- 404 Not Found: Пользователь не найден - 422 Validation Error: Ошибка валидации данных
- 500 Internal Server Error: Внутренняя ошибка сервера
### Прокси для Telegram API ### Прокси для Telegram API
@ -442,23 +397,12 @@ API предоставляет функциональность для рабо
**Ответ (200 OK):** **Ответ (200 OK):**
```json ```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} #### GET /stickers/proxy/sticker/{file_id}
Прокси для получения изображения стикера без раскрытия токена бота. Прокси для получения изображения стикера без раскрытия токена бота.
@ -467,14 +411,12 @@ API предоставляет функциональность для рабо
- `file_id` (string, обязательный): File ID стикера - `file_id` (string, обязательный): File ID стикера
**Ответ (200 OK):** **Ответ (200 OK):**
Изображение стикера в формате WebP с заголовками: ```
- Content-Type: image/webp "string"
- Content-Disposition: inline ```
- Cache-Control: public, max-age=86400
**Ошибки:** **Ошибки:**
- 404 Not Found: Стикер не найден - 422 Validation Error: Ошибка валидации данных
- 500 Internal Server Error: Ошибка при получении стикера
#### POST /stickers/test/upload #### POST /stickers/test/upload
@ -485,67 +427,63 @@ API предоставляет функциональность для рабо
- `image_url` (string, обязательный): URL изображения для загрузки - `image_url` (string, обязательный): URL изображения для загрузки
**Ответ (200 OK):** **Ответ (200 OK):**
```json ```
{ "string"
"success": true,
"file_id": "file_id_from_telegram",
"file_url": "http://localhost:8001/stickers/proxy/sticker/file_id_from_telegram"
}
``` ```
**Ошибки:** **Ошибки:**
- 500 Internal Server Error: Ошибка при загрузке изображения - 422 Validation Error: Ошибка валидации данных
## Модели данных ## Модели данных
### UserBase ### UserBase
```json ```json
{ {
"user_id": 123456789, "user_id": 1,
"username": "example_user", "username": "john_doe",
"chat_id": 123456789, "chat_id": 123456789,
"balance": 0 "balance": 100
} }
``` ```
### UserCreate ### UserCreate
```json ```json
{ {
"user_id": 123456789, "user_id": 1,
"username": "example_user", "username": "john_doe",
"chat_id": 123456789, "chat_id": 123456789,
"balance": 0 "balance": 100
} }
``` ```
### ImageBase ### ImageBase
```json ```json
{ {
"id": 1, "id": 0,
"link": "file_id_from_telegram", "link": "string",
"prompt_id": "prompt_id_from_comfyui", "prompt_id": "string",
"status": "COMPLETED", "status": "string",
"created_at": "2025-03-12T12:00:00", "created_at": "2025-03-19T12:15:53.248Z",
"sticker_set_id": null "sticker_set_id": 0
} }
``` ```
### StickerUploadRequest ### StickerUploadRequest
```json ```json
{ {
"user_id": 123456789, "user_id": 0,
"link": "https://example.com/image.png" "link": "string"
} }
``` ```
### StickerSetRequest ### StickerSetRequest
```json ```json
{ {
"user_id": 123456789, "user_id": 0,
"sticker_set_name": "example_set", "sticker_set_name": "string",
"title": "Example Sticker Set", "title": "string",
"file_id": "file_id_from_telegram", "file_id": "string",
"emojis": "😀", "emojis": "string",
"is_animated": false, "is_animated": false,
"is_video": false "is_video": false
} }
@ -554,14 +492,14 @@ API предоставляет функциональность для рабо
### StickerFileID ### StickerFileID
```json ```json
{ {
"file_id": "file_id_from_telegram" "file_id": "string"
} }
``` ```
### StickerSetPosition ### StickerSetPosition
```json ```json
{ {
"sticker_file_id": "file_id_from_telegram", "file_id": "string",
"position": 0 "position": 0
} }
``` ```
@ -569,7 +507,7 @@ API предоставляет функциональность для рабо
### StickerSetName ### StickerSetName
```json ```json
{ {
"sticker_set_name": "example_set_by_bot_name" "sticker_set_name": "string"
} }
``` ```
@ -577,46 +515,51 @@ API предоставляет функциональность для рабо
```json ```json
{ {
"tag": "image_generation", "tag": "image_generation",
"user_id": 123456789, "user_id": 0,
"workflow": { "workflow": {}
// Объект workflow для ComfyUI
}
} }
``` ```
### CreateStickerSetDBRequest ### CreateStickerSetDBRequest
```json ```json
{ {
"user_id": 123456789, "user_id": 0,
"sticker_set_name": "example_set_by_bot_name" "sticker_set_name": "string"
} }
``` ```
### StickerSetResponse ### StickerSetResponse
```json ```json
{ {
"id": 1, "id": 0,
"set_name": "example_set_by_bot_name", "set_name": "string",
"user_id": 123456789 "user_id": 0
} }
``` ```
### TaskPosition ### HTTPValidationError
```json ```json
{ {
"task_id": 123, "detail": [
"status": "PENDING", {
"queue_position": 3 "loc": [
"string",
0
],
"msg": "string",
"type": "string"
}
]
} }
``` ```
### PendingTask ### ValidationError
```json ```json
{ {
"task_id": 123, "loc": [
"prompt_id": "prompt_id_from_comfyui", "string",
"status": "PENDING", 0
"created_at": "2025-03-13T11:15:00", ],
"queue_position": 3, "msg": "string",
"updated_at": "2025-03-13T11:20:00" "type": "string"
} }

View File

@ -32,6 +32,7 @@ import umbrella from './umbrella250x.png';
import defaultAvatar from './default-avatar.svg'; import defaultAvatar from './default-avatar.svg';
import shieldIcon from './shield-icon.png'; import shieldIcon from './shield-icon.png';
import reactLogo from './react.svg'; import reactLogo from './react.svg';
import tokenIcon from './token_ico.png';
export const images = { export const images = {
ahareBot, ahareBot,
@ -67,5 +68,6 @@ export const images = {
umbrella, umbrella,
defaultAvatar, defaultAvatar,
shieldIcon, shieldIcon,
reactLogo reactLogo,
tokenIcon
}; };

BIN
src/assets/token_ico.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 27 KiB

View File

@ -1,6 +1,6 @@
.container { .container {
width: 100%; width: 100%;
overflow: hidden; overflow: visible;
position: relative; position: relative;
margin: 0 calc(-1 * var(--spacing-medium)); margin: 0 calc(-1 * var(--spacing-medium));
padding: var(--spacing-medium); padding: var(--spacing-medium);
@ -16,6 +16,7 @@
-ms-overflow-style: none; /* IE and Edge */ -ms-overflow-style: none; /* IE and Edge */
scroll-snap-type: x mandatory; scroll-snap-type: x mandatory;
gap: calc(var(--spacing-medium) * 0.75); gap: calc(var(--spacing-medium) * 0.75);
padding-left: 3px; /* Отступ для обводки первых кнопок */
padding-bottom: var(--spacing-small); /* Для градиента */ padding-bottom: var(--spacing-small); /* Для градиента */
padding-right: var(--spacing-medium); /* Отступ для последнего элемента */ padding-right: var(--spacing-medium); /* Отступ для последнего элемента */
margin-right: calc(-1 * var(--spacing-medium)); /* Компенсация отступа контейнера */ margin-right: calc(-1 * var(--spacing-medium)); /* Компенсация отступа контейнера */
@ -32,7 +33,7 @@
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: center; justify-content: center;
width: 120px; /* Фиксированная ширина для кнопок */ width: 120px; /* Уменьшенная ширина для кнопок */
} }
/* Добавляем градиент-индикатор скролла справа */ /* Добавляем градиент-индикатор скролла справа */

View File

@ -35,7 +35,6 @@
.selected { .selected {
border-color: var(--color-primary); border-color: var(--color-primary);
border-width: 3px; /* Увеличиваем толщину с 2px до 3px */ border-width: 3px; /* Увеличиваем толщину с 2px до 3px */
transform: translateY(-2px); /* Добавляем эффект приподнятия */
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1); /* Добавляем тень как при hover */ box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1); /* Добавляем тень как при hover */
} }
@ -51,7 +50,6 @@
border-color: var(--color-primary); border-color: var(--color-primary);
border-width: 3px; border-width: 3px;
box-shadow: 0 0 0 3px var(--color-primary), 0 4px 12px rgba(0, 0, 0, 0.1); 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; background-position: center;
} }
/* Предотвращаем двойное приподнятие при наведении на выбранную кнопку */ /* Стиль для наведения на выбранную кнопку */
.selected:hover { .selected:hover {
transform: translateY(-2px); /* Оставляем то же приподнятие */ transform: none; /* Убираем эффект приподнятия */
} }
.button:active { .button:active {

View File

@ -102,6 +102,15 @@
.balanceIcon { .balanceIcon {
font-size: 1.25rem; font-size: 1.25rem;
color: var(--color-primary); color: var(--color-primary);
display: flex;
align-items: center;
justify-content: center;
}
.tokenImage {
width: 20px;
height: 20px;
object-fit: contain;
} }
.balanceValue { .balanceValue {

View File

@ -2,6 +2,7 @@ import React, { useState, useEffect } from 'react';
import { Link } from 'react-router-dom'; import { Link } from 'react-router-dom';
import { MOCK_USER } from '../../constants/mock'; import { MOCK_USER } from '../../constants/mock';
import { getUserInfo, isTelegramWebAppAvailable } from '../../constants/user'; import { getUserInfo, isTelegramWebAppAvailable } from '../../constants/user';
import { images } from '../../assets';
import styles from './Header.module.css'; import styles from './Header.module.css';
const Header: React.FC = () => { const Header: React.FC = () => {
@ -50,7 +51,9 @@ const Header: React.FC = () => {
onClick={() => alert('Пополнить баланс')} onClick={() => alert('Пополнить баланс')}
title="Нажмите чтобы пополнить баланс" title="Нажмите чтобы пополнить баланс"
> >
<span className={styles.balanceIcon}>💎</span> <span className={styles.balanceIcon}>
<img src={images.tokenIcon} alt="Токены" className={styles.tokenImage} />
</span>
<span className={styles.balanceValue}> <span className={styles.balanceValue}>
{user.balance} {user.balance}
</span> </span>

View File

@ -1,7 +1,7 @@
export const baseWorkflow = { export const baseWorkflow = {
"305": { "305": {
"inputs": { "inputs": {
"ckpt_name": "SDXL\\dreamshaperXL_lightningDPMSDE.safetensors" "ckpt_name": "dreamshaperXL_lightningDPMSDE.safetensors"
}, },
"class_type": "CheckpointLoaderSimple", "class_type": "CheckpointLoaderSimple",
"_meta": { "_meta": {

View File

@ -8,6 +8,14 @@ import { stylePresets } from '../config/stylePresets';
import apiService from '../services/api'; import apiService from '../services/api';
import NotificationModal from '../components/shared/NotificationModal'; import NotificationModal from '../components/shared/NotificationModal';
// Интерфейс для хранения данных о последней генерации
interface LastGenerationData {
imageData?: string;
style?: string;
presetId?: string;
customPrompt?: string;
}
const Home: React.FC = () => { const Home: React.FC = () => {
const navigate = useNavigate(); const navigate = useNavigate();
@ -35,6 +43,9 @@ const Home: React.FC = () => {
const [isLoading, setIsLoading] = useState(false); const [isLoading, setIsLoading] = useState(false);
const [promptText, setPromptText] = useState(''); const [promptText, setPromptText] = useState('');
// Состояние для хранения данных о последней успешной генерации
const [lastGenerationData, setLastGenerationData] = useState<LastGenerationData>({});
// Обработчики для модального окна // Обработчики для модального окна
const handleGalleryClick = useCallback(() => { const handleGalleryClick = useCallback(() => {
setIsNotificationVisible(false); setIsNotificationVisible(false);
@ -63,8 +74,63 @@ const Home: React.FC = () => {
if (actionType === 'function') { if (actionType === 'function') {
if (actionValue === 'startGeneration') { if (actionValue === 'startGeneration') {
// Проверка наличия изображения
if (!imageData) { 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; return;
} }
@ -83,6 +149,14 @@ const Home: React.FC = () => {
const response = await apiService.generateImage(imageData, selectedStyle, selectedPresetId, userPrompt); const response = await apiService.generateImage(imageData, selectedStyle, selectedPresetId, userPrompt);
console.log('Generation response:', response); console.log('Generation response:', response);
// Сохраняем данные о текущей генерации
setLastGenerationData({
imageData,
style: selectedStyle,
presetId: selectedPresetId,
customPrompt: userPrompt
});
// Проверяем, была ли ошибка перевода // Проверяем, была ли ошибка перевода
if (response.translationFailed) { if (response.translationFailed) {
setNotificationTitle('Недопустимый промпт'); setNotificationTitle('Недопустимый промпт');
@ -157,7 +231,7 @@ const Home: React.FC = () => {
// Если выбрана любая другая кнопка, скрываем поле ввода // Если выбрана любая другая кнопка, скрываем поле ввода
setIsInputVisible(false); setIsInputVisible(false);
}, [navigate, imageData, selectedStyle, selectedPresetId, customPrompt]); }, [navigate, imageData, selectedStyle, selectedPresetId, customPrompt, lastGenerationData]);
// Эффект для обновления window.history.state при загрузке из localStorage // Эффект для обновления window.history.state при загрузке из localStorage
useEffect(() => { useEffect(() => {

View File

@ -34,8 +34,22 @@ const TermsAndConditions: React.FC = () => {
</p> </p>
<div className={styles.links}> <div className={styles.links}>
<a href="#" className={styles.link}>Условия использования</a> <a
<a href="#" className={styles.link}>Политика конфиденциальности</a> href="https://telegra.ph/Polzovatelskoe-soglashenie-03-19-13"
className={styles.link}
target="_blank"
rel="noopener noreferrer"
>
Условия использования
</a>
<a
href="https://telegra.ph/Politika-konfidencialnosti-03-19-10"
className={styles.link}
target="_blank"
rel="noopener noreferrer"
>
Политика конфиденциальности
</a>
</div> </div>
<div className={styles.buttonsContainer}> <div className={styles.buttonsContainer}>

View File

@ -90,7 +90,8 @@ export class StickerService {
file_id: firstSticker, file_id: firstSticker,
emojis: firstEmoji, emojis: firstEmoji,
is_animated: false, is_animated: false,
is_video: false is_video: false,
format: "static" // Добавляем поле format для соответствия требованиям API
}; };
// Логируем данные запроса // Логируем данные запроса
@ -203,7 +204,8 @@ export class StickerService {
file_id: fileId, file_id: fileId,
emojis: emoji, emojis: emoji,
is_animated: false, is_animated: false,
is_video: false is_video: false,
format: "static" // Добавляем поле format для соответствия требованиям API
}; };
// Логируем данные запроса // Логируем данные запроса

View File

@ -1,7 +1,7 @@
{ {
"305": { "305": {
"inputs": { "inputs": {
"ckpt_name": "SDXL\\dreamshaperXL_lightningDPMSDE.safetensors" "ckpt_name": "dreamshaperXL_lightningDPMSDE.safetensors"
}, },
"class_type": "CheckpointLoaderSimple", "class_type": "CheckpointLoaderSimple",
"_meta": { "_meta": {