From 2956a0d49f6fe6b6f873c571ad78bf989f2e45fd Mon Sep 17 00:00:00 2001 From: shiva raj badu Date: Mon, 12 May 2025 22:11:20 +0545 Subject: [PATCH 1/2] user upload image implemented --- app/ipc/index.ts | 3 +- app/ipc/upload_image.ts | 28 +++++++++++++++++++ app/preloads/index.ts | 1 + package.json | 2 +- .../components/ImageEditor.tsx | 25 ++++++----------- 5 files changed, 41 insertions(+), 18 deletions(-) create mode 100644 app/ipc/upload_image.ts diff --git a/app/ipc/index.ts b/app/ipc/index.ts index f4a60fc7..137b3dab 100644 --- a/app/ipc/index.ts +++ b/app/ipc/index.ts @@ -4,7 +4,7 @@ import { setupSlideMetadataHandlers } from "./slide_metadata"; import { setupReadFile } from "./read_file"; import { setupFooterHandlers } from "./footer_handlers"; import { setupThemeHandlers } from "./theme_handlers"; - +import { setupUploadImage } from "./upload_image"; export function setupIpcHandlers() { setupExportHandlers(); setupUserConfigHandlers(); @@ -12,4 +12,5 @@ export function setupIpcHandlers() { setupReadFile(); setupFooterHandlers(); setupThemeHandlers(); + setupUploadImage(); } \ No newline at end of file diff --git a/app/ipc/upload_image.ts b/app/ipc/upload_image.ts new file mode 100644 index 00000000..8caa16d7 --- /dev/null +++ b/app/ipc/upload_image.ts @@ -0,0 +1,28 @@ +import { ipcMain } from "electron"; +import path from "path"; +import fs from "fs"; +import crypto from "crypto"; +import { baseDir } from "../utils/constants"; + +export function setupUploadImage() { + ipcMain.handle("upload-image", async (_, file: Buffer) => { + try { + // Create uploads directory if it doesn't exist + const uploadsDir = path.join(baseDir, "uploads"); + fs.mkdirSync(uploadsDir, { recursive: true }); + + // Generate unique filename + const filename = `${crypto.randomBytes(16).toString('hex')}.png`; + const filePath = path.join(uploadsDir, filename); + + // Write file to disk + await fs.writeFileSync(filePath, file); + + // Return the relative path that can be used in the frontend + return `/uploads/${filename}`; + } catch (error) { + console.error("Error saving image:", error); + throw error; + } + }); +} \ No newline at end of file diff --git a/app/preloads/index.ts b/app/preloads/index.ts index 14084829..91ad8fe4 100644 --- a/app/preloads/index.ts +++ b/app/preloads/index.ts @@ -19,4 +19,5 @@ contextBridge.exposeInMainWorld('electron', { setFooter: (userId: string, properties: any) => ipcRenderer.invoke("set-footer", userId, properties), getTheme: (userId: string) => ipcRenderer.invoke("get-theme", userId), setTheme: (userId: string, themeData: any) => ipcRenderer.invoke("set-theme", userId, themeData), + uploadImage: (file: Buffer) => ipcRenderer.invoke("upload-image", file), }); diff --git a/package.json b/package.json index fd944bc9..cb461685 100644 --- a/package.json +++ b/package.json @@ -13,7 +13,7 @@ "setup:env": "npm install && cd servers/fastapi && poetry install && cd ../../servers/nextjs && npm install", "build:ts": "rm -rf app_dist && tsc", "build:css": "tailwindcss -i ./resources/ui/assets/css/tailwind.import.css -o ./resources/ui/assets/css/tailwind.css --watch", - "build:nextjs": "rm -rf resources/nextjs && cd servers/nextjs && npm run build && mv out ../../resources/nextjs", + "build:nextjs": "rm -rf resources/nextjs && cd servers/nextjs && npm run build && cp -r out ../../resources/nextjs", "build:fastapi": "rm -rf resources/fastapi && cd servers/fastapi && .venv/bin/pyinstaller --distpath ../../resources server.spec", "build:electron": "rm -rf app_dist && tsc && node build.js", "clean:build": "rm -rf resources/nextjs && rm -rf resources/fastapi && rm -rf app_dist" diff --git a/servers/nextjs/app/(presentation-generator)/components/ImageEditor.tsx b/servers/nextjs/app/(presentation-generator)/components/ImageEditor.tsx index b058be46..6652c78b 100644 --- a/servers/nextjs/app/(presentation-generator)/components/ImageEditor.tsx +++ b/servers/nextjs/app/(presentation-generator)/components/ImageEditor.tsx @@ -7,15 +7,12 @@ import { SheetTitle, } from "@/components/ui/sheet"; import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs"; -import { Input } from "@/components/ui/input"; import { Button } from "@/components/ui/button"; import { Textarea } from "@/components/ui/textarea"; import { - Search, Wand2, Upload, Edit, - Crop, Move, Maximize, } from "lucide-react"; @@ -38,6 +35,7 @@ import { } from "@/components/ui/popover"; import ToolTip from "@/components/ToolTip"; import { getEnv } from "@/utils/constant"; +import { ipcRenderer } from "electron"; interface ImageEditorProps { initialImage: string | null; @@ -234,8 +232,6 @@ const ImageEditor = ({ } }; - - const handleFileUpload = async ( event: React.ChangeEvent ) => { @@ -263,23 +259,20 @@ const ImageEditor = ({ setIsUploading(true); setUploadError(null); - const formData = new FormData(); - formData.append("file", file); - const response = await fetch("/api/user-upload", { - method: "POST", - body: formData, - }); + // Convert file to buffer + const buffer = await file.arrayBuffer(); - if (!response.ok) { - throw new Error("Upload failed"); - } + // Send to electron main process + // @ts-ignore + const relativePath = await window.electron.uploadImage(Buffer.from(buffer)); - const data = await response.json(); - setUploadedImageUrl(data.url); + // Update state with the returned path + setUploadedImageUrl(relativePath); } catch (err) { const error_message = "Failed to upload image. Please try again."; setUploadError(error_message); + console.error("Upload error:", err); } finally { setIsUploading(false); } From ab5f9b8ce397ef9e36a6fbbaaf05bee524f02b7c Mon Sep 17 00:00:00 2001 From: shiva raj badu Date: Mon, 12 May 2025 22:57:20 +0545 Subject: [PATCH 2/2] Image Editor: upload image improved --- app/ipc/upload_image.ts | 6 +++--- app/utils/constants.ts | 2 +- .../(presentation-generator)/components/ImageEditor.tsx | 8 +++----- 3 files changed, 7 insertions(+), 9 deletions(-) diff --git a/app/ipc/upload_image.ts b/app/ipc/upload_image.ts index 8caa16d7..ad102dd6 100644 --- a/app/ipc/upload_image.ts +++ b/app/ipc/upload_image.ts @@ -2,13 +2,13 @@ import { ipcMain } from "electron"; import path from "path"; import fs from "fs"; import crypto from "crypto"; -import { baseDir } from "../utils/constants"; +import { userDataDir } from "../utils/constants"; export function setupUploadImage() { ipcMain.handle("upload-image", async (_, file: Buffer) => { try { // Create uploads directory if it doesn't exist - const uploadsDir = path.join(baseDir, "uploads"); + const uploadsDir = path.join(userDataDir, "uploads"); fs.mkdirSync(uploadsDir, { recursive: true }); // Generate unique filename @@ -19,7 +19,7 @@ export function setupUploadImage() { await fs.writeFileSync(filePath, file); // Return the relative path that can be used in the frontend - return `/uploads/${filename}`; + return filePath; } catch (error) { console.error("Error saving image:", error); throw error; diff --git a/app/utils/constants.ts b/app/utils/constants.ts index 85c8951a..d95bc844 100644 --- a/app/utils/constants.ts +++ b/app/utils/constants.ts @@ -4,7 +4,7 @@ import path from "path" export const localhost = "http://0.0.0.0" -export const isDev = false; +export const isDev = true; export const baseDir = app.getAppPath(); export const fastapiDir = isDev ? path.join(baseDir, "servers/fastapi") : path.join(baseDir, "resources/fastapi"); export const nextjsDir = isDev ? path.join(baseDir, "servers/nextjs") : path.join(baseDir, "resources/nextjs"); diff --git a/servers/nextjs/app/(presentation-generator)/components/ImageEditor.tsx b/servers/nextjs/app/(presentation-generator)/components/ImageEditor.tsx index 6652c78b..f6d1c8e2 100644 --- a/servers/nextjs/app/(presentation-generator)/components/ImageEditor.tsx +++ b/servers/nextjs/app/(presentation-generator)/components/ImageEditor.tsx @@ -496,7 +496,7 @@ const ImageEditor = ({
- + AI Generate @@ -553,9 +553,7 @@ const ImageEditor = ({ {`Preview Uploaded preview