import { isCid, isDid, isNsid, isResourceUri, Nsid } from "@atcute/lexicons/syntax"; import { A, useNavigate, useParams } from "@solidjs/router"; import { createEffect, createSignal, ErrorBoundary, For, on, Show } from "solid-js"; import { resolveLexiconAuthority } from "../utils/api"; import { hideMedia } from "../views/settings"; import { pds } from "./navbar"; import { addNotification, removeNotification } from "./notification"; import VideoPlayer from "./video-player"; interface AtBlob { $type: string; ref: { $link: string }; mimeType: string; } const JSONString = (props: { data: string; isType?: boolean; isLink?: boolean; parentIsBlob?: boolean; }) => { const navigate = useNavigate(); const params = useParams(); const isURL = URL.canParse ?? ((url, base) => { try { new URL(url, base); return true; } catch { return false; } }); const handleClick = async (lex: string) => { try { const [nsid, anchor] = lex.split("#"); const authority = await resolveLexiconAuthority(nsid as Nsid); const hash = anchor ? `#schema:${anchor}` : "#schema"; navigate(`/at://${authority}/com.atproto.lexicon.schema/${nsid}${hash}`); } catch (err) { console.error("Failed to resolve lexicon authority:", err); const id = addNotification({ message: "Could not resolve schema", type: "error", }); setTimeout(() => removeNotification(id), 5000); } }; return ( " {(part) => ( <> {isResourceUri(part) ? {part} : isDid(part) ? {part} : isNsid(part.split("#")[0]) && props.isType ? : isCid(part) && props.isLink && props.parentIsBlob && params.repo ? {part} : ( isURL(part) && ["http:", "https:", "web+at:"].includes(new URL(part).protocol) && part.split("\n").length === 1 ) ? {part} : part} )} " ); }; const JSONNumber = ({ data }: { data: number }) => { return {data}; }; const JSONBoolean = ({ data }: { data: boolean }) => { return {data ? "true" : "false"}; }; const JSONNull = () => { return null; }; const JSONObject = (props: { data: { [x: string]: JSONType }; repo: string; parentIsBlob?: boolean; }) => { const params = useParams(); const [hide, setHide] = createSignal( localStorage.hideMedia === "true" || params.rkey === undefined, ); const [mediaLoaded, setMediaLoaded] = createSignal(false); createEffect(() => { if (hideMedia()) setHide(hideMedia()); }); createEffect( on( hide, (value) => { if (value === false) setMediaLoaded(false); }, { defer: true }, ), ); const isBlob = props.data.$type === "blob"; const isBlobContext = isBlob || props.parentIsBlob; const Obj = ({ key, value }: { key: string; value: JSONType }) => { const [show, setShow] = createSignal(true); return ( ); }; const rawObj = ( {([key, value]) => } ); const blob: AtBlob = props.data as any; if (blob.$type === "blob") { return ( <> setMediaLoaded(true)} /> Failed to load video}> setMediaLoaded(true)} /> {rawObj} ); } return rawObj; }; const JSONArray = (props: { data: JSONType[]; repo: string; parentIsBlob?: boolean }) => { return ( {(value, index) => ( )} ); }; export const JSONValue = (props: { data: JSONType; repo: string; isType?: boolean; isLink?: boolean; parentIsBlob?: boolean; }) => { const data = props.data; if (typeof data === "string") return ( ); if (typeof data === "number") return ; if (typeof data === "boolean") return ; if (data === null) return ; if (Array.isArray(data)) return ; return ; }; export type JSONType = string | number | boolean | null | { [x: string]: JSONType } | JSONType[];