diff --git a/src/assets/emo/1.png b/src/assets/emo/1.png new file mode 100644 index 0000000..00ebe29 Binary files /dev/null and b/src/assets/emo/1.png differ diff --git a/src/assets/emo/10.png b/src/assets/emo/10.png new file mode 100644 index 0000000..2b22df7 Binary files /dev/null and b/src/assets/emo/10.png differ diff --git a/src/assets/emo/11.png b/src/assets/emo/11.png new file mode 100644 index 0000000..e365766 Binary files /dev/null and b/src/assets/emo/11.png differ diff --git a/src/assets/emo/12.png b/src/assets/emo/12.png new file mode 100644 index 0000000..8a7b9a3 Binary files /dev/null and b/src/assets/emo/12.png differ diff --git a/src/assets/emo/13.png b/src/assets/emo/13.png new file mode 100644 index 0000000..a7afcee Binary files /dev/null and b/src/assets/emo/13.png differ diff --git a/src/assets/emo/14.png b/src/assets/emo/14.png new file mode 100644 index 0000000..491f8b3 Binary files /dev/null and b/src/assets/emo/14.png differ diff --git a/src/assets/emo/15.png b/src/assets/emo/15.png new file mode 100644 index 0000000..b2b10e9 Binary files /dev/null and b/src/assets/emo/15.png differ diff --git a/src/assets/emo/16.png b/src/assets/emo/16.png new file mode 100644 index 0000000..04a353f Binary files /dev/null and b/src/assets/emo/16.png differ diff --git a/src/assets/emo/17.png b/src/assets/emo/17.png new file mode 100644 index 0000000..6354b4f Binary files /dev/null and b/src/assets/emo/17.png differ diff --git a/src/assets/emo/18.png b/src/assets/emo/18.png new file mode 100644 index 0000000..ef4bb78 Binary files /dev/null and b/src/assets/emo/18.png differ diff --git a/src/assets/emo/19.png b/src/assets/emo/19.png new file mode 100644 index 0000000..89a9648 Binary files /dev/null and b/src/assets/emo/19.png differ diff --git a/src/assets/emo/2.png b/src/assets/emo/2.png new file mode 100644 index 0000000..1127a6a Binary files /dev/null and b/src/assets/emo/2.png differ diff --git a/src/assets/emo/20.png b/src/assets/emo/20.png new file mode 100644 index 0000000..3452c1f Binary files /dev/null and b/src/assets/emo/20.png differ diff --git a/src/assets/emo/21.png b/src/assets/emo/21.png new file mode 100644 index 0000000..f51a82d Binary files /dev/null and b/src/assets/emo/21.png differ diff --git a/src/assets/emo/22.png b/src/assets/emo/22.png new file mode 100644 index 0000000..9749c6d Binary files /dev/null and b/src/assets/emo/22.png differ diff --git a/src/assets/emo/23.png b/src/assets/emo/23.png new file mode 100644 index 0000000..38940f7 Binary files /dev/null and b/src/assets/emo/23.png differ diff --git a/src/assets/emo/24.png b/src/assets/emo/24.png new file mode 100644 index 0000000..2354844 Binary files /dev/null and b/src/assets/emo/24.png differ diff --git a/src/assets/emo/25.png b/src/assets/emo/25.png new file mode 100644 index 0000000..8f22d0c Binary files /dev/null and b/src/assets/emo/25.png differ diff --git a/src/assets/emo/26.png b/src/assets/emo/26.png new file mode 100644 index 0000000..3ce32cf Binary files /dev/null and b/src/assets/emo/26.png differ diff --git a/src/assets/emo/27.png b/src/assets/emo/27.png new file mode 100644 index 0000000..1501f88 Binary files /dev/null and b/src/assets/emo/27.png differ diff --git a/src/assets/emo/28.png b/src/assets/emo/28.png new file mode 100644 index 0000000..8512eb3 Binary files /dev/null and b/src/assets/emo/28.png differ diff --git a/src/assets/emo/29.png b/src/assets/emo/29.png new file mode 100644 index 0000000..05d586d Binary files /dev/null and b/src/assets/emo/29.png differ diff --git a/src/assets/emo/3.png b/src/assets/emo/3.png new file mode 100644 index 0000000..cba4096 Binary files /dev/null and b/src/assets/emo/3.png differ diff --git a/src/assets/emo/30.png b/src/assets/emo/30.png new file mode 100644 index 0000000..e49bcbc Binary files /dev/null and b/src/assets/emo/30.png differ diff --git a/src/assets/emo/31.png b/src/assets/emo/31.png new file mode 100644 index 0000000..e6070cd Binary files /dev/null and b/src/assets/emo/31.png differ diff --git a/src/assets/emo/32.png b/src/assets/emo/32.png new file mode 100644 index 0000000..6abfa84 Binary files /dev/null and b/src/assets/emo/32.png differ diff --git a/src/assets/emo/33.png b/src/assets/emo/33.png new file mode 100644 index 0000000..9040ce8 Binary files /dev/null and b/src/assets/emo/33.png differ diff --git a/src/assets/emo/34.png b/src/assets/emo/34.png new file mode 100644 index 0000000..709b019 Binary files /dev/null and b/src/assets/emo/34.png differ diff --git a/src/assets/emo/35.png b/src/assets/emo/35.png new file mode 100644 index 0000000..268966f Binary files /dev/null and b/src/assets/emo/35.png differ diff --git a/src/assets/emo/36.png b/src/assets/emo/36.png new file mode 100644 index 0000000..f67c720 Binary files /dev/null and b/src/assets/emo/36.png differ diff --git a/src/assets/emo/4.png b/src/assets/emo/4.png new file mode 100644 index 0000000..5d0bbaa Binary files /dev/null and b/src/assets/emo/4.png differ diff --git a/src/assets/emo/5.png b/src/assets/emo/5.png new file mode 100644 index 0000000..fba38aa Binary files /dev/null and b/src/assets/emo/5.png differ diff --git a/src/assets/emo/6.png b/src/assets/emo/6.png new file mode 100644 index 0000000..2628bb8 Binary files /dev/null and b/src/assets/emo/6.png differ diff --git a/src/assets/emo/7.png b/src/assets/emo/7.png new file mode 100644 index 0000000..d1d7129 Binary files /dev/null and b/src/assets/emo/7.png differ diff --git a/src/assets/emo/8.png b/src/assets/emo/8.png new file mode 100644 index 0000000..2f6bf65 Binary files /dev/null and b/src/assets/emo/8.png differ diff --git a/src/assets/emo/9.png b/src/assets/emo/9.png new file mode 100644 index 0000000..c56addd Binary files /dev/null and b/src/assets/emo/9.png differ diff --git a/src/assets/emo/prompts.txt b/src/assets/emo/prompts.txt new file mode 100644 index 0000000..43a61af --- /dev/null +++ b/src/assets/emo/prompts.txt @@ -0,0 +1,71 @@ +1) half of body, Face struggling to hold up a comically large trophy. Conveying mock pride and exhaustion - хороший стабильный результат + +2) half of body, clutching a giant plush teddy bear to their chest. Conveying comfort and fondness - хороший стабильный результат + +3) half of body looks with adoration at the perfect single rose, which it gracefully holds in its hand. An expression of romance and appreciation - хороший стабильный результат + +4) half of body, With a cup of warm tea in his hands, his face looks wery tired, clean face - хороший стабильный результат кроме детей + +5) upper half of body, target to face, holding a beautifully wrapped gift box. Conveying anticipation or excitement - хороший стабильный результат + +6) Half body. Facelooking contentedly at a small bouquet of flowers. Conveying joy and appreciation - хороший стабильный результат + +7) Half body. Face covering their mouth in a silent scream face is expressing surprise and shock - хороший стабильный результат + +8) Full body. Face wearing headphones and dancing enthusiastically. Not looking at the camera. Conveying joy and freedom - хороший стабильный результат + +9) Full body. Face looking nervous while holding a microphone at a karaoke, not looking at the camera. Conveying nervousness and anxiety before starting singing - хороший стабильный результат + +10) half body, make a green bloody zombie, wery angry with a cup of coffee in his hands - хороший стабильный результат + +11) full body, homeless sitting in the trash. torn dirty clothes - хороший стабильный результат + +12) half body, Make hulk head, maximum anger, green skin - очень хороший но редко не стабильный результат + +13) half body, focus to head, holds out one mug of beer at arm's length to the viewer - хороший почти всегда стабильный результат + +14) half body, fully clothed, laughs so hard going to cry - хороший результат но очень разнообразный + +15) half body, fully clothed, shakes one fist holding it out to the viewer - хороший реузльтат на мужчинах, на женщинах не самый стабильный + +16) half body, fully clothed, boxing, holding his hands in a protective position near his head - хороший стабильный результат + +17) Half of body, full face, holding a tiny kitten with both hands, looking at it with exaggerated amazement. Conveying love and adoration for pets - хороший стабильный результат + +18) Half of body, full face, holding a tiny puppy with both hands, looking at it with exaggerated amazement. Conveying love and adoration for pets - хороший стабильный результат + +19) Full body, wearing a bright superhero cape while trying to make a dramatic entrance but tripping over. Conveying a mix of confidence and clumsiness - не плохой результат + +20) Half of body, face scrunched up in delight, holding an ice cream cone that’s too big to handle. Conveying carefree joy and summer vibes- хороший стабильный результат + +21) Half body, dressed as a wizard, conjuring colorful sparks from a magic wand, with a look of intense concentration. Conveying magic and wonder - хороший стабильный результат + +22) Half of the body, with big dragon wings on its back and fiery breath, looked surprised, holding a tiny dragon egg in its hands - хороший стабильный результат + +23) Half body, fully clothed, in a cyberpunk outfit with neon lights - стабильно хорошо + +24) Half of body, wearing a cloak and holding a glowing spellbook, surrounded by floating magical runes, looking determined - супер стабильный результат + +25) Half of body, as a pirate captain with a parrot on the shoulder - стабильный результат + +26) Half of body, dressed as a cybernetic samurai with a glowing katana, clear face - не плохой результат + +27) Half of body, dressed as a mad scientist with wild hair, looking excitedly - очень стабильный результат + +28) Half of body, elegantly dressed, holding a glittering glass of red wine, eyes sparkling with delight, as if savoring a fine vintage - очень стабильный результат + +29) half body, greets by raising onlu one hand up - достаточно стабильно + +30) Half of body, with both hands raised high in a classic “thumbs up” gesture, wearing a bright smile that expresses confidence and positivity - очень стабильно + +31) Half body, holding a big heart in both hands, eyes shining with love and joy - крайне стабильный результат + +32) Half body, focus on face, turned into a thick green slime, Green slime underfoot, The body is green slime. Green slime on the head + +33) full body, focus on face, A man is riding a horse. horse in iron armor war + +34) half body, a man made of fire, body on fire, fire on his head, very angry, hands clenched into fists + +35) Half of body, vividly dressed as Doctor Strange, with his iconic cloak billowing dramatically behind him. He is holding a swirling, glowing portal with one hand, while intricate magical symbols and runes surround him. His expression is focused and determined as he channels mystical energy, creating a mesmerizing vibrant portal that seems to shimmer with colors of blue and purple + +36) half body, Captain America \ No newline at end of file diff --git a/src/assets/index.ts b/src/assets/index.ts index a05722c..5786166 100644 --- a/src/assets/index.ts +++ b/src/assets/index.ts @@ -35,6 +35,44 @@ import shieldIcon from './shield-icon.png'; import reactLogo from './react.svg'; import tokenIcon from './token_ico.png'; +// Импорты изображений для эмоций +import emoTrophy from './emo/1.png'; +import emoTeddyBear from './emo/2.png'; +import emoRose from './emo/3.png'; +import emoTea from './emo/4.png'; +import emoGift from './emo/5.png'; +import emoFlowers from './emo/6.png'; +import emoShock from './emo/7.png'; +import emoDance from './emo/8.png'; +import emoKaraoke from './emo/9.png'; +import emoZombie from './emo/10.png'; +import emoHomeless from './emo/11.png'; +import emoHulk from './emo/12.png'; +import emoBeer from './emo/13.png'; +import emoLaugh from './emo/14.png'; +import emoThreat from './emo/15.png'; +import emoBoxing from './emo/16.png'; +import emoKitten from './emo/17.png'; +import emoPuppy from './emo/18.png'; +import emoSuperhero from './emo/19.png'; +import emoIceCream from './emo/20.png'; +import emoWizard from './emo/21.png'; +import emoDragon from './emo/22.png'; +import emoCyberpunk from './emo/23.png'; +import emoMage from './emo/24.png'; +import emoPirate from './emo/25.png'; +import emoSamurai from './emo/26.png'; +import emoScientist from './emo/27.png'; +import emoWine from './emo/28.png'; +import emoGreeting from './emo/29.png'; +import emoThumbsUp from './emo/30.png'; +import emoHeart from './emo/31.png'; +import emoSlime from './emo/32.png'; +import emoRider from './emo/33.png'; +import emoFire from './emo/34.png'; +import emoDrStrange from './emo/35.png'; +import emoCaptainAmerica from './emo/36.png'; + export const images = { ahareBot, faq, @@ -71,5 +109,43 @@ export const images = { defaultAvatar, shieldIcon, reactLogo, - tokenIcon + tokenIcon, + + // Изображения для эмоций + emoTrophy, + emoTeddyBear, + emoRose, + emoTea, + emoGift, + emoFlowers, + emoShock, + emoDance, + emoKaraoke, + emoZombie, + emoHomeless, + emoHulk, + emoBeer, + emoLaugh, + emoThreat, + emoBoxing, + emoKitten, + emoPuppy, + emoSuperhero, + emoIceCream, + emoWizard, + emoDragon, + emoCyberpunk, + emoMage, + emoPirate, + emoSamurai, + emoScientist, + emoWine, + emoGreeting, + emoThumbsUp, + emoHeart, + emoSlime, + emoRider, + emoFire, + emoDrStrange, + emoCaptainAmerica }; diff --git a/src/assets/meme/10_250x.png b/src/assets/meme/10_250x.png new file mode 100644 index 0000000..f68f2d3 Binary files /dev/null and b/src/assets/meme/10_250x.png differ diff --git a/src/assets/meme/1_250x.png b/src/assets/meme/1_250x.png new file mode 100644 index 0000000..8da93b2 Binary files /dev/null and b/src/assets/meme/1_250x.png differ diff --git a/src/assets/meme/2_250x.png b/src/assets/meme/2_250x.png new file mode 100644 index 0000000..6030b6e Binary files /dev/null and b/src/assets/meme/2_250x.png differ diff --git a/src/assets/meme/3_250x.png b/src/assets/meme/3_250x.png new file mode 100644 index 0000000..735b971 Binary files /dev/null and b/src/assets/meme/3_250x.png differ diff --git a/src/assets/meme/4_250x.png b/src/assets/meme/4_250x.png new file mode 100644 index 0000000..d62622f Binary files /dev/null and b/src/assets/meme/4_250x.png differ diff --git a/src/assets/meme/5_250x.png b/src/assets/meme/5_250x.png new file mode 100644 index 0000000..13d6ee3 Binary files /dev/null and b/src/assets/meme/5_250x.png differ diff --git a/src/assets/meme/6_250x.png b/src/assets/meme/6_250x.png new file mode 100644 index 0000000..e08c639 Binary files /dev/null and b/src/assets/meme/6_250x.png differ diff --git a/src/assets/meme/7_250x.png b/src/assets/meme/7_250x.png new file mode 100644 index 0000000..cfa8ff6 Binary files /dev/null and b/src/assets/meme/7_250x.png differ diff --git a/src/assets/meme/8_250x.png b/src/assets/meme/8_250x.png new file mode 100644 index 0000000..01d5d34 Binary files /dev/null and b/src/assets/meme/8_250x.png differ diff --git a/src/assets/meme/9_250x.png b/src/assets/meme/9_250x.png new file mode 100644 index 0000000..7e56bcc Binary files /dev/null and b/src/assets/meme/9_250x.png differ diff --git a/src/assets/memes.ts b/src/assets/memes.ts new file mode 100644 index 0000000..011529a --- /dev/null +++ b/src/assets/memes.ts @@ -0,0 +1,72 @@ +// Интерфейс для данных мема +export interface MemeData { + id: string; + name: string; + description: string; + thumbnailUrl: string; + // base64 будет добавлен позже +} + +// Список мемов +export const memes: MemeData[] = [ + { + id: 'meme1', + name: 'Мем 1', + description: 'Описание мема 1', + thumbnailUrl: '/src/assets/meme/1_250x.png' + }, + { + id: 'meme2', + name: 'Мем 2', + description: 'Описание мема 2', + thumbnailUrl: '/src/assets/meme/2_250x.png' + }, + { + id: 'meme3', + name: 'Мем 3', + description: 'Описание мема 3', + thumbnailUrl: '/src/assets/meme/3_250x.png' + }, + { + id: 'meme4', + name: 'Мем 4', + description: 'Описание мема 4', + thumbnailUrl: '/src/assets/meme/4_250x.png' + }, + { + id: 'meme5', + name: 'Мем 5', + description: 'Описание мема 5', + thumbnailUrl: '/src/assets/meme/5_250x.png' + }, + { + id: 'meme6', + name: 'Мем 6', + description: 'Описание мема 6', + thumbnailUrl: '/src/assets/meme/6_250x.png' + }, + { + id: 'meme7', + name: 'Мем 7', + description: 'Описание мема 7', + thumbnailUrl: '/src/assets/meme/7_250x.png' + }, + { + id: 'meme8', + name: 'Мем 8', + description: 'Описание мема 8', + thumbnailUrl: '/src/assets/meme/8_250x.png' + }, + { + id: 'meme9', + name: 'Мем 9', + description: 'Описание мема 9', + thumbnailUrl: '/src/assets/meme/9_250x.png' + }, + { + id: 'meme10', + name: 'Мем 10', + description: 'Описание мема 10', + thumbnailUrl: '/src/assets/meme/10_250x.png' + } +]; diff --git a/src/assets/prompts.ts b/src/assets/prompts.ts index c8c8fac..346941e 100644 --- a/src/assets/prompts.ts +++ b/src/assets/prompts.ts @@ -1,4 +1,5 @@ export const prompts: Record = { + // Промпты для стиля "чиби" 'chibi-sportscar': 'riding in a sports car', 'chibi-skateboard': 'Riding a skateboard with the wind in the hair', 'chibi-coffee': 'Drinking coffee from a cup and smiling', @@ -21,5 +22,43 @@ export const prompts: Record = { 'chibi-knight': 'Dressed as a knight', 'chibi-ballerina': 'Dressed as a ballerina', 'chibi-firefighter': 'Dressed as a firefighter', - 'chibi-chef': 'Dressed as a chef' + 'chibi-chef': 'Dressed as a chef', + + // Промпты для стиля "Эмоции" (подраздел "промпты") + 'emotions-trophy': 'half of body, Face struggling to hold up a comically large trophy. Conveying mock pride and exhaustion', + 'emotions-teddybear': 'half of body, clutching a giant plush teddy bear to their chest. Conveying comfort and fondness', + 'emotions-rose': 'half of body looks with adoration at the perfect single rose, which it gracefully holds in its hand. An expression of romance and appreciation', + 'emotions-tea': 'half of body, With a cup of warm tea in his hands, his face looks wery tired, clean face', + 'emotions-gift': 'upper half of body, target to face, holding a beautifully wrapped gift box. Conveying anticipation or excitement', + 'emotions-flowers': 'Half body. Facelooking contentedly at a small bouquet of flowers. Conveying joy and appreciation', + 'emotions-shock': 'Half body. Face covering their mouth in a silent scream face is expressing surprise and shock', + 'emotions-dance': 'Full body. Face wearing headphones and dancing enthusiastically. Not looking at the camera. Conveying joy and freedom', + 'emotions-karaoke': 'Full body. Face looking nervous while holding a microphone at a karaoke, not looking at the camera. Conveying nervousness and anxiety before starting singing', + 'emotions-zombie': 'half body, make a green bloody zombie, wery angry with a cup of coffee in his hands', + 'emotions-homeless': 'full body, homeless sitting in the trash. torn dirty clothes', + 'emotions-hulk': 'half body, Make hulk head, maximum anger, green skin', + 'emotions-beer': 'half body, focus to head, holds out one mug of beer at arms length to the viewer', + 'emotions-laugh': 'half body, fully clothed, laughs so hard going to cry', + 'emotions-threat': 'half body, fully clothed, shakes one fist holding it out to the viewer', + 'emotions-boxing': 'half body, fully clothed, boxing, holding his hands in a protective position near his head', + 'emotions-kitten': 'Half of body, full face, holding a tiny kitten with both hands, looking at it with exaggerated amazement. Conveying love and adoration for pets', + 'emotions-puppy': 'Half of body, full face, holding a tiny puppy with both hands, looking at it with exaggerated amazement. Conveying love and adoration for pets', + 'emotions-superhero': 'Full body, wearing a bright superhero cape while trying to make a dramatic entrance but tripping over. Conveying a mix of confidence and clumsiness', + 'emotions-icecream': 'Half of body, face scrunched up in delight, holding an ice cream cone that is too big to handle. Conveying carefree joy and summer vibes', + 'emotions-wizard': 'Half body, dressed as a wizard, conjuring colorful sparks from a magic wand, with a look of intense concentration. Conveying magic and wonder', + 'emotions-dragon': 'Half of the body, with big dragon wings on its back and fiery breath, looked surprised, holding a tiny dragon egg in its hands', + 'emotions-cyberpunk': 'Half body, fully clothed, in a cyberpunk outfit with neon lights', + 'emotions-mage': 'Half of body, wearing a cloak and holding a glowing spellbook, surrounded by floating magical runes, looking determined', + 'emotions-pirate': 'Half of body, as a pirate captain with a parrot on the shoulder', + 'emotions-samurai': 'Half of body, dressed as a cybernetic samurai with a glowing katana, clear face', + 'emotions-scientist': 'Half of body, dressed as a mad scientist with wild hair, looking excitedly', + 'emotions-wine': 'Half of body, elegantly dressed, holding a glittering glass of red wine, eyes sparkling with delight, as if savoring a fine vintage', + 'emotions-greeting': 'half body, greets by raising onlu one hand up', + 'emotions-thumbsup': 'Half of body, with both hands raised high in a classic "thumbs up" gesture, wearing a bright smile that expresses confidence and positivity', + 'emotions-heart': 'Half body, holding a big heart in both hands, eyes shining with love and joy', + 'emotions-slime': 'Half body, focus on face, turned into a thick green slime, Green slime underfoot, The body is green slime. Green slime on the head', + 'emotions-rider': 'full body, focus on face, A man is riding a horse. horse in iron armor war', + 'emotions-fire': 'half body, a man made of fire, body on fire, fire on his head, very angry, hands clenched into fists', + 'emotions-drstrange': 'Half of body, vividly dressed as Doctor Strange, with his iconic cloak billowing dramatically behind him. He is holding a swirling, glowing portal with one hand, while intricate magical symbols and runes surround him. His expression is focused and determined as he channels mystical energy, creating a mesmerizing vibrant portal that seems to shimmer with colors of blue and purple', + 'emotions-captainamerica': 'half body, Captain America' }; diff --git a/src/components/blocks/BlockRenderer.tsx b/src/components/blocks/BlockRenderer.tsx index 5998af8..8ba8a86 100644 --- a/src/components/blocks/BlockRenderer.tsx +++ b/src/components/blocks/BlockRenderer.tsx @@ -2,6 +2,8 @@ import React from 'react'; import { Block, ButtonBlock, DividerBlock as DividerBlockType, TextInputBlock as TextInputBlockType, GenerateButtonBlock, StepTitleBlock } from '../../types/blocks'; import ScrollableButtonsBlock from './ScrollableButtonsBlock'; import GridButtonsBlock from './GridButtonsBlock'; +import GenderSelectionButtons from './GenderSelectionButtons'; +import EmotionTypeButtons from './EmotionTypeButtons'; import UploadPhotoBlock from './UploadPhotoBlock'; import DividerBlock from './DividerBlock'; import TextInputBlock from './TextInputBlock'; @@ -23,6 +25,14 @@ const BlockRenderer: React.FC = ({ block, onAction, extraPro if (block.type === 'scrollableButtons') { return ; } + // Используем специальный компонент для блока выбора пола + if (block.id === 'genderSelection') { + return ; + } + // Используем специальный компонент для блока выбора типа эмоций + if (block.id === 'emotionTypeSelection') { + return ; + } return ; case 'uploadPhoto': return void; + selectedButtonId?: string; +} + +const EmotionTypeButtons: React.FC = ({ block, onAction, selectedButtonId }) => { + const { buttons, style } = block; + const { gap = 8, padding = "4px 16px 16px" } = style; + + return ( +
+
+ {buttons.map((button) => ( +
+ +
+ ))} +
+
+ ); +}; + +export default EmotionTypeButtons; diff --git a/src/components/blocks/GenderSelectionButtons.module.css b/src/components/blocks/GenderSelectionButtons.module.css new file mode 100644 index 0000000..48309e8 --- /dev/null +++ b/src/components/blocks/GenderSelectionButtons.module.css @@ -0,0 +1,66 @@ +/* Стили для блока выбора пола */ +.genderSelectionContainer { + width: 100%; + box-sizing: border-box; +} + +.genderSelectionGrid { + display: grid; + width: 100%; + gap: 8px; + grid-template-columns: repeat(3, 1fr); + padding: 0; + margin: 0 auto; + box-sizing: border-box; +} + +.genderButtonWrapper { + width: 100%; + display: flex; + align-items: center; + justify-content: center; + position: relative; + padding: 0; + margin: 0; + min-height: 44px; /* Минимальная высота для кнопки */ +} + +/* Стили для кнопок выбора пола */ +.genderButton { + position: relative; + border: none; + border-radius: var(--border-radius); + padding: var(--spacing-small); + cursor: pointer; + overflow: hidden; + display: flex; + flex-direction: column; + justify-content: center; + align-items: center; + transition: all 0.2s ease-in-out; + text-align: center; + background-color: #E0E0E0; /* Нейтральный цвет фона */ + color: var(--color-text); + width: 100%; + height: 100%; +} + +/* Стиль для выбранной кнопки */ +.genderButtonSelected { + background-color: var(--color-primary); + color: white; + box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1); +} + +.genderButtonTitle { + font-weight: 600; + font-size: 1rem; + line-height: 1.2; + margin: 0; + text-align: center; + width: 100%; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + padding: 0 2px; +} diff --git a/src/components/blocks/GenderSelectionButtons.tsx b/src/components/blocks/GenderSelectionButtons.tsx new file mode 100644 index 0000000..0df766b --- /dev/null +++ b/src/components/blocks/GenderSelectionButtons.tsx @@ -0,0 +1,47 @@ +import React from 'react'; +import { ButtonBlock } from '../../types/blocks'; +import styles from './GenderSelectionButtons.module.css'; + +interface GenderSelectionButtonsProps { + block: ButtonBlock; + onAction?: (actionType: string, actionValue: string, blockId?: string, buttonId?: string) => void; + selectedButtonId?: string; +} + +const GenderSelectionButtons: React.FC = ({ block, onAction, selectedButtonId }) => { + const { buttons, style } = block; + const { gap = 8, padding = "4px 16px 16px" } = style; + + return ( +
+
+ {buttons.map((button) => ( +
+ +
+ ))} +
+
+ ); +}; + +export default GenderSelectionButtons; diff --git a/src/components/blocks/GridButtonsBlock.module.css b/src/components/blocks/GridButtonsBlock.module.css index 3246b31..1f92889 100644 --- a/src/components/blocks/GridButtonsBlock.module.css +++ b/src/components/blocks/GridButtonsBlock.module.css @@ -8,7 +8,7 @@ display: flex; flex-direction: column; position: relative; - padding-bottom: 48px; /* Место для кнопки */ + padding-bottom: 64px; /* Увеличенное место для кнопки */ } .grid { @@ -107,7 +107,7 @@ } .grid.expanded { - max-height: 1200px; /* Увеличенная высота для всех кнопок */ + max-height: 2000px; /* Увеличенная высота для всех кнопок */ } /* Добавляем тень при наведении на весь блок */ diff --git a/src/components/shared/NotificationModal.module.css b/src/components/shared/NotificationModal.module.css index e98c966..6d852d3 100644 --- a/src/components/shared/NotificationModal.module.css +++ b/src/components/shared/NotificationModal.module.css @@ -47,26 +47,56 @@ white-space: pre-line; } -.promptContainer { - background-color: var(--color-border); - border-radius: var(--border-radius); - padding: var(--spacing-small); +.generationPreview { + width: 100%; + height: 200px; + display: flex; + justify-content: center; + align-items: center; margin-bottom: var(--spacing-medium); - max-height: 100px; - overflow-y: auto; + border-radius: var(--border-radius); + overflow: hidden; + background-color: var(--color-border); + position: relative; } -.promptLabel { - font-size: 12px; - font-weight: 600; - margin-bottom: 4px; - color: var(--color-text-secondary); +.generatedImage { + max-width: 100%; + max-height: 100%; + object-fit: contain; } -.promptText { - font-size: 12px; - word-break: break-word; - font-family: monospace; +.magicRipple { + width: 130px; + height: 130px; + border-radius: 50%; + background: radial-gradient(circle, var(--color-primary) 0%, transparent 70%); + animation: ripple 2s infinite ease-in-out; +} + +.generationText { + position: absolute; + bottom: 20px; + width: 100%; + text-align: center; + font-size: 16px; + font-weight: 500; + color: var(--color-text); +} + +@keyframes ripple { + 0% { + transform: scale(0.8); + opacity: 1; + } + 50% { + transform: scale(1.2); + opacity: 0.5; + } + 100% { + transform: scale(0.8); + opacity: 1; + } } .buttons { diff --git a/src/components/shared/NotificationModal.tsx b/src/components/shared/NotificationModal.tsx index 8f2ef6e..907a290 100644 --- a/src/components/shared/NotificationModal.tsx +++ b/src/components/shared/NotificationModal.tsx @@ -6,7 +6,6 @@ interface NotificationModalProps { title: string; message: string; isLoading?: boolean; - promptText?: string; onGalleryClick: () => void; onContinueClick: () => void; showGalleryButton?: boolean; // Параметр для управления видимостью кнопки "В галерею" @@ -14,6 +13,10 @@ interface NotificationModalProps { continueButtonText?: string; // Новый параметр для изменения текста кнопки "Продолжить" galleryButtonText?: string; // Новый параметр для изменения текста кнопки "В галерею" isPrimaryGalleryButton?: boolean; // Новый параметр для управления стилем кнопки "В галерею" + taskId?: string; // ID задачи генерации + generatedImageUrl?: string; // URL сгенерированного изображения + isGenerating?: boolean; // Флаг, указывающий, что идет генерация + queuePosition?: number; // Позиция в очереди } const NotificationModal: React.FC = ({ @@ -21,14 +24,17 @@ const NotificationModal: React.FC = ({ title, message, isLoading = false, - promptText, onGalleryClick, onContinueClick, showGalleryButton = true, // По умолчанию кнопка "В галерею" видима showButtons = true, // По умолчанию все кнопки видимы continueButtonText = 'Продолжить', // По умолчанию текст кнопки "Продолжить" galleryButtonText = 'В галерею', // По умолчанию текст кнопки "В галерею" - isPrimaryGalleryButton = true // По умолчанию кнопка "В галерею" синяя + isPrimaryGalleryButton = true, // По умолчанию кнопка "В галерею" синяя + taskId, + generatedImageUrl, + isGenerating = false, + queuePosition }) => { if (!isVisible) return null; @@ -43,10 +49,18 @@ const NotificationModal: React.FC = ({
{message}
- {promptText && ( -
-
Использованный промпт:
-
{promptText}
+ {isGenerating && queuePosition !== undefined && queuePosition <= 2 && ( +
+ {generatedImageUrl ? ( + Сгенерированный стикер + ) : ( + <> +
+ {/* Анимация магической ряби */} +
+
Генерация...
+ + )}
)} diff --git a/src/config/homeScreen.ts b/src/config/homeScreen.ts index 007101f..1ca7a6d 100644 --- a/src/config/homeScreen.ts +++ b/src/config/homeScreen.ts @@ -74,7 +74,58 @@ export const homeScreenConfig: AppConfig = { type: 'uploadPhoto', id: 'photoUpload', style: { - padding: "4px 16px 16px" + padding: "4px 16px 8px" + } + }, + { + type: 'gridButtons', + id: 'genderSelection', + buttons: [ + { + id: 'auto', + type: 'square', + background: { + type: 'color', + colors: ['#E0E0E0'] + }, + title: 'Авто', + action: { + type: 'selectGenderDetection', + value: 'auto' + } + }, + { + id: 'man', + type: 'square', + background: { + type: 'color', + colors: ['#E0E0E0'] + }, + title: 'Мужчина', + action: { + type: 'selectGender', + value: 'man' + } + }, + { + id: 'woman', + type: 'square', + background: { + type: 'color', + colors: ['#E0E0E0'] + }, + title: 'Женщина', + action: { + type: 'selectGender', + value: 'woman' + } + } + ], + style: { + gap: 8, + padding: "4px 16px 16px", + buttonSize: 100, + columns: 3 } }, { @@ -87,6 +138,20 @@ export const homeScreenConfig: AppConfig = { type: 'scrollableButtons', id: 'styleActions', buttons: [ + { + id: 'emotions', + type: 'square', + background: { + type: 'gradient', + colors: ['#2B9CFF', '#1E88E5'] + }, + title: 'Эмоции', + imageUrl: images.emotions, + action: { + type: 'selectStyle', + value: 'emotions' + } + }, { id: 'chibi', type: 'square', @@ -101,21 +166,6 @@ export const homeScreenConfig: AppConfig = { value: 'chibi' } }, - { - id: 'emotions', - type: 'square', - background: { - type: 'gradient', - colors: ['#2B9CFF', '#1E88E5'] - }, - title: 'Эмоции', - imageUrl: images.emotions, - action: { - type: 'selectStyle', - value: 'emotions' - }, - disabled: true - }, { id: 'realism', type: 'square', @@ -145,31 +195,210 @@ export const homeScreenConfig: AppConfig = { text: 'Выбери образ' }, { - type: 'textInput', - id: 'customPrompt', + type: 'gridButtons', + id: 'emotionTypeSelection', + buttons: [ + { + id: 'prompts', + type: 'square', + background: { + type: 'gradient', + colors: ['#2B9CFF', '#1E88E5'] + }, + title: 'Коллекция', + action: { + type: 'selectEmotionType', + value: 'prompts' + } + }, + { + id: 'memes', + type: 'square', + background: { + type: 'gradient', + colors: ['#FF69B4', '#FF1493'] + }, + title: 'Мемы', + action: { + type: 'selectEmotionType', + value: 'memes' + } + } + ], style: { - padding: "4px 16px 16px" + gap: 8, + padding: "4px 16px 16px", + buttonSize: 100, + columns: 2 + } + }, + { + type: 'gridButtons', + id: 'memeSelection', + buttons: [ + { + id: 'meme1', + type: 'square', + background: { + type: 'gradient', + colors: ['#FF69B4', '#FF1493'] + }, + title: 'Мем 1', + imageUrl: '/src/assets/meme/1_250x.png', + action: { + type: 'selectMeme', + value: 'meme1' + } + }, + { + id: 'meme2', + type: 'square', + background: { + type: 'gradient', + colors: ['#2B9CFF', '#1E88E5'] + }, + title: 'Мем 2', + imageUrl: '/src/assets/meme/2_250x.png', + action: { + type: 'selectMeme', + value: 'meme2' + } + }, + { + id: 'meme3', + type: 'square', + background: { + type: 'gradient', + colors: ['#4CAF50', '#45A049'] + }, + title: 'Мем 3', + imageUrl: '/src/assets/meme/3_250x.png', + action: { + type: 'selectMeme', + value: 'meme3' + } + }, + { + id: 'meme4', + type: 'square', + background: { + type: 'gradient', + colors: ['#9C27B0', '#7B1FA2'] + }, + title: 'Мем 4', + imageUrl: '/src/assets/meme/4_250x.png', + action: { + type: 'selectMeme', + value: 'meme4' + } + }, + { + id: 'meme5', + type: 'square', + background: { + type: 'gradient', + colors: ['#FF5722', '#F4511E'] + }, + title: 'Мем 5', + imageUrl: '/src/assets/meme/5_250x.png', + action: { + type: 'selectMeme', + value: 'meme5' + } + }, + { + id: 'meme6', + type: 'square', + background: { + type: 'gradient', + colors: ['#FF9800', '#FB8C00'] + }, + title: 'Мем 6', + imageUrl: '/src/assets/meme/6_250x.png', + action: { + type: 'selectMeme', + value: 'meme6' + } + }, + { + id: 'meme7', + type: 'square', + background: { + type: 'gradient', + colors: ['#607D8B', '#455A64'] + }, + title: 'Мем 7', + imageUrl: '/src/assets/meme/7_250x.png', + action: { + type: 'selectMeme', + value: 'meme7' + } + }, + { + id: 'meme8', + type: 'square', + background: { + type: 'gradient', + colors: ['#795548', '#5D4037'] + }, + title: 'Мем 8', + imageUrl: '/src/assets/meme/8_250x.png', + action: { + type: 'selectMeme', + value: 'meme8' + } + }, + { + id: 'meme9', + type: 'square', + background: { + type: 'gradient', + colors: ['#009688', '#00796B'] + }, + title: 'Мем 9', + imageUrl: '/src/assets/meme/9_250x.png', + action: { + type: 'selectMeme', + value: 'meme9' + } + }, + { + id: 'meme10', + type: 'square', + background: { + type: 'gradient', + colors: ['#673AB7', '#512DA8'] + }, + title: 'Мем 10', + imageUrl: '/src/assets/meme/10_250x.png', + action: { + type: 'selectMeme', + value: 'meme10' + } + } + ], + style: { + gap: 8, + padding: "4px 16px 16px", + buttonSize: 100, + columns: 3 + } + }, + { + type: 'gridButtons', + id: 'emotionPromptsSelection', + buttons: [], + style: { + gap: 8, + padding: "4px 16px 16px", + buttonSize: 100, + columns: 3 } }, { type: 'gridButtons', id: 'quickActions', - buttons: [ - { - id: 'customPrompt', - type: 'square', - background: { - type: 'gradient', - colors: ['#2196F3', '#1976D2'] - }, - title: 'Свой промпт', - imageUrl: images.prompt, - action: { - type: 'function', - value: 'toggleInput' - } - } - ], + buttons: [], style: { gap: 8, padding: "4px 8px 16px", diff --git a/src/config/stylePresets.ts b/src/config/stylePresets.ts index 5d5a1e0..c4e8769 100644 --- a/src/config/stylePresets.ts +++ b/src/config/stylePresets.ts @@ -480,144 +480,510 @@ export const stylePresets: StylePresets = { }, emotions: { buttons: [ + // Базовые эмоции (отсортированы в начале) { - id: 'emotions-happy', + id: 'emotions-greeting', type: 'square', background: { type: 'gradient', - colors: ['#FFD700', '#FFA500'] + colors: ['#4CAF50', '#45A049'] }, - title: 'Радость', - icon: '😊', + title: 'Привет', + imageUrl: images.emoGreeting, action: { type: 'selectPreset', - value: 'happy' + value: 'greeting' } }, { - id: 'emotions-sad', + id: 'emotions-thumbsup', type: 'square', background: { type: 'gradient', colors: ['#2196F3', '#1976D2'] }, - title: 'Грусть', - icon: '😢', + title: 'Класс', + imageUrl: images.emoThumbsUp, action: { type: 'selectPreset', - value: 'sad' + value: 'thumbsup' } }, { - id: 'emotions-angry', - type: 'square', - background: { - type: 'gradient', - colors: ['#FF5722', '#F4511E'] - }, - title: 'Злость', - icon: '😠', - action: { - type: 'selectPreset', - value: 'angry' - } - }, - { - id: 'emotions-love', + id: 'emotions-heart', type: 'square', background: { type: 'gradient', colors: ['#FF69B4', '#FF1493'] }, - title: 'Любовь', - icon: '❤️', + title: 'Сердце', + imageUrl: images.emoHeart, action: { type: 'selectPreset', - value: 'love' + value: 'heart' } }, { - id: 'emotions-surprise', + id: 'emotions-laugh', + type: 'square', + background: { + type: 'gradient', + colors: ['#FFD700', '#FFA500'] + }, + title: 'Смех', + imageUrl: images.emoLaugh, + action: { + type: 'selectPreset', + value: 'laugh' + } + }, + { + id: 'emotions-shock', type: 'square', background: { type: 'gradient', colors: ['#9C27B0', '#7B1FA2'] }, - title: 'Удивление', - icon: '😲', + title: 'Шок', + imageUrl: images.emoShock, action: { type: 'selectPreset', - value: 'surprise' + value: 'shock' } }, { - id: 'emotions-fear', + id: 'emotions-threat', type: 'square', background: { type: 'gradient', - colors: ['#607D8B', '#455A64'] + colors: ['#FF5722', '#F4511E'] }, - title: 'Страх', - icon: '😱', + title: 'Угроза', + imageUrl: images.emoThreat, action: { type: 'selectPreset', - value: 'fear' + value: 'threat' } }, { - id: 'emotions-sleepy', - type: 'square', - background: { - type: 'gradient', - colors: ['#9575CD', '#7E57C2'] - }, - title: 'Сонный', - icon: '😴', - action: { - type: 'selectPreset', - value: 'sleepy' - } - }, - { - id: 'emotions-cool', - type: 'square', - background: { - type: 'gradient', - colors: ['#212121', '#000000'] - }, - title: 'Крутой', - icon: '😎', - action: { - type: 'selectPreset', - value: 'cool' - } - }, - { - id: 'emotions-silly', + id: 'emotions-hulk', type: 'square', background: { type: 'gradient', colors: ['#4CAF50', '#2E7D32'] }, - title: 'Глупый', - icon: '🤪', + title: 'Халк', + imageUrl: images.emoHulk, action: { type: 'selectPreset', - value: 'silly' + value: 'hulk' } }, { - id: 'emotions-thinking', + id: 'emotions-fire', + type: 'square', + background: { + type: 'gradient', + colors: ['#FF5722', '#F4511E'] + }, + title: 'Огонь', + imageUrl: images.emoFire, + action: { + type: 'selectPreset', + value: 'fire' + } + }, + { + id: 'emotions-tea', + type: 'square', + background: { + type: 'gradient', + colors: ['#795548', '#5D4037'] + }, + title: 'Чай', + imageUrl: images.emoTea, + action: { + type: 'selectPreset', + value: 'tea' + } + }, + { + id: 'emotions-dance', + type: 'square', + background: { + type: 'gradient', + colors: ['#9575CD', '#7E57C2'] + }, + title: 'Танец', + imageUrl: images.emoDance, + action: { + type: 'selectPreset', + value: 'dance' + } + }, + // Остальные эмоции + { + id: 'emotions-trophy', + type: 'square', + background: { + type: 'gradient', + colors: ['#FFD700', '#FFA500'] + }, + title: 'Трофей', + imageUrl: images.emoTrophy, + action: { + type: 'selectPreset', + value: 'trophy' + } + }, + { + id: 'emotions-teddybear', + type: 'square', + background: { + type: 'gradient', + colors: ['#795548', '#5D4037'] + }, + title: 'Мишка', + imageUrl: images.emoTeddyBear, + action: { + type: 'selectPreset', + value: 'teddybear' + } + }, + { + id: 'emotions-rose', + type: 'square', + background: { + type: 'gradient', + colors: ['#FF69B4', '#FF1493'] + }, + title: 'Роза', + imageUrl: images.emoRose, + action: { + type: 'selectPreset', + value: 'rose' + } + }, + { + id: 'emotions-gift', + type: 'square', + background: { + type: 'gradient', + colors: ['#FF69B4', '#FF1493'] + }, + title: 'Подарок', + imageUrl: images.emoGift, + action: { + type: 'selectPreset', + value: 'gift' + } + }, + { + id: 'emotions-flowers', + type: 'square', + background: { + type: 'gradient', + colors: ['#4CAF50', '#45A049'] + }, + title: 'Букет', + imageUrl: images.emoFlowers, + action: { + type: 'selectPreset', + value: 'flowers' + } + }, + { + id: 'emotions-karaoke', + type: 'square', + background: { + type: 'gradient', + colors: ['#9C27B0', '#7B1FA2'] + }, + title: 'Караоке', + imageUrl: images.emoKaraoke, + action: { + type: 'selectPreset', + value: 'karaoke' + } + }, + { + id: 'emotions-zombie', + type: 'square', + background: { + type: 'gradient', + colors: ['#4CAF50', '#2E7D32'] + }, + title: 'Зомби', + imageUrl: images.emoZombie, + action: { + type: 'selectPreset', + value: 'zombie' + } + }, + { + id: 'emotions-homeless', + type: 'square', + background: { + type: 'gradient', + colors: ['#607D8B', '#455A64'] + }, + title: 'Бездомный', + imageUrl: images.emoHomeless, + action: { + type: 'selectPreset', + value: 'homeless' + } + }, + { + id: 'emotions-beer', type: 'square', background: { type: 'gradient', colors: ['#FF9800', '#F57C00'] }, - title: 'Думающий', - icon: '🤔', + title: 'Пиво', + imageUrl: images.emoBeer, action: { type: 'selectPreset', - value: 'thinking' + value: 'beer' + } + }, + { + id: 'emotions-boxing', + type: 'square', + background: { + type: 'gradient', + colors: ['#FF5722', '#F4511E'] + }, + title: 'Бокс', + imageUrl: images.emoBoxing, + action: { + type: 'selectPreset', + value: 'boxing' + } + }, + { + id: 'emotions-kitten', + type: 'square', + background: { + type: 'gradient', + colors: ['#FF69B4', '#FF1493'] + }, + title: 'Котёнок', + imageUrl: images.emoKitten, + action: { + type: 'selectPreset', + value: 'kitten' + } + }, + { + id: 'emotions-puppy', + type: 'square', + background: { + type: 'gradient', + colors: ['#795548', '#5D4037'] + }, + title: 'Щенок', + imageUrl: images.emoPuppy, + action: { + type: 'selectPreset', + value: 'puppy' + } + }, + { + id: 'emotions-superhero', + type: 'square', + background: { + type: 'gradient', + colors: ['#3F51B5', '#303F9F'] + }, + title: 'Супергерой', + imageUrl: images.emoSuperhero, + action: { + type: 'selectPreset', + value: 'superhero' + } + }, + { + id: 'emotions-icecream', + type: 'square', + background: { + type: 'gradient', + colors: ['#00BCD4', '#0097A7'] + }, + title: 'Мороженое', + imageUrl: images.emoIceCream, + action: { + type: 'selectPreset', + value: 'icecream' + } + }, + { + id: 'emotions-wizard', + type: 'square', + background: { + type: 'gradient', + colors: ['#9C27B0', '#7B1FA2'] + }, + title: 'Волшебник', + imageUrl: images.emoWizard, + action: { + type: 'selectPreset', + value: 'wizard' + } + }, + { + id: 'emotions-dragon', + type: 'square', + background: { + type: 'gradient', + colors: ['#FF5722', '#F4511E'] + }, + title: 'Дракон', + imageUrl: images.emoDragon, + action: { + type: 'selectPreset', + value: 'dragon' + } + }, + { + id: 'emotions-cyberpunk', + type: 'square', + background: { + type: 'gradient', + colors: ['#212121', '#000000'] + }, + title: 'Киберпанк', + imageUrl: images.emoCyberpunk, + action: { + type: 'selectPreset', + value: 'cyberpunk' + } + }, + { + id: 'emotions-mage', + type: 'square', + background: { + type: 'gradient', + colors: ['#3F51B5', '#303F9F'] + }, + title: 'Маг', + imageUrl: images.emoMage, + action: { + type: 'selectPreset', + value: 'mage' + } + }, + { + id: 'emotions-pirate', + type: 'square', + background: { + type: 'gradient', + colors: ['#795548', '#5D4037'] + }, + title: 'Пират', + imageUrl: images.emoPirate, + action: { + type: 'selectPreset', + value: 'pirate' + } + }, + { + id: 'emotions-samurai', + type: 'square', + background: { + type: 'gradient', + colors: ['#212121', '#000000'] + }, + title: 'Самурай', + imageUrl: images.emoSamurai, + action: { + type: 'selectPreset', + value: 'samurai' + } + }, + { + id: 'emotions-scientist', + type: 'square', + background: { + type: 'gradient', + colors: ['#607D8B', '#455A64'] + }, + title: 'Учёный', + imageUrl: images.emoScientist, + action: { + type: 'selectPreset', + value: 'scientist' + } + }, + { + id: 'emotions-wine', + type: 'square', + background: { + type: 'gradient', + colors: ['#9C27B0', '#7B1FA2'] + }, + title: 'Вино', + imageUrl: images.emoWine, + action: { + type: 'selectPreset', + value: 'wine' + } + }, + { + id: 'emotions-slime', + type: 'square', + background: { + type: 'gradient', + colors: ['#4CAF50', '#2E7D32'] + }, + title: 'Слизь', + imageUrl: images.emoSlime, + action: { + type: 'selectPreset', + value: 'slime' + } + }, + { + id: 'emotions-rider', + type: 'square', + background: { + type: 'gradient', + colors: ['#795548', '#5D4037'] + }, + title: 'Всадник', + imageUrl: images.emoRider, + action: { + type: 'selectPreset', + value: 'rider' + } + }, + { + id: 'emotions-drstrange', + type: 'square', + background: { + type: 'gradient', + colors: ['#3F51B5', '#303F9F'] + }, + title: 'Доктор Стрэндж', + imageUrl: images.emoDrStrange, + action: { + type: 'selectPreset', + value: 'drstrange' + } + }, + { + id: 'emotions-captainamerica', + type: 'square', + background: { + type: 'gradient', + colors: ['#3F51B5', '#303F9F'] + }, + title: 'Капитан Америка', + imageUrl: images.emoCaptainAmerica, + action: { + type: 'selectPreset', + value: 'captainamerica' } } ] diff --git a/src/constants/workflows/chibiWorkflow.ts b/src/constants/workflows/chibiWorkflow.ts new file mode 100644 index 0000000..13e8ca9 --- /dev/null +++ b/src/constants/workflows/chibiWorkflow.ts @@ -0,0 +1,637 @@ +// Воркфлоу для стиля Chibi с выбором пола +export const chibiWorkflow = { + "305": { + "inputs": { + "ckpt_name": "dreamshaperXL_lightningDPMSDE.safetensors" + }, + "class_type": "CheckpointLoaderSimple", + "_meta": { + "title": "Загрузить контрольную точку" + } + }, + "307": { + "inputs": { + "share_norm": "both", + "share_attn": "q+k", + "scale": 0.7000000000000001, + "model": [ + "309", + 0 + ] + }, + "class_type": "StyleAlignedBatchAlign", + "_meta": { + "title": "StyleAligned Batch Align" + } + }, + "308": { + "inputs": { + "text_positive": "Sticker,chibi:2,Flat:1.5,(full body:2),Simple details,(Empty Background:2)", + "text_negative": "Realism, photo-realism, real materials,(full body:2)", + "style": "sai-cinematic", + "log_prompt": false, + "style_positive": true, + "style_negative": true + }, + "class_type": "SDXLPromptStyler", + "_meta": { + "title": "SDXL Prompt Styler" + } + }, + "309": { + "inputs": { + "b1": 1.3, + "b2": 1.4000000000000001, + "s1": 0.9, + "s2": 0.2, + "model": [ + "406", + 0 + ] + }, + "class_type": "FreeU_V2", + "_meta": { + "title": "FreeU_V2" + } + }, + "312": { + "inputs": { + "text": [ + "308", + 1 + ], + "clip": [ + "406", + 1 + ] + }, + "class_type": "CLIPTextEncode", + "_meta": { + "title": "Кодирование текста CLIP (Запрос)" + } + }, + "313": { + "inputs": { + "prompt_1": "Boxers, with red boxing gloves, swinging their fists", + "prompt_2": "Dressed in a Superman costume", + "prompt_3": "Dress up as Santa Claus with a rattle in your hand", + "prompt_4": "Holding a bouquet of roses in his hand and wearing a gown", + "prompt_5": "Dressed in a wide hip hop suit,Playing the guitar,tattooing,denim,street dance,dancing", + "simple_prompt_list": [ + "316", + 0 + ] + }, + "class_type": "CR Simple Prompt List", + "_meta": { + "title": "CR Simple Prompt List (Legacy)" + } + }, + "314": { + "inputs": { + "keyframe_interval": 1, + "loops": 1, + "transition_type": "Default", + "transition_speed": "Default", + "transition_profile": "Default", + "keyframe_format": "Deforum", + "simple_prompt_list": [ + "313", + 0 + ] + }, + "class_type": "CR Simple Prompt List Keyframes", + "_meta": { + "title": "CR Simple Prompt List Keyframes (Legacy)" + } + }, + "316": { + "inputs": { + "prompt_1": "military clothes", + "prompt_2": "Pirate captain with a sword", + "prompt_3": "Drinking coffee from a coffee cup and smiling", + "prompt_4": "Dressed in a spacesuit and wearing a glass helmet", + "prompt_5": "Wearing luxurious clothes, holding a red heart-shaped balloon and smiling" + }, + "class_type": "CR Simple Prompt List", + "_meta": { + "title": "CR Simple Prompt List (Legacy)" + } + }, + "318": { + "inputs": {}, + "class_type": "Anything Everywhere3", + "_meta": { + "title": "Anything Everywhere3" + } + }, + "326": { + "inputs": { + "image": "photo_2025-02-03_14-06-19.jpg", + "upload": "image" + }, + "class_type": "LoadImage", + "_meta": { + "title": "Загрузить изображение" + } + }, + "328": { + "inputs": { + "seed": [ + "404", + 0 + ], + "steps": 7, + "cfg": 2, + "sampler_name": "dpmpp_2m", + "scheduler": "karras", + "denoise": 1, + "preview_method": "auto", + "vae_decode": "true", + "model": [ + "347", + 0 + ], + "positive": [ + "339", + 0 + ], + "negative": [ + "312", + 0 + ], + "latent_image": [ + "348", + 0 + ], + "optional_vae": [ + "305", + 2 + ] + }, + "class_type": "KSampler (Efficient)", + "_meta": { + "title": "KSampler (Efficient)" + } + }, + "339": { + "inputs": { + "text": [ + "314", + 0 + ], + "max_frames": 10, + "print_output": false, + "pre_text": [ + "308", + 0 + ], + "app_text": [ + "523", + 0 + ], + "start_frame": 0, + "end_frame": 0, + "clip": [ + "406", + 1 + ] + }, + "class_type": "BatchPromptSchedule", + "_meta": { + "title": "Batch Prompt Schedule 📅🅕🅝" + } + }, + "344": { + "inputs": { + "pulid_file": "ip-adapter_pulid_sdxl_fp16.safetensors" + }, + "class_type": "PulidModelLoader", + "_meta": { + "title": "Load PuLID Model" + } + }, + "345": { + "inputs": { + "provider": "CUDA" + }, + "class_type": "PulidInsightFaceLoader", + "_meta": { + "title": "Load InsightFace (PuLID)" + } + }, + "346": { + "inputs": {}, + "class_type": "PulidEvaClipLoader", + "_meta": { + "title": "Load Eva Clip (PuLID)" + } + }, + "347": { + "inputs": { + "method": "fidelity", + "weight": 1, + "start_at": 0, + "end_at": 1, + "model": [ + "307", + 0 + ], + "pulid": [ + "344", + 0 + ], + "eva_clip": [ + "346", + 0 + ], + "face_analysis": [ + "345", + 0 + ], + "image": [ + "384", + 0 + ] + }, + "class_type": "ApplyPulid", + "_meta": { + "title": "Apply PuLID" + } + }, + "348": { + "inputs": { + "width": 768, + "height": 768, + "batch_size": 1 + }, + "class_type": "EmptyLatentImage", + "_meta": { + "title": "Пустое латентное изображение" + } + }, + "376": { + "inputs": { + "rmbgmodel": [ + "377", + 0 + ], + "image": [ + "378", + 5 + ] + }, + "class_type": "BRIA_RMBG_Zho", + "_meta": { + "title": "🧹BRIA RMBG" + } + }, + "377": { + "inputs": {}, + "class_type": "BRIA_RMBG_ModelLoader_Zho", + "_meta": { + "title": "🧹BRIA_RMBG Model Loader" + } + }, + "378": { + "inputs": { + "seed": [ + "404", + 0 + ], + "steps": 6, + "cfg": 2, + "sampler_name": "dpmpp_2m", + "scheduler": "karras", + "denoise": 0.6, + "preview_method": "auto", + "vae_decode": "true", + "model": [ + "382", + 0 + ], + "positive": [ + "382", + 1 + ], + "negative": [ + "382", + 2 + ], + "latent_image": [ + "417", + 0 + ], + "optional_vae": [ + "305", + 2 + ] + }, + "class_type": "KSampler (Efficient)", + "_meta": { + "title": "KSampler (Efficient)" + } + }, + "379": { + "inputs": { + "instantid_file": "ip-adapter.bin" + }, + "class_type": "InstantIDModelLoader", + "_meta": { + "title": "Load InstantID Model" + } + }, + "380": { + "inputs": { + "control_net_name": "diffusion_pytorch_model.safetensors" + }, + "class_type": "ControlNetLoader", + "_meta": { + "title": "Загрузить модель ControlNet" + } + }, + "381": { + "inputs": { + "provider": "CUDA" + }, + "class_type": "InstantIDFaceAnalysis", + "_meta": { + "title": "InstantID Face Analysis" + } + }, + "382": { + "inputs": { + "weight": 1, + "start_at": 0, + "end_at": 1, + "instantid": [ + "379", + 0 + ], + "insightface": [ + "381", + 0 + ], + "control_net": [ + "380", + 0 + ], + "image": [ + "384", + 0 + ], + "model": [ + "307", + 0 + ], + "positive": [ + "328", + 1 + ], + "negative": [ + "328", + 2 + ], + "image_kps": [ + "328", + 5 + ] + }, + "class_type": "ApplyInstantID", + "_meta": { + "title": "Apply InstantID" + } + }, + "384": { + "inputs": { + "side_length": 512, + "side": "Longest", + "upscale_method": "nearest-exact", + "crop": "disabled", + "image": [ + "563", + 0 + ] + }, + "class_type": "DF_Image_scale_to_side", + "_meta": { + "title": "Image scale to side" + } + }, + "404": { + "inputs": { + "seed": 0 + }, + "class_type": "Seed Everywhere", + "_meta": { + "title": "Seed Everywhere" + } + }, + "405": { + "inputs": { + "toggle": true, + "mode": "simple", + "num_loras": 3, + "lora_1_name": "StickersRedmond.safetensors", + "lora_1_strength": 1, + "lora_1_model_strength": 2, + "lora_1_clip_strength": 2, + "lora_2_name": "cartoon_style.pt", + "lora_2_strength": 2, + "lora_2_model_strength": 1, + "lora_2_clip_strength": 1, + "lora_3_name": "smiling.pt", + "lora_3_strength": 2, + "lora_3_model_strength": 2, + "lora_3_clip_strength": 1, + "lora_4_name": "None", + "lora_4_strength": 1, + "lora_4_model_strength": 1, + "lora_4_clip_strength": 1, + "lora_5_name": "None", + "lora_5_strength": 1, + "lora_5_model_strength": 1, + "lora_5_clip_strength": 1, + "lora_6_name": "None", + "lora_6_strength": 1, + "lora_6_model_strength": 1, + "lora_6_clip_strength": 1, + "lora_7_name": "None", + "lora_7_strength": 1, + "lora_7_model_strength": 1, + "lora_7_clip_strength": 1, + "lora_8_name": "None", + "lora_8_strength": 1, + "lora_8_model_strength": 1, + "lora_8_clip_strength": 1, + "lora_9_name": "None", + "lora_9_strength": 1, + "lora_9_model_strength": 1, + "lora_9_clip_strength": 1, + "lora_10_name": "None", + "lora_10_strength": 1, + "lora_10_model_strength": 1, + "lora_10_clip_strength": 1 + }, + "class_type": "easy loraStack", + "_meta": { + "title": "EasyLoraStack" + } + }, + "406": { + "inputs": { + "model": [ + "305", + 0 + ], + "clip": [ + "305", + 1 + ], + "lora_stack": [ + "405", + 0 + ] + }, + "class_type": "CR Apply LoRA Stack", + "_meta": { + "title": "💊 CR Apply LoRA Stack" + } + }, + "417": { + "inputs": { + "upscale_method": "nearest-exact", + "width": 1024, + "height": 1024, + "crop": "disabled", + "samples": [ + "328", + 3 + ] + }, + "class_type": "LatentUpscale", + "_meta": { + "title": "Увеличить латент" + } + }, + "523": { + "inputs": { + "text": [ + "564", + 0 + ] + }, + "class_type": "ShowText|pysssss", + "_meta": { + "title": "✴️ U-NAI Get Text" + } + }, + "536": { + "inputs": { + "text_input": "Identify if the person in the image is a man, woman, boy or girl. Answer with just one word.", + "model_name": "Qwen2-VL-2B", + "memory_mode": "Balanced (8-bit)", + "max_new_tokens": 512, + "temperature": 0.7000000000000001, + "top_p": 0.8, + "fps": 1, + "image": [ + "555", + 0 + ] + }, + "class_type": "Qwen2VLNode", + "_meta": { + "title": "Qwen2-VL Model" + } + }, + "539": { + "inputs": { + "aggressive": false, + "image": [ + "376", + 0 + ] + }, + "class_type": "FreeMemoryImage", + "_meta": { + "title": "Free Memory (Image)" + } + }, + "555": { + "inputs": { + "width": 762, + "height": 762, + "method": "lanczos", + "images": [ + "563", + 0 + ] + }, + "class_type": "ImageTransformResizeAbsolute", + "_meta": { + "title": "ImageTransformResizeAbsolute" + } + }, + "556": { + "inputs": { + "images": [ + "555", + 0 + ] + }, + "class_type": "PreviewImage", + "_meta": { + "title": "Предварительный просмотр изображения" + } + }, + "562": { + "inputs": { + "Actions": "Send to websocket", + "images": [ + "539", + 0 + ] + }, + "class_type": "ImageOutput", + "_meta": { + "title": "Image(s) To Websocket (Base64)" + } + }, + "563": { + "inputs": { + "image": "" + }, + "class_type": "Load Image (Base64)", + "_meta": { + "title": "Load Image (Base64)" + } + }, + "564": { + "inputs": { + "select": 1, + "sel_mode": false, + "input1": [ + "536", + 0 + ], + "input2": [ + "565", + 0 + ] + }, + "class_type": "ImpactSwitch", + "_meta": { + "title": "Switch (Any)" + } + }, + "565": { + "inputs": { + "text": "" + }, + "class_type": "CR Text", + "_meta": { + "title": "🔤 CR Text" + } + } +}; diff --git a/src/constants/workflows/index.ts b/src/constants/workflows/index.ts new file mode 100644 index 0000000..ae4e6ef --- /dev/null +++ b/src/constants/workflows/index.ts @@ -0,0 +1,30 @@ +// Типы воркфлоу +export enum WorkflowType { + CHIBI = 'chibi', + PROMPT = 'prompt', + MEME = 'meme' +} + +// Импорт воркфлоу +import { chibiWorkflow } from './chibiWorkflow'; +import { promptWorkflow } from './promptWorkflow'; +import { memeWorkflow } from './memeWorkflow'; + +// Функция для получения воркфлоу по типу +export const getWorkflowByType = (type: WorkflowType) => { + switch (type) { + case WorkflowType.CHIBI: + return chibiWorkflow; + case WorkflowType.PROMPT: + return promptWorkflow; + case WorkflowType.MEME: + return memeWorkflow; + default: + return chibiWorkflow; // По умолчанию возвращаем chibi + } +}; + +// Экспорт всех воркфлоу +export { chibiWorkflow } from './chibiWorkflow'; +export { promptWorkflow } from './promptWorkflow'; +export { memeWorkflow } from './memeWorkflow'; diff --git a/src/constants/workflows/memeWorkflow.ts b/src/constants/workflows/memeWorkflow.ts new file mode 100644 index 0000000..02f6d4d --- /dev/null +++ b/src/constants/workflows/memeWorkflow.ts @@ -0,0 +1,581 @@ +// Воркфлоу для нового стиля с мемами +export const memeWorkflow = { + "376": { + "inputs": { + "rmbgmodel": [ + "615", + 0 + ], + "image": [ + "606", + 0 + ] + }, + "class_type": "BRIA_RMBG_Zho", + "_meta": { + "title": "🧹BRIA RMBG" + } + }, + "379": { + "inputs": { + "instantid_file": "ip-adapter.bin" + }, + "class_type": "InstantIDModelLoader", + "_meta": { + "title": "Load InstantID Model" + } + }, + "380": { + "inputs": { + "control_net_name": "diffusion_pytorch_model.safetensors" + }, + "class_type": "ControlNetLoader", + "_meta": { + "title": "Загрузить модель ControlNet" + } + }, + "523": { + "inputs": { + "text": [ + "689", + 0 + ], + "text2": "man" + }, + "class_type": "ShowText|pysssss", + "_meta": { + "title": "✴️ U-NAI Get Text" + } + }, + "536": { + "inputs": { + "text_input": "Identify if the person in the image is a man, woman, boy or girl. Answer with just one word.", + "model_name": "Qwen2-VL-2B", + "memory_mode": "Balanced (8-bit)", + "max_new_tokens": 512, + "temperature": 0.7000000000000001, + "top_p": 0.8, + "fps": 1, + "image": [ + "563", + 0 + ] + }, + "class_type": "Qwen2VLNode", + "_meta": { + "title": "Qwen2-VL Model" + } + }, + "539": { + "inputs": { + "aggressive": false, + "image": [ + "376", + 0 + ] + }, + "class_type": "FreeMemoryImage", + "_meta": { + "title": "Free Memory (Image)" + } + }, + "562": { + "inputs": { + "Actions": "Send to websocket", + "images": [ + "539", + 0 + ] + }, + "class_type": "ImageOutput", + "_meta": { + "title": "Image(s) To Websocket (Base64)" + } + }, + "563": { + "inputs": { + "image": "" + }, + "class_type": "Load Image (Base64)", + "_meta": { + "title": "Load Image (Base64)" + } + }, + "566": { + "inputs": { + "seed": 698459364937105, + "steps": 8, + "cfg": 4, + "sampler_name": "dpmpp_2m_sde", + "scheduler": "karras", + "denoise": 1, + "preview_method": "auto", + "vae_decode": "true", + "model": [ + "576", + 0 + ], + "positive": [ + "590", + 0 + ], + "negative": [ + "588", + 0 + ], + "latent_image": [ + "591", + 0 + ], + "optional_vae": [ + "575", + 2 + ] + }, + "class_type": "KSampler (Efficient)", + "_meta": { + "title": "KSampler (Efficient)" + } + }, + "567": { + "inputs": { + "seed": 711685301954594, + "steps": 10, + "cfg": 4, + "sampler_name": "euler", + "scheduler": "karras", + "denoise": 1, + "preview_method": "auto", + "vae_decode": "true", + "model": [ + "582", + 0 + ], + "positive": [ + "582", + 1 + ], + "negative": [ + "582", + 2 + ], + "latent_image": [ + "577", + 0 + ], + "optional_vae": [ + "575", + 2 + ] + }, + "class_type": "KSampler (Efficient)", + "_meta": { + "title": "KSampler (Efficient)" + } + }, + "569": { + "inputs": { + "text": ", Sticker, svg, vector art, sharp, kawaii style, Anime style" + }, + "class_type": "CR Text", + "_meta": { + "title": "🔤 CR Text" + } + }, + "570": { + "inputs": { + "text": "shiny, photo, photography, soft, nsfw, nude, ugly, broken, watermark, oversaturated" + }, + "class_type": "CR Text", + "_meta": { + "title": "🔤 CR Text" + } + }, + "571": { + "inputs": { + "text": "half body, simple T-shirt" + }, + "class_type": "CR Text", + "_meta": { + "title": "🔤 CR Text" + } + }, + "573": { + "inputs": { + "provider": "CUDA" + }, + "class_type": "InstantIDFaceAnalysis", + "_meta": { + "title": "InstantID Face Analysis" + } + }, + "575": { + "inputs": { + "ckpt_name": "dreamshaperXL_lightningDPMSDE.safetensors" + }, + "class_type": "CheckpointLoaderSimple", + "_meta": { + "title": "Загрузить контрольную точку" + } + }, + "576": { + "inputs": { + "hard_mode": true, + "boost": true, + "model": [ + "575", + 0 + ] + }, + "class_type": "Automatic CFG", + "_meta": { + "title": "Automatic CFG" + } + }, + "577": { + "inputs": { + "width": 1016, + "height": 1016, + "batch_size": 1 + }, + "class_type": "EmptyLatentImage", + "_meta": { + "title": "Пустое латентное изображение" + } + }, + "578": { + "inputs": { + "lora_name": "StickersRedmond.safetensors", + "strength_model": 0.9, + "strength_clip": 1, + "model": [ + "575", + 0 + ], + "clip": [ + "575", + 1 + ] + }, + "class_type": "LoraLoader", + "_meta": { + "title": "Загрузить LoRA" + } + }, + "579": { + "inputs": { + "hard_mode": true, + "boost": true, + "model": [ + "578", + 0 + ] + }, + "class_type": "Automatic CFG", + "_meta": { + "title": "Automatic CFG" + } + }, + "580": { + "inputs": { + "delimiter": "", + "clean_whitespace": "false", + "text_a": [ + "589", + 0 + ], + "text_b": [ + "569", + 0 + ] + }, + "class_type": "Text Concatenate", + "_meta": { + "title": "Text Concatenate" + } + }, + "581": { + "inputs": { + "text": [ + "580", + 0 + ], + "clip": [ + "578", + 1 + ] + }, + "class_type": "CLIPTextEncode", + "_meta": { + "title": "Кодирование текста CLIP (Запрос)" + } + }, + "582": { + "inputs": { + "weight": 1, + "start_at": 0, + "end_at": 1, + "instantid": [ + "379", + 0 + ], + "insightface": [ + "573", + 0 + ], + "control_net": [ + "380", + 0 + ], + "image": [ + "584", + 0 + ], + "model": [ + "579", + 0 + ], + "positive": [ + "581", + 0 + ], + "negative": [ + "583", + 0 + ], + "image_kps": [ + "608", + 0 + ] + }, + "class_type": "ApplyInstantID", + "_meta": { + "title": "Apply InstantID" + } + }, + "583": { + "inputs": { + "text": [ + "570", + 0 + ], + "clip": [ + "578", + 1 + ] + }, + "class_type": "CLIPTextEncode", + "_meta": { + "title": "Кодирование текста CLIP (Запрос)" + } + }, + "584": { + "inputs": { + "upscale_method": "lanczos", + "megapixels": 1, + "image": [ + "563", + 0 + ] + }, + "class_type": "ImageScaleToTotalPixels", + "_meta": { + "title": "Масштабировать изображение до общего количества пикселей" + } + }, + "585": { + "inputs": { + "text": "" + }, + "class_type": "CR Text", + "_meta": { + "title": "🔤 CR Text" + } + }, + "588": { + "inputs": { + "text": [ + "570", + 0 + ], + "clip": [ + "575", + 1 + ] + }, + "class_type": "CLIPTextEncode", + "_meta": { + "title": "Кодирование текста CLIP (Запрос)" + } + }, + "589": { + "inputs": { + "delimiter": "", + "clean_whitespace": "false", + "text_a": [ + "609", + 0 + ], + "text_b": [ + "585", + 0 + ] + }, + "class_type": "Text Concatenate", + "_meta": { + "title": "Text Concatenate" + } + }, + "590": { + "inputs": { + "text": [ + "589", + 0 + ], + "clip": [ + "575", + 1 + ] + }, + "class_type": "CLIPTextEncode", + "_meta": { + "title": "Кодирование текста CLIP (Запрос)" + } + }, + "591": { + "inputs": { + "width": 1024, + "height": 1024, + "batch_size": 1 + }, + "class_type": "EmptyLatentImage", + "_meta": { + "title": "Пустое латентное изображение" + } + }, + "603": { + "inputs": { + "image": "Patrick Bateman Ou.png", + "upload": "image" + }, + "class_type": "LoadImage", + "_meta": { + "title": "face" + } + }, + "606": { + "inputs": { + "rotate_pitch": 0, + "rotate_yaw": 0, + "rotate_roll": 0, + "blink": 0, + "eyebrow": 0, + "wink": 0, + "pupil_x": 0, + "pupil_y": 0, + "aaa": 0, + "eee": 0, + "woo": 0, + "smile": 0.01, + "src_ratio": 1, + "sample_ratio": 0.8, + "sample_parts": "OnlyExpression", + "crop_factor": 1.7, + "src_image": [ + "567", + 5 + ], + "sample_image": [ + "603", + 0 + ] + }, + "class_type": "ExpressionEditor", + "_meta": { + "title": "Expression Editor (PHM)" + } + }, + "608": { + "inputs": { + "rotate_pitch": 0, + "rotate_yaw": 0, + "rotate_roll": 0, + "blink": 0, + "eyebrow": 0, + "wink": 0, + "pupil_x": 0, + "pupil_y": 0, + "aaa": 0, + "eee": 0, + "woo": 0, + "smile": 0, + "src_ratio": 1, + "sample_ratio": 1, + "sample_parts": "All", + "crop_factor": 1.7000000000000002, + "src_image": [ + "566", + 5 + ], + "sample_image": [ + "603", + 0 + ] + }, + "class_type": "ExpressionEditor", + "_meta": { + "title": "Expression Editor (PHM)" + } + }, + "609": { + "inputs": { + "separator": ", ", + "arg1": [ + "523", + 0 + ], + "arg2": [ + "571", + 0 + ] + }, + "class_type": "PromptUtilitiesJoinStringList", + "_meta": { + "title": "Join String List" + } + }, + "615": { + "inputs": {}, + "class_type": "BRIA_RMBG_ModelLoader_Zho", + "_meta": { + "title": "🧹BRIA_RMBG Model Loader" + } + }, + "689": { + "inputs": { + "select": 1, + "sel_mode": false, + "input1": [ + "536", + 0 + ], + "input2": [ + "769", + 0 + ] + }, + "class_type": "ImpactSwitch", + "_meta": { + "title": "Switch (Any)" + } + }, + "769": { + "inputs": { + "text": "man" + }, + "class_type": "CR Text", + "_meta": { + "title": "🔤 CR Text" + } + } +}; diff --git a/src/constants/workflows/promptWorkflow.ts b/src/constants/workflows/promptWorkflow.ts new file mode 100644 index 0000000..14ab616 --- /dev/null +++ b/src/constants/workflows/promptWorkflow.ts @@ -0,0 +1,558 @@ +// Воркфлоу для нового стиля с промптами +export const promptWorkflow = { + "326": { + "inputs": { + "image": "girl2.png", + "upload": "image" + }, + "class_type": "LoadImage", + "_meta": { + "title": "Загрузить изображение" + } + }, + "376": { + "inputs": { + "rmbgmodel": [ + "615", + 0 + ], + "image": [ + "606", + 0 + ] + }, + "class_type": "BRIA_RMBG_Zho", + "_meta": { + "title": "🧹BRIA RMBG" + } + }, + "379": { + "inputs": { + "instantid_file": "ip-adapter.bin" + }, + "class_type": "InstantIDModelLoader", + "_meta": { + "title": "Load InstantID Model" + } + }, + "380": { + "inputs": { + "control_net_name": "diffusion_pytorch_model.safetensors" + }, + "class_type": "ControlNetLoader", + "_meta": { + "title": "Загрузить модель ControlNet" + } + }, + "523": { + "inputs": { + "text": [ + "689", + 0 + ], + "text2": "girl" + }, + "class_type": "ShowText|pysssss", + "_meta": { + "title": "✴️ U-NAI Get Text" + } + }, + "536": { + "inputs": { + "text_input": "Identify if the person in the image is a man, woman, boy or girl. Answer with just one word.", + "model_name": "Qwen2-VL-2B", + "memory_mode": "Balanced (8-bit)", + "max_new_tokens": 512, + "temperature": 0.7000000000000001, + "top_p": 0.8, + "fps": 1, + "image": [ + "563", + 0 + ] + }, + "class_type": "Qwen2VLNode", + "_meta": { + "title": "Qwen2-VL Model" + } + }, + "539": { + "inputs": { + "aggressive": false, + "image": [ + "376", + 0 + ] + }, + "class_type": "FreeMemoryImage", + "_meta": { + "title": "Free Memory (Image)" + } + }, + "562": { + "inputs": { + "Actions": "Send to websocket", + "images": [ + "539", + 0 + ] + }, + "class_type": "ImageOutput", + "_meta": { + "title": "Image(s) To Websocket (Base64)" + } + }, + "563": { + "inputs": { + "image": "" + }, + "class_type": "Load Image (Base64)", + "_meta": { + "title": "Load Image (Base64)" + } + }, + "566": { + "inputs": { + "seed": 866300843763550, + "steps": 10, + "cfg": 4, + "sampler_name": "dpmpp_2m_sde", + "scheduler": "karras", + "denoise": 1, + "preview_method": "auto", + "vae_decode": "true", + "model": [ + "576", + 0 + ], + "positive": [ + "590", + 0 + ], + "negative": [ + "588", + 0 + ], + "latent_image": [ + "591", + 0 + ], + "optional_vae": [ + "575", + 2 + ] + }, + "class_type": "KSampler (Efficient)", + "_meta": { + "title": "KSampler (Efficient)" + } + }, + "567": { + "inputs": { + "seed": 378971921426134, + "steps": 10, + "cfg": 4, + "sampler_name": "euler", + "scheduler": "karras", + "denoise": 1, + "preview_method": "auto", + "vae_decode": "true", + "model": [ + "582", + 0 + ], + "positive": [ + "582", + 1 + ], + "negative": [ + "582", + 2 + ], + "latent_image": [ + "577", + 0 + ], + "optional_vae": [ + "575", + 2 + ] + }, + "class_type": "KSampler (Efficient)", + "_meta": { + "title": "KSampler (Efficient)" + } + }, + "569": { + "inputs": { + "text": ", Sticker, svg, vector art, sharp" + }, + "class_type": "CR Text", + "_meta": { + "title": "🔤 CR Text" + } + }, + "570": { + "inputs": { + "text": "shiny, photo, photography, soft, nsfw, nude, ugly, broken, watermark, oversaturated, naked" + }, + "class_type": "CR Text", + "_meta": { + "title": "🔤 CR Text" + } + }, + "571": { + "inputs": { + "text": "" + }, + "class_type": "CR Text", + "_meta": { + "title": "🔤 CR Text" + } + }, + "573": { + "inputs": { + "provider": "CUDA" + }, + "class_type": "InstantIDFaceAnalysis", + "_meta": { + "title": "InstantID Face Analysis" + } + }, + "575": { + "inputs": { + "ckpt_name": "dreamshaperXL_lightningDPMSDE.safetensors" + }, + "class_type": "CheckpointLoaderSimple", + "_meta": { + "title": "Загрузить контрольную точку" + } + }, + "576": { + "inputs": { + "hard_mode": true, + "boost": true, + "model": [ + "575", + 0 + ] + }, + "class_type": "Automatic CFG", + "_meta": { + "title": "Automatic CFG" + } + }, + "577": { + "inputs": { + "width": 1016, + "height": 1016, + "batch_size": 1 + }, + "class_type": "EmptyLatentImage", + "_meta": { + "title": "Пустое латентное изображение" + } + }, + "578": { + "inputs": { + "lora_name": "StickersRedmond.safetensors", + "strength_model": 1, + "strength_clip": 1, + "model": [ + "575", + 0 + ], + "clip": [ + "575", + 1 + ] + }, + "class_type": "LoraLoader", + "_meta": { + "title": "Загрузить LoRA" + } + }, + "579": { + "inputs": { + "hard_mode": true, + "boost": true, + "model": [ + "578", + 0 + ] + }, + "class_type": "Automatic CFG", + "_meta": { + "title": "Automatic CFG" + } + }, + "580": { + "inputs": { + "delimiter": "", + "clean_whitespace": "false", + "text_a": [ + "589", + 0 + ], + "text_b": [ + "569", + 0 + ] + }, + "class_type": "Text Concatenate", + "_meta": { + "title": "Text Concatenate" + } + }, + "581": { + "inputs": { + "text": [ + "580", + 0 + ], + "clip": [ + "578", + 1 + ] + }, + "class_type": "CLIPTextEncode", + "_meta": { + "title": "Кодирование текста CLIP (Запрос)" + } + }, + "582": { + "inputs": { + "weight": 1, + "start_at": 0, + "end_at": 1, + "instantid": [ + "379", + 0 + ], + "insightface": [ + "573", + 0 + ], + "control_net": [ + "380", + 0 + ], + "image": [ + "584", + 0 + ], + "model": [ + "579", + 0 + ], + "positive": [ + "581", + 0 + ], + "negative": [ + "583", + 0 + ], + "image_kps": [ + "566", + 5 + ] + }, + "class_type": "ApplyInstantID", + "_meta": { + "title": "Apply InstantID" + } + }, + "583": { + "inputs": { + "text": [ + "570", + 0 + ], + "clip": [ + "578", + 1 + ] + }, + "class_type": "CLIPTextEncode", + "_meta": { + "title": "Кодирование текста CLIP (Запрос)" + } + }, + "584": { + "inputs": { + "upscale_method": "lanczos", + "megapixels": 1, + "image": [ + "563", + 0 + ] + }, + "class_type": "ImageScaleToTotalPixels", + "_meta": { + "title": "Масштабировать изображение до общего количества пикселей" + } + }, + "585": { + "inputs": { + "text": "Half of body, full face, holding a tiny capybara with both hands, looking at it with exaggerated amazement. Conveying love and adoration for pets" + }, + "class_type": "CR Text", + "_meta": { + "title": "🔤 CR Text" + } + }, + "587": { + "inputs": { + "filename_prefix": "ComfyUI" + }, + "class_type": "SaveImage", + "_meta": { + "title": "Сохранить изображение" + } + }, + "588": { + "inputs": { + "text": [ + "570", + 0 + ], + "clip": [ + "575", + 1 + ] + }, + "class_type": "CLIPTextEncode", + "_meta": { + "title": "Кодирование текста CLIP (Запрос)" + } + }, + "589": { + "inputs": { + "delimiter": "", + "clean_whitespace": "false", + "text_a": [ + "609", + 0 + ], + "text_b": [ + "585", + 0 + ] + }, + "class_type": "Text Concatenate", + "_meta": { + "title": "Text Concatenate" + } + }, + "590": { + "inputs": { + "text": [ + "589", + 0 + ], + "clip": [ + "575", + 1 + ] + }, + "class_type": "CLIPTextEncode", + "_meta": { + "title": "Кодирование текста CLIP (Запрос)" + } + }, + "591": { + "inputs": { + "width": 1024, + "height": 1024, + "batch_size": 1 + }, + "class_type": "EmptyLatentImage", + "_meta": { + "title": "Пустое латентное изображение" + } + }, + "606": { + "inputs": { + "rotate_pitch": 0, + "rotate_yaw": 0, + "rotate_roll": 0, + "blink": 0, + "eyebrow": 0, + "wink": 0, + "pupil_x": 0, + "pupil_y": 0, + "aaa": 0, + "eee": 0, + "woo": 0, + "smile": 0, + "src_ratio": 1, + "sample_ratio": 1, + "sample_parts": "OnlyExpression", + "crop_factor": 1.7, + "src_image": [ + "567", + 5 + ], + "sample_image": [ + "566", + 5 + ] + }, + "class_type": "ExpressionEditor", + "_meta": { + "title": "Expression Editor (PHM)" + } + }, + "609": { + "inputs": { + "separator": ", ", + "arg1": [ + "523", + 0 + ], + "arg2": [ + "571", + 0 + ] + }, + "class_type": "PromptUtilitiesJoinStringList", + "_meta": { + "title": "Join String List" + } + }, + "615": { + "inputs": {}, + "class_type": "BRIA_RMBG_ModelLoader_Zho", + "_meta": { + "title": "🧹BRIA_RMBG Model Loader" + } + }, + "689": { + "inputs": { + "select": 1, + "sel_mode": false, + "input1": [ + "536", + 0 + ], + "input2": [ + "769", + 0 + ] + }, + "class_type": "ImpactSwitch", + "_meta": { + "title": "Switch (Any)" + } + }, + "769": { + "inputs": { + "text": "women" + }, + "class_type": "CR Text", + "_meta": { + "title": "🔤 CR Text" + } + } +}; diff --git a/src/screens/Gallery.module.css b/src/screens/Gallery.module.css index acc04f8..dd9cb81 100644 --- a/src/screens/Gallery.module.css +++ b/src/screens/Gallery.module.css @@ -12,7 +12,7 @@ display: flex; flex-direction: column; gap: var(--spacing-large); - padding: calc(3rem + var(--spacing-small)) var(--spacing-medium) calc(6rem + var(--safe-area-inset-bottom)); + padding: calc(3rem + var(--spacing-small)) var(--spacing-medium) calc(10rem + var(--safe-area-inset-bottom)); width: 100%; box-sizing: border-box; overflow-y: auto; @@ -242,3 +242,43 @@ margin: 0; font-size: 0.8rem; } + +/* Стили для фиксированной кнопки "Создать стикерпак" */ +.createButtonFixed { + /* Размеры и отступы как у кнопки генерации */ + padding: 16px; + height: auto; + line-height: normal; + + /* Размер шрифта как у кнопки генерации */ + font-size: 18px; + font-weight: 600; + + /* Фиксируем кнопку внизу экрана */ + position: fixed; + bottom: calc(6rem + var(--safe-area-inset-bottom)); /* Увеличенный отступ от навигации */ + left: var(--spacing-medium); + right: var(--spacing-medium); + width: auto; /* Вместо width: 100% */ + max-width: calc(28rem - 2 * var(--spacing-medium)); /* Соответствует ширине контейнера */ + margin: 0 auto; /* Центрирование */ + transform: none; /* Убираем transform: translateX(-50%) */ + z-index: 100; /* Увеличиваем z-index */ + + /* Остальные стили */ + background-color: var(--color-primary); + color: white; + border: none; + border-radius: var(--border-radius); + cursor: pointer; + transition: transform 0.2s; + text-align: center; +} + +.createButtonFixed:hover { + transform: translateY(-1px); /* Исправляем hover эффект */ +} + +.createButtonFixed:active { + transform: translateY(1px); /* Исправляем active эффект */ +} diff --git a/src/screens/Gallery.tsx b/src/screens/Gallery.tsx index 8dc9a13..546de9b 100644 --- a/src/screens/Gallery.tsx +++ b/src/screens/Gallery.tsx @@ -1,4 +1,5 @@ import React, { useEffect, useState, useRef, useCallback } from 'react'; +import { useNavigate } from 'react-router-dom'; import styles from './Gallery.module.css'; import apiService from '../services/api'; import { GeneratedImage, PendingTask } from '../types/api'; @@ -7,6 +8,7 @@ import ImageWithFallback from '../components/shared/ImageWithFallback'; import NotificationModal from '../components/shared/NotificationModal'; const GalleryScreen: React.FC = () => { + const navigate = useNavigate(); const [images, setImages] = useState([]); const [pendingTasks, setPendingTasks] = useState([]); const [loading, setLoading] = useState(true); @@ -80,6 +82,11 @@ const GalleryScreen: React.FC = () => { setIsDeleteMode(false); setSelectedForDelete(null); }, []); + + // Обработчик для кнопки "Создать стикерпак" + const handleCreateStickerPack = useCallback(() => { + navigate('/create-sticker-pack'); + }, [navigate]); // Обработчик клика по контейнеру для выхода из режима удаления const handleGridClick = useCallback((e: React.MouseEvent) => { @@ -353,6 +360,16 @@ const GalleryScreen: React.FC = () => { onGalleryClick={() => setSelectedForDelete(null)} isPrimaryGalleryButton={false} /> + + {/* Кнопка "Создать стикерпак" */} + {!loading && !error && images.length > 0 && !isDeleteMode && ( + + )}
); }; diff --git a/src/screens/Home.tsx b/src/screens/Home.tsx index ea63347..bb9b046 100644 --- a/src/screens/Home.tsx +++ b/src/screens/Home.tsx @@ -13,6 +13,7 @@ import { tokenPacks } from '../constants/tokenPacks'; import { getCurrentUserId } from '../constants/user'; import { useBalance } from '../contexts/BalanceContext'; import { sendTargetEvent } from '../services/analyticsService'; +import { WorkflowType } from '../constants/workflows'; // Интерфейс для хранения данных о последней генерации interface LastGenerationData { @@ -39,17 +40,26 @@ const Home: React.FC = () => { return state?.imageData || localStorage.getItem('stickerImageData') || undefined; }); const [isInputVisible, setIsInputVisible] = useState(false); - const [selectedStyle, setSelectedStyle] = useState('chibi'); // По умолчанию выбран первый стиль - const [selectedStyleButtonId, setSelectedStyleButtonId] = useState('chibi'); // Для хранения ID выбранной кнопки стиля + const [selectedStyle, setSelectedStyle] = useState('emotions'); // По умолчанию выбран стиль "Эмоции" + const [selectedStyleButtonId, setSelectedStyleButtonId] = useState('emotions'); // Для хранения ID выбранной кнопки стиля const [selectedPresetId, setSelectedPresetId] = useState(undefined); // Для хранения ID выбранного пресета const [customPrompt, setCustomPrompt] = useState(''); // Для хранения пользовательского промпта + // Состояния для выбора типа эмоций и мема + const [selectedEmotionType, setSelectedEmotionType] = useState<'memes' | 'prompts' | undefined>('prompts'); // По умолчанию выбран тип "Промпты" + const [selectedEmotionTypeButtonId, setSelectedEmotionTypeButtonId] = useState('prompts'); // Для хранения ID выбранной кнопки типа эмоций + const [selectedMemeId, setSelectedMemeId] = useState(undefined); // Для хранения ID выбранного мема + + // Состояния для выбора пола + const [genderDetection, setGenderDetection] = useState<'auto' | 'manual'>('auto'); // По умолчанию автоматическое определение пола + const [manualGender, setManualGender] = useState<'man' | 'woman' | undefined>(undefined); // Для хранения выбранного пола + const [selectedGenderButtonId, setSelectedGenderButtonId] = useState('auto'); // Для хранения ID выбранной кнопки пола + // Состояния для модального окна уведомления const [isNotificationVisible, setIsNotificationVisible] = useState(false); const [notificationTitle, setNotificationTitle] = useState(''); const [notificationMessage, setNotificationMessage] = useState(''); const [isLoading, setIsLoading] = useState(false); - const [promptText, setPromptText] = useState(''); const [showGalleryButton, setShowGalleryButton] = useState(true); const [showButtons, setShowButtons] = useState(true); const [continueButtonText, setContinueButtonText] = useState('Продолжить'); @@ -58,6 +68,20 @@ const Home: React.FC = () => { const [missingTokens, setMissingTokens] = useState(0); const [lastPurchasedPack, setLastPurchasedPack] = useState(null); + // Новые состояния для отслеживания задачи генерации и изображения + const [currentTaskId, setCurrentTaskId] = useState(undefined); + const [generatedImageUrl, setGeneratedImageUrl] = useState(undefined); + const [checkInterval, setCheckInterval] = useState(null); + const [queuePosition, setQueuePosition] = useState(undefined); + + // Состояния для отслеживания изображений + const [imagesCheckInterval, setImagesCheckInterval] = useState(null); + + // Используем useRef вместо useState для хранения начальных значений + // Это позволит избежать проблемы с асинхронным обновлением состояний + const initialImagesCountRef = useRef(0); + const initialImageIdsRef = useRef([]); + // Обработчики для модального окна const handleGalleryClick = useCallback(() => { setIsNotificationVisible(false); @@ -67,6 +91,34 @@ const Home: React.FC = () => { const handleContinueClick = useCallback(() => { setIsNotificationVisible(false); }, []); + + // Функция для проверки новых изображений + const checkForNewImages = useCallback(async () => { + try { + // Получаем текущий список изображений + const images = await apiService.getGeneratedImages(); + + // Проверяем, увеличилось ли количество изображений + if (images.length > initialImagesCountRef.current) { + // Если количество изображений увеличилось, проверяем, что первое изображение действительно новое + const latestImage = images[0]; + const isNewImage = !initialImageIdsRef.current.includes(latestImage.link); + + if (isNewImage) { + // Устанавливаем URL изображения только если это действительно новое изображение + setGeneratedImageUrl(latestImage.url); + + // Очищаем интервал, так как изображение найдено + if (imagesCheckInterval) { + clearInterval(imagesCheckInterval); + setImagesCheckInterval(null); + } + } + } + } catch (error) { + console.error('Ошибка при проверке новых изображений:', error); + } + }, [imagesCheckInterval]); const handleBlockAction = useCallback(async (actionType: string, actionValue: string, blockId?: string, buttonId?: string) => { if (actionType === 'selectStyle') { @@ -81,6 +133,49 @@ const Home: React.FC = () => { // Обработка выбора пресета setSelectedPresetId(buttonId); console.log('Selected preset:', actionValue, 'Button ID:', buttonId); + + // Если выбран пресет, отличный от "Свой промпт", скрываем поле ввода текста + if (buttonId !== 'customPrompt') { + setIsInputVisible(false); + } + + return; + } + + if (actionType === 'selectGenderDetection') { + // Обработка выбора способа определения пола + setGenderDetection('auto'); + setManualGender(undefined); + setSelectedGenderButtonId(buttonId); + console.log('Selected gender detection:', actionValue, 'Button ID:', buttonId); + return; + } + + if (actionType === 'selectGender') { + // Обработка выбора пола + setGenderDetection('manual'); + setManualGender(actionValue as 'man' | 'woman'); + setSelectedGenderButtonId(buttonId); + console.log('Selected gender:', actionValue, 'Button ID:', buttonId); + return; + } + + if (actionType === 'selectEmotionType') { + // Обработка выбора типа эмоций + setSelectedEmotionType(actionValue as 'memes' | 'prompts'); + setSelectedEmotionTypeButtonId(buttonId); + // Сбрасываем выбранный мем или пресет при смене типа + setSelectedMemeId(undefined); + setSelectedPresetId(undefined); + console.log('Selected emotion type:', actionValue, 'Button ID:', buttonId); + return; + } + + if (actionType === 'selectMeme') { + // Обработка выбора мема + setSelectedMemeId(buttonId); + setSelectedPresetId(buttonId); // Используем тот же ID для совместимости с существующей логикой + console.log('Selected meme:', actionValue, 'Button ID:', buttonId); return; } @@ -94,6 +189,8 @@ const Home: React.FC = () => { setShowGalleryButton(false); // Скрываем кнопку "В галерею", так как генерация не была запущена setShowButtons(true); // Показываем кнопки setContinueButtonText('Закрыть'); // Устанавливаем текст кнопки "Закрыть" + setCurrentTaskId(undefined); // Сбрасываем ID задачи, чтобы не отображалась анимация + setQueuePosition(undefined); // Сбрасываем позицию в очереди setIsNotificationVisible(true); return; } @@ -106,6 +203,8 @@ const Home: React.FC = () => { setShowGalleryButton(false); // Скрываем кнопку "В галерею", так как генерация не была запущена setShowButtons(true); // Показываем кнопки setContinueButtonText('Закрыть'); // Устанавливаем текст кнопки "Закрыть" + setCurrentTaskId(undefined); // Сбрасываем ID задачи, чтобы не отображалась анимация + setQueuePosition(undefined); // Сбрасываем позицию в очереди setIsNotificationVisible(true); return; } @@ -118,6 +217,8 @@ const Home: React.FC = () => { setShowGalleryButton(false); // Скрываем кнопку "В галерею", так как генерация не была запущена setShowButtons(true); // Показываем кнопки setContinueButtonText('Закрыть'); // Устанавливаем текст кнопки "Закрыть" + setCurrentTaskId(undefined); // Сбрасываем ID задачи, чтобы не отображалась анимация + setQueuePosition(undefined); // Сбрасываем позицию в очереди setIsNotificationVisible(true); return; } @@ -154,6 +255,8 @@ const Home: React.FC = () => { setShowGalleryButton(false); // Скрываем кнопку "В галерею", так как генерация не была запущена setShowButtons(true); // Показываем кнопки setContinueButtonText('Закрыть'); // Устанавливаем текст кнопки "Закрыть" + setCurrentTaskId(undefined); // Сбрасываем ID задачи, чтобы не отображалась анимация + setQueuePosition(undefined); // Сбрасываем позицию в очереди setIsNotificationVisible(true); return; } @@ -169,11 +272,22 @@ const Home: React.FC = () => { return; } - // Показываем уведомление о начале генерации + // Получаем текущий список изображений перед генерацией + try { + const currentImages = await apiService.getGeneratedImages(); + // Используем ref вместо состояний для мгновенного обновления + initialImagesCountRef.current = currentImages.length; + initialImageIdsRef.current = currentImages.map(img => img.link); + } catch (error) { + console.error('Ошибка при получении списка изображений:', error); + // Продолжаем генерацию даже при ошибке получения списка + } + + // Сбрасываем URL изображения и показываем уведомление о начале генерации + setGeneratedImageUrl(undefined); // Важно: сбрасываем URL изображения перед началом генерации setNotificationTitle('Генерация стикера'); setNotificationMessage('Отправка запроса...'); setIsLoading(true); - setPromptText(''); setShowGalleryButton(true); setShowButtons(false); setContinueButtonText('Продолжить'); @@ -182,8 +296,43 @@ const Home: React.FC = () => { // Если выбран "Свой промпт" и введен текст, используем его const userPrompt = selectedPresetId === 'customPrompt' && customPrompt ? customPrompt : undefined; - // Отправляем запрос на генерацию - const response = await apiService.generateImage(imageData, selectedStyle, selectedPresetId, userPrompt); + // Создаем объект с параметрами генерации + const generationOptions: any = { + promptId: selectedPresetId, + userPrompt, + genderDetection, + manualGender + }; + + // Если выбран тип "Мемы", добавляем ID мема + if (selectedStyle === 'emotions' && selectedEmotionType === 'memes' && selectedMemeId) { + generationOptions.memeId = selectedMemeId; + } + + console.log('Generation options:', generationOptions); + + // Определяем тип воркфлоу в зависимости от выбранного стиля и типа эмоций + let workflowType = WorkflowType.CHIBI; + if (selectedStyle === 'chibi') { + workflowType = WorkflowType.CHIBI; + } else if (selectedStyle === 'emotions') { + if (selectedEmotionType === 'memes') { + workflowType = WorkflowType.MEME; + } else { + workflowType = WorkflowType.PROMPT; + } + } else if (selectedStyle === 'realism') { + workflowType = WorkflowType.PROMPT; + } + + console.log('Using workflow type:', workflowType, 'for style:', selectedStyle); + + // Отправляем запрос на генерацию с использованием нового метода + const response = await apiService.generateImageWithWorkflow( + imageData, + workflowType, + generationOptions + ); console.log('Generation response:', response); // Сохраняем данные о текущей генерации @@ -232,13 +381,15 @@ const Home: React.FC = () => { setShowGalleryButton(false); // Скрываем кнопку "В галерею", так как генерация не была успешно запущена setShowButtons(true); // Показываем кнопки в случае ошибки перевода setContinueButtonText('Закрыть'); // Меняем текст кнопки на "Закрыть" + setCurrentTaskId(undefined); // Сбрасываем ID задачи при ошибке + setQueuePosition(undefined); // Сбрасываем позицию в очереди return; } // Если нет ошибки перевода, продолжаем обработку результата - if (response.result && response.usedPrompt) { - // Получаем результат и использованный промпт - const { result, usedPrompt } = response; + if (response.result) { + // Получаем результат + const { result } = response; // Обновляем уведомление с информацией о позиции в очереди if (result.queue_position !== undefined) { @@ -263,8 +414,30 @@ const Home: React.FC = () => { ); } - // Устанавливаем использованный промпт, показываем кнопки и меняем текст кнопки "Продолжить" на "Закрыть" - setPromptText(usedPrompt); + // Сохраняем ID задачи + if (result.Task_ID) { + setCurrentTaskId(result.Task_ID); + + // Устанавливаем позицию в очереди + if (result.queue_position !== undefined) { + setQueuePosition(result.queue_position); + } + + // Запускаем интервал для проверки новых изображений + // Очищаем предыдущий интервал, если он был + if (imagesCheckInterval) { + clearInterval(imagesCheckInterval); + } + + // Устанавливаем новый интервал + const intervalId = window.setInterval(() => { + checkForNewImages(); + }, 2000); // Проверяем каждые 2 секунды + + setImagesCheckInterval(intervalId); + } + + // Показываем кнопки и меняем текст кнопки "Продолжить" на "Закрыть" setShowButtons(true); setContinueButtonText('Закрыть'); } @@ -278,16 +451,26 @@ const Home: React.FC = () => { setShowGalleryButton(false); // Скрываем кнопку "В галерею", так как генерация не была успешно запущена setShowButtons(true); // Показываем кнопки в случае ошибки setContinueButtonText('Закрыть'); // Меняем текст кнопки на "Закрыть" + setCurrentTaskId(undefined); // Сбрасываем ID задачи при ошибке + setQueuePosition(undefined); // Сбрасываем позицию в очереди setIsNotificationVisible(true); } return; } if (actionValue === 'toggleInput') { + // Добавляем логирование для отладки + console.log('Нажата кнопка "Свой промпт"', { + blockId, + buttonId, + selectedStyle, + selectedEmotionType, + isInputVisible: !isInputVisible // Новое значение + }); + setIsInputVisible(prev => !prev); // Устанавливаем selectedPresetId в 'customPrompt' при нажатии на кнопку "Свой промпт" setSelectedPresetId('customPrompt'); - console.log('Выбран свой промпт, установлен ID:', 'customPrompt'); return; } @@ -313,9 +496,11 @@ const Home: React.FC = () => { return; } - // Если выбрана любая другая кнопка, скрываем поле ввода - setIsInputVisible(false); - }, [navigate, imageData, selectedStyle, selectedPresetId, customPrompt, lastGenerationData]); + // Если выбрана любая другая кнопка (кроме "Свой промпт"), скрываем поле ввода + if (!(actionType === 'function' && actionValue === 'toggleInput' && buttonId === 'customPrompt')) { + setIsInputVisible(false); + } + }, [navigate, imageData, selectedStyle, selectedPresetId, customPrompt, lastGenerationData, genderDetection, manualGender, selectedEmotionType, selectedMemeId, imagesCheckInterval, checkForNewImages]); // Эффект для обновления window.history.state при загрузке из localStorage useEffect(() => { @@ -350,19 +535,31 @@ const Home: React.FC = () => { return () => { window.removeEventListener('beforeunload', handleBeforeUnload); + + // Очищаем интервалы при размонтировании компонента + if (imagesCheckInterval) { + clearInterval(imagesCheckInterval); + } + if (checkInterval) { + clearInterval(checkInterval); + } }; - }, []); + }, [imagesCheckInterval, checkInterval]); // Функция для получения кнопок в зависимости от блока const getBlockButtons = useCallback((block: any) => { if (block.id === 'quickActions') { - // Берем кнопку "Свой промпт" из конфигурации - const customPromptButton = block.buttons[0]; - // Добавляем к ней кнопки из выбранного стиля - return [customPromptButton, ...(stylePresets[selectedStyle]?.buttons || [])]; + // Возвращаем только кнопки из выбранного стиля + return stylePresets[selectedStyle]?.buttons || []; } + + if (block.id === 'emotionPromptsSelection' && selectedStyle === 'emotions' && selectedEmotionType === 'prompts') { + // Возвращаем только кнопки из стиля "Эмоции" + return stylePresets.emotions?.buttons || []; + } + return block.buttons; - }, [selectedStyle]); + }, [selectedStyle, selectedEmotionType]); return (
@@ -372,13 +569,16 @@ const Home: React.FC = () => { title={notificationTitle} message={notificationMessage} isLoading={isLoading} - promptText={promptText} onGalleryClick={handleGalleryClick} onContinueClick={handleContinueClick} showGalleryButton={showGalleryButton} showButtons={showButtons} continueButtonText={continueButtonText} isPrimaryGalleryButton={true} + taskId={currentTaskId} + generatedImageUrl={generatedImageUrl} + isGenerating={!!currentTaskId} + queuePosition={queuePosition} /> {/* Компонент обработки обратной связи */} @@ -491,9 +691,82 @@ const Home: React.FC = () => { /> {/* Блоки из конфигурации */}
- {homeScreenConfig.homeScreen.blocks - .filter(block => block.type !== 'generateButton') - .map((block) => { + {(() => { + // Получаем все блоки из конфигурации + const allBlocks = homeScreenConfig.homeScreen.blocks.filter(block => block.type !== 'generateButton'); + + // Создаем массив блоков для отображения в нужном порядке + const blocksToRender = []; + + // Проходим по всем блокам и добавляем их в массив для отображения в нужном порядке + for (const block of allBlocks) { + // Блоки для выбора типа эмоций показываем только если выбран стиль "Эмоции" + if (block.id === 'emotionTypeTitle' || block.id === 'emotionTypeSelection') { + if (selectedStyle === 'emotions') { + blocksToRender.push(block); + } + continue; + } + + // Блок с полем ввода текста (customPrompt) показываем после emotionTypeSelection и перед emotionPromptsSelection + // если выбран стиль "Эмоции" и тип "Промпты" и нажата кнопка "Свой промпт" + if (block.id === 'customPrompt') { + // Для стиля "Чиби" показываем в обычном порядке + if (selectedStyle === 'chibi' && isInputVisible) { + blocksToRender.push(block); + } + // Для стиля "Эмоции" и типа "Промпты" блок будет добавлен позже в специальном месте + continue; + } + + // Блок выбора мемов показываем только если выбран стиль "Эмоции" и тип "Мемы" + if (block.id === 'memeSelection') { + if (selectedStyle === 'emotions' && selectedEmotionType === 'memes') { + blocksToRender.push(block); + } + continue; + } + + // Блок выбора промптов для эмоций показываем только если выбран стиль "Эмоции" и тип "Промпты" + if (block.id === 'emotionPromptsSelection') { + if (selectedStyle === 'emotions' && selectedEmotionType === 'prompts') { + // Если выбран стиль "Эмоции" и тип "Промпты", то сначала добавляем поле ввода текста, + // если оно должно быть видимым + if (isInputVisible) { + const textInputBlock = allBlocks.find(b => b.id === 'customPrompt'); + if (textInputBlock) { + blocksToRender.push(textInputBlock); + } + } + + // Затем добавляем блок с промптами + blocksToRender.push(block); + } + continue; + } + + // Блок с пресетами (quickActions) показываем только если выбран стиль "Чиби" или не выбран стиль "Эмоции" + if (block.id === 'quickActions') { + if (selectedStyle !== 'emotions') { + blocksToRender.push(block); + } + continue; + } + + // Блок с заголовком "Выбери образ" (step3) показываем только если не выбран стиль "Эмоции" или уже выбран тип эмоций + if (block.id === 'step3') { + if (selectedStyle !== 'emotions' || selectedEmotionType !== undefined) { + blocksToRender.push(block); + } + continue; + } + + // Остальные блоки показываем всегда + blocksToRender.push(block); + } + + // Отображаем блоки + return blocksToRender.map((block) => { // Создаем копию блока с модифицированными кнопками const modifiedBlock = { ...block, @@ -508,6 +781,18 @@ const Home: React.FC = () => { } else if (block.id === 'quickActions') { // Для блока пресетов передаем ID выбранного пресета selectedButtonId = selectedPresetId; + } else if (block.id === 'genderSelection') { + // Для блока выбора пола передаем ID выбранной кнопки пола + selectedButtonId = selectedGenderButtonId; + } else if (block.id === 'emotionTypeSelection') { + // Для блока выбора типа эмоций передаем ID выбранной кнопки типа эмоций + selectedButtonId = selectedEmotionTypeButtonId; + } else if (block.id === 'memeSelection') { + // Для блока выбора мема передаем ID выбранного мема + selectedButtonId = selectedMemeId; + } else if (block.id === 'emotionPromptsSelection') { + // Для блока выбора промптов для эмоций передаем ID выбранного пресета + selectedButtonId = selectedPresetId; } return ( @@ -522,7 +807,8 @@ const Home: React.FC = () => { } : undefined} /> ); - })} + }); + })()}
{homeScreenConfig.homeScreen.blocks .filter(block => block.type === 'generateButton') diff --git a/src/screens/StickerPacks.module.css b/src/screens/StickerPacks.module.css index 5985c84..d70c506 100644 --- a/src/screens/StickerPacks.module.css +++ b/src/screens/StickerPacks.module.css @@ -141,6 +141,15 @@ padding: calc(var(--spacing-medium) / 4) var(--spacing-medium) var(--spacing-medium) var(--spacing-medium); box-sizing: border-box; max-width: 100%; + position: relative; /* Добавляем для правильного позиционирования кнопки */ +} + +/* Стили для кнопки удаления на карточке стикерпака */ +.packItem .deleteButton { + position: absolute; + top: 8px; + right: 8px; + z-index: 2; } .packItem:hover { @@ -230,8 +239,10 @@ .detailsHeader { display: flex; + flex-direction: column; align-items: center; margin-bottom: var(--spacing-medium); + position: relative; } .backButton { @@ -241,14 +252,17 @@ cursor: pointer; font-weight: 500; padding: var(--spacing-small); - margin-right: var(--spacing-small); + position: absolute; + left: 0; + top: 0; } .detailsTitle { - flex-grow: 1; font-size: 1.2rem; font-weight: 500; color: var(--color-text); + text-align: center; + margin: var(--spacing-small) 0; } .deleteButton { @@ -323,7 +337,8 @@ display: flex; justify-content: center; gap: var(--spacing-medium); - margin-top: var(--spacing-medium); + margin: var(--spacing-medium) 0; + width: 100%; } .addStickerButton { diff --git a/src/screens/StickerPacks.tsx b/src/screens/StickerPacks.tsx index 633256e..d79a42f 100644 --- a/src/screens/StickerPacks.tsx +++ b/src/screens/StickerPacks.tsx @@ -3,6 +3,7 @@ import { useNavigate } from 'react-router-dom'; import styles from './StickerPacks.module.css'; import { stickerService } from '../services/stickerService'; import { getCurrentUserId } from '../constants/user'; +import NotificationModal from '../components/shared/NotificationModal'; // Функция для удаления дописанной части из названия стикерпака const cleanPackTitle = (title: string): string => { @@ -31,6 +32,10 @@ const StickerPacks: React.FC = () => { const [loading, setLoading] = useState(true); const [error, setError] = useState(null); const [selectedPack, setSelectedPack] = useState(null); + const [packToDelete, setPackToDelete] = useState(null); + const [isDeleting, setIsDeleting] = useState(false); + const [stickerToDelete, setStickerToDelete] = useState(null); + const [isDeletingSticker, setIsDeletingSticker] = useState(false); useEffect(() => { const fetchStickerPacks = async () => { @@ -76,18 +81,24 @@ const StickerPacks: React.FC = () => { setSelectedPack(null); }; - const handleDeletePack = async (packName: string) => { - if (!confirm('Вы уверены, что хотите удалить этот стикерпак?')) { - return; - } + const handleDeletePack = (packName: string) => { + setPackToDelete(packName); + }; - try { - await stickerService.deleteStickerPack(packName); - setStickerPacks(prevPacks => prevPacks.filter(pack => pack.name !== packName)); - setSelectedPack(null); - } catch (err) { - console.error('Ошибка при удалении стикерпака:', err); - alert('Не удалось удалить стикерпак'); + const handleConfirmDelete = async () => { + if (packToDelete) { + try { + setIsDeleting(true); + await stickerService.deleteStickerPack(packToDelete); + setStickerPacks(prevPacks => prevPacks.filter(pack => pack.name !== packToDelete)); + setSelectedPack(null); + setIsDeleting(false); + setPackToDelete(null); + } catch (err) { + console.error('Ошибка при удалении стикерпака:', err); + alert('Не удалось удалить стикерпак'); + setIsDeleting(false); + } } }; @@ -97,34 +108,41 @@ const StickerPacks: React.FC = () => { } }; - const handleDeleteSticker = async (fileId: string) => { + const handleDeleteSticker = (fileId: string) => { if (!fileId) { alert('Не удалось определить ID стикера'); return; } - - if (!confirm('Вы уверены, что хотите удалить этот стикер?')) { - return; - } - - try { - await stickerService.deleteStickerByFileId(fileId); - - // Обновляем список стикеров в выбранном стикерпаке - if (selectedPack) { - const updatedPack = await stickerService.getStickerPack(selectedPack.name); - setSelectedPack(updatedPack); + + setStickerToDelete(fileId); + }; + + const handleConfirmDeleteSticker = async () => { + if (stickerToDelete) { + try { + setIsDeletingSticker(true); + await stickerService.deleteStickerByFileId(stickerToDelete); - // Также обновляем стикерпак в общем списке - setStickerPacks(prevPacks => - prevPacks.map(pack => - pack.name === selectedPack.name ? updatedPack : pack - ) - ); + // Обновляем список стикеров в выбранном стикерпаке + if (selectedPack) { + const updatedPack = await stickerService.getStickerPack(selectedPack.name); + setSelectedPack(updatedPack); + + // Также обновляем стикерпак в общем списке + setStickerPacks(prevPacks => + prevPacks.map(pack => + pack.name === selectedPack.name ? updatedPack : pack + ) + ); + } + + setIsDeletingSticker(false); + setStickerToDelete(null); + } catch (err) { + console.error('Ошибка при удалении стикера:', err); + alert('Не удалось удалить стикер'); + setIsDeletingSticker(false); } - } catch (err) { - console.error('Ошибка при удалении стикера:', err); - alert('Не удалось удалить стикер'); } }; @@ -204,6 +222,17 @@ const StickerPacks: React.FC = () => {
))} + + {/* Кнопка удаления стикерпака */} + ))} @@ -227,11 +256,22 @@ const StickerPacks: React.FC = () => { ← Назад

{cleanPackTitle(selectedPack.title)}

+ + + {/* Перемещенный блок с кнопками */} +
+ +
@@ -262,24 +302,36 @@ const StickerPacks: React.FC = () => { ))} - -
- - - -
)} + + {/* Модальное окно подтверждения удаления стикерпака */} + setPackToDelete(null)} + isPrimaryGalleryButton={false} + /> + + {/* Модальное окно подтверждения удаления стикера */} + setStickerToDelete(null)} + isPrimaryGalleryButton={false} + /> ); }; diff --git a/src/services/api.ts b/src/services/api.ts index 9ecba7d..d4c6208 100644 --- a/src/services/api.ts +++ b/src/services/api.ts @@ -1,9 +1,11 @@ -import { GenerationResponse, ApiError as ApiErrorType, GeneratedImage, PendingTask, GenerationResult } from '../types/api'; +import { GenerationResponse, ApiError as ApiErrorType, GeneratedImage, PendingTask, GenerationResult, GenerationOptions } from '../types/api'; import { baseWorkflow } from '../constants/baseWorkflow'; +import { WorkflowType, getWorkflowByType } from '../constants/workflows'; import { prompts } from '../assets/prompts'; import translateService from './translateService'; import { getCurrentUserId, isTelegramWebAppAvailable } from '../constants/user'; import { trackStickerGeneration, trackRejectedPrompt } from './analyticsService'; +import memeService from './memeService'; const API_BASE_URL = 'https://stickerserver.gymnasticstuff.uk'; @@ -252,6 +254,7 @@ const apiService = { } }, + // Существующий метод для генерации изображений (для обратной совместимости) async generateImage(imageData: string, style?: string, promptId?: string, userPrompt?: string): Promise { try { // Создаем копию базового воркфлоу @@ -358,6 +361,168 @@ const apiService = { } throw new Error('Failed to generate image'); } + }, + + // Новый метод для генерации изображений с использованием выбранного воркфлоу + async generateImageWithWorkflow( + imageData: string, + workflowType: WorkflowType, + options: GenerationOptions + ): Promise { + try { + // Получаем базовый воркфлоу в зависимости от типа + const workflow = JSON.parse(JSON.stringify(getWorkflowByType(workflowType))); + + // Вставляем изображение пользователя в узел 563 + workflow['563'].inputs.image = imageData; + + // Настраиваем определение пола + const genderSwitchNode = workflowType === WorkflowType.CHIBI ? '564' : '689'; + workflow[genderSwitchNode].inputs.select = options.genderDetection === 'auto' ? 1 : 2; + + // Если выбрано ручное определение пола + if (options.genderDetection === 'manual' && options.manualGender) { + const genderNode = workflowType === WorkflowType.CHIBI ? '565' : '769'; + workflow[genderNode].inputs.text = options.manualGender; + } + + // Переменная для хранения использованного промпта + let usedPrompt = ''; + let translationFailed = false; + + // Обрабатываем специфичные для каждого типа воркфлоу параметры + switch (workflowType) { + case WorkflowType.CHIBI: + // Обработка промпта для CHIBI + if (options.userPrompt && options.promptId === 'customPrompt') { + // Используем существующий код для перевода + const result = await this.handlePromptTranslation(options.userPrompt); + if (result.translationFailed) { + return result; + } + workflow['316'].inputs.prompt_1 = result.usedPrompt || ''; + usedPrompt = result.usedPrompt || ''; + } else if (options.promptId && prompts[options.promptId]) { + workflow['316'].inputs.prompt_1 = prompts[options.promptId]; + usedPrompt = prompts[options.promptId]; + } + break; + + case WorkflowType.PROMPT: + // Обработка промпта для PROMPT + if (options.userPrompt && options.promptId === 'customPrompt') { + // Используем существующий код для перевода + const result = await this.handlePromptTranslation(options.userPrompt); + if (result.translationFailed) { + return result; + } + workflow['585'].inputs.text = result.usedPrompt || ''; + usedPrompt = result.usedPrompt || ''; + } else if (options.promptId && prompts[options.promptId]) { + workflow['585'].inputs.text = prompts[options.promptId]; + usedPrompt = prompts[options.promptId]; + } + break; + + case WorkflowType.MEME: + // Загружаем мем для стиля с мемами + if (options.memeId) { + const memeBase64 = memeService.getMemeBase64(options.memeId); + workflow['603'].inputs.image = memeBase64; + } else { + return { + translationFailed: true, + errorDetails: 'Не указан ID мема для стиля MEME' + }; + } + break; + } + + // Определяем тег на основе выбранного типа воркфлоу + const tag = workflowType === WorkflowType.CHIBI ? 'chibi' : 'image_generation'; + + // Создаем строку JSON для workflow + const workflowJson = JSON.stringify(workflow); + + // Создаем тело запроса + const requestBodyJson = `{"tag":"${tag}","user_id":${getCurrentUserId()},"workflow":${workflowJson}}`; + + // Сохраняем JSON для отладки только при локальной разработке + if (!isTelegramWebAppAvailable()) { + const blob = new Blob([requestBodyJson], { type: 'application/json' }); + const url = URL.createObjectURL(blob); + const a = document.createElement('a'); + a.href = url; + a.download = 'generation_request.json'; + document.body.appendChild(a); + a.click(); + document.body.removeChild(a); + URL.revokeObjectURL(url); + } + + // Отправляем запрос + const response = await fetch(`${API_BASE_URL}/generate_image`, { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + body: requestBodyJson + }); + + if (!response.ok) { + const errorData: ApiErrorType = await response.json(); + throw new GenerationError(errorData.detail); + } + + const result = await response.json() as GenerationResponse; + + // Отслеживаем событие генерации стикера + if (usedPrompt) { + trackStickerGeneration(usedPrompt); + } + + // Возвращаем результат и использованный промпт + return { + result, + usedPrompt, + translationFailed: false + }; + } catch (error) { + if (error instanceof GenerationError) { + throw error; + } + throw new Error('Failed to generate image'); + } + }, + + // Вспомогательный метод для обработки перевода промпта + async handlePromptTranslation(userPrompt: string): Promise { + console.log('Переводим пользовательский промпт:', userPrompt); + + // Используем существующий метод перевода + const translationResult = await translateService.translateWithLLM(userPrompt); + + if (translationResult.success) { + // Успешный перевод + console.log('Переведенный промпт:', translationResult.text); + return { + translationFailed: false, + usedPrompt: translationResult.text + }; + } else { + // Перевод не удался + console.error('Не удалось перевести промпт:', translationResult.text); + + // Отслеживаем событие неудавшейся генерации + trackRejectedPrompt(userPrompt); + + // Возвращаем ошибку + return { + translationFailed: true, + usedPrompt: 'Недопустимый промпт', + errorDetails: translationResult.text + }; + } } }; diff --git a/src/services/memeService.ts b/src/services/memeService.ts new file mode 100644 index 0000000..f55d688 --- /dev/null +++ b/src/services/memeService.ts @@ -0,0 +1,56 @@ +import { memes, MemeData } from '../assets/memes'; + +/** + * Сервис для работы с мемами + */ + +/** + * Получить список всех мемов + * @returns Массив мемов + */ +export const getMemesList = (): MemeData[] => { + return memes; +}; + +/** + * Получить мем по ID + * @param id ID мема + * @returns Объект мема или undefined, если мем не найден + */ +export const getMemeById = (id: string): MemeData | undefined => { + return memes.find(meme => meme.id === id); +}; + +/** + * Получить путь к изображению мема по ID + * Возвращает путь в формате для Linux системы: 512meme/(номер)_512x.png + * @param id ID мема (формат: meme1, meme2, ...) + * @returns Путь к изображению мема или пустая строка, если мем не найден + */ +export const getMemeBase64 = (id: string): string => { + // Извлекаем номер из ID мема (например, из "meme5" получаем "5") + const memeNumber = id.replace('meme', ''); + + // Проверяем, что номер валидный + if (!memeNumber || isNaN(Number(memeNumber)) || Number(memeNumber) < 1 || Number(memeNumber) > 10) { + console.error(`[Ошибка] Некорректный ID мема: ${id}`); + return ''; + } + + // Формируем путь к изображению мема в формате для Linux системы с добавлением "x" + const memePath = `512meme/${memeNumber}_512x.png`; + console.log(`[Мем] Запрошен мем с ID: ${id}, путь: ${memePath}`); + + return memePath; +}; + +/** + * Экспорт всех функций сервиса + */ +const memeService = { + getMemesList, + getMemeById, + getMemeBase64 +}; + +export default memeService; diff --git a/src/types/api.ts b/src/types/api.ts index 3b18a66..a8fa4de 100644 --- a/src/types/api.ts +++ b/src/types/api.ts @@ -61,6 +61,15 @@ export interface StickerSetResponse { user_id: number; } +// Интерфейс для параметров метода generateImage +export interface GenerationOptions { + promptId?: string; + userPrompt?: string; + memeId?: string; + genderDetection: 'auto' | 'manual'; + manualGender?: 'man' | 'woman' | 'boy' | 'girl'; +} + // Интерфейс для ответа от apiService.generateImage export interface GenerationResult { result?: GenerationResponse; diff --git a/src/types/blocks.ts b/src/types/blocks.ts index 5a861f1..a5fb83e 100644 --- a/src/types/blocks.ts +++ b/src/types/blocks.ts @@ -15,7 +15,7 @@ export interface BlockButton { imageUrl?: string; color?: string; action?: { - type: 'route' | 'function' | 'selectStyle' | 'selectPreset'; + type: 'route' | 'function' | 'selectStyle' | 'selectPreset' | 'selectWorkflowType' | 'selectGenderDetection' | 'selectGender' | 'selectMeme' | 'selectEmotionType'; value: string; }; disabled?: boolean; diff --git a/workflow/stickerV1_chibi/readme.txt b/workflow/stickerV1_chibi/readme.txt new file mode 100644 index 0000000..e524ee1 --- /dev/null +++ b/workflow/stickerV1_chibi/readme.txt @@ -0,0 +1,4 @@ +563 - загрузка base64 изображение +316 - промпт (только первый который military clothes меняем на свой) +565 - выбор пола человека ручной +564 - переключатель автоматического определения или выбора вручную пола человека (1 - автоматическое, 2 - ручное) \ No newline at end of file diff --git a/workflow/stickerV1_chibi/stickerV1_base64_ws_switch.json b/workflow/stickerV1_chibi/stickerV1_base64_ws_switch.json new file mode 100644 index 0000000..26617fc --- /dev/null +++ b/workflow/stickerV1_chibi/stickerV1_base64_ws_switch.json @@ -0,0 +1,636 @@ +{ + "305": { + "inputs": { + "ckpt_name": "dreamshaperXL_lightningDPMSDE.safetensors" + }, + "class_type": "CheckpointLoaderSimple", + "_meta": { + "title": "Загрузить контрольную точку" + } + }, + "307": { + "inputs": { + "share_norm": "both", + "share_attn": "q+k", + "scale": 0.7000000000000001, + "model": [ + "309", + 0 + ] + }, + "class_type": "StyleAlignedBatchAlign", + "_meta": { + "title": "StyleAligned Batch Align" + } + }, + "308": { + "inputs": { + "text_positive": "Sticker,chibi:2,Flat:1.5,(full body:2),Simple details,(Empty Background:2)", + "text_negative": "Realism, photo-realism, real materials,(full body:2)", + "style": "sai-cinematic", + "log_prompt": false, + "style_positive": true, + "style_negative": true + }, + "class_type": "SDXLPromptStyler", + "_meta": { + "title": "SDXL Prompt Styler" + } + }, + "309": { + "inputs": { + "b1": 1.3, + "b2": 1.4000000000000001, + "s1": 0.9, + "s2": 0.2, + "model": [ + "406", + 0 + ] + }, + "class_type": "FreeU_V2", + "_meta": { + "title": "FreeU_V2" + } + }, + "312": { + "inputs": { + "text": [ + "308", + 1 + ], + "clip": [ + "406", + 1 + ] + }, + "class_type": "CLIPTextEncode", + "_meta": { + "title": "Кодирование текста CLIP (Запрос)" + } + }, + "313": { + "inputs": { + "prompt_1": "Boxers, with red boxing gloves, swinging their fists", + "prompt_2": "Dressed in a Superman costume", + "prompt_3": "Dress up as Santa Claus with a rattle in your hand", + "prompt_4": "Holding a bouquet of roses in his hand and wearing a gown", + "prompt_5": "Dressed in a wide hip hop suit,Playing the guitar,tattooing,denim,street dance,dancing", + "simple_prompt_list": [ + "316", + 0 + ] + }, + "class_type": "CR Simple Prompt List", + "_meta": { + "title": "CR Simple Prompt List (Legacy)" + } + }, + "314": { + "inputs": { + "keyframe_interval": 1, + "loops": 1, + "transition_type": "Default", + "transition_speed": "Default", + "transition_profile": "Default", + "keyframe_format": "Deforum", + "simple_prompt_list": [ + "313", + 0 + ] + }, + "class_type": "CR Simple Prompt List Keyframes", + "_meta": { + "title": "CR Simple Prompt List Keyframes (Legacy)" + } + }, + "316": { + "inputs": { + "prompt_1": "military clothes", + "prompt_2": "Pirate captain with a sword", + "prompt_3": "Drinking coffee from a coffee cup and smiling", + "prompt_4": "Dressed in a spacesuit and wearing a glass helmet", + "prompt_5": "Wearing luxurious clothes, holding a red heart-shaped balloon and smiling" + }, + "class_type": "CR Simple Prompt List", + "_meta": { + "title": "CR Simple Prompt List (Legacy)" + } + }, + "318": { + "inputs": {}, + "class_type": "Anything Everywhere3", + "_meta": { + "title": "Anything Everywhere3" + } + }, + "326": { + "inputs": { + "image": "photo_2025-02-03_14-06-19.jpg", + "upload": "image" + }, + "class_type": "LoadImage", + "_meta": { + "title": "Загрузить изображение" + } + }, + "328": { + "inputs": { + "seed": [ + "404", + 0 + ], + "steps": 7, + "cfg": 2, + "sampler_name": "dpmpp_2m", + "scheduler": "karras", + "denoise": 1, + "preview_method": "auto", + "vae_decode": "true", + "model": [ + "347", + 0 + ], + "positive": [ + "339", + 0 + ], + "negative": [ + "312", + 0 + ], + "latent_image": [ + "348", + 0 + ], + "optional_vae": [ + "305", + 2 + ] + }, + "class_type": "KSampler (Efficient)", + "_meta": { + "title": "KSampler (Efficient)" + } + }, + "339": { + "inputs": { + "text": [ + "314", + 0 + ], + "max_frames": 10, + "print_output": false, + "pre_text": [ + "308", + 0 + ], + "app_text": [ + "523", + 0 + ], + "start_frame": 0, + "end_frame": 0, + "clip": [ + "406", + 1 + ] + }, + "class_type": "BatchPromptSchedule", + "_meta": { + "title": "Batch Prompt Schedule 📅🅕🅝" + } + }, + "344": { + "inputs": { + "pulid_file": "ip-adapter_pulid_sdxl_fp16.safetensors" + }, + "class_type": "PulidModelLoader", + "_meta": { + "title": "Load PuLID Model" + } + }, + "345": { + "inputs": { + "provider": "CUDA" + }, + "class_type": "PulidInsightFaceLoader", + "_meta": { + "title": "Load InsightFace (PuLID)" + } + }, + "346": { + "inputs": {}, + "class_type": "PulidEvaClipLoader", + "_meta": { + "title": "Load Eva Clip (PuLID)" + } + }, + "347": { + "inputs": { + "method": "fidelity", + "weight": 1, + "start_at": 0, + "end_at": 1, + "model": [ + "307", + 0 + ], + "pulid": [ + "344", + 0 + ], + "eva_clip": [ + "346", + 0 + ], + "face_analysis": [ + "345", + 0 + ], + "image": [ + "384", + 0 + ] + }, + "class_type": "ApplyPulid", + "_meta": { + "title": "Apply PuLID" + } + }, + "348": { + "inputs": { + "width": 768, + "height": 768, + "batch_size": 1 + }, + "class_type": "EmptyLatentImage", + "_meta": { + "title": "Пустое латентное изображение" + } + }, + "376": { + "inputs": { + "rmbgmodel": [ + "377", + 0 + ], + "image": [ + "378", + 5 + ] + }, + "class_type": "BRIA_RMBG_Zho", + "_meta": { + "title": "🧹BRIA RMBG" + } + }, + "377": { + "inputs": {}, + "class_type": "BRIA_RMBG_ModelLoader_Zho", + "_meta": { + "title": "🧹BRIA_RMBG Model Loader" + } + }, + "378": { + "inputs": { + "seed": [ + "404", + 0 + ], + "steps": 6, + "cfg": 2, + "sampler_name": "dpmpp_2m", + "scheduler": "karras", + "denoise": 0.6, + "preview_method": "auto", + "vae_decode": "true", + "model": [ + "382", + 0 + ], + "positive": [ + "382", + 1 + ], + "negative": [ + "382", + 2 + ], + "latent_image": [ + "417", + 0 + ], + "optional_vae": [ + "305", + 2 + ] + }, + "class_type": "KSampler (Efficient)", + "_meta": { + "title": "KSampler (Efficient)" + } + }, + "379": { + "inputs": { + "instantid_file": "ip-adapter.bin" + }, + "class_type": "InstantIDModelLoader", + "_meta": { + "title": "Load InstantID Model" + } + }, + "380": { + "inputs": { + "control_net_name": "diffusion_pytorch_model.safetensors" + }, + "class_type": "ControlNetLoader", + "_meta": { + "title": "Загрузить модель ControlNet" + } + }, + "381": { + "inputs": { + "provider": "CUDA" + }, + "class_type": "InstantIDFaceAnalysis", + "_meta": { + "title": "InstantID Face Analysis" + } + }, + "382": { + "inputs": { + "weight": 1, + "start_at": 0, + "end_at": 1, + "instantid": [ + "379", + 0 + ], + "insightface": [ + "381", + 0 + ], + "control_net": [ + "380", + 0 + ], + "image": [ + "384", + 0 + ], + "model": [ + "307", + 0 + ], + "positive": [ + "328", + 1 + ], + "negative": [ + "328", + 2 + ], + "image_kps": [ + "328", + 5 + ] + }, + "class_type": "ApplyInstantID", + "_meta": { + "title": "Apply InstantID" + } + }, + "384": { + "inputs": { + "side_length": 512, + "side": "Longest", + "upscale_method": "nearest-exact", + "crop": "disabled", + "image": [ + "563", + 0 + ] + }, + "class_type": "DF_Image_scale_to_side", + "_meta": { + "title": "Image scale to side" + } + }, + "404": { + "inputs": { + "seed": 0 + }, + "class_type": "Seed Everywhere", + "_meta": { + "title": "Seed Everywhere" + } + }, + "405": { + "inputs": { + "toggle": true, + "mode": "simple", + "num_loras": 3, + "lora_1_name": "StickersRedmond.safetensors", + "lora_1_strength": 1, + "lora_1_model_strength": 2, + "lora_1_clip_strength": 2, + "lora_2_name": "cartoon_style.pt", + "lora_2_strength": 2, + "lora_2_model_strength": 1, + "lora_2_clip_strength": 1, + "lora_3_name": "smiling.pt", + "lora_3_strength": 2, + "lora_3_model_strength": 2, + "lora_3_clip_strength": 1, + "lora_4_name": "None", + "lora_4_strength": 1, + "lora_4_model_strength": 1, + "lora_4_clip_strength": 1, + "lora_5_name": "None", + "lora_5_strength": 1, + "lora_5_model_strength": 1, + "lora_5_clip_strength": 1, + "lora_6_name": "None", + "lora_6_strength": 1, + "lora_6_model_strength": 1, + "lora_6_clip_strength": 1, + "lora_7_name": "None", + "lora_7_strength": 1, + "lora_7_model_strength": 1, + "lora_7_clip_strength": 1, + "lora_8_name": "None", + "lora_8_strength": 1, + "lora_8_model_strength": 1, + "lora_8_clip_strength": 1, + "lora_9_name": "None", + "lora_9_strength": 1, + "lora_9_model_strength": 1, + "lora_9_clip_strength": 1, + "lora_10_name": "None", + "lora_10_strength": 1, + "lora_10_model_strength": 1, + "lora_10_clip_strength": 1 + }, + "class_type": "easy loraStack", + "_meta": { + "title": "EasyLoraStack" + } + }, + "406": { + "inputs": { + "model": [ + "305", + 0 + ], + "clip": [ + "305", + 1 + ], + "lora_stack": [ + "405", + 0 + ] + }, + "class_type": "CR Apply LoRA Stack", + "_meta": { + "title": "💊 CR Apply LoRA Stack" + } + }, + "417": { + "inputs": { + "upscale_method": "nearest-exact", + "width": 1024, + "height": 1024, + "crop": "disabled", + "samples": [ + "328", + 3 + ] + }, + "class_type": "LatentUpscale", + "_meta": { + "title": "Увеличить латент" + } + }, + "523": { + "inputs": { + "text": [ + "564", + 0 + ] + }, + "class_type": "ShowText|pysssss", + "_meta": { + "title": "✴️ U-NAI Get Text" + } + }, + "536": { + "inputs": { + "text_input": "Identify if the person in the image is a man, woman, boy or girl. Answer with just one word.", + "model_name": "Qwen2-VL-2B", + "memory_mode": "Balanced (8-bit)", + "max_new_tokens": 512, + "temperature": 0.7000000000000001, + "top_p": 0.8, + "fps": 1, + "image": [ + "555", + 0 + ] + }, + "class_type": "Qwen2VLNode", + "_meta": { + "title": "Qwen2-VL Model" + } + }, + "539": { + "inputs": { + "aggressive": false, + "image": [ + "376", + 0 + ] + }, + "class_type": "FreeMemoryImage", + "_meta": { + "title": "Free Memory (Image)" + } + }, + "555": { + "inputs": { + "width": 762, + "height": 762, + "method": "lanczos", + "images": [ + "563", + 0 + ] + }, + "class_type": "ImageTransformResizeAbsolute", + "_meta": { + "title": "ImageTransformResizeAbsolute" + } + }, + "556": { + "inputs": { + "images": [ + "555", + 0 + ] + }, + "class_type": "PreviewImage", + "_meta": { + "title": "Предварительный просмотр изображения" + } + }, + "562": { + "inputs": { + "Actions": "Send to websocket", + "images": [ + "539", + 0 + ] + }, + "class_type": "ImageOutput", + "_meta": { + "title": "Image(s) To Websocket (Base64)" + } + }, + "563": { + "inputs": { + "image": "" + }, + "class_type": "Load Image (Base64)", + "_meta": { + "title": "Load Image (Base64)" + } + }, + "564": { + "inputs": { + "select": 1, + "sel_mode": false, + "input1": [ + "536", + 0 + ], + "input2": [ + "565", + 0 + ] + }, + "class_type": "ImpactSwitch", + "_meta": { + "title": "Switch (Any)" + } + }, + "565": { + "inputs": { + "text": "" + }, + "class_type": "CR Text", + "_meta": { + "title": "🔤 CR Text" + } + } +} \ No newline at end of file diff --git a/workflow/stickerV2/readme.txt b/workflow/stickerV2/readme.txt new file mode 100644 index 0000000..e708b77 --- /dev/null +++ b/workflow/stickerV2/readme.txt @@ -0,0 +1,6 @@ + +563 - загрузка base64 лицо +562 - получение base64 результата +689 - переключатель автоматического определения пола человека или ручного (1- автоматическое, 2- ручное) +769 - ввод пола человека +585 - промпт \ No newline at end of file diff --git a/workflow/stickerV2/stickerV2_base64_ws_final.json b/workflow/stickerV2/stickerV2_base64_ws_final.json new file mode 100644 index 0000000..b2acd60 --- /dev/null +++ b/workflow/stickerV2/stickerV2_base64_ws_final.json @@ -0,0 +1,525 @@ +{ + "326": { + "inputs": { + "image": "Screenshot_20.png", + "upload": "image" + }, + "class_type": "LoadImage", + "_meta": { + "title": "Загрузить изображение" + } + }, + "376": { + "inputs": { + "rmbgmodel": [ + "615", + 0 + ], + "image": [ + "567", + 5 + ] + }, + "class_type": "BRIA_RMBG_Zho", + "_meta": { + "title": "🧹BRIA RMBG" + } + }, + "379": { + "inputs": { + "instantid_file": "ip-adapter.bin" + }, + "class_type": "InstantIDModelLoader", + "_meta": { + "title": "Load InstantID Model" + } + }, + "380": { + "inputs": { + "control_net_name": "diffusion_pytorch_model.safetensors" + }, + "class_type": "ControlNetLoader", + "_meta": { + "title": "Загрузить модель ControlNet" + } + }, + "523": { + "inputs": { + "text": [ + "689", + 0 + ], + "text2": "man" + }, + "class_type": "ShowText|pysssss", + "_meta": { + "title": "✴️ U-NAI Get Text" + } + }, + "536": { + "inputs": { + "text_input": "Identify if the person in the image is a man, woman, boy or girl. Answer with just one word.", + "model_name": "Qwen2-VL-2B", + "memory_mode": "Balanced (8-bit)", + "max_new_tokens": 512, + "temperature": 0.7000000000000001, + "top_p": 0.8, + "fps": 1, + "image": [ + "563", + 0 + ] + }, + "class_type": "Qwen2VLNode", + "_meta": { + "title": "Qwen2-VL Model" + } + }, + "539": { + "inputs": { + "aggressive": false, + "image": [ + "376", + 0 + ] + }, + "class_type": "FreeMemoryImage", + "_meta": { + "title": "Free Memory (Image)" + } + }, + "562": { + "inputs": { + "Actions": "Send to websocket", + "images": [ + "539", + 0 + ] + }, + "class_type": "ImageOutput", + "_meta": { + "title": "Image(s) To Websocket (Base64)" + } + }, + "563": { + "inputs": { + "image": "" + }, + "class_type": "Load Image (Base64)", + "_meta": { + "title": "Load Image (Base64)" + } + }, + "566": { + "inputs": { + "seed": 378971921426134, + "steps": 8, + "cfg": 4, + "sampler_name": "dpmpp_2m_sde", + "scheduler": "karras", + "denoise": 1, + "preview_method": "auto", + "vae_decode": "true", + "model": [ + "576", + 0 + ], + "positive": [ + "590", + 0 + ], + "negative": [ + "588", + 0 + ], + "latent_image": [ + "591", + 0 + ], + "optional_vae": [ + "575", + 2 + ] + }, + "class_type": "KSampler (Efficient)", + "_meta": { + "title": "KSampler (Efficient)" + } + }, + "567": { + "inputs": { + "seed": 378971921426134, + "steps": 8, + "cfg": 4, + "sampler_name": "dpmpp_2m_sde", + "scheduler": "karras", + "denoise": 1, + "preview_method": "auto", + "vae_decode": "true", + "model": [ + "582", + 0 + ], + "positive": [ + "582", + 1 + ], + "negative": [ + "582", + 2 + ], + "latent_image": [ + "577", + 0 + ], + "optional_vae": [ + "575", + 2 + ] + }, + "class_type": "KSampler (Efficient)", + "_meta": { + "title": "KSampler (Efficient)" + } + }, + "569": { + "inputs": { + "text": ", Sticker, svg, vector art, sharp, kawaii style, Anime style" + }, + "class_type": "CR Text", + "_meta": { + "title": "🔤 CR Text" + } + }, + "570": { + "inputs": { + "text": "shiny, photo, photography, soft, nsfw, nude, ugly, broken, watermark, oversaturated" + }, + "class_type": "CR Text", + "_meta": { + "title": "🔤 CR Text" + } + }, + "571": { + "inputs": { + "text": "half body, looking at viewer, with empty space around" + }, + "class_type": "CR Text", + "_meta": { + "title": "🔤 CR Text" + } + }, + "573": { + "inputs": { + "provider": "CUDA" + }, + "class_type": "InstantIDFaceAnalysis", + "_meta": { + "title": "InstantID Face Analysis" + } + }, + "575": { + "inputs": { + "ckpt_name": "dreamshaperXL_lightningDPMSDE.safetensors" + }, + "class_type": "CheckpointLoaderSimple", + "_meta": { + "title": "Загрузить контрольную точку" + } + }, + "576": { + "inputs": { + "hard_mode": true, + "boost": true, + "model": [ + "575", + 0 + ] + }, + "class_type": "Automatic CFG", + "_meta": { + "title": "Automatic CFG" + } + }, + "577": { + "inputs": { + "width": 1016, + "height": 1016, + "batch_size": 1 + }, + "class_type": "EmptyLatentImage", + "_meta": { + "title": "Пустое латентное изображение" + } + }, + "578": { + "inputs": { + "lora_name": "StickersRedmond.safetensors", + "strength_model": 0.9, + "strength_clip": 1, + "model": [ + "575", + 0 + ], + "clip": [ + "575", + 1 + ] + }, + "class_type": "LoraLoader", + "_meta": { + "title": "Загрузить LoRA" + } + }, + "579": { + "inputs": { + "hard_mode": true, + "boost": true, + "model": [ + "578", + 0 + ] + }, + "class_type": "Automatic CFG", + "_meta": { + "title": "Automatic CFG" + } + }, + "580": { + "inputs": { + "delimiter": "", + "clean_whitespace": "false", + "text_a": [ + "589", + 0 + ], + "text_b": [ + "569", + 0 + ] + }, + "class_type": "Text Concatenate", + "_meta": { + "title": "Text Concatenate" + } + }, + "581": { + "inputs": { + "text": [ + "580", + 0 + ], + "clip": [ + "578", + 1 + ] + }, + "class_type": "CLIPTextEncode", + "_meta": { + "title": "Кодирование текста CLIP (Запрос)" + } + }, + "582": { + "inputs": { + "weight": 1, + "start_at": 0, + "end_at": 1, + "instantid": [ + "379", + 0 + ], + "insightface": [ + "573", + 0 + ], + "control_net": [ + "380", + 0 + ], + "image": [ + "584", + 0 + ], + "model": [ + "579", + 0 + ], + "positive": [ + "581", + 0 + ], + "negative": [ + "583", + 0 + ], + "image_kps": [ + "566", + 5 + ] + }, + "class_type": "ApplyInstantID", + "_meta": { + "title": "Apply InstantID" + } + }, + "583": { + "inputs": { + "text": [ + "570", + 0 + ], + "clip": [ + "578", + 1 + ] + }, + "class_type": "CLIPTextEncode", + "_meta": { + "title": "Кодирование текста CLIP (Запрос)" + } + }, + "584": { + "inputs": { + "upscale_method": "lanczos", + "megapixels": 1, + "image": [ + "563", + 0 + ] + }, + "class_type": "ImageScaleToTotalPixels", + "_meta": { + "title": "Масштабировать изображение до общего количества пикселей" + } + }, + "585": { + "inputs": { + "text": "character belting out a song into a microphone, full of energy and passion" + }, + "class_type": "CR Text", + "_meta": { + "title": "🔤 CR Text" + } + }, + "587": { + "inputs": { + "filename_prefix": "ComfyUI" + }, + "class_type": "SaveImage", + "_meta": { + "title": "Сохранить изображение" + } + }, + "588": { + "inputs": { + "text": [ + "570", + 0 + ], + "clip": [ + "575", + 1 + ] + }, + "class_type": "CLIPTextEncode", + "_meta": { + "title": "Кодирование текста CLIP (Запрос)" + } + }, + "589": { + "inputs": { + "delimiter": "", + "clean_whitespace": "false", + "text_a": [ + "609", + 0 + ], + "text_b": [ + "585", + 0 + ] + }, + "class_type": "Text Concatenate", + "_meta": { + "title": "Text Concatenate" + } + }, + "590": { + "inputs": { + "text": [ + "589", + 0 + ], + "clip": [ + "575", + 1 + ] + }, + "class_type": "CLIPTextEncode", + "_meta": { + "title": "Кодирование текста CLIP (Запрос)" + } + }, + "591": { + "inputs": { + "width": 1024, + "height": 1024, + "batch_size": 1 + }, + "class_type": "EmptyLatentImage", + "_meta": { + "title": "Пустое латентное изображение" + } + }, + "609": { + "inputs": { + "separator": ", ", + "arg1": [ + "523", + 0 + ], + "arg2": [ + "571", + 0 + ] + }, + "class_type": "PromptUtilitiesJoinStringList", + "_meta": { + "title": "Join String List" + } + }, + "615": { + "inputs": {}, + "class_type": "BRIA_RMBG_ModelLoader_Zho", + "_meta": { + "title": "🧹BRIA_RMBG Model Loader" + } + }, + "689": { + "inputs": { + "select": 1, + "sel_mode": false, + "input1": [ + "536", + 0 + ], + "input2": [ + "769", + 0 + ] + }, + "class_type": "ImpactSwitch", + "_meta": { + "title": "Switch (Any)" + } + }, + "769": { + "inputs": { + "text": "woomen" + }, + "class_type": "CR Text", + "_meta": { + "title": "🔤 CR Text" + } + } +} \ No newline at end of file diff --git a/workflow/stickerV2/stickerV2_base64_ws_final_prompts.json b/workflow/stickerV2/stickerV2_base64_ws_final_prompts.json new file mode 100644 index 0000000..c7a2dfe --- /dev/null +++ b/workflow/stickerV2/stickerV2_base64_ws_final_prompts.json @@ -0,0 +1,557 @@ +{ + "326": { + "inputs": { + "image": "girl2.png", + "upload": "image" + }, + "class_type": "LoadImage", + "_meta": { + "title": "Загрузить изображение" + } + }, + "376": { + "inputs": { + "rmbgmodel": [ + "615", + 0 + ], + "image": [ + "606", + 0 + ] + }, + "class_type": "BRIA_RMBG_Zho", + "_meta": { + "title": "🧹BRIA RMBG" + } + }, + "379": { + "inputs": { + "instantid_file": "ip-adapter.bin" + }, + "class_type": "InstantIDModelLoader", + "_meta": { + "title": "Load InstantID Model" + } + }, + "380": { + "inputs": { + "control_net_name": "instantid-controlnet.safetensors" + }, + "class_type": "ControlNetLoader", + "_meta": { + "title": "Загрузить модель ControlNet" + } + }, + "523": { + "inputs": { + "text": [ + "689", + 0 + ], + "text2": "girl" + }, + "class_type": "ShowText|pysssss", + "_meta": { + "title": "✴️ U-NAI Get Text" + } + }, + "536": { + "inputs": { + "text_input": "Identify if the person in the image is a man, woman, boy or girl. Answer with just one word.", + "model_name": "Qwen2-VL-2B", + "memory_mode": "Balanced (8-bit)", + "max_new_tokens": 512, + "temperature": 0.7000000000000001, + "top_p": 0.8, + "fps": 1, + "image": [ + "563", + 0 + ] + }, + "class_type": "Qwen2VLNode", + "_meta": { + "title": "Qwen2-VL Model" + } + }, + "539": { + "inputs": { + "aggressive": false, + "image": [ + "376", + 0 + ] + }, + "class_type": "FreeMemoryImage", + "_meta": { + "title": "Free Memory (Image)" + } + }, + "562": { + "inputs": { + "Actions": "Send to websocket", + "images": [ + "539", + 0 + ] + }, + "class_type": "ImageOutput", + "_meta": { + "title": "Image(s) To Websocket (Base64)" + } + }, + "563": { + "inputs": { + "image": "" + }, + "class_type": "Load Image (Base64)", + "_meta": { + "title": "Load Image (Base64)" + } + }, + "566": { + "inputs": { + "seed": 866300843763550, + "steps": 10, + "cfg": 4, + "sampler_name": "dpmpp_2m_sde", + "scheduler": "karras", + "denoise": 1, + "preview_method": "auto", + "vae_decode": "true", + "model": [ + "576", + 0 + ], + "positive": [ + "590", + 0 + ], + "negative": [ + "588", + 0 + ], + "latent_image": [ + "591", + 0 + ], + "optional_vae": [ + "575", + 2 + ] + }, + "class_type": "KSampler (Efficient)", + "_meta": { + "title": "KSampler (Efficient)" + } + }, + "567": { + "inputs": { + "seed": 378971921426134, + "steps": 10, + "cfg": 4, + "sampler_name": "euler", + "scheduler": "karras", + "denoise": 1, + "preview_method": "auto", + "vae_decode": "true", + "model": [ + "582", + 0 + ], + "positive": [ + "582", + 1 + ], + "negative": [ + "582", + 2 + ], + "latent_image": [ + "577", + 0 + ], + "optional_vae": [ + "575", + 2 + ] + }, + "class_type": "KSampler (Efficient)", + "_meta": { + "title": "KSampler (Efficient)" + } + }, + "569": { + "inputs": { + "text": ", Sticker, svg, vector art, sharp" + }, + "class_type": "CR Text", + "_meta": { + "title": "🔤 CR Text" + } + }, + "570": { + "inputs": { + "text": "shiny, photo, photography, soft, nsfw, nude, ugly, broken, watermark, oversaturated, naked" + }, + "class_type": "CR Text", + "_meta": { + "title": "🔤 CR Text" + } + }, + "571": { + "inputs": { + "text": "" + }, + "class_type": "CR Text", + "_meta": { + "title": "🔤 CR Text" + } + }, + "573": { + "inputs": { + "provider": "CUDA" + }, + "class_type": "InstantIDFaceAnalysis", + "_meta": { + "title": "InstantID Face Analysis" + } + }, + "575": { + "inputs": { + "ckpt_name": "dreamshaperXL_lightningDPMSDE.safetensors" + }, + "class_type": "CheckpointLoaderSimple", + "_meta": { + "title": "Загрузить контрольную точку" + } + }, + "576": { + "inputs": { + "hard_mode": true, + "boost": true, + "model": [ + "575", + 0 + ] + }, + "class_type": "Automatic CFG", + "_meta": { + "title": "Automatic CFG" + } + }, + "577": { + "inputs": { + "width": 1016, + "height": 1016, + "batch_size": 1 + }, + "class_type": "EmptyLatentImage", + "_meta": { + "title": "Пустое латентное изображение" + } + }, + "578": { + "inputs": { + "lora_name": "StickersRedmond.safetensors", + "strength_model": 1, + "strength_clip": 1, + "model": [ + "575", + 0 + ], + "clip": [ + "575", + 1 + ] + }, + "class_type": "LoraLoader", + "_meta": { + "title": "Загрузить LoRA" + } + }, + "579": { + "inputs": { + "hard_mode": true, + "boost": true, + "model": [ + "578", + 0 + ] + }, + "class_type": "Automatic CFG", + "_meta": { + "title": "Automatic CFG" + } + }, + "580": { + "inputs": { + "delimiter": "", + "clean_whitespace": "false", + "text_a": [ + "589", + 0 + ], + "text_b": [ + "569", + 0 + ] + }, + "class_type": "Text Concatenate", + "_meta": { + "title": "Text Concatenate" + } + }, + "581": { + "inputs": { + "text": [ + "580", + 0 + ], + "clip": [ + "578", + 1 + ] + }, + "class_type": "CLIPTextEncode", + "_meta": { + "title": "Кодирование текста CLIP (Запрос)" + } + }, + "582": { + "inputs": { + "weight": 1, + "start_at": 0, + "end_at": 1, + "instantid": [ + "379", + 0 + ], + "insightface": [ + "573", + 0 + ], + "control_net": [ + "380", + 0 + ], + "image": [ + "584", + 0 + ], + "model": [ + "579", + 0 + ], + "positive": [ + "581", + 0 + ], + "negative": [ + "583", + 0 + ], + "image_kps": [ + "566", + 5 + ] + }, + "class_type": "ApplyInstantID", + "_meta": { + "title": "Apply InstantID" + } + }, + "583": { + "inputs": { + "text": [ + "570", + 0 + ], + "clip": [ + "578", + 1 + ] + }, + "class_type": "CLIPTextEncode", + "_meta": { + "title": "Кодирование текста CLIP (Запрос)" + } + }, + "584": { + "inputs": { + "upscale_method": "lanczos", + "megapixels": 1, + "image": [ + "563", + 0 + ] + }, + "class_type": "ImageScaleToTotalPixels", + "_meta": { + "title": "Масштабировать изображение до общего количества пикселей" + } + }, + "585": { + "inputs": { + "text": "Half of body, full face, holding a tiny capybara with both hands, looking at it with exaggerated amazement. Conveying love and adoration for pets" + }, + "class_type": "CR Text", + "_meta": { + "title": "🔤 CR Text" + } + }, + "587": { + "inputs": { + "filename_prefix": "ComfyUI" + }, + "class_type": "SaveImage", + "_meta": { + "title": "Сохранить изображение" + } + }, + "588": { + "inputs": { + "text": [ + "570", + 0 + ], + "clip": [ + "575", + 1 + ] + }, + "class_type": "CLIPTextEncode", + "_meta": { + "title": "Кодирование текста CLIP (Запрос)" + } + }, + "589": { + "inputs": { + "delimiter": "", + "clean_whitespace": "false", + "text_a": [ + "609", + 0 + ], + "text_b": [ + "585", + 0 + ] + }, + "class_type": "Text Concatenate", + "_meta": { + "title": "Text Concatenate" + } + }, + "590": { + "inputs": { + "text": [ + "589", + 0 + ], + "clip": [ + "575", + 1 + ] + }, + "class_type": "CLIPTextEncode", + "_meta": { + "title": "Кодирование текста CLIP (Запрос)" + } + }, + "591": { + "inputs": { + "width": 1024, + "height": 1024, + "batch_size": 1 + }, + "class_type": "EmptyLatentImage", + "_meta": { + "title": "Пустое латентное изображение" + } + }, + "606": { + "inputs": { + "rotate_pitch": 0, + "rotate_yaw": 0, + "rotate_roll": 0, + "blink": 0, + "eyebrow": 0, + "wink": 0, + "pupil_x": 0, + "pupil_y": 0, + "aaa": 0, + "eee": 0, + "woo": 0, + "smile": 0, + "src_ratio": 1, + "sample_ratio": 1, + "sample_parts": "OnlyExpression", + "crop_factor": 1.7, + "src_image": [ + "567", + 5 + ], + "sample_image": [ + "566", + 5 + ] + }, + "class_type": "ExpressionEditor", + "_meta": { + "title": "Expression Editor (PHM)" + } + }, + "609": { + "inputs": { + "separator": ", ", + "arg1": [ + "523", + 0 + ], + "arg2": [ + "571", + 0 + ] + }, + "class_type": "PromptUtilitiesJoinStringList", + "_meta": { + "title": "Join String List" + } + }, + "615": { + "inputs": {}, + "class_type": "BRIA_RMBG_ModelLoader_Zho", + "_meta": { + "title": "🧹BRIA_RMBG Model Loader" + } + }, + "689": { + "inputs": { + "select": 1, + "sel_mode": false, + "input1": [ + "536", + 0 + ], + "input2": [ + "769", + 0 + ] + }, + "class_type": "ImpactSwitch", + "_meta": { + "title": "Switch (Any)" + } + }, + "769": { + "inputs": { + "text": "woomen" + }, + "class_type": "CR Text", + "_meta": { + "title": "🔤 CR Text" + } + } +} \ No newline at end of file diff --git a/workflow/stickerV2_meme/readme.txt b/workflow/stickerV2_meme/readme.txt new file mode 100644 index 0000000..82eb0d8 --- /dev/null +++ b/workflow/stickerV2_meme/readme.txt @@ -0,0 +1,6 @@ +603 - загрузка изображения мема лежит по пути 512meme\(1_512.png - 10_512.png) формат путя нужно указывать для линукс системы. номера изображенйи соответствуют номеру мема на кнопке на фронте +563 - загрузка base64 лицо +562 - получение base64 результата +689 - переключатель автоматического определения пола человека или ручного (1- автоматическое, 2- ручное) +769 - ввод пола человека +585 - промпт в meme не используется \ No newline at end of file diff --git a/workflow/stickerV2_meme/stickerV2_base64_ws_final_meme.json b/workflow/stickerV2_meme/stickerV2_base64_ws_final_meme.json new file mode 100644 index 0000000..a63aae6 --- /dev/null +++ b/workflow/stickerV2_meme/stickerV2_base64_ws_final_meme.json @@ -0,0 +1,580 @@ +{ + "376": { + "inputs": { + "rmbgmodel": [ + "615", + 0 + ], + "image": [ + "606", + 0 + ] + }, + "class_type": "BRIA_RMBG_Zho", + "_meta": { + "title": "🧹BRIA RMBG" + } + }, + "379": { + "inputs": { + "instantid_file": "ip-adapter.bin" + }, + "class_type": "InstantIDModelLoader", + "_meta": { + "title": "Load InstantID Model" + } + }, + "380": { + "inputs": { + "control_net_name": "diffusion_pytorch_model.safetensors" + }, + "class_type": "ControlNetLoader", + "_meta": { + "title": "Загрузить модель ControlNet" + } + }, + "523": { + "inputs": { + "text": [ + "689", + 0 + ], + "text2": "man" + }, + "class_type": "ShowText|pysssss", + "_meta": { + "title": "✴️ U-NAI Get Text" + } + }, + "536": { + "inputs": { + "text_input": "Identify if the person in the image is a man, woman, boy or girl. Answer with just one word.", + "model_name": "Qwen2-VL-2B", + "memory_mode": "Balanced (8-bit)", + "max_new_tokens": 512, + "temperature": 0.7000000000000001, + "top_p": 0.8, + "fps": 1, + "image": [ + "563", + 0 + ] + }, + "class_type": "Qwen2VLNode", + "_meta": { + "title": "Qwen2-VL Model" + } + }, + "539": { + "inputs": { + "aggressive": false, + "image": [ + "376", + 0 + ] + }, + "class_type": "FreeMemoryImage", + "_meta": { + "title": "Free Memory (Image)" + } + }, + "562": { + "inputs": { + "Actions": "Send to websocket", + "images": [ + "539", + 0 + ] + }, + "class_type": "ImageOutput", + "_meta": { + "title": "Image(s) To Websocket (Base64)" + } + }, + "563": { + "inputs": { + "image": "" + }, + "class_type": "Load Image (Base64)", + "_meta": { + "title": "Load Image (Base64)" + } + }, + "566": { + "inputs": { + "seed": 698459364937105, + "steps": 8, + "cfg": 4, + "sampler_name": "dpmpp_2m_sde", + "scheduler": "karras", + "denoise": 1, + "preview_method": "auto", + "vae_decode": "true", + "model": [ + "576", + 0 + ], + "positive": [ + "590", + 0 + ], + "negative": [ + "588", + 0 + ], + "latent_image": [ + "591", + 0 + ], + "optional_vae": [ + "575", + 2 + ] + }, + "class_type": "KSampler (Efficient)", + "_meta": { + "title": "KSampler (Efficient)" + } + }, + "567": { + "inputs": { + "seed": 711685301954594, + "steps": 10, + "cfg": 4, + "sampler_name": "euler", + "scheduler": "karras", + "denoise": 1, + "preview_method": "auto", + "vae_decode": "true", + "model": [ + "582", + 0 + ], + "positive": [ + "582", + 1 + ], + "negative": [ + "582", + 2 + ], + "latent_image": [ + "577", + 0 + ], + "optional_vae": [ + "575", + 2 + ] + }, + "class_type": "KSampler (Efficient)", + "_meta": { + "title": "KSampler (Efficient)" + } + }, + "569": { + "inputs": { + "text": ", Sticker, svg, vector art, sharp, kawaii style, Anime style" + }, + "class_type": "CR Text", + "_meta": { + "title": "🔤 CR Text" + } + }, + "570": { + "inputs": { + "text": "shiny, photo, photography, soft, nsfw, nude, ugly, broken, watermark, oversaturated" + }, + "class_type": "CR Text", + "_meta": { + "title": "🔤 CR Text" + } + }, + "571": { + "inputs": { + "text": "half body, simple T-shirt" + }, + "class_type": "CR Text", + "_meta": { + "title": "🔤 CR Text" + } + }, + "573": { + "inputs": { + "provider": "CUDA" + }, + "class_type": "InstantIDFaceAnalysis", + "_meta": { + "title": "InstantID Face Analysis" + } + }, + "575": { + "inputs": { + "ckpt_name": "dreamshaperXL_lightningDPMSDE.safetensors" + }, + "class_type": "CheckpointLoaderSimple", + "_meta": { + "title": "Загрузить контрольную точку" + } + }, + "576": { + "inputs": { + "hard_mode": true, + "boost": true, + "model": [ + "575", + 0 + ] + }, + "class_type": "Automatic CFG", + "_meta": { + "title": "Automatic CFG" + } + }, + "577": { + "inputs": { + "width": 1016, + "height": 1016, + "batch_size": 1 + }, + "class_type": "EmptyLatentImage", + "_meta": { + "title": "Пустое латентное изображение" + } + }, + "578": { + "inputs": { + "lora_name": "StickersRedmond.safetensors", + "strength_model": 0.9, + "strength_clip": 1, + "model": [ + "575", + 0 + ], + "clip": [ + "575", + 1 + ] + }, + "class_type": "LoraLoader", + "_meta": { + "title": "Загрузить LoRA" + } + }, + "579": { + "inputs": { + "hard_mode": true, + "boost": true, + "model": [ + "578", + 0 + ] + }, + "class_type": "Automatic CFG", + "_meta": { + "title": "Automatic CFG" + } + }, + "580": { + "inputs": { + "delimiter": "", + "clean_whitespace": "false", + "text_a": [ + "589", + 0 + ], + "text_b": [ + "569", + 0 + ] + }, + "class_type": "Text Concatenate", + "_meta": { + "title": "Text Concatenate" + } + }, + "581": { + "inputs": { + "text": [ + "580", + 0 + ], + "clip": [ + "578", + 1 + ] + }, + "class_type": "CLIPTextEncode", + "_meta": { + "title": "Кодирование текста CLIP (Запрос)" + } + }, + "582": { + "inputs": { + "weight": 1, + "start_at": 0, + "end_at": 1, + "instantid": [ + "379", + 0 + ], + "insightface": [ + "573", + 0 + ], + "control_net": [ + "380", + 0 + ], + "image": [ + "584", + 0 + ], + "model": [ + "579", + 0 + ], + "positive": [ + "581", + 0 + ], + "negative": [ + "583", + 0 + ], + "image_kps": [ + "608", + 0 + ] + }, + "class_type": "ApplyInstantID", + "_meta": { + "title": "Apply InstantID" + } + }, + "583": { + "inputs": { + "text": [ + "570", + 0 + ], + "clip": [ + "578", + 1 + ] + }, + "class_type": "CLIPTextEncode", + "_meta": { + "title": "Кодирование текста CLIP (Запрос)" + } + }, + "584": { + "inputs": { + "upscale_method": "lanczos", + "megapixels": 1, + "image": [ + "563", + 0 + ] + }, + "class_type": "ImageScaleToTotalPixels", + "_meta": { + "title": "Масштабировать изображение до общего количества пикселей" + } + }, + "585": { + "inputs": { + "text": "" + }, + "class_type": "CR Text", + "_meta": { + "title": "🔤 CR Text" + } + }, + "588": { + "inputs": { + "text": [ + "570", + 0 + ], + "clip": [ + "575", + 1 + ] + }, + "class_type": "CLIPTextEncode", + "_meta": { + "title": "Кодирование текста CLIP (Запрос)" + } + }, + "589": { + "inputs": { + "delimiter": "", + "clean_whitespace": "false", + "text_a": [ + "609", + 0 + ], + "text_b": [ + "585", + 0 + ] + }, + "class_type": "Text Concatenate", + "_meta": { + "title": "Text Concatenate" + } + }, + "590": { + "inputs": { + "text": [ + "589", + 0 + ], + "clip": [ + "575", + 1 + ] + }, + "class_type": "CLIPTextEncode", + "_meta": { + "title": "Кодирование текста CLIP (Запрос)" + } + }, + "591": { + "inputs": { + "width": 1024, + "height": 1024, + "batch_size": 1 + }, + "class_type": "EmptyLatentImage", + "_meta": { + "title": "Пустое латентное изображение" + } + }, + "603": { + "inputs": { + "image": "Patrick Bateman Ou.png", + "upload": "image" + }, + "class_type": "LoadImage", + "_meta": { + "title": "face" + } + }, + "606": { + "inputs": { + "rotate_pitch": 0, + "rotate_yaw": 0, + "rotate_roll": 0, + "blink": 0, + "eyebrow": 0, + "wink": 0, + "pupil_x": 0, + "pupil_y": 0, + "aaa": 0, + "eee": 0, + "woo": 0, + "smile": 0.01, + "src_ratio": 1, + "sample_ratio": 0.8, + "sample_parts": "OnlyExpression", + "crop_factor": 1.7, + "src_image": [ + "567", + 5 + ], + "sample_image": [ + "603", + 0 + ] + }, + "class_type": "ExpressionEditor", + "_meta": { + "title": "Expression Editor (PHM)" + } + }, + "608": { + "inputs": { + "rotate_pitch": 0, + "rotate_yaw": 0, + "rotate_roll": 0, + "blink": 0, + "eyebrow": 0, + "wink": 0, + "pupil_x": 0, + "pupil_y": 0, + "aaa": 0, + "eee": 0, + "woo": 0, + "smile": 0, + "src_ratio": 1, + "sample_ratio": 1, + "sample_parts": "All", + "crop_factor": 1.7000000000000002, + "src_image": [ + "566", + 5 + ], + "sample_image": [ + "603", + 0 + ] + }, + "class_type": "ExpressionEditor", + "_meta": { + "title": "Expression Editor (PHM)" + } + }, + "609": { + "inputs": { + "separator": ", ", + "arg1": [ + "523", + 0 + ], + "arg2": [ + "571", + 0 + ] + }, + "class_type": "PromptUtilitiesJoinStringList", + "_meta": { + "title": "Join String List" + } + }, + "615": { + "inputs": {}, + "class_type": "BRIA_RMBG_ModelLoader_Zho", + "_meta": { + "title": "🧹BRIA_RMBG Model Loader" + } + }, + "689": { + "inputs": { + "select": 1, + "sel_mode": false, + "input1": [ + "536", + 0 + ], + "input2": [ + "769", + 0 + ] + }, + "class_type": "ImpactSwitch", + "_meta": { + "title": "Switch (Any)" + } + }, + "769": { + "inputs": { + "text": "man" + }, + "class_type": "CR Text", + "_meta": { + "title": "🔤 CR Text" + } + } +} \ No newline at end of file diff --git a/workflow/stickerV2_meme/stickerV2_base64_ws_meme.json b/workflow/stickerV2_meme/stickerV2_base64_ws_meme.json new file mode 100644 index 0000000..3980183 --- /dev/null +++ b/workflow/stickerV2_meme/stickerV2_base64_ws_meme.json @@ -0,0 +1,606 @@ +{ + "326": { + "inputs": { + "image": "512.png" + }, + "class_type": "LoadImage", + "_meta": { + "title": "Загрузить изображение" + } + }, + "376": { + "inputs": { + "rmbgmodel": [ + "615", + 0 + ], + "image": [ + "606", + 0 + ] + }, + "class_type": "BRIA_RMBG_Zho", + "_meta": { + "title": "🧹BRIA RMBG" + } + }, + "379": { + "inputs": { + "instantid_file": "ip-adapter.bin" + }, + "class_type": "InstantIDModelLoader", + "_meta": { + "title": "Load InstantID Model" + } + }, + "380": { + "inputs": { + "control_net_name": "diffusion_pytorch_model.safetensors" + }, + "class_type": "ControlNetLoader", + "_meta": { + "title": "Загрузить модель ControlNet" + } + }, + "523": { + "inputs": { + "text": [ + "689", + 0 + ], + "text2": "Man" + }, + "class_type": "ShowText|pysssss", + "_meta": { + "title": "Show Text 🐍" + } + }, + "536": { + "inputs": { + "text_input": "Identify if the person in the image is a man, woman, boy or girl. Answer with just one word.", + "model_name": "Qwen2-VL-2B", + "memory_mode": "Balanced (8-bit)", + "max_new_tokens": 512, + "temperature": 0.7000000000000001, + "top_p": 0.8, + "fps": 1, + "image": [ + "563", + 0 + ] + }, + "class_type": "Qwen2VLNode", + "_meta": { + "title": "Qwen2-VL Model" + } + }, + "539": { + "inputs": { + "aggressive": false, + "image": [ + "376", + 0 + ] + }, + "class_type": "FreeMemoryImage", + "_meta": { + "title": "Free Memory (Image)" + } + }, + "562": { + "inputs": { + "Actions": "Send to websocket", + "images": [ + "539", + 0 + ] + }, + "class_type": "ImageOutput", + "_meta": { + "title": "Image(s) To Websocket (Base64)" + } + }, + "563": { + "inputs": { + "image": "" + }, + "class_type": "Load Image (Base64)", + "_meta": { + "title": "Load Image (Base64)" + } + }, + "566": { + "inputs": { + "seed": 378971921426134, + "steps": 8, + "cfg": 4, + "sampler_name": "dpmpp_2m_sde", + "scheduler": "karras", + "denoise": 1, + "preview_method": "auto", + "vae_decode": "true", + "model": [ + "576", + 0 + ], + "positive": [ + "590", + 0 + ], + "negative": [ + "588", + 0 + ], + "latent_image": [ + "591", + 0 + ], + "optional_vae": [ + "575", + 2 + ] + }, + "class_type": "KSampler (Efficient)", + "_meta": { + "title": "KSampler (Efficient)" + } + }, + "567": { + "inputs": { + "seed": 378971921426134, + "steps": 8, + "cfg": 4, + "sampler_name": "dpmpp_2m_sde", + "scheduler": "karras", + "denoise": 1, + "preview_method": "auto", + "vae_decode": "true", + "model": [ + "582", + 0 + ], + "positive": [ + "582", + 1 + ], + "negative": [ + "582", + 2 + ], + "latent_image": [ + "577", + 0 + ], + "optional_vae": [ + "575", + 2 + ] + }, + "class_type": "KSampler (Efficient)", + "_meta": { + "title": "KSampler (Efficient)" + } + }, + "569": { + "inputs": { + "text": ", Sticker, svg, vector art, sharp, kawaii style, Anime style" + }, + "class_type": "CR Text", + "_meta": { + "title": "🔤 CR Text" + } + }, + "570": { + "inputs": { + "text": "shiny, photo, photography, soft, nsfw, nude, ugly, broken, watermark, oversaturated" + }, + "class_type": "CR Text", + "_meta": { + "title": "🔤 CR Text" + } + }, + "571": { + "inputs": { + "text": "half body, looking at viewer, with empty space around" + }, + "class_type": "CR Text", + "_meta": { + "title": "🔤 CR Text" + } + }, + "573": { + "inputs": { + "provider": "CUDA" + }, + "class_type": "InstantIDFaceAnalysis", + "_meta": { + "title": "InstantID Face Analysis" + } + }, + "575": { + "inputs": { + "ckpt_name": "dreamshaperXL_lightningDPMSDE.safetensors" + }, + "class_type": "CheckpointLoaderSimple", + "_meta": { + "title": "Загрузить сheckpoint" + } + }, + "576": { + "inputs": { + "hard_mode": true, + "boost": true, + "model": [ + "575", + 0 + ] + }, + "class_type": "Automatic CFG", + "_meta": { + "title": "Automatic CFG" + } + }, + "577": { + "inputs": { + "width": 1016, + "height": 1016, + "batch_size": 1 + }, + "class_type": "EmptyLatentImage", + "_meta": { + "title": "Пустое латентное изображение" + } + }, + "578": { + "inputs": { + "lora_name": "StickersRedmond.safetensors", + "strength_model": 0.9, + "strength_clip": 1, + "model": [ + "575", + 0 + ], + "clip": [ + "575", + 1 + ] + }, + "class_type": "LoraLoader", + "_meta": { + "title": "Загрузить LoRA" + } + }, + "579": { + "inputs": { + "hard_mode": true, + "boost": true, + "model": [ + "578", + 0 + ] + }, + "class_type": "Automatic CFG", + "_meta": { + "title": "Automatic CFG" + } + }, + "580": { + "inputs": { + "delimiter": "", + "clean_whitespace": "false", + "text_a": [ + "589", + 0 + ], + "text_b": [ + "569", + 0 + ] + }, + "class_type": "Text Concatenate", + "_meta": { + "title": "Text Concatenate" + } + }, + "581": { + "inputs": { + "text": [ + "580", + 0 + ], + "clip": [ + "578", + 1 + ] + }, + "class_type": "CLIPTextEncode", + "_meta": { + "title": "Кодирование текста CLIP (Запрос)" + } + }, + "582": { + "inputs": { + "weight": 1, + "start_at": 0, + "end_at": 1, + "instantid": [ + "379", + 0 + ], + "insightface": [ + "573", + 0 + ], + "control_net": [ + "380", + 0 + ], + "image": [ + "584", + 0 + ], + "model": [ + "579", + 0 + ], + "positive": [ + "581", + 0 + ], + "negative": [ + "583", + 0 + ], + "image_kps": [ + "608", + 0 + ] + }, + "class_type": "ApplyInstantID", + "_meta": { + "title": "Apply InstantID" + } + }, + "583": { + "inputs": { + "text": [ + "570", + 0 + ], + "clip": [ + "578", + 1 + ] + }, + "class_type": "CLIPTextEncode", + "_meta": { + "title": "Кодирование текста CLIP (Запрос)" + } + }, + "584": { + "inputs": { + "upscale_method": "lanczos", + "megapixels": 1, + "image": [ + "563", + 0 + ] + }, + "class_type": "ImageScaleToTotalPixels", + "_meta": { + "title": "Масштабировать изображение до общего количества пикселей" + } + }, + "585": { + "inputs": { + "text": "" + }, + "class_type": "CR Text", + "_meta": { + "title": "🔤 CR Text" + } + }, + "587": { + "inputs": { + "filename_prefix": "ComfyUI" + }, + "class_type": "SaveImage", + "_meta": { + "title": "Сохранить изображение" + } + }, + "588": { + "inputs": { + "text": [ + "570", + 0 + ], + "clip": [ + "575", + 1 + ] + }, + "class_type": "CLIPTextEncode", + "_meta": { + "title": "Кодирование текста CLIP (Запрос)" + } + }, + "589": { + "inputs": { + "delimiter": "", + "clean_whitespace": "false", + "text_a": [ + "609", + 0 + ], + "text_b": [ + "585", + 0 + ] + }, + "class_type": "Text Concatenate", + "_meta": { + "title": "Text Concatenate" + } + }, + "590": { + "inputs": { + "text": [ + "589", + 0 + ], + "clip": [ + "575", + 1 + ] + }, + "class_type": "CLIPTextEncode", + "_meta": { + "title": "Кодирование текста CLIP (Запрос)" + } + }, + "591": { + "inputs": { + "width": 1024, + "height": 1024, + "batch_size": 1 + }, + "class_type": "EmptyLatentImage", + "_meta": { + "title": "Пустое латентное изображение" + } + }, + "603": { + "inputs": { + "image": "Screenshot_цув4.png" + }, + "class_type": "LoadImage", + "_meta": { + "title": "face" + } + }, + "606": { + "inputs": { + "rotate_pitch": 0, + "rotate_yaw": 0, + "rotate_roll": 0, + "blink": 0, + "eyebrow": 0, + "wink": 0, + "pupil_x": 0, + "pupil_y": 0, + "aaa": 0, + "eee": 0, + "woo": 0, + "smile": 0.01, + "src_ratio": 1, + "sample_ratio": 1.2, + "sample_parts": "OnlyExpression", + "crop_factor": 1.7, + "src_image": [ + "567", + 5 + ], + "sample_image": [ + "770", + 0 + ] + }, + "class_type": "ExpressionEditor", + "_meta": { + "title": "Expression Editor (PHM)" + } + }, + "608": { + "inputs": { + "rotate_pitch": 0, + "rotate_yaw": 0, + "rotate_roll": 0, + "blink": 0, + "eyebrow": 0, + "wink": 0, + "pupil_x": 0, + "pupil_y": 0, + "aaa": 0, + "eee": 0, + "woo": 0, + "smile": 0, + "src_ratio": 1, + "sample_ratio": 1, + "sample_parts": "All", + "crop_factor": 1.7, + "src_image": [ + "566", + 5 + ], + "sample_image": [ + "770", + 0 + ] + }, + "class_type": "ExpressionEditor", + "_meta": { + "title": "Expression Editor (PHM)" + } + }, + "609": { + "inputs": { + "separator": ", ", + "arg1": [ + "523", + 0 + ], + "arg2": [ + "571", + 0 + ] + }, + "class_type": "PromptUtilitiesJoinStringList", + "_meta": { + "title": "Join String List" + } + }, + "615": { + "inputs": {}, + "class_type": "BRIA_RMBG_ModelLoader_Zho", + "_meta": { + "title": "🧹BRIA_RMBG Model Loader" + } + }, + "689": { + "inputs": { + "select": 1, + "sel_mode": false, + "input1": [ + "536", + 0 + ], + "input2": [ + "769", + 0 + ] + }, + "class_type": "ImpactSwitch", + "_meta": { + "title": "Switch (Any)" + } + }, + "769": { + "inputs": { + "text": "woomen" + }, + "class_type": "CR Text", + "_meta": { + "title": "🔤 CR Text" + } + }, + "770": { + "inputs": { + "image": "" + }, + "class_type": "Load Image (Base64)", + "_meta": { + "title": "Load Image (Base64)" + } + } +} \ No newline at end of file