mirror of
https://github.com/invoke-ai/InvokeAI
synced 2024-08-30 20:32:17 +00:00
feat(ui): store active tab as name, not index (#4697)
This fixes an issue with tab changing when some tabs are disabled.
This commit is contained in:
parent
d45c47db81
commit
34c563060f
@ -14,7 +14,7 @@ import { stateSelector } from 'app/store/store';
|
|||||||
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
|
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
|
||||||
import ImageGalleryContent from 'features/gallery/components/ImageGalleryContent';
|
import ImageGalleryContent from 'features/gallery/components/ImageGalleryContent';
|
||||||
import NodeEditorPanelGroup from 'features/nodes/components/sidePanel/NodeEditorPanelGroup';
|
import NodeEditorPanelGroup from 'features/nodes/components/sidePanel/NodeEditorPanelGroup';
|
||||||
import { InvokeTabName, tabMap } from 'features/ui/store/tabMap';
|
import { InvokeTabName } from 'features/ui/store/tabMap';
|
||||||
import { setActiveTab } from 'features/ui/store/uiSlice';
|
import { setActiveTab } from 'features/ui/store/uiSlice';
|
||||||
import { ResourceKey } from 'i18next';
|
import { ResourceKey } from 'i18next';
|
||||||
import { isEqual } from 'lodash-es';
|
import { isEqual } from 'lodash-es';
|
||||||
@ -110,7 +110,7 @@ export const NO_GALLERY_TABS: InvokeTabName[] = ['modelManager', 'queue'];
|
|||||||
export const NO_SIDE_PANEL_TABS: InvokeTabName[] = ['modelManager', 'queue'];
|
export const NO_SIDE_PANEL_TABS: InvokeTabName[] = ['modelManager', 'queue'];
|
||||||
|
|
||||||
const InvokeTabs = () => {
|
const InvokeTabs = () => {
|
||||||
const activeTab = useAppSelector(activeTabIndexSelector);
|
const activeTabIndex = useAppSelector(activeTabIndexSelector);
|
||||||
const activeTabName = useAppSelector(activeTabNameSelector);
|
const activeTabName = useAppSelector(activeTabNameSelector);
|
||||||
const enabledTabs = useAppSelector(enabledTabsSelector);
|
const enabledTabs = useAppSelector(enabledTabsSelector);
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
@ -150,13 +150,13 @@ const InvokeTabs = () => {
|
|||||||
|
|
||||||
const handleTabChange = useCallback(
|
const handleTabChange = useCallback(
|
||||||
(index: number) => {
|
(index: number) => {
|
||||||
const activeTabName = tabMap[index];
|
const tab = enabledTabs[index];
|
||||||
if (!activeTabName) {
|
if (!tab) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
dispatch(setActiveTab(activeTabName));
|
dispatch(setActiveTab(tab.id));
|
||||||
},
|
},
|
||||||
[dispatch]
|
[dispatch, enabledTabs]
|
||||||
);
|
);
|
||||||
|
|
||||||
const {
|
const {
|
||||||
@ -216,8 +216,8 @@ const InvokeTabs = () => {
|
|||||||
return (
|
return (
|
||||||
<Tabs
|
<Tabs
|
||||||
variant="appTabs"
|
variant="appTabs"
|
||||||
defaultIndex={activeTab}
|
defaultIndex={activeTabIndex}
|
||||||
index={activeTab}
|
index={activeTabIndex}
|
||||||
onChange={handleTabChange}
|
onChange={handleTabChange}
|
||||||
sx={{
|
sx={{
|
||||||
flexGrow: 1,
|
flexGrow: 1,
|
||||||
|
@ -1,13 +0,0 @@
|
|||||||
import { InvokeTabName, tabMap } from './tabMap';
|
|
||||||
import { UIState } from './uiTypes';
|
|
||||||
|
|
||||||
export const setActiveTabReducer = (
|
|
||||||
state: UIState,
|
|
||||||
newActiveTab: number | InvokeTabName
|
|
||||||
) => {
|
|
||||||
if (typeof newActiveTab === 'number') {
|
|
||||||
state.activeTab = newActiveTab;
|
|
||||||
} else {
|
|
||||||
state.activeTab = tabMap.indexOf(newActiveTab);
|
|
||||||
}
|
|
||||||
};
|
|
@ -1,27 +1,23 @@
|
|||||||
import { createSelector } from '@reduxjs/toolkit';
|
import { createSelector } from '@reduxjs/toolkit';
|
||||||
import { RootState } from 'app/store/store';
|
import { RootState } from 'app/store/store';
|
||||||
import { isEqual } from 'lodash-es';
|
import { isEqual, isString } from 'lodash-es';
|
||||||
|
import { tabMap } from './tabMap';
|
||||||
import { InvokeTabName, tabMap } from './tabMap';
|
|
||||||
import { UIState } from './uiTypes';
|
|
||||||
|
|
||||||
export const activeTabNameSelector = createSelector(
|
export const activeTabNameSelector = createSelector(
|
||||||
(state: RootState) => state.ui,
|
(state: RootState) => state,
|
||||||
(ui: UIState) => tabMap[ui.activeTab] as InvokeTabName,
|
/**
|
||||||
{
|
* Previously `activeTab` was an integer, but now it's a string.
|
||||||
memoizeOptions: {
|
* Default to first tab in case user has integer.
|
||||||
equalityCheck: isEqual,
|
*/
|
||||||
},
|
({ ui }) => (isString(ui.activeTab) ? ui.activeTab : 'txt2img')
|
||||||
}
|
|
||||||
);
|
);
|
||||||
|
|
||||||
export const activeTabIndexSelector = createSelector(
|
export const activeTabIndexSelector = createSelector(
|
||||||
(state: RootState) => state.ui,
|
(state: RootState) => state,
|
||||||
(ui: UIState) => ui.activeTab,
|
({ ui, config }) => {
|
||||||
{
|
const tabs = tabMap.filter((t) => !config.disabledTabs.includes(t));
|
||||||
memoizeOptions: {
|
const idx = tabs.indexOf(ui.activeTab);
|
||||||
equalityCheck: isEqual,
|
return idx === -1 ? 0 : idx;
|
||||||
},
|
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -2,12 +2,11 @@ import type { PayloadAction } from '@reduxjs/toolkit';
|
|||||||
import { createSlice } from '@reduxjs/toolkit';
|
import { createSlice } from '@reduxjs/toolkit';
|
||||||
import { initialImageChanged } from 'features/parameters/store/generationSlice';
|
import { initialImageChanged } from 'features/parameters/store/generationSlice';
|
||||||
import { SchedulerParam } from 'features/parameters/types/parameterSchemas';
|
import { SchedulerParam } from 'features/parameters/types/parameterSchemas';
|
||||||
import { setActiveTabReducer } from './extraReducers';
|
|
||||||
import { InvokeTabName } from './tabMap';
|
import { InvokeTabName } from './tabMap';
|
||||||
import { UIState } from './uiTypes';
|
import { UIState } from './uiTypes';
|
||||||
|
|
||||||
export const initialUIState: UIState = {
|
export const initialUIState: UIState = {
|
||||||
activeTab: 0,
|
activeTab: 'txt2img',
|
||||||
shouldShowImageDetails: false,
|
shouldShowImageDetails: false,
|
||||||
shouldUseCanvasBetaLayout: false,
|
shouldUseCanvasBetaLayout: false,
|
||||||
shouldShowExistingModelsInSearch: false,
|
shouldShowExistingModelsInSearch: false,
|
||||||
@ -26,7 +25,7 @@ export const uiSlice = createSlice({
|
|||||||
initialState: initialUIState,
|
initialState: initialUIState,
|
||||||
reducers: {
|
reducers: {
|
||||||
setActiveTab: (state, action: PayloadAction<InvokeTabName>) => {
|
setActiveTab: (state, action: PayloadAction<InvokeTabName>) => {
|
||||||
setActiveTabReducer(state, action.payload);
|
state.activeTab = action.payload;
|
||||||
},
|
},
|
||||||
setShouldShowImageDetails: (state, action: PayloadAction<boolean>) => {
|
setShouldShowImageDetails: (state, action: PayloadAction<boolean>) => {
|
||||||
state.shouldShowImageDetails = action.payload;
|
state.shouldShowImageDetails = action.payload;
|
||||||
@ -73,7 +72,7 @@ export const uiSlice = createSlice({
|
|||||||
},
|
},
|
||||||
extraReducers(builder) {
|
extraReducers(builder) {
|
||||||
builder.addCase(initialImageChanged, (state) => {
|
builder.addCase(initialImageChanged, (state) => {
|
||||||
setActiveTabReducer(state, 'img2img');
|
state.activeTab = 'img2img';
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
import { SchedulerParam } from 'features/parameters/types/parameterSchemas';
|
import { SchedulerParam } from 'features/parameters/types/parameterSchemas';
|
||||||
|
import { InvokeTabName } from './tabMap';
|
||||||
|
|
||||||
export type Coordinates = {
|
export type Coordinates = {
|
||||||
x: number;
|
x: number;
|
||||||
@ -13,7 +14,7 @@ export type Dimensions = {
|
|||||||
export type Rect = Coordinates & Dimensions;
|
export type Rect = Coordinates & Dimensions;
|
||||||
|
|
||||||
export interface UIState {
|
export interface UIState {
|
||||||
activeTab: number;
|
activeTab: InvokeTabName;
|
||||||
shouldShowImageDetails: boolean;
|
shouldShowImageDetails: boolean;
|
||||||
shouldUseCanvasBetaLayout: boolean;
|
shouldUseCanvasBetaLayout: boolean;
|
||||||
shouldShowExistingModelsInSearch: boolean;
|
shouldShowExistingModelsInSearch: boolean;
|
||||||
|
Loading…
Reference in New Issue
Block a user