mirror of
https://github.com/invoke-ai/InvokeAI.git
synced 2026-02-13 17:34:57 -05:00
Fixes & Styling updates
This commit is contained in:
committed by
psychedelicious
parent
90201be670
commit
8b8e29d22d
@@ -2471,6 +2471,10 @@
|
||||
"title": "Upload Image to Upscale",
|
||||
"description": "Click or drag an image to upscale (JPG, PNG, WebP up to 100MB)"
|
||||
},
|
||||
"replaceImage": {
|
||||
"title": "Replace Current Image",
|
||||
"description": "Click or drag a new image to replace the current one"
|
||||
},
|
||||
"imageReady": {
|
||||
"title": "Image Ready",
|
||||
"description": "Press Invoke to begin upscaling"
|
||||
|
||||
@@ -11,6 +11,7 @@ export const LaunchpadButton = memo(
|
||||
display="flex"
|
||||
position="relative"
|
||||
alignItems="center"
|
||||
justifyContent="left"
|
||||
borderWidth={1}
|
||||
borderRadius="base"
|
||||
p={4}
|
||||
|
||||
@@ -1,17 +1,14 @@
|
||||
import { Box, Flex, Grid, Heading, Icon, Text } from '@invoke-ai/ui-library';
|
||||
import { Box, Button, Flex, Grid, Heading, Icon, Text } from '@invoke-ai/ui-library';
|
||||
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
|
||||
import { useImageUploadButton } from 'common/hooks/useImageUploadButton';
|
||||
import { setUpscaleInitialImageDndTarget } from 'features/dnd/dnd';
|
||||
import { DndDropTarget } from 'features/dnd/DndDropTarget';
|
||||
import { DndImage } from 'features/dnd/DndImage';
|
||||
import { DndImageIcon } from 'features/dnd/DndImageIcon';
|
||||
import ParamSpandrelModel from 'features/parameters/components/Upscale/ParamSpandrelModel';
|
||||
import { selectUpscaleInitialImage, upscaleInitialImageChanged } from 'features/parameters/store/upscaleSlice';
|
||||
import { MainModelPicker } from 'features/settingsAccordions/components/GenerationSettingsAccordion/MainModelPicker';
|
||||
import { UpscaleScaleSlider } from 'features/settingsAccordions/components/UpscaleSettingsAccordion/UpscaleScaleSlider';
|
||||
import { selectUpscaleInitialImage, upscaleInitialImageChanged, creativityChanged, structureChanged, selectCreativity, selectStructure } from 'features/parameters/store/upscaleSlice';
|
||||
import { memo, useCallback, useMemo } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { PiArrowCounterClockwiseBold, PiImageBold, PiUploadBold } from 'react-icons/pi';
|
||||
import { PiArrowCounterClockwiseBold, PiImageBold, PiUploadBold, PiShieldCheckBold, PiScalesBold, PiPaletteBold, PiSparkleBold } from 'react-icons/pi';
|
||||
import type { ImageDTO } from 'services/api/types';
|
||||
|
||||
import { LaunchpadButton } from './LaunchpadButton';
|
||||
@@ -20,6 +17,8 @@ export const UpscalingLaunchpadPanel = memo(() => {
|
||||
const { t } = useTranslation();
|
||||
const dispatch = useAppDispatch();
|
||||
const upscaleInitialImage = useAppSelector(selectUpscaleInitialImage);
|
||||
const creativity = useAppSelector(selectCreativity);
|
||||
const structure = useAppSelector(selectStructure);
|
||||
|
||||
const dndTargetData = useMemo(() => setUpscaleInitialImageDndTarget.getData(), []);
|
||||
|
||||
@@ -36,6 +35,27 @@ export const UpscalingLaunchpadPanel = memo(() => {
|
||||
|
||||
const uploadApi = useImageUploadButton({ allowMultiple: false, onUpload });
|
||||
|
||||
// Preset button handlers
|
||||
const onConservativeClick = useCallback(() => {
|
||||
dispatch(creativityChanged(-5));
|
||||
dispatch(structureChanged(5));
|
||||
}, [dispatch]);
|
||||
|
||||
const onBalancedClick = useCallback(() => {
|
||||
dispatch(creativityChanged(0));
|
||||
dispatch(structureChanged(0));
|
||||
}, [dispatch]);
|
||||
|
||||
const onCreativeClick = useCallback(() => {
|
||||
dispatch(creativityChanged(5));
|
||||
dispatch(structureChanged(-2));
|
||||
}, [dispatch]);
|
||||
|
||||
const onArtisticClick = useCallback(() => {
|
||||
dispatch(creativityChanged(8));
|
||||
dispatch(structureChanged(-5));
|
||||
}, [dispatch]);
|
||||
|
||||
return (
|
||||
<Flex flexDir="column" h="full" w="full" alignItems="center" gap={2}>
|
||||
<Flex flexDir="column" w="full" gap={4} px={14} maxW={768} pt="20vh">
|
||||
@@ -57,34 +77,14 @@ export const UpscalingLaunchpadPanel = memo(() => {
|
||||
</>
|
||||
) : (
|
||||
<>
|
||||
<Flex position="relative" w={16} h={16} alignItems="center" justifyContent="center">
|
||||
<DndImage imageDTO={upscaleInitialImage} />
|
||||
<Flex position="absolute" flexDir="column" top={1} insetInlineEnd={1} gap={1}>
|
||||
<DndImageIcon
|
||||
onClick={onReset}
|
||||
icon={<PiArrowCounterClockwiseBold size={12} />}
|
||||
tooltip={t('common.reset')}
|
||||
/>
|
||||
</Flex>
|
||||
<Text
|
||||
position="absolute"
|
||||
background="base.900"
|
||||
color="base.50"
|
||||
fontSize="xs"
|
||||
fontWeight="semibold"
|
||||
bottom={0}
|
||||
left={0}
|
||||
opacity={0.7}
|
||||
px={1}
|
||||
lineHeight={1.25}
|
||||
borderTopEndRadius="base"
|
||||
borderBottomStartRadius="base"
|
||||
pointerEvents="none"
|
||||
>{`${upscaleInitialImage.width}x${upscaleInitialImage.height}`}</Text>
|
||||
</Flex>
|
||||
<Icon as={PiImageBold} boxSize={8} color="base.500" />
|
||||
<Flex flexDir="column" alignItems="flex-start" gap={2}>
|
||||
<Heading size="sm">{t('ui.launchpad.upscaling.imageReady.title')}</Heading>
|
||||
<Text color="base.300">{t('ui.launchpad.upscaling.imageReady.description')}</Text>
|
||||
<Heading size="sm">{t('ui.launchpad.upscaling.replaceImage.title')}</Heading>
|
||||
<Text color="base.300">{t('ui.launchpad.upscaling.replaceImage.description')}</Text>
|
||||
</Flex>
|
||||
<Flex position="absolute" right={3} bottom={3}>
|
||||
<PiUploadBold />
|
||||
<input {...uploadApi.getUploadInputProps()} />
|
||||
</Flex>
|
||||
</>
|
||||
)}
|
||||
@@ -108,33 +108,54 @@ export const UpscalingLaunchpadPanel = memo(() => {
|
||||
{/* Controls */}
|
||||
<style>{`.launchpad-hide-label .chakra-form__label { display: none !important; }`}</style>
|
||||
<Grid gridTemplateColumns="1fr 1fr" gap={10} alignItems="start" mt={upscaleInitialImage ? 8 : 12}>
|
||||
{/* Left Column: All parameters stacked */}
|
||||
<Flex flexDir="column" gap={6} alignItems="flex-start">
|
||||
<Box w="full">
|
||||
<Text fontWeight="semibold" fontSize="sm" mb={1}>
|
||||
{t('ui.launchpad.upscaling.upscaleModel')}
|
||||
</Text>
|
||||
<Box className="launchpad-hide-label">
|
||||
<ParamSpandrelModel />
|
||||
</Box>
|
||||
</Box>
|
||||
<Box w="full">
|
||||
<Text fontWeight="semibold" fontSize="sm" mb={1}>
|
||||
{t('ui.launchpad.upscaling.model')}
|
||||
</Text>
|
||||
<Box className="launchpad-hide-label">
|
||||
<MainModelPicker />
|
||||
</Box>
|
||||
</Box>
|
||||
<Box w="full">
|
||||
<Text fontWeight="semibold" fontSize="sm" mb={1}>
|
||||
{t('ui.launchpad.upscaling.scale')}
|
||||
</Text>
|
||||
<Box className="launchpad-hide-label">
|
||||
<UpscaleScaleSlider />
|
||||
</Box>
|
||||
</Box>
|
||||
</Flex>
|
||||
{/* Left Column: Creativity and Structural Defaults */}
|
||||
<Box>
|
||||
<Text fontWeight="semibold" fontSize="sm" mb={3}>
|
||||
Creativity & Structural Defaults
|
||||
</Text>
|
||||
<Flex flexDir="column" gap={2}>
|
||||
<Button
|
||||
size="sm"
|
||||
variant={creativity === -5 && structure === 5 ? "solid" : "outline"}
|
||||
colorScheme="base"
|
||||
justifyContent="center"
|
||||
onClick={onConservativeClick}
|
||||
leftIcon={<PiShieldCheckBold />}
|
||||
>
|
||||
Conservative
|
||||
</Button>
|
||||
<Button
|
||||
size="sm"
|
||||
variant={creativity === 0 && structure === 0 ? "solid" : "outline"}
|
||||
colorScheme="base"
|
||||
justifyContent="center"
|
||||
onClick={onBalancedClick}
|
||||
leftIcon={<PiScalesBold />}
|
||||
>
|
||||
Balanced
|
||||
</Button>
|
||||
<Button
|
||||
size="sm"
|
||||
variant={creativity === 5 && structure === -2 ? "solid" : "outline"}
|
||||
colorScheme="base"
|
||||
justifyContent="center"
|
||||
onClick={onCreativeClick}
|
||||
leftIcon={<PiPaletteBold />}
|
||||
>
|
||||
Creative
|
||||
</Button>
|
||||
<Button
|
||||
size="sm"
|
||||
variant={creativity === 8 && structure === -5 ? "solid" : "outline"}
|
||||
colorScheme="base"
|
||||
justifyContent="center"
|
||||
onClick={onArtisticClick}
|
||||
leftIcon={<PiSparkleBold />}
|
||||
>
|
||||
Artistic
|
||||
</Button>
|
||||
</Flex>
|
||||
</Box>
|
||||
{/* Right Column: Description/help text */}
|
||||
<Box>
|
||||
<Text variant="subtext" fontSize="sm" lineHeight="1.6">
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { Flex, Heading, Icon, Link, Text } from '@invoke-ai/ui-library';
|
||||
import { Button, Flex, Heading, Icon, Text } from '@invoke-ai/ui-library';
|
||||
import { useWorkflowLibraryModal } from 'features/nodes/store/workflowLibraryModal';
|
||||
import { useNewWorkflow } from 'features/workflowLibrary/components/NewWorkflowConfirmationAlertDialog';
|
||||
import { useLoadWorkflowFromFile } from 'features/workflowLibrary/hooks/useLoadWorkflowFromFile';
|
||||
@@ -53,14 +53,18 @@ export const WorkflowsLaunchpadPanel = memo(() => {
|
||||
{t('ui.launchpad.workflows.description')}
|
||||
</Text>
|
||||
|
||||
<Link
|
||||
href="https://support.invoke.ai/support/solutions/articles/151000189610-getting-started-with-workflows-denoise-latents"
|
||||
isExternal
|
||||
color="invokeBlue.400"
|
||||
fontSize="sm"
|
||||
>
|
||||
{t('ui.launchpad.workflows.learnMoreLink')}
|
||||
</Link>
|
||||
<Text>
|
||||
<Button
|
||||
as="a"
|
||||
variant="link"
|
||||
href="https://support.invoke.ai/support/solutions/articles/151000189610-getting-started-with-workflows-denoise-latents"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
size="sm"
|
||||
>
|
||||
{t('ui.launchpad.workflows.learnMoreLink')}
|
||||
</Button>
|
||||
</Text>
|
||||
|
||||
{/* Action Buttons */}
|
||||
<Flex flexDir="column" gap={8}>
|
||||
|
||||
@@ -1,11 +1,13 @@
|
||||
import { Button, Flex, Image, Link, Text } from '@invoke-ai/ui-library';
|
||||
import { Flex, Heading, Icon, Image, Link, Text } from '@invoke-ai/ui-library';
|
||||
import { useAppDispatch } from 'app/store/storeHooks';
|
||||
import { LaunchpadButton } from 'features/controlLayers/components/SimpleSession/LaunchpadButton';
|
||||
import { useIsWorkflowUntouched } from 'features/nodes/components/sidePanel/workflow/IsolatedWorkflowBuilderWatcher';
|
||||
import { useWorkflowLibraryModal } from 'features/nodes/store/workflowLibraryModal';
|
||||
import { workflowModeChanged } from 'features/nodes/store/workflowLibrarySlice';
|
||||
import InvokeLogoSVG from 'public/assets/images/invoke-symbol-wht-lrg.svg';
|
||||
import { useCallback } from 'react';
|
||||
import { Trans, useTranslation } from 'react-i18next';
|
||||
import { PiFolderOpenBold, PiPlusBold } from 'react-icons/pi';
|
||||
|
||||
export const EmptyState = () => {
|
||||
const isWorkflowUntouched = useIsWorkflowUntouched();
|
||||
@@ -18,8 +20,9 @@ export const EmptyState = () => {
|
||||
borderRadius="base"
|
||||
flexDir="column"
|
||||
gap={5}
|
||||
maxW="230px"
|
||||
maxW="400px"
|
||||
pt={24}
|
||||
px={4}
|
||||
>
|
||||
<Image
|
||||
src={InvokeLogoSVG}
|
||||
@@ -49,15 +52,27 @@ const CleanEditorContent = () => {
|
||||
|
||||
return (
|
||||
<>
|
||||
<Flex gap={2}>
|
||||
<Button size="sm" onClick={onClickNewWorkflow}>
|
||||
{t('nodes.newWorkflow')}
|
||||
</Button>
|
||||
<Button size="sm" colorScheme="invokeBlue" onClick={workflowLibraryModal.open}>
|
||||
{t('nodes.loadWorkflow')}
|
||||
</Button>
|
||||
<Flex flexDir="column" gap={4} w="full">
|
||||
<LaunchpadButton onClick={onClickNewWorkflow} gap={4}>
|
||||
<Icon as={PiPlusBold} boxSize={6} color="base.500" />
|
||||
<Flex flexDir="column" alignItems="flex-start" gap={1}>
|
||||
<Heading size="sm">{t('nodes.newWorkflow')}</Heading>
|
||||
<Text color="base.300" fontSize="sm">
|
||||
Create a new workflow from scratch
|
||||
</Text>
|
||||
</Flex>
|
||||
</LaunchpadButton>
|
||||
<LaunchpadButton onClick={workflowLibraryModal.open} gap={4}>
|
||||
<Icon as={PiFolderOpenBold} boxSize={6} color="base.500" />
|
||||
<Flex flexDir="column" alignItems="flex-start" gap={1}>
|
||||
<Heading size="sm">{t('nodes.loadWorkflow')}</Heading>
|
||||
<Text color="base.300" fontSize="sm">
|
||||
Browse and load existing workflows
|
||||
</Text>
|
||||
</Flex>
|
||||
</LaunchpadButton>
|
||||
</Flex>
|
||||
<Text textAlign="center" fontSize="md">
|
||||
<Text textAlign="center" fontSize="sm" color="base.400" mt={4}>
|
||||
<Trans i18nKey="nodes.workflowHelpText" size="sm" components={workflowHelpTextComponents} />
|
||||
</Text>
|
||||
</>
|
||||
@@ -74,12 +89,20 @@ const DirtyEditorContent = () => {
|
||||
|
||||
return (
|
||||
<>
|
||||
<Text textAlign="center" fontSize="md">
|
||||
<Text textAlign="center" fontSize="md" mb={4}>
|
||||
{t('nodes.noFieldsViewMode')}
|
||||
</Text>
|
||||
<Button size="sm" colorScheme="invokeBlue" onClick={onClick}>
|
||||
{t('nodes.edit')}
|
||||
</Button>
|
||||
<Flex flexDir="column" gap={4} w="full">
|
||||
<LaunchpadButton onClick={onClick} gap={4}>
|
||||
<Icon as={PiPlusBold} boxSize={6} color="base.500" />
|
||||
<Flex flexDir="column" alignItems="flex-start" gap={1}>
|
||||
<Heading size="sm">{t('nodes.edit')}</Heading>
|
||||
<Text color="base.300" fontSize="sm">
|
||||
Switch to edit mode to build workflows
|
||||
</Text>
|
||||
</Flex>
|
||||
</LaunchpadButton>
|
||||
</Flex>
|
||||
</>
|
||||
);
|
||||
};
|
||||
@@ -93,4 +116,4 @@ const workflowHelpTextComponents = {
|
||||
target="_blank"
|
||||
/>
|
||||
),
|
||||
};
|
||||
};
|
||||
Reference in New Issue
Block a user