Skip to content

Commit

Permalink
Merge branch 'main' into fix-begin-end-validation
Browse files Browse the repository at this point in the history
  • Loading branch information
JPPhoto authored Feb 6, 2025
2 parents 0f20503 + 25bb96e commit 2ec34b9
Show file tree
Hide file tree
Showing 27 changed files with 378 additions and 169 deletions.
163 changes: 86 additions & 77 deletions invokeai/app/services/shared/graph.py

Large diffs are not rendered by default.

1 change: 0 additions & 1 deletion invokeai/frontend/web/public/locales/de.json
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,6 @@
"autoAssignBoardOnClick": "Board per Klick automatisch zuweisen",
"noImageSelected": "Kein Bild ausgewählt",
"starImage": "Bild markieren",
"assets": "Ressourcen",
"unstarImage": "Markierung entfernen",
"image": "Bild",
"deleteSelection": "Lösche Auswahl",
Expand Down
23 changes: 17 additions & 6 deletions invokeai/frontend/web/public/locales/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -305,8 +305,8 @@
},
"gallery": {
"gallery": "Gallery",
"alwaysShowImageSizeBadge": "Always Show Image Size Badge",
"assets": "Assets",
"alwaysShowImageSizeBadge": "Always Show Image Size Badge",
"assetsTab": "Files you’ve uploaded for use in your projects.",
"autoAssignBoardOnClick": "Auto-Assign Board on Click",
"autoSwitchNewImages": "Auto-Switch to New Images",
Expand Down Expand Up @@ -1248,6 +1248,8 @@
"problemCopyingLayer": "Unable to Copy Layer",
"problemSavingLayer": "Unable to Save Layer",
"problemDownloadingImage": "Unable to Download Image",
"pasteSuccess": "Pasted to {{destination}}",
"pasteFailed": "Paste Failed",
"prunedQueue": "Pruned Queue",
"sentToCanvas": "Sent to Canvas",
"sentToUpscale": "Sent to Upscale",
Expand Down Expand Up @@ -1816,6 +1818,14 @@
"newControlLayer": "New $t(controlLayers.controlLayer)",
"newInpaintMask": "New $t(controlLayers.inpaintMask)",
"newRegionalGuidance": "New $t(controlLayers.regionalGuidance)",
"pasteTo": "Paste To",
"pasteToAssets": "Assets",
"pasteToAssetsDesc": "Paste to Assets",
"pasteToBbox": "Bbox",
"pasteToBboxDesc": "New Layer (in Bbox)",
"pasteToCanvas": "Canvas",
"pasteToCanvasDesc": "New Layer (in Canvas)",
"pastedTo": "Pasted to {{destination}}",
"transparency": "Transparency",
"enableTransparencyEffect": "Enable Transparency Effect",
"disableTransparencyEffect": "Disable Transparency Effect",
Expand Down Expand Up @@ -2235,11 +2245,12 @@
"whatsNew": {
"whatsNewInInvoke": "What's New in Invoke",
"items": [
"Low-VRAM mode",
"Dynamic memory management",
"Faster model loading times",
"Fewer memory errors",
"Expanded workflow batch capabilities"
"Improved VRAM setting defaults",
"On-demand model cache clearing",
"Expanded FLUX LoRA compatibility",
"Canvas Adjust Image filter",
"Cancel all but current queue item",
"Copy from and paste to Canvas"
],
"readReleaseNotes": "Read Release Notes",
"watchRecentReleaseVideos": "Watch Recent Release Videos",
Expand Down
1 change: 0 additions & 1 deletion invokeai/frontend/web/public/locales/es.json
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,6 @@
"deleteImage_many": "Eliminar {{count}} Imágenes",
"deleteImage_other": "Eliminar {{count}} Imágenes",
"deleteImagePermanent": "Las imágenes eliminadas no se pueden restaurar.",
"assets": "Activos",
"autoAssignBoardOnClick": "Asignar automática tableros al hacer clic",
"gallery": "Galería",
"noImageSelected": "Sin imágenes seleccionadas",
Expand Down
1 change: 0 additions & 1 deletion invokeai/frontend/web/public/locales/fr.json
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,6 @@
"sortDirection": "Direction de tri",
"sideBySide": "Côte-à-Côte",
"hover": "Au passage de la souris",
"assets": "Ressources",
"alwaysShowImageSizeBadge": "Toujours montrer le badge de taille de l'Image",
"gallery": "Galerie",
"bulkDownloadRequestFailed": "Problème lors de la préparation du téléchargement",
Expand Down
26 changes: 24 additions & 2 deletions invokeai/frontend/web/public/locales/it.json
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,6 @@
"deleteImage_many": "Elimina {{count}} immagini",
"deleteImage_other": "Elimina {{count}} immagini",
"deleteImagePermanent": "Le immagini eliminate non possono essere ripristinate.",
"assets": "Risorse",
"autoAssignBoardOnClick": "Assegna automaticamente la bacheca al clic",
"featuresWillReset": "Se elimini questa immagine, quelle funzionalità verranno immediatamente ripristinate.",
"loading": "Caricamento in corso",
Expand Down Expand Up @@ -1132,7 +1131,11 @@
"generation": "Generazione",
"other": "Altro",
"gallery": "Galleria",
"batchSize": "Dimensione del lotto"
"batchSize": "Dimensione del lotto",
"cancelAllExceptCurrentQueueItemAlertDialog2": "Vuoi davvero annullare tutti gli elementi in coda in sospeso?",
"confirm": "Conferma",
"cancelAllExceptCurrentQueueItemAlertDialog": "L'annullamento di tutti gli elementi della coda, eccetto quello corrente, interromperà gli elementi in sospeso ma consentirà il completamento di quello in corso.",
"cancelAllExceptCurrentTooltip": "Annulla tutto tranne l'elemento corrente"
},
"models": {
"noMatchingModels": "Nessun modello corrispondente",
Expand Down Expand Up @@ -1963,6 +1966,25 @@
"noise_type": "Tipo di rumore",
"label": "Aggiungi rumore",
"noise_amount": "Quantità"
},
"adjust_image": {
"description": "Regola il canale selezionato di un'immagine.",
"alpha": "Alfa (RGBA)",
"label": "Regola l'immagine",
"blue": "Blu (RGBA)",
"luminosity": "Luminosità (LAB)",
"channel": "Canale",
"value_setting": "Valore",
"scale_values": "Scala i valori",
"red": "Rosso (RGBA)",
"green": "Verde (RGBA)",
"cyan": "Ciano (CMYK)",
"magenta": "Magenta (CMYK)",
"yellow": "Giallo (CMYK)",
"black": "Nero (CMYK)",
"hue": "Tonalità (HSV)",
"saturation": "Saturazione (HSV)",
"value": "Valore (HSV)"
}
},
"controlLayers_withCount_hidden": "Livelli di controllo ({{count}} nascosti)",
Expand Down
1 change: 0 additions & 1 deletion invokeai/frontend/web/public/locales/ja.json
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,6 @@
"featuresWillReset": "この画像を削除すると、これらの機能は即座にリセットされます。",
"unstarImage": "スターを外す",
"loading": "ロード中",
"assets": "アセット",
"currentlyInUse": "この画像は現在下記の機能を使用しています:",
"drop": "ドロップ",
"dropOrUpload": "$t(gallery.drop) またはアップロード",
Expand Down
1 change: 0 additions & 1 deletion invokeai/frontend/web/public/locales/ko.json
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,6 @@
"gallerySettings": "갤러리 설정",
"deleteSelection": "선택 항목 삭제",
"featuresWillReset": "이 이미지를 삭제하면 해당 기능이 즉시 재설정됩니다.",
"assets": "자산",
"noImagesInGallery": "보여줄 이미지가 없음",
"autoSwitchNewImages": "새로운 이미지로 자동 전환",
"loading": "불러오는 중",
Expand Down
1 change: 0 additions & 1 deletion invokeai/frontend/web/public/locales/nl.json
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,6 @@
"deleteImage_one": "Verwijder afbeelding",
"deleteImage_other": "",
"deleteImagePermanent": "Verwijderde afbeeldingen kunnen niet worden hersteld.",
"assets": "Eigen onderdelen",
"autoAssignBoardOnClick": "Ken automatisch bord toe bij klikken",
"featuresWillReset": "Als je deze afbeelding verwijdert, dan worden deze functies onmiddellijk teruggezet.",
"loading": "Bezig met laden",
Expand Down
1 change: 0 additions & 1 deletion invokeai/frontend/web/public/locales/pl.json
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,6 @@
"assetsTab": "Pliki, które wrzuciłeś do użytku w twoich projektach.",
"currentlyInUse": "Ten obraz jest obecnie w użyciu przez następujące funkcje:",
"boardsSettings": "Ustawienia tablic",
"assets": "Aktywy",
"autoAssignBoardOnClick": "Automatycznie przypisz tablicę po kliknięciu",
"copy": "Kopiuj"
},
Expand Down
1 change: 0 additions & 1 deletion invokeai/frontend/web/public/locales/ru.json
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,6 @@
"deleteImage_one": "Удалить изображение",
"deleteImage_few": "Удалить {{count}} изображения",
"deleteImage_many": "Удалить {{count}} изображений",
"assets": "Ресурсы",
"autoAssignBoardOnClick": "Авто-назначение доски по клику",
"deleteSelection": "Удалить выделенное",
"featuresWillReset": "Если вы удалите это изображение, эти функции будут немедленно сброшены.",
Expand Down
1 change: 0 additions & 1 deletion invokeai/frontend/web/public/locales/tr.json
Original file line number Diff line number Diff line change
Expand Up @@ -195,7 +195,6 @@
},
"gallery": {
"deleteImagePermanent": "Silinen görseller geri getirilemez.",
"assets": "Özkaynaklar",
"autoAssignBoardOnClick": "Tıklanan Panoya Otomatik Atama",
"loading": "Yükleniyor",
"starImage": "Yıldız Koy",
Expand Down
1 change: 0 additions & 1 deletion invokeai/frontend/web/public/locales/vi.json
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,6 @@
"bulkDownloadRequestedDesc": "Yêu cầu tải xuống đang được chuẩn bị. Vui lòng chờ trong giây lát.",
"starImage": "Gắn Sao Cho Ảnh",
"openViewer": "Mở Trình Xem",
"assets": "Tài Nguyên",
"viewerImage": "Trình Xem Ảnh",
"sideBySide": "Cạnh Nhau",
"alwaysShowImageSizeBadge": "Luôn Hiển Thị Kích Thước Ảnh",
Expand Down
1 change: 0 additions & 1 deletion invokeai/frontend/web/public/locales/zh_CN.json
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,6 @@
"noImagesInGallery": "无图像可用于显示",
"deleteImage_other": "删除{{count}}张图片",
"deleteImagePermanent": "删除的图片无法被恢复。",
"assets": "素材",
"autoAssignBoardOnClick": "点击后自动分配面板",
"featuresWillReset": "如果您删除该图像,这些功能会立即被重置。",
"loading": "加载中",
Expand Down
5 changes: 5 additions & 0 deletions invokeai/frontend/web/src/app/components/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,12 @@ import { useFocusRegionWatcher } from 'common/hooks/focus';
import { useClearStorage } from 'common/hooks/useClearStorage';
import { useGlobalHotkeys } from 'common/hooks/useGlobalHotkeys';
import ChangeBoardModal from 'features/changeBoardModal/components/ChangeBoardModal';
import { CanvasPasteModal } from 'features/controlLayers/components/CanvasPasteModal';
import {
NewCanvasSessionDialog,
NewGallerySessionDialog,
} from 'features/controlLayers/components/NewSessionConfirmationAlertDialog';
import { CanvasManagerProviderGate } from 'features/controlLayers/contexts/CanvasManagerProviderGate';
import DeleteImageModal from 'features/deleteImageModal/components/DeleteImageModal';
import { FullscreenDropzone } from 'features/dnd/FullscreenDropzone';
import { DynamicPromptsModal } from 'features/dynamicPrompts/components/DynamicPromptsPreviewModal';
Expand Down Expand Up @@ -112,6 +114,9 @@ const App = ({ config = DEFAULT_CONFIG, studioInitAction }: Props) => {
<ImageContextMenu />
<FullscreenDropzone />
<VideosModal />
<CanvasManagerProviderGate>
<CanvasPasteModal />
</CanvasManagerProviderGate>
</ErrorBoundary>
);
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import type { AppStartListening } from 'app/store/middleware/listenerMiddleware'
import { zPydanticValidationError } from 'features/system/store/zodSchemas';
import { toast } from 'features/toast/toast';
import { t } from 'i18next';
import { truncate, upperFirst } from 'lodash-es';
import { truncate } from 'lodash-es';
import { serializeError } from 'serialize-error';
import { queueApi } from 'services/api/endpoints/queue';
import type { JsonObject } from 'type-fest';
Expand Down Expand Up @@ -52,15 +52,12 @@ export const addBatchEnqueuedListener = (startAppListening: AppStartListening) =
const result = zPydanticValidationError.safeParse(response);
if (result.success) {
result.data.data.detail.map((e) => {
const description = truncate(e.msg.replace(/^(Value|Index|Key) error, /i, ''), { length: 256 });
toast({
id: 'QUEUE_BATCH_FAILED',
title: truncate(upperFirst(e.msg), { length: 128 }),
title: t('queue.batchFailedToQueue'),
status: 'error',
description: truncate(
`Path:
${e.loc.join('.')}`,
{ length: 128 }
),
description,
});
});
} else if (response.status !== 403) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ import { Menu, MenuButton, MenuGroup, MenuItem, MenuList } from '@invoke-ai/ui-l
import { SubMenuButtonContent, useSubMenu } from 'common/hooks/useSubMenu';
import { CanvasContextMenuItemsCropCanvasToBbox } from 'features/controlLayers/components/CanvasContextMenu/CanvasContextMenuItemsCropCanvasToBbox';
import { NewLayerIcon } from 'features/controlLayers/components/common/icons';
import { useCopyCanvasToClipboard } from 'features/controlLayers/hooks/copyHooks';
import {
useCopyCanvasToClipboard,
useNewControlLayerFromBbox,
useNewGlobalReferenceImageFromBbox,
useNewRasterLayerFromBbox,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,150 @@
import {
Button,
Flex,
Modal,
ModalBody,
ModalCloseButton,
ModalContent,
ModalFooter,
ModalHeader,
ModalOverlay,
} from '@invoke-ai/ui-library';
import { useStore } from '@nanostores/react';
import { useAppStore } from 'app/store/nanostores/store';
import { useAppSelector } from 'app/store/storeHooks';
import { useAssertSingleton } from 'common/hooks/useAssertSingleton';
import { useCanvasManager } from 'features/controlLayers/contexts/CanvasManagerProviderGate';
import { selectAutoAddBoardId } from 'features/gallery/store/gallerySelectors';
import { createNewCanvasEntityFromImage } from 'features/imageActions/actions';
import { toast } from 'features/toast/toast';
import { atom } from 'nanostores';
import { memo, useCallback } from 'react';
import { useTranslation } from 'react-i18next';
import { PiBoundingBoxBold, PiImageBold } from 'react-icons/pi';
import { useUploadImageMutation } from 'services/api/endpoints/images';

const $imageFile = atom<File | null>(null);
export const setFileToPaste = (file: File) => $imageFile.set(file);
const clearFileToPaste = () => $imageFile.set(null);

export const CanvasPasteModal = memo(() => {
useAssertSingleton('CanvasPasteModal');
const { dispatch, getState } = useAppStore();
const { t } = useTranslation();
const imageToPaste = useStore($imageFile);
const canvasManager = useCanvasManager();
const autoAddBoardId = useAppSelector(selectAutoAddBoardId);
const [uploadImage, { isLoading }] = useUploadImageMutation({ fixedCacheKey: 'canvasPasteModal' });

const getPosition = useCallback(
(destination: 'canvas' | 'bbox') => {
const { x, y } = canvasManager.stateApi.getBbox().rect;
if (destination === 'bbox') {
return { x, y };
}
const rasterLayerAdapters = canvasManager.compositor.getVisibleAdaptersOfType('raster_layer');
if (rasterLayerAdapters.length === 0) {
return { x, y };
}
{
const { x, y } = canvasManager.compositor.getRectOfAdapters(rasterLayerAdapters);
return { x, y };
}
},
[canvasManager.compositor, canvasManager.stateApi]
);

const handlePaste = useCallback(
async (file: File, destination: 'assets' | 'canvas' | 'bbox') => {
try {
const is_intermediate = destination !== 'assets';
const imageDTO = await uploadImage({
file,
is_intermediate,
image_category: 'user',
board_id: autoAddBoardId === 'none' ? undefined : autoAddBoardId,
}).unwrap();

if (destination !== 'assets') {
createNewCanvasEntityFromImage({
type: 'raster_layer',
imageDTO,
dispatch,
getState,
overrides: { position: getPosition(destination) },
});
}
} catch {
toast({
title: t('toast.pasteFailed'),
status: 'error',
});
} finally {
clearFileToPaste();
toast({
title: t('toast.pasteSuccess', {
destination:
destination === 'assets'
? t('controlLayers.pasteToAssets')
: destination === 'bbox'
? t('controlLayers.pasteToBbox')
: t('controlLayers.pasteToCanvas'),
}),
status: 'success',
});
}
},
[autoAddBoardId, dispatch, getPosition, getState, t, uploadImage]
);

const pasteToAssets = useCallback(() => {
if (!imageToPaste) {
return;
}
handlePaste(imageToPaste, 'assets');
}, [handlePaste, imageToPaste]);

const pasteToCanvas = useCallback(() => {
if (!imageToPaste) {
return;
}
handlePaste(imageToPaste, 'canvas');
}, [handlePaste, imageToPaste]);

const pasteToBbox = useCallback(() => {
if (!imageToPaste) {
return;
}
handlePaste(imageToPaste, 'bbox');
}, [handlePaste, imageToPaste]);

return (
<Modal isOpen={imageToPaste !== null} onClose={clearFileToPaste} useInert={false} isCentered size="2xl">
<ModalOverlay />
<ModalContent>
<ModalHeader>{t('controlLayers.pasteTo')}</ModalHeader>
<ModalCloseButton />
<ModalBody display="flex" justifyContent="center">
<Flex flexDir="column" gap={4} w="min-content">
<Button size="lg" onClick={pasteToCanvas} isDisabled={isLoading} leftIcon={<PiImageBold />}>
{t('controlLayers.pasteToCanvasDesc')}
</Button>
<Button size="lg" onClick={pasteToBbox} isDisabled={isLoading} leftIcon={<PiBoundingBoxBold />}>
{t('controlLayers.pasteToBboxDesc')}
</Button>
<Button size="lg" onClick={pasteToAssets} isDisabled={isLoading} variant="ghost">
{t('controlLayers.pasteToAssetsDesc')}
</Button>
</Flex>
</ModalBody>
<ModalFooter>
<Button onClick={clearFileToPaste} variant="ghost" isLoading={isLoading}>
{t('common.cancel')}
</Button>
</ModalFooter>
</ModalContent>
</Modal>
);
});

CanvasPasteModal.displayName = 'CanvasPasteModal';
Loading

0 comments on commit 2ec34b9

Please sign in to comment.