File size: 4,621 Bytes
8a37e0a
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
import { Button, Divider, Flex, 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';
import { LOADING_SYMBOL, useHasImages } from 'features/gallery/hooks/useHasImages';
import { $installModelsTab } from 'features/modelManagerV2/subpanels/InstallModels';
import { useFeatureStatus } from 'features/system/hooks/useFeatureStatus';
import { selectIsLocal } from 'features/system/store/configSlice';
import { setActiveTab } from 'features/ui/store/uiSlice';
import { memo, useCallback, useMemo } from 'react';
import { Trans, useTranslation } from 'react-i18next';
import { PiImageBold } from 'react-icons/pi';
import { useMainModels } from 'services/api/hooks/modelsByType';

export const NoContentForViewer = memo(() => {
  const hasImages = useHasImages();
  const [mainModels, { data }] = useMainModels();
  const isLocal = useAppSelector(selectIsLocal);
  const isEnabled = useFeatureStatus('starterModels');
  const { t } = useTranslation();
  const dispatch = useAppDispatch();

  const handleClickDownloadStarterModels = useCallback(() => {
    dispatch(setActiveTab('models'));
    $installModelsTab.set(3);
  }, [dispatch]);

  const handleClickImportModels = useCallback(() => {
    dispatch(setActiveTab('models'));
    $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={4} alignItems="center" textAlign="center" maxW="600px">
      <InvokeLogoIcon w={40} h={40} />
      <Flex flexDir="column" gap={8} alignItems="center" textAlign="center">
        <Text fontSize="md" color="base.200" pt={16}>
          {isLocal ? (
            <Trans
              i18nKey="newUserExperience.toGetStartedLocal"
              components={{
                StrongComponent: <Text as="span" color="white" fontSize="md" fontWeight="semibold" />,
              }}
            />
          ) : (
            <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: (
                <Text
                  as="a"
                  color="white"
                  fontSize="md"
                  fontWeight="semibold"
                  href="https://www.youtube.com/playlist?list=PLvWK1Kc8iXGrQy8r9TYg6QdUuJ5MMx-ZO"
                  target="_blank"
                />
              ),
            }}
          />
        </Text>
      </Flex>
    </Flex>
  );
});

NoContentForViewer.displayName = 'NoContentForViewer';