feat(ui): update floating buttons & other incidental UI tweaks

This commit is contained in:
psychedelicious
2023-09-19 21:30:41 +10:00
parent 143d7e03ef
commit f051daea4f
17 changed files with 129 additions and 80 deletions

View File

@@ -948,6 +948,7 @@
"seamLowThreshold": "Low",
"seed": "Seed",
"seedWeights": "Seed Weights",
"imageActions": "Image Actions",
"sendTo": "Send to",
"sendToImg2Img": "Send to Image to Image",
"sendToUnifiedCanvas": "Send To Unified Canvas",
@@ -960,7 +961,7 @@
"tileSize": "Tile Size",
"toggleLoopback": "Toggle Loopback",
"type": "Type",
"upscale": "Upscale",
"upscale": "Upscale (Shift + U)",
"upscaleImage": "Upscale Image",
"upscaling": "Upscaling",
"useAll": "Use All",

View File

@@ -1,6 +1,8 @@
import { createSelector } from '@reduxjs/toolkit';
import { stateSelector } from 'app/store/store';
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
import { useQueueBack } from 'features/queue/hooks/useQueueBack';
import { useQueueFront } from 'features/queue/hooks/useQueueFront';
import {
ctrlKeyPressed,
metaKeyPressed,
@@ -33,6 +35,39 @@ const globalHotkeysSelector = createSelector(
const GlobalHotkeys: React.FC = () => {
const dispatch = useAppDispatch();
const { shift, ctrl, meta } = useAppSelector(globalHotkeysSelector);
const {
queueBack,
isDisabled: isDisabledQueueBack,
isLoading: isLoadingQueueBack,
} = useQueueBack();
useHotkeys(
['ctrl+enter', 'meta+enter'],
queueBack,
{
enabled: () => !isDisabledQueueBack && !isLoadingQueueBack,
preventDefault: true,
enableOnFormTags: ['input', 'textarea', 'select'],
},
[queueBack, isDisabledQueueBack, isLoadingQueueBack]
);
const {
queueFront,
isDisabled: isDisabledQueueFront,
isLoading: isLoadingQueueFront,
} = useQueueFront();
useHotkeys(
['ctrl+shift+enter', 'meta+shift+enter'],
queueFront,
{
enabled: () => !isDisabledQueueFront && !isLoadingQueueFront,
preventDefault: true,
enableOnFormTags: ['input', 'textarea', 'select'],
},
[queueFront, isDisabledQueueFront, isLoadingQueueFront]
);
useHotkeys(
'*',

View File

@@ -37,9 +37,8 @@ import {
FaHourglassHalf,
FaQuoteRight,
FaSeedling,
FaShareAlt,
} from 'react-icons/fa';
import { MdDeviceHub } from 'react-icons/md';
import { FaCircleNodes, FaEllipsis } from 'react-icons/fa6';
import {
useGetImageDTOQuery,
useGetImageMetadataFromFileQuery,
@@ -255,10 +254,10 @@ const CurrentImageButtons = (props: CurrentImageButtonsProps) => {
<Menu>
<MenuButton
as={IAIIconButton}
aria-label={`${t('parameters.sendTo')}...`}
tooltip={`${t('parameters.sendTo')}...`}
aria-label={t('parameters.imageActions')}
tooltip={t('parameters.imageActions')}
isDisabled={!imageDTO}
icon={<FaShareAlt />}
icon={<FaEllipsis />}
/>
<MenuList motionProps={menuListMotionProps}>
{imageDTO && <SingleSelectionMenuItems imageDTO={imageDTO} />}
@@ -269,7 +268,7 @@ const CurrentImageButtons = (props: CurrentImageButtonsProps) => {
<ButtonGroup isAttached={true} isDisabled={shouldDisableToolbarButtons}>
<IAIIconButton
isLoading={isLoading}
icon={<MdDeviceHub />}
icon={<FaCircleNodes />}
tooltip={`${t('nodes.loadWorkflow')} (W)`}
aria-label={`${t('nodes.loadWorkflow')} (W)`}
isDisabled={!workflow}

View File

@@ -16,6 +16,7 @@ import { useFeatureStatus } from 'features/system/hooks/useFeatureStatus';
import { useCopyImageToClipboard } from 'features/ui/hooks/useCopyImageToClipboard';
import { setActiveTab } from 'features/ui/store/uiSlice';
import { memo, useCallback } from 'react';
import { flushSync } from 'react-dom';
import { useTranslation } from 'react-i18next';
import {
FaAsterisk,
@@ -28,7 +29,8 @@ import {
FaShare,
FaTrash,
} from 'react-icons/fa';
import { MdDeviceHub, MdStar, MdStarBorder } from 'react-icons/md';
import { FaCircleNodes } from 'react-icons/fa6';
import { MdStar, MdStarBorder } from 'react-icons/md';
import {
useGetImageMetadataFromFileQuery,
useStarImagesMutation,
@@ -37,7 +39,6 @@ import {
import { ImageDTO } from 'services/api/types';
import { configSelector } from '../../../system/store/configSelectors';
import { sentImageToCanvas, sentImageToImg2Img } from '../../store/actions';
import { flushSync } from 'react-dom';
type SingleSelectionMenuItemsProps = {
imageDTO: ImageDTO;
@@ -180,7 +181,7 @@ const SingleSelectionMenuItems = (props: SingleSelectionMenuItemsProps) => {
{t('parameters.downloadImage')}
</MenuItem>
<MenuItem
icon={isLoading ? <SpinnerIcon /> : <MdDeviceHub />}
icon={isLoading ? <SpinnerIcon /> : <FaCircleNodes />}
onClickCapture={handleLoadWorkflow}
isDisabled={isLoading || !workflow}
>

View File

@@ -7,7 +7,7 @@ import IAIPopover from 'common/components/IAIPopover';
import { useIsQueueMutationInProgress } from 'features/queue/hooks/useIsQueueMutationInProgress';
import { memo, useCallback } from 'react';
import { useTranslation } from 'react-i18next';
import { FaExpandArrowsAlt } from 'react-icons/fa';
import { FaExpand } from 'react-icons/fa';
import { ImageDTO } from 'services/api/types';
import ParamESRGANModel from './ParamRealESRGANModel';
@@ -34,8 +34,9 @@ const ParamUpscalePopover = (props: Props) => {
onClose={onClose}
triggerComponent={
<IAIIconButton
tooltip={t('parameters.upscale')}
onClick={onOpen}
icon={<FaExpandArrowsAlt />}
icon={<FaExpand />}
aria-label={t('parameters.upscale')}
/>
}

View File

@@ -3,12 +3,14 @@ import { useTranslation } from 'react-i18next';
import { FaTimes } from 'react-icons/fa';
import { useCancelCurrentQueueItem } from '../hooks/useCancelCurrentQueueItem';
import QueueButton from './common/QueueButton';
import { ChakraProps } from '@chakra-ui/react';
type Props = {
asIconButton?: boolean;
sx?: ChakraProps['sx'];
};
const CancelCurrentQueueItemButton = ({ asIconButton }: Props) => {
const CancelCurrentQueueItemButton = ({ asIconButton, sx }: Props) => {
const { t } = useTranslation();
const { cancelQueueItem, isLoading, currentQueueItemId } =
useCancelCurrentQueueItem();
@@ -23,6 +25,7 @@ const CancelCurrentQueueItemButton = ({ asIconButton }: Props) => {
icon={<FaTimes />}
onClick={cancelQueueItem}
colorScheme="error"
sx={sx}
/>
);
};

View File

@@ -3,12 +3,14 @@ import { useTranslation } from 'react-i18next';
import { FaTrash } from 'react-icons/fa';
import { useClearQueue } from '../hooks/useClearQueue';
import QueueButton from './common/QueueButton';
import { ChakraProps } from '@chakra-ui/react';
type Props = {
asIconButton?: boolean;
sx?: ChakraProps['sx'];
};
const ClearQueueButton = ({ asIconButton }: Props) => {
const ClearQueueButton = ({ asIconButton, sx }: Props) => {
const { t } = useTranslation();
const { clearQueue, isLoading, queueStatus } = useClearQueue();
@@ -22,6 +24,7 @@ const ClearQueueButton = ({ asIconButton }: Props) => {
icon={<FaTrash />}
onClick={clearQueue}
colorScheme="error"
sx={sx}
/>
);
};

View File

@@ -1,24 +1,31 @@
import IAIButton from 'common/components/IAIButton';
import { memo } from 'react';
import { useTranslation } from 'react-i18next';
import { FaPlus } from 'react-icons/fa';
import { useQueueBack } from '../hooks/useQueueBack';
import EnqueueButtonTooltip from './QueueButtonTooltip';
import QueueButton from './common/QueueButton';
import { ChakraProps } from '@chakra-ui/react';
const QueueBackButton = () => {
type Props = {
asIconButton?: boolean;
sx?: ChakraProps['sx'];
};
const QueueBackButton = ({ asIconButton, sx }: Props) => {
const { t } = useTranslation();
const { queueBack, isLoading, isDisabled } = useQueueBack();
return (
<IAIButton
<QueueButton
asIconButton={asIconButton}
colorScheme="accent"
label={t('queue.queueBack')}
isDisabled={isDisabled}
isLoading={isLoading}
colorScheme="accent"
onClick={queueBack}
tooltip={<EnqueueButtonTooltip />}
flexGrow={3}
minW={44}
>
{t('queue.queueBack')}
</IAIButton>
icon={<FaPlus />}
sx={sx}
/>
);
};

View File

@@ -28,7 +28,7 @@ const QueueControls = () => {
<Flex gap={2} w="full">
<ButtonGroup isAttached flexGrow={2}>
<QueueBackButton />
<QueueFrontButton />
<QueueFrontButton asIconButton />
<CancelCurrentQueueItemButton asIconButton />
</ButtonGroup>
<ButtonGroup isAttached>

View File

@@ -1,22 +1,30 @@
import IAIIconButton from 'common/components/IAIIconButton';
import { memo } from 'react';
import { useTranslation } from 'react-i18next';
import { FaBoltLightning } from 'react-icons/fa6';
import { useQueueFront } from '../hooks/useQueueFront';
import EnqueueButtonTooltip from './QueueButtonTooltip';
import QueueButton from './common/QueueButton';
import { ChakraProps } from '@chakra-ui/react';
const QueueFrontButton = () => {
type Props = {
asIconButton?: boolean;
sx?: ChakraProps['sx'];
};
const QueueFrontButton = ({ asIconButton, sx }: Props) => {
const { t } = useTranslation();
const { queueFront, isLoading, isDisabled } = useQueueFront();
return (
<IAIIconButton
<QueueButton
asIconButton={asIconButton}
colorScheme="base"
aria-label={t('queue.queueFront')}
label={t('queue.queueFront')}
isDisabled={isDisabled}
isLoading={isLoading}
onClick={queueFront}
tooltip={<EnqueueButtonTooltip prepend />}
icon={<FaBoltLightning />}
sx={sx}
/>
);
};

View File

@@ -1,11 +1,11 @@
import { ThemeTypings } from '@chakra-ui/react';
import { ChakraProps, ThemeTypings } from '@chakra-ui/react';
import IAIButton from 'common/components/IAIButton';
import IAIIconButton from 'common/components/IAIIconButton';
import { ReactElement, memo } from 'react';
import { ReactElement, ReactNode, memo } from 'react';
type Props = {
label: string;
tooltip: string;
tooltip: ReactNode;
icon: ReactElement;
onClick: () => void;
isDisabled?: boolean;
@@ -13,6 +13,7 @@ type Props = {
asIconButton?: boolean;
isLoading?: boolean;
loadingText?: string;
sx?: ChakraProps['sx'];
};
const QueueButton = ({
@@ -25,6 +26,7 @@ const QueueButton = ({
asIconButton,
isLoading,
loadingText,
sx,
}: Props) => {
if (asIconButton) {
return (
@@ -36,6 +38,7 @@ const QueueButton = ({
isDisabled={isDisabled}
colorScheme={colorScheme}
isLoading={isLoading}
sx={sx}
/>
);
}
@@ -51,6 +54,7 @@ const QueueButton = ({
isLoading={isLoading}
loadingText={loadingText ?? label}
flexGrow={1}
sx={sx}
>
{label}
</IAIButton>

View File

@@ -4,7 +4,6 @@ import { useIsReadyToEnqueue } from 'common/hooks/useIsReadyToEnqueue';
import { clampSymmetrySteps } from 'features/parameters/store/generationSlice';
import { activeTabNameSelector } from 'features/ui/store/uiSelectors';
import { useCallback, useMemo } from 'react';
import { useHotkeys } from 'react-hotkeys-hook';
import { useEnqueueBatchMutation } from 'services/api/endpoints/queue';
export const useQueueBack = () => {
@@ -23,16 +22,5 @@ export const useQueueBack = () => {
dispatch(enqueueRequested({ tabName, prepend: false }));
}, [dispatch, isDisabled, tabName]);
useHotkeys(
['ctrl+enter', 'meta+enter'],
queueBack,
{
enabled: () => !isDisabled && !isLoading,
preventDefault: true,
enableOnFormTags: ['input', 'textarea', 'select'],
},
[tabName, isDisabled, isLoading]
);
return { queueBack, isLoading, isDisabled };
};

View File

@@ -4,7 +4,6 @@ import { useIsReadyToEnqueue } from 'common/hooks/useIsReadyToEnqueue';
import { clampSymmetrySteps } from 'features/parameters/store/generationSlice';
import { activeTabNameSelector } from 'features/ui/store/uiSelectors';
import { useCallback, useMemo } from 'react';
import { useHotkeys } from 'react-hotkeys-hook';
import { useEnqueueBatchMutation } from 'services/api/endpoints/queue';
export const useQueueFront = () => {
@@ -23,16 +22,5 @@ export const useQueueFront = () => {
dispatch(enqueueRequested({ tabName, prepend: true }));
}, [dispatch, isDisabled, tabName]);
useHotkeys(
['ctrl+shift+enter', 'meta+shift+enter'],
queueFront,
{
enabled: () => !isDisabled && !isLoading,
preventDefault: true,
enableOnFormTags: ['input', 'textarea', 'select'],
},
[isLoading, isDisabled, tabName]
);
return { queueFront, isLoading, isDisabled };
};

View File

@@ -44,9 +44,7 @@ const FloatingGalleryButton = ({
p: 0,
px: 3,
h: 48,
borderStartEndRadius: 0,
borderEndEndRadius: 0,
shadow: '2xl',
borderEndRadius: 0,
}}
/>
</Flex>

View File

@@ -1,5 +1,8 @@
import { ChakraProps, Flex, Portal } from '@chakra-ui/react';
import { ButtonGroup, ChakraProps, Flex, Portal } from '@chakra-ui/react';
import IAIIconButton from 'common/components/IAIIconButton';
import CancelCurrentQueueItemButton from 'features/queue/components/CancelCurrentQueueItemButton';
import ClearQueueButton from 'features/queue/components/ClearQueueButton';
import QueueBackButton from 'features/queue/components/QueueBackButton';
import { RefObject, memo } from 'react';
import { useTranslation } from 'react-i18next';
@@ -7,9 +10,8 @@ import { FaSlidersH } from 'react-icons/fa';
import { ImperativePanelHandle } from 'react-resizable-panels';
const floatingButtonStyles: ChakraProps['sx'] = {
borderStartStartRadius: 0,
borderEndStartRadius: 0,
shadow: '2xl',
borderStartRadius: 0,
flexGrow: 1,
};
type Props = {
@@ -41,14 +43,23 @@ const FloatingSidePanelButtons = ({
insetInlineStart="5.13rem"
direction="column"
gap={2}
h={48}
>
<IAIIconButton
tooltip="Show Side Panel (O, T)"
aria-label={t('common.showOptionsPanel')}
onClick={handleShowSidePanel}
sx={floatingButtonStyles}
icon={<FaSlidersH />}
/>
<ButtonGroup isAttached orientation="vertical" flexGrow={3}>
<IAIIconButton
tooltip="Show Side Panel (O, T)"
aria-label={t('common.showOptionsPanel')}
onClick={handleShowSidePanel}
sx={floatingButtonStyles}
icon={<FaSlidersH />}
/>
<QueueBackButton asIconButton sx={floatingButtonStyles} />
<CancelCurrentQueueItemButton
asIconButton
sx={floatingButtonStyles}
/>
</ButtonGroup>
<ClearQueueButton asIconButton sx={floatingButtonStyles} />
</Flex>
</Portal>
);

View File

@@ -21,9 +21,9 @@ import { isEqual } from 'lodash-es';
import { MouseEvent, ReactNode, memo, useCallback, useMemo } from 'react';
import { useHotkeys } from 'react-hotkeys-hook';
import { useTranslation } from 'react-i18next';
import { FaCube, FaFont, FaImage } from 'react-icons/fa';
import { FaListOl } from 'react-icons/fa6';
import { MdDeviceHub, MdGridOn } from 'react-icons/md';
import { FaCube, FaFont, FaImage, FaStream } from 'react-icons/fa';
import { FaCircleNodes } from 'react-icons/fa6';
import { MdGridOn } from 'react-icons/md';
import { Panel, PanelGroup } from 'react-resizable-panels';
import { usePanel } from '../hooks/usePanel';
import { usePanelStorage } from '../hooks/usePanelStorage';
@@ -71,7 +71,9 @@ const tabs: InvokeTabInfo[] = [
{
id: 'nodes',
translationKey: 'common.nodes',
icon: <Icon as={MdDeviceHub} sx={{ boxSize: 6, pointerEvents: 'none' }} />,
icon: (
<Icon as={FaCircleNodes} sx={{ boxSize: 6, pointerEvents: 'none' }} />
),
content: <NodesTab />,
},
{
@@ -83,7 +85,7 @@ const tabs: InvokeTabInfo[] = [
{
id: 'queue',
translationKey: 'queue.queue',
icon: <Icon as={FaListOl} sx={{ boxSize: 6, pointerEvents: 'none' }} />,
icon: <Icon as={FaStream} sx={{ boxSize: 6, pointerEvents: 'none' }} />,
content: <QueueTab />,
},
];

View File

@@ -8868,12 +8868,6 @@ export type components = {
/** Ui Order */
ui_order?: number;
};
/**
* StableDiffusionOnnxModelFormat
* @description An enumeration.
* @enum {string}
*/
StableDiffusionOnnxModelFormat: "olive" | "onnx";
/**
* ControlNetModelFormat
* @description An enumeration.
@@ -8898,6 +8892,12 @@ export type components = {
* @enum {string}
*/
StableDiffusion2ModelFormat: "checkpoint" | "diffusers";
/**
* StableDiffusionOnnxModelFormat
* @description An enumeration.
* @enum {string}
*/
StableDiffusionOnnxModelFormat: "olive" | "onnx";
};
responses: never;
parameters: never;