import type { Property } from 'csstype'; import { IconButton } from '@/app/components/button'; import { ChatAction } from '@/app/components/chat'; import chatStyles from '@/app/components/chat.module.scss'; import { WindowContent } from '@/app/components/home'; import homeStyles from '@/app/components/home.module.scss'; import styles from '@/app/components/sd/sd.module.scss'; import { showConfirm, showImageModal, showModal, } from '@/app/components/ui-lib'; import { getClientConfig } from '@/app/config/client'; import { Path } from '@/app/constant'; import DeleteIcon from '@/app/icons/clear.svg'; import CopyIcon from '@/app/icons/copy.svg'; import ErrorIcon from '@/app/icons/delete.svg'; import MaxIcon from '@/app/icons/max.svg'; import MinIcon from '@/app/icons/min.svg'; import PromptIcon from '@/app/icons/prompt.svg'; import ResetIcon from '@/app/icons/reload.svg'; import ReturnIcon from '@/app/icons/return.svg'; import SDIcon from '@/app/icons/sd.svg'; import LoadingIcon from '@/app/icons/three-dots.svg'; import Locale from '@/app/locales'; import { useAppConfig } from '@/app/store'; import { useSdStore } from '@/app/store/sd'; import { copyToClipboard, getMessageTextContent, useMobileScreen, } from '@/app/utils'; import { removeImage } from '@/app/utils/chat'; import clsx from 'clsx'; import React, { useEffect, useMemo, useRef, useState } from 'react'; import { useLocation, useNavigate } from 'react-router-dom'; import { params } from './sd-panel'; import { SideBar } from './sd-sidebar'; function getSdTaskStatus(item: any) { let s: string; let color: Property.Color | undefined; switch (item.status) { case 'success': s = Locale.Sd.Status.Success; color = 'green'; break; case 'error': s = Locale.Sd.Status.Error; color = 'red'; break; case 'wait': s = Locale.Sd.Status.Wait; color = 'yellow'; break; case 'running': s = Locale.Sd.Status.Running; color = 'blue'; break; default: s = item.status.toUpperCase(); } return (

{Locale.Sd.Status.Name} : {s} {item.status === 'error' && ( { showModal({ title: Locale.Sd.Detail, children: (

{item.error}
), }); }} > - {' '} {item.error} )}

); } export function Sd() { const isMobileScreen = useMobileScreen(); const navigate = useNavigate(); const location = useLocation(); const clientConfig = useMemo(() => getClientConfig(), []); const showMaxIcon = !isMobileScreen && !clientConfig?.isApp; const config = useAppConfig(); const scrollRef = useRef(null); const sdStore = useSdStore(); const [sdImages, setSdImages] = useState(sdStore.draw); const isSd = location.pathname === Path.Sd; useEffect(() => { setSdImages(sdStore.draw); }, [sdStore.currentId]); return ( <>
{isMobileScreen && (
} bordered title={Locale.Chat.Actions.ChatList} onClick={() => navigate(Path.Sd)} />
)}
Stability AI
{Locale.Sd.SubTitle(sdImages.length || 0)}
{showMaxIcon && (
: } bordered onClick={() => { config.update( config => (config.tightBorder = !config.tightBorder), ); }} />
)} {isMobileScreen && }
{sdImages.length > 0 ? ( sdImages.map((item: any) => { return (
{item.status === 'success' ? ( {item.id} showImageModal( item.img_data, true, isMobileScreen ? { width: '100%', height: 'fit-content' } : { maxWidth: '100%', maxHeight: '100%' }, isMobileScreen ? { width: '100%', height: 'fit-content' } : { width: '100%', height: '100%' }, )} /> ) : item.status === 'error' ? (
) : (
)}

{Locale.SdPanel.Prompt} : {' '} { showModal({ title: Locale.Sd.Detail, children: (

{item.params.prompt}
), }); }} > {item.params.prompt}

{Locale.SdPanel.AIModel} : {item.model_name}

{getSdTaskStatus(item)}

{item.created_at}

} onClick={() => { showModal({ title: Locale.Sd.GenerateParams, children: (
{Object.keys(item.params).map((key) => { let label = key; let value = item.params[key]; switch (label) { case 'prompt': label = Locale.SdPanel.Prompt; break; case 'negative_prompt': label = Locale.SdPanel.NegativePrompt; break; case 'aspect_ratio': label = Locale.SdPanel.AspectRatio; break; case 'seed': label = 'Seed'; value = value || 0; break; case 'output_format': label = Locale.SdPanel.OutFormat; value = value?.toUpperCase(); break; case 'style': label = Locale.SdPanel.ImageStyle; value = params .find( item => item.value === 'style', ) ?.options ?.find( item => item.value === value, ) ?.name; break; default: break; } return (
{label} : {' '} {value}
); })}
), }); }} /> } onClick={() => copyToClipboard( getMessageTextContent({ role: 'user', content: item.params.prompt, }), )} /> } onClick={() => { const reqData = { model: item.model, model_name: item.model_name, status: 'wait', params: { ...item.params }, created_at: new Date().toLocaleString(), img_data: '', }; sdStore.sendTask(reqData); }} /> } onClick={async () => { if ( await showConfirm(Locale.Sd.Danger.Delete) ) { // remove img_data + remove item in list removeImage(item.img_data).finally(() => { sdStore.draw = sdImages.filter( (i: any) => i.id !== item.id, ); sdStore.getNextId(); }); } }} />
); }) ) : (
{Locale.Sd.EmptyRecord}
)}
); }