"use client"; import { useState, useEffect, useRef, useCallback } from "react"; import Link from "next/link"; import ThemedLayout from "@/components/layouts/ThemedLayout"; import { useAccount } from "@/contexts/AccountContext"; type Msg = { id: string; from: string; text: string; ts: number }; const MSG_KEY_PREFIX = "cyberlux-msgs-v1"; const BOT_NAMES = ["void_cartographer", "relay_op", "ledger_moth", "phantom_q", "EU_shift"]; const BOT_REPLIES: Record = { market: [ "Check /market — catalog updates every ~6h.", "New drops typically show up late cycle. /drops has the schedule.", ], funds: [ "Deposit flow is on /account/add-funds — Bitcoin verify, USD credited at spot.", "After one confirmation paste your txid at /account/add-funds. Done.", ], forum: [ "Forum is at /forum — threaded, ring-gated, persists per device.", "Post your thread on /forum/submit if you want a dedicated slot.", ], exchange: [ "Classifieds are live on /exchange — WTS/WTB, stored local.", "Exchange listings open to any signed-in handle.", ], barter: ["Ash Pit (/barter) is the swap board. Four lanes: goods, services, data, open."], default: [ "Copy that.", "Noted.", "Channel is live.", "Acknowledged.", "Check your vault for anything pending.", "Markets move. Stay verified.", ], }; function getBotReply(text: string): string { const t = text.toLowerCase(); for (const [k, v] of Object.entries(BOT_REPLIES)) { if (k !== "default" && t.includes(k)) { return v[Math.floor(Math.random() * v.length)]!; } } return BOT_REPLIES.default[Math.floor(Math.random() * BOT_REPLIES.default.length)]!; } function uid() { return Math.random().toString(36).slice(2, 10); } function botName() { return BOT_NAMES[Math.floor(Math.random() * BOT_NAMES.length)]!; } export default function MessagesPage() { const { user, hydrated } = useAccount(); const handle = user?.username ?? null; const storageKey = `${MSG_KEY_PREFIX}:${handle ?? "anon"}`; const [msgs, setMsgs] = useState([]); const [input, setInput] = useState(""); const [ready, setReady] = useState(false); const endRef = useRef(null); useEffect(() => { if (!hydrated) return; try { const raw = localStorage.getItem(storageKey); if (raw) { setMsgs(JSON.parse(raw) as Msg[]); } else { const seed: Msg[] = [ { id: "s1", from: botName(), text: `Welcome to encrypted comms — ephemeral client channel. Posts here are stored only on your device under key "${storageKey}". Sign in to separate conversations per handle.`, ts: Date.now() - 180000, }, ]; setMsgs(seed); localStorage.setItem(storageKey, JSON.stringify(seed)); } } catch { // ignore } setReady(true); }, [storageKey, hydrated]); useEffect(() => { if (!ready) return; try { localStorage.setItem(storageKey, JSON.stringify(msgs.slice(-100))); } catch { // ignore } endRef.current?.scrollIntoView({ behavior: "smooth" }); }, [msgs, ready, storageKey]); const send = useCallback(() => { const text = input.trim(); if (!text) return; const mine: Msg = { id: uid(), from: handle ?? "anon", text, ts: Date.now() }; setMsgs((p) => [...p, mine]); setInput(""); const delay = 700 + Math.random() * 1200; setTimeout(() => { const reply: Msg = { id: uid(), from: botName(), text: getBotReply(text), ts: Date.now() }; setMsgs((p) => [...p, reply]); }, delay); }, [input, handle]); const clearHistory = () => { setMsgs([]); localStorage.removeItem(storageKey); }; const ts = (n: number) => new Date(n).toLocaleTimeString([], { hour: "2-digit", minute: "2-digit" }); return (

ENCRYPTED COMMS

{handle ? ( <>Channel: @{handle} · stored locally · no server transport ) : ( <> Sign in {" "} to persist messages to your handle )}

{!ready ? (
Loading…
) : ( msgs.map((m) => { const mine = m.from === handle || (m.from === "anon" && !handle); return (
@{m.from} {ts(m.ts)}
{m.text}
); }) )}
setInput(e.target.value)} onKeyDown={(e) => e.key === "Enter" && send()} placeholder={ready ? "Message the channel…" : "Loading…"} disabled={!ready} className="flex-1 rounded-xl border border-white/10 bg-transparent px-4 py-3 text-sm focus:border-neon-cyan/40 focus:outline-none disabled:opacity-50" maxLength={500} />
Client-only storage
No server transport
Per-handle isolation
Forum (persisted threads) → Barter board Dashboard
); }