extremely wip tangled spa
at main 4.3 kB view raw
1import { type Params, useParams } from "@solidjs/router"; 2import { createMemo, createResource, onMount, Show } from "solid-js"; 3import { figureOutDid } from "../../../util/handle"; 4import { toRelativeTime } from "../../../util/time"; 5import type { Commit, DID } from "../../../util/types"; 6import { Header } from "../components/header"; 7import { useDid } from "../context"; 8import { getRepoCommit } from "../main.data"; 9import { buildTree, type TreeNode } from "./data"; 10import { DiffView, Sidebar } from "./generic"; 11 12export async function preloadRepoCommit({ params }: { params: Params }) { 13 const did = await figureOutDid(params.user!); 14 if (!did) return; 15 getRepoCommit(did, params.repo!, params.ref!); 16} 17 18export default function RepoCommit() { 19 const params = useParams() as { user: string; repo: string; ref: string }; 20 const did = useDid(); 21 22 const [commit] = createResource( 23 () => { 24 const d = did(); 25 if (!d) return; 26 return [d, params.repo, params.ref] as const; 27 }, 28 async ([did, repo, ref]) => { 29 const res = await getRepoCommit(did as DID, repo, ref); 30 if (!res.ok) return; 31 return res.data as Commit; 32 }, 33 ); 34 35 const commitDiffViewInput = createMemo(() => { 36 if (!commit()?.diff) return; 37 return commit()!.diff.diff.map((diff) => ({ 38 oldName: diff.name.old, 39 newName: diff.name.new, 40 textFragments: diff.text_fragments, 41 })); 42 }); 43 44 const sidebar = createMemo(() => { 45 if (!commit()?.diff.diff) 46 return { name: "", fullPath: "", type: "directory" } as TreeNode; 47 return buildTree(commit()!.diff.diff.map((v) => v.name.new)); 48 }); 49 50 const message = createMemo(() => { 51 const c = commit(); 52 if (!c) return; 53 54 const titleEnd = c.diff.commit.message.indexOf("\n"); 55 return { 56 title: c.diff.commit.message.slice(0, titleEnd), 57 content: c.diff.commit.message.slice(titleEnd + 1), 58 }; 59 }); 60 61 onMount(() => { 62 if (window.location.hash) { 63 const element = document.getElementById(window.location.hash.slice(1)); 64 if (element) 65 element.scrollIntoView({ behavior: "instant", block: "start" }); 66 } 67 }); 68 69 return ( 70 <div class="mx-auto max-w-10xl"> 71 <Show when={commit() && message()}> 72 <CommitHeader 73 user={params.user} 74 repo={params.repo} 75 message={message()!} 76 commit={commit()!} 77 /> 78 </Show> 79 <Show when={sidebar()?.children && commit() && commitDiffViewInput()}> 80 <div class="flex flex-col gap-1 md:flex-row"> 81 <Sidebar 82 sidebar={sidebar()} 83 insertions={commit()!.diff.stat.insertions} 84 deletions={commit()!.diff.stat.deletions} 85 /> 86 <div class="min-w-0 flex-1 flex-col gap-1 p-1 max-md:pt-0 md:pl-0"> 87 <DiffView diff={commitDiffViewInput()!} /> 88 </div> 89 </div> 90 </Show> 91 </div> 92 ); 93} 94 95function CommitHeader(props: { 96 user: string; 97 repo: string; 98 message: { title: string; content: string }; 99 commit: Commit; 100}) { 101 const date = () => new Date(props.commit.diff.commit.author.When); 102 return ( 103 <div> 104 <Header user={props.user} repo={props.repo} /> 105 <div class="mx-1 flex flex-col gap-2 rounded bg-white p-4 dark:bg-gray-800"> 106 <div>{props.message.title}</div> 107 <Show when={props.message.content}> 108 <div class="text-xs">{props.message.content}</div> 109 </Show> 110 <div class="text-gray-500 text-xs dark:text-gray-300"> 111 <span 112 title={date().toLocaleString(undefined, { 113 dateStyle: "full", 114 timeStyle: "short", 115 })} 116 >{`${toRelativeTime(date())}`}</span> 117 <span class="select-none px-1 before:content-['\00B7']" /> 118 <span>{`${props.commit.diff.commit.author.Name} <${props.commit.diff.commit.author.Email}>`}</span> 119 <span class="select-none px-1 before:content-['\00B7']" /> 120 <a 121 class="hover:text-gray-600 hover:underline hover:dark:text-gray-200" 122 href={`/${props.user}/${props.repo}/commit/${props.commit.ref}`} 123 > 124 {props.commit.ref.slice(0, 8)} 125 </a> 126 <Show when={props.commit.diff.commit.parent}> 127 <div class="iconify gravity-ui--arrow-left mx-1 text-[0.6rem]" /> 128 <a 129 class="hover:text-gray-600 hover:underline hover:dark:text-gray-200" 130 href={`/${props.user}/${props.repo}/commit/${props.commit.diff.commit.parent}`} 131 > 132 {props.commit.diff.commit.parent.slice(0, 8)} 133 </a> 134 </Show> 135 </div> 136 </div> 137 </div> 138 ); 139}