mirror of
https://github.com/invoke-ai/InvokeAI
synced 2024-08-30 20:32:17 +00:00
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:
commit
68f2fb2601
@ -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', () => {
|
||||
|
@ -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) {
|
||||
|
@ -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({
|
||||
|
@ -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>
|
||||
|
@ -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}
|
||||
|
@ -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' },
|
||||
}}
|
||||
>
|
||||
|
@ -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 (
|
||||
|
@ -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;
|
||||
|
@ -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'),
|
||||
|
@ -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}
|
||||
|
@ -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>
|
||||
);
|
||||
};
|
||||
|
@ -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')}
|
||||
|
@ -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: {
|
||||
|
@ -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",
|
||||
|
Loading…
Reference in New Issue
Block a user