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:
psychedelicious 2023-09-27 00:06:39 +10:00 committed by GitHub
parent d45c47db81
commit 34c563060f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 26 additions and 43 deletions

View File

@ -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,

View File

@ -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);
}
};

View File

@ -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;
},
} }
); );

View File

@ -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';
}); });
}, },
}); });

View File

@ -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;