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", "useCanvasBeta": "Use Canvas Beta Layout",
"enableImageDebugging": "Enable Image Debugging", "enableImageDebugging": "Enable Image Debugging",
"useSlidersForAll": "Use Sliders For All Options", "useSlidersForAll": "Use Sliders For All Options",
"autoShowProgress": "Auto Show Progress Images",
"resetWebUI": "Reset Web UI", "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.", "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.", "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 { useFeatureStatus } from 'features/system/hooks/useFeatureStatus';
import { useLogger } from 'app/logging/useLogger'; import { useLogger } from 'app/logging/useLogger';
import ProgressImagePreview from 'features/parameters/components/ProgressImagePreview'; 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 { floatingProgressImageMoved } from 'features/ui/store/uiSlice';
import { restrictToWindowEdges } from '@dnd-kit/modifiers'; // import { restrictToWindowEdges } from '@dnd-kit/modifiers';
const DEFAULT_CONFIG = {}; const DEFAULT_CONFIG = {};
@ -67,76 +67,65 @@ const App = ({ config = DEFAULT_CONFIG, children }: Props) => {
setLoadingOverridden(true); setLoadingOverridden(true);
}, []); }, []);
const handleDragEnd = useCallback(
(event: DragEndEvent) => {
dispatch(
floatingProgressImageMoved({ x: event.delta.x, y: event.delta.y })
);
},
[dispatch]
);
return ( return (
<DndContext onDragEnd={handleDragEnd} modifiers={[restrictToWindowEdges]}> <Grid w="100vw" h="100vh" position="relative" overflow="hidden">
<Grid w="100vw" h="100vh" position="relative" overflow="hidden"> {isLightboxEnabled && <Lightbox />}
{isLightboxEnabled && <Lightbox />} <ImageUploader>
<ImageUploader> <ProgressBar />
<ProgressBar /> <Grid
<Grid gap={4}
p={4}
gridAutoRows="min-content auto"
w={APP_WIDTH}
h={APP_HEIGHT}
>
{children || <SiteHeader />}
<Flex
gap={4} gap={4}
p={4} w={{ base: '100vw', xl: 'full' }}
gridAutoRows="min-content auto" h="full"
w={APP_WIDTH} flexDir={{ base: 'column', xl: 'row' }}
h={APP_HEIGHT}
> >
{children || <SiteHeader />} <InvokeTabs />
<Flex <ImageGalleryPanel />
gap={4} </Flex>
w={{ base: '100vw', xl: 'full' }} </Grid>
h="full" </ImageUploader>
flexDir={{ base: 'column', xl: 'row' }}
>
<InvokeTabs />
<ImageGalleryPanel />
</Flex>
</Grid>
</ImageUploader>
<AnimatePresence> <AnimatePresence>
{!isApplicationReady && !loadingOverridden && ( {!isApplicationReady && !loadingOverridden && (
<motion.div <motion.div
key="loading" key="loading"
initial={{ opacity: 1 }} initial={{ opacity: 1 }}
animate={{ opacity: 1 }} animate={{ opacity: 1 }}
exit={{ opacity: 0 }} exit={{ opacity: 0 }}
transition={{ duration: 0.3 }} transition={{ duration: 0.3 }}
style={{ zIndex: 3 }} style={{ zIndex: 3 }}
> >
<Box position="absolute" top={0} left={0} w="100vw" h="100vh"> <Box position="absolute" top={0} left={0} w="100vw" h="100vh">
<Loading /> <Loading />
</Box> </Box>
<Box <Box
onClick={handleOverrideClicked} onClick={handleOverrideClicked}
position="absolute" position="absolute"
top={0} top={0}
right={0} right={0}
cursor="pointer" cursor="pointer"
w="2rem" w="2rem"
h="2rem" h="2rem"
/> />
</motion.div> </motion.div>
)} )}
</AnimatePresence> </AnimatePresence>
<Portal> <Portal>
<FloatingParametersPanelButtons /> <FloatingParametersPanelButtons />
</Portal> </Portal>
<Portal> <Portal>
<FloatingGalleryButton /> <FloatingGalleryButton />
</Portal> </Portal>
<ProgressImagePreview /> <ProgressImagePreview />
</Grid> </Grid>
</DndContext>
); );
}; };

View File

