feat(ui): accept callback to override navigate to model manager functionality

If provided, `<NavigateToModelManagerButton />` will render, even if `disabledTabs` includes "models". If provided, `<NavigateToModelManagerButton />` will run the callback instead of switching tabs within the studio.

The button's tooltip is now just "Manage Models" and its icon is the same as the model manager tab's icon ([CUBE!](https://www.youtube.com/watch?v=4aGDCE6Nrz0)).
This commit is contained in:
psychedelicious
2025-04-09 15:39:52 +10:00
parent 298444f2bc
commit 9cc13556aa
4 changed files with 33 additions and 9 deletions

View File

@@ -871,7 +871,8 @@
"installingXModels_one": "Installing {{count}} model",
"installingXModels_other": "Installing {{count}} models",
"skippingXDuplicates_one": ", skipping {{count}} duplicate",
"skippingXDuplicates_other": ", skipping {{count}} duplicates"
"skippingXDuplicates_other": ", skipping {{count}} duplicates",
"manageModels": "Manage Models"
},
"models": {
"addLora": "Add LoRA",

View File

@@ -12,6 +12,7 @@ import type { CustomStarUi } from 'app/store/nanostores/customStarUI';
import { $customStarUI } from 'app/store/nanostores/customStarUI';
import { $isDebugging } from 'app/store/nanostores/isDebugging';
import { $logo } from 'app/store/nanostores/logo';
import { $onClickGoToModelManager } from 'app/store/nanostores/onClickGoToModelManager';
import { $openAPISchemaUrl } from 'app/store/nanostores/openAPISchemaUrl';
import { $projectId, $projectName, $projectUrl } from 'app/store/nanostores/projectId';
import { $queueId, DEFAULT_QUEUE_ID } from 'app/store/nanostores/queueId';
@@ -59,6 +60,10 @@ interface Props extends PropsWithChildren {
workflowTagCategories?: WorkflowTagCategory[];
workflowSortOptions?: WorkflowSortOption[];
loggingOverrides?: LoggingOverrides;
/**
* If provided, overrides in-app navigation to the model manager
*/
onClickGoToModelManager?: () => void;
}
const InvokeAIUI = ({
@@ -81,6 +86,7 @@ const InvokeAIUI = ({
workflowTagCategories,
workflowSortOptions,
loggingOverrides,
onClickGoToModelManager,
}: Props) => {
useLayoutEffect(() => {
/*
@@ -205,6 +211,16 @@ const InvokeAIUI = ({
};
}, [logo]);
useEffect(() => {
if (onClickGoToModelManager) {
$onClickGoToModelManager.set(onClickGoToModelManager);
}
return () => {
$onClickGoToModelManager.set(undefined);
};
}, [onClickGoToModelManager]);
useEffect(() => {
if (workflowCategories) {
$workflowLibraryCategoriesOptions.set(workflowCategories);

View File

@@ -0,0 +1,3 @@
import { atom } from 'nanostores';
export const $onClickGoToModelManager = atom<(() => void) | undefined>(undefined);

View File

@@ -1,31 +1,35 @@
import type { IconButtonProps } from '@invoke-ai/ui-library';
import { IconButton } from '@invoke-ai/ui-library';
import { useStore } from '@nanostores/react';
import { $onClickGoToModelManager } from 'app/store/nanostores/onClickGoToModelManager';
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
import { selectIsModelsTabDisabled } from 'features/system/store/configSlice';
import { setActiveTab } from 'features/ui/store/uiSlice';
import { memo, useCallback } from 'react';
import { useTranslation } from 'react-i18next';
import { PiGearSixFill } from 'react-icons/pi';
import { PiCubeBold } from 'react-icons/pi';
export const NavigateToModelManagerButton = memo((props: Omit<IconButtonProps, 'aria-label'>) => {
const isModelsTabDisabled = useAppSelector(selectIsModelsTabDisabled);
const onClickGoToModelManager = useStore($onClickGoToModelManager);
const { t } = useTranslation();
const dispatch = useAppDispatch();
const isModelsTabDisabled = useAppSelector(selectIsModelsTabDisabled);
const handleClick = useCallback(() => {
const onClick = useCallback(() => {
dispatch(setActiveTab('models'));
}, [dispatch]);
if (isModelsTabDisabled) {
if (isModelsTabDisabled && !onClickGoToModelManager) {
return null;
}
return (
<IconButton
icon={<PiGearSixFill />}
tooltip={`${t('common.goTo')} ${t('ui.tabs.modelsTab')}`}
aria-label={`${t('common.goTo')} ${t('ui.tabs.modelsTab')}`}
onClick={handleClick}
icon={<PiCubeBold />}
tooltip={`${t('modelManager.manageModels')}`}
aria-label={`${t('modelManager.manageModels')}`}
onClick={onClickGoToModelManager ?? onClick}
size="sm"
variant="ghost"
{...props}