From ec621bf55aefda6649ce49d7ece6065ab2c54368 Mon Sep 17 00:00:00 2001 From: Mohamed Bassem Date: Sat, 8 Nov 2025 18:04:46 +0000 Subject: feat(mobile): add custom headers configuration in sign-in screen (#2103) * feat(mobile): add custom headers configuration in sign-in screen Add ability for mobile app users to configure custom HTTP headers that are sent with every API request. This enables users to add authentication headers, proxy headers, or other custom headers required by their server setup. Changes: - Add customHeaders field to mobile app settings schema - Create CustomHeadersModal component for managing headers - Update sign-in screen with link to configure custom headers - Modify tRPC provider to merge custom headers with Authorization header The custom headers are stored securely in the app settings and persist across sessions. * fix keyboard * add custom headers to other callsites --------- Co-authored-by: Claude --- apps/mobile/components/CustomHeadersModal.tsx | 200 ++++++++++++++++++++++++++ 1 file changed, 200 insertions(+) create mode 100644 apps/mobile/components/CustomHeadersModal.tsx (limited to 'apps/mobile/components/CustomHeadersModal.tsx') diff --git a/apps/mobile/components/CustomHeadersModal.tsx b/apps/mobile/components/CustomHeadersModal.tsx new file mode 100644 index 00000000..6d022eb8 --- /dev/null +++ b/apps/mobile/components/CustomHeadersModal.tsx @@ -0,0 +1,200 @@ +import { useState } from "react"; +import { Modal, Pressable, ScrollView, View } from "react-native"; +import { KeyboardAwareScrollView } from "react-native-keyboard-controller"; +import { Plus, Trash2, X } from "lucide-react-native"; +import { useColorScheme } from "nativewind"; + +import { Button } from "./ui/Button"; +import { Input } from "./ui/Input"; +import { Text } from "./ui/Text"; + +interface CustomHeadersModalProps { + visible: boolean; + customHeaders: Record; + onClose: () => void; + onSave: (headers: Record) => void; +} + +export function CustomHeadersModal({ + visible, + customHeaders, + onClose, + onSave, +}: CustomHeadersModalProps) { + const { colorScheme } = useColorScheme(); + const iconColor = colorScheme === "dark" ? "#d1d5db" : "#374151"; + + // Convert headers object to array of entries for easier manipulation + const [headers, setHeaders] = useState<{ key: string; value: string }[]>( + Object.entries(customHeaders).map(([key, value]) => ({ key, value })), + ); + const [newHeaderKey, setNewHeaderKey] = useState(""); + const [newHeaderValue, setNewHeaderValue] = useState(""); + + 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, + ); + + onSave(headersObject); + onClose(); + }; + + const handleCancel = () => { + // Reset to original headers + setHeaders( + Object.entries(customHeaders).map(([key, value]) => ({ key, value })), + ); + setNewHeaderKey(""); + setNewHeaderValue(""); + onClose(); + }; + + return ( + + + + + + {/* Header */} + + 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} + + + handleRemoveHeader(index)} + className="p-2" + > + + + + ))} + + )} + + + {/* Add New Header */} + + Add New Header + + + + + + {/* Action Buttons */} + + + + + + + + + ); +} -- cgit v1.2.3-70-g09d2