import { useEffect, useRef, useState } from "react"; import { gsap } from "gsap"; import { ScrollTrigger } from "gsap/ScrollTrigger"; import { MessageSquare, ExternalLink, Copy, Check, Key, type LucideIcon, } from "lucide-react"; import { useReducedMotion } from "../hooks/useReducedMotion"; gsap.registerPlugin(ScrollTrigger); interface ContactItem { label: string; value: string; href?: string; isLink?: boolean; unavailable?: boolean; icon?: LucideIcon; } interface ContactGroup { category: string; items: ContactItem[]; } const contacts: ContactGroup[] = [ { category: "Messaging", items: [ { label: "Simplex", value: "Open chat", href: "https://simplex.chat/contact#/?v=2-7&smp=smp%3A%2F%2FPQUV2eL0t7OStZOoAsPEV2QYWt4-xilbakvGUGOItUo%3D%40smp6.simplex.im%2F3_XOiEnk2Ebup7DqgOwGM5kXlIZX-uJo%23%2F%3Fv%3D1-4%26dh%3DMCowBQYDK2VuAyEAPJz5X-WHhJk_y1MLRxy7NTfspD-vKF0pmmi_GAJpExY%253D%26q%3Dc%26srv%3Dbylepyau3ty4czmn77q4fglvperknl4bi2eb2fdy2bh4jxtf32kf73yd.onion", isLink: true, }, { label: "Discord", value: "@sysrand [1408202642588438589] / @forgecadrape [1452113626365169958]", }, { label: "Telegram", value: "@forgecadrape (main) / @xorededx" }, { label: "XMPP", value: "sw@anoxinon.me (main) / me0w@xmpp.jp" }, { label: "Session", value: "056834db96cedde6012da9d5402c683c0eb260ed866da145a8f86e7f329bf77222", }, { label: "Tox", value: "5622A2D2218AF235E39E356792270413BBE7CAEEAA531A20EEF11BF2FD10576E5050F0A55970", }, { label: "Potato Chat", value: "@depoliticized" }, { label: "Element", value: "Open profile", href: "https://matrix.to/#/@depoliticized:tchncs.de", isLink: true, }, { label: "Briar", value: "temporary unavailable", unavailable: true }, ], }, { category: "Email", items: [ { label: "Primary", value: "contact@stealer.wtf (temporary unavailable)", unavailable: true, }, ], }, { category: "Git", items: [ { label: "serpent256", value: "View profile", href: "https://git.fingeri.ng/serpent256", isLink: true, }, { label: "raped.cc", value: "View profile (main)", href: "https://git.fingeri.ng/raped.cc", isLink: true, }, { label: "whiskers", value: "View org", href: "https://git.fingeri.ng/whiskers", isLink: true, }, ], }, { category: "PGP", items: [ { label: "Public Key", value: "Download /pub-pgp.txt", href: "./pub-pgp.txt", isLink: true, icon: Key, }, ], }, ]; function CopyButton({ text }: { text: string }) { const [copied, setCopied] = useState(false); const handleCopy = async () => { try { await navigator.clipboard.writeText(text); setCopied(true); setTimeout(() => setCopied(false), 2000); } catch { // Fallback } }; return ( {copied ? ( ) : ( )} ); } export default function ContactSection() { const sectionRef = useRef(null); const reducedMotion = useReducedMotion(); useEffect(() => { if (reducedMotion || !sectionRef.current) return; const ctx = gsap.context(() => { gsap.fromTo( ".contact-reveal", { y: 40, opacity: 0 }, { y: 0, opacity: 1, duration: 0.8, stagger: 0.1, ease: "expo.out", scrollTrigger: { trigger: sectionRef.current, start: "top 70%", toggleActions: "play none none none", }, }, ); }, sectionRef); return () => ctx.revert(); }, [reducedMotion]); return ( {!reducedMotion && ( )} {/* Section label */} 006 Contact {/* Header */} Get in touch Reach out through any of these channels. I prefer encrypted messaging when possible. {/* Contact grid */} {contacts.map((group) => ( {group.category} {group.items.map((item) => ( {item.label} {item.isLink && item.href ? ( {item.icon && } {item.value} ) : item.unavailable ? ( {item.value} ) : ( {item.value} )} {!item.isLink && !item.unavailable && ( )} ))} ))} ); }
Reach out through any of these channels. I prefer encrypted messaging when possible.