Radish alpha
r
rad:z4V1sjrXqjvFdnCUbxPFqd5p4DtH5
Radicle web interface
Radicle
Git
radicle-explorer src views repos History.svelte
<script lang="ts">
  import type {
    BaseUrl,
    CommitHeader,
    PeerRefs,
    Repo,
    SeedingPolicy,
    Tree,
  } from "@http-client";
  import type { RepoRoute } from "./router";

  import config from "@app/lib/config";
  import { HttpdClient } from "@http-client";
  import { baseUrlToString, formatQualifiedRefname } from "@app/lib/utils";
  import { groupCommits } from "@app/lib/commit";

  import Button from "@app/components/Button.svelte";
  import CloneButton from "@app/views/repos/Header/CloneButton.svelte";
  import CommitTeaser from "./Commit/CommitTeaser.svelte";
  import ErrorMessage from "@app/components/ErrorMessage.svelte";
  import Header from "./Source/Header.svelte";
  import Layout from "./Layout.svelte";
  import Link from "@app/components/Link.svelte";
  import List from "@app/components/List.svelte";
  import Loading from "@app/components/Loading.svelte";
  import RepoNameHeader from "./Source/RepoNameHeader.svelte";
  import Separator from "./Separator.svelte";

  export let baseUrl: BaseUrl;
  export let seedingPolicy: SeedingPolicy;
  export let commit: string;
  export let commitHeaders: CommitHeader[];
  export let peer: string | undefined;
  export let peers: PeerRefs[];
  export let repo: Repo;
  export let revision: string | undefined;
  export let tree: Tree;
  export let nodeAvatarUrl: string | undefined;

  $: currentRefname = formatQualifiedRefname(
    revision || repo.payloads["xyz.radicle.project"].data.defaultBranch,
    peer,
  );

  const api = new HttpdClient(baseUrl);
  let totalCommits: number | undefined = undefined;

  function fetchTotalCommits(rid: string, sha: string) {
    void api.repo.getTreeStatsBySha(rid, sha).then(stats => {
      totalCommits = stats.commits;
    });
  }

  $: fetchTotalCommits(repo.rid, commit);

  // eslint-disable-next-line @typescript-eslint/no-explicit-any
  let error: any;
  let page = 0;
  let loading = false;
  let allCommitHeaders: CommitHeader[];

  $: baseRoute = {
    resource: "repo.history",
    node: baseUrl,
    repo: repo.rid,
  } as Extract<RepoRoute, { resource: "repo.history" }>;
  $: {
    allCommitHeaders = commitHeaders;
    page = 0;
  }

  async function loadMore() {
    loading = true;
    page += 1;
    try {
      const response = await api.repo.getAllCommits(repo.rid, {
        parent: allCommitHeaders[0].id,
        page,
        perPage: config.source.commitsPerPage,
      });
      allCommitHeaders = [...allCommitHeaders, ...response];
    } catch (e) {
      error = e;
    }
    loading = false;
  }
</script>

<style>
  .more {
    margin-top: 2rem;
    min-height: 3rem;
    display: flex;
    align-items: center;
    justify-content: center;
  }
  .group-header {
    margin: 1rem 0 0.5rem 1rem;
    font: var(--txt-body-m-regular);
    color: var(--color-text-tertiary);
  }
</style>

<Layout {nodeAvatarUrl} {baseUrl} {repo} activeTab="source">
  <svelte:fragment slot="breadcrumb">
    <Separator />
    <Link
      route={{
        resource: "repo.history",
        repo: repo.rid,
        node: baseUrl,
      }}>
      Commits
    </Link>
  </svelte:fragment>
  <svelte:fragment slot="actions">
    <CloneButton
      {baseUrl}
      {currentRefname}
      id={repo.rid}
      name={repo.payloads["xyz.radicle.project"].data.name} />
  </svelte:fragment>
  <RepoNameHeader {repo} {baseUrl} {seedingPolicy} slot="header" />

  <div
    style:padding="1rem"
    style:border-bottom="1px solid var(--color-border-subtle)"
    slot="subheader">
    <Header
      {baseRoute}
      {commit}
      {peers}
      {peer}
      {repo}
      {revision}
      {tree}
      node={baseUrl}
      filesLinkActive={false}
      historyLinkActive={true} />
  </div>

  <div>
    {#each groupCommits(allCommitHeaders) as group (group.time)}
      <div class="group-header">{group.date}</div>
      <List items={group.commits}>
        <CommitTeaser
          slot="item"
          let:item
          repoId={repo.rid}
          {baseUrl}
          commit={item} />
      </List>
    {/each}
  </div>

  {#if totalCommits === undefined || loading || allCommitHeaders.length < totalCommits}
    <div class="more">
      {#if totalCommits === undefined || loading}
        <Loading small={page !== 0} center />
      {:else if allCommitHeaders.length < totalCommits}
        <Button size="large" variant="outline" on:click={loadMore}>More</Button>
      {/if}
    </div>
  {/if}

  {#if error}
    <div class="message">
      <ErrorMessage
        title="Couldn't load commits"
        description="Make sure you are able to connect to the seed <code>{baseUrlToString(
          api.baseUrl,
        )}</code>"
        {error} />
    </div>
  {/if}
</Layout>