diff --git a/electron/main.ts b/electron/main.ts index c613017..4f73d83 100644 --- a/electron/main.ts +++ b/electron/main.ts @@ -1,4 +1,5 @@ import { app, BrowserWindow, Menu, dialog, ipcMain } from "electron"; +import type { OpenDialogOptions } from "electron"; import { readFile, writeFile } from "node:fs/promises"; import path from "node:path"; import { fileURLToPath } from "node:url"; @@ -31,11 +32,17 @@ async function createWindow() { } } -ipcMain.handle("envhelper:open-file", async () => { - const result = await dialog.showOpenDialog({ +ipcMain.handle("envhelper:open-file", async (event) => { + const owner = BrowserWindow.fromWebContents(event.sender); + const options = { properties: ["openFile"], - filters: [{ name: "Environment files", extensions: ["env", "txt", "*"] }] - }); + filters: [ + { name: "Environment files", extensions: ["env", "txt"] }, + { name: "All files", extensions: ["*"] } + ] + } satisfies OpenDialogOptions; + + const result = owner ? await dialog.showOpenDialog(owner, options) : await dialog.showOpenDialog(options); if (result.canceled || result.filePaths.length === 0) { return null; diff --git a/src/App.tsx b/src/App.tsx index 253a2c6..ba386a8 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -441,6 +441,33 @@ function addUnique(values: string[], value: string): string[] { return values.some((entry) => normalizeKey(entry) === normalized) ? values : [...values, value]; } +function openFileWithBrowserPicker(): Promise<{ name: string; content: string } | null> { + return new Promise((resolve) => { + const input = document.createElement("input"); + input.type = "file"; + input.accept = ".env,.txt,text/plain"; + + input.addEventListener( + "change", + async () => { + const file = input.files?.[0]; + if (!file) { + resolve(null); + return; + } + + resolve({ + name: file.name, + content: await file.text() + }); + }, + { once: true } + ); + + input.click(); + }); +} + export default function App() { const [input, setInput] = useState(""); const [loadedPath, setLoadedPath] = useState(null); @@ -480,10 +507,24 @@ export default function App() { }, [ignoredAutoDefaults]); async function openFile() { - const file = await window.envHelper?.openFile(); + try { + if (window.envHelper?.openFile) { + const file = await window.envHelper.openFile(); + if (file) { + setInput(file.content); + setLoadedPath(file.path); + } + + return; + } + } catch (error) { + console.warn("Native file dialog failed, falling back to browser file input.", error); + } + + const file = await openFileWithBrowserPicker(); if (file) { setInput(file.content); - setLoadedPath(file.path); + setLoadedPath(file.name); } }