-
Notifications
You must be signed in to change notification settings - Fork 25
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add image generation to assistant (#181)
* wip * Add image character inference in novel builder * wip emotions inference * fix img gen * Fix seed, fix inference for multiple emotions * Add pending generations widget * disable emotions gen if no default image * Add cretion credits for character and emotions * add poses to character generation, wip novel assistant with imggen * wip emotion group generation * Fix pose image inference, fix premium novel assistant * add pricing constraint to novel assistant, remove parts of disclaimer * Add spend approval modal * Add item and background generation * remove old generation prompts * add background and item image generation to novel assistant * minor fixes * revert configs
- Loading branch information
Showing
38 changed files
with
2,488 additions
and
161 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,79 @@ | ||
@import '../styles/variables'; | ||
.CreditsWidget { | ||
position: relative; // Ensure the dropdown is positioned relative to the widget | ||
display: flex; | ||
justify-content: center; | ||
align-items: center; | ||
gap: 10px; | ||
font-size: 0.9rem; | ||
font-weight: normal; | ||
|
||
&__credits { | ||
display: flex; | ||
align-items: center; | ||
gap: 0.5rem; | ||
} | ||
|
||
&__pending { | ||
cursor: pointer; | ||
display: inline-flex; | ||
} | ||
|
||
.rotating-cog { | ||
font-size: 1.2rem; | ||
/* Rotating animation for the cog */ | ||
animation: rotation 2s linear infinite; | ||
color: $text-2; | ||
transition: color 0.2s ease-out; | ||
|
||
&:hover { | ||
color: #fff; | ||
} | ||
} | ||
|
||
@keyframes rotation { | ||
from { | ||
transform: rotate(0deg); | ||
} | ||
to { | ||
transform: rotate(359deg); | ||
} | ||
} | ||
|
||
&__dropdown { | ||
position: absolute; | ||
top: 110%; | ||
right: 0; | ||
background-color: $background-1; | ||
border: 1px solid $text-2; | ||
width: 300px; | ||
max-height: 200px; | ||
overflow-y: auto; | ||
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.2); | ||
z-index: 10; | ||
padding: 0.5rem; | ||
border-radius: 4px; | ||
} | ||
|
||
&__dropdown-header { | ||
font-size: 0.9rem; | ||
font-weight: normal; | ||
padding: 0.2rem; | ||
text-align: right; | ||
} | ||
|
||
&__dropdown-content { | ||
padding: 0.2rem; | ||
overflow: auto; | ||
max-height: 150px; | ||
} | ||
|
||
&__inference { | ||
background-color: $background-2; | ||
padding: 4px; | ||
margin-bottom: 4px; | ||
&:last-child { | ||
border-bottom: none; | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,109 @@ | ||
import { useAppSelector, useAppDispatch } from '../state/store'; | ||
import { fetchPrices, fetchUser } from '../state/slices/userSlice'; | ||
import { useEffect, useState } from 'react'; | ||
import { PiCoinsLight } from 'react-icons/pi'; | ||
import { IoCog } from 'react-icons/io5'; | ||
import './CreditsWidget.scss'; | ||
|
||
interface PendingInference { | ||
inferenceId: string; | ||
inferenceType: 'character' | 'emotion' | 'background' | 'item'; | ||
prompt: string; | ||
characterId?: string; | ||
outfitId?: string; | ||
emotionId?: string; | ||
backgroundId?: string; | ||
itemId?: string; | ||
} | ||
|
||
export default function CreditsWidget() { | ||
const dispatch = useAppDispatch(); | ||
const user = useAppSelector((state) => state.user.user); | ||
const pendingInferences = useAppSelector((state) => state.novel.pendingInferences); | ||
const characters = useAppSelector((state) => state.novel.characters); | ||
const inventory = useAppSelector((state) => state.novel.inventory); | ||
const backgrounds = useAppSelector((state) => state.novel.backgrounds); | ||
|
||
const [showDropdown, setShowDropdown] = useState(false); | ||
|
||
useEffect(() => { | ||
dispatch(fetchUser()); | ||
dispatch(fetchPrices()); | ||
}, [dispatch]); | ||
|
||
useEffect(() => { | ||
if (!pendingInferences || pendingInferences.length === 0) { | ||
setShowDropdown(false); | ||
} | ||
}, [pendingInferences]); | ||
|
||
const renderInference = (inference: PendingInference) => { | ||
switch (inference.inferenceType) { | ||
case 'character': { | ||
const character = characters.find((c) => c.id === inference.characterId); | ||
let outfitName = ''; | ||
if (character && character.card && character.card.data && character.card.data.extensions?.mikugg_v2?.outfits) { | ||
const outfit = character.card.data.extensions.mikugg_v2.outfits.find((o) => o.id === inference.outfitId); | ||
outfitName = outfit ? outfit.name : inference.outfitId || ''; | ||
} | ||
return ( | ||
<div> | ||
{character ? character.name : inference.characterId} - {outfitName} outfit | ||
</div> | ||
); | ||
} | ||
case 'emotion': { | ||
const character = characters.find((c) => c.id === inference.characterId); | ||
let outfitName = ''; | ||
if (character && character.card && character.card.data && character.card.data.extensions?.mikugg_v2?.outfits) { | ||
const outfit = character.card.data.extensions.mikugg_v2.outfits.find((o) => o.id === inference.outfitId); | ||
outfitName = outfit ? outfit.name : inference.outfitId || ''; | ||
} | ||
return ( | ||
<div> | ||
{character ? character.name : inference.characterId} - {outfitName}, {inference.emotionId} | ||
</div> | ||
); | ||
} | ||
case 'item': { | ||
const item = inventory?.find((i) => i.id === inference.itemId); | ||
return <div>{item ? item.name : inference.itemId} item</div>; | ||
} | ||
case 'background': { | ||
const bg = backgrounds.find((b) => b.id === inference.backgroundId); | ||
return <div>{bg ? bg.name : inference.backgroundId} background</div>; | ||
} | ||
default: | ||
return <div>Unknown inference</div>; | ||
} | ||
}; | ||
|
||
return ( | ||
<div className="CreditsWidget"> | ||
<div className="CreditsWidget__credits"> | ||
<PiCoinsLight /> {user?.credits || 0} credits | ||
</div> | ||
{pendingInferences?.length ? ( | ||
<div | ||
className="CreditsWidget__pending" | ||
onClick={() => setShowDropdown((prev) => !prev)} | ||
title="View pending inferences" | ||
> | ||
<IoCog className="rotating-cog" /> | ||
</div> | ||
) : null} | ||
{showDropdown && pendingInferences?.length && ( | ||
<div className="CreditsWidget__dropdown"> | ||
<div className="CreditsWidget__dropdown-header">Pending Generations</div> | ||
<div className="CreditsWidget__dropdown-content scrollbar"> | ||
{pendingInferences.map((inference: PendingInference) => ( | ||
<div key={inference.inferenceId} className="CreditsWidget__inference"> | ||
{renderInference(inference)} | ||
</div> | ||
))} | ||
</div> | ||
</div> | ||
)} | ||
</div> | ||
); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.