add various actions for commercial purposes

This commit is contained in:
Mary Hipp 2024-01-12 14:29:45 -05:00 committed by psychedelicious
parent 7366913a31
commit 9722135cda
15 changed files with 111 additions and 19 deletions

View File

@ -8,6 +8,7 @@ import { queueApi } from 'services/api/endpoints/queue';
import { theme, TOAST_OPTIONS } from 'theme/theme'; import { theme, TOAST_OPTIONS } from 'theme/theme';
import { startAppListening } from '..'; import { startAppListening } from '..';
import { batchEnqueued } from '../../../actions';
const { toast } = createStandaloneToast({ const { toast } = createStandaloneToast({
theme: theme, theme: theme,
@ -19,6 +20,7 @@ export const addBatchEnqueuedListener = () => {
startAppListening({ startAppListening({
matcher: queueApi.endpoints.enqueueBatch.matchFulfilled, matcher: queueApi.endpoints.enqueueBatch.matchFulfilled,
effect: async (action) => { effect: async (action) => {
console.log({ action })
const response = action.payload; const response = action.payload;
const arg = action.meta.arg.originalArgs; const arg = action.meta.arg.originalArgs;
logger('queue').debug( logger('queue').debug(

View File

@ -17,6 +17,7 @@ import { boardsApi } from 'services/api/endpoints/boards';
import { imagesApi } from 'services/api/endpoints/images'; import { imagesApi } from 'services/api/endpoints/images';
import { startAppListening } from '..'; import { startAppListening } from '..';
import { imageUploaded } from '../../../../../features/gallery/store/actions';
export const addImageUploadedFulfilledListener = () => { export const addImageUploadedFulfilledListener = () => {
startAppListening({ startAppListening({
@ -40,6 +41,8 @@ export const addImageUploadedFulfilledListener = () => {
return; return;
} }
dispatch(imageUploaded({ postUploadAction: postUploadAction?.type }))
const DEFAULT_UPLOADED_TOAST: UseToastOptions = { const DEFAULT_UPLOADED_TOAST: UseToastOptions = {
title: t('toast.imageUploaded'), title: t('toast.imageUploaded'),
status: 'success', status: 'success',

View File

@ -5,6 +5,8 @@ import type { InvExpanderProps } from 'common/components/InvExpander/types';
import { InvText } from 'common/components/InvText/wrapper'; import { InvText } from 'common/components/InvText/wrapper';
import { t } from 'i18next'; import { t } from 'i18next';
import { BiCollapseVertical, BiExpandVertical } from 'react-icons/bi'; import { BiCollapseVertical, BiExpandVertical } from 'react-icons/bi';
import { useAppDispatch } from '../../../app/store/storeHooks';
import { useCallback } from 'react';
const buttonStyles: SystemStyleObject = { const buttonStyles: SystemStyleObject = {
color: 'base.400', color: 'base.400',
@ -23,9 +25,15 @@ export const InvExpander = ({
children, children,
label = t('common.advancedOptions'), label = t('common.advancedOptions'),
defaultIsOpen = false, defaultIsOpen = false,
onClick,
}: InvExpanderProps) => { }: InvExpanderProps) => {
const { isOpen, onToggle } = useDisclosure({ defaultIsOpen }); const { isOpen, onToggle } = useDisclosure({ defaultIsOpen });
const onToggleExpander = useCallback(() => {
onClick && onClick(isOpen);
onToggle();
}, [onClick, onToggle, isOpen]);
return ( return (
<Flex flexDir="column" w="full"> <Flex flexDir="column" w="full">
<Flex <Flex
@ -35,7 +43,7 @@ export const InvExpander = ({
gap={3} gap={3}
py={4} py={4}
px={2} px={2}
onClick={onToggle} onClick={onToggleExpander}
sx={buttonStyles} sx={buttonStyles}
> >
<Divider w="unset" flexGrow={1} sx={buttonStyles} /> <Divider w="unset" flexGrow={1} sx={buttonStyles} />

View File

@ -1,6 +1,8 @@
import { ThunkAction } from '@reduxjs/toolkit';
import type { PropsWithChildren } from 'react'; import type { PropsWithChildren } from 'react';
export type InvExpanderProps = PropsWithChildren<{ export type InvExpanderProps = PropsWithChildren<{
label?: string; label?: string;
defaultIsOpen?: boolean; defaultIsOpen?: boolean;
onClick?: (isOpen: boolean) => void
}>; }>;

View File

@ -4,21 +4,35 @@ import {
InvAccordionItem, InvAccordionItem,
InvAccordionPanel, InvAccordionPanel,
} from 'common/components/InvAccordion/wrapper'; } from 'common/components/InvAccordion/wrapper';
import { memo } from 'react'; import { memo, useCallback } from 'react';
import type { InvSingleAccordionProps } from './types'; import type { InvSingleAccordionProps } from './types';
export const InvSingleAccordion = memo((props: InvSingleAccordionProps) => { export const InvSingleAccordion = memo((props: InvSingleAccordionProps) => {
const handleAccordionClick = useCallback(
(isExpanded: boolean) => {
props.onClick && props.onClick(isExpanded);
},
[props.onClick]
);
return ( return (
<InvAccordion <InvAccordion
allowToggle allowToggle
defaultIndex={props.defaultIsOpen ? 0 : undefined} defaultIndex={props.defaultIsOpen ? 0 : undefined}
> >
<InvAccordionItem> <InvAccordionItem>
<InvAccordionButton badges={props.badges}> {({ isExpanded }) => (
<>
<InvAccordionButton
badges={props.badges}
onClick={() => handleAccordionClick(isExpanded)}
>
{props.label} {props.label}
</InvAccordionButton> </InvAccordionButton>
<InvAccordionPanel>{props.children}</InvAccordionPanel> <InvAccordionPanel>{props.children}</InvAccordionPanel>
</>
)}
</InvAccordionItem> </InvAccordionItem>
</InvAccordion> </InvAccordion>
); );

View File

@ -4,4 +4,5 @@ export type InvSingleAccordionProps = PropsWithChildren<{
label: string; label: string;
badges?: (string | number)[]; badges?: (string | number)[];
defaultIsOpen?: boolean; defaultIsOpen?: boolean;
onClick?: (isOpen?: boolean) => void
}>; }>;

View File

@ -20,6 +20,7 @@ import { useBoardName } from 'services/api/hooks/useBoardName';
import type { BoardDTO } from 'services/api/types'; import type { BoardDTO } from 'services/api/types';
import GalleryBoardContextMenuItems from './GalleryBoardContextMenuItems'; import GalleryBoardContextMenuItems from './GalleryBoardContextMenuItems';
import { bulkDownloadRequested } from '../../store/actions';
type Props = { type Props = {
board?: BoardDTO; board?: BoardDTO;
@ -66,6 +67,8 @@ const BoardContextMenu = ({
board_id: board_id, board_id: board_id,
}).unwrap(); }).unwrap();
dispatch(bulkDownloadRequested({ type: 'board' }));
dispatch( dispatch(
addToast({ addToast({
title: t('gallery.preparingDownload'), title: t('gallery.preparingDownload'),

View File

@ -3,14 +3,19 @@ import { memo, useCallback } from 'react';
import { useTranslation } from 'react-i18next'; import { useTranslation } from 'react-i18next';
import { PiPlusBold } from 'react-icons/pi'; import { PiPlusBold } from 'react-icons/pi';
import { useCreateBoardMutation } from 'services/api/endpoints/boards'; import { useCreateBoardMutation } from 'services/api/endpoints/boards';
import { useAppDispatch } from '../../../../../app/store/storeHooks';
import { boardCreated } from '../../../store/actions';
const AddBoardButton = () => { const AddBoardButton = () => {
const { t } = useTranslation(); const { t } = useTranslation();
const [createBoard, { isLoading }] = useCreateBoardMutation(); const [createBoard, { isLoading }] = useCreateBoardMutation();
const dispatch = useAppDispatch();
const DEFAULT_BOARD_NAME = t('boards.myBoard'); const DEFAULT_BOARD_NAME = t('boards.myBoard');
const handleCreateBoard = useCallback(() => { const handleCreateBoard = useCallback(async () => {
createBoard(DEFAULT_BOARD_NAME); await createBoard(DEFAULT_BOARD_NAME).unwrap();
}, [createBoard, DEFAULT_BOARD_NAME]); dispatch(boardCreated());
}, [createBoard, DEFAULT_BOARD_NAME, dispatch]);
return ( return (
<InvIconButton <InvIconButton

View File

@ -24,6 +24,7 @@ import {
useStarImagesMutation, useStarImagesMutation,
useUnstarImagesMutation, useUnstarImagesMutation,
} from 'services/api/endpoints/images'; } from 'services/api/endpoints/images';
import { bulkDownloadRequested } from '../../store/actions';
const MultipleSelectionMenuItems = () => { const MultipleSelectionMenuItems = () => {
const { t } = useTranslation(); const { t } = useTranslation();
@ -61,6 +62,8 @@ const MultipleSelectionMenuItems = () => {
image_names: selection.map((img) => img.image_name), image_names: selection.map((img) => img.image_name),
}).unwrap(); }).unwrap();
dispatch(bulkDownloadRequested({ type: 'images' }));
dispatch( dispatch(
addToast({ addToast({
title: t('gallery.preparingDownload'), title: t('gallery.preparingDownload'),

View File

@ -15,3 +15,8 @@ export const requestedBoardImagesDeletion =
export const sentImageToCanvas = createAction('gallery/sentImageToCanvas'); export const sentImageToCanvas = createAction('gallery/sentImageToCanvas');
export const sentImageToImg2Img = createAction('gallery/sentImageToImg2Img'); export const sentImageToImg2Img = createAction('gallery/sentImageToImg2Img');
export const imageUploaded = createAction<{ postUploadAction?: string }>('gallery/imageUploaded');
export const boardCreated = createAction('gallery/boardCreated');
export const bulkDownloadRequested = createAction<{ type: string }>('gallery/bulkDownloadRequested')

View File

@ -12,6 +12,9 @@ import { memo, useCallback, useRef } from 'react';
import type { HotkeyCallback } from 'react-hotkeys-hook'; import type { HotkeyCallback } from 'react-hotkeys-hook';
import { useHotkeys } from 'react-hotkeys-hook'; import { useHotkeys } from 'react-hotkeys-hook';
import { useTranslation } from 'react-i18next'; import { useTranslation } from 'react-i18next';
import { FaDice } from 'react-icons/fa';
import { InvTooltip } from '../../../../common/components/InvTooltip/InvTooltip';
import { InvIconButton } from '../../../../common/components/InvIconButton/InvIconButton';
export const ParamPositivePrompt = memo(() => { export const ParamPositivePrompt = memo(() => {
const dispatch = useAppDispatch(); const dispatch = useAppDispatch();
@ -71,8 +74,18 @@ export const ParamPositivePrompt = memo(() => {
/> />
<PromptOverlayButtonWrapper> <PromptOverlayButtonWrapper>
<AddEmbeddingButton isOpen={isOpen} onOpen={onOpen} /> <AddEmbeddingButton isOpen={isOpen} onOpen={onOpen} />
{baseModel === 'sdxl' && <SDXLConcatButton />} <SDXLConcatButton />
<ShowDynamicPromptsPreviewButton /> <ShowDynamicPromptsPreviewButton />
<InvTooltip label={'Shuffle Prompt'}>
<InvIconButton
size="sm"
variant="promptOverlay"
// isDisabled={isOpen}
aria-label={t('dynamicPrompts.showDynamicPrompts')}
icon={<FaDice />}
// onClick={onOpen}
/>
</InvTooltip>
</PromptOverlayButtonWrapper> </PromptOverlayButtonWrapper>
</Box> </Box>
</EmbeddingPopover> </EmbeddingPopover>

View File

@ -8,3 +8,8 @@ export const initialImageSelected = createAction<ImageDTO | undefined>(
export const modelSelected = createAction<MainModelField>( export const modelSelected = createAction<MainModelField>(
'generation/modelSelected' 'generation/modelSelected'
); );
export const imageAdvancedOptionsExpanded = createAction('parameters/imageAdvancedOptionsExpanded')
export const generationAdvancedOptionsExpanded = createAction('parameters/generationAdvancedOptionsExpanded')
export const advancedPanelExpanded = createAction('parameters/advancedPanelExpanded')

View File

@ -1,6 +1,6 @@
import { Flex } from '@chakra-ui/layout'; import { Flex } from '@chakra-ui/layout';
import { createMemoizedSelector } from 'app/store/createMemoizedSelector'; import { createMemoizedSelector } from 'app/store/createMemoizedSelector';
import { useAppSelector } from 'app/store/storeHooks'; import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
import { InvControlGroup } from 'common/components/InvControl/InvControlGroup'; import { InvControlGroup } from 'common/components/InvControl/InvControlGroup';
import type { InvLabelProps } from 'common/components/InvControl/types'; import type { InvLabelProps } from 'common/components/InvControl/types';
import { InvSingleAccordion } from 'common/components/InvSingleAccordion/InvSingleAccordion'; import { InvSingleAccordion } from 'common/components/InvSingleAccordion/InvSingleAccordion';
@ -11,8 +11,9 @@ import ParamSeamlessYAxis from 'features/parameters/components/Seamless/ParamSea
import ParamVAEModelSelect from 'features/parameters/components/VAEModel/ParamVAEModelSelect'; import ParamVAEModelSelect from 'features/parameters/components/VAEModel/ParamVAEModelSelect';
import ParamVAEPrecision from 'features/parameters/components/VAEModel/ParamVAEPrecision'; import ParamVAEPrecision from 'features/parameters/components/VAEModel/ParamVAEPrecision';
import { selectGenerationSlice } from 'features/parameters/store/generationSlice'; import { selectGenerationSlice } from 'features/parameters/store/generationSlice';
import { memo } from 'react'; import { memo, useCallback } from 'react';
import { useTranslation } from 'react-i18next'; import { useTranslation } from 'react-i18next';
import { advancedPanelExpanded } from '../../parameters/store/actions';
const labelProps: InvLabelProps = { const labelProps: InvLabelProps = {
minW: '9.2rem', minW: '9.2rem',
@ -51,9 +52,20 @@ const selectBadges = createMemoizedSelector(
export const AdvancedSettingsAccordion = memo(() => { export const AdvancedSettingsAccordion = memo(() => {
const badges = useAppSelector(selectBadges); const badges = useAppSelector(selectBadges);
const { t } = useTranslation(); const { t } = useTranslation();
const dispatch = useAppDispatch();
const onAccordionClick = useCallback((isOpen?: boolean) => {
if (!isOpen) {
dispatch(advancedPanelExpanded());
}
}, []);
return ( return (
<InvSingleAccordion label={t('accordions.advanced.title')} badges={badges}> <InvSingleAccordion
label={t('accordions.advanced.title')}
badges={badges}
onClick={onAccordionClick}
>
<Flex gap={4} alignItems="center" p={4} flexDir="column"> <Flex gap={4} alignItems="center" p={4} flexDir="column">
<Flex gap={4} w="full"> <Flex gap={4} w="full">
<ParamVAEModelSelect /> <ParamVAEModelSelect />

View File

@ -1,6 +1,6 @@
import { Flex } from '@chakra-ui/layout'; import { Flex } from '@chakra-ui/layout';
import { createMemoizedSelector } from 'app/store/createMemoizedSelector'; import { createMemoizedSelector } from 'app/store/createMemoizedSelector';
import { useAppSelector } from 'app/store/storeHooks'; import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
import { InvControlGroup } from 'common/components/InvControl/InvControlGroup'; import { InvControlGroup } from 'common/components/InvControl/InvControlGroup';
import type { InvLabelProps } from 'common/components/InvControl/types'; import type { InvLabelProps } from 'common/components/InvControl/types';
import { InvExpander } from 'common/components/InvExpander/InvExpander'; import { InvExpander } from 'common/components/InvExpander/InvExpander';
@ -22,8 +22,9 @@ import ParamSteps from 'features/parameters/components/Core/ParamSteps';
import ParamMainModelSelect from 'features/parameters/components/MainModel/ParamMainModelSelect'; import ParamMainModelSelect from 'features/parameters/components/MainModel/ParamMainModelSelect';
import { selectGenerationSlice } from 'features/parameters/store/generationSlice'; import { selectGenerationSlice } from 'features/parameters/store/generationSlice';
import { size } from 'lodash-es'; import { size } from 'lodash-es';
import { memo } from 'react'; import { memo, useCallback } from 'react';
import { useTranslation } from 'react-i18next'; import { useTranslation } from 'react-i18next';
import { generationAdvancedOptionsExpanded } from '../../parameters/store/actions';
const labelProps: InvLabelProps = { const labelProps: InvLabelProps = {
minW: '4rem', minW: '4rem',
@ -47,6 +48,13 @@ const badgesSelector = createMemoizedSelector(
export const GenerationSettingsAccordion = memo(() => { export const GenerationSettingsAccordion = memo(() => {
const { t } = useTranslation(); const { t } = useTranslation();
const { loraTabBadges, accordionBadges } = useAppSelector(badgesSelector); const { loraTabBadges, accordionBadges } = useAppSelector(badgesSelector);
const dispatch = useAppDispatch();
const onToggleExpander = useCallback((isOpen?: boolean) => {
if (!isOpen) {
dispatch(generationAdvancedOptionsExpanded());
}
}, []);
return ( return (
<InvSingleAccordion <InvSingleAccordion
@ -67,7 +75,7 @@ export const GenerationSettingsAccordion = memo(() => {
<ParamMainModelSelect /> <ParamMainModelSelect />
<SyncModelsIconButton /> <SyncModelsIconButton />
</Flex> </Flex>
<InvExpander> <InvExpander onClick={onToggleExpander}>
<Flex gap={4} flexDir="column" pb={4}> <Flex gap={4} flexDir="column" pb={4}>
<InvControlGroup labelProps={labelProps}> <InvControlGroup labelProps={labelProps}>
<ParamScheduler /> <ParamScheduler />

View File

@ -1,6 +1,6 @@
import { Flex } from '@chakra-ui/react'; import { Flex } from '@chakra-ui/react';
import { createMemoizedSelector } from 'app/store/createMemoizedSelector'; import { createMemoizedSelector } from 'app/store/createMemoizedSelector';
import { useAppSelector } from 'app/store/storeHooks'; import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
import { InvControlGroup } from 'common/components/InvControl/InvControlGroup'; import { InvControlGroup } from 'common/components/InvControl/InvControlGroup';
import type { InvLabelProps } from 'common/components/InvControl/types'; import type { InvLabelProps } from 'common/components/InvControl/types';
import { InvExpander } from 'common/components/InvExpander/InvExpander'; import { InvExpander } from 'common/components/InvExpander/InvExpander';
@ -18,11 +18,12 @@ import { ParamSeedRandomize } from 'features/parameters/components/Seed/ParamSee
import { ParamSeedShuffle } from 'features/parameters/components/Seed/ParamSeedShuffle'; import { ParamSeedShuffle } from 'features/parameters/components/Seed/ParamSeedShuffle';
import { selectGenerationSlice } from 'features/parameters/store/generationSlice'; import { selectGenerationSlice } from 'features/parameters/store/generationSlice';
import { activeTabNameSelector } from 'features/ui/store/uiSelectors'; import { activeTabNameSelector } from 'features/ui/store/uiSelectors';
import { memo } from 'react'; import { memo, useCallback } from 'react';
import { useTranslation } from 'react-i18next'; import { useTranslation } from 'react-i18next';
import { ImageSizeCanvas } from './ImageSizeCanvas'; import { ImageSizeCanvas } from './ImageSizeCanvas';
import { ImageSizeLinear } from './ImageSizeLinear'; import { ImageSizeLinear } from './ImageSizeLinear';
import { imageAdvancedOptionsExpanded } from '../../parameters/store/actions';
const selector = createMemoizedSelector( const selector = createMemoizedSelector(
[ [
@ -73,6 +74,13 @@ const scalingLabelProps: InvLabelProps = {
export const ImageSettingsAccordion = memo(() => { export const ImageSettingsAccordion = memo(() => {
const { t } = useTranslation(); const { t } = useTranslation();
const { badges, activeTabName } = useAppSelector(selector); const { badges, activeTabName } = useAppSelector(selector);
const dispatch = useAppDispatch();
const onToggleExpander = useCallback((isOpen?: boolean) => {
if (!isOpen) {
dispatch(imageAdvancedOptionsExpanded());
}
}, []);
return ( return (
<InvSingleAccordion <InvSingleAccordion
@ -86,7 +94,7 @@ export const ImageSettingsAccordion = memo(() => {
) : ( ) : (
<ImageSizeLinear /> <ImageSizeLinear />
)} )}
<InvExpander> <InvExpander onClick={onToggleExpander}>
<Flex gap={4} pb={4} flexDir="column"> <Flex gap={4} pb={4} flexDir="column">
<Flex gap={4} alignItems="center"> <Flex gap={4} alignItems="center">
<ParamSeedNumberInput /> <ParamSeedNumberInput />