feat: more updates to first run view

This commit is contained in:
psychedelicious
2025-01-09 08:33:00 +11:00
parent fc8cf224ca
commit e09cf64779
2 changed files with 139 additions and 102 deletions

View File

@@ -2133,10 +2133,8 @@
"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>.",
"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>.",
"gettingStartedSeries": "Want more guidance? Check out our <LinkComponent>Getting Started Series</LinkComponent> for tips on unlocking the full potential of the Invoke Studio.",
"lowVRAMMode": "For best performance, follow the <LinkComponent>Low VRAM mode guide</LinkComponent>.",
"downloadStarterModels": "Download Starter Models",
"importModels": "Import Models",
"noModelsInstalled": "It looks like you don't have any models installed"
"lowVRAMMode": "For best performance, follow our <LinkComponent>Low VRAM mode guide</LinkComponent>.",
"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>."
},
"whatsNew": {
"whatsNewInInvoke": "What's New in Invoke",

View File

@@ -1,4 +1,15 @@
import { Button, Divider, Flex, Icon, Link, Spinner, Text } from '@invoke-ai/ui-library';
import {
Alert,
AlertDescription,
AlertIcon,
Button,
Divider,
Flex,
Icon,
Link,
Spinner,
Text,
} from '@invoke-ai/ui-library';
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
import { IAINoContentFallback } from 'common/components/IAIImageFallback';
import { InvokeLogoIcon } from 'common/components/InvokeLogoIcon';
@@ -13,21 +24,112 @@ import { Trans, useTranslation } from 'react-i18next';
import { PiArrowSquareOutBold, PiImageBold } from 'react-icons/pi';
import { useMainModels } from 'services/api/hooks/modelsByType';
const ExternalLink = (props: PropsWithChildren<{ href: string }>) => {
return (
<Link isExternal display="inline-flex" alignItems="center" href={props.href} color="base.50">
{props.children}
<Icon display="inline" verticalAlign="middle" marginInlineStart={2} as={PiArrowSquareOutBold} />
</Link>
);
};
export const NoContentForViewer = memo(() => {
const hasImages = useHasImages();
const [mainModels, { data }] = useMainModels();
const isLocal = useAppSelector(selectIsLocal);
const isEnabled = useFeatureStatus('starterModels');
const { t } = useTranslation();
const showStarterBundles = useMemo(() => {
return isEnabled && data && mainModels.length === 0;
}, [mainModels.length, data, isEnabled]);
if (hasImages === LOADING_SYMBOL) {
// Blank bg w/ a spinner. The new user experience components below have an invoke logo, but it's not centered.
// If we show the logo while loading, there is an awkward layout shift where the invoke logo moves a bit. Less
// jarring to show a blank bg with a spinner - it will only be shown for a moment as we do the initial images
// fetching.
return <LoadingSpinner />;
}
if (hasImages) {
return <IAINoContentFallback icon={PiImageBold} label={t('gallery.noImageSelected')} />;
}
return (
<Flex flexDir="column" gap={8} alignItems="center" textAlign="center" maxW="600px">
<InvokeLogoIcon w={32} h={32} />
<Flex flexDir="column" gap={4} alignItems="center" textAlign="center">
{isLocal ? <GetStartedLocal /> : <GetStartedCommercial />}
{showStarterBundles && <StarterBundlesCallout />}
<Divider />
<GettingStartedVideosCallout />
{isLocal && <LowVRAMAlert />}
</Flex>
</Flex>
);
});
NoContentForViewer.displayName = 'NoContentForViewer';
const LoadingSpinner = () => {
return (
<Flex position="relative" width="full" height="full" alignItems="center" justifyContent="center">
<Spinner label="Loading" color="grey" position="absolute" size="sm" width={8} height={8} right={4} bottom={4} />
</Flex>
);
};
const ExternalLink = (props: PropsWithChildren<{ href: string }>) => {
return (
<Button
as={Link}
variant="link"
isExternal
display="inline-flex"
alignItems="center"
href={props.href}
color="base.50"
>
{props.children}
<Icon display="inline" verticalAlign="middle" marginInlineStart={2} as={PiArrowSquareOutBold} />
</Button>
);
};
const InlineButton = (props: PropsWithChildren<{ onClick: () => void }>) => {
return (
<Button variant="link" size="md" onClick={props.onClick} color="base.50">
{props.children}
</Button>
);
};
const StrongComponent = <Text as="span" color="base.50" fontSize="md" />;
const GetStartedLocal = () => {
return (
<Text fontSize="md" color="base.200">
<Trans i18nKey="newUserExperience.toGetStartedLocal" components={{ StrongComponent }} />
</Text>
);
};
const GetStartedCommercial = () => {
return (
<Text fontSize="md" color="base.200">
<Trans i18nKey="newUserExperience.toGetStarted" components={{ StrongComponent }} />
</Text>
);
};
const GettingStartedVideosCallout = () => {
return (
<Text fontSize="md" color="base.200">
<Trans
i18nKey="newUserExperience.gettingStartedSeries"
components={{
LinkComponent: (
<ExternalLink href="https://www.youtube.com/playlist?list=PLvWK1Kc8iXGrQy8r9TYg6QdUuJ5MMx-ZO" />
),
}}
/>
</Text>
);
};
const StarterBundlesCallout = () => {
const dispatch = useAppDispatch();
const handleClickDownloadStarterModels = useCallback(() => {
@@ -40,94 +142,31 @@ export const NoContentForViewer = memo(() => {
$installModelsTab.set(0);
}, [dispatch]);
const showStarterBundles = useMemo(() => {
return isEnabled && data && mainModels.length === 0;
}, [mainModels.length, data, isEnabled]);
if (hasImages === LOADING_SYMBOL) {
return (
// Blank bg w/ a spinner. The new user experience components below have an invoke logo, but it's not centered.
// If we show the logo while loading, there is an awkward layout shift where the invoke logo moves a bit. Less
// jarring to show a blank bg with a spinner - it will only be shown for a moment as we do the initial images
// fetching.
<Flex position="relative" width="full" height="full" alignItems="center" justifyContent="center">
<Spinner label="Loading" color="grey" position="absolute" size="sm" width={8} height={8} right={4} bottom={4} />
</Flex>
);
}
if (hasImages) {
return <IAINoContentFallback icon={PiImageBold} label={t('gallery.noImageSelected')} />;
}
return (
<Flex flexDir="column" gap={8} alignItems="center" textAlign="center" maxW="600px">
<InvokeLogoIcon w={32} h={32} />
<Flex flexDir="column" gap={8} alignItems="center" textAlign="center">
{isLocal ? (
<>
<Text fontSize="md" color="base.200">
<Trans
i18nKey="newUserExperience.toGetStartedLocal"
components={{
StrongComponent: <Text as="span" color="white" fontSize="md" fontWeight="semibold" />,
}}
/>
</Text>
<Text fontSize="md" color="base.200">
<Trans
i18nKey="newUserExperience.lowVRAMMode"
components={{
LinkComponent: <ExternalLink href="https://invoke-ai.github.io/InvokeAI/features/low-vram/" />,
}}
/>
</Text>
</>
) : (
<Text fontSize="md" color="base.200">
<Trans
i18nKey="newUserExperience.toGetStarted"
components={{
StrongComponent: <Text as="span" color="white" fontSize="md" fontWeight="semibold" />,
}}
/>
</Text>
)}
{showStarterBundles && (
<Flex flexDir="column" gap={2} alignItems="center">
<Text fontSize="md" color="base.200">
{t('newUserExperience.noModelsInstalled')}
</Text>
<Flex gap={3} alignItems="center">
<Button size="sm" onClick={handleClickDownloadStarterModels}>
{t('newUserExperience.downloadStarterModels')}
</Button>
<Text fontSize="sm" color="base.200">
{t('common.or')}
</Text>
<Button size="sm" onClick={handleClickImportModels}>
{t('newUserExperience.importModels')}
</Button>
</Flex>
</Flex>
)}
<Divider />
<Text fontSize="md" color="base.200">
<Trans
i18nKey="newUserExperience.gettingStartedSeries"
components={{
LinkComponent: (
<ExternalLink href="https://www.youtube.com/playlist?list=PLvWK1Kc8iXGrQy8r9TYg6QdUuJ5MMx-ZO" />
),
}}
/>
</Text>
</Flex>
</Flex>
<Text fontSize="md" color="base.200">
<Trans
i18nKey="newUserExperience.noModelsInstalled"
components={{
DownloadStarterModelsButton: <InlineButton onClick={handleClickDownloadStarterModels} />,
ImportModelsButton: <InlineButton onClick={handleClickImportModels} />,
}}
/>
</Text>
);
});
};
NoContentForViewer.displayName = 'NoContentForViewer';
const LowVRAMAlert = () => {
return (
<Alert status="warning" borderRadius="base" fontSize="md" shadow="md" w="fit-content">
<AlertIcon />
<AlertDescription>
<Trans
i18nKey="newUserExperience.lowVRAMMode"
components={{
LinkComponent: <ExternalLink href="https://invoke-ai.github.io/InvokeAI/features/low-vram/" />,
}}
/>
</AlertDescription>
</Alert>
);
};