extremely wip tangled spa
at main 3.1 kB view raw
1import { type Params, useParams } from "@solidjs/router"; 2import { createMemo, createResource, onMount, Show } from "solid-js"; 3import { figureOutDid } from "../../../util/handle"; 4import type { Compare, DID } from "../../../util/types"; 5import { Header } from "../components/header"; 6import { useDid } from "../context"; 7import { getRepoCommit, getRepoCompare } from "../main.data"; 8import { buildTree, type TreeNode } from "./data"; 9import { DiffView, Sidebar } from "./generic"; 10 11export async function preloadRepoCompare({ params }: { params: Params }) { 12 const did = await figureOutDid(params.user!); 13 if (!did) return; 14 getRepoCommit(did, params.repo!, params.ref!); 15} 16 17export default function RepoCompare() { 18 const params = useParams() as { 19 user: string; 20 repo: string; 21 base: string; 22 compare: string; 23 }; 24 const did = useDid(); 25 26 const [compare] = createResource( 27 () => { 28 const d = did(); 29 if (!d) return; 30 return [d, params.repo, params.base, params.compare] as const; 31 }, 32 async ([did, repo, base, compare]) => { 33 const res = await getRepoCompare(did as DID, repo, base, compare); 34 if (!res.ok) return; 35 return res.data as Compare; 36 }, 37 ); 38 39 const compareDiffViewInput = createMemo(() => { 40 if (!compare()?.combined_patch) return; 41 return compare()!.combined_patch!.map((diff) => ({ 42 oldName: diff.OldName, 43 newName: diff.NewName, 44 textFragments: diff.TextFragments || [], 45 })); 46 }); 47 48 const sidebar = createMemo(() => { 49 if (!compare()?.combined_patch) 50 return { name: "", fullPath: "", type: "directory" } as TreeNode; 51 const set = new Set( 52 compare()!.combined_patch!.flatMap((file) => [ 53 file.NewName, 54 file.OldName, 55 ]), 56 ); 57 set.delete(""); 58 return buildTree(set); 59 }); 60 61 const compareNumbers = createMemo(() => { 62 if (!compare()?.combined_patch) return { insertions: 0, deletions: 0 }; 63 let [insertions, deletions] = [0, 0]; 64 compare()!.combined_patch!.forEach((file) => { 65 if (!file.TextFragments) return; 66 file.TextFragments.forEach((fragment) => { 67 insertions += fragment.LinesAdded; 68 deletions += fragment.LinesDeleted; 69 }); 70 }); 71 return { insertions, deletions }; 72 }); 73 74 onMount(() => { 75 if (window.location.hash) { 76 const element = document.getElementById(window.location.hash.slice(1)); 77 if (element) 78 element.scrollIntoView({ behavior: "instant", block: "start" }); 79 } 80 }); 81 82 return ( 83 <div class="mx-auto max-w-10xl"> 84 <Show when={compare()}> 85 <CommitHeader user={params.user} repo={params.repo} /> 86 </Show> 87 <Show when={sidebar()?.children && compare() && compareDiffViewInput()}> 88 <div class="flex flex-col gap-1 md:flex-row"> 89 <Sidebar 90 sidebar={sidebar()} 91 insertions={compareNumbers().insertions} 92 deletions={compareNumbers().deletions} 93 /> 94 <div class="min-w-0 flex-1 flex-col gap-1 p-1 max-md:pt-0 md:pl-0"> 95 <DiffView diff={compareDiffViewInput()!} /> 96 </div> 97 </div> 98 </Show> 99 </div> 100 ); 101} 102 103function CommitHeader(props: { user: string; repo: string }) { 104 return ( 105 <div> 106 <Header user={props.user} repo={props.repo} /> 107 </div> 108 ); 109}