import { AtUri } from "@atproto/api"; import { useNavigate, type UseNavigateResult } from "@tanstack/react-router"; import { useAtom } from "jotai"; import { useState } from "react"; import { useAuth } from "~/providers/UnifiedAuthProvider"; import { lycanURLAtom } from "~/utils/atoms"; import { useQueryLycanStatus } from "~/utils/useQuery"; /** * Basically the best equivalent to Search that i can do */ export function Import({ optionaltextstring, }: { optionaltextstring?: string; }) { const [textInput, setTextInput] = useState( optionaltextstring ); const navigate = useNavigate(); const { status } = useAuth(); const [lycandomain] = useAtom(lycanURLAtom); const lycanExists = lycandomain !== ""; const { data: lycanstatusdata } = useQueryLycanStatus(); const lycanIndexed = lycanstatusdata?.status === "finished" || false; const lycanIndexing = lycanstatusdata?.status === "in_progress" || false; const lycanIndexingProgress = lycanIndexing ? lycanstatusdata?.progress : undefined; const authed = status === "signedIn"; const lycanReady = lycanExists && lycanIndexed && authed; const handleEnter = () => { if (!textInput) return; handleImport({ text: textInput, navigate, lycanReady: lycanReady || (!!lycanIndexingProgress && lycanIndexingProgress > 0), }); }; const placeholder = lycanReady ? "Search..." : "Import..."; return (
setTextInput(e.target.value)} onKeyDown={(e) => { if (e.key === "Enter") handleEnter(); }} className="w-full h-12 pl-12 pr-4 rounded-full bg-gray-100 dark:bg-gray-800 text-gray-800 dark:text-gray-200 placeholder-gray-400 dark:placeholder-gray-500 focus:outline-none focus:ring-2 focus:ring-gray-400 dark:focus:ring-gray-500 box-border transition" />
); } function handleImport({ text, navigate, lycanReady, }: { text: string; navigate: UseNavigateResult; lycanReady?: boolean; }) { const trimmed = text.trim(); // parse text /** * text might be * 1. bsky dot app url (reddwarf link segments might be uri encoded,) * 2. aturi * 3. plain handle * 4. plain did */ // 1. Check if it’s a URL try { const url = new URL(text); const knownHosts = [ "bsky.app", "social.daniela.lol", "deer.social", "reddwarf.whey.party", "reddwarf.app", "main.bsky.dev", "catsky.social", "blacksky.community", "red-dwarf-social-app.whey.party", "zeppelin.social", ]; if (knownHosts.includes(url.hostname)) { // parse path to get URI or handle const path = decodeURIComponent(url.pathname.slice(1)); // remove leading / console.log("BSky URL path:", path); navigate({ to: `/${path}`, }); return; } } catch { // not a URL, continue } // 2. Check if text looks like an at-uri try { if (text.startsWith("at://")) { console.log("AT URI detected:", text); const aturi = new AtUri(text); switch (aturi.collection) { case "app.bsky.feed.post": { navigate({ to: "/profile/$did/post/$rkey", params: { did: aturi.host, rkey: aturi.rkey, }, }); return; } case "app.bsky.actor.profile": { navigate({ to: "/profile/$did", params: { did: aturi.host, }, }); return; } // todo add more handlers as more routes are added. like feeds, lists, etc etc thanks! default: { // continue } } } } catch { // continue } // 3. Plain handle (starts with @) try { if (text.startsWith("@")) { const handle = text.slice(1); console.log("Handle detected:", handle); navigate({ to: "/profile/$did", params: { did: handle } }); return; } } catch { // continue } // 4. Plain DID (starts with did:) try { if (text.startsWith("did:")) { console.log("did detected:", text); navigate({ to: "/profile/$did", params: { did: text } }); return; } } catch { // continue } // if all else fails // try { // // probably a user? // navigate({ to: "/profile/$did", params: { did: text } }); // return; // } catch { // // continue // } if (lycanReady) { navigate({ to: "/search", search: { q: text } }); } }