From 7a57bc99cfc3b40a1b4089c48bd6db7fa4364e17 Mon Sep 17 00:00:00 2001 From: psychedelicious <4822129+psychedelicious@users.noreply.github.com> Date: Thu, 4 Jan 2024 18:25:12 +1100 Subject: [PATCH] feat(ui): statusindicator changes We are now using the lefthand vertical strip for the settings menu button. This is a good place for the status indicator. Really, we only need to display something *if there is a problem*. If the app is processing, the progress bar indicates that. For the case where the panels are collapsed, I'll add the floating buttons back in some form, and we'll indicate via those if the app is processing something. --- .../src/common/components/InvButton/theme.ts | 2 +- .../common/components/InvProgress/theme.ts | 78 ++++++++++------- .../components/InvTooltip/InvTooltip.tsx | 1 + .../src/common/components/InvTooltip/theme.ts | 5 +- .../components/InvokeQueueBackButton.tsx | 8 +- .../queue/components/QueueControls.tsx | 6 +- .../system/components/ProgressBar.tsx | 12 +-- .../system/components/StatusIndicator.tsx | 83 ++++--------------- .../src/features/ui/components/InvokeTabs.tsx | 32 +++---- invokeai/frontend/web/src/theme/animations.ts | 2 + 10 files changed, 97 insertions(+), 132 deletions(-) diff --git a/invokeai/frontend/web/src/common/components/InvButton/theme.ts b/invokeai/frontend/web/src/common/components/InvButton/theme.ts index afd9aa4e98..5b54c36f97 100644 --- a/invokeai/frontend/web/src/common/components/InvButton/theme.ts +++ b/invokeai/frontend/web/src/common/components/InvButton/theme.ts @@ -204,7 +204,7 @@ export const buttonTheme = defineStyleConfig({ _hover: { bg: 'none', svg: { - fill: 'base.500', + fill: 'base.400', }, }, '&[data-selected="true"]': { diff --git a/invokeai/frontend/web/src/common/components/InvProgress/theme.ts b/invokeai/frontend/web/src/common/components/InvProgress/theme.ts index 7b9ecea23a..4ca58154cb 100644 --- a/invokeai/frontend/web/src/common/components/InvProgress/theme.ts +++ b/invokeai/frontend/web/src/common/components/InvProgress/theme.ts @@ -1,35 +1,57 @@ import { progressAnatomy as parts } from '@chakra-ui/anatomy'; -import { - createMultiStyleConfigHelpers, - defineStyle, -} from '@chakra-ui/styled-system'; +import { createMultiStyleConfigHelpers } from '@chakra-ui/styled-system'; +import { generateStripe, getColorVar } from '@chakra-ui/theme-tools'; const { defineMultiStyleConfig, definePartsStyle } = createMultiStyleConfigHelpers(parts.keys); -const invokeAIFilledTrack = defineStyle((_props) => ({ - bg: 'blue.500', -})); - -const invokeAITrack = defineStyle((_props) => { - return { - bg: 'base.800', - }; -}); - -const invokeAI = definePartsStyle((props) => ({ - filledTrack: invokeAIFilledTrack(props), - track: invokeAITrack(props), -})); - export const progressTheme = defineMultiStyleConfig({ - baseStyle: { - track: { borderRadius: '2px' }, - }, - variants: { - invokeAI, - }, - defaultProps: { - variant: 'invokeAI', - }, + baseStyle: definePartsStyle( + ({ theme: t, colorScheme: c, hasStripe, isIndeterminate }) => { + const bgColor = `${c}.300`; + const addStripe = !isIndeterminate && hasStripe; + const gradient = `linear-gradient( + to right, + transparent 0%, + ${getColorVar(t, bgColor)} 50%, + transparent 100% + )`; + return { + track: { + borderRadius: '2px', + bg: 'base.800', + }, + filledTrack: { + borderRadius: '2px', + ...(addStripe && generateStripe()), + ...(isIndeterminate ? { bgImage: gradient } : { bgColor }), + }, + }; + } + ), }); +// export const progressTheme = defineMultiStyleConfig({ +// baseStyle: definePartsStyle( +// ({ theme: t, colorScheme: c, hasStripe, isIndeterminate }) => { +// const bgColor = `${c}.500`; +// const addStripe = !isIndeterminate && hasStripe; +// const gradient = `linear-gradient( +// to right, +// transparent 0%, +// ${getColorVar(t, bgColor)} 50%, +// transparent 100% +// )`; +// return { +// track: { +// borderRadius: '2px', +// bg: 'base.800', +// }, +// filledTrack: { +// borderRadius: '2px', +// ...(addStripe && generateStripe("xs")), +// ...(isIndeterminate ? { bgImage: gradient } : { bgColor }), +// }, +// }; +// } +// ), +// }); diff --git a/invokeai/frontend/web/src/common/components/InvTooltip/InvTooltip.tsx b/invokeai/frontend/web/src/common/components/InvTooltip/InvTooltip.tsx index 226681e4b0..684490fc24 100644 --- a/invokeai/frontend/web/src/common/components/InvTooltip/InvTooltip.tsx +++ b/invokeai/frontend/web/src/common/components/InvTooltip/InvTooltip.tsx @@ -12,6 +12,7 @@ export const InvTooltip = memo( ref={ref} hasArrow={hasArrow} placement={placement} + arrowSize={8} {...rest} > {children} diff --git a/invokeai/frontend/web/src/common/components/InvTooltip/theme.ts b/invokeai/frontend/web/src/common/components/InvTooltip/theme.ts index 42f7d83c48..2e7f2190aa 100644 --- a/invokeai/frontend/web/src/common/components/InvTooltip/theme.ts +++ b/invokeai/frontend/web/src/common/components/InvTooltip/theme.ts @@ -3,14 +3,15 @@ import { cssVar } from '@chakra-ui/theme-tools'; const $arrowBg = cssVar('popper-arrow-bg'); -// define the base component styles const baseStyle = defineStyle(() => ({ borderRadius: 'md', shadow: 'dark-lg', bg: 'base.200', color: 'base.800', [$arrowBg.variable]: 'colors.base.200', - pb: 1.5, + pt: 1, + px: 2, + pb: 1, })); // export the component theme diff --git a/invokeai/frontend/web/src/features/queue/components/InvokeQueueBackButton.tsx b/invokeai/frontend/web/src/features/queue/components/InvokeQueueBackButton.tsx index a8b56c91ad..155a77858f 100644 --- a/invokeai/frontend/web/src/features/queue/components/InvokeQueueBackButton.tsx +++ b/invokeai/frontend/web/src/features/queue/components/InvokeQueueBackButton.tsx @@ -28,6 +28,7 @@ const selector = createMemoizedSelector([stateSelector], (state) => { const { initial, min, sliderMax, inputMax, fineStep, coarseStep } = state.config.sd.iterations; const { iterations } = state.generation; + const isLoadingDynamicPrompts = state.dynamicPrompts.isLoading; return { iterations, @@ -37,15 +38,14 @@ const selector = createMemoizedSelector([stateSelector], (state) => { inputMax, step: coarseStep, fineStep, + isLoadingDynamicPrompts, }; }); export const InvokeQueueBackButton = memo(() => { - const isLoadingDynamicPrompts = useAppSelector( - (state) => state.dynamicPrompts.isLoading - ); const { queueBack, isLoading, isDisabled } = useQueueBack(); - const { iterations, step, fineStep } = useAppSelector(selector); + const { iterations, step, fineStep, isLoadingDynamicPrompts } = + useAppSelector(selector); const dispatch = useAppDispatch(); const handleChange = useCallback( (v: number) => { diff --git a/invokeai/frontend/web/src/features/queue/components/QueueControls.tsx b/invokeai/frontend/web/src/features/queue/components/QueueControls.tsx index e5ce3a30d9..61dd0f5473 100644 --- a/invokeai/frontend/web/src/features/queue/components/QueueControls.tsx +++ b/invokeai/frontend/web/src/features/queue/components/QueueControls.tsx @@ -3,7 +3,6 @@ import { InvButtonGroup } from 'common/components/InvButtonGroup/InvButtonGroup' import ClearQueueButton from 'features/queue/components/ClearQueueButton'; import QueueFrontButton from 'features/queue/components/QueueFrontButton'; import ProgressBar from 'features/system/components/ProgressBar'; -import StatusIndicator from 'features/system/components/StatusIndicator'; import { useFeatureStatus } from 'features/system/hooks/useFeatureStatus'; import { memo } from 'react'; @@ -31,10 +30,7 @@ const QueueControls = () => { {isPauseEnabled && } */} - - - - + ); }; diff --git a/invokeai/frontend/web/src/features/system/components/ProgressBar.tsx b/invokeai/frontend/web/src/features/system/components/ProgressBar.tsx index ceee058a62..9e8fd6db1e 100644 --- a/invokeai/frontend/web/src/features/system/components/ProgressBar.tsx +++ b/invokeai/frontend/web/src/features/system/components/ProgressBar.tsx @@ -16,12 +16,7 @@ const progressBarSelector = createMemoizedSelector( } ); -type ProgressBarProps = { - height?: number | string; -}; - -const ProgressBar = (props: ProgressBarProps) => { - const { height = 'full' } = props; +const ProgressBar = () => { const { t } = useTranslation(); const { data: queueStatus } = useGetQueueStatusQuery(); const { hasSteps, value, isConnected } = useAppSelector(progressBarSelector); @@ -30,13 +25,12 @@ const ProgressBar = (props: ProgressBarProps) => { ); }; diff --git a/invokeai/frontend/web/src/features/system/components/StatusIndicator.tsx b/invokeai/frontend/web/src/features/system/components/StatusIndicator.tsx index fc137274dc..5d7d375cd7 100644 --- a/invokeai/frontend/web/src/features/system/components/StatusIndicator.tsx +++ b/invokeai/frontend/web/src/features/system/components/StatusIndicator.tsx @@ -1,81 +1,28 @@ -import { Flex, Icon } from '@chakra-ui/react'; -import { createMemoizedSelector } from 'app/store/createMemoizedSelector'; -import { stateSelector } from 'app/store/store'; +import { Icon } from '@chakra-ui/react'; import { useAppSelector } from 'app/store/storeHooks'; -import { InvText } from 'common/components/InvText/wrapper'; import { InvTooltip } from 'common/components/InvTooltip/InvTooltip'; -import { STATUS_TRANSLATION_KEYS } from 'features/system/store/types'; -import type { ResourceKey } from 'i18next'; -import { memo, useMemo, useRef } from 'react'; +import { memo } from 'react'; import { useTranslation } from 'react-i18next'; -import { FaCircle } from 'react-icons/fa'; -import { useHoverDirty } from 'react-use'; -import { useGetQueueStatusQuery } from 'services/api/endpoints/queue'; - -const statusIndicatorSelector = createMemoizedSelector( - stateSelector, - ({ system }) => { - const { isConnected, status } = system; - - return { - isConnected, - statusTranslationKey: STATUS_TRANSLATION_KEYS[status], - }; - } -); - -const COLOR_MAP = { - ok: 'invokeYellow.500', - working: 'blue.500', - error: 'red.500', -}; +import { FaExclamationTriangle } from 'react-icons/fa'; const StatusIndicator = () => { - const { isConnected, statusTranslationKey } = useAppSelector( - statusIndicatorSelector - ); + const isConnected = useAppSelector((state) => state.system.isConnected); const { t } = useTranslation(); - const ref = useRef(null); - const { data: queueStatus } = useGetQueueStatusQuery(); - const statusColor = useMemo(() => { - if (!isConnected) { - return 'error'; - } - - if (queueStatus?.queue.in_progress) { - return 'working'; - } - - return 'ok'; - }, [queueStatus?.queue.in_progress, isConnected]); - - const isHovered = useHoverDirty(ref); - - return ( - + if (!isConnected) { + return ( - {t(statusTranslationKey as ResourceKey)} - - ) - } + label={t('common.statusDisconnected')} + placement="end" + shouldWrapChildren + gutter={10} > - + - - ); + ); + } + + return null; }; export default memo(StatusIndicator); diff --git a/invokeai/frontend/web/src/features/ui/components/InvokeTabs.tsx b/invokeai/frontend/web/src/features/ui/components/InvokeTabs.tsx index b7176260b8..07c4167709 100644 --- a/invokeai/frontend/web/src/features/ui/components/InvokeTabs.tsx +++ b/invokeai/frontend/web/src/features/ui/components/InvokeTabs.tsx @@ -15,6 +15,7 @@ import ImageGalleryContent from 'features/gallery/components/ImageGalleryContent import NodeEditorPanelGroup from 'features/nodes/components/sidePanel/NodeEditorPanelGroup'; import InvokeAILogoComponent from 'features/system/components/InvokeAILogoComponent'; import SettingsMenu from 'features/system/components/SettingsModal/SettingsMenu'; +import StatusIndicator from 'features/system/components/StatusIndicator'; import type { UsePanelOptions } from 'features/ui/hooks/usePanel'; import { usePanel } from 'features/ui/hooks/usePanel'; import { usePanelStorage } from 'features/ui/hooks/usePanelStorage'; @@ -125,17 +126,17 @@ const InvokeTabs = () => { () => enabledTabs.map((tab) => ( - + + + )), [enabledTabs, t, handleClickTab, activeTabName] @@ -254,13 +255,14 @@ const InvokeTabs = () => { p={4} isLazy > - + - + {tabs} - - + + +