mirror of
https://github.com/invoke-ai/InvokeAI.git
synced 2026-04-23 03:00:31 -04:00
Merge branch 'main' into maryhipp/license-notice-flux-dev
This commit is contained in:
@@ -4,7 +4,7 @@ import { useImageViewer } from 'features/gallery/components/ImageViewer/useImage
|
||||
import { $isMenuOpen } from 'features/stylePresets/store/isMenuOpen';
|
||||
import { setActiveTab } from 'features/ui/store/uiSlice';
|
||||
import { useWorkflowLibraryModal } from 'features/workflowLibrary/store/isWorkflowLibraryModalOpen';
|
||||
import { useCallback } from 'react';
|
||||
import { useCallback, useState } from 'react';
|
||||
|
||||
export type StudioDestination =
|
||||
| 'generation'
|
||||
@@ -16,22 +16,26 @@ export type StudioDestination =
|
||||
|
||||
export const useHandleStudioDestination = () => {
|
||||
const dispatch = useAppDispatch();
|
||||
const imageViewer = useImageViewer();
|
||||
const { open: imageViewerOpen, close: imageViewerClose } = useImageViewer();
|
||||
const [initialized, setInitialized] = useState(false);
|
||||
|
||||
const workflowLibraryModal = useWorkflowLibraryModal();
|
||||
|
||||
const handleStudioDestination = useCallback(
|
||||
(destination: StudioDestination) => {
|
||||
if (initialized) {
|
||||
return;
|
||||
}
|
||||
switch (destination) {
|
||||
case 'generation':
|
||||
dispatch(setActiveTab('canvas'));
|
||||
dispatch(settingsSendToCanvasChanged(false));
|
||||
imageViewer.open();
|
||||
imageViewerOpen();
|
||||
break;
|
||||
case 'canvas':
|
||||
dispatch(setActiveTab('canvas'));
|
||||
dispatch(settingsSendToCanvasChanged(true));
|
||||
imageViewer.close();
|
||||
imageViewerClose();
|
||||
break;
|
||||
case 'workflows':
|
||||
dispatch(setActiveTab('workflows'));
|
||||
@@ -41,7 +45,7 @@ export const useHandleStudioDestination = () => {
|
||||
break;
|
||||
case 'viewAllWorkflows':
|
||||
dispatch(setActiveTab('workflows'));
|
||||
workflowLibraryModal.setFalse();
|
||||
workflowLibraryModal.setTrue();
|
||||
break;
|
||||
case 'viewAllStylePresets':
|
||||
dispatch(setActiveTab('canvas'));
|
||||
@@ -51,8 +55,9 @@ export const useHandleStudioDestination = () => {
|
||||
dispatch(setActiveTab('canvas'));
|
||||
break;
|
||||
}
|
||||
setInitialized(true);
|
||||
},
|
||||
[dispatch, imageViewer, workflowLibraryModal]
|
||||
[dispatch, imageViewerOpen, imageViewerClose, workflowLibraryModal, initialized]
|
||||
);
|
||||
|
||||
return handleStudioDestination;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { Flex, Link, Text } from '@invoke-ai/ui-library';
|
||||
import { Flex, Link, Spacer, Text } from '@invoke-ai/ui-library';
|
||||
import { useStore } from '@nanostores/react';
|
||||
import { $projectName, $projectUrl } from 'app/store/nanostores/projectId';
|
||||
import { memo } from 'react';
|
||||
@@ -9,7 +9,7 @@ export const GalleryHeader = memo(() => {
|
||||
|
||||
if (projectName && projectUrl) {
|
||||
return (
|
||||
<Flex gap={2} w="full" alignItems="center" justifyContent="space-evenly" pe={2}>
|
||||
<Flex gap={2} alignItems="center" justifyContent="space-evenly" pe={2} w="50%">
|
||||
<Text fontSize="md" fontWeight="semibold" noOfLines={1} wordBreak="break-all" w="full" textAlign="center">
|
||||
<Link href={projectUrl}>{projectName}</Link>
|
||||
</Text>
|
||||
@@ -17,7 +17,7 @@ export const GalleryHeader = memo(() => {
|
||||
);
|
||||
}
|
||||
|
||||
return null;
|
||||
return <Spacer />;
|
||||
});
|
||||
|
||||
GalleryHeader.displayName = 'GalleryHeader';
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { Box, Button, Collapse, Divider, Flex, IconButton, Spacer, useDisclosure } from '@invoke-ai/ui-library';
|
||||
import { Box, Button, Collapse, Divider, Flex, IconButton, useDisclosure } from '@invoke-ai/ui-library';
|
||||
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
|
||||
import { useScopeOnFocus } from 'common/hooks/interactionScopes';
|
||||
import { GalleryHeader } from 'features/gallery/components/GalleryHeader';
|
||||
@@ -52,18 +52,19 @@ const GalleryPanelContent = () => {
|
||||
|
||||
return (
|
||||
<Flex ref={ref} position="relative" flexDirection="column" h="full" w="full" tabIndex={-1}>
|
||||
<GalleryHeader />
|
||||
<Flex alignItems="center" w="full">
|
||||
<Button
|
||||
size="sm"
|
||||
variant="ghost"
|
||||
onClick={boardsListPanel.toggle}
|
||||
rightIcon={boardsListPanel.isCollapsed ? <PiCaretDownBold /> : <PiCaretUpBold />}
|
||||
>
|
||||
{boardsListPanel.isCollapsed ? t('boards.viewBoards') : t('boards.hideBoards')}
|
||||
</Button>
|
||||
<Spacer />
|
||||
<Flex h="full">
|
||||
<Flex w="25%">
|
||||
<Button
|
||||
size="sm"
|
||||
variant="ghost"
|
||||
onClick={boardsListPanel.toggle}
|
||||
rightIcon={boardsListPanel.isCollapsed ? <PiCaretDownBold /> : <PiCaretUpBold />}
|
||||
>
|
||||
{boardsListPanel.isCollapsed ? t('boards.viewBoards') : t('boards.hideBoards')}
|
||||
</Button>
|
||||
</Flex>
|
||||
<GalleryHeader />
|
||||
<Flex h="full" w="25%" justifyContent="flex-end">
|
||||
<GallerySettingsPopover />
|
||||
<IconButton
|
||||
size="sm"
|
||||
|
||||
@@ -1,18 +1,18 @@
|
||||
import {
|
||||
Box,
|
||||
Flex,
|
||||
IconButton,
|
||||
Image,
|
||||
Popover,
|
||||
PopoverArrow,
|
||||
PopoverBody,
|
||||
PopoverCloseButton,
|
||||
PopoverContent,
|
||||
PopoverHeader,
|
||||
PopoverTrigger,
|
||||
Text,
|
||||
} from '@invoke-ai/ui-library';
|
||||
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
|
||||
import { shouldShowNotificationIndicatorChanged } from 'features/ui/store/uiSlice';
|
||||
import { shouldShowNotificationChanged } from 'features/ui/store/uiSlice';
|
||||
import InvokeSymbol from 'public/assets/images/invoke-favicon.png';
|
||||
import { useCallback } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
@@ -24,9 +24,9 @@ import { CanvasV2Announcement } from './CanvasV2Announcement';
|
||||
export const Notifications = () => {
|
||||
const { t } = useTranslation();
|
||||
const dispatch = useAppDispatch();
|
||||
const shouldShowNotificationIndicator = useAppSelector((s) => s.ui.shouldShowNotificationIndicator);
|
||||
const shouldShowNotification = useAppSelector((s) => s.ui.shouldShowNotification);
|
||||
const resetIndicator = useCallback(() => {
|
||||
dispatch(shouldShowNotificationIndicatorChanged(false));
|
||||
dispatch(shouldShowNotificationChanged(false));
|
||||
}, [dispatch]);
|
||||
const { data } = useGetAppVersionQuery();
|
||||
|
||||
@@ -35,7 +35,7 @@ export const Notifications = () => {
|
||||
}
|
||||
|
||||
return (
|
||||
<Popover onOpen={resetIndicator} placement="top-start">
|
||||
<Popover onClose={resetIndicator} placement="top-start" autoFocus={false} defaultIsOpen={shouldShowNotification}>
|
||||
<PopoverTrigger>
|
||||
<Flex pos="relative">
|
||||
<IconButton
|
||||
@@ -44,22 +44,12 @@ export const Notifications = () => {
|
||||
icon={<PiLightbulbFilamentBold fontSize={20} />}
|
||||
boxSize={8}
|
||||
/>
|
||||
{shouldShowNotificationIndicator && (
|
||||
<Box
|
||||
pos="absolute"
|
||||
top={0}
|
||||
right="2px"
|
||||
w={2}
|
||||
h={2}
|
||||
backgroundColor="invokeYellow.500"
|
||||
borderRadius="100%"
|
||||
/>
|
||||
)}
|
||||
</Flex>
|
||||
</PopoverTrigger>
|
||||
<PopoverContent p={2}>
|
||||
<PopoverArrow />
|
||||
<PopoverHeader fontSize="md" fontWeight="semibold">
|
||||
<PopoverCloseButton />
|
||||
<PopoverHeader fontSize="md" fontWeight="semibold" pt={5}>
|
||||
<Flex alignItems="center" gap={3}>
|
||||
<Image src={InvokeSymbol} boxSize={6} />
|
||||
{t('whatsNew.whatsNewInInvoke')}
|
||||
|
||||
@@ -13,7 +13,7 @@ const initialUIState: UIState = {
|
||||
shouldShowProgressInViewer: true,
|
||||
accordions: {},
|
||||
expanders: {},
|
||||
shouldShowNotificationIndicator: true,
|
||||
shouldShowNotification: true,
|
||||
};
|
||||
|
||||
export const uiSlice = createSlice({
|
||||
@@ -37,8 +37,8 @@ export const uiSlice = createSlice({
|
||||
const { id, isOpen } = action.payload;
|
||||
state.expanders[id] = isOpen;
|
||||
},
|
||||
shouldShowNotificationIndicatorChanged: (state, action: PayloadAction<boolean>) => {
|
||||
state.shouldShowNotificationIndicator = action.payload;
|
||||
shouldShowNotificationChanged: (state, action: PayloadAction<boolean>) => {
|
||||
state.shouldShowNotification = action.payload;
|
||||
},
|
||||
},
|
||||
extraReducers(builder) {
|
||||
@@ -54,7 +54,7 @@ export const {
|
||||
setShouldShowProgressInViewer,
|
||||
accordionStateChanged,
|
||||
expanderStateChanged,
|
||||
shouldShowNotificationIndicatorChanged,
|
||||
shouldShowNotificationChanged,
|
||||
} = uiSlice.actions;
|
||||
|
||||
export const selectUiSlice = (state: RootState) => state.ui;
|
||||
|
||||
@@ -26,7 +26,7 @@ export interface UIState {
|
||||
*/
|
||||
expanders: Record<string, boolean>;
|
||||
/**
|
||||
* Whether or not to show the user an indicator on notifications icon.
|
||||
* Whether or not to show the user the open notification.
|
||||
*/
|
||||
shouldShowNotificationIndicator: boolean;
|
||||
shouldShowNotification: boolean;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user