218 lines · 9.6 KB
import { createFileRoute, Link, Outlet, redirect, useNavigate } from "@tanstack/react-router";
import { useEffect, useState } from "react";
import { setRepoVisibility } from "~/lib/analytics";
import { forkRepo, getRepoHeader, toggleStar, transferableOwners } from "~/fns/repos";
import { WatchMenu } from "~/components/WatchMenu";
import { useAction } from "~/hooks/use-action";
import { useOptimisticMutation } from "~/hooks/use-optimistic-mutation";
import { useViewer } from "~/hooks/use-viewer";
import { Badge } from "~/ui/Badge";
import { Button } from "~/ui/Button";
import { inputClass } from "~/ui/Field";
import { cn } from "~/utils/cn";
import { RepoProvisioning } from "~/components/RepoProvisioning";
import { useDismiss } from "~/hooks/use-dismiss";
import { usePollWhile } from "~/hooks/use-poll-while";
import { useEditorHotkey } from "~/hooks/use-editor-hotkey";
import { TextLink } from "~/ui/TextLink";
import { CountBadge } from "~/ui/CountBadge";
import { TabBar, TabLink } from "~/ui/Nav";

export const Route = createFileRoute("/$owner/$repo")({
  loader: async ({ params, location }) => {
    const header = await getRepoHeader({ data: { owner: params.owner, repo: params.repo } });
    const canonical = `/${header.repo.owner}/${header.repo.name}`;
    if (canonical.toLowerCase() !== `/${params.owner}/${params.repo}`.toLowerCase()) {
      const rest = location.pathname.split("/").slice(3).join("/");
      throw redirect({ href: `${canonical}${rest ? `/${rest}` : ""}${location.searchStr}` });
    }
    return header;
  },
  head: ({ params }) => ({ meta: [{ title: `${params.owner}/${params.repo} · gitfor` }] }),
  component: RepoLayout,
});

function CloneBox({ url }: { url: string }) {
  const [open, setOpen] = useState(false);
  const ref = useDismiss<HTMLDivElement>(open, () => setOpen(false));
  return (
    <div ref={ref} className="relative">
      <Button variant="primary" size="sm" onClick={() => setOpen((value) => !value)} aria-expanded={open}>