mirror of
https://github.com/invoke-ai/InvokeAI
synced 2024-08-30 20:32:17 +00:00
fix(ui): memoize model manager components
This commit is contained in:
parent
47414be1e6
commit
f8e27b837b
@ -1,13 +1,13 @@
|
|||||||
import { Button, Flex, FormControl, FormErrorMessage, FormHelperText, FormLabel, Input } from '@invoke-ai/ui-library';
|
import { Button, Flex, FormControl, FormErrorMessage, FormHelperText, FormLabel, Input } from '@invoke-ai/ui-library';
|
||||||
import { useInstallModel } from 'features/modelManagerV2/hooks/useInstallModel';
|
import { useInstallModel } from 'features/modelManagerV2/hooks/useInstallModel';
|
||||||
import type { ChangeEventHandler } from 'react';
|
import type { ChangeEventHandler } from 'react';
|
||||||
import { useCallback, useState } from 'react';
|
import { memo, useCallback, useState } from 'react';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
import { useLazyGetHuggingFaceModelsQuery } from 'services/api/endpoints/models';
|
import { useLazyGetHuggingFaceModelsQuery } from 'services/api/endpoints/models';
|
||||||
|
|
||||||
import { HuggingFaceResults } from './HuggingFaceResults';
|
import { HuggingFaceResults } from './HuggingFaceResults';
|
||||||
|
|
||||||
export const HuggingFaceForm = () => {
|
export const HuggingFaceForm = memo(() => {
|
||||||
const [huggingFaceRepo, setHuggingFaceRepo] = useState('');
|
const [huggingFaceRepo, setHuggingFaceRepo] = useState('');
|
||||||
const [displayResults, setDisplayResults] = useState(false);
|
const [displayResults, setDisplayResults] = useState(false);
|
||||||
const [errorMessage, setErrorMessage] = useState('');
|
const [errorMessage, setErrorMessage] = useState('');
|
||||||
@ -66,4 +66,6 @@ export const HuggingFaceForm = () => {
|
|||||||
{data && data.urls && displayResults && <HuggingFaceResults results={data.urls} />}
|
{data && data.urls && displayResults && <HuggingFaceResults results={data.urls} />}
|
||||||
</Flex>
|
</Flex>
|
||||||
);
|
);
|
||||||
};
|
});
|
||||||
|
|
||||||
|
HuggingFaceForm.displayName = 'HuggingFaceForm';
|
||||||
|
@ -1,13 +1,13 @@
|
|||||||
import { Flex, IconButton, Text } from '@invoke-ai/ui-library';
|
import { Flex, IconButton, Text } from '@invoke-ai/ui-library';
|
||||||
import { useInstallModel } from 'features/modelManagerV2/hooks/useInstallModel';
|
import { useInstallModel } from 'features/modelManagerV2/hooks/useInstallModel';
|
||||||
import { useCallback } from 'react';
|
import { memo, useCallback } from 'react';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
import { PiPlusBold } from 'react-icons/pi';
|
import { PiPlusBold } from 'react-icons/pi';
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
result: string;
|
result: string;
|
||||||
};
|
};
|
||||||
export const HuggingFaceResultItem = ({ result }: Props) => {
|
export const HuggingFaceResultItem = memo(({ result }: Props) => {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
|
|
||||||
const [installModel] = useInstallModel();
|
const [installModel] = useInstallModel();
|
||||||
@ -27,4 +27,6 @@ export const HuggingFaceResultItem = ({ result }: Props) => {
|
|||||||
<IconButton aria-label={t('modelManager.install')} icon={<PiPlusBold />} onClick={onClick} size="sm" />
|
<IconButton aria-label={t('modelManager.install')} icon={<PiPlusBold />} onClick={onClick} size="sm" />
|
||||||
</Flex>
|
</Flex>
|
||||||
);
|
);
|
||||||
};
|
});
|
||||||
|
|
||||||
|
HuggingFaceResultItem.displayName = 'HuggingFaceResultItem';
|
||||||
|
@ -11,7 +11,7 @@ import {
|
|||||||
import ScrollableContent from 'common/components/OverlayScrollbars/ScrollableContent';
|
import ScrollableContent from 'common/components/OverlayScrollbars/ScrollableContent';
|
||||||
import { useInstallModel } from 'features/modelManagerV2/hooks/useInstallModel';
|
import { useInstallModel } from 'features/modelManagerV2/hooks/useInstallModel';
|
||||||
import type { ChangeEventHandler } from 'react';
|
import type { ChangeEventHandler } from 'react';
|
||||||
import { useCallback, useMemo, useState } from 'react';
|
import { memo, useCallback, useMemo, useState } from 'react';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
import { PiXBold } from 'react-icons/pi';
|
import { PiXBold } from 'react-icons/pi';
|
||||||
|
|
||||||
@ -21,7 +21,7 @@ type HuggingFaceResultsProps = {
|
|||||||
results: string[];
|
results: string[];
|
||||||
};
|
};
|
||||||
|
|
||||||
export const HuggingFaceResults = ({ results }: HuggingFaceResultsProps) => {
|
export const HuggingFaceResults = memo(({ results }: HuggingFaceResultsProps) => {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const [searchTerm, setSearchTerm] = useState('');
|
const [searchTerm, setSearchTerm] = useState('');
|
||||||
|
|
||||||
@ -93,4 +93,6 @@ export const HuggingFaceResults = ({ results }: HuggingFaceResultsProps) => {
|
|||||||
</Flex>
|
</Flex>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
};
|
});
|
||||||
|
|
||||||
|
HuggingFaceResults.displayName = 'HuggingFaceResults';
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import { Button, Checkbox, Flex, FormControl, FormHelperText, FormLabel, Input } from '@invoke-ai/ui-library';
|
import { Button, Checkbox, Flex, FormControl, FormHelperText, FormLabel, Input } from '@invoke-ai/ui-library';
|
||||||
import { useInstallModel } from 'features/modelManagerV2/hooks/useInstallModel';
|
import { useInstallModel } from 'features/modelManagerV2/hooks/useInstallModel';
|
||||||
import { t } from 'i18next';
|
import { t } from 'i18next';
|
||||||
import { useCallback } from 'react';
|
import { memo, useCallback } from 'react';
|
||||||
import type { SubmitHandler } from 'react-hook-form';
|
import type { SubmitHandler } from 'react-hook-form';
|
||||||
import { useForm } from 'react-hook-form';
|
import { useForm } from 'react-hook-form';
|
||||||
|
|
||||||
@ -10,7 +10,7 @@ type SimpleImportModelConfig = {
|
|||||||
inplace: boolean;
|
inplace: boolean;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const InstallModelForm = () => {
|
export const InstallModelForm = memo(() => {
|
||||||
const [installModel, { isLoading }] = useInstallModel();
|
const [installModel, { isLoading }] = useInstallModel();
|
||||||
|
|
||||||
const { register, handleSubmit, formState, reset } = useForm<SimpleImportModelConfig>({
|
const { register, handleSubmit, formState, reset } = useForm<SimpleImportModelConfig>({
|
||||||
@ -74,4 +74,6 @@ export const InstallModelForm = () => {
|
|||||||
</Flex>
|
</Flex>
|
||||||
</form>
|
</form>
|
||||||
);
|
);
|
||||||
};
|
});
|
||||||
|
|
||||||
|
InstallModelForm.displayName = 'InstallModelForm';
|
||||||
|
@ -2,12 +2,12 @@ import { Box, Button, Flex, Heading } from '@invoke-ai/ui-library';
|
|||||||
import ScrollableContent from 'common/components/OverlayScrollbars/ScrollableContent';
|
import ScrollableContent from 'common/components/OverlayScrollbars/ScrollableContent';
|
||||||
import { toast } from 'features/toast/toast';
|
import { toast } from 'features/toast/toast';
|
||||||
import { t } from 'i18next';
|
import { t } from 'i18next';
|
||||||
import { useCallback, useMemo } from 'react';
|
import { memo, useCallback, useMemo } from 'react';
|
||||||
import { useListModelInstallsQuery, usePruneCompletedModelInstallsMutation } from 'services/api/endpoints/models';
|
import { useListModelInstallsQuery, usePruneCompletedModelInstallsMutation } from 'services/api/endpoints/models';
|
||||||
|
|
||||||
import { ModelInstallQueueItem } from './ModelInstallQueueItem';
|
import { ModelInstallQueueItem } from './ModelInstallQueueItem';
|
||||||
|
|
||||||
export const ModelInstallQueue = () => {
|
export const ModelInstallQueue = memo(() => {
|
||||||
const { data } = useListModelInstallsQuery();
|
const { data } = useListModelInstallsQuery();
|
||||||
|
|
||||||
const [_pruneCompletedModelInstalls] = usePruneCompletedModelInstallsMutation();
|
const [_pruneCompletedModelInstalls] = usePruneCompletedModelInstallsMutation();
|
||||||
@ -61,4 +61,6 @@ export const ModelInstallQueue = () => {
|
|||||||
</Box>
|
</Box>
|
||||||
</Flex>
|
</Flex>
|
||||||
);
|
);
|
||||||
};
|
});
|
||||||
|
|
||||||
|
ModelInstallQueue.displayName = 'ModelInstallQueue';
|
||||||
|
@ -2,7 +2,7 @@ import { Flex, IconButton, Progress, Text, Tooltip } from '@invoke-ai/ui-library
|
|||||||
import { toast } from 'features/toast/toast';
|
import { toast } from 'features/toast/toast';
|
||||||
import { t } from 'i18next';
|
import { t } from 'i18next';
|
||||||
import { isNil } from 'lodash-es';
|
import { isNil } from 'lodash-es';
|
||||||
import { useCallback, useMemo } from 'react';
|
import { memo, useCallback, useMemo } from 'react';
|
||||||
import { PiXBold } from 'react-icons/pi';
|
import { PiXBold } from 'react-icons/pi';
|
||||||
import { useCancelModelInstallMutation } from 'services/api/endpoints/models';
|
import { useCancelModelInstallMutation } from 'services/api/endpoints/models';
|
||||||
import type { ModelInstallJob } from 'services/api/types';
|
import type { ModelInstallJob } from 'services/api/types';
|
||||||
@ -25,7 +25,7 @@ const formatBytes = (bytes: number) => {
|
|||||||
return `${bytes.toFixed(2)} ${units[i]}`;
|
return `${bytes.toFixed(2)} ${units[i]}`;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const ModelInstallQueueItem = (props: ModelListItemProps) => {
|
export const ModelInstallQueueItem = memo((props: ModelListItemProps) => {
|
||||||
const { installJob } = props;
|
const { installJob } = props;
|
||||||
|
|
||||||
const [deleteImportModel] = useCancelModelInstallMutation();
|
const [deleteImportModel] = useCancelModelInstallMutation();
|
||||||
@ -124,7 +124,9 @@ export const ModelInstallQueueItem = (props: ModelListItemProps) => {
|
|||||||
/>
|
/>
|
||||||
</Flex>
|
</Flex>
|
||||||
);
|
);
|
||||||
};
|
});
|
||||||
|
|
||||||
|
ModelInstallQueueItem.displayName = 'ModelInstallQueueItem';
|
||||||
|
|
||||||
type TooltipLabelProps = {
|
type TooltipLabelProps = {
|
||||||
installJob: ModelInstallJob;
|
installJob: ModelInstallJob;
|
||||||
@ -132,7 +134,7 @@ type TooltipLabelProps = {
|
|||||||
source: string;
|
source: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
const TooltipLabel = ({ name, source, installJob }: TooltipLabelProps) => {
|
const TooltipLabel = memo(({ name, source, installJob }: TooltipLabelProps) => {
|
||||||
const progressString = useMemo(() => {
|
const progressString = useMemo(() => {
|
||||||
if (installJob.status !== 'downloading' || installJob.bytes === undefined || installJob.total_bytes === undefined) {
|
if (installJob.status !== 'downloading' || installJob.bytes === undefined || installJob.total_bytes === undefined) {
|
||||||
return '';
|
return '';
|
||||||
@ -156,4 +158,6 @@ const TooltipLabel = ({ name, source, installJob }: TooltipLabelProps) => {
|
|||||||
)}
|
)}
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
};
|
});
|
||||||
|
|
||||||
|
TooltipLabel.displayName = 'TooltipLabel';
|
||||||
|
@ -2,13 +2,13 @@ import { Button, Flex, FormControl, FormErrorMessage, FormHelperText, FormLabel,
|
|||||||
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
|
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
|
||||||
import { setScanPath } from 'features/modelManagerV2/store/modelManagerV2Slice';
|
import { setScanPath } from 'features/modelManagerV2/store/modelManagerV2Slice';
|
||||||
import type { ChangeEventHandler } from 'react';
|
import type { ChangeEventHandler } from 'react';
|
||||||
import { useCallback, useState } from 'react';
|
import { memo, useCallback, useState } from 'react';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
import { useLazyScanFolderQuery } from 'services/api/endpoints/models';
|
import { useLazyScanFolderQuery } from 'services/api/endpoints/models';
|
||||||
|
|
||||||
import { ScanModelsResults } from './ScanFolderResults';
|
import { ScanModelsResults } from './ScanFolderResults';
|
||||||
|
|
||||||
export const ScanModelsForm = () => {
|
export const ScanModelsForm = memo(() => {
|
||||||
const scanPath = useAppSelector((state) => state.modelmanagerV2.scanPath);
|
const scanPath = useAppSelector((state) => state.modelmanagerV2.scanPath);
|
||||||
const dispatch = useAppDispatch();
|
const dispatch = useAppDispatch();
|
||||||
const [errorMessage, setErrorMessage] = useState('');
|
const [errorMessage, setErrorMessage] = useState('');
|
||||||
@ -56,4 +56,6 @@ export const ScanModelsForm = () => {
|
|||||||
{data && <ScanModelsResults results={data} />}
|
{data && <ScanModelsResults results={data} />}
|
||||||
</Flex>
|
</Flex>
|
||||||
);
|
);
|
||||||
};
|
});
|
||||||
|
|
||||||
|
ScanModelsForm.displayName = 'ScanModelsForm';
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import { Badge, Box, Flex, IconButton, Text } from '@invoke-ai/ui-library';
|
import { Badge, Box, Flex, IconButton, Text } from '@invoke-ai/ui-library';
|
||||||
import { useCallback } from 'react';
|
import { memo, useCallback } from 'react';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
import { PiPlusBold } from 'react-icons/pi';
|
import { PiPlusBold } from 'react-icons/pi';
|
||||||
import type { ScanFolderResponse } from 'services/api/endpoints/models';
|
import type { ScanFolderResponse } from 'services/api/endpoints/models';
|
||||||
@ -8,7 +8,7 @@ type Props = {
|
|||||||
result: ScanFolderResponse[number];
|
result: ScanFolderResponse[number];
|
||||||
installModel: (source: string) => void;
|
installModel: (source: string) => void;
|
||||||
};
|
};
|
||||||
export const ScanModelResultItem = ({ result, installModel }: Props) => {
|
export const ScanModelResultItem = memo(({ result, installModel }: Props) => {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
|
|
||||||
const handleInstall = useCallback(() => {
|
const handleInstall = useCallback(() => {
|
||||||
@ -30,4 +30,6 @@ export const ScanModelResultItem = ({ result, installModel }: Props) => {
|
|||||||
</Box>
|
</Box>
|
||||||
</Flex>
|
</Flex>
|
||||||
);
|
);
|
||||||
};
|
});
|
||||||
|
|
||||||
|
ScanModelResultItem.displayName = 'ScanModelResultItem';
|
||||||
|
@ -14,7 +14,7 @@ import {
|
|||||||
import ScrollableContent from 'common/components/OverlayScrollbars/ScrollableContent';
|
import ScrollableContent from 'common/components/OverlayScrollbars/ScrollableContent';
|
||||||
import { useInstallModel } from 'features/modelManagerV2/hooks/useInstallModel';
|
import { useInstallModel } from 'features/modelManagerV2/hooks/useInstallModel';
|
||||||
import type { ChangeEvent, ChangeEventHandler } from 'react';
|
import type { ChangeEvent, ChangeEventHandler } from 'react';
|
||||||
import { useCallback, useMemo, useState } from 'react';
|
import { memo, useCallback, useMemo, useState } from 'react';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
import { PiXBold } from 'react-icons/pi';
|
import { PiXBold } from 'react-icons/pi';
|
||||||
import type { ScanFolderResponse } from 'services/api/endpoints/models';
|
import type { ScanFolderResponse } from 'services/api/endpoints/models';
|
||||||
@ -25,7 +25,7 @@ type ScanModelResultsProps = {
|
|||||||
results: ScanFolderResponse;
|
results: ScanFolderResponse;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const ScanModelsResults = ({ results }: ScanModelResultsProps) => {
|
export const ScanModelsResults = memo(({ results }: ScanModelResultsProps) => {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const [searchTerm, setSearchTerm] = useState('');
|
const [searchTerm, setSearchTerm] = useState('');
|
||||||
const [inplace, setInplace] = useState(true);
|
const [inplace, setInplace] = useState(true);
|
||||||
@ -116,4 +116,6 @@ export const ScanModelsResults = ({ results }: ScanModelResultsProps) => {
|
|||||||
</Flex>
|
</Flex>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
};
|
});
|
||||||
|
|
||||||
|
ScanModelsResults.displayName = 'ScanModelsResults';
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import { Badge, Box, Flex, IconButton, Text } from '@invoke-ai/ui-library';
|
import { Badge, Box, Flex, IconButton, Text } from '@invoke-ai/ui-library';
|
||||||
import { useInstallModel } from 'features/modelManagerV2/hooks/useInstallModel';
|
import { useInstallModel } from 'features/modelManagerV2/hooks/useInstallModel';
|
||||||
import ModelBaseBadge from 'features/modelManagerV2/subpanels/ModelManagerPanel/ModelBaseBadge';
|
import ModelBaseBadge from 'features/modelManagerV2/subpanels/ModelManagerPanel/ModelBaseBadge';
|
||||||
import { useCallback, useMemo } from 'react';
|
import { memo, useCallback, useMemo } from 'react';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
import { PiPlusBold } from 'react-icons/pi';
|
import { PiPlusBold } from 'react-icons/pi';
|
||||||
import type { GetStarterModelsResponse } from 'services/api/endpoints/models';
|
import type { GetStarterModelsResponse } from 'services/api/endpoints/models';
|
||||||
@ -9,7 +9,7 @@ import type { GetStarterModelsResponse } from 'services/api/endpoints/models';
|
|||||||
type Props = {
|
type Props = {
|
||||||
result: GetStarterModelsResponse[number];
|
result: GetStarterModelsResponse[number];
|
||||||
};
|
};
|
||||||
export const StarterModelsResultItem = ({ result }: Props) => {
|
export const StarterModelsResultItem = memo(({ result }: Props) => {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const allSources = useMemo(() => {
|
const allSources = useMemo(() => {
|
||||||
const _allSources = [{ source: result.source, config: { name: result.name, description: result.description } }];
|
const _allSources = [{ source: result.source, config: { name: result.name, description: result.description } }];
|
||||||
@ -47,4 +47,6 @@ export const StarterModelsResultItem = ({ result }: Props) => {
|
|||||||
</Box>
|
</Box>
|
||||||
</Flex>
|
</Flex>
|
||||||
);
|
);
|
||||||
};
|
});
|
||||||
|
|
||||||
|
StarterModelsResultItem.displayName = 'StarterModelsResultItem';
|
||||||
|
@ -1,10 +1,11 @@
|
|||||||
import { Flex } from '@invoke-ai/ui-library';
|
import { Flex } from '@invoke-ai/ui-library';
|
||||||
import { FetchingModelsLoader } from 'features/modelManagerV2/subpanels/ModelManagerPanel/FetchingModelsLoader';
|
import { FetchingModelsLoader } from 'features/modelManagerV2/subpanels/ModelManagerPanel/FetchingModelsLoader';
|
||||||
|
import { memo } from 'react';
|
||||||
import { useGetStarterModelsQuery } from 'services/api/endpoints/models';
|
import { useGetStarterModelsQuery } from 'services/api/endpoints/models';
|
||||||
|
|
||||||
import { StarterModelsResults } from './StarterModelsResults';
|
import { StarterModelsResults } from './StarterModelsResults';
|
||||||
|
|
||||||
export const StarterModelsForm = () => {
|
export const StarterModelsForm = memo(() => {
|
||||||
const { isLoading, data } = useGetStarterModelsQuery();
|
const { isLoading, data } = useGetStarterModelsQuery();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@ -13,4 +14,6 @@ export const StarterModelsForm = () => {
|
|||||||
{data && <StarterModelsResults results={data} />}
|
{data && <StarterModelsResults results={data} />}
|
||||||
</Flex>
|
</Flex>
|
||||||
);
|
);
|
||||||
};
|
});
|
||||||
|
|
||||||
|
StarterModelsForm.displayName = 'StarterModelsForm';
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import { Flex, IconButton, Input, InputGroup, InputRightElement } from '@invoke-ai/ui-library';
|
import { Flex, IconButton, Input, InputGroup, InputRightElement } from '@invoke-ai/ui-library';
|
||||||
import ScrollableContent from 'common/components/OverlayScrollbars/ScrollableContent';
|
import ScrollableContent from 'common/components/OverlayScrollbars/ScrollableContent';
|
||||||
import type { ChangeEventHandler } from 'react';
|
import type { ChangeEventHandler } from 'react';
|
||||||
import { useCallback, useMemo, useState } from 'react';
|
import { memo, useCallback, useMemo, useState } from 'react';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
import { PiXBold } from 'react-icons/pi';
|
import { PiXBold } from 'react-icons/pi';
|
||||||
import type { GetStarterModelsResponse } from 'services/api/endpoints/models';
|
import type { GetStarterModelsResponse } from 'services/api/endpoints/models';
|
||||||
@ -12,7 +12,7 @@ type StarterModelsResultsProps = {
|
|||||||
results: NonNullable<GetStarterModelsResponse>;
|
results: NonNullable<GetStarterModelsResponse>;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const StarterModelsResults = ({ results }: StarterModelsResultsProps) => {
|
export const StarterModelsResults = memo(({ results }: StarterModelsResultsProps) => {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const [searchTerm, setSearchTerm] = useState('');
|
const [searchTerm, setSearchTerm] = useState('');
|
||||||
|
|
||||||
@ -79,4 +79,6 @@ export const StarterModelsResults = ({ results }: StarterModelsResultsProps) =>
|
|||||||
</Flex>
|
</Flex>
|
||||||
</Flex>
|
</Flex>
|
||||||
);
|
);
|
||||||
};
|
});
|
||||||
|
|
||||||
|
StarterModelsResults.displayName = 'StarterModelsResults';
|
||||||
|
@ -2,7 +2,7 @@ import { Box, Flex, Heading, Tab, TabList, TabPanel, TabPanels, Tabs } from '@in
|
|||||||
import { useStore } from '@nanostores/react';
|
import { useStore } from '@nanostores/react';
|
||||||
import { StarterModelsForm } from 'features/modelManagerV2/subpanels/AddModelPanel/StarterModels/StarterModelsForm';
|
import { StarterModelsForm } from 'features/modelManagerV2/subpanels/AddModelPanel/StarterModels/StarterModelsForm';
|
||||||
import { atom } from 'nanostores';
|
import { atom } from 'nanostores';
|
||||||
import { useCallback } from 'react';
|
import { memo, useCallback } from 'react';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
|
|
||||||
import { HuggingFaceForm } from './AddModelPanel/HuggingFaceFolder/HuggingFaceForm';
|
import { HuggingFaceForm } from './AddModelPanel/HuggingFaceFolder/HuggingFaceForm';
|
||||||
@ -12,7 +12,7 @@ import { ScanModelsForm } from './AddModelPanel/ScanFolder/ScanFolderForm';
|
|||||||
|
|
||||||
export const $installModelsTab = atom(0);
|
export const $installModelsTab = atom(0);
|
||||||
|
|
||||||
export const InstallModels = () => {
|
export const InstallModels = memo(() => {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const index = useStore($installModelsTab);
|
const index = useStore($installModelsTab);
|
||||||
const onChange = useCallback((index: number) => {
|
const onChange = useCallback((index: number) => {
|
||||||
@ -49,4 +49,6 @@ export const InstallModels = () => {
|
|||||||
</Box>
|
</Box>
|
||||||
</Flex>
|
</Flex>
|
||||||
);
|
);
|
||||||
};
|
});
|
||||||
|
|
||||||
|
InstallModels.displayName = 'InstallModels';
|
||||||
|
@ -1,14 +1,14 @@
|
|||||||
import { Button, Flex, Heading } from '@invoke-ai/ui-library';
|
import { Button, Flex, Heading } from '@invoke-ai/ui-library';
|
||||||
import { useAppDispatch } from 'app/store/storeHooks';
|
import { useAppDispatch } from 'app/store/storeHooks';
|
||||||
import { setSelectedModelKey } from 'features/modelManagerV2/store/modelManagerV2Slice';
|
import { setSelectedModelKey } from 'features/modelManagerV2/store/modelManagerV2Slice';
|
||||||
import { useCallback } from 'react';
|
import { memo, useCallback } from 'react';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
import { PiPlusBold } from 'react-icons/pi';
|
import { PiPlusBold } from 'react-icons/pi';
|
||||||
|
|
||||||
import ModelList from './ModelManagerPanel/ModelList';
|
import ModelList from './ModelManagerPanel/ModelList';
|
||||||
import { ModelListNavigation } from './ModelManagerPanel/ModelListNavigation';
|
import { ModelListNavigation } from './ModelManagerPanel/ModelListNavigation';
|
||||||
|
|
||||||
export const ModelManager = () => {
|
export const ModelManager = memo(() => {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const dispatch = useAppDispatch();
|
const dispatch = useAppDispatch();
|
||||||
const handleClickAddModel = useCallback(() => {
|
const handleClickAddModel = useCallback(() => {
|
||||||
@ -29,4 +29,6 @@ export const ModelManager = () => {
|
|||||||
</Flex>
|
</Flex>
|
||||||
</Flex>
|
</Flex>
|
||||||
);
|
);
|
||||||
};
|
});
|
||||||
|
|
||||||
|
ModelManager.displayName = 'ModelManager';
|
||||||
|
@ -3,12 +3,12 @@ import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
|
|||||||
import { setSearchTerm } from 'features/modelManagerV2/store/modelManagerV2Slice';
|
import { setSearchTerm } from 'features/modelManagerV2/store/modelManagerV2Slice';
|
||||||
import { t } from 'i18next';
|
import { t } from 'i18next';
|
||||||
import type { ChangeEventHandler } from 'react';
|
import type { ChangeEventHandler } from 'react';
|
||||||
import { useCallback } from 'react';
|
import { memo, useCallback } from 'react';
|
||||||
import { PiXBold } from 'react-icons/pi';
|
import { PiXBold } from 'react-icons/pi';
|
||||||
|
|
||||||
import { ModelTypeFilter } from './ModelTypeFilter';
|
import { ModelTypeFilter } from './ModelTypeFilter';
|
||||||
|
|
||||||
export const ModelListNavigation = () => {
|
export const ModelListNavigation = memo(() => {
|
||||||
const dispatch = useAppDispatch();
|
const dispatch = useAppDispatch();
|
||||||
const searchTerm = useAppSelector((s) => s.modelmanagerV2.searchTerm);
|
const searchTerm = useAppSelector((s) => s.modelmanagerV2.searchTerm);
|
||||||
|
|
||||||
@ -49,4 +49,6 @@ export const ModelListNavigation = () => {
|
|||||||
</InputGroup>
|
</InputGroup>
|
||||||
</Flex>
|
</Flex>
|
||||||
);
|
);
|
||||||
};
|
});
|
||||||
|
|
||||||
|
ModelListNavigation.displayName = 'ModelListNavigation';
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
import { StickyScrollable } from 'features/system/components/StickyScrollable';
|
import { StickyScrollable } from 'features/system/components/StickyScrollable';
|
||||||
|
import { memo } from 'react';
|
||||||
import type { AnyModelConfig } from 'services/api/types';
|
import type { AnyModelConfig } from 'services/api/types';
|
||||||
|
|
||||||
import ModelListItem from './ModelListItem';
|
import ModelListItem from './ModelListItem';
|
||||||
@ -8,7 +9,7 @@ type ModelListWrapperProps = {
|
|||||||
modelList: AnyModelConfig[];
|
modelList: AnyModelConfig[];
|
||||||
};
|
};
|
||||||
|
|
||||||
export const ModelListWrapper = (props: ModelListWrapperProps) => {
|
export const ModelListWrapper = memo((props: ModelListWrapperProps) => {
|
||||||
const { title, modelList } = props;
|
const { title, modelList } = props;
|
||||||
return (
|
return (
|
||||||
<StickyScrollable title={title} contentSx={{ gap: 1, p: 2 }}>
|
<StickyScrollable title={title} contentSx={{ gap: 1, p: 2 }}>
|
||||||
@ -17,4 +18,6 @@ export const ModelListWrapper = (props: ModelListWrapperProps) => {
|
|||||||
))}
|
))}
|
||||||
</StickyScrollable>
|
</StickyScrollable>
|
||||||
);
|
);
|
||||||
};
|
});
|
||||||
|
|
||||||
|
ModelListWrapper.displayName = 'ModelListWrapper';
|
||||||
|
@ -2,12 +2,12 @@ import { Button, Menu, MenuButton, MenuItem, MenuList } from '@invoke-ai/ui-libr
|
|||||||
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
|
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
|
||||||
import type { FilterableModelType } from 'features/modelManagerV2/store/modelManagerV2Slice';
|
import type { FilterableModelType } from 'features/modelManagerV2/store/modelManagerV2Slice';
|
||||||
import { setFilteredModelType } from 'features/modelManagerV2/store/modelManagerV2Slice';
|
import { setFilteredModelType } from 'features/modelManagerV2/store/modelManagerV2Slice';
|
||||||
import { useCallback, useMemo } from 'react';
|
import { memo, useCallback, useMemo } from 'react';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
import { PiFunnelBold } from 'react-icons/pi';
|
import { PiFunnelBold } from 'react-icons/pi';
|
||||||
import { objectKeys } from 'tsafe';
|
import { objectKeys } from 'tsafe';
|
||||||
|
|
||||||
export const ModelTypeFilter = () => {
|
export const ModelTypeFilter = memo(() => {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const dispatch = useAppDispatch();
|
const dispatch = useAppDispatch();
|
||||||
const MODEL_TYPE_LABELS: Record<FilterableModelType, string> = useMemo(
|
const MODEL_TYPE_LABELS: Record<FilterableModelType, string> = useMemo(
|
||||||
@ -57,4 +57,6 @@ export const ModelTypeFilter = () => {
|
|||||||
</MenuList>
|
</MenuList>
|
||||||
</Menu>
|
</Menu>
|
||||||
);
|
);
|
||||||
};
|
});
|
||||||
|
|
||||||
|
ModelTypeFilter.displayName = 'ModelTypeFilter';
|
||||||
|
@ -1,14 +1,17 @@
|
|||||||
import { Box } from '@invoke-ai/ui-library';
|
import { Box } from '@invoke-ai/ui-library';
|
||||||
import { useAppSelector } from 'app/store/storeHooks';
|
import { useAppSelector } from 'app/store/storeHooks';
|
||||||
|
import { memo } from 'react';
|
||||||
|
|
||||||
import { InstallModels } from './InstallModels';
|
import { InstallModels } from './InstallModels';
|
||||||
import { Model } from './ModelPanel/Model';
|
import { Model } from './ModelPanel/Model';
|
||||||
|
|
||||||
export const ModelPane = () => {
|
export const ModelPane = memo(() => {
|
||||||
const selectedModelKey = useAppSelector((s) => s.modelmanagerV2.selectedModelKey);
|
const selectedModelKey = useAppSelector((s) => s.modelmanagerV2.selectedModelKey);
|
||||||
return (
|
return (
|
||||||
<Box layerStyle="first" p={4} borderRadius="base" w="50%" h="full">
|
<Box layerStyle="first" p={4} borderRadius="base" w="50%" h="full">
|
||||||
{selectedModelKey ? <Model key={selectedModelKey} /> : <InstallModels />}
|
{selectedModelKey ? <Model key={selectedModelKey} /> : <InstallModels />}
|
||||||
</Box>
|
</Box>
|
||||||
);
|
);
|
||||||
};
|
});
|
||||||
|
|
||||||
|
ModelPane.displayName = 'ModelPane';
|
||||||
|
@ -3,7 +3,7 @@ import { useControlNetOrT2IAdapterDefaultSettings } from 'features/modelManagerV
|
|||||||
import { DefaultPreprocessor } from 'features/modelManagerV2/subpanels/ModelPanel/ControlNetOrT2IAdapterDefaultSettings/DefaultPreprocessor';
|
import { DefaultPreprocessor } from 'features/modelManagerV2/subpanels/ModelPanel/ControlNetOrT2IAdapterDefaultSettings/DefaultPreprocessor';
|
||||||
import type { FormField } from 'features/modelManagerV2/subpanels/ModelPanel/MainModelDefaultSettings/MainModelDefaultSettings';
|
import type { FormField } from 'features/modelManagerV2/subpanels/ModelPanel/MainModelDefaultSettings/MainModelDefaultSettings';
|
||||||
import { toast } from 'features/toast/toast';
|
import { toast } from 'features/toast/toast';
|
||||||
import { useCallback } from 'react';
|
import { memo, useCallback } from 'react';
|
||||||
import type { SubmitHandler } from 'react-hook-form';
|
import type { SubmitHandler } from 'react-hook-form';
|
||||||
import { useForm } from 'react-hook-form';
|
import { useForm } from 'react-hook-form';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
@ -19,7 +19,7 @@ type Props = {
|
|||||||
modelConfig: ControlNetModelConfig | T2IAdapterModelConfig;
|
modelConfig: ControlNetModelConfig | T2IAdapterModelConfig;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const ControlNetOrT2IAdapterDefaultSettings = ({ modelConfig }: Props) => {
|
export const ControlNetOrT2IAdapterDefaultSettings = memo(({ modelConfig }: Props) => {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
|
|
||||||
const defaultSettingsDefaults = useControlNetOrT2IAdapterDefaultSettings(modelConfig);
|
const defaultSettingsDefaults = useControlNetOrT2IAdapterDefaultSettings(modelConfig);
|
||||||
@ -83,4 +83,6 @@ export const ControlNetOrT2IAdapterDefaultSettings = ({ modelConfig }: Props) =>
|
|||||||
</SimpleGrid>
|
</SimpleGrid>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
};
|
});
|
||||||
|
|
||||||
|
ControlNetOrT2IAdapterDefaultSettings.displayName = 'ControlNetOrT2IAdapterDefaultSettings';
|
||||||
|
@ -4,7 +4,7 @@ import { InformationalPopover } from 'common/components/InformationalPopover/Inf
|
|||||||
import type { ControlNetOrT2IAdapterDefaultSettingsFormData } from 'features/modelManagerV2/subpanels/ModelPanel/ControlNetOrT2IAdapterDefaultSettings/ControlNetOrT2IAdapterDefaultSettings';
|
import type { ControlNetOrT2IAdapterDefaultSettingsFormData } from 'features/modelManagerV2/subpanels/ModelPanel/ControlNetOrT2IAdapterDefaultSettings/ControlNetOrT2IAdapterDefaultSettings';
|
||||||
import type { FormField } from 'features/modelManagerV2/subpanels/ModelPanel/MainModelDefaultSettings/MainModelDefaultSettings';
|
import type { FormField } from 'features/modelManagerV2/subpanels/ModelPanel/MainModelDefaultSettings/MainModelDefaultSettings';
|
||||||
import { SettingToggle } from 'features/modelManagerV2/subpanels/ModelPanel/SettingToggle';
|
import { SettingToggle } from 'features/modelManagerV2/subpanels/ModelPanel/SettingToggle';
|
||||||
import { useCallback, useMemo } from 'react';
|
import { memo, useCallback, useMemo } from 'react';
|
||||||
import type { UseControllerProps } from 'react-hook-form';
|
import type { UseControllerProps } from 'react-hook-form';
|
||||||
import { useController } from 'react-hook-form';
|
import { useController } from 'react-hook-form';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
@ -28,7 +28,7 @@ const OPTIONS = [
|
|||||||
|
|
||||||
type DefaultSchedulerType = ControlNetOrT2IAdapterDefaultSettingsFormData['preprocessor'];
|
type DefaultSchedulerType = ControlNetOrT2IAdapterDefaultSettingsFormData['preprocessor'];
|
||||||
|
|
||||||
export function DefaultPreprocessor(props: UseControllerProps<ControlNetOrT2IAdapterDefaultSettingsFormData>) {
|
export const DefaultPreprocessor = memo((props: UseControllerProps<ControlNetOrT2IAdapterDefaultSettingsFormData>) => {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const { field } = useController(props);
|
const { field } = useController(props);
|
||||||
|
|
||||||
@ -63,4 +63,6 @@ export function DefaultPreprocessor(props: UseControllerProps<ControlNetOrT2IAda
|
|||||||
<Combobox isDisabled={isDisabled} value={value} options={OPTIONS} onChange={onChange} />
|
<Combobox isDisabled={isDisabled} value={value} options={OPTIONS} onChange={onChange} />
|
||||||
</FormControl>
|
</FormControl>
|
||||||
);
|
);
|
||||||
}
|
});
|
||||||
|
|
||||||
|
DefaultPreprocessor.displayName = 'DefaultPreprocessor';
|
||||||
|
@ -2,7 +2,7 @@ import { CompositeNumberInput, CompositeSlider, Flex, FormControl, FormLabel } f
|
|||||||
import { useAppSelector } from 'app/store/storeHooks';
|
import { useAppSelector } from 'app/store/storeHooks';
|
||||||
import { InformationalPopover } from 'common/components/InformationalPopover/InformationalPopover';
|
import { InformationalPopover } from 'common/components/InformationalPopover/InformationalPopover';
|
||||||
import { SettingToggle } from 'features/modelManagerV2/subpanels/ModelPanel/SettingToggle';
|
import { SettingToggle } from 'features/modelManagerV2/subpanels/ModelPanel/SettingToggle';
|
||||||
import { useCallback, useMemo } from 'react';
|
import { memo, useCallback, useMemo } from 'react';
|
||||||
import type { UseControllerProps } from 'react-hook-form';
|
import type { UseControllerProps } from 'react-hook-form';
|
||||||
import { useController } from 'react-hook-form';
|
import { useController } from 'react-hook-form';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
@ -11,7 +11,7 @@ import type { MainModelDefaultSettingsFormData } from './MainModelDefaultSetting
|
|||||||
|
|
||||||
type DefaultCfgRescaleMultiplierType = MainModelDefaultSettingsFormData['cfgRescaleMultiplier'];
|
type DefaultCfgRescaleMultiplierType = MainModelDefaultSettingsFormData['cfgRescaleMultiplier'];
|
||||||
|
|
||||||
export function DefaultCfgRescaleMultiplier(props: UseControllerProps<MainModelDefaultSettingsFormData>) {
|
export const DefaultCfgRescaleMultiplier = memo((props: UseControllerProps<MainModelDefaultSettingsFormData>) => {
|
||||||
const { field } = useController(props);
|
const { field } = useController(props);
|
||||||
|
|
||||||
const sliderMin = useAppSelector((s) => s.config.sd.cfgRescaleMultiplier.sliderMin);
|
const sliderMin = useAppSelector((s) => s.config.sd.cfgRescaleMultiplier.sliderMin);
|
||||||
@ -74,4 +74,6 @@ export function DefaultCfgRescaleMultiplier(props: UseControllerProps<MainModelD
|
|||||||
</Flex>
|
</Flex>
|
||||||
</FormControl>
|
</FormControl>
|
||||||
);
|
);
|
||||||
}
|
});
|
||||||
|
|
||||||
|
DefaultCfgRescaleMultiplier.displayName = 'DefaultCfgRescaleMultiplier';
|
||||||
|
@ -2,7 +2,7 @@ import { CompositeNumberInput, CompositeSlider, Flex, FormControl, FormLabel } f
|
|||||||
import { useAppSelector } from 'app/store/storeHooks';
|
import { useAppSelector } from 'app/store/storeHooks';
|
||||||
import { InformationalPopover } from 'common/components/InformationalPopover/InformationalPopover';
|
import { InformationalPopover } from 'common/components/InformationalPopover/InformationalPopover';
|
||||||
import { SettingToggle } from 'features/modelManagerV2/subpanels/ModelPanel/SettingToggle';
|
import { SettingToggle } from 'features/modelManagerV2/subpanels/ModelPanel/SettingToggle';
|
||||||
import { useCallback, useMemo } from 'react';
|
import { memo, useCallback, useMemo } from 'react';
|
||||||
import type { UseControllerProps } from 'react-hook-form';
|
import type { UseControllerProps } from 'react-hook-form';
|
||||||
import { useController } from 'react-hook-form';
|
import { useController } from 'react-hook-form';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
@ -11,7 +11,7 @@ import type { MainModelDefaultSettingsFormData } from './MainModelDefaultSetting
|
|||||||
|
|
||||||
type DefaultCfgType = MainModelDefaultSettingsFormData['cfgScale'];
|
type DefaultCfgType = MainModelDefaultSettingsFormData['cfgScale'];
|
||||||
|
|
||||||
export function DefaultCfgScale(props: UseControllerProps<MainModelDefaultSettingsFormData>) {
|
export const DefaultCfgScale = memo((props: UseControllerProps<MainModelDefaultSettingsFormData>) => {
|
||||||
const { field } = useController(props);
|
const { field } = useController(props);
|
||||||
|
|
||||||
const sliderMin = useAppSelector((s) => s.config.sd.guidance.sliderMin);
|
const sliderMin = useAppSelector((s) => s.config.sd.guidance.sliderMin);
|
||||||
@ -74,4 +74,6 @@ export function DefaultCfgScale(props: UseControllerProps<MainModelDefaultSettin
|
|||||||
</Flex>
|
</Flex>
|
||||||
</FormControl>
|
</FormControl>
|
||||||
);
|
);
|
||||||
}
|
});
|
||||||
|
|
||||||
|
DefaultCfgScale.displayName = 'DefaultCfgScale';
|
||||||
|
@ -2,7 +2,7 @@ import { CompositeNumberInput, CompositeSlider, Flex, FormControl, FormLabel } f
|
|||||||
import { useAppSelector } from 'app/store/storeHooks';
|
import { useAppSelector } from 'app/store/storeHooks';
|
||||||
import { InformationalPopover } from 'common/components/InformationalPopover/InformationalPopover';
|
import { InformationalPopover } from 'common/components/InformationalPopover/InformationalPopover';
|
||||||
import { SettingToggle } from 'features/modelManagerV2/subpanels/ModelPanel/SettingToggle';
|
import { SettingToggle } from 'features/modelManagerV2/subpanels/ModelPanel/SettingToggle';
|
||||||
import { useCallback, useMemo } from 'react';
|
import { memo, useCallback, useMemo } from 'react';
|
||||||
import type { UseControllerProps } from 'react-hook-form';
|
import type { UseControllerProps } from 'react-hook-form';
|
||||||
import { useController } from 'react-hook-form';
|
import { useController } from 'react-hook-form';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
@ -16,7 +16,7 @@ type Props = {
|
|||||||
optimalDimension: number;
|
optimalDimension: number;
|
||||||
};
|
};
|
||||||
|
|
||||||
export function DefaultHeight({ control, optimalDimension }: Props) {
|
export const DefaultHeight = memo(({ control, optimalDimension }: Props) => {
|
||||||
const { field } = useController({ control, name: 'height' });
|
const { field } = useController({ control, name: 'height' });
|
||||||
const sliderMin = useAppSelector((s) => s.config.sd.height.sliderMin);
|
const sliderMin = useAppSelector((s) => s.config.sd.height.sliderMin);
|
||||||
const sliderMax = useAppSelector((s) => s.config.sd.height.sliderMax);
|
const sliderMax = useAppSelector((s) => s.config.sd.height.sliderMax);
|
||||||
@ -78,4 +78,6 @@ export function DefaultHeight({ control, optimalDimension }: Props) {
|
|||||||
</Flex>
|
</Flex>
|
||||||
</FormControl>
|
</FormControl>
|
||||||
);
|
);
|
||||||
}
|
});
|
||||||
|
|
||||||
|
DefaultHeight.displayName = 'DefaultHeight';
|
||||||
|
@ -4,7 +4,7 @@ import { InformationalPopover } from 'common/components/InformationalPopover/Inf
|
|||||||
import { SettingToggle } from 'features/modelManagerV2/subpanels/ModelPanel/SettingToggle';
|
import { SettingToggle } from 'features/modelManagerV2/subpanels/ModelPanel/SettingToggle';
|
||||||
import { SCHEDULER_OPTIONS } from 'features/parameters/types/constants';
|
import { SCHEDULER_OPTIONS } from 'features/parameters/types/constants';
|
||||||
import { isParameterScheduler } from 'features/parameters/types/parameterSchemas';
|
import { isParameterScheduler } from 'features/parameters/types/parameterSchemas';
|
||||||
import { useCallback, useMemo } from 'react';
|
import { memo, useCallback, useMemo } from 'react';
|
||||||
import type { UseControllerProps } from 'react-hook-form';
|
import type { UseControllerProps } from 'react-hook-form';
|
||||||
import { useController } from 'react-hook-form';
|
import { useController } from 'react-hook-form';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
@ -13,7 +13,7 @@ import type { MainModelDefaultSettingsFormData } from './MainModelDefaultSetting
|
|||||||
|
|
||||||
type DefaultSchedulerType = MainModelDefaultSettingsFormData['scheduler'];
|
type DefaultSchedulerType = MainModelDefaultSettingsFormData['scheduler'];
|
||||||
|
|
||||||
export function DefaultScheduler(props: UseControllerProps<MainModelDefaultSettingsFormData>) {
|
export const DefaultScheduler = memo((props: UseControllerProps<MainModelDefaultSettingsFormData>) => {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const { field } = useController(props);
|
const { field } = useController(props);
|
||||||
|
|
||||||
@ -51,4 +51,6 @@ export function DefaultScheduler(props: UseControllerProps<MainModelDefaultSetti
|
|||||||
<Combobox isDisabled={isDisabled} value={value} options={SCHEDULER_OPTIONS} onChange={onChange} />
|
<Combobox isDisabled={isDisabled} value={value} options={SCHEDULER_OPTIONS} onChange={onChange} />
|
||||||
</FormControl>
|
</FormControl>
|
||||||
);
|
);
|
||||||
}
|
});
|
||||||
|
|
||||||
|
DefaultScheduler.displayName = 'DefaultScheduler';
|
||||||
|
@ -2,7 +2,7 @@ import { CompositeNumberInput, CompositeSlider, Flex, FormControl, FormLabel } f
|
|||||||
import { useAppSelector } from 'app/store/storeHooks';
|
import { useAppSelector } from 'app/store/storeHooks';
|
||||||
import { InformationalPopover } from 'common/components/InformationalPopover/InformationalPopover';
|
import { InformationalPopover } from 'common/components/InformationalPopover/InformationalPopover';
|
||||||
import { SettingToggle } from 'features/modelManagerV2/subpanels/ModelPanel/SettingToggle';
|
import { SettingToggle } from 'features/modelManagerV2/subpanels/ModelPanel/SettingToggle';
|
||||||
import { useCallback, useMemo } from 'react';
|
import { memo, useCallback, useMemo } from 'react';
|
||||||
import type { UseControllerProps } from 'react-hook-form';
|
import type { UseControllerProps } from 'react-hook-form';
|
||||||
import { useController } from 'react-hook-form';
|
import { useController } from 'react-hook-form';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
@ -11,7 +11,7 @@ import type { MainModelDefaultSettingsFormData } from './MainModelDefaultSetting
|
|||||||
|
|
||||||
type DefaultSteps = MainModelDefaultSettingsFormData['steps'];
|
type DefaultSteps = MainModelDefaultSettingsFormData['steps'];
|
||||||
|
|
||||||
export function DefaultSteps(props: UseControllerProps<MainModelDefaultSettingsFormData>) {
|
export const DefaultSteps = memo((props: UseControllerProps<MainModelDefaultSettingsFormData>) => {
|
||||||
const { field } = useController(props);
|
const { field } = useController(props);
|
||||||
|
|
||||||
const sliderMin = useAppSelector((s) => s.config.sd.steps.sliderMin);
|
const sliderMin = useAppSelector((s) => s.config.sd.steps.sliderMin);
|
||||||
@ -74,4 +74,6 @@ export function DefaultSteps(props: UseControllerProps<MainModelDefaultSettingsF
|
|||||||
</Flex>
|
</Flex>
|
||||||
</FormControl>
|
</FormControl>
|
||||||
);
|
);
|
||||||
}
|
});
|
||||||
|
|
||||||
|
DefaultSteps.displayName = 'DefaultSteps';
|
||||||
|
@ -4,7 +4,7 @@ import { skipToken } from '@reduxjs/toolkit/query';
|
|||||||
import { useAppSelector } from 'app/store/storeHooks';
|
import { useAppSelector } from 'app/store/storeHooks';
|
||||||
import { InformationalPopover } from 'common/components/InformationalPopover/InformationalPopover';
|
import { InformationalPopover } from 'common/components/InformationalPopover/InformationalPopover';
|
||||||
import { SettingToggle } from 'features/modelManagerV2/subpanels/ModelPanel/SettingToggle';
|
import { SettingToggle } from 'features/modelManagerV2/subpanels/ModelPanel/SettingToggle';
|
||||||
import { useCallback, useMemo } from 'react';
|
import { memo, useCallback, useMemo } from 'react';
|
||||||
import type { UseControllerProps } from 'react-hook-form';
|
import type { UseControllerProps } from 'react-hook-form';
|
||||||
import { useController } from 'react-hook-form';
|
import { useController } from 'react-hook-form';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
@ -15,7 +15,7 @@ import type { MainModelDefaultSettingsFormData } from './MainModelDefaultSetting
|
|||||||
|
|
||||||
type DefaultVaeType = MainModelDefaultSettingsFormData['vae'];
|
type DefaultVaeType = MainModelDefaultSettingsFormData['vae'];
|
||||||
|
|
||||||
export function DefaultVae(props: UseControllerProps<MainModelDefaultSettingsFormData>) {
|
export const DefaultVae = memo((props: UseControllerProps<MainModelDefaultSettingsFormData>) => {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const { field } = useController(props);
|
const { field } = useController(props);
|
||||||
const selectedModelKey = useAppSelector((s) => s.modelmanagerV2.selectedModelKey);
|
const selectedModelKey = useAppSelector((s) => s.modelmanagerV2.selectedModelKey);
|
||||||
@ -64,4 +64,6 @@ export function DefaultVae(props: UseControllerProps<MainModelDefaultSettingsFor
|
|||||||
<Combobox isDisabled={isDisabled} value={value} options={compatibleOptions} onChange={onChange} />
|
<Combobox isDisabled={isDisabled} value={value} options={compatibleOptions} onChange={onChange} />
|
||||||
</FormControl>
|
</FormControl>
|
||||||
);
|
);
|
||||||
}
|
});
|
||||||
|
|
||||||
|
DefaultVae.displayName = 'DefaultVae';
|
||||||
|
@ -3,7 +3,7 @@ import { Combobox, Flex, FormControl, FormLabel } from '@invoke-ai/ui-library';
|
|||||||
import { InformationalPopover } from 'common/components/InformationalPopover/InformationalPopover';
|
import { InformationalPopover } from 'common/components/InformationalPopover/InformationalPopover';
|
||||||
import { SettingToggle } from 'features/modelManagerV2/subpanels/ModelPanel/SettingToggle';
|
import { SettingToggle } from 'features/modelManagerV2/subpanels/ModelPanel/SettingToggle';
|
||||||
import { isParameterPrecision } from 'features/parameters/types/parameterSchemas';
|
import { isParameterPrecision } from 'features/parameters/types/parameterSchemas';
|
||||||
import { useCallback, useMemo } from 'react';
|
import { memo, useCallback, useMemo } from 'react';
|
||||||
import type { UseControllerProps } from 'react-hook-form';
|
import type { UseControllerProps } from 'react-hook-form';
|
||||||
import { useController } from 'react-hook-form';
|
import { useController } from 'react-hook-form';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
@ -17,7 +17,7 @@ const options = [
|
|||||||
|
|
||||||
type DefaultVaePrecisionType = MainModelDefaultSettingsFormData['vaePrecision'];
|
type DefaultVaePrecisionType = MainModelDefaultSettingsFormData['vaePrecision'];
|
||||||
|
|
||||||
export function DefaultVaePrecision(props: UseControllerProps<MainModelDefaultSettingsFormData>) {
|
export const DefaultVaePrecision = memo((props: UseControllerProps<MainModelDefaultSettingsFormData>) => {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const { field } = useController(props);
|
const { field } = useController(props);
|
||||||
|
|
||||||
@ -52,4 +52,6 @@ export function DefaultVaePrecision(props: UseControllerProps<MainModelDefaultSe
|
|||||||
<Combobox isDisabled={isDisabled} value={value} options={options} onChange={onChange} />
|
<Combobox isDisabled={isDisabled} value={value} options={options} onChange={onChange} />
|
||||||
</FormControl>
|
</FormControl>
|
||||||
);
|
);
|
||||||
}
|
});
|
||||||
|
|
||||||
|
DefaultVaePrecision.displayName = 'DefaultVaePrecision';
|
||||||
|
@ -2,7 +2,7 @@ import { CompositeNumberInput, CompositeSlider, Flex, FormControl, FormLabel } f
|
|||||||
import { useAppSelector } from 'app/store/storeHooks';
|
import { useAppSelector } from 'app/store/storeHooks';
|
||||||
import { InformationalPopover } from 'common/components/InformationalPopover/InformationalPopover';
|
import { InformationalPopover } from 'common/components/InformationalPopover/InformationalPopover';
|
||||||
import { SettingToggle } from 'features/modelManagerV2/subpanels/ModelPanel/SettingToggle';
|
import { SettingToggle } from 'features/modelManagerV2/subpanels/ModelPanel/SettingToggle';
|
||||||
import { useCallback, useMemo } from 'react';
|
import { memo, useCallback, useMemo } from 'react';
|
||||||
import type { UseControllerProps } from 'react-hook-form';
|
import type { UseControllerProps } from 'react-hook-form';
|
||||||
import { useController } from 'react-hook-form';
|
import { useController } from 'react-hook-form';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
@ -16,7 +16,7 @@ type Props = {
|
|||||||
optimalDimension: number;
|
optimalDimension: number;
|
||||||
};
|
};
|
||||||
|
|
||||||
export function DefaultWidth({ control, optimalDimension }: Props) {
|
export const DefaultWidth = memo(({ control, optimalDimension }: Props) => {
|
||||||
const { field } = useController({ control, name: 'width' });
|
const { field } = useController({ control, name: 'width' });
|
||||||
const sliderMin = useAppSelector((s) => s.config.sd.width.sliderMin);
|
const sliderMin = useAppSelector((s) => s.config.sd.width.sliderMin);
|
||||||
const sliderMax = useAppSelector((s) => s.config.sd.width.sliderMax);
|
const sliderMax = useAppSelector((s) => s.config.sd.width.sliderMax);
|
||||||
@ -78,4 +78,6 @@ export function DefaultWidth({ control, optimalDimension }: Props) {
|
|||||||
</Flex>
|
</Flex>
|
||||||
</FormControl>
|
</FormControl>
|
||||||
);
|
);
|
||||||
}
|
});
|
||||||
|
|
||||||
|
DefaultWidth.displayName = 'DefaultWidth';
|
||||||
|
@ -6,7 +6,7 @@ import { DefaultWidth } from 'features/modelManagerV2/subpanels/ModelPanel/MainM
|
|||||||
import type { ParameterScheduler } from 'features/parameters/types/parameterSchemas';
|
import type { ParameterScheduler } from 'features/parameters/types/parameterSchemas';
|
||||||
import { getOptimalDimension } from 'features/parameters/util/optimalDimension';
|
import { getOptimalDimension } from 'features/parameters/util/optimalDimension';
|
||||||
import { toast } from 'features/toast/toast';
|
import { toast } from 'features/toast/toast';
|
||||||
import { useCallback, useMemo } from 'react';
|
import { memo, useCallback, useMemo } from 'react';
|
||||||
import type { SubmitHandler } from 'react-hook-form';
|
import type { SubmitHandler } from 'react-hook-form';
|
||||||
import { useForm } from 'react-hook-form';
|
import { useForm } from 'react-hook-form';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
@ -41,7 +41,7 @@ type Props = {
|
|||||||
modelConfig: MainModelConfig;
|
modelConfig: MainModelConfig;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const MainModelDefaultSettings = ({ modelConfig }: Props) => {
|
export const MainModelDefaultSettings = memo(({ modelConfig }: Props) => {
|
||||||
const selectedModelKey = useAppSelector((s) => s.modelmanagerV2.selectedModelKey);
|
const selectedModelKey = useAppSelector((s) => s.modelmanagerV2.selectedModelKey);
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
|
|
||||||
@ -124,4 +124,6 @@ export const MainModelDefaultSettings = ({ modelConfig }: Props) => {
|
|||||||
</SimpleGrid>
|
</SimpleGrid>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
};
|
});
|
||||||
|
|
||||||
|
MainModelDefaultSettings.displayName = 'MainModelDefaultSettings';
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import { useAppSelector } from 'app/store/storeHooks';
|
import { useAppSelector } from 'app/store/storeHooks';
|
||||||
import { IAINoContentFallback, IAINoContentFallbackWithSpinner } from 'common/components/IAIImageFallback';
|
import { IAINoContentFallback, IAINoContentFallbackWithSpinner } from 'common/components/IAIImageFallback';
|
||||||
import { useMemo } from 'react';
|
import { memo, useMemo } from 'react';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
import { PiExclamationMarkBold } from 'react-icons/pi';
|
import { PiExclamationMarkBold } from 'react-icons/pi';
|
||||||
import { modelConfigsAdapterSelectors, useGetModelConfigsQuery } from 'services/api/endpoints/models';
|
import { modelConfigsAdapterSelectors, useGetModelConfigsQuery } from 'services/api/endpoints/models';
|
||||||
@ -8,7 +8,7 @@ import { modelConfigsAdapterSelectors, useGetModelConfigsQuery } from 'services/
|
|||||||
import { ModelEdit } from './ModelEdit';
|
import { ModelEdit } from './ModelEdit';
|
||||||
import { ModelView } from './ModelView';
|
import { ModelView } from './ModelView';
|
||||||
|
|
||||||
export const Model = () => {
|
export const Model = memo(() => {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const selectedModelMode = useAppSelector((s) => s.modelmanagerV2.selectedModelMode);
|
const selectedModelMode = useAppSelector((s) => s.modelmanagerV2.selectedModelMode);
|
||||||
const selectedModelKey = useAppSelector((s) => s.modelmanagerV2.selectedModelKey);
|
const selectedModelKey = useAppSelector((s) => s.modelmanagerV2.selectedModelKey);
|
||||||
@ -42,4 +42,6 @@ export const Model = () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return <ModelEdit modelConfig={modelConfig} />;
|
return <ModelEdit modelConfig={modelConfig} />;
|
||||||
};
|
});
|
||||||
|
|
||||||
|
Model.displayName = 'Model';
|
||||||
|
@ -1,11 +1,12 @@
|
|||||||
import { FormControl, FormLabel, Text } from '@invoke-ai/ui-library';
|
import { FormControl, FormLabel, Text } from '@invoke-ai/ui-library';
|
||||||
|
import { memo } from 'react';
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
label: string;
|
label: string;
|
||||||
value: string | null | undefined;
|
value: string | null | undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const ModelAttrView = ({ label, value }: Props) => {
|
export const ModelAttrView = memo(({ label, value }: Props) => {
|
||||||
return (
|
return (
|
||||||
<FormControl flexDir="column" alignItems="flex-start" gap={0}>
|
<FormControl flexDir="column" alignItems="flex-start" gap={0}>
|
||||||
<FormLabel>{label}</FormLabel>
|
<FormLabel>{label}</FormLabel>
|
||||||
@ -14,4 +15,6 @@ export const ModelAttrView = ({ label, value }: Props) => {
|
|||||||
</Text>
|
</Text>
|
||||||
</FormControl>
|
</FormControl>
|
||||||
);
|
);
|
||||||
};
|
});
|
||||||
|
|
||||||
|
ModelAttrView.displayName = 'ModelAttrView';
|
||||||
|
@ -9,7 +9,7 @@ import {
|
|||||||
useDisclosure,
|
useDisclosure,
|
||||||
} from '@invoke-ai/ui-library';
|
} from '@invoke-ai/ui-library';
|
||||||
import { toast } from 'features/toast/toast';
|
import { toast } from 'features/toast/toast';
|
||||||
import { useCallback } from 'react';
|
import { memo, useCallback } from 'react';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
import { useConvertModelMutation } from 'services/api/endpoints/models';
|
import { useConvertModelMutation } from 'services/api/endpoints/models';
|
||||||
import type { CheckpointModelConfig } from 'services/api/types';
|
import type { CheckpointModelConfig } from 'services/api/types';
|
||||||
@ -18,7 +18,7 @@ interface ModelConvertProps {
|
|||||||
modelConfig: CheckpointModelConfig;
|
modelConfig: CheckpointModelConfig;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const ModelConvertButton = ({ modelConfig }: ModelConvertProps) => {
|
export const ModelConvertButton = memo(({ modelConfig }: ModelConvertProps) => {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const [convertModel, { isLoading }] = useConvertModelMutation();
|
const [convertModel, { isLoading }] = useConvertModelMutation();
|
||||||
const { isOpen, onOpen, onClose } = useDisclosure();
|
const { isOpen, onOpen, onClose } = useDisclosure();
|
||||||
@ -90,4 +90,6 @@ export const ModelConvertButton = ({ modelConfig }: ModelConvertProps) => {
|
|||||||
</ConfirmationAlertDialog>
|
</ConfirmationAlertDialog>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
};
|
});
|
||||||
|
|
||||||
|
ModelConvertButton.displayName = 'ModelConvertButton';
|
||||||
|
@ -14,7 +14,7 @@ import { useAppDispatch } from 'app/store/storeHooks';
|
|||||||
import { setSelectedModelMode } from 'features/modelManagerV2/store/modelManagerV2Slice';
|
import { setSelectedModelMode } from 'features/modelManagerV2/store/modelManagerV2Slice';
|
||||||
import { ModelHeader } from 'features/modelManagerV2/subpanels/ModelPanel/ModelHeader';
|
import { ModelHeader } from 'features/modelManagerV2/subpanels/ModelPanel/ModelHeader';
|
||||||
import { toast } from 'features/toast/toast';
|
import { toast } from 'features/toast/toast';
|
||||||
import { useCallback } from 'react';
|
import { memo, useCallback } from 'react';
|
||||||
import { type SubmitHandler, useForm } from 'react-hook-form';
|
import { type SubmitHandler, useForm } from 'react-hook-form';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
import { PiCheckBold, PiXBold } from 'react-icons/pi';
|
import { PiCheckBold, PiXBold } from 'react-icons/pi';
|
||||||
@ -33,7 +33,7 @@ const stringFieldOptions = {
|
|||||||
validate: (value?: string | null) => (value && value.trim().length > 3) || 'Must be at least 3 characters',
|
validate: (value?: string | null) => (value && value.trim().length > 3) || 'Must be at least 3 characters',
|
||||||
};
|
};
|
||||||
|
|
||||||
export const ModelEdit = ({ modelConfig }: Props) => {
|
export const ModelEdit = memo(({ modelConfig }: Props) => {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const [updateModel, { isLoading: isSubmitting }] = useUpdateModelMutation();
|
const [updateModel, { isLoading: isSubmitting }] = useUpdateModelMutation();
|
||||||
const dispatch = useAppDispatch();
|
const dispatch = useAppDispatch();
|
||||||
@ -156,4 +156,6 @@ export const ModelEdit = ({ modelConfig }: Props) => {
|
|||||||
</Flex>
|
</Flex>
|
||||||
</Flex>
|
</Flex>
|
||||||
);
|
);
|
||||||
};
|
});
|
||||||
|
|
||||||
|
ModelEdit.displayName = 'ModelEdit';
|
||||||
|
@ -1,11 +1,11 @@
|
|||||||
import { Button } from '@invoke-ai/ui-library';
|
import { Button } from '@invoke-ai/ui-library';
|
||||||
import { useAppDispatch } from 'app/store/storeHooks';
|
import { useAppDispatch } from 'app/store/storeHooks';
|
||||||
import { setSelectedModelMode } from 'features/modelManagerV2/store/modelManagerV2Slice';
|
import { setSelectedModelMode } from 'features/modelManagerV2/store/modelManagerV2Slice';
|
||||||
import { useCallback } from 'react';
|
import { memo, useCallback } from 'react';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
import { IoPencil } from 'react-icons/io5';
|
import { IoPencil } from 'react-icons/io5';
|
||||||
|
|
||||||
export const ModelEditButton = () => {
|
export const ModelEditButton = memo(() => {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const dispatch = useAppDispatch();
|
const dispatch = useAppDispatch();
|
||||||
|
|
||||||
@ -18,4 +18,6 @@ export const ModelEditButton = () => {
|
|||||||
{t('modelManager.edit')}
|
{t('modelManager.edit')}
|
||||||
</Button>
|
</Button>
|
||||||
);
|
);
|
||||||
};
|
});
|
||||||
|
|
||||||
|
ModelEditButton.displayName = 'ModelEditButton';
|
||||||
|
@ -4,6 +4,7 @@ import { ModelConvertButton } from 'features/modelManagerV2/subpanels/ModelPanel
|
|||||||
import { ModelEditButton } from 'features/modelManagerV2/subpanels/ModelPanel/ModelEditButton';
|
import { ModelEditButton } from 'features/modelManagerV2/subpanels/ModelPanel/ModelEditButton';
|
||||||
import { ModelHeader } from 'features/modelManagerV2/subpanels/ModelPanel/ModelHeader';
|
import { ModelHeader } from 'features/modelManagerV2/subpanels/ModelPanel/ModelHeader';
|
||||||
import { TriggerPhrases } from 'features/modelManagerV2/subpanels/ModelPanel/TriggerPhrases';
|
import { TriggerPhrases } from 'features/modelManagerV2/subpanels/ModelPanel/TriggerPhrases';
|
||||||
|
import { memo } from 'react';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
import type { AnyModelConfig } from 'services/api/types';
|
import type { AnyModelConfig } from 'services/api/types';
|
||||||
|
|
||||||
@ -14,7 +15,7 @@ type Props = {
|
|||||||
modelConfig: AnyModelConfig;
|
modelConfig: AnyModelConfig;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const ModelView = ({ modelConfig }: Props) => {
|
export const ModelView = memo(({ modelConfig }: Props) => {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
return (
|
return (
|
||||||
<Flex flexDir="column" gap={4}>
|
<Flex flexDir="column" gap={4}>
|
||||||
@ -61,4 +62,6 @@ export const ModelView = ({ modelConfig }: Props) => {
|
|||||||
</Flex>
|
</Flex>
|
||||||
</Flex>
|
</Flex>
|
||||||
);
|
);
|
||||||
};
|
});
|
||||||
|
|
||||||
|
ModelView.displayName = 'ModelView';
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import { Switch } from '@invoke-ai/ui-library';
|
import { Switch, typedMemo } from '@invoke-ai/ui-library';
|
||||||
import type { ChangeEvent } from 'react';
|
import type { ChangeEvent } from 'react';
|
||||||
import { useCallback, useMemo } from 'react';
|
import { useCallback, useMemo } from 'react';
|
||||||
import type { UseControllerProps } from 'react-hook-form';
|
import type { UseControllerProps } from 'react-hook-form';
|
||||||
@ -6,7 +6,7 @@ import { useController } from 'react-hook-form';
|
|||||||
|
|
||||||
import type { FormField } from './MainModelDefaultSettings/MainModelDefaultSettings';
|
import type { FormField } from './MainModelDefaultSettings/MainModelDefaultSettings';
|
||||||
|
|
||||||
export function SettingToggle<T, F extends Record<string, FormField<T>>>(props: UseControllerProps<F>) {
|
export const SettingToggle = typedMemo(<T, F extends Record<string, FormField<T>>>(props: UseControllerProps<F>) => {
|
||||||
const { field } = useController(props);
|
const { field } = useController(props);
|
||||||
|
|
||||||
const value = useMemo(() => {
|
const value = useMemo(() => {
|
||||||
@ -25,4 +25,6 @@ export function SettingToggle<T, F extends Record<string, FormField<T>>>(props:
|
|||||||
);
|
);
|
||||||
|
|
||||||
return <Switch size="sm" isChecked={value} onChange={onChange} />;
|
return <Switch size="sm" isChecked={value} onChange={onChange} />;
|
||||||
}
|
});
|
||||||
|
|
||||||
|
SettingToggle.displayName = 'SettingToggle';
|
||||||
|
@ -10,7 +10,7 @@ import {
|
|||||||
TagLabel,
|
TagLabel,
|
||||||
} from '@invoke-ai/ui-library';
|
} from '@invoke-ai/ui-library';
|
||||||
import type { ChangeEvent } from 'react';
|
import type { ChangeEvent } from 'react';
|
||||||
import { useCallback, useMemo, useState } from 'react';
|
import { memo, useCallback, useMemo, useState } from 'react';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
import { PiPlusBold } from 'react-icons/pi';
|
import { PiPlusBold } from 'react-icons/pi';
|
||||||
import { useUpdateModelMutation } from 'services/api/endpoints/models';
|
import { useUpdateModelMutation } from 'services/api/endpoints/models';
|
||||||
@ -20,7 +20,7 @@ type Props = {
|
|||||||
modelConfig: MainModelConfig | LoRAModelConfig;
|
modelConfig: MainModelConfig | LoRAModelConfig;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const TriggerPhrases = ({ modelConfig }: Props) => {
|
export const TriggerPhrases = memo(({ modelConfig }: Props) => {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const [phrase, setPhrase] = useState('');
|
const [phrase, setPhrase] = useState('');
|
||||||
|
|
||||||
@ -92,7 +92,9 @@ export const TriggerPhrases = ({ modelConfig }: Props) => {
|
|||||||
{t('common.add')}
|
{t('common.add')}
|
||||||
</Button>
|
</Button>
|
||||||
</Flex>
|
</Flex>
|
||||||
{!!errors.length && errors.map((error) => <FormErrorMessage key={error}>{error}</FormErrorMessage>)}
|
{errors.map((error) => (
|
||||||
|
<FormErrorMessage key={error}>{error}</FormErrorMessage>
|
||||||
|
))}
|
||||||
</Flex>
|
</Flex>
|
||||||
</FormControl>
|
</FormControl>
|
||||||
</form>
|
</form>
|
||||||
@ -107,4 +109,6 @@ export const TriggerPhrases = ({ modelConfig }: Props) => {
|
|||||||
</Flex>
|
</Flex>
|
||||||
</Flex>
|
</Flex>
|
||||||
);
|
);
|
||||||
};
|
});
|
||||||
|
|
||||||
|
TriggerPhrases.displayName = 'TriggerPhrases';
|
||||||
|
Loading…
x
Reference in New Issue
Block a user