@ -1,11 +1,4 @@
import React, { import React, { lazy, memo, PropsWithChildren, useEffect } from 'react';
lazy,
memo,
PropsWithChildren,
useCallback,
useEffect,
useState,
} from 'react';
import { Provider } from 'react-redux'; import { Provider } from 'react-redux';
import { PersistGate } from 'redux-persist/integration/react'; import { PersistGate } from 'redux-persist/integration/react';
import { store } from 'app/store/store'; 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 { createSelector } from '@reduxjs/toolkit';
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks'; import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
import { systemSelector } from 'features/system/store/systemSelectors'; import { systemSelector } from 'features/system/store/systemSelectors';
import { memo, useCallback } from 'react'; import { memo } from 'react';
import { FaImage, FaStopwatch } from 'react-icons/fa'; import { FaImage, FaStopwatch } from 'react-icons/fa';
import { uiSelector } from 'features/ui/store/uiSelectors'; import { uiSelector } from 'features/ui/store/uiSelectors';
import IAIIconButton from 'common/components/IAIIconButton'; import IAIIconButton from 'common/components/IAIIconButton';
@ -11,35 +11,49 @@ import { useTranslation } from 'react-i18next';
import { import {
floatingProgressImageMoved, floatingProgressImageMoved,
floatingProgressImageResized, floatingProgressImageResized,
shouldShowProgressImagesToggled, setShouldShowProgressImages,
} from 'features/ui/store/uiSlice'; } from 'features/ui/store/uiSlice';
import { Rnd } from 'react-rnd'; import { Rnd } from 'react-rnd';
import { Rect } from 'features/ui/store/uiTypes'; import { Rect } from 'features/ui/store/uiTypes';
import { isEqual } from 'lodash';
const selector = createSelector([systemSelector, uiSelector], (system, ui) => { const selector = createSelector(
const { progressImage } = system; [systemSelector, uiSelector],
const { floatingProgressImageRect, shouldShowProgressImages } = ui; (system, ui) => {
const { progressImage, isProcessing } = system;
const {
floatingProgressImageRect,
shouldShowProgressImages,
shouldAutoShowProgressImages,
} = ui;
return { const showProgressWindow =
progressImage, shouldAutoShowProgressImages && isProcessing
floatingProgressImageRect, ? true
shouldShowProgressImages, : shouldShowProgressImages;
};
}); return {
progressImage,
floatingProgressImageRect,
showProgressWindow,
};
},
{
memoizeOptions: {
resultEqualityCheck: isEqual,
},
}
);
const ProgressImagePreview = () => { const ProgressImagePreview = () => {
const dispatch = useAppDispatch(); const dispatch = useAppDispatch();
const { progressImage, floatingProgressImageRect, shouldShowProgressImages } = const { showProgressWindow, progressImage, floatingProgressImageRect } =
useAppSelector(selector); useAppSelector(selector);
const { t } = useTranslation(); const { t } = useTranslation();
const toggleProgressImages = useCallback(() => { return showProgressWindow ? (
dispatch(shouldShowProgressImagesToggled());
}, [dispatch]);
return shouldShowProgressImages ? (
<Rnd <Rnd
bounds="window" bounds="window"
minHeight={200} minHeight={200}
@ -113,7 +127,7 @@ const ProgressImagePreview = () => {
</Text> </Text>
</Flex> </Flex>
<IAIIconButton <IAIIconButton
onClick={toggleProgressImages} onClick={() => dispatch(setShouldShowProgressImages(false))}
aria-label={t('ui.hideProgressImages')} aria-label={t('ui.hideProgressImages')}
size="xs" size="xs"
icon={<CloseIcon />} icon={<CloseIcon />}
@ -141,7 +155,6 @@ const ProgressImagePreview = () => {
maxWidth: '100%', maxWidth: '100%',
maxHeight: '100%', maxHeight: '100%',
height: 'auto', height: 'auto',
imageRendering: 'pixelated',
borderRadius: 'base', borderRadius: 'base',
p: 2, p: 2,
}} }}
@ -163,9 +176,13 @@ const ProgressImagePreview = () => {
</Rnd> </Rnd>
) : ( ) : (
<IAIIconButton <IAIIconButton
onClick={toggleProgressImages} onClick={() => dispatch(setShouldShowProgressImages(true))}
tooltip={t('ui.showProgressImages')} tooltip={t('ui.showProgressImages')}
sx={{ position: 'absolute', bottom: 4, insetInlineStart: 4 }} sx={{
position: 'absolute',
bottom: 4,
insetInlineStart: 4,
}}
aria-label={t('ui.showProgressImages')} aria-label={t('ui.showProgressImages')}
icon={<FaStopwatch />} icon={<FaStopwatch />}
/> />

View File

@ -28,6 +28,7 @@ import {
} from 'features/system/store/systemSlice'; } from 'features/system/store/systemSlice';
import { uiSelector } from 'features/ui/store/uiSelectors'; import { uiSelector } from 'features/ui/store/uiSelectors';
import { import {
setShouldAutoShowProgressImages,
setShouldUseCanvasBetaLayout, setShouldUseCanvasBetaLayout,
setShouldUseSliders, setShouldUseSliders,
} from 'features/ui/store/uiSlice'; } from 'features/ui/store/uiSlice';
@ -50,7 +51,11 @@ const selector = createSelector(
shouldLogToConsole, shouldLogToConsole,
} = system; } = system;
const { shouldUseCanvasBetaLayout, shouldUseSliders } = ui; const {
shouldUseCanvasBetaLayout,
shouldUseSliders,
shouldAutoShowProgressImages,
} = ui;
return { return {
shouldConfirmOnDelete, shouldConfirmOnDelete,
@ -58,6 +63,7 @@ const selector = createSelector(
enableImageDebugging, enableImageDebugging,
shouldUseCanvasBetaLayout, shouldUseCanvasBetaLayout,
shouldUseSliders, shouldUseSliders,
shouldAutoShowProgressImages,
consoleLogLevel, consoleLogLevel,
shouldLogToConsole, shouldLogToConsole,
}; };
@ -108,6 +114,7 @@ const SettingsModal = ({ children }: SettingsModalProps) => {
enableImageDebugging, enableImageDebugging,
shouldUseCanvasBetaLayout, shouldUseCanvasBetaLayout,
shouldUseSliders, shouldUseSliders,
shouldAutoShowProgressImages,
consoleLogLevel, consoleLogLevel,
shouldLogToConsole, shouldLogToConsole,
} = useAppSelector(selector); } = useAppSelector(selector);
@ -186,6 +193,13 @@ const SettingsModal = ({ children }: SettingsModalProps) => {
dispatch(setShouldUseSliders(e.target.checked)) dispatch(setShouldUseSliders(e.target.checked))
} }
/> />
<IAISwitch
label={t('settings.autoShowProgress')}
isChecked={shouldAutoShowProgressImages}
onChange={(e: ChangeEvent<HTMLInputElement>) =>
dispatch(setShouldAutoShowProgressImages(e.target.checked))
}
/>
</Flex> </Flex>
<Flex sx={modalSectionStyles}> <Flex sx={modalSectionStyles}>

