Merge branch 'main' into release/invokeai-3-0-beta

This commit is contained in:
Lincoln Stein 2023-07-09 13:26:49 -04:00
commit f335363a6f
6 changed files with 76 additions and 36 deletions

View File

@ -59,6 +59,7 @@ const IAIMantineMultiSelect = (props: IAIMultiSelectProps) => {
onKeyDown={handleKeyDown}
onKeyUp={handleKeyUp}
searchable={searchable}
maxDropdownHeight={300}
styles={() => ({
label: {
color: mode(base700, base300)(colorMode),

View File

@ -3,7 +3,7 @@ import { Select, SelectProps } from '@mantine/core';
import { useAppDispatch } from 'app/store/storeHooks';
import { useChakraThemeTokens } from 'common/hooks/useChakraThemeTokens';
import { shiftKeyPressed } from 'features/ui/store/hotkeysSlice';
import { KeyboardEvent, memo, useCallback } from 'react';
import { KeyboardEvent, RefObject, memo, useCallback, useState } from 'react';
import { mode } from 'theme/util/mode';
export type IAISelectDataType = {
@ -14,10 +14,11 @@ export type IAISelectDataType = {
type IAISelectProps = SelectProps & {
tooltip?: string;
inputRef?: RefObject<HTMLInputElement>;
};
const IAIMantineSelect = (props: IAISelectProps) => {
const { searchable = true, tooltip, ...rest } = props;
const { searchable = true, tooltip, inputRef, onChange, ...rest } = props;
const dispatch = useAppDispatch();
const {
base50,
@ -38,7 +39,9 @@ const IAIMantineSelect = (props: IAISelectProps) => {
} = useChakraThemeTokens();
const { colorMode } = useColorMode();
const [searchValue, setSearchValue] = useState('');
// we want to capture shift keypressed even when an input is focused
const handleKeyDown = useCallback(
(e: KeyboardEvent<HTMLInputElement>) => {
if (e.shiftKey) {
@ -57,14 +60,33 @@ const IAIMantineSelect = (props: IAISelectProps) => {
[dispatch]
);
// wrap onChange to clear search value on select
const handleChange = useCallback(
(v: string | null) => {
setSearchValue('');
if (!onChange) {
return;
}
onChange(v);
},
[onChange]
);
const [boxShadow] = useToken('shadows', ['dark-lg']);
return (
<Tooltip label={tooltip} placement="top" hasArrow>
<Select
ref={inputRef}
searchValue={searchValue}
onSearchChange={setSearchValue}
onChange={handleChange}
onKeyDown={handleKeyDown}
onKeyUp={handleKeyUp}
searchable={searchable}
maxDropdownHeight={300}
styles={() => ({
label: {
color: mode(base700, base300)(colorMode),

View File

@ -9,7 +9,7 @@ import {
import { SelectItem } from '@mantine/core';
import { RootState } from 'app/store/store';
import { useAppSelector } from 'app/store/storeHooks';
import IAIMantineMultiSelect from 'common/components/IAIMantineMultiSelect';
import IAIMantineSelect from 'common/components/IAIMantineSelect';
import IAIMantineSelectItemWithTooltip from 'common/components/IAIMantineSelectItemWithTooltip';
import { MODEL_TYPE_MAP } from 'features/system/components/ModelSelect';
import { forEach } from 'lodash-es';
@ -61,12 +61,12 @@ const ParamEmbeddingPopover = (props: Props) => {
}, [embeddingQueryData, currentMainModel?.base_model]);
const handleChange = useCallback(
(v: string[]) => {
if (v.length === 0) {
(v: string | null) => {
if (!v) {
return;
}
onSelect(v[0]);
onSelect(v);
},
[onSelect]
);
@ -106,16 +106,16 @@ const ParamEmbeddingPopover = (props: Props) => {
</Text>
</Flex>
) : (
<IAIMantineMultiSelect
<IAIMantineSelect
inputRef={inputRef}
autoFocus
placeholder={'Add Embedding'}
value={[]}
value={null}
data={data}
maxDropdownHeight={400}
nothingFound="No Matching Embeddings"
nothingFound="No matching Embeddings"
itemComponent={IAIMantineSelectItemWithTooltip}
disabled={data.length === 0}
filter={(value, selected, item: SelectItem) =>
filter={(value, item: SelectItem) =>
item.label
?.toLowerCase()
.includes(value.toLowerCase().trim()) ||

View File

@ -4,7 +4,7 @@ import { createSelector } from '@reduxjs/toolkit';
import { RootState, stateSelector } from 'app/store/store';
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
import { defaultSelectorOptions } from 'app/store/util/defaultMemoizeOptions';
import IAIMantineMultiSelect from 'common/components/IAIMantineMultiSelect';
import IAIMantineSelect from 'common/components/IAIMantineSelect';
import IAIMantineSelectItemWithTooltip from 'common/components/IAIMantineSelectItemWithTooltip';
import { loraAdded } from 'features/lora/store/loraSlice';
import { MODEL_TYPE_MAP } from 'features/system/components/ModelSelect';
@ -58,12 +58,15 @@ const ParamLoraSelect = () => {
}, [loras, lorasQueryData, currentMainModel?.base_model]);
const handleChange = useCallback(
(v: string[]) => {
const loraEntity = lorasQueryData?.entities[v[0]];
(v: string | null | undefined) => {
if (!v) {
return;
}
const loraEntity = lorasQueryData?.entities[v];
if (!loraEntity) {
return;
}
v[0] && dispatch(loraAdded(loraEntity));
dispatch(loraAdded(loraEntity));
},
[dispatch, lorasQueryData?.entities]
);
@ -79,15 +82,14 @@ const ParamLoraSelect = () => {
}
return (
<IAIMantineMultiSelect
<IAIMantineSelect
placeholder={data.length === 0 ? 'All LoRAs added' : 'Add LoRA'}
value={[]}
value={null}
data={data}
maxDropdownHeight={400}
nothingFound="No matching LoRAs"
itemComponent={IAIMantineSelectItemWithTooltip}
disabled={data.length === 0}
filter={(value, selected, item: SelectItem) =>
filter={(value, item: SelectItem) =>
item.label?.toLowerCase().includes(value.toLowerCase().trim()) ||
item.value.toLowerCase().includes(value.toLowerCase().trim())
}

View File

@ -1,15 +1,15 @@
import 'reactflow/dist/style.css';
import { useCallback, forwardRef } from 'react';
import { Flex, Text } from '@chakra-ui/react';
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
import { nodeAdded, nodesSelector } from '../store/nodesSlice';
import { map } from 'lodash-es';
import { useBuildInvocation } from '../hooks/useBuildInvocation';
import { AnyInvocationType } from 'services/events/types';
import { useAppToaster } from 'app/components/Toaster';
import { createSelector } from '@reduxjs/toolkit';
import { useAppToaster } from 'app/components/Toaster';
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
import { defaultSelectorOptions } from 'app/store/util/defaultMemoizeOptions';
import IAIMantineMultiSelect from 'common/components/IAIMantineMultiSelect';
import IAIMantineSelect from 'common/components/IAIMantineSelect';
import { map } from 'lodash-es';
import { forwardRef, useCallback } from 'react';
import 'reactflow/dist/style.css';
import { AnyInvocationType } from 'services/events/types';
import { useBuildInvocation } from '../hooks/useBuildInvocation';
import { nodeAdded, nodesSelector } from '../store/nodesSlice';
type NodeTemplate = {
label: string;
@ -58,24 +58,33 @@ const AddNodeMenu = () => {
[dispatch, buildInvocation, toaster]
);
const handleChange = useCallback(
(v: string | null) => {
if (!v) {
return;
}
addNode(v as AnyInvocationType);
},
[addNode]
);
return (
<Flex sx={{ gap: 2, alignItems: 'center' }}>
<IAIMantineMultiSelect
<IAIMantineSelect
selectOnBlur={false}
placeholder="Add Node"
value={[]}
value={null}
data={data}
maxDropdownHeight={400}
nothingFound="No matching nodes"
itemComponent={SelectItem}
filter={(value, selected, item: NodeTemplate) =>
filter={(value, item: NodeTemplate) =>
item.label.toLowerCase().includes(value.toLowerCase().trim()) ||
item.value.toLowerCase().includes(value.toLowerCase().trim()) ||
item.description.toLowerCase().includes(value.toLowerCase().trim())
}
onChange={(v) => {
v[0] && addNode(v[0] as AnyInvocationType);
}}
onChange={handleChange}
sx={{
width: '18rem',
}}

View File

@ -41,6 +41,7 @@ import UnifiedCanvasTab from './tabs/UnifiedCanvas/UnifiedCanvasTab';
export interface InvokeTabInfo {
id: InvokeTabName;
translationKey: string;
icon: ReactNode;
content: ReactNode;
}
@ -48,26 +49,31 @@ export interface InvokeTabInfo {
const tabs: InvokeTabInfo[] = [
{
id: 'txt2img',
translationKey: 'common.txt2img',
icon: <Icon as={FaFont} sx={{ boxSize: 6, pointerEvents: 'none' }} />,
content: <TextToImageTab />,
},
{
id: 'img2img',
translationKey: 'common.img2img',
icon: <Icon as={FaImage} sx={{ boxSize: 6, pointerEvents: 'none' }} />,
content: <ImageTab />,
},
{
id: 'unifiedCanvas',
translationKey: 'common.unifiedCanvas',
icon: <Icon as={MdGridOn} sx={{ boxSize: 6, pointerEvents: 'none' }} />,
content: <UnifiedCanvasTab />,
},
{
id: 'nodes',
translationKey: 'common.nodes',
icon: <Icon as={MdDeviceHub} sx={{ boxSize: 6, pointerEvents: 'none' }} />,
content: <NodesTab />,
},
{
id: 'modelManager',
translationKey: 'modelManager.modelManager',
icon: <Icon as={FaCube} sx={{ boxSize: 6, pointerEvents: 'none' }} />,
content: <ModelManagerTab />,
},
@ -146,12 +152,12 @@ const InvokeTabs = () => {
<Tooltip
key={tab.id}
hasArrow
label={String(t(`common.${tab.id}` as ResourceKey))}
label={String(t(tab.translationKey as ResourceKey))}
placement="end"
>
<Tab onClick={handleClickTab}>
<VisuallyHidden>
{String(t(`common.${tab.id}` as ResourceKey))}
{String(t(tab.translationKey as ResourceKey))}
</VisuallyHidden>
{tab.icon}
</Tab>