extremely wip tangled spa
at main 3.5 kB view raw
1import { 2 createAsync, 3 type Params, 4 useNavigate, 5 useParams, 6} from "@solidjs/router"; 7import { createMemo, createResource, onMount, Show } from "solid-js"; 8import { CodeBlock } from "../../elements/code_block"; 9import { formatBytes } from "../../util/bytes"; 10import { getLanguage } from "../../util/get_language"; 11import { figureOutDid } from "../../util/handle"; 12import { Header } from "./components/header"; 13import { PathBar } from "./components/pathbar"; 14import { useDid } from "./context"; 15import { getRepoBlob, getRepoBlobUrl, getRepoDefaultBranch } from "./main.data"; 16 17export async function preloadRepoBlob({ params }: { params: Params }) { 18 const did = await figureOutDid(params.user!); 19 if (!did) return; 20 getRepoBlob(did, params.repo!, params.ref!, params.path!); 21} 22 23export default function RepoBlob() { 24 const params = useParams() as { 25 user: string; 26 repo: string; 27 ref: string; 28 path: string; 29 }; 30 const did = useDid(); 31 const navigate = useNavigate(); 32 33 const blob = createAsync(() => 34 (async () => { 35 const d = did(); 36 if (!d) return; 37 const res = await getRepoBlob(d, params.repo, params.ref, params.path); 38 if (res.status === 404) { 39 const split = window.location.pathname.split("/"); 40 split[3] = "tree"; 41 navigate(split.join("/"), { replace: true }); 42 } 43 if (!res.ok) return; 44 return res.data; 45 })(), 46 ); 47 48 const blobUrl = createAsync(async () => { 49 const d = did(); 50 if (!d) return; 51 return await getRepoBlobUrl(d, params.repo, params.ref, params.path); 52 }); 53 54 const codeBlock = createMemo(() => { 55 if (!blob()?.content) return; 56 return ( 57 <CodeBlock 58 code={blob()!.content!} 59 language={getLanguage(blob()!.path.split("/").pop()) || "text"} 60 /> 61 ); 62 }); 63 64 const [defaultBranch] = createResource(did, async (did) => { 65 const res = await getRepoDefaultBranch(did, params.repo); 66 if (!res.ok) return; 67 return res.data.name; 68 }); 69 70 const ref = () => params.ref || defaultBranch(); 71 72 onMount(() => { 73 if (window.location.hash) { 74 const element = document.getElementById(window.location.hash.slice(1)); 75 if (element) 76 element.scrollIntoView({ behavior: "instant", block: "start" }); 77 } 78 }); 79 80 return ( 81 <div class="mx-auto max-w-5xl"> 82 <Header user={params.user} repo={params.repo} /> 83 <div class="flex flex-col rounded bg-white py-2 dark:bg-gray-800"> 84 <div class="mx-5 flex flex-col justify-between gap-1 border-gray-300 border-b py-2 md:flex-row md:items-center dark:border-gray-700"> 85 <PathBar 86 user={params.user} 87 repo={params.repo} 88 gitref={ref()!} 89 path={params.path} 90 is_file={true} 91 /> 92 <div class="text-gray-500 text-xs dark:text-gray-400"> 93 <Show when={blobUrl() && ref() && blob()}> 94 <span> 95 {"at "} 96 <a 97 href={`/${params.user}/${params.repo}/tree/${ref()!}`} 98 class="text-black hover:text-gray-700 hover:underline dark:text-white hover:dark:text-gray-300" 99 > 100 {ref()!} 101 </a> 102 </span> 103 <span class="select-none px-1 before:content-['\00B7']" /> 104 <span>{formatBytes(blob()!.size!)}</span> 105 <span class="select-none px-1 before:content-['\00B7']" /> 106 <a 107 href={blobUrl()} 108 class="text-black hover:text-gray-700 hover:underline dark:text-white hover:dark:text-gray-300" 109 > 110 view raw 111 </a> 112 </Show> 113 </div> 114 </div> 115 <div class="flex flex-col p-4">{codeBlock()}</div> 116 </div> 117 </div> 118 ); 119}