mirror of
https://github.com/invoke-ai/InvokeAI
synced 2024-08-30 20:32:17 +00:00
add option for custom star ui (#4530)
Co-authored-by: Mary Hipp <maryhipp@Marys-MacBook-Air.local>
This commit is contained in:
parent
0f0366f1f3
commit
d989c7fa34
@ -18,6 +18,8 @@ import { usePreselectedImage } from '../../features/parameters/hooks/usePreselec
|
|||||||
import AppErrorBoundaryFallback from './AppErrorBoundaryFallback';
|
import AppErrorBoundaryFallback from './AppErrorBoundaryFallback';
|
||||||
import GlobalHotkeys from './GlobalHotkeys';
|
import GlobalHotkeys from './GlobalHotkeys';
|
||||||
import Toaster from './Toaster';
|
import Toaster from './Toaster';
|
||||||
|
import { CustomStarUi } from '../../features/ui/store/uiTypes';
|
||||||
|
import { setCustomStarUi } from '../../features/ui/store/uiSlice';
|
||||||
|
|
||||||
const DEFAULT_CONFIG = {};
|
const DEFAULT_CONFIG = {};
|
||||||
|
|
||||||
@ -28,12 +30,14 @@ interface Props {
|
|||||||
imageName: string;
|
imageName: string;
|
||||||
action: 'sendToImg2Img' | 'sendToCanvas' | 'useAllParameters';
|
action: 'sendToImg2Img' | 'sendToCanvas' | 'useAllParameters';
|
||||||
};
|
};
|
||||||
|
customStarUi?: CustomStarUi;
|
||||||
}
|
}
|
||||||
|
|
||||||
const App = ({
|
const App = ({
|
||||||
config = DEFAULT_CONFIG,
|
config = DEFAULT_CONFIG,
|
||||||
headerComponent,
|
headerComponent,
|
||||||
selectedImage,
|
selectedImage,
|
||||||
|
customStarUi,
|
||||||
}: Props) => {
|
}: Props) => {
|
||||||
const language = useAppSelector(languageSelector);
|
const language = useAppSelector(languageSelector);
|
||||||
|
|
||||||
@ -57,6 +61,12 @@ const App = ({
|
|||||||
}
|
}
|
||||||
}, [dispatch, config, logger]);
|
}, [dispatch, config, logger]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (customStarUi) {
|
||||||
|
dispatch(setCustomStarUi(customStarUi));
|
||||||
|
}
|
||||||
|
}, [customStarUi, dispatch]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
dispatch(appStarted());
|
dispatch(appStarted());
|
||||||
}, [dispatch]);
|
}, [dispatch]);
|
||||||
|
@ -15,6 +15,7 @@ import { socketMiddleware } from 'services/events/middleware';
|
|||||||
import Loading from '../../common/components/Loading/Loading';
|
import Loading from '../../common/components/Loading/Loading';
|
||||||
import '../../i18n';
|
import '../../i18n';
|
||||||
import AppDndContext from '../../features/dnd/components/AppDndContext';
|
import AppDndContext from '../../features/dnd/components/AppDndContext';
|
||||||
|
import { CustomStarUi } from '../../features/ui/store/uiTypes';
|
||||||
|
|
||||||
const App = lazy(() => import('./App'));
|
const App = lazy(() => import('./App'));
|
||||||
const ThemeLocaleProvider = lazy(() => import('./ThemeLocaleProvider'));
|
const ThemeLocaleProvider = lazy(() => import('./ThemeLocaleProvider'));
|
||||||
@ -30,6 +31,7 @@ interface Props extends PropsWithChildren {
|
|||||||
imageName: string;
|
imageName: string;
|
||||||
action: 'sendToImg2Img' | 'sendToCanvas' | 'useAllParameters';
|
action: 'sendToImg2Img' | 'sendToCanvas' | 'useAllParameters';
|
||||||
};
|
};
|
||||||
|
customStarUi?: CustomStarUi;
|
||||||
}
|
}
|
||||||
|
|
||||||
const InvokeAIUI = ({
|
const InvokeAIUI = ({
|
||||||
@ -40,6 +42,7 @@ const InvokeAIUI = ({
|
|||||||
middleware,
|
middleware,
|
||||||
projectId,
|
projectId,
|
||||||
selectedImage,
|
selectedImage,
|
||||||
|
customStarUi,
|
||||||
}: Props) => {
|
}: Props) => {
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
// configure API client token
|
// configure API client token
|
||||||
@ -90,6 +93,7 @@ const InvokeAIUI = ({
|
|||||||
config={config}
|
config={config}
|
||||||
headerComponent={headerComponent}
|
headerComponent={headerComponent}
|
||||||
selectedImage={selectedImage}
|
selectedImage={selectedImage}
|
||||||
|
customStarUi={customStarUi}
|
||||||
/>
|
/>
|
||||||
</AppDndContext>
|
</AppDndContext>
|
||||||
</ThemeLocaleProvider>
|
</ThemeLocaleProvider>
|
||||||
|
@ -12,10 +12,12 @@ import {
|
|||||||
useStarImagesMutation,
|
useStarImagesMutation,
|
||||||
useUnstarImagesMutation,
|
useUnstarImagesMutation,
|
||||||
} from '../../../../services/api/endpoints/images';
|
} from '../../../../services/api/endpoints/images';
|
||||||
|
import { uiSelector } from '../../../ui/store/uiSelectors';
|
||||||
|
|
||||||
const MultipleSelectionMenuItems = () => {
|
const MultipleSelectionMenuItems = () => {
|
||||||
const dispatch = useAppDispatch();
|
const dispatch = useAppDispatch();
|
||||||
const selection = useAppSelector((state) => state.gallery.selection);
|
const selection = useAppSelector((state) => state.gallery.selection);
|
||||||
|
const { customStarUi } = useAppSelector(uiSelector);
|
||||||
|
|
||||||
const [starImages] = useStarImagesMutation();
|
const [starImages] = useStarImagesMutation();
|
||||||
const [unstarImages] = useUnstarImagesMutation();
|
const [unstarImages] = useUnstarImagesMutation();
|
||||||
@ -49,15 +51,18 @@ const MultipleSelectionMenuItems = () => {
|
|||||||
<>
|
<>
|
||||||
{areAllStarred && (
|
{areAllStarred && (
|
||||||
<MenuItem
|
<MenuItem
|
||||||
icon={<MdStarBorder />}
|
icon={customStarUi ? customStarUi.on.icon : <MdStarBorder />}
|
||||||
onClickCapture={handleUnstarSelection}
|
onClickCapture={handleUnstarSelection}
|
||||||
>
|
>
|
||||||
Unstar All
|
{customStarUi ? customStarUi.off.text : `Unstar All`}
|
||||||
</MenuItem>
|
</MenuItem>
|
||||||
)}
|
)}
|
||||||
{(areAllUnstarred || (!areAllStarred && !areAllUnstarred)) && (
|
{(areAllUnstarred || (!areAllStarred && !areAllUnstarred)) && (
|
||||||
<MenuItem icon={<MdStar />} onClickCapture={handleStarSelection}>
|
<MenuItem
|
||||||
Star All
|
icon={customStarUi ? customStarUi.on.icon : <MdStar />}
|
||||||
|
onClickCapture={handleStarSelection}
|
||||||
|
>
|
||||||
|
{customStarUi ? customStarUi.on.text : `Star All`}
|
||||||
</MenuItem>
|
</MenuItem>
|
||||||
)}
|
)}
|
||||||
<MenuItem icon={<FaFolder />} onClickCapture={handleChangeBoard}>
|
<MenuItem icon={<FaFolder />} onClickCapture={handleChangeBoard}>
|
||||||
|
@ -35,6 +35,7 @@ import { ImageDTO } from 'services/api/types';
|
|||||||
import { sentImageToCanvas, sentImageToImg2Img } from '../../store/actions';
|
import { sentImageToCanvas, sentImageToImg2Img } from '../../store/actions';
|
||||||
import { workflowLoadRequested } from 'features/nodes/store/actions';
|
import { workflowLoadRequested } from 'features/nodes/store/actions';
|
||||||
import { configSelector } from '../../../system/store/configSelectors';
|
import { configSelector } from '../../../system/store/configSelectors';
|
||||||
|
import { uiSelector } from '../../../ui/store/uiSelectors';
|
||||||
|
|
||||||
type SingleSelectionMenuItemsProps = {
|
type SingleSelectionMenuItemsProps = {
|
||||||
imageDTO: ImageDTO;
|
imageDTO: ImageDTO;
|
||||||
@ -50,6 +51,7 @@ const SingleSelectionMenuItems = (props: SingleSelectionMenuItemsProps) => {
|
|||||||
|
|
||||||
const isCanvasEnabled = useFeatureStatus('unifiedCanvas').isFeatureEnabled;
|
const isCanvasEnabled = useFeatureStatus('unifiedCanvas').isFeatureEnabled;
|
||||||
const { shouldFetchMetadataFromApi } = useAppSelector(configSelector);
|
const { shouldFetchMetadataFromApi } = useAppSelector(configSelector);
|
||||||
|
const { customStarUi } = useAppSelector(uiSelector);
|
||||||
|
|
||||||
const { metadata, workflow, isLoading } = useGetImageMetadataFromFileQuery(
|
const { metadata, workflow, isLoading } = useGetImageMetadataFromFileQuery(
|
||||||
{ image: imageDTO, shouldFetchMetadataFromApi },
|
{ image: imageDTO, shouldFetchMetadataFromApi },
|
||||||
@ -225,12 +227,18 @@ const SingleSelectionMenuItems = (props: SingleSelectionMenuItemsProps) => {
|
|||||||
Change Board
|
Change Board
|
||||||
</MenuItem>
|
</MenuItem>
|
||||||
{imageDTO.starred ? (
|
{imageDTO.starred ? (
|
||||||
<MenuItem icon={<MdStar />} onClickCapture={handleUnstarImage}>
|
<MenuItem
|
||||||
Unstar Image
|
icon={customStarUi ? customStarUi.off.icon : <MdStar />}
|
||||||
|
onClickCapture={handleUnstarImage}
|
||||||
|
>
|
||||||
|
{customStarUi ? customStarUi.off.text : `Unstar Image`}
|
||||||
</MenuItem>
|
</MenuItem>
|
||||||
) : (
|
) : (
|
||||||
<MenuItem icon={<MdStarBorder />} onClickCapture={handleStarImage}>
|
<MenuItem
|
||||||
Star Image
|
icon={customStarUi ? customStarUi.on.icon : <MdStarBorder />}
|
||||||
|
onClickCapture={handleStarImage}
|
||||||
|
>
|
||||||
|
{customStarUi ? customStarUi.on.text : `Star Image`}
|
||||||
</MenuItem>
|
</MenuItem>
|
||||||
)}
|
)}
|
||||||
<MenuItem
|
<MenuItem
|
||||||
|
@ -18,6 +18,7 @@ import {
|
|||||||
useUnstarImagesMutation,
|
useUnstarImagesMutation,
|
||||||
} from 'services/api/endpoints/images';
|
} from 'services/api/endpoints/images';
|
||||||
import IAIDndImageIcon from '../../../../common/components/IAIDndImageIcon';
|
import IAIDndImageIcon from '../../../../common/components/IAIDndImageIcon';
|
||||||
|
import { uiSelector } from '../../../ui/store/uiSelectors';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
|
|
||||||
interface HoverableImageProps {
|
interface HoverableImageProps {
|
||||||
@ -34,6 +35,8 @@ const GalleryImage = (props: HoverableImageProps) => {
|
|||||||
const { handleClick, isSelected, selection, selectionCount } =
|
const { handleClick, isSelected, selection, selectionCount } =
|
||||||
useMultiselect(imageDTO);
|
useMultiselect(imageDTO);
|
||||||
|
|
||||||
|
const { customStarUi } = useAppSelector(uiSelector);
|
||||||
|
|
||||||
const handleDelete = useCallback(
|
const handleDelete = useCallback(
|
||||||
(e: MouseEvent<HTMLButtonElement>) => {
|
(e: MouseEvent<HTMLButtonElement>) => {
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
@ -91,12 +94,22 @@ const GalleryImage = (props: HoverableImageProps) => {
|
|||||||
|
|
||||||
const starIcon = useMemo(() => {
|
const starIcon = useMemo(() => {
|
||||||
if (imageDTO?.starred) {
|
if (imageDTO?.starred) {
|
||||||
return <MdStar size="20" />;
|
return customStarUi ? customStarUi.on.icon : <MdStar size="20" />;
|
||||||
}
|
}
|
||||||
if (!imageDTO?.starred && isHovered) {
|
if (!imageDTO?.starred && isHovered) {
|
||||||
return <MdStarBorder size="20" />;
|
return customStarUi ? customStarUi.off.icon : <MdStarBorder size="20" />;
|
||||||
}
|
}
|
||||||
}, [imageDTO?.starred, isHovered]);
|
}, [imageDTO?.starred, isHovered, customStarUi]);
|
||||||
|
|
||||||
|
const starTooltip = useMemo(() => {
|
||||||
|
if (imageDTO?.starred) {
|
||||||
|
return customStarUi ? customStarUi.off.text : 'Unstar';
|
||||||
|
}
|
||||||
|
if (!imageDTO?.starred) {
|
||||||
|
return customStarUi ? customStarUi.on.text : 'Star';
|
||||||
|
}
|
||||||
|
return '';
|
||||||
|
}, [imageDTO?.starred, customStarUi]);
|
||||||
|
|
||||||
if (!imageDTO) {
|
if (!imageDTO) {
|
||||||
return <IAIFillSkeleton />;
|
return <IAIFillSkeleton />;
|
||||||
@ -131,7 +144,7 @@ const GalleryImage = (props: HoverableImageProps) => {
|
|||||||
<IAIDndImageIcon
|
<IAIDndImageIcon
|
||||||
onClick={toggleStarredState}
|
onClick={toggleStarredState}
|
||||||
icon={starIcon}
|
icon={starIcon}
|
||||||
tooltip={imageDTO.starred ? 'Unstar' : 'Star'}
|
tooltip={starTooltip}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
{isHovered && shift && (
|
{isHovered && shift && (
|
||||||
|
@ -4,7 +4,7 @@ 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 { setActiveTabReducer } from './extraReducers';
|
||||||
import { InvokeTabName } from './tabMap';
|
import { InvokeTabName } from './tabMap';
|
||||||
import { UIState } from './uiTypes';
|
import { CustomStarUi, UIState } from './uiTypes';
|
||||||
|
|
||||||
export const initialUIState: UIState = {
|
export const initialUIState: UIState = {
|
||||||
activeTab: 0,
|
activeTab: 0,
|
||||||
@ -19,6 +19,7 @@ export const initialUIState: UIState = {
|
|||||||
favoriteSchedulers: [],
|
favoriteSchedulers: [],
|
||||||
globalContextMenuCloseTrigger: 0,
|
globalContextMenuCloseTrigger: 0,
|
||||||
panels: {},
|
panels: {},
|
||||||
|
customStarUi: undefined,
|
||||||
};
|
};
|
||||||
|
|
||||||
export const uiSlice = createSlice({
|
export const uiSlice = createSlice({
|
||||||
@ -70,6 +71,9 @@ export const uiSlice = createSlice({
|
|||||||
) => {
|
) => {
|
||||||
state.panels[action.payload.name] = action.payload.value;
|
state.panels[action.payload.name] = action.payload.value;
|
||||||
},
|
},
|
||||||
|
setCustomStarUi: (state, action: PayloadAction<CustomStarUi>) => {
|
||||||
|
state.customStarUi = action.payload;
|
||||||
|
},
|
||||||
},
|
},
|
||||||
extraReducers(builder) {
|
extraReducers(builder) {
|
||||||
builder.addCase(initialImageChanged, (state) => {
|
builder.addCase(initialImageChanged, (state) => {
|
||||||
@ -91,6 +95,7 @@ export const {
|
|||||||
setShouldAutoChangeDimensions,
|
setShouldAutoChangeDimensions,
|
||||||
contextMenusClosed,
|
contextMenusClosed,
|
||||||
panelsChanged,
|
panelsChanged,
|
||||||
|
setCustomStarUi,
|
||||||
} = uiSlice.actions;
|
} = uiSlice.actions;
|
||||||
|
|
||||||
export default uiSlice.reducer;
|
export default uiSlice.reducer;
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
import { MenuItemProps } from '@chakra-ui/react';
|
||||||
import { SchedulerParam } from 'features/parameters/types/parameterSchemas';
|
import { SchedulerParam } from 'features/parameters/types/parameterSchemas';
|
||||||
|
|
||||||
export type Coordinates = {
|
export type Coordinates = {
|
||||||
@ -12,6 +13,17 @@ export type Dimensions = {
|
|||||||
|
|
||||||
export type Rect = Coordinates & Dimensions;
|
export type Rect = Coordinates & Dimensions;
|
||||||
|
|
||||||
|
export type CustomStarUi = {
|
||||||
|
on: {
|
||||||
|
icon: MenuItemProps['icon'];
|
||||||
|
text: string;
|
||||||
|
};
|
||||||
|
off: {
|
||||||
|
icon: MenuItemProps['icon'];
|
||||||
|
text: string;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
export interface UIState {
|
export interface UIState {
|
||||||
activeTab: number;
|
activeTab: number;
|
||||||
shouldShowImageDetails: boolean;
|
shouldShowImageDetails: boolean;
|
||||||
@ -25,4 +37,5 @@ export interface UIState {
|
|||||||
favoriteSchedulers: SchedulerParam[];
|
favoriteSchedulers: SchedulerParam[];
|
||||||
globalContextMenuCloseTrigger: number;
|
globalContextMenuCloseTrigger: number;
|
||||||
panels: Record<string, string>;
|
panels: Record<string, string>;
|
||||||
|
customStarUi?: CustomStarUi;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user