From 8547cc989842d2995e632ff19de7a8d94dacec31 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alejandro=20G=C3=B3mez?= Date: Wed, 15 Apr 2026 14:37:04 +0200 Subject: [PATCH] fix: replace numeric timestamp input with date picker in NIP-5C scrolls Add TimestampInput component with relative presets (1h, 1d, 1w, 1mo ago) and native datetime-local picker. Shows locale-aware preview via formatTimestamp. Values remain unix timestamp strings for compatibility. Closes #263 Co-Authored-By: Claude Opus 4.6 (1M context) --- src/components/scroll/ScrollParamForm.tsx | 74 +++++++++++++++++++++++ 1 file changed, 74 insertions(+) diff --git a/src/components/scroll/ScrollParamForm.tsx b/src/components/scroll/ScrollParamForm.tsx index b3f858b..f2ffabb 100644 --- a/src/components/scroll/ScrollParamForm.tsx +++ b/src/components/scroll/ScrollParamForm.tsx @@ -2,8 +2,76 @@ import { Settings } from "lucide-react"; import { PARAM_CONFIG } from "@/components/nostr/kinds/ScrollRenderer"; import { Label } from "@/components/ui/label"; import { Input } from "@/components/ui/input"; +import { formatTimestamp } from "@/hooks/useLocale"; import type { ScrollParam } from "@/lib/nip5c-helpers"; +const TIMESTAMP_PRESETS = [ + { label: "1h ago", offset: 3600 }, + { label: "1d ago", offset: 86400 }, + { label: "1w ago", offset: 604800 }, + { label: "1mo ago", offset: 2592000 }, +] as const; + +function unixToDatetimeLocal(unixSeconds: number): string { + const date = new Date(unixSeconds * 1000); + // toISOString gives UTC; adjust to local time for datetime-local input + const offset = date.getTimezoneOffset() * 60000; + return new Date(date.getTime() - offset).toISOString().slice(0, 16); +} + +function TimestampInput({ + value, + onChange, + disabled, +}: { + value: string; + onChange: (value: string) => void; + disabled?: boolean; +}) { + const numericValue = value ? parseInt(value, 10) : null; + const datetimeValue = + numericValue && !isNaN(numericValue) + ? unixToDatetimeLocal(numericValue) + : ""; + + return ( +
+
+ {TIMESTAMP_PRESETS.map(({ label, offset }) => ( + + ))} +
+ { + const parsed = new Date(e.target.value).getTime(); + if (!isNaN(parsed)) { + onChange(String(Math.floor(parsed / 1000))); + } + }} + disabled={disabled} + className="h-8 text-xs" + /> + {numericValue && !isNaN(numericValue) && ( + + {formatTimestamp(numericValue, "datetime")} + + )} +
+ ); +} + interface ScrollParamFormProps { params: ScrollParam[]; values: Record; @@ -90,6 +158,12 @@ export function ScrollParamForm({ className="flex-1 h-8 text-xs" /> + ) : param.type === "timestamp" ? ( + setValue(param.name, v)} + disabled={disabled} + /> ) : (