Skip to content

Commit e09cf64

Browse files
feat: more updates to first run view
1 parent fc8cf22 commit e09cf64

File tree

2 files changed

+132
-95
lines changed

2 files changed

+132
-95
lines changed

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

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2133,10 +2133,8 @@
21332133
"toGetStartedLocal": "To get started, make sure to download or import models needed to run Invoke. Then, enter a prompt in the box and click <StrongComponent>Invoke</StrongComponent> to generate your first image. Select a prompt template to improve results. You can choose to save your images directly to the <StrongComponent>Gallery</StrongComponent> or edit them to the <StrongComponent>Canvas</StrongComponent>.",
21342134
"toGetStarted": "To get started, enter a prompt in the box and click <StrongComponent>Invoke</StrongComponent> to generate your first image. Select a prompt template to improve results. You can choose to save your images directly to the <StrongComponent>Gallery</StrongComponent> or edit them to the <StrongComponent>Canvas</StrongComponent>.",
21352135
"gettingStartedSeries": "Want more guidance? Check out our <LinkComponent>Getting Started Series</LinkComponent> for tips on unlocking the full potential of the Invoke Studio.",
2136-
"lowVRAMMode": "For best performance, follow the <LinkComponent>Low VRAM mode guide</LinkComponent>.",
2137-
"downloadStarterModels": "Download Starter Models",
2138-
"importModels": "Import Models",
2139-
"noModelsInstalled": "It looks like you don't have any models installed"
2136+
"lowVRAMMode": "For best performance, follow our <LinkComponent>Low VRAM mode guide</LinkComponent>.",
2137+
"noModelsInstalled": "It looks like you don't have any models installed! You can <DownloadStarterModelsButton>download a starter model bundle</DownloadStarterModelsButton> or <ImportModelsButton>import models</ImportModelsButton>."
21402138
},
21412139
"whatsNew": {
21422140
"whatsNewInInvoke": "What's New in Invoke",
Lines changed: 130 additions & 91 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,15 @@
1-
import { Button, Divider, Flex, Icon, Link, Spinner, Text } from '@invoke-ai/ui-library';
1+
import {
2+
Alert,
3+
AlertDescription,
4+
AlertIcon,
5+
Button,
6+
Divider,
7+
Flex,
8+
Icon,
9+
Link,
10+
Spinner,
11+
Text,
12+
} from '@invoke-ai/ui-library';
213
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
314
import { IAINoContentFallback } from 'common/components/IAIImageFallback';
415
import { InvokeLogoIcon } from 'common/components/InvokeLogoIcon';
@@ -13,47 +24,23 @@ import { Trans, useTranslation } from 'react-i18next';
1324
import { PiArrowSquareOutBold, PiImageBold } from 'react-icons/pi';
1425
import { useMainModels } from 'services/api/hooks/modelsByType';
1526

16-
const ExternalLink = (props: PropsWithChildren<{ href: string }>) => {
17-
return (
18-
<Link isExternal display="inline-flex" alignItems="center" href={props.href} color="base.50">
19-
{props.children}
20-
<Icon display="inline" verticalAlign="middle" marginInlineStart={2} as={PiArrowSquareOutBold} />
21-
</Link>
22-
);
23-
};
24-
2527
export const NoContentForViewer = memo(() => {
2628
const hasImages = useHasImages();
2729
const [mainModels, { data }] = useMainModels();
2830
const isLocal = useAppSelector(selectIsLocal);
2931
const isEnabled = useFeatureStatus('starterModels');
3032
const { t } = useTranslation();
31-
const dispatch = useAppDispatch();
32-
33-
const handleClickDownloadStarterModels = useCallback(() => {
34-
dispatch(setActiveTab('models'));
35-
$installModelsTab.set(3);
36-
}, [dispatch]);
37-
38-
const handleClickImportModels = useCallback(() => {
39-
dispatch(setActiveTab('models'));
40-
$installModelsTab.set(0);
41-
}, [dispatch]);
4233

4334
const showStarterBundles = useMemo(() => {
4435
return isEnabled && data && mainModels.length === 0;
4536
}, [mainModels.length, data, isEnabled]);
4637

4738
if (hasImages === LOADING_SYMBOL) {
48-
return (
49-
// Blank bg w/ a spinner. The new user experience components below have an invoke logo, but it's not centered.
50-
// If we show the logo while loading, there is an awkward layout shift where the invoke logo moves a bit. Less
51-
// jarring to show a blank bg with a spinner - it will only be shown for a moment as we do the initial images
52-
// fetching.
53-
<Flex position="relative" width="full" height="full" alignItems="center" justifyContent="center">
54-
<Spinner label="Loading" color="grey" position="absolute" size="sm" width={8} height={8} right={4} bottom={4} />
55-
</Flex>
56-
);
39+
// Blank bg w/ a spinner. The new user experience components below have an invoke logo, but it's not centered.
40+
// If we show the logo while loading, there is an awkward layout shift where the invoke logo moves a bit. Less
41+
// jarring to show a blank bg with a spinner - it will only be shown for a moment as we do the initial images
42+
// fetching.
43+
return <LoadingSpinner />;
5744
}
5845

5946
if (hasImages) {
@@ -63,71 +50,123 @@ export const NoContentForViewer = memo(() => {
6350
return (
6451
<Flex flexDir="column" gap={8} alignItems="center" textAlign="center" maxW="600px">
6552
<InvokeLogoIcon w={32} h={32} />
66-
<Flex flexDir="column" gap={8} alignItems="center" textAlign="center">
67-
{isLocal ? (
68-
<>
69-
<Text fontSize="md" color="base.200">
70-
<Trans
71-
i18nKey="newUserExperience.toGetStartedLocal"
72-
components={{
73-
StrongComponent: <Text as="span" color="white" fontSize="md" fontWeight="semibold" />,
74-
}}
75-
/>
76-
</Text>
77-
<Text fontSize="md" color="base.200">
78-
<Trans
79-
i18nKey="newUserExperience.lowVRAMMode"
80-
components={{
81-
LinkComponent: <ExternalLink href="https://invoke-ai.github.io/InvokeAI/features/low-vram/" />,
82-
}}
83-
/>
84-
</Text>
85-
</>
86-
) : (
87-
<Text fontSize="md" color="base.200">
88-
<Trans
89-
i18nKey="newUserExperience.toGetStarted"
90-
components={{
91-
StrongComponent: <Text as="span" color="white" fontSize="md" fontWeight="semibold" />,
92-
}}
93-
/>
94-
</Text>
95-
)}
96-
97-
{showStarterBundles && (
98-
<Flex flexDir="column" gap={2} alignItems="center">
99-
<Text fontSize="md" color="base.200">
100-
{t('newUserExperience.noModelsInstalled')}
101-
</Text>
102-
<Flex gap={3} alignItems="center">
103-
<Button size="sm" onClick={handleClickDownloadStarterModels}>
104-
{t('newUserExperience.downloadStarterModels')}
105-
</Button>
106-
<Text fontSize="sm" color="base.200">
107-
{t('common.or')}
108-
</Text>
109-
<Button size="sm" onClick={handleClickImportModels}>
110-
{t('newUserExperience.importModels')}
111-
</Button>
112-
</Flex>
113-
</Flex>
114-
)}
115-
53+
<Flex flexDir="column" gap={4} alignItems="center" textAlign="center">
54+
{isLocal ? <GetStartedLocal /> : <GetStartedCommercial />}
55+
{showStarterBundles && <StarterBundlesCallout />}
11656
<Divider />
117-
118-
<Text fontSize="md" color="base.200">
119-
<Trans
120-
i18nKey="newUserExperience.gettingStartedSeries"
121-
components={{
122-
LinkComponent: (
123-
<ExternalLink href="https://www.youtube.com/playlist?list=PLvWK1Kc8iXGrQy8r9TYg6QdUuJ5MMx-ZO" />
124-
),
125-
}}
126-
/>
127-
</Text>
57+
<GettingStartedVideosCallout />
58+
{isLocal && <LowVRAMAlert />}
12859
</Flex>
12960
</Flex>
13061
);
13162
});
13263

13364
NoContentForViewer.displayName = 'NoContentForViewer';
65+
66+
const LoadingSpinner = () => {
67+
return (
68+
<Flex position="relative" width="full" height="full" alignItems="center" justifyContent="center">
69+
<Spinner label="Loading" color="grey" position="absolute" size="sm" width={8} height={8} right={4} bottom={4} />
70+
</Flex>
71+
);
72+
};
73+
74+
const ExternalLink = (props: PropsWithChildren<{ href: string }>) => {
75+
return (
76+
<Button
77+
as={Link}
78+
variant="link"
79+
isExternal
80+
display="inline-flex"
81+
alignItems="center"
82+
href={props.href}
83+
color="base.50"
84+
>
85+
{props.children}
86+
<Icon display="inline" verticalAlign="middle" marginInlineStart={2} as={PiArrowSquareOutBold} />
87+
</Button>
88+
);
89+
};
90+
91+
const InlineButton = (props: PropsWithChildren<{ onClick: () => void }>) => {
92+
return (
93+
<Button variant="link" size="md" onClick={props.onClick} color="base.50">
94+
{props.children}
95+
</Button>
96+
);
97+
};
98+
99+
const StrongComponent = <Text as="span" color="base.50" fontSize="md" />;
100+
101+
const GetStartedLocal = () => {
102+
return (
103+
<Text fontSize="md" color="base.200">
104+
<Trans i18nKey="newUserExperience.toGetStartedLocal" components={{ StrongComponent }} />
105+
</Text>
106+
);
107+
};
108+
109+
const GetStartedCommercial = () => {
110+
return (
111+
<Text fontSize="md" color="base.200">
112+
<Trans i18nKey="newUserExperience.toGetStarted" components={{ StrongComponent }} />
113+
</Text>
114+
);
115+
};
116+
117+
const GettingStartedVideosCallout = () => {
118+
return (
119+
<Text fontSize="md" color="base.200">
120+
<Trans
121+
i18nKey="newUserExperience.gettingStartedSeries"
122+
components={{
123+
LinkComponent: (
124+
<ExternalLink href="https://www.youtube.com/playlist?list=PLvWK1Kc8iXGrQy8r9TYg6QdUuJ5MMx-ZO" />
125+
),
126+
}}
127+
/>
128+
</Text>
129+
);
130+
};
131+
132+
const StarterBundlesCallout = () => {
133+
const dispatch = useAppDispatch();
134+
135+
const handleClickDownloadStarterModels = useCallback(() => {
136+
dispatch(setActiveTab('models'));
137+
$installModelsTab.set(3);
138+
}, [dispatch]);
139+
140+
const handleClickImportModels = useCallback(() => {
141+
dispatch(setActiveTab('models'));
142+
$installModelsTab.set(0);
143+
}, [dispatch]);
144+
145+
return (
146+
<Text fontSize="md" color="base.200">
147+
<Trans
148+
i18nKey="newUserExperience.noModelsInstalled"
149+
components={{
150+
DownloadStarterModelsButton: <InlineButton onClick={handleClickDownloadStarterModels} />,
151+
ImportModelsButton: <InlineButton onClick={handleClickImportModels} />,
152+
}}
153+
/>
154+
</Text>
155+
);
156+
};
157+
158+
const LowVRAMAlert = () => {
159+
return (
160+
<Alert status="warning" borderRadius="base" fontSize="md" shadow="md" w="fit-content">
161+
<AlertIcon />
162+
<AlertDescription>
163+
<Trans
164+
i18nKey="newUserExperience.lowVRAMMode"
165+
components={{
166+
LinkComponent: <ExternalLink href="https://invoke-ai.github.io/InvokeAI/features/low-vram/" />,
167+
}}
168+
/>
169+
</AlertDescription>
170+
</Alert>
171+
);
172+
};

0 commit comments

Comments
 (0)