feat(ui): Add auto show progress previews setting

This commit is contained in:
blessedcoolant 2023-05-01 10:45:27 +12:00 committed by psychedelicious
parent 29743a9e02
commit d4b250d509
7 changed files with 123 additions and 100 deletions

View File

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

View File

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

View File

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

View File

@ -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 />}
/>

View File

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

View File

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

View File

@ -31,4 +31,5 @@ export interface UIState {
openUnifiedCanvasAccordionItems: number[];
floatingProgressImageRect: Rect;
shouldShowProgressImages: boolean;
shouldAutoShowProgressImages: boolean;
}