import type { DnsOverride, Workspace } from '@yaakapp-internal/models'; import { patchModel } from '@yaakapp-internal/models'; import { useCallback, useId, useMemo } from 'react'; import { Button } from './core/Button'; import { Checkbox } from './core/Checkbox'; import { IconButton } from './core/IconButton'; import { PlainInput } from './core/PlainInput'; import { HStack, VStack } from './core/Stacks'; import { Table, TableBody, TableCell, TableHead, TableHeaderCell, TableRow } from './core/Table'; interface Props { workspace: Workspace; } interface DnsOverrideWithId extends DnsOverride { _id: string; } export function DnsOverridesEditor({ workspace }: Props) { const reactId = useId(); // Ensure each override has an internal ID for React keys const overridesWithIds = useMemo(() => { return workspace.settingDnsOverrides.map((override, index) => ({ ...override, _id: `${reactId}-${index}`, })); }, [workspace.settingDnsOverrides, reactId]); const handleChange = useCallback( (overrides: DnsOverride[]) => { patchModel(workspace, { settingDnsOverrides: overrides }); }, [workspace], ); const handleAdd = useCallback(() => { const newOverride: DnsOverride = { hostname: '', ipv4: [''], ipv6: [], enabled: true, }; handleChange([...workspace.settingDnsOverrides, newOverride]); }, [workspace.settingDnsOverrides, handleChange]); const handleUpdate = useCallback( (index: number, update: Partial) => { const updated = workspace.settingDnsOverrides.map((o, i) => i === index ? { ...o, ...update } : o, ); handleChange(updated); }, [workspace.settingDnsOverrides, handleChange], ); const handleDelete = useCallback( (index: number) => { const updated = workspace.settingDnsOverrides.filter((_, i) => i !== index); handleChange(updated); }, [workspace.settingDnsOverrides, handleChange], ); return (
Override DNS resolution for specific hostnames. This works like{' '} /etc/hosts{' '} but only for requests made from this workspace.
{overridesWithIds.length > 0 && ( Hostname IPv4 Address IPv6 Address {overridesWithIds.map((override, index) => ( handleUpdate(index, update)} onDelete={() => handleDelete(index)} /> ))}
)}
); } interface DnsOverrideRowProps { override: DnsOverride; onUpdate: (update: Partial) => void; onDelete: () => void; } function DnsOverrideRow({ override, onUpdate, onDelete }: DnsOverrideRowProps) { const ipv4Value = override.ipv4.join(', '); const ipv6Value = override.ipv6.join(', '); return ( onUpdate({ enabled })} /> onUpdate({ hostname })} /> onUpdate({ ipv4: value .split(',') .map((s) => s.trim()) .filter(Boolean), }) } /> onUpdate({ ipv6: value .split(',') .map((s) => s.trim()) .filter(Boolean), }) } /> ); }