mirror of
https://github.com/invoke-ai/InvokeAI.git
synced 2026-04-23 03:00:31 -04:00
Fixes edge cases, adds invoke button to header when options floating
This commit is contained in:
@@ -1,22 +1,18 @@
|
||||
import { Button, ButtonProps, Tooltip } from '@chakra-ui/react';
|
||||
|
||||
interface Props extends ButtonProps {
|
||||
export interface IAIButtonProps extends ButtonProps {
|
||||
label: string;
|
||||
tooltip?: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reusable customized button component. Originally was more customized - now probably unecessary.
|
||||
*
|
||||
* TODO: Get rid of this.
|
||||
* Reusable customized button component.
|
||||
*/
|
||||
const IAIButton = (props: Props) => {
|
||||
const { label, tooltip = '', size = 'sm', ...rest } = props;
|
||||
const IAIButton = (props: IAIButtonProps) => {
|
||||
const { label, tooltip = '', ...rest } = props;
|
||||
return (
|
||||
<Tooltip label={tooltip}>
|
||||
<Button size={size} {...rest}>
|
||||
{label}
|
||||
</Button>
|
||||
<Button {...rest}>{label}</Button>
|
||||
</Tooltip>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -1,23 +1,11 @@
|
||||
import { useCallback, ReactNode, useState, useEffect } from 'react';
|
||||
import { RootState, useAppDispatch, useAppSelector } from '../../app/store';
|
||||
import { tabMap } from '../../features/tabs/InvokeTabs';
|
||||
import { useAppDispatch, useAppSelector } from '../../app/store';
|
||||
import { FileRejection, useDropzone } from 'react-dropzone';
|
||||
import { Heading, Spinner, useToast } from '@chakra-ui/react';
|
||||
import { createSelector } from '@reduxjs/toolkit';
|
||||
import { OptionsState } from '../../features/options/optionsSlice';
|
||||
import { uploadImage } from '../../app/socketio/actions';
|
||||
import { ImageUploadDestination, UploadImagePayload } from '../../app/invokeai';
|
||||
import { ImageUploaderTriggerContext } from '../../app/contexts/ImageUploaderTriggerContext';
|
||||
|
||||
const appSelector = createSelector(
|
||||
(state: RootState) => state.options,
|
||||
(options: OptionsState) => {
|
||||
const { activeTab } = options;
|
||||
return {
|
||||
activeTabName: tabMap[activeTab],
|
||||
};
|
||||
}
|
||||
);
|
||||
import { activeTabNameSelector } from '../../features/options/optionsSelectors';
|
||||
|
||||
type ImageUploaderProps = {
|
||||
children: ReactNode;
|
||||
@@ -26,7 +14,7 @@ type ImageUploaderProps = {
|
||||
const ImageUploader = (props: ImageUploaderProps) => {
|
||||
const { children } = props;
|
||||
const dispatch = useAppDispatch();
|
||||
const { activeTabName } = useAppSelector(appSelector);
|
||||
const activeTabName = useAppSelector(activeTabNameSelector);
|
||||
const toast = useToast({});
|
||||
const [isHandlingUpload, setIsHandlingUpload] = useState<boolean>(false);
|
||||
|
||||
|
||||
@@ -3,11 +3,11 @@ import _ from 'lodash';
|
||||
import { useMemo } from 'react';
|
||||
import { useAppSelector } from '../../app/store';
|
||||
import { RootState } from '../../app/store';
|
||||
import { activeTabNameSelector } from '../../features/options/optionsSelectors';
|
||||
import { OptionsState } from '../../features/options/optionsSlice';
|
||||
|
||||
import { SystemState } from '../../features/system/systemSlice';
|
||||
import { InpaintingState } from '../../features/tabs/Inpainting/inpaintingSlice';
|
||||
import { tabMap } from '../../features/tabs/InvokeTabs';
|
||||
import { validateSeedWeights } from '../util/seedWeightPairs';
|
||||
|
||||
export const useCheckParametersSelector = createSelector(
|
||||
@@ -15,8 +15,9 @@ export const useCheckParametersSelector = createSelector(
|
||||
(state: RootState) => state.options,
|
||||
(state: RootState) => state.system,
|
||||
(state: RootState) => state.inpainting,
|
||||
activeTabNameSelector
|
||||
],
|
||||
(options: OptionsState, system: SystemState, inpainting: InpaintingState) => {
|
||||
(options: OptionsState, system: SystemState, inpainting: InpaintingState, activeTabName) => {
|
||||
return {
|
||||
// options
|
||||
prompt: options.prompt,
|
||||
@@ -25,7 +26,7 @@ export const useCheckParametersSelector = createSelector(
|
||||
maskPath: options.maskPath,
|
||||
initialImage: options.initialImage,
|
||||
seed: options.seed,
|
||||
activeTabName: tabMap[options.activeTab],
|
||||
activeTabName,
|
||||
// system
|
||||
isProcessing: system.isProcessing,
|
||||
isConnected: system.isConnected,
|
||||
|
||||
20
frontend/src/common/hooks/useClickOutsideWatcher.ts
Normal file
20
frontend/src/common/hooks/useClickOutsideWatcher.ts
Normal file
@@ -0,0 +1,20 @@
|
||||
import { RefObject, useEffect } from 'react';
|
||||
|
||||
const useClickOutsideWatcher = (
|
||||
ref: RefObject<HTMLElement>,
|
||||
callback: () => void
|
||||
) => {
|
||||
useEffect(() => {
|
||||
function handleClickOutside(e: MouseEvent) {
|
||||
if (ref.current && !ref.current.contains(e.target as Node)) {
|
||||
callback();
|
||||
}
|
||||
}
|
||||
document.addEventListener('mousedown', handleClickOutside);
|
||||
return () => {
|
||||
document.removeEventListener('mousedown', handleClickOutside);
|
||||
};
|
||||
}, [ref, callback]);
|
||||
};
|
||||
|
||||
export default useClickOutsideWatcher;
|
||||
Reference in New Issue
Block a user