From ec87813a257e63f8a161e7bc04679e9fab6fbcf6 Mon Sep 17 00:00:00 2001 From: Mohamed Bassem Date: Sun, 9 Nov 2025 12:21:54 +0000 Subject: feat(extension): Add custom header support for extension (#2111) Fixes #1287 --- apps/browser-extension/src/CustomHeadersPage.tsx | 155 +++++++++++++++++++++++ 1 file changed, 155 insertions(+) create mode 100644 apps/browser-extension/src/CustomHeadersPage.tsx (limited to 'apps/browser-extension/src/CustomHeadersPage.tsx') diff --git a/apps/browser-extension/src/CustomHeadersPage.tsx b/apps/browser-extension/src/CustomHeadersPage.tsx new file mode 100644 index 00000000..1b3fd8df --- /dev/null +++ b/apps/browser-extension/src/CustomHeadersPage.tsx @@ -0,0 +1,155 @@ +import { useEffect, useState } from "react"; +import { Plus, Trash2 } from "lucide-react"; +import { useNavigate } from "react-router-dom"; + +import { Button } from "./components/ui/button"; +import { Input } from "./components/ui/input"; +import Logo from "./Logo"; +import usePluginSettings from "./utils/settings"; + +export default function CustomHeadersPage() { + const navigate = useNavigate(); + const { settings, setSettings } = usePluginSettings(); + + // Convert headers object to array of entries for easier manipulation + const [headers, setHeaders] = useState<{ key: string; value: string }[]>([]); + const [newHeaderKey, setNewHeaderKey] = useState(""); + const [newHeaderValue, setNewHeaderValue] = useState(""); + + // Update headers when settings change (e.g., when loaded from storage) + useEffect(() => { + setHeaders( + Object.entries(settings.customHeaders || {}).map(([key, value]) => ({ + key, + value, + })), + ); + }, [settings.customHeaders]); + + const handleAddHeader = () => { + if (!newHeaderKey.trim() || !newHeaderValue.trim()) { + return; + } + + // Check if header already exists + const existingIndex = headers.findIndex((h) => h.key === newHeaderKey); + if (existingIndex >= 0) { + // Update existing header + const updatedHeaders = [...headers]; + updatedHeaders[existingIndex].value = newHeaderValue; + setHeaders(updatedHeaders); + } else { + // Add new header + setHeaders([...headers, { key: newHeaderKey, value: newHeaderValue }]); + } + + setNewHeaderKey(""); + setNewHeaderValue(""); + }; + + const handleRemoveHeader = (index: number) => { + setHeaders(headers.filter((_, i) => i !== index)); + }; + + const handleSave = () => { + // Convert array back to object + const headersObject = headers.reduce( + (acc, { key, value }) => { + if (key.trim() && value.trim()) { + acc[key] = value; + } + return acc; + }, + {} as Record, + ); + + setSettings((s) => ({ ...s, customHeaders: headersObject })); + navigate(-1); + }; + + const handleCancel = () => { + navigate(-1); + }; + + return ( +
+ + Custom Headers +

+ Add custom HTTP headers that will be sent with every API request. +

+
+ + {/* Existing Headers List */} +
+ {headers.length === 0 ? ( +

+ No custom headers configured +

+ ) : ( + headers.map((header, index) => ( +
+
+

{header.key}

+

+ {header.value} +

+
+ +
+ )) + )} +
+ +
+ + {/* Add New Header */} +
+

Add New Header

+ setNewHeaderKey(e.target.value)} + autoCapitalize="none" + /> + setNewHeaderValue(e.target.value)} + autoCapitalize="none" + /> + +
+ +
+ + {/* Action Buttons */} +
+ + +
+
+ ); +} -- cgit v1.2.3-70-g09d2