mirror of
https://github.com/invoke-ai/InvokeAI
synced 2024-08-30 20:32:17 +00:00
feat(ui): Add auto show progress previews setting
This commit is contained in:
parent
29743a9e02
commit
d4b250d509
@ -527,6 +527,7 @@
|
||||
"useCanvasBeta": "Use Canvas Beta Layout",
|
||||
"enableImageDebugging": "Enable Image Debugging",
|
||||
"useSlidersForAll": "Use Sliders For All Options",
|
||||
"autoShowProgress": "Auto Show Progress Images",
|
||||
"resetWebUI": "Reset Web UI",
|
||||
"resetWebUIDesc1": "Resetting the web UI only resets the browser's local cache of your images and remembered settings. It does not delete any images from disk.",
|
||||
"resetWebUIDesc2": "If images aren't showing up in the gallery or something else isn't working, please try resetting before submitting an issue on GitHub.",
|
||||
|
@ -28,9 +28,9 @@ import { configChanged } from 'features/system/store/configSlice';
|
||||
import { useFeatureStatus } from 'features/system/hooks/useFeatureStatus';
|
||||
import { useLogger } from 'app/logging/useLogger';
|
||||
import ProgressImagePreview from 'features/parameters/components/ProgressImagePreview';
|
||||
import { DndContext, DragEndEvent } from '@dnd-kit/core';
|
||||
// import { DndContext, DragEndEvent } from '@dnd-kit/core';
|
||||
import { floatingProgressImageMoved } from 'features/ui/store/uiSlice';
|
||||
import { restrictToWindowEdges } from '@dnd-kit/modifiers';
|
||||
// import { restrictToWindowEdges } from '@dnd-kit/modifiers';
|
||||
|
||||
const DEFAULT_CONFIG = {};
|
||||
|
||||
@ -67,76 +67,65 @@ const App = ({ config = DEFAULT_CONFIG, children }: Props) => {
|
||||
setLoadingOverridden(true);
|
||||
}, []);
|
||||
|
||||
const handleDragEnd = useCallback(
|
||||
(event: DragEndEvent) => {
|
||||
dispatch(
|
||||
floatingProgressImageMoved({ x: event.delta.x, y: event.delta.y })
|
||||
);
|
||||
},
|
||||
[dispatch]
|
||||
);
|
||||
|
||||
return (
|
||||
<DndContext onDragEnd={handleDragEnd} modifiers={[restrictToWindowEdges]}>
|
||||
<Grid w="100vw" h="100vh" position="relative" overflow="hidden">
|
||||
{isLightboxEnabled && <Lightbox />}
|
||||
<ImageUploader>
|
||||
<ProgressBar />
|
||||
<Grid
|
||||
<Grid w="100vw" h="100vh" position="relative" overflow="hidden">
|
||||
{isLightboxEnabled && <Lightbox />}
|
||||
<ImageUploader>
|
||||
<ProgressBar />
|
||||
<Grid
|
||||
gap={4}
|
||||
p={4}
|
||||
gridAutoRows="min-content auto"
|
||||
w={APP_WIDTH}
|
||||
h={APP_HEIGHT}
|
||||
>
|
||||
{children || <SiteHeader />}
|
||||
<Flex
|
||||
gap={4}
|
||||
p={4}
|
||||
gridAutoRows="min-content auto"
|
||||
w={APP_WIDTH}
|
||||
h={APP_HEIGHT}
|
||||
w={{ base: '100vw', xl: 'full' }}
|
||||
h="full"
|
||||
flexDir={{ base: 'column', xl: 'row' }}
|
||||
>
|
||||
{children || <SiteHeader />}
|
||||
<Flex
|
||||
gap={4}
|
||||
w={{ base: '100vw', xl: 'full' }}
|
||||
h="full"
|
||||
flexDir={{ base: 'column', xl: 'row' }}
|
||||
>
|
||||
<InvokeTabs />
|
||||
<ImageGalleryPanel />
|
||||
</Flex>
|
||||
</Grid>
|
||||
</ImageUploader>
|
||||
<InvokeTabs />
|
||||
<ImageGalleryPanel />
|
||||
</Flex>
|
||||
</Grid>
|
||||
</ImageUploader>
|
||||
|
||||
<AnimatePresence>
|
||||
{!isApplicationReady && !loadingOverridden && (
|
||||
<motion.div
|
||||
key="loading"
|
||||
initial={{ opacity: 1 }}
|
||||
animate={{ opacity: 1 }}
|
||||
exit={{ opacity: 0 }}
|
||||
transition={{ duration: 0.3 }}
|
||||
style={{ zIndex: 3 }}
|
||||
>
|
||||
<Box position="absolute" top={0} left={0} w="100vw" h="100vh">
|
||||
<Loading />
|
||||
</Box>
|
||||
<Box
|
||||
onClick={handleOverrideClicked}
|
||||
position="absolute"
|
||||
top={0}
|
||||
right={0}
|
||||
cursor="pointer"
|
||||
w="2rem"
|
||||
h="2rem"
|
||||
/>
|
||||
</motion.div>
|
||||
)}
|
||||
</AnimatePresence>
|
||||
<AnimatePresence>
|
||||
{!isApplicationReady && !loadingOverridden && (
|
||||
<motion.div
|
||||
key="loading"
|
||||
initial={{ opacity: 1 }}
|
||||
animate={{ opacity: 1 }}
|
||||
exit={{ opacity: 0 }}
|
||||
transition={{ duration: 0.3 }}
|
||||
style={{ zIndex: 3 }}
|
||||
>
|
||||
<Box position="absolute" top={0} left={0} w="100vw" h="100vh">
|
||||
<Loading />
|
||||
</Box>
|
||||
<Box
|
||||
onClick={handleOverrideClicked}
|
||||
position="absolute"
|
||||
top={0}
|
||||
right={0}
|
||||
cursor="pointer"
|
||||
w="2rem"
|
||||
h="2rem"
|
||||
/>
|
||||
</motion.div>
|
||||
)}
|
||||
</AnimatePresence>
|
||||
|
||||
<Portal>
|
||||
<FloatingParametersPanelButtons />
|
||||
</Portal>
|
||||
<Portal>
|
||||
<FloatingGalleryButton />
|
||||
</Portal>
|
||||
<ProgressImagePreview />
|
||||
</Grid>
|
||||
</DndContext>
|
||||
<Portal>
|
||||
<FloatingParametersPanelButtons />
|
||||
</Portal>
|
||||
<Portal>
|
||||
<FloatingGalleryButton />
|
||||
</Portal>
|
||||
<ProgressImagePreview />
|
||||
</Grid>
|
||||
);
|
||||
};
|
||||
|
||||
|
@ -1,11 +1,4 @@
|
||||
import React, {
|
||||
lazy,
|
||||
memo,
|
||||
PropsWithChildren,
|
||||
useCallback,
|
||||
useEffect,
|
||||
useState,
|
||||
} from 'react';
|
||||
import React, { lazy, memo, PropsWithChildren, useEffect } from 'react';
|
||||
import { Provider } from 'react-redux';
|
||||
import { PersistGate } from 'redux-persist/integration/react';
|
||||
import { store } from 'app/store/store';
|
||||
|
@ -2,7 +2,7 @@ import { Flex, Icon, Image, Text } from '@chakra-ui/react';
|
||||
import { createSelector } from '@reduxjs/toolkit';
|
||||
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
|
||||
import { systemSelector } from 'features/system/store/systemSelectors';
|
||||
import { memo, useCallback } from 'react';
|
||||
import { memo } from 'react';
|
||||
import { FaImage, FaStopwatch } from 'react-icons/fa';
|
||||
import { uiSelector } from 'features/ui/store/uiSelectors';
|
||||
import IAIIconButton from 'common/components/IAIIconButton';
|
||||
@ -11,35 +11,49 @@ import { useTranslation } from 'react-i18next';
|
||||
import {
|
||||
floatingProgressImageMoved,
|
||||
floatingProgressImageResized,
|
||||
shouldShowProgressImagesToggled,
|
||||
setShouldShowProgressImages,
|
||||
} from 'features/ui/store/uiSlice';
|
||||
import { Rnd } from 'react-rnd';
|
||||
import { Rect } from 'features/ui/store/uiTypes';
|
||||
import { isEqual } from 'lodash';
|
||||
|
||||
const selector = createSelector([systemSelector, uiSelector], (system, ui) => {
|
||||
const { progressImage } = system;
|
||||
const { floatingProgressImageRect, shouldShowProgressImages } = ui;
|
||||
const selector = createSelector(
|
||||
[systemSelector, uiSelector],
|
||||
(system, ui) => {
|
||||
const { progressImage, isProcessing } = system;
|
||||
const {
|
||||
floatingProgressImageRect,
|
||||
shouldShowProgressImages,
|
||||
shouldAutoShowProgressImages,
|
||||
} = ui;
|
||||
|
||||
return {
|
||||
progressImage,
|
||||
floatingProgressImageRect,
|
||||
shouldShowProgressImages,
|
||||
};
|
||||
});
|
||||
const showProgressWindow =
|
||||
shouldAutoShowProgressImages && isProcessing
|
||||
? true
|
||||
: shouldShowProgressImages;
|
||||
|
||||
return {
|
||||
progressImage,
|
||||
floatingProgressImageRect,
|
||||
showProgressWindow,
|
||||
};
|
||||
},
|
||||
{
|
||||
memoizeOptions: {
|
||||
resultEqualityCheck: isEqual,
|
||||
},
|
||||
}
|
||||
);
|
||||
|
||||
const ProgressImagePreview = () => {
|
||||
const dispatch = useAppDispatch();
|
||||
|
||||
const { progressImage, floatingProgressImageRect, shouldShowProgressImages } =
|
||||
const { showProgressWindow, progressImage, floatingProgressImageRect } =
|
||||
useAppSelector(selector);
|
||||
|
||||
const { t } = useTranslation();
|
||||
|
||||
const toggleProgressImages = useCallback(() => {
|
||||
dispatch(shouldShowProgressImagesToggled());
|
||||
}, [dispatch]);
|
||||
|
||||
return shouldShowProgressImages ? (
|
||||
return showProgressWindow ? (
|
||||
<Rnd
|
||||
bounds="window"
|
||||
minHeight={200}
|
||||
@ -113,7 +127,7 @@ const ProgressImagePreview = () => {
|
||||
</Text>
|
||||
</Flex>
|
||||
<IAIIconButton
|
||||
onClick={toggleProgressImages}
|
||||
onClick={() => dispatch(setShouldShowProgressImages(false))}
|
||||
aria-label={t('ui.hideProgressImages')}
|
||||
size="xs"
|
||||
icon={<CloseIcon />}
|
||||
@ -141,7 +155,6 @@ const ProgressImagePreview = () => {
|
||||
maxWidth: '100%',
|
||||
maxHeight: '100%',
|
||||
height: 'auto',
|
||||
imageRendering: 'pixelated',
|
||||
borderRadius: 'base',
|
||||
p: 2,
|
||||
}}
|
||||
@ -163,9 +176,13 @@ const ProgressImagePreview = () => {
|
||||
</Rnd>
|
||||
) : (
|
||||
<IAIIconButton
|
||||
onClick={toggleProgressImages}
|
||||
onClick={() => dispatch(setShouldShowProgressImages(true))}
|
||||
tooltip={t('ui.showProgressImages')}
|
||||
sx={{ position: 'absolute', bottom: 4, insetInlineStart: 4 }}
|
||||
sx={{
|
||||
position: 'absolute',
|
||||
bottom: 4,
|
||||
insetInlineStart: 4,
|
||||
}}
|
||||
aria-label={t('ui.showProgressImages')}
|
||||
icon={<FaStopwatch />}
|
||||
/>
|
||||
|
@ -28,6 +28,7 @@ import {
|
||||
} from 'features/system/store/systemSlice';
|
||||
import { uiSelector } from 'features/ui/store/uiSelectors';
|
||||
import {
|
||||
setShouldAutoShowProgressImages,
|
||||
setShouldUseCanvasBetaLayout,
|
||||
setShouldUseSliders,
|
||||
} from 'features/ui/store/uiSlice';
|
||||
@ -50,7 +51,11 @@ const selector = createSelector(
|
||||
shouldLogToConsole,
|
||||
} = system;
|
||||
|
||||
const { shouldUseCanvasBetaLayout, shouldUseSliders } = ui;
|
||||
const {
|
||||
shouldUseCanvasBetaLayout,
|
||||
shouldUseSliders,
|
||||
shouldAutoShowProgressImages,
|
||||
} = ui;
|
||||
|
||||
return {
|
||||
shouldConfirmOnDelete,
|
||||
@ -58,6 +63,7 @@ const selector = createSelector(
|
||||
enableImageDebugging,
|
||||
shouldUseCanvasBetaLayout,
|
||||
shouldUseSliders,
|
||||
shouldAutoShowProgressImages,
|
||||
consoleLogLevel,
|
||||
shouldLogToConsole,
|
||||
};
|
||||
@ -108,6 +114,7 @@ const SettingsModal = ({ children }: SettingsModalProps) => {
|
||||
enableImageDebugging,
|
||||
shouldUseCanvasBetaLayout,
|
||||
shouldUseSliders,
|
||||
shouldAutoShowProgressImages,
|
||||
consoleLogLevel,
|
||||
shouldLogToConsole,
|
||||
} = useAppSelector(selector);
|
||||
@ -186,6 +193,13 @@ const SettingsModal = ({ children }: SettingsModalProps) => {
|
||||
dispatch(setShouldUseSliders(e.target.checked))
|
||||
}
|
||||
/>
|
||||
<IAISwitch
|
||||
label={t('settings.autoShowProgress')}
|
||||
isChecked={shouldAutoShowProgressImages}
|
||||
onChange={(e: ChangeEvent<HTMLInputElement>) =>
|
||||
dispatch(setShouldAutoShowProgressImages(e.target.checked))
|
||||
}
|
||||
/>
|
||||
</Flex>
|
||||
|
||||
<Flex sx={modalSectionStyles}>
|
||||
|
@ -23,6 +23,7 @@ const initialUIState: UIState = {
|
||||
openUnifiedCanvasAccordionItems: [],
|
||||
floatingProgressImageRect: { x: 0, y: 0, width: 0, height: 0 },
|
||||
shouldShowProgressImages: false,
|
||||
shouldAutoShowProgressImages: false,
|
||||
};
|
||||
|
||||
const initialState: UIState = initialUIState;
|
||||
@ -122,8 +123,14 @@ export const uiSlice = createSlice({
|
||||
...action.payload,
|
||||
};
|
||||
},
|
||||
shouldShowProgressImagesToggled: (state) => {
|
||||
state.shouldShowProgressImages = !state.shouldShowProgressImages;
|
||||
setShouldShowProgressImages: (state, action: PayloadAction<boolean>) => {
|
||||
state.shouldShowProgressImages = action.payload;
|
||||
},
|
||||
setShouldAutoShowProgressImages: (
|
||||
state,
|
||||
action: PayloadAction<boolean>
|
||||
) => {
|
||||
state.shouldAutoShowProgressImages = action.payload;
|
||||
},
|
||||
},
|
||||
});
|
||||
@ -150,7 +157,8 @@ export const {
|
||||
openAccordionItemsChanged,
|
||||
floatingProgressImageMoved,
|
||||
floatingProgressImageResized,
|
||||
shouldShowProgressImagesToggled,
|
||||
setShouldShowProgressImages,
|
||||
setShouldAutoShowProgressImages,
|
||||
} = uiSlice.actions;
|
||||
|
||||
export default uiSlice.reducer;
|
||||
|
@ -31,4 +31,5 @@ export interface UIState {
|
||||
openUnifiedCanvasAccordionItems: number[];
|
||||
floatingProgressImageRect: Rect;
|
||||
shouldShowProgressImages: boolean;
|
||||
shouldAutoShowProgressImages: boolean;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user