This repository has no description
0

Configure Feed

Select the types of activity you want to include in your feed.

core / web / src / lib / components / repo / EmptyRepo.svelte
4.0 kB 134 lines
1<script lang="ts"> 2 import { resolve } from "$app/paths"; 3 import { getAuth } from "$lib/auth.svelte"; 4 import { createBobbinClient } from "$lib/api/client"; 5 import { count } from "$lib/api/count"; 6 import type { RepoInfo } from "./types"; 7 8 interface Props { 9 repo: RepoInfo; 10 /** 11 * Overrides the SSH key lookup, for deterministic stories/tests. 12 * Left unset in real usage, in which case it's figured out from the API. 13 */ 14 hasSshKey?: boolean; 15 } 16 17 let { repo, hasSshKey }: Props = $props(); 18 19 const auth = getAuth(); 20 const isOwner = $derived(auth.currentDid === repo.ownerDid); 21 // same host rewrite as the clone urls 22 const sshHost = $derived( 23 (repo.knot === "knot1.tangled.sh" ? "tangled.org" : repo.knot) 24 .replace(/^[a-z]+:\/\//, "") 25 .split(/[:/]/)[0] 26 ); 27 const remote = $derived(`git@${sshHost}:${repo.repoDid ?? `${repo.ownerHandle}/${repo.name}`}`); 28 29 type KeyStatus = "checking" | "has-key" | "no-key"; 30 31 let keyStatus = $state<KeyStatus>("checking"); 32 33 $effect(() => { 34 if (hasSshKey !== undefined) { 35 keyStatus = hasSshKey ? "has-key" : "no-key"; 36 return; 37 } 38 39 if (!isOwner) return; 40 const did = auth.currentDid; 41 if (!did) return; 42 43 let cancelled = false; 44 keyStatus = "checking"; 45 46 (async () => { 47 try { 48 const ctx = createBobbinClient({ serviceUrl: auth.bobbinUrl }); 49 const result = await count(ctx, "sh.tangled.publicKey.countKeys", did); 50 if (!cancelled) keyStatus = result.count > 0 ? "has-key" : "no-key"; 51 } catch { 52 // safe fallback: guide the owner through generating a key. 53 if (!cancelled) keyStatus = "no-key"; 54 } 55 })(); 56 57 return () => { 58 cancelled = true; 59 }; 60 }); 61</script> 62 63{#snippet bullet(n: number)} 64 <span 65 class="mr-2 inline-flex size-5 shrink-0 items-center justify-center rounded-full bg-background-inset align-middle font-mono text-xs" 66 > 67 {n} 68 </span> 69{/snippet} 70 71{#snippet codeBlock(lines: string[])} 72 <pre class="overflow-x-auto rounded bg-background-inset p-3 font-mono text-sm">{lines.join( 73 "\n" 74 )}</pre> 75{/snippet} 76 77{#if isOwner} 78 {#if keyStatus === "checking"} 79 <div class="py-6" aria-hidden="true"></div> 80 {:else if keyStatus === "has-key"} 81 <div class="flex w-full place-content-center"> 82 <div class="flex w-fit flex-col gap-5 py-6 text-sm"> 83 <p>This is an empty repository.</p> 84 <div class="flex flex-col gap-2"> 85 <p class="text-foreground-subtle">…create a new repository on the command line</p> 86 {@render codeBlock([ 87 `echo "# ${repo.name}" >> README.md`, 88 "git init", 89 "git add README.md", 90 'git commit -m "initial commit"', 91 `git branch -M ${repo.defaultBranch}`, 92 `git remote add origin ${remote}`, 93 `git push -u origin ${repo.defaultBranch}` 94 ])} 95 </div> 96 <div class="flex flex-col gap-2"> 97 <p class="text-foreground-subtle"> 98 …or push an existing repository from the command line 99 </p> 100 {@render codeBlock([ 101 `git remote add origin ${remote}`, 102 `git branch -M ${repo.defaultBranch}`, 103 `git push -u origin ${repo.defaultBranch}` 104 ])} 105 </div> 106 </div> 107 </div> 108 {:else} 109 <div class="flex w-full place-content-center"> 110 <div class="flex w-fit flex-col gap-4 py-6 text-sm"> 111 <p>This is an empty repository. To get started:</p> 112 <p> 113 {@render bullet(1)}First, generate a new 114 <a 115 href="https://git-scm.com/book/en/v2/Git-on-the-Server-Generating-Your-SSH-Public-Key" 116 rel="noopener" 117 class="underline">SSH key pair</a 118 >. 119 </p> 120 <p> 121 {@render bullet(2)}Then add the public key from the 122 <a href={resolve("/settings/keys")} class="underline">keys page</a> in your settings. 123 </p> 124 <p> 125 {@render bullet(3)}Configure your remote to 126 <code class="rounded bg-background-inset px-1 font-mono">{remote}</code> 127 </p> 128 <p>{@render bullet(4)}Push!</p> 129 </div> 130 </div> 131 {/if} 132{:else} 133 <p class="py-6 text-center text-foreground-subtle">This is an empty repository.</p> 134{/if}