tauri fixes

This commit is contained in:
babayaga 2025-09-18 17:15:49 +02:00
parent 002542ac34
commit e3dd519686
8 changed files with 149 additions and 75 deletions

File diff suppressed because one or more lines are too long

Binary file not shown.

View File

@ -28,6 +28,7 @@ function App() {
const [ipcInitialized, setIpcInitialized] = useState(false);
const [messageToSend, setMessageToSend] = useState("");
const [generationTimeoutId, setGenerationTimeoutId] = useState<NodeJS.Timeout | null>(null);
const [currentIndex, setCurrentIndex] = useState(0);
const deleteFilePermanently = async (pathToDelete: string) => {
addDebugMessage('info', `Requesting deletion of file: ${pathToDelete}`);
@ -127,19 +128,30 @@ function App() {
const addFiles = async (newPaths: string[]) => {
const uniqueNewPaths = newPaths.filter(newPath => !files.some(f => f.path === newPath));
const newImageFiles: ImageFile[] = [];
if (uniqueNewPaths.length === 0) {
return;
}
// Update destination directory
const firstPath = uniqueNewPaths[0];
const lastSeparatorIndex = Math.max(firstPath.lastIndexOf('/'), firstPath.lastIndexOf('\\'));
const newDir = firstPath.substring(0, lastSeparatorIndex);
const currentFilename = dst.split(/[/\\]/).pop() || generateDefaultDst(1, firstPath);
const newDst = `${newDir}${firstPath.includes('\\') ? '\\' : '/'}${currentFilename}`;
setDst(newDst);
// Read files
const newImageFiles: ImageFile[] = [];
for (const path of uniqueNewPaths) {
try {
const buffer = await tauriApi.fs.readFile(path);
const base64 = arrayBufferToBase64(Array.from(buffer));
const mimeType = path.toLowerCase().endsWith('.png') ? 'image/png' :
path.toLowerCase().endsWith('.jpg') || path.toLowerCase().endsWith('.jpeg') ? 'image/jpeg' :
'image/png';
const src = `data:${mimeType};base64,${base64}`;
newImageFiles.push({ path, src });
newImageFiles.push({ path, src, selected: false, isGenerated: false });
} catch (e) {
const errorMessage = e instanceof Error ? e.message : JSON.stringify(e);
console.error(`Failed to read file: ${path}`, e);
@ -147,7 +159,20 @@ function App() {
}
}
setFiles(prevFiles => [...prevFiles, ...newImageFiles]);
const lastPath = uniqueNewPaths[uniqueNewPaths.length - 1];
setFiles(prevFiles => {
const combinedFiles = [...prevFiles, ...newImageFiles];
const newIndex = combinedFiles.findIndex(f => f.path === lastPath);
if (newIndex !== -1) {
setCurrentIndex(newIndex);
}
return combinedFiles.map(file => ({
...file,
selected: file.path === lastPath
}));
});
};
const removeFile = (pathToRemove: string) => {
@ -159,7 +184,7 @@ function App() {
};
const handleImageSelection = (imagePath: string, isMultiSelect: boolean) => {
setFiles(prev =>
setFiles(prev =>
prev.map(file => {
if (file.path === imagePath) {
// For multi-select, toggle the current state. For single-select, always select it.
@ -490,6 +515,8 @@ function App() {
onImageDelete={deleteFilePermanently}
onImageSaveAs={saveImageAs}
addFiles={addFiles}
currentIndex={currentIndex}
setCurrentIndex={setCurrentIndex}
/>
{/* Debug Panel */}

View File

@ -8,6 +8,8 @@ interface ImageGalleryProps {
onImageDelete?: (imagePath: string) => void;
onImageSaveAs?: (imagePath: string) => void;
showSelection?: boolean;
currentIndex: number;
setCurrentIndex: (index: number) => void;
}
export default function ImageGallery({
@ -16,9 +18,10 @@ export default function ImageGallery({
onImageRemove,
onImageDelete,
onImageSaveAs,
showSelection = false
showSelection = false,
currentIndex,
setCurrentIndex
}: ImageGalleryProps) {
const [currentIndex, setCurrentIndex] = useState(0);
const [lightboxOpen, setLightboxOpen] = useState(false);
const [lightboxLoaded, setLightboxLoaded] = useState(false);
@ -27,7 +30,7 @@ export default function ImageGallery({
if (images.length > 0 && currentIndex >= images.length) {
setCurrentIndex(Math.max(0, images.length - 1));
}
}, [images.length, currentIndex]);
}, [images.length, currentIndex, setCurrentIndex]);
// ESC key handler for lightbox
useEffect(() => {
@ -51,7 +54,7 @@ export default function ImageGallery({
document.addEventListener('keydown', handleKeyDown);
return () => document.removeEventListener('keydown', handleKeyDown);
}
}, [lightboxOpen, currentIndex, images.length]);
}, [lightboxOpen, currentIndex, images.length, setCurrentIndex]);
const preloadImage = (index: number) => {
if (images.length === 0 || index < 0 || index >= images.length) return;

View File

@ -22,6 +22,8 @@ interface PromptFormProps {
onImageDelete?: (path: string) => void;
onImageSaveAs?: (path: string) => void;
addFiles: (paths: string[]) => void;
currentIndex: number;
setCurrentIndex: (index: number) => void;
}
const PromptForm: React.FC<PromptFormProps> = ({
@ -42,7 +44,9 @@ const PromptForm: React.FC<PromptFormProps> = ({
addImageFromUrl,
onImageDelete,
onImageSaveAs,
addFiles
addFiles,
currentIndex,
setCurrentIndex
}) => {
const selectedCount = getSelectedImages().length;
const { ref: dropZoneRef, dragIn } = useDropZone({ onDrop: addFiles });
@ -67,6 +71,12 @@ const PromptForm: React.FC<PromptFormProps> = ({
placeholder="Describe the image you want to generate or edit..."
className="w-full glass-input p-4 rounded-xl min-h-[120px] resize-none"
rows={4}
onKeyDown={(e) => {
if (e.key === 'Enter' && (e.ctrlKey || e.metaKey)) {
e.preventDefault();
submit();
}
}}
/>
</div>
@ -152,6 +162,8 @@ const PromptForm: React.FC<PromptFormProps> = ({
onImageSaveAs={onImageSaveAs}
showSelection={true}
onImageDelete={onImageDelete}
currentIndex={currentIndex}
setCurrentIndex={setCurrentIndex}
/>
</div>
</div>

View File

@ -15,7 +15,8 @@ const useDropZone = ({ onDrop }: { onDrop: (paths: string[]) => void }) => {
useEffect(() => {
const unlisten = listen<TauriDragDropEvent>("tauri://drag-drop", (e) => {
const { x, y } = e.payload.position;
if (document.elementFromPoint(x, y) === ref.current) {
const element = document.elementFromPoint(x, y);
if (ref.current && element && ref.current.contains(element)) {
onDrop(e.payload.paths);
setDragIn(false);
}
@ -29,7 +30,8 @@ const useDropZone = ({ onDrop }: { onDrop: (paths: string[]) => void }) => {
useEffect(() => {
const unlisten = listen<TauriDragDropEvent>("tauri://drag-over", (e) => {
const { x, y } = e.payload.position;
if (document.elementFromPoint(x, y) === ref.current) {
const element = document.elementFromPoint(x, y);
if (ref.current && element && ref.current.contains(element)) {
setDragIn(true);
} else {
setDragIn(false);

View File

@ -19,6 +19,50 @@ import { prompt as resolvePrompt } from '../prompt.js';
import { spawn } from 'node:child_process';
import { loadConfig } from '../config.js';
function generateUniqueFilename(dst: string | undefined, genFiles: string[]): string {
let dstDir: string;
if (dst) {
const absoluteDst = path.resolve(dst);
const dstStat = exists(absoluteDst) ? statSync(absoluteDst) : null;
if (dstStat && dstStat.isDirectory()) {
dstDir = absoluteDst;
} else {
dstDir = path.dirname(absoluteDst);
}
} else if (genFiles.length > 0) {
dstDir = path.dirname(genFiles[0]);
} else {
dstDir = process.cwd(); // fallback to current working dir
}
let baseFileName;
let i = 0;
if (genFiles.length > 0) {
const originalBaseName = path.basename(genFiles[0], path.extname(genFiles[0]));
const match = originalBaseName.match(/_gen_(\d+)$/);
if (match && match.index) {
baseFileName = originalBaseName.substring(0, match.index);
i = parseInt(match[1], 10) + 1;
} else {
baseFileName = originalBaseName;
}
} else {
baseFileName = 'generated';
}
let newFileName;
let finalDstPath;
do {
newFileName = `${baseFileName}_gen_${i}.png`;
finalDstPath = path.resolve(dstDir, newFileName);
i++;
} while (exists(finalDstPath));
return finalDstPath;
}
function getGuiAppPath(): string {
// Get the directory of this script file, then navigate to the GUI app
@ -217,39 +261,10 @@ async function launchGuiAndGetPrompt(argv: any): Promise<string | null> {
try {
const genPrompt = message.prompt;
const genFiles = message.files || [];
const genDst = message.dst;
// --- New logic for destination path ---
let dstDir: string;
if (argv.dst) {
const absoluteDst = path.resolve(argv.dst);
const dstStat = exists(absoluteDst) ? statSync(absoluteDst) : null;
if (dstStat && dstStat.isDirectory()) {
dstDir = absoluteDst;
} else {
dstDir = path.dirname(absoluteDst);
}
} else if (genFiles.length > 0) {
dstDir = path.dirname(genFiles[0]);
} else {
dstDir = process.cwd(); // fallback to current working dir
}
const baseFileName = genFiles.length > 0
? path.basename(genFiles[0], path.extname(genFiles[0]))
: 'generated';
let i = 0;
let newFileName;
let finalDstPath;
do {
newFileName = `${baseFileName}_gen_${i}.png`;
finalDstPath = path.resolve(dstDir, newFileName);
i++;
} while (exists(finalDstPath));
const finalDstPath = generateUniqueFilename(genDst, genFiles);
logger.info(`📝 Determined destination path for generated image: ${finalDstPath}`);
// --- End new logic ---
logger.info(`🎨 Starting image generation: "${genPrompt}"`);

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.7 MiB