Radish alpha
r
rad:z4V1sjrXqjvFdnCUbxPFqd5p4DtH5
Radicle web interface
Radicle
Git
radicle-explorer src views repos Source Tree Folder.svelte
<script lang="ts">
  import type { BaseUrl, Tree } from "@http-client";

  import { createEventDispatcher } from "svelte";

  import Loading from "@app/components/Loading.svelte";
  import Link from "@app/components/Link.svelte";

  import File from "./File.svelte";
  import Icon from "@app/components/Icon.svelte";
  import Submodule from "./Submodule.svelte";

  export let baseUrl: BaseUrl;
  export let currentPath: string;
  export let fetchTree: (path: string) => Promise<Tree | undefined>;
  export let name: string;
  export let peer: string | undefined;
  export let prefix: string;
  export let repoId: string;
  export let revision: string | undefined;

  $: expanded = currentPath.indexOf(prefix) === 0;
  $: tree = expanded
    ? fetchTree(prefix).then(tree => {
        return tree;
      })
    : Promise.resolve(undefined);

  const dispatch = createEventDispatcher<{ select: string }>();
  const onSelectFile = ({ detail: path }: { detail: string }) =>
    dispatch("select", path);
</script>

<style>
  .folder {
    display: flex;
    cursor: pointer;
    padding: 0.25rem 0.875rem;
    margin: 0.25rem 0;
    user-select: none;
    white-space: nowrap;
  }
  .folder:hover {
    background-color: var(--color-surface-subtle);
    border-radius: var(--border-radius-sm);
  }

  .folder-name {
    margin-left: 0.25rem;
    font: var(--txt-body-m-regular);
  }

  .container {
    padding-left: 1rem;
    margin-left: 0.5rem;
  }

  .loading {
    display: inline-block;
    padding: 0.5rem 0;
  }
  .icon-container {
    display: flex;
    justify-content: center;
    align-items: center;
    color: var(--color-text-tertiary);
    margin-right: 0.125rem;
  }

  .expanded {
    color: var(--color-text-primary);
  }
</style>

<!-- svelte-ignore a11y-click-events-have-key-events -->
<div
  role="button"
  tabindex="0"
  class="folder"
  on:click={() => {
    // eslint-disable-next-line
    expanded = !expanded;
  }}>
  <div class="icon-container" class:expanded>
    {#if expanded}
      <Icon name="folder-open" />
    {:else}
      <Icon name="folder" />
    {/if}
  </div>
  <span class="folder-name" class:expanded>{name}</span>
</div>

{#if expanded}
  <div class="container">
    {#await tree}
      <span class="loading"><Loading grayscale noDelay small margins /></span>
    {:then tree}
      {#if tree}
        {#each tree.entries as entry (entry.path)}
          {#if entry.kind === "tree"}
            <!-- svelte:self doesn't check types, make sure to pass in all
            required props! -->
            <svelte:self
              name={entry.name}
              on:select={onSelectFile}
              prefix={`${entry.path}/`}
              {baseUrl}
              {currentPath}
              {fetchTree}
              {peer}
              {repoId}
              {revision} />
          {:else if entry.kind === "submodule"}
            <Submodule name={entry.name} oid={entry.oid} />
          {:else}
            <Link
              route={{
                resource: "repo.source",
                repo: repoId,
                node: baseUrl,
                path: entry.path,
                peer,
                revision,
              }}
              on:afterNavigate={() => onSelectFile({ detail: entry.path })}>
              <File active={entry.path === currentPath} name={entry.name} />
            </Link>
          {/if}
        {/each}
      {/if}
    {/await}
  </div>
{/if}