mirror of
https://github.com/invoke-ai/InvokeAI
synced 2024-08-30 20:32:17 +00:00
revert(ui): remove floating viewer
There are unresolved platform-specific issues with this component, and its utility is debatable. Should be easy to just revert this commit to add it back in the future if desired.
This commit is contained in:
parent
a826f8f8c5
commit
72ce239592
@ -89,7 +89,6 @@
|
||||
"react-konva": "^18.2.10",
|
||||
"react-redux": "9.1.2",
|
||||
"react-resizable-panels": "^2.0.19",
|
||||
"react-rnd": "^10.4.10",
|
||||
"react-select": "5.8.0",
|
||||
"react-use": "^17.5.0",
|
||||
"react-virtuoso": "^4.7.10",
|
||||
|
@ -122,9 +122,6 @@ dependencies:
|
||||
react-resizable-panels:
|
||||
specifier: ^2.0.19
|
||||
version: 2.0.19(react-dom@18.3.1)(react@18.3.1)
|
||||
react-rnd:
|
||||
specifier: ^10.4.10
|
||||
version: 10.4.10(react-dom@18.3.1)(react@18.3.1)
|
||||
react-select:
|
||||
specifier: 5.8.0
|
||||
version: 5.8.0(@types/react@18.3.1)(react-dom@18.3.1)(react@18.3.1)
|
||||
@ -7208,11 +7205,6 @@ packages:
|
||||
requiresBuild: true
|
||||
dev: true
|
||||
|
||||
/clsx@1.2.1:
|
||||
resolution: {integrity: sha512-EcR6r5a8bj6pu3ycsa/E/cKVGuTgZJZdsyUYHOksG/UHIiKfjxzRxYJpyVBwYaQeOvghal9fcc4PidlgzugAQg==}
|
||||
engines: {node: '>=6'}
|
||||
dev: false
|
||||
|
||||
/color-convert@1.9.3:
|
||||
resolution: {integrity: sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==}
|
||||
dependencies:
|
||||
@ -10814,16 +10806,6 @@ packages:
|
||||
unpipe: 1.0.0
|
||||
dev: true
|
||||
|
||||
/re-resizable@6.9.14(react-dom@18.3.1)(react@18.3.1):
|
||||
resolution: {integrity: sha512-2UbPrpezMr6gkHKNCRA/N6QGGU237SKOZ78yMHId204A/oXWSAREAIuGZNQ9qlrJosewzcsv2CphZH3u7hC6ng==}
|
||||
peerDependencies:
|
||||
react: ^16.13.1 || ^17.0.0 || ^18.0.0
|
||||
react-dom: ^16.13.1 || ^17.0.0 || ^18.0.0
|
||||
dependencies:
|
||||
react: 18.3.1
|
||||
react-dom: 18.3.1(react@18.3.1)
|
||||
dev: false
|
||||
|
||||
/react-clientside-effect@1.2.6(react@18.3.1):
|
||||
resolution: {integrity: sha512-XGGGRQAKY+q25Lz9a/4EPqom7WRjz3z9R2k4jhVKA/puQFH/5Nt27vFZYql4m4NVNdUvX8PS3O7r/Zzm7cjUlg==}
|
||||
peerDependencies:
|
||||
@ -10877,18 +10859,6 @@ packages:
|
||||
react: 18.3.1
|
||||
scheduler: 0.23.2
|
||||
|
||||
/react-draggable@4.4.6(react-dom@18.3.1)(react@18.3.1):
|
||||
resolution: {integrity: sha512-LtY5Xw1zTPqHkVmtM3X8MUOxNDOUhv/khTgBgrUvwaS064bwVvxT+q5El0uUFNx5IEPKXuRejr7UqLwBIg5pdw==}
|
||||
peerDependencies:
|
||||
react: '>= 16.3.0'
|
||||
react-dom: '>= 16.3.0'
|
||||
dependencies:
|
||||
clsx: 1.2.1
|
||||
prop-types: 15.8.1
|
||||
react: 18.3.1
|
||||
react-dom: 18.3.1(react@18.3.1)
|
||||
dev: false
|
||||
|
||||
/react-dropzone@14.2.3(react@18.3.1):
|
||||
resolution: {integrity: sha512-O3om8I+PkFKbxCukfIR3QAGftYXDZfOE2N1mr/7qebQJHs7U+/RSL/9xomJNpRg9kM5h9soQSdf0Gc7OHF5Fug==}
|
||||
engines: {node: '>= 10.13'}
|
||||
@ -11099,19 +11069,6 @@ packages:
|
||||
react-dom: 18.3.1(react@18.3.1)
|
||||
dev: false
|
||||
|
||||
/react-rnd@10.4.10(react-dom@18.3.1)(react@18.3.1):
|
||||
resolution: {integrity: sha512-YjQAgEeSbNUoOXSD9ZBvIiLVizFb+bNhpDk8DbIRHA557NW02CXbwsAeOTpJQnsdhEL+NP2I+Ssrwejqcodtjg==}
|
||||
peerDependencies:
|
||||
react: '>=16.3.0'
|
||||
react-dom: '>=16.3.0'
|
||||
dependencies:
|
||||
re-resizable: 6.9.14(react-dom@18.3.1)(react@18.3.1)
|
||||
react: 18.3.1
|
||||
react-dom: 18.3.1(react@18.3.1)
|
||||
react-draggable: 4.4.6(react-dom@18.3.1)(react@18.3.1)
|
||||
tslib: 2.6.2
|
||||
dev: false
|
||||
|
||||
/react-select@5.7.7(@types/react@18.3.1)(react-dom@18.3.1)(react@18.3.1):
|
||||
resolution: {integrity: sha512-HhashZZJDRlfF/AKj0a0Lnfs3sRdw/46VJIRd8IbB9/Ovr74+ZIwkAdSBjSPXsFMG+u72c5xShqwLSKIJllzqw==}
|
||||
peerDependencies:
|
||||
|
@ -12,7 +12,6 @@ import { useGlobalHotkeys } from 'common/hooks/useGlobalHotkeys';
|
||||
import ChangeBoardModal from 'features/changeBoardModal/components/ChangeBoardModal';
|
||||
import DeleteImageModal from 'features/deleteImageModal/components/DeleteImageModal';
|
||||
import { DynamicPromptsModal } from 'features/dynamicPrompts/components/DynamicPromptsPreviewModal';
|
||||
import { FloatingImageViewer } from 'features/gallery/components/ImageViewer/FloatingImageViewer';
|
||||
import { useStarterModelsToast } from 'features/modelManagerV2/hooks/useStarterModelsToast';
|
||||
import { configChanged } from 'features/system/store/configSlice';
|
||||
import { languageSelector } from 'features/system/store/systemSelectors';
|
||||
@ -97,7 +96,6 @@ const App = ({ config = DEFAULT_CONFIG, selectedImage }: Props) => {
|
||||
<DynamicPromptsModal />
|
||||
<Toaster />
|
||||
<PreselectedImage selectedImage={selectedImage} />
|
||||
<FloatingImageViewer />
|
||||
</ErrorBoundary>
|
||||
);
|
||||
};
|
||||
|
@ -1,190 +0,0 @@
|
||||
import { Flex, IconButton, Spacer, Text, useShiftModifier } from '@invoke-ai/ui-library';
|
||||
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
|
||||
import CurrentImagePreview from 'features/gallery/components/ImageViewer/CurrentImagePreview';
|
||||
import { isFloatingImageViewerOpenChanged } from 'features/gallery/store/gallerySlice';
|
||||
import { memo, useCallback, useLayoutEffect, useRef } from 'react';
|
||||
import { flushSync } from 'react-dom';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { PiHourglassBold, PiXBold } from 'react-icons/pi';
|
||||
import { Rnd } from 'react-rnd';
|
||||
|
||||
const defaultDim = 256;
|
||||
const maxDim = 512;
|
||||
const defaultSize = { width: defaultDim, height: defaultDim + 24 };
|
||||
const maxSize = { width: maxDim, height: maxDim + 24 };
|
||||
const rndDefault = { x: 0, y: 0, ...defaultSize };
|
||||
|
||||
const rndStyles = {
|
||||
zIndex: 11,
|
||||
};
|
||||
|
||||
const enableResizing = {
|
||||
top: false,
|
||||
right: false,
|
||||
bottom: false,
|
||||
left: false,
|
||||
topRight: false,
|
||||
bottomRight: true,
|
||||
bottomLeft: false,
|
||||
topLeft: false,
|
||||
};
|
||||
|
||||
const FloatingImageViewerComponent = memo(() => {
|
||||
const { t } = useTranslation();
|
||||
const dispatch = useAppDispatch();
|
||||
const shift = useShiftModifier();
|
||||
const rndRef = useRef<Rnd>(null);
|
||||
const imagePreviewRef = useRef<HTMLDivElement>(null);
|
||||
const onClose = useCallback(() => {
|
||||
dispatch(isFloatingImageViewerOpenChanged(false));
|
||||
}, [dispatch]);
|
||||
|
||||
const fitToScreen = useCallback(() => {
|
||||
if (!imagePreviewRef.current || !rndRef.current) {
|
||||
return;
|
||||
}
|
||||
const el = imagePreviewRef.current;
|
||||
const rnd = rndRef.current;
|
||||
|
||||
const { top, right, bottom, left, width, height } = el.getBoundingClientRect();
|
||||
const { innerWidth, innerHeight } = window;
|
||||
|
||||
const newPosition = rnd.getDraggablePosition();
|
||||
|
||||
if (top < 0) {
|
||||
newPosition.y = 0;
|
||||
}
|
||||
if (left < 0) {
|
||||
newPosition.x = 0;
|
||||
}
|
||||
if (bottom > innerHeight) {
|
||||
newPosition.y = innerHeight - height;
|
||||
}
|
||||
if (right > innerWidth) {
|
||||
newPosition.x = innerWidth - width;
|
||||
}
|
||||
rnd.updatePosition(newPosition);
|
||||
}, []);
|
||||
|
||||
const onDoubleClick = useCallback(() => {
|
||||
if (!rndRef.current || !imagePreviewRef.current) {
|
||||
return;
|
||||
}
|
||||
const { width, height } = imagePreviewRef.current.getBoundingClientRect();
|
||||
if (width === defaultSize.width && height === defaultSize.height) {
|
||||
rndRef.current.updateSize(maxSize);
|
||||
} else {
|
||||
rndRef.current.updateSize(defaultSize);
|
||||
}
|
||||
flushSync(fitToScreen);
|
||||
}, [fitToScreen]);
|
||||
|
||||
useLayoutEffect(() => {
|
||||
window.addEventListener('resize', fitToScreen);
|
||||
return () => {
|
||||
window.removeEventListener('resize', fitToScreen);
|
||||
};
|
||||
}, [fitToScreen]);
|
||||
|
||||
useLayoutEffect(() => {
|
||||
// Set the initial position
|
||||
if (!imagePreviewRef.current || !rndRef.current) {
|
||||
return;
|
||||
}
|
||||
|
||||
const { width, height } = imagePreviewRef.current.getBoundingClientRect();
|
||||
|
||||
const initialPosition = {
|
||||
// 54 = width of left-hand vertical bar of tab icons
|
||||
// 430 = width of parameters panel
|
||||
x: 54 + 430 / 2 - width / 2,
|
||||
// 16 = just a reasonable bottom padding
|
||||
y: window.innerHeight - height - 16,
|
||||
};
|
||||
|
||||
rndRef.current.updatePosition(initialPosition);
|
||||
}, [fitToScreen]);
|
||||
|
||||
return (
|
||||
<Rnd
|
||||
ref={rndRef}
|
||||
default={rndDefault}
|
||||
bounds="window"
|
||||
lockAspectRatio={shift}
|
||||
minWidth={defaultSize.width}
|
||||
minHeight={defaultSize.height}
|
||||
maxWidth={maxSize.width}
|
||||
maxHeight={maxSize.height}
|
||||
style={rndStyles}
|
||||
enableResizing={enableResizing}
|
||||
>
|
||||
<Flex
|
||||
ref={imagePreviewRef}
|
||||
flexDir="column"
|
||||
bg="base.850"
|
||||
borderRadius="base"
|
||||
w="full"
|
||||
h="full"
|
||||
borderWidth={1}
|
||||
shadow="dark-lg"
|
||||
cursor="move"
|
||||
>
|
||||
<Flex bg="base.800" w="full" p={1} onDoubleClick={onDoubleClick}>
|
||||
<Text fontSize="sm" fontWeight="semibold" color="base.300" ps={2}>
|
||||
{t('common.viewer')}
|
||||
</Text>
|
||||
<Spacer />
|
||||
<IconButton aria-label={t('common.close')} icon={<PiXBold />} size="sm" variant="link" onClick={onClose} />
|
||||
</Flex>
|
||||
<Flex p={2} w="full" h="full">
|
||||
<CurrentImagePreview
|
||||
isDragDisabled={true}
|
||||
isDropDisabled={true}
|
||||
withNextPrevButtons={false}
|
||||
withMetadata={false}
|
||||
alwaysShowProgress
|
||||
/>
|
||||
</Flex>
|
||||
</Flex>
|
||||
</Rnd>
|
||||
);
|
||||
});
|
||||
|
||||
FloatingImageViewerComponent.displayName = 'FloatingImageViewerComponent';
|
||||
|
||||
export const FloatingImageViewer = memo(() => {
|
||||
const isOpen = useAppSelector((s) => s.gallery.isFloatingImageViewerOpen);
|
||||
|
||||
if (!isOpen) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return <FloatingImageViewerComponent />;
|
||||
});
|
||||
|
||||
FloatingImageViewer.displayName = 'FloatingImageViewer';
|
||||
|
||||
export const ToggleFloatingImageViewerButton = memo(() => {
|
||||
const { t } = useTranslation();
|
||||
const dispatch = useAppDispatch();
|
||||
const isOpen = useAppSelector((s) => s.gallery.isFloatingImageViewerOpen);
|
||||
|
||||
const onToggle = useCallback(() => {
|
||||
dispatch(isFloatingImageViewerOpenChanged(!isOpen));
|
||||
}, [dispatch, isOpen]);
|
||||
|
||||
return (
|
||||
<IconButton
|
||||
tooltip={isOpen ? t('gallery.closeFloatingViewer') : t('gallery.openFloatingViewer')}
|
||||
aria-label={isOpen ? t('gallery.closeFloatingViewer') : t('gallery.openFloatingViewer')}
|
||||
icon={<PiHourglassBold fontSize={16} />}
|
||||
size="sm"
|
||||
onClick={onToggle}
|
||||
variant="link"
|
||||
colorScheme={isOpen ? 'invokeBlue' : 'base'}
|
||||
boxSize={8}
|
||||
/>
|
||||
);
|
||||
});
|
||||
|
||||
ToggleFloatingImageViewerButton.displayName = 'ToggleFloatingImageViewerButton';
|
@ -24,7 +24,6 @@ const initialGalleryState: GalleryState = {
|
||||
limit: INITIAL_IMAGE_LIMIT,
|
||||
offset: 0,
|
||||
isImageViewerOpen: false,
|
||||
isFloatingImageViewerOpen: false,
|
||||
};
|
||||
|
||||
export const gallerySlice = createSlice({
|
||||
@ -82,9 +81,6 @@ export const gallerySlice = createSlice({
|
||||
isImageViewerOpenChanged: (state, action: PayloadAction<boolean>) => {
|
||||
state.isImageViewerOpen = action.payload;
|
||||
},
|
||||
isFloatingImageViewerOpenChanged: (state, action: PayloadAction<boolean>) => {
|
||||
state.isFloatingImageViewerOpen = action.payload;
|
||||
},
|
||||
},
|
||||
extraReducers: (builder) => {
|
||||
builder.addCase(setActiveTab, (state) => {
|
||||
@ -129,7 +125,6 @@ export const {
|
||||
moreImagesLoaded,
|
||||
alwaysShowImageSizeBadgeChanged,
|
||||
isImageViewerOpenChanged,
|
||||
isFloatingImageViewerOpenChanged,
|
||||
} = gallerySlice.actions;
|
||||
|
||||
const isAnyBoardDeleted = isAnyOf(
|
||||
|
@ -21,5 +21,4 @@ export type GalleryState = {
|
||||
limit: number;
|
||||
alwaysShowImageSizeBadge: boolean;
|
||||
isImageViewerOpen: boolean;
|
||||
isFloatingImageViewerOpen: boolean;
|
||||
};
|
||||
|
@ -4,7 +4,6 @@ import { createMemoizedSelector } from 'app/store/createMemoizedSelector';
|
||||
import { $customNavComponent } from 'app/store/nanostores/customNavComponent';
|
||||
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
|
||||
import ImageGalleryContent from 'features/gallery/components/ImageGalleryContent';
|
||||
import { ToggleFloatingImageViewerButton } from 'features/gallery/components/ImageViewer/FloatingImageViewer';
|
||||
import { ImageViewer } from 'features/gallery/components/ImageViewer/ImageViewer';
|
||||
import NodeEditorPanelGroup from 'features/nodes/components/sidePanel/NodeEditorPanelGroup';
|
||||
import InvokeAILogoComponent from 'features/system/components/InvokeAILogoComponent';
|
||||
@ -224,7 +223,6 @@ const InvokeTabs = () => {
|
||||
</TabList>
|
||||
<Spacer />
|
||||
<StatusIndicator />
|
||||
<ToggleFloatingImageViewerButton />
|
||||
{customNavComponent ? customNavComponent : <SettingsMenu />}
|
||||
</Flex>
|
||||
<PanelGroup
|
||||
|
Loading…
Reference in New Issue
Block a user