diff --git a/src/components/Import.tsx b/src/components/Import.tsx new file mode 100644 index 0000000..d1de33e --- /dev/null +++ b/src/components/Import.tsx @@ -0,0 +1,149 @@ +import { AtUri } from "@atproto/api"; +import { useNavigate, type UseNavigateResult } from "@tanstack/react-router"; +import { useState } from "react"; + +/** + * Basically the best equivalent to Search that i can do + */ +export function Import() { + const [textInput, setTextInput] = useState(); + const navigate = useNavigate(); + + const handleEnter = () => { + if (!textInput) return; + handleImport({ + text: textInput, + navigate, + }); + }; + + 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, +}: { + text: string; + navigate: UseNavigateResult; +}) { + const trimmed = text.trim(); + // parse text + /** + * text might be + * 1. bsky dot app url (deer.social, reddwarf.whey.party, main.bsky.dev, catskys.social) (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", + "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 + // } +} diff --git a/src/components/Login.tsx b/src/components/Login.tsx index 5d444b1..365f54d 100644 --- a/src/components/Login.tsx +++ b/src/components/Login.tsx @@ -24,7 +24,7 @@ export default function Login({ className={ compact ? "flex items-center justify-center p-1" - : "p-6 bg-gray-100 dark:bg-gray-900 rounded-xl shadow border border-gray-200 dark:border-gray-800 mt-6 mx-4 flex justify-center items-center h-[280px]" + : "p-6 bg-gray-100 dark:bg-gray-900 rounded-xl shadow border border-gray-200 dark:border-gray-800 mt-4 mx-4 flex justify-center items-center h-[280px]" } > +

You are logged in! @@ -77,7 +77,7 @@ export default function Login({ if (!compact) { // Large view renders the form directly in the card return ( -

+
); diff --git a/src/routes/__root.tsx b/src/routes/__root.tsx index e360e4c..2c74aeb 100644 --- a/src/routes/__root.tsx +++ b/src/routes/__root.tsx @@ -18,6 +18,7 @@ import { KeepAliveOutlet, KeepAliveProvider } from "tanstack-router-keepalive"; import { Composer } from "~/components/Composer"; import { DefaultCatchBoundary } from "~/components/DefaultCatchBoundary"; +import { Import } from "~/components/Import"; import Login from "~/components/Login"; import { NotFound } from "~/components/NotFound"; import { FluentEmojiHighContrastGlowingStar } from "~/components/Star"; @@ -153,6 +154,18 @@ function RootDocument({ children }: { children: React.ReactNode }) { text="Home" /> + } + ActiveIcon={} + active={locationEnum === "search"} + onClickCallbback={() => + navigate({ + to: "/search", + //params: { did: agent.assertDid }, + }) + } + text="Explore" + /> @@ -181,18 +194,6 @@ function RootDocument({ children }: { children: React.ReactNode }) { } text="Feeds" /> - } - ActiveIcon={} - active={locationEnum === "search"} - onClickCallbback={() => - navigate({ - to: "/search", - //params: { did: agent.assertDid }, - }) - } - text="Search" - /> @@ -387,6 +388,19 @@ function RootDocument({ children }: { children: React.ReactNode }) { text="Home" /> + } + ActiveIcon={} + active={locationEnum === "search"} + onClickCallbback={() => + navigate({ + to: "/search", + //params: { did: agent.assertDid }, + }) + } + text="Explore" + /> - } - ActiveIcon={} - active={locationEnum === "search"} - onClickCallbback={() => - navigate({ - to: "/search", - //params: { did: agent.assertDid }, - }) - } - text="Search" - />
; + return ( + <> +
{ + if (window.history.length > 1) { + window.history.back(); + } else { + window.location.assign("/"); + } + }} + /> +
+ +
+

+ Sorry we dont have search. But instead, you can load some of these + types of content into Red Dwarf: +

+
    +
  • + Bluesky URLs from supported clients (like{" "} + bsky.app or{" "} + deer.social). +
  • +
  • + AT-URIs (e.g.,{" "} + at://did:example/collection/item + ). +
  • +
  • + Plain handles (like{" "} + @username.bsky.social). +
  • +
  • + Direct DIDs (Decentralized Identifiers, starting with{" "} + did:). +
  • +
+

+ Simply paste one of these into the import field above and press + Enter to load the content. +

+
+
+ + ); }