Skip to content

Commit 8b8e29d

Browse files
hipsterusernamepsychedelicious
authored andcommitted
Fixes & Styling updates
1 parent 90201be commit 8b8e29d

File tree

5 files changed

+137
-84
lines changed

5 files changed

+137
-84
lines changed

invokeai/frontend/web/public/locales/en.json

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2471,6 +2471,10 @@
24712471
"title": "Upload Image to Upscale",
24722472
"description": "Click or drag an image to upscale (JPG, PNG, WebP up to 100MB)"
24732473
},
2474+
"replaceImage": {
2475+
"title": "Replace Current Image",
2476+
"description": "Click or drag a new image to replace the current one"
2477+
},
24742478
"imageReady": {
24752479
"title": "Image Ready",
24762480
"description": "Press Invoke to begin upscaling"

invokeai/frontend/web/src/features/controlLayers/components/SimpleSession/LaunchpadButton.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ export const LaunchpadButton = memo(
1111
display="flex"
1212
position="relative"
1313
alignItems="center"
14+
justifyContent="left"
1415
borderWidth={1}
1516
borderRadius="base"
1617
p={4}

invokeai/frontend/web/src/features/controlLayers/components/SimpleSession/UpscalingLaunchpadPanel.tsx

Lines changed: 81 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,14 @@
1-
import { Box, Flex, Grid, Heading, Icon, Text } from '@invoke-ai/ui-library';
1+
import { Box, Button, Flex, Grid, Heading, Icon, Text } from '@invoke-ai/ui-library';
22
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
33
import { useImageUploadButton } from 'common/hooks/useImageUploadButton';
44
import { setUpscaleInitialImageDndTarget } from 'features/dnd/dnd';
55
import { DndDropTarget } from 'features/dnd/DndDropTarget';
66
import { DndImage } from 'features/dnd/DndImage';
77
import { DndImageIcon } from 'features/dnd/DndImageIcon';
8-
import ParamSpandrelModel from 'features/parameters/components/Upscale/ParamSpandrelModel';
9-
import { selectUpscaleInitialImage, upscaleInitialImageChanged } from 'features/parameters/store/upscaleSlice';
10-
import { MainModelPicker } from 'features/settingsAccordions/components/GenerationSettingsAccordion/MainModelPicker';
11-
import { UpscaleScaleSlider } from 'features/settingsAccordions/components/UpscaleSettingsAccordion/UpscaleScaleSlider';
8+
import { selectUpscaleInitialImage, upscaleInitialImageChanged, creativityChanged, structureChanged, selectCreativity, selectStructure } from 'features/parameters/store/upscaleSlice';
129
import { memo, useCallback, useMemo } from 'react';
1310
import { useTranslation } from 'react-i18next';
14-
import { PiArrowCounterClockwiseBold, PiImageBold, PiUploadBold } from 'react-icons/pi';
11+
import { PiArrowCounterClockwiseBold, PiImageBold, PiUploadBold, PiShieldCheckBold, PiScalesBold, PiPaletteBold, PiSparkleBold } from 'react-icons/pi';
1512
import type { ImageDTO } from 'services/api/types';
1613

1714
import { LaunchpadButton } from './LaunchpadButton';
@@ -20,6 +17,8 @@ export const UpscalingLaunchpadPanel = memo(() => {
2017
const { t } = useTranslation();
2118
const dispatch = useAppDispatch();
2219
const upscaleInitialImage = useAppSelector(selectUpscaleInitialImage);
20+
const creativity = useAppSelector(selectCreativity);
21+
const structure = useAppSelector(selectStructure);
2322

2423
const dndTargetData = useMemo(() => setUpscaleInitialImageDndTarget.getData(), []);
2524

@@ -36,6 +35,27 @@ export const UpscalingLaunchpadPanel = memo(() => {
3635

3736
const uploadApi = useImageUploadButton({ allowMultiple: false, onUpload });
3837

38+
// Preset button handlers
39+
const onConservativeClick = useCallback(() => {
40+
dispatch(creativityChanged(-5));
41+
dispatch(structureChanged(5));
42+
}, [dispatch]);
43+
44+
const onBalancedClick = useCallback(() => {
45+
dispatch(creativityChanged(0));
46+
dispatch(structureChanged(0));
47+
}, [dispatch]);
48+
49+
const onCreativeClick = useCallback(() => {
50+
dispatch(creativityChanged(5));
51+
dispatch(structureChanged(-2));
52+
}, [dispatch]);
53+
54+
const onArtisticClick = useCallback(() => {
55+
dispatch(creativityChanged(8));
56+
dispatch(structureChanged(-5));
57+
}, [dispatch]);
58+
3959
return (
4060
<Flex flexDir="column" h="full" w="full" alignItems="center" gap={2}>
4161
<Flex flexDir="column" w="full" gap={4} px={14} maxW={768} pt="20vh">
@@ -57,34 +77,14 @@ export const UpscalingLaunchpadPanel = memo(() => {
5777
</>
5878
) : (
5979
<>
60-
<Flex position="relative" w={16} h={16} alignItems="center" justifyContent="center">
61-
<DndImage imageDTO={upscaleInitialImage} />
62-
<Flex position="absolute" flexDir="column" top={1} insetInlineEnd={1} gap={1}>
63-
<DndImageIcon
64-
onClick={onReset}
65-
icon={<PiArrowCounterClockwiseBold size={12} />}
66-
tooltip={t('common.reset')}
67-
/>
68-
</Flex>
69-
<Text
70-
position="absolute"
71-
background="base.900"
72-
color="base.50"
73-
fontSize="xs"
74-
fontWeight="semibold"
75-
bottom={0}
76-
left={0}
77-
opacity={0.7}
78-
px={1}
79-
lineHeight={1.25}
80-
borderTopEndRadius="base"
81-
borderBottomStartRadius="base"
82-
pointerEvents="none"
83-
>{`${upscaleInitialImage.width}x${upscaleInitialImage.height}`}</Text>
84-
</Flex>
80+
<Icon as={PiImageBold} boxSize={8} color="base.500" />
8581
<Flex flexDir="column" alignItems="flex-start" gap={2}>
86-
<Heading size="sm">{t('ui.launchpad.upscaling.imageReady.title')}</Heading>
87-
<Text color="base.300">{t('ui.launchpad.upscaling.imageReady.description')}</Text>
82+
<Heading size="sm">{t('ui.launchpad.upscaling.replaceImage.title')}</Heading>
83+
<Text color="base.300">{t('ui.launchpad.upscaling.replaceImage.description')}</Text>
84+
</Flex>
85+
<Flex position="absolute" right={3} bottom={3}>
86+
<PiUploadBold />
87+
<input {...uploadApi.getUploadInputProps()} />
8888
</Flex>
8989
</>
9090
)}
@@ -108,33 +108,54 @@ export const UpscalingLaunchpadPanel = memo(() => {
108108
{/* Controls */}
109109
<style>{`.launchpad-hide-label .chakra-form__label { display: none !important; }`}</style>
110110
<Grid gridTemplateColumns="1fr 1fr" gap={10} alignItems="start" mt={upscaleInitialImage ? 8 : 12}>
111-
{/* Left Column: All parameters stacked */}
112-
<Flex flexDir="column" gap={6} alignItems="flex-start">
113-
<Box w="full">
114-
<Text fontWeight="semibold" fontSize="sm" mb={1}>
115-
{t('ui.launchpad.upscaling.upscaleModel')}
116-
</Text>
117-
<Box className="launchpad-hide-label">
118-
<ParamSpandrelModel />
119-
</Box>
120-
</Box>
121-
<Box w="full">
122-
<Text fontWeight="semibold" fontSize="sm" mb={1}>
123-
{t('ui.launchpad.upscaling.model')}
124-
</Text>
125-
<Box className="launchpad-hide-label">
126-
<MainModelPicker />
127-
</Box>
128-
</Box>
129-
<Box w="full">
130-
<Text fontWeight="semibold" fontSize="sm" mb={1}>
131-
{t('ui.launchpad.upscaling.scale')}
132-
</Text>
133-
<Box className="launchpad-hide-label">
134-
<UpscaleScaleSlider />
135-
</Box>
136-
</Box>
137-
</Flex>
111+
{/* Left Column: Creativity and Structural Defaults */}
112+
<Box>
113+
<Text fontWeight="semibold" fontSize="sm" mb={3}>
114+
Creativity & Structural Defaults
115+
</Text>
116+
<Flex flexDir="column" gap={2}>
117+
<Button
118+
size="sm"
119+
variant={creativity === -5 && structure === 5 ? "solid" : "outline"}
120+
colorScheme="base"
121+
justifyContent="center"
122+
onClick={onConservativeClick}
123+
leftIcon={<PiShieldCheckBold />}
124+
>
125+
Conservative
126+
</Button>
127+
<Button
128+
size="sm"
129+
variant={creativity === 0 && structure === 0 ? "solid" : "outline"}
130+
colorScheme="base"
131+
justifyContent="center"
132+
onClick={onBalancedClick}
133+
leftIcon={<PiScalesBold />}
134+
>
135+
Balanced
136+
</Button>
137+
<Button
138+
size="sm"
139+
variant={creativity === 5 && structure === -2 ? "solid" : "outline"}
140+
colorScheme="base"
141+
justifyContent="center"
142+
onClick={onCreativeClick}
143+
leftIcon={<PiPaletteBold />}
144+
>
145+
Creative
146+
</Button>
147+
<Button
148+
size="sm"
149+
variant={creativity === 8 && structure === -5 ? "solid" : "outline"}
150+
colorScheme="base"
151+
justifyContent="center"
152+
onClick={onArtisticClick}
153+
leftIcon={<PiSparkleBold />}
154+
>
155+
Artistic
156+
</Button>
157+
</Flex>
158+
</Box>
138159
{/* Right Column: Description/help text */}
139160
<Box>
140161
<Text variant="subtext" fontSize="sm" lineHeight="1.6">

invokeai/frontend/web/src/features/controlLayers/components/SimpleSession/WorkflowsLaunchpadPanel.tsx

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { Flex, Heading, Icon, Link, Text } from '@invoke-ai/ui-library';
1+
import { Button, Flex, Heading, Icon, Text } from '@invoke-ai/ui-library';
22
import { useWorkflowLibraryModal } from 'features/nodes/store/workflowLibraryModal';
33
import { useNewWorkflow } from 'features/workflowLibrary/components/NewWorkflowConfirmationAlertDialog';
44
import { useLoadWorkflowFromFile } from 'features/workflowLibrary/hooks/useLoadWorkflowFromFile';
@@ -53,14 +53,18 @@ export const WorkflowsLaunchpadPanel = memo(() => {
5353
{t('ui.launchpad.workflows.description')}
5454
</Text>
5555

56-
<Link
57-
href="https://support.invoke.ai/support/solutions/articles/151000189610-getting-started-with-workflows-denoise-latents"
58-
isExternal
59-
color="invokeBlue.400"
60-
fontSize="sm"
61-
>
62-
{t('ui.launchpad.workflows.learnMoreLink')}
63-
</Link>
56+
<Text>
57+
<Button
58+
as="a"
59+
variant="link"
60+
href="https://support.invoke.ai/support/solutions/articles/151000189610-getting-started-with-workflows-denoise-latents"
61+
target="_blank"
62+
rel="noopener noreferrer"
63+
size="sm"
64+
>
65+
{t('ui.launchpad.workflows.learnMoreLink')}
66+
</Button>
67+
</Text>
6468

6569
{/* Action Buttons */}
6670
<Flex flexDir="column" gap={8}>

invokeai/frontend/web/src/features/nodes/components/sidePanel/viewMode/EmptyState.tsx

Lines changed: 38 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,13 @@
1-
import { Button, Flex, Image, Link, Text } from '@invoke-ai/ui-library';
1+
import { Flex, Heading, Icon, Image, Link, Text } from '@invoke-ai/ui-library';
22
import { useAppDispatch } from 'app/store/storeHooks';
3+
import { LaunchpadButton } from 'features/controlLayers/components/SimpleSession/LaunchpadButton';
34
import { useIsWorkflowUntouched } from 'features/nodes/components/sidePanel/workflow/IsolatedWorkflowBuilderWatcher';
45
import { useWorkflowLibraryModal } from 'features/nodes/store/workflowLibraryModal';
56
import { workflowModeChanged } from 'features/nodes/store/workflowLibrarySlice';
67
import InvokeLogoSVG from 'public/assets/images/invoke-symbol-wht-lrg.svg';
78
import { useCallback } from 'react';
89
import { Trans, useTranslation } from 'react-i18next';
10+
import { PiFolderOpenBold, PiPlusBold } from 'react-icons/pi';
911

1012
export const EmptyState = () => {
1113
const isWorkflowUntouched = useIsWorkflowUntouched();
@@ -18,8 +20,9 @@ export const EmptyState = () => {
1820
borderRadius="base"
1921
flexDir="column"
2022
gap={5}
21-
maxW="230px"
23+
maxW="400px"
2224
pt={24}
25+
px={4}
2326
>
2427
<Image
2528
src={InvokeLogoSVG}
@@ -49,15 +52,27 @@ const CleanEditorContent = () => {
4952

5053
return (
5154
<>
52-
<Flex gap={2}>
53-
<Button size="sm" onClick={onClickNewWorkflow}>
54-
{t('nodes.newWorkflow')}
55-
</Button>
56-
<Button size="sm" colorScheme="invokeBlue" onClick={workflowLibraryModal.open}>
57-
{t('nodes.loadWorkflow')}
58-
</Button>
55+
<Flex flexDir="column" gap={4} w="full">
56+
<LaunchpadButton onClick={onClickNewWorkflow} gap={4}>
57+
<Icon as={PiPlusBold} boxSize={6} color="base.500" />
58+
<Flex flexDir="column" alignItems="flex-start" gap={1}>
59+
<Heading size="sm">{t('nodes.newWorkflow')}</Heading>
60+
<Text color="base.300" fontSize="sm">
61+
Create a new workflow from scratch
62+
</Text>
63+
</Flex>
64+
</LaunchpadButton>
65+
<LaunchpadButton onClick={workflowLibraryModal.open} gap={4}>
66+
<Icon as={PiFolderOpenBold} boxSize={6} color="base.500" />
67+
<Flex flexDir="column" alignItems="flex-start" gap={1}>
68+
<Heading size="sm">{t('nodes.loadWorkflow')}</Heading>
69+
<Text color="base.300" fontSize="sm">
70+
Browse and load existing workflows
71+
</Text>
72+
</Flex>
73+
</LaunchpadButton>
5974
</Flex>
60-
<Text textAlign="center" fontSize="md">
75+
<Text textAlign="center" fontSize="sm" color="base.400" mt={4}>
6176
<Trans i18nKey="nodes.workflowHelpText" size="sm" components={workflowHelpTextComponents} />
6277
</Text>
6378
</>
@@ -74,12 +89,20 @@ const DirtyEditorContent = () => {
7489

7590
return (
7691
<>
77-
<Text textAlign="center" fontSize="md">
92+
<Text textAlign="center" fontSize="md" mb={4}>
7893
{t('nodes.noFieldsViewMode')}
7994
</Text>
80-
<Button size="sm" colorScheme="invokeBlue" onClick={onClick}>
81-
{t('nodes.edit')}
82-
</Button>
95+
<Flex flexDir="column" gap={4} w="full">
96+
<LaunchpadButton onClick={onClick} gap={4}>
97+
<Icon as={PiPlusBold} boxSize={6} color="base.500" />
98+
<Flex flexDir="column" alignItems="flex-start" gap={1}>
99+
<Heading size="sm">{t('nodes.edit')}</Heading>
100+
<Text color="base.300" fontSize="sm">
101+
Switch to edit mode to build workflows
102+
</Text>
103+
</Flex>
104+
</LaunchpadButton>
105+
</Flex>
83106
</>
84107
);
85108
};
@@ -93,4 +116,4 @@ const workflowHelpTextComponents = {
93116
target="_blank"
94117
/>
95118
),
96-
};
119+
};

0 commit comments

Comments
 (0)