Browse Source

fix: address PR feedback (security & UX)

handoff-20260429-1057
CatoPaus 7 months ago
parent
commit
5560aecf94
  1. 21
      src/app/api/open-directory/route.ts
  2. 49
      src/components/Header.tsx

21
src/app/api/open-directory/route.ts

@ -1,10 +1,10 @@
import { NextRequest, NextResponse } from "next/server";
import { exec } from "child_process";
import { execFile } from "child_process";
import { promisify } from "util";
import os from "os";
const execAsync = promisify(exec);
const execFileAsync = promisify(execFile);
export async function POST(req: NextRequest) {
try {
@ -19,24 +19,29 @@ export async function POST(req: NextRequest) {
}
let command = "";
let args: string[] = [];
const platform = os.platform();
switch (platform) {
case "darwin":
command = `open "${path}"`;
command = "open";
args = [path];
break;
case "win32":
command = `explorer "${path}"`;
command = "explorer";
args = [path];
break;
case "linux":
command = `xdg-open "${path}"`;
command = "xdg-open";
args = [path];
break;
default:
// Fallback for other Unix-like systems, might not work everywhere
command = `xdg-open "${path}"`;
// Fallback for other Unix-like systems
command = "xdg-open";
args = [path];
}
await execAsync(command);
await execFileAsync(command, args);
return NextResponse.json({ success: true });
} catch (error) {

49
src/components/Header.tsx

@ -81,15 +81,24 @@ export function Header() {
if (!saveDirectoryPath) return;
try {
await fetch("/api/open-directory", {
const response = await fetch("/api/open-directory", {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({ path: saveDirectoryPath }),
});
const result = await response.json();
if (!response.ok || !result.success) {
console.error("Failed to open directory:", result.error);
alert(`Failed to open project folder: ${result.error || "Unknown error"}`);
return;
}
} catch (error) {
console.error("Failed to open directory:", error);
alert("Failed to open project folder. Please try again.");
}
};
@ -142,25 +151,27 @@ export function Header() {
<span className="absolute -top-0.5 -right-0.5 w-2 h-2 rounded-full bg-red-500" />
)}
</button>
<button
onClick={handleOpenDirectory}
className="p-1 text-neutral-400 hover:text-neutral-200 transition-colors"
title="Open Project Folder"
>
<svg
className="w-4 h-4"
fill="none"
viewBox="0 0 24 24"
stroke="currentColor"
strokeWidth={2}
{saveDirectoryPath && (
<button
onClick={handleOpenDirectory}
className="p-1 text-neutral-400 hover:text-neutral-200 transition-colors"
title="Open Project Folder"
>
<path
strokeLinecap="round"
strokeLinejoin="round"
d="M2.25 12.75V12A2.25 2.25 0 0 1 4.5 9.75h15A2.25 2.25 0 0 1 21.75 12v.75m-8.69-6.44-2.12-2.12a1.5 1.5 0 0 0-1.061-.44H4.5A2.25 2.25 0 0 0 2.25 6v12a2.25 2.25 0 0 0 2.25 2.25h15A2.25 2.25 0 0 0 21.75 18V9a2.25 2.25 0 0 0-2.25-2.25h-5.379a1.5 1.5 0 0 1-1.06-.44Z"
/>
</svg>
</button>
<svg
className="w-4 h-4"
fill="none"
viewBox="0 0 24 24"
stroke="currentColor"
strokeWidth={2}
>
<path
strokeLinecap="round"
strokeLinejoin="round"
d="M2.25 12.75V12A2.25 2.25 0 0 1 4.5 9.75h15A2.25 2.25 0 0 1 21.75 12v.75m-8.69-6.44-2.12-2.12a1.5 1.5 0 0 0-1.061-.44H4.5A2.25 2.25 0 0 0 2.25 6v12a2.25 2.25 0 0 0 2.25 2.25h15A2.25 2.25 0 0 0 21.75 18V9a2.25 2.25 0 0 0-2.25-2.25h-5.379a1.5 1.5 0 0 1-1.06-.44Z"
/>
</svg>
</button>
)}
<button
onClick={handleOpenSettings}
className="p-1 text-neutral-400 hover:text-neutral-200 transition-colors"

Loading…
Cancel
Save