View File

@ -23,6 +23,7 @@ const initialUIState: UIState = {
openUnifiedCanvasAccordionItems: [], openUnifiedCanvasAccordionItems: [],
floatingProgressImageRect: { x: 0, y: 0, width: 0, height: 0 }, floatingProgressImageRect: { x: 0, y: 0, width: 0, height: 0 },
shouldShowProgressImages: false, shouldShowProgressImages: false,
shouldAutoShowProgressImages: false,
}; };
const initialState: UIState = initialUIState; const initialState: UIState = initialUIState;
@ -122,8 +123,14 @@ export const uiSlice = createSlice({
...action.payload, ...action.payload,
}; };
}, },
shouldShowProgressImagesToggled: (state) => { setShouldShowProgressImages: (state, action: PayloadAction<boolean>) => {
state.shouldShowProgressImages = !state.shouldShowProgressImages; state.shouldShowProgressImages = action.payload;
},
setShouldAutoShowProgressImages: (
state,
action: PayloadAction<boolean>
) => {
state.shouldAutoShowProgressImages = action.payload;
}, },
}, },
}); });
@ -150,7 +157,8 @@ export const {
openAccordionItemsChanged, openAccordionItemsChanged,
floatingProgressImageMoved, floatingProgressImageMoved,
floatingProgressImageResized, floatingProgressImageResized,
shouldShowProgressImagesToggled, setShouldShowProgressImages,
setShouldAutoShowProgressImages,
} = uiSlice.actions; } = uiSlice.actions;
export default uiSlice.reducer; export default uiSlice.reducer;

View File

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