mirror of
https://github.com/invoke-ai/InvokeAI
synced 2025-07-26 13:26:21 +00:00
Add collapsible sections to style preset list with state management
Co-authored-by: kent <kent@invoke.ai>
This commit is contained in:
@ -55,9 +55,7 @@ export const ModelInstallQueue = memo(() => {
|
||||
<Box layerStyle="first" p={3} borderRadius="base" w="full" h="full">
|
||||
<ScrollableContent>
|
||||
<Flex flexDir="column-reverse" gap="2" w="full">
|
||||
{data?.map((model) => (
|
||||
<ModelInstallQueueItem key={model.id} installJob={model} />
|
||||
))}
|
||||
{data?.map((model) => <ModelInstallQueueItem key={model.id} installJob={model} />)}
|
||||
</Flex>
|
||||
</ScrollableContent>
|
||||
</Box>
|
||||
|
@ -1,8 +1,13 @@
|
||||
import { Button, Collapse, Flex, Icon, Text, useDisclosure } from '@invoke-ai/ui-library';
|
||||
import { useAppSelector } from 'app/store/storeHooks';
|
||||
import { Button, Collapse, Flex, Icon, Text } from '@invoke-ai/ui-library';
|
||||
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
|
||||
import { IAINoContentFallback } from 'common/components/IAIImageFallback';
|
||||
import { fixTooltipCloseOnScrollStyles } from 'common/util/fixTooltipCloseOnScrollStyles';
|
||||
import { selectStylePresetSearchTerm } from 'features/stylePresets/store/stylePresetSlice';
|
||||
import {
|
||||
collapsedSectionToggled,
|
||||
selectCollapsedSections,
|
||||
selectStylePresetSearchTerm,
|
||||
} from 'features/stylePresets/store/stylePresetSlice';
|
||||
import { useCallback } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { PiCaretDownBold } from 'react-icons/pi';
|
||||
import type { StylePresetRecordWithImage } from 'services/api/endpoints/stylePresets';
|
||||
@ -11,12 +16,37 @@ import { StylePresetListItem } from './StylePresetListItem';
|
||||
|
||||
export const StylePresetList = ({ title, data }: { title: string; data: StylePresetRecordWithImage[] }) => {
|
||||
const { t } = useTranslation();
|
||||
const { onToggle, isOpen } = useDisclosure({ defaultIsOpen: true });
|
||||
const dispatch = useAppDispatch();
|
||||
const searchTerm = useAppSelector(selectStylePresetSearchTerm);
|
||||
const collapsedSections = useAppSelector(selectCollapsedSections);
|
||||
|
||||
// Determine which section this is based on the title
|
||||
const getSectionKey = useCallback(
|
||||
(title: string) => {
|
||||
if (title === t('stylePresets.myTemplates')) {
|
||||
return 'myTemplates';
|
||||
}
|
||||
if (title === t('stylePresets.sharedTemplates')) {
|
||||
return 'sharedTemplates';
|
||||
}
|
||||
if (title === t('stylePresets.defaultTemplates')) {
|
||||
return 'defaultTemplates';
|
||||
}
|
||||
return 'myTemplates'; // fallback
|
||||
},
|
||||
[t]
|
||||
);
|
||||
|
||||
const sectionKey = getSectionKey(title);
|
||||
const isOpen = !collapsedSections[sectionKey];
|
||||
|
||||
const handleToggle = useCallback(() => {
|
||||
dispatch(collapsedSectionToggled(sectionKey));
|
||||
}, [dispatch, sectionKey]);
|
||||
|
||||
return (
|
||||
<Flex flexDir="column">
|
||||
<Button variant="unstyled" onClick={onToggle}>
|
||||
<Button variant="unstyled" onClick={handleToggle}>
|
||||
<Flex gap={2} alignItems="center">
|
||||
<Icon boxSize={4} as={PiCaretDownBold} transform={isOpen ? undefined : 'rotate(-90deg)'} fill="base.500" />
|
||||
<Text fontSize="sm" fontWeight="semibold" userSelect="none" color="base.500">
|
||||
|
@ -13,6 +13,11 @@ const initialState: StylePresetState = {
|
||||
searchTerm: '',
|
||||
viewMode: false,
|
||||
showPromptPreviews: false,
|
||||
collapsedSections: {
|
||||
myTemplates: false,
|
||||
sharedTemplates: false,
|
||||
defaultTemplates: false,
|
||||
},
|
||||
};
|
||||
|
||||
export const stylePresetSlice = createSlice({
|
||||
@ -31,6 +36,10 @@ export const stylePresetSlice = createSlice({
|
||||
showPromptPreviewsChanged: (state, action: PayloadAction<boolean>) => {
|
||||
state.showPromptPreviews = action.payload;
|
||||
},
|
||||
collapsedSectionToggled: (state, action: PayloadAction<keyof StylePresetState['collapsedSections']>) => {
|
||||
const section = action.payload;
|
||||
state.collapsedSections[section] = !state.collapsedSections[section];
|
||||
},
|
||||
},
|
||||
extraReducers(builder) {
|
||||
builder.addCase(paramsReset, () => {
|
||||
@ -57,8 +66,13 @@ export const stylePresetSlice = createSlice({
|
||||
},
|
||||
});
|
||||
|
||||
export const { activeStylePresetIdChanged, searchTermChanged, viewModeChanged, showPromptPreviewsChanged } =
|
||||
stylePresetSlice.actions;
|
||||
export const {
|
||||
activeStylePresetIdChanged,
|
||||
searchTermChanged,
|
||||
viewModeChanged,
|
||||
showPromptPreviewsChanged,
|
||||
collapsedSectionToggled,
|
||||
} = stylePresetSlice.actions;
|
||||
|
||||
/* eslint-disable-next-line @typescript-eslint/no-explicit-any */
|
||||
const migrateStylePresetState = (state: any): any => {
|
||||
@ -85,6 +99,7 @@ export const selectStylePresetActivePresetId = createStylePresetSelector(
|
||||
export const selectStylePresetViewMode = createStylePresetSelector((stylePreset) => stylePreset.viewMode);
|
||||
export const selectStylePresetSearchTerm = createStylePresetSelector((stylePreset) => stylePreset.searchTerm);
|
||||
export const selectShowPromptPreviews = createStylePresetSelector((stylePreset) => stylePreset.showPromptPreviews);
|
||||
export const selectCollapsedSections = createStylePresetSelector((stylePreset) => stylePreset.collapsedSections);
|
||||
|
||||
/**
|
||||
* Tracks whether or not the style preset menu is open.
|
||||
|
@ -3,4 +3,9 @@ export type StylePresetState = {
|
||||
searchTerm: string;
|
||||
viewMode: boolean;
|
||||
showPromptPreviews: boolean;
|
||||
collapsedSections: {
|
||||
myTemplates: boolean;
|
||||
sharedTemplates: boolean;
|
||||
defaultTemplates: boolean;
|
||||
};
|
||||
};
|
||||
|
Reference in New Issue
Block a user