Code button: the SSH tab shows the address it will have, disabled, with why it is not on yet
The SSH tab showed only a note. It now shows git@<host>:owner/repo.git in the same line as HTTPS, dimmed with its copy button disabled (CopyLine disabled), and the note under it, linking to SSH keys. Settings → SSH keys says the same: keys added now work once SSH is on; until then HTTPS with an access token.
4 files+32−70/4 viewed
| 1 | 1 | import { Link } from "react-router"; | |
| 2 | 2 | ||
| 3 | − | import { cloneUrl, useAddresses } from "../lib/addresses"; | |
| 3 | + | import { cloneUrl, sshUrl, useAddresses } from "../lib/addresses"; | |
| 4 | 4 | import { AgentSetup } from "./agent-setup"; | |
| 5 | 5 | import { CopyLine } from "./ui"; | |
| 6 | 6 | import { Tabs, TabsContent, TabsList, TabsTrigger } from "./ui/tabs"; | |
| 26 | 26 | </p> | |
| 27 | 27 | </TabsContent> | |
| 28 | 28 | <TabsContent value="ssh"> | |
| 29 | − | <p className="rounded-lg border border-dashed border-line p-3 text-xs text-muted"> | |
| 30 | − | Git over SSH is waiting on inbound TCP on Cloudflare, which g1t has applied for. Use HTTPS for now: it | |
| 31 | − | clones, fetches and pushes the same. Keys you add under Settings → SSH keys will work as soon as SSH is on. | |
| 29 | + | <CopyLine text={sshUrl(addresses, path)} disabled /> | |
| 30 | + | <p className="mt-2 text-xs text-muted"> | |
| 31 | + | Not on yet: git over SSH is waiting on inbound TCP on Cloudflare, which g1t has applied for. Use HTTPS for | |
| 32 | + | now; it clones, fetches and pushes the same. Keys you add under{" "} | |
| 33 | + | <Link to="/settings/keys" className="text-fg underline underline-offset-4"> | |
| 34 | + | SSH keys | |
| 35 | + | </Link>{" "} | |
| 36 | + | will work as soon as SSH is on. | |
| 32 | 37 | </p> | |
| 33 | 38 | </TabsContent> | |
| 34 | 39 | <TabsContent value="agent"> |
| 348 | 348 | export function CopyLine({ | |
| 349 | 349 | text, | |
| 350 | 350 | prompt, | |
| 351 | + | disabled, | |
| 351 | 352 | }: { | |
| 352 | 353 | text: string; | |
| 353 | 354 | prompt?: boolean; | |
| 355 | + | /** Shown, so it is clear what will be there, but not yet usable: dimmed, with no copy. */ | |
| 356 | + | disabled?: boolean; | |
| 354 | 357 | }) { | |
| 355 | 358 | const [copied, setCopied] = useState(false); | |
| 356 | 359 | return ( | |
| 357 | − | <div className="group flex items-center gap-3 rounded-lg border border-line bg-surface py-2 pr-2 pl-3.5 font-mono text-[0.8125rem]"> | |
| 360 | + | <div | |
| 361 | + | aria-disabled={disabled || undefined} | |
| 362 | + | className={`group flex items-center gap-3 rounded-lg border border-line bg-surface py-2 pr-2 pl-3.5 font-mono text-[0.8125rem] ${disabled ? "cursor-not-allowed text-faint select-none" : ""}`} | |
| 363 | + | > | |
| 358 | 364 | {/* Wraps rather than hides: a command or an address is no use half seen. */} | |
| 359 | 365 | <code className="min-w-0 grow whitespace-pre-wrap [overflow-wrap:anywhere]"> | |
| 360 | 366 | {prompt && <span className="mr-2 text-faint select-none">$</span>} | |
| 373 | 379 | <button | |
| 374 | 380 | type="button" | |
| 375 | 381 | aria-label="Copy" | |
| 376 | − | className="shrink-0 rounded-md p-1.5 text-faint transition-colors hover:bg-raised hover:text-fg" | |
| 382 | + | disabled={disabled} | |
| 383 | + | className="shrink-0 rounded-md p-1.5 text-faint transition-colors hover:bg-raised hover:text-fg disabled:cursor-not-allowed disabled:opacity-50 disabled:hover:bg-transparent disabled:hover:text-faint" | |
| 377 | 384 | onClick={() => { | |
| 378 | 385 | void navigator.clipboard.writeText(text); | |
| 379 | 386 | setCopied(true); |
| 54 | 54 | return addressesFrom(useRouteLoaderData("root")); | |
| 55 | 55 | } | |
| 56 | 56 | ||
| 57 | + | /** The SSH clone address of a repository (`git@host:owner/name.git`), from its `owner/name`. */ | |
| 58 | + | export function sshUrl(addresses: Pick<Addresses, "site">, path: string): string { | |
| 59 | + | return `git@${new URL(addresses.site).hostname}:${path.replace(/^\/+/, "")}.git`; | |
| 60 | + | } | |
| 61 | + | ||
| 57 | 62 | /** The HTTPS clone address of a repository, from its `owner/name`. */ | |
| 58 | 63 | export function cloneUrl(addresses: Pick<Addresses, "site">, path: string): string { | |
| 59 | 64 | return `${addresses.site}/${path.replace(/^\/+/, "")}.git`; |
| 1 | 1 | import { identity } from "../../lib/services.server"; | |
| 2 | − | import { Form } from "react-router"; | |
| 2 | + | import { Form, Link } from "react-router"; | |
| 3 | 3 | ||
| 4 | 4 | import type { Route } from "./+types/keys"; | |
| 5 | 5 | import { page } from "../../lib/meta"; | |
| 40 | 40 | const { keys } = loaderData; | |
| 41 | 41 | return ( | |
| 42 | 42 | <section id="ssh-keys" className="scroll-mt-20"> | |
| 43 | + | <p className="mb-4 rounded-lg border border-dashed border-line p-3 text-xs text-muted"> | |
| 44 | + | Git over SSH is not on yet: it is waiting on inbound TCP on Cloudflare, which g1t has applied for. Keys you | |
| 45 | + | add now will work as soon as it is. Until then, clone and push over HTTPS with an{" "} | |
| 46 | + | <Link to="/settings/tokens" className="text-fg underline underline-offset-4"> | |
| 47 | + | access token | |
| 48 | + | </Link> | |
| 49 | + | . | |
| 50 | + | </p> | |
| 43 | 51 | <ul className="divide-y divide-line rounded-md border border-line empty:hidden"> | |
| 44 | 52 | {keys.map((key) => ( | |
| 45 | 53 | <li key={key.id} className="flex items-center gap-4 px-4 py-3"> |