3.0 Pre-Release Polish -- Bug Fixes / Style Fixes / Misc (#3812)

## What type of PR is this? (check all applicable)

- [ ] Refactor
- [x] Feature
- [x] Bug Fix
- [ ] Optimization
- [ ] Documentation Update


## Have you discussed this change with the InvokeAI team?
- [x] Yes
- [ ] No, because:

      
## Description

Making some final style fixes before we push the next 3.0 version
tomorrow.

- Fixed light mode colors in Settings Modal.
- Double checked other light mode colors. Nothing seems off.
- Added Base Model badge to the model list item. Makes it visually
better and also serves as a quick glance feature for the user.
- Some minor styling updates to the Node Editor.
- Fixed hotkeys 'G' and 'O', 'Shift+G' and 'Shift+O' used to toggle the
panels not resizing canvas. #3780
- Fixed hotkey 'N' not working for Snap To Grid on Canvas.
- Fixed brush opacity hotkeys not working.
- Cleaned up hotkeys modal of hotkeys that are no longer used.
- Updated compel requirement to `2.0.0`


## Related Tickets & Documents

<!--
For pull requests that relate or close an issue, please include them
below. 

For example having the text: "closes #1234" would connect the current
pull
request to issue 1234.  And when we merge the pull request, Github will
automatically close the issue.
-->

- Related Issue #
- Closes #3780

## QA Instructions, Screenshots, Recordings

<!-- 
Please provide steps on how to test changes, any hardware or 
software specifications as well as any other pertinent information. 
-->

## Added/updated tests?

- [ ] Yes
- [x] No : _please replace this line with details on why tests
      have not been included_

## [optional] Are there any post deployment tasks we need to perform?
This commit is contained in:
blessedcoolant 2023-07-19 00:04:57 +12:00 committed by GitHub
commit 68f2fb2601
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
14 changed files with 135 additions and 77 deletions

View File

@ -1,7 +1,9 @@
import { createSelector } from '@reduxjs/toolkit';
import { RootState } from 'app/store/store';
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
import { requestCanvasRescale } from 'features/canvas/store/thunks/requestCanvasScale';
import { shiftKeyPressed } from 'features/ui/store/hotkeysSlice';
import { activeTabNameSelector } from 'features/ui/store/uiSelectors';
import {
setActiveTab,
toggleGalleryPanel,
@ -14,10 +16,11 @@ import React, { memo } from 'react';
import { isHotkeyPressed, useHotkeys } from 'react-hotkeys-hook';
const globalHotkeysSelector = createSelector(
(state: RootState) => state.hotkeys,
(hotkeys) => {
[(state: RootState) => state.hotkeys, (state: RootState) => state.ui],
(hotkeys, ui) => {
const { shift } = hotkeys;
return { shift };
const { shouldPinParametersPanel, shouldPinGallery } = ui;
return { shift, shouldPinGallery, shouldPinParametersPanel };
},
{
memoizeOptions: {
@ -34,7 +37,10 @@ const globalHotkeysSelector = createSelector(
*/
const GlobalHotkeys: React.FC = () => {
const dispatch = useAppDispatch();
const { shift } = useAppSelector(globalHotkeysSelector);
const { shift, shouldPinParametersPanel, shouldPinGallery } = useAppSelector(
globalHotkeysSelector
);
const activeTabName = useAppSelector(activeTabNameSelector);
useHotkeys(
'*',
@ -51,18 +57,30 @@ const GlobalHotkeys: React.FC = () => {
useHotkeys('o', () => {
dispatch(toggleParametersPanel());
if (activeTabName === 'unifiedCanvas' && shouldPinParametersPanel) {
dispatch(requestCanvasRescale());
}
});
useHotkeys(['shift+o'], () => {
dispatch(togglePinParametersPanel());
if (activeTabName === 'unifiedCanvas') {
dispatch(requestCanvasRescale());
}
});
useHotkeys('g', () => {
dispatch(toggleGalleryPanel());
if (activeTabName === 'unifiedCanvas' && shouldPinGallery) {
dispatch(requestCanvasRescale());
}
});
useHotkeys(['shift+g'], () => {
dispatch(togglePinGalleryPanel());
if (activeTabName === 'unifiedCanvas') {
dispatch(requestCanvasRescale());
}
});
useHotkeys('1', () => {

View File

@ -11,6 +11,7 @@ import {
setIsMouseOverBoundingBox,
setIsMovingBoundingBox,
setIsTransformingBoundingBox,
setShouldSnapToGrid,
} from 'features/canvas/store/canvasSlice';
import { uiSelector } from 'features/ui/store/uiSelectors';
import Konva from 'konva';
@ -20,6 +21,7 @@ import { Vector2d } from 'konva/lib/types';
import { isEqual } from 'lodash-es';
import { useCallback, useEffect, useRef, useState } from 'react';
import { useHotkeys } from 'react-hotkeys-hook';
import { Group, Rect, Transformer } from 'react-konva';
const boundingBoxPreviewSelector = createSelector(
@ -91,6 +93,10 @@ const IAICanvasBoundingBox = (props: IAICanvasBoundingBoxPreviewProps) => {
const scaledStep = 64 * stageScale;
useHotkeys('N', () => {
dispatch(setShouldSnapToGrid(!shouldSnapToGrid));
});
const handleOnDragMove = useCallback(
(e: KonvaEventObject<DragEvent>) => {
if (!shouldSnapToGrid) {

View File

@ -139,7 +139,7 @@ const IAICanvasToolChooserOptions = () => {
);
useHotkeys(
['shift+BracketLeft'],
['Shift+BracketLeft'],
() => {
dispatch(
setBrushColor({
@ -156,7 +156,7 @@ const IAICanvasToolChooserOptions = () => {
);
useHotkeys(
['shift+BracketRight'],
['Shift+BracketRight'],
() => {
dispatch(
setBrushColor({

View File

@ -110,8 +110,11 @@ const SelectItem = forwardRef<HTMLDivElement, ItemProps>(
return (
<div ref={ref} {...others}>
<div>
<Text>{label}</Text>
<Text size="xs" color="base.600">
<Text fontWeight={600}>{label}</Text>
<Text
size="xs"
sx={{ color: 'base.600', _dark: { color: 'base.500' } }}
>
{description}
</Text>
</div>

View File

@ -20,8 +20,8 @@ const IAINodeHeader = (props: IAINodeHeaderProps) => {
justifyContent: 'space-between',
px: 2,
py: 1,
bg: 'base.300',
_dark: { bg: 'base.700' },
bg: 'base.100',
_dark: { bg: 'base.900' },
}}
>
<Tooltip label={nodeId}>
@ -30,7 +30,7 @@ const IAINodeHeader = (props: IAINodeHeaderProps) => {
sx={{
fontWeight: 600,
color: 'base.900',
_dark: { color: 'base.100' },
_dark: { color: 'base.200' },
}}
>
{title}

View File

@ -59,7 +59,7 @@ export const InvocationComponent = memo((props: NodeProps<InvocationValue>) => {
flexDirection: 'column',
borderBottomRadius: 'md',
py: 2,
bg: 'base.200',
bg: 'base.150',
_dark: { bg: 'base.800' },
}}
>

View File

@ -1,9 +1,9 @@
import 'reactflow/dist/style.css';
import { Box } from '@chakra-ui/react';
import { ReactFlowProvider } from 'reactflow';
import 'reactflow/dist/style.css';
import { Flow } from './Flow';
import { memo } from 'react';
import { Flow } from './Flow';
const NodeEditor = () => {
return (

View File

@ -1,9 +1,9 @@
import { Box, useToken } from '@chakra-ui/react';
import { NODE_MIN_WIDTH } from 'app/constants';
import { useAppSelector } from 'app/store/storeHooks';
import { PropsWithChildren } from 'react';
import { DRAG_HANDLE_CLASSNAME } from '../hooks/useBuildInvocation';
import { useAppSelector } from 'app/store/storeHooks';
type NodeWrapperProps = PropsWithChildren & {
selected: boolean;

View File

@ -15,7 +15,7 @@ import {
ModalOverlay,
useDisclosure,
} from '@chakra-ui/react';
import { cloneElement, ReactElement } from 'react';
import { ReactElement, cloneElement } from 'react';
import { useTranslation } from 'react-i18next';
import HotkeysModalItem from './HotkeysModalItem';
@ -65,11 +65,6 @@ export default function HotkeysModal({ children }: HotkeysModalProps) {
desc: t('hotkeys.pinOptions.desc'),
hotkey: 'Shift+O',
},
{
title: t('hotkeys.toggleViewer.title'),
desc: t('hotkeys.toggleViewer.desc'),
hotkey: 'Z',
},
{
title: t('hotkeys.toggleGallery.title'),
desc: t('hotkeys.toggleGallery.desc'),
@ -85,12 +80,6 @@ export default function HotkeysModal({ children }: HotkeysModalProps) {
desc: t('hotkeys.changeTabs.desc'),
hotkey: '1-5',
},
{
title: t('hotkeys.consoleToggle.title'),
desc: t('hotkeys.consoleToggle.desc'),
hotkey: '`',
},
];
const generalHotkeys = [
@ -109,11 +98,6 @@ export default function HotkeysModal({ children }: HotkeysModalProps) {
desc: t('hotkeys.setParameters.desc'),
hotkey: 'A',
},
{
title: t('hotkeys.restoreFaces.title'),
desc: t('hotkeys.restoreFaces.desc'),
hotkey: 'Shift+R',
},
{
title: t('hotkeys.upscale.title'),
desc: t('hotkeys.upscale.desc'),

View File

@ -183,7 +183,7 @@ const SettingsModal = ({ children, config }: SettingsModalProps) => {
>
<ModalOverlay />
<ModalContent>
<ModalHeader>{t('common.settingsLabel')}</ModalHeader>
<ModalHeader bg="none">{t('common.settingsLabel')}</ModalHeader>
<ModalCloseButton />
<ModalBody>
<Flex sx={{ gap: 4, flexDirection: 'column' }}>
@ -331,12 +331,15 @@ export default SettingsModal;
const StyledFlex = (props: PropsWithChildren) => {
return (
<Flex
layerStyle="second"
sx={{
flexDirection: 'column',
gap: 2,
p: 4,
borderRadius: 'base',
bg: 'base.100',
_dark: {
bg: 'base.900',
},
}}
>
{props.children}

View File

@ -3,7 +3,7 @@ import { EntityState } from '@reduxjs/toolkit';
import IAIButton from 'common/components/IAIButton';
import IAIInput from 'common/components/IAIInput';
import { forEach } from 'lodash-es';
import type { ChangeEvent } from 'react';
import type { ChangeEvent, PropsWithChildren } from 'react';
import { useCallback, useState } from 'react';
import { useTranslation } from 'react-i18next';
import {
@ -44,13 +44,7 @@ const ModelList = (props: ModelListProps) => {
return (
<Flex flexDirection="column" rowGap={4} width="50%" minWidth="50%">
<Flex
flexDirection="column"
gap={4}
maxHeight={window.innerHeight - 240}
overflow="scroll"
paddingInlineEnd={4}
>
<Flex flexDirection="column" gap={4} paddingInlineEnd={4}>
<ButtonGroup isAttached>
<IAIButton
onClick={() => setModelFormatFilter('all')}
@ -83,35 +77,39 @@ const ModelList = (props: ModelListProps) => {
{['all', 'diffusers'].includes(modelFormatFilter) &&
filteredDiffusersModels.length > 0 && (
<Flex sx={{ gap: 2, flexDir: 'column' }}>
<Text variant="subtext" fontSize="sm">
Diffusers
</Text>
{filteredDiffusersModels.map((model) => (
<ModelListItem
key={model.id}
model={model}
isSelected={selectedModelId === model.id}
setSelectedModelId={setSelectedModelId}
/>
))}
</Flex>
<StyledModelContainer>
<Flex sx={{ gap: 2, flexDir: 'column' }}>
<Text variant="subtext" fontSize="sm">
Diffusers
</Text>
{filteredDiffusersModels.map((model) => (
<ModelListItem
key={model.id}
model={model}
isSelected={selectedModelId === model.id}
setSelectedModelId={setSelectedModelId}
/>
))}
</Flex>
</StyledModelContainer>
)}
{['all', 'checkpoint'].includes(modelFormatFilter) &&
filteredCheckpointModels.length > 0 && (
<Flex sx={{ gap: 2, flexDir: 'column' }}>
<Text variant="subtext" fontSize="sm">
Checkpoint
</Text>
{filteredCheckpointModels.map((model) => (
<ModelListItem
key={model.id}
model={model}
isSelected={selectedModelId === model.id}
setSelectedModelId={setSelectedModelId}
/>
))}
</Flex>
<StyledModelContainer>
<Flex sx={{ gap: 2, flexDir: 'column' }}>
<Text variant="subtext" fontSize="sm">
Checkpoint
</Text>
{filteredCheckpointModels.map((model) => (
<ModelListItem
key={model.id}
model={model}
isSelected={selectedModelId === model.id}
setSelectedModelId={setSelectedModelId}
/>
))}
</Flex>
</StyledModelContainer>
)}
</Flex>
</Flex>
@ -143,3 +141,24 @@ const modelsFilter = (
});
return filteredModels;
};
const StyledModelContainer = (props: PropsWithChildren) => {
return (
<Flex
flexDirection="column"
maxHeight={window.innerHeight - 280}
overflow="scroll"
gap={4}
borderRadius={4}
p={4}
sx={{
bg: 'base.200',
_dark: {
bg: 'base.800',
},
}}
>
{props.children}
</Flex>
);
};

View File

@ -1,5 +1,5 @@
import { DeleteIcon } from '@chakra-ui/icons';
import { Flex, Text, Tooltip } from '@chakra-ui/react';
import { Badge, Flex, Text, Tooltip } from '@chakra-ui/react';
import { makeToast } from 'app/components/Toaster';
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
import IAIAlertDialog from 'common/components/IAIAlertDialog';
@ -20,6 +20,13 @@ type ModelListItemProps = {
setSelectedModelId: (v: string | undefined) => void;
};
const modelBaseTypeMap = {
'sd-1': 'SD1',
'sd-2': 'SD2',
sdxl: 'SDXL',
'sdxl-refiner': 'SDXLR',
};
export default function ModelListItem(props: ModelListItemProps) {
const isBusy = useAppSelector(selectIsBusy);
const { t } = useTranslation();
@ -76,7 +83,7 @@ export default function ModelListItem(props: ModelListItemProps) {
bg: isSelected ? 'accent.400' : 'base.100',
color: isSelected ? 'base.50' : 'base.800',
_hover: {
bg: isSelected ? 'accent.500' : 'base.200',
bg: isSelected ? 'accent.500' : 'base.300',
color: isSelected ? 'base.50' : 'base.800',
},
_dark: {
@ -84,15 +91,33 @@ export default function ModelListItem(props: ModelListItemProps) {
bg: isSelected ? 'accent.600' : 'base.850',
_hover: {
color: isSelected ? 'base.50' : 'base.100',
bg: isSelected ? 'accent.550' : 'base.800',
bg: isSelected ? 'accent.550' : 'base.700',
},
},
}}
onClick={handleSelectModel}
>
<Tooltip label={model.description} hasArrow placement="bottom">
<Text sx={{ fontWeight: 500 }}>{model.model_name}</Text>
</Tooltip>
<Flex gap={4} alignItems="center">
<Badge
minWidth={14}
p={1}
fontSize="sm"
sx={{
bg: 'base.350',
color: 'base.900',
_dark: { bg: 'base.500' },
}}
>
{
modelBaseTypeMap[
model.base_model as keyof typeof modelBaseTypeMap
]
}
</Badge>
<Tooltip label={model.description} hasArrow placement="bottom">
<Text sx={{ fontWeight: 500 }}>{model.model_name}</Text>
</Tooltip>
</Flex>
</Flex>
<IAIAlertDialog
title={t('modelManager.deleteModel')}

View File

@ -13,13 +13,13 @@ import { popoverTheme } from './components/popover';
import { progressTheme } from './components/progress';
import { no_scrollbar } from './components/scrollbar';
import { selectTheme } from './components/select';
import { skeletonTheme } from './components/skeleton';
import { sliderTheme } from './components/slider';
import { switchTheme } from './components/switch';
import { tabsTheme } from './components/tabs';
import { textTheme } from './components/text';
import { textareaTheme } from './components/textarea';
import { tooltipTheme } from './components/tooltip';
import { skeletonTheme } from './components/skeleton';
export const theme: ThemeOverride = {
config: {
@ -74,7 +74,7 @@ export const theme: ThemeOverride = {
'0px 0px 0px 1px var(--invokeai-colors-base-150), 0px 0px 0px 4px var(--invokeai-colors-accent-400)',
dark: '0px 0px 0px 1px var(--invokeai-colors-base-900), 0px 0px 0px 4px var(--invokeai-colors-accent-400)',
},
nodeSelectedOutline: `0 0 0 2px var(--invokeai-colors-base-500)`,
nodeSelectedOutline: `0 0 0 2px var(--invokeai-colors-accent-450)`,
},
colors: InvokeAIColors,
components: {

View File

@ -38,7 +38,7 @@ dependencies = [
"albumentations",
"click",
"clip_anytorch", # replacing "clip @ https://github.com/openai/CLIP/archive/eaa22acb90a5876642d0507623e859909230a52d.zip",
"compel==2.0.0rc2",
"compel==2.0.0",
"controlnet-aux>=0.0.6",
"timm==0.6.13", # needed to override timm latest in controlnet_aux, see https://github.com/isl-org/ZoeDepth/issues/26
"datasets",