Radish alpha
r
Radicle desktop app
Radicle
Git (anonymous pull)
Log in to clone via SSH
Add revision selector
Rūdolfs Ošiņš committed 1 year ago
commit 5310fe0b92b83a2586812fc2a69eb7445ec5fcff
parent 5069613ff6898a0856cd82825edbce4b3c43927d
3 files changed +153 -42
modified src/components/Revision.svelte
@@ -1,10 +1,8 @@
<script lang="ts">
-
  import type { Action } from "@bindings/cob/patch/Action";
  import type { Author } from "@bindings/cob/Author";
  import type { Config } from "@bindings/config/Config";
  import type { Diff } from "@bindings/diff/Diff";
  import type { Embed } from "@bindings/cob/thread/Embed";
-
  import type { Operation } from "@bindings/cob/Operation";
  import type { Revision } from "@bindings/cob/patch/Revision";
  import type { Thread } from "@bindings/cob/thread/Thread";

@@ -21,7 +19,6 @@
  import CommentComponent from "@app/components/Comment.svelte";
  import CommentToggleInput from "@app/components/CommentToggleInput.svelte";
  import Icon from "@app/components/Icon.svelte";
-
  import PatchTimeline from "@app/components/PatchTimeline.svelte";
  import ThreadComponent from "@app/components/Thread.svelte";

  interface Props {
@@ -30,26 +27,17 @@
    patchId: string;
    revision: Revision;
    config: Config;
-
    activity: Operation<Action>[];
    reload: () => Promise<void>;
  }

  /* eslint-disable prefer-const */
-
  let {
-
    rid,
-
    repoDelegates,
-
    patchId,
-
    revision,
-
    config,
-
    activity,
-
    reload,
-
  }: Props = $props();
+
  let { rid, repoDelegates, patchId, revision, config, reload }: Props =
+
    $props();
  /* eslint-enable prefer-const */

  let focusReply: boolean = $state(false);
  let hideChanges = $state(false);
  let hideDiscussion = $state(false);
-
  let hideTimeline = $state(false);
  let topLevelReplyOpen = $state(false);

  const threads = $derived(
@@ -78,7 +66,6 @@

    hideDiscussion = false;
    hideChanges = false;
-
    hideTimeline = false;
  });

  async function editRevision(
@@ -350,19 +337,3 @@
    {/await}
  </div>
</div>
-

-
<div>
-
  <!-- svelte-ignore a11y_click_events_have_key_events -->
-
  <div
-
    role="button"
-
    tabindex="0"
-
    class="txt-semibold global-flex"
-
    style:margin="1rem 0"
-
    style:cursor="pointer"
-
    onclick={() => (hideTimeline = !hideTimeline)}>
-
    <Icon name={hideTimeline ? "chevron-right" : "chevron-down"} />Timeline
-
  </div>
-
  <div class:hide={hideTimeline}>
-
    <PatchTimeline {activity} {patchId} />
-
  </div>
-
</div>
modified src/components/Tab.svelte
@@ -37,6 +37,7 @@
    display: flex;
    gap: 0.5rem;
    padding: 5px 0;
+
    align-items: center;
  }

  .active {
modified src/views/repo/Patch.svelte
@@ -9,9 +9,13 @@
  import type { RepoInfo } from "@bindings/repo/RepoInfo";
  import type { Revision } from "@bindings/cob/patch/Revision";

+
  import uniqBy from "lodash/uniqBy";
+
  import orderBy from "lodash/orderBy";
+

  import * as roles from "@app/lib/roles";
  import { announce } from "@app/components/AnnounceSwitch.svelte";
  import {
+
    authorForNodeId,
    formatOid,
    patchStatusBackgroundColor,
    patchStatusColor,
@@ -33,6 +37,13 @@
  import Sidebar from "@app/components/Sidebar.svelte";
  import Tab from "@app/components/Tab.svelte";
  import TextInput from "@app/components/TextInput.svelte";
+
  import NakedButton from "@app/components/NakedButton.svelte";
+
  import Popover, { closeFocused } from "@app/components/Popover.svelte";
+
  import DropdownList from "@app/components/DropdownList.svelte";
+
  import DropdownListItem from "@app/components/DropdownListItem.svelte";
+
  import NodeId from "@app/components/NodeId.svelte";
+
  import Avatar from "@app/components/Avatar.svelte";
+
  import PatchTimeline from "@app/components/PatchTimeline.svelte";

  interface Props {
    repo: RepoInfo;
@@ -65,6 +76,24 @@
  let labelSaveInProgress: boolean = $state(false);
  let assigneesSaveInProgress: boolean = $state(false);
  let tab: "patch" | "revisions" = $state("patch");
+
  let hideTimeline = $state(false);
+
  let selectedRevision: Revision = $state(revisions.slice(-1)[0]);
+
  const revisionAuthors = $derived(
+
    orderBy(
+
      uniqBy(
+
        revisions.map(r => {
+
          return r.author;
+
        }),
+
        "did",
+
      ),
+
      [
+
        o => {
+
          return o.did === patch.author.did;
+
        },
+
      ],
+
      ["desc"],
+
    ),
+
  );

  $effect(() => {
    items = patches.content;
@@ -79,6 +108,8 @@
    tab = "patch";
    editingTitle = false;
    updatedTitle = patch.title;
+
    selectedRevision = revisions.slice(-1)[0];
+
    hideTimeline = false;
  });

  const project = $derived(repo.payloads["xyz.radicle.project"]!);
@@ -257,7 +288,7 @@
    padding-bottom: 1rem;
  }
  .content {
-
    padding: 1rem 1rem 1rem 0;
+
    padding: 1rem 1rem 0 0;
  }

  .metadata-divider {
@@ -279,6 +310,12 @@
    margin-bottom: 0.5rem;
    color: var(--color-foreground-dim);
  }
+
  .dropdown-group:not(:last-of-type) {
+
    margin-bottom: 1rem;
+
  }
+
  .hide {
+
    display: none;
+
  }
</style>

<Layout {loadMoreSecondColumn} publicKey={config.publicKey}>
@@ -419,6 +456,9 @@
          style:z-index="10"
          style:gap="1rem"
          style:padding="0 1rem">
+
          <span class="txt-small" style:color="var(--color-foreground-dim)">
+
            Revisions
+
          </span>
          <Tab
            active={tab === "patch"}
            onclick={() => {
@@ -438,14 +478,99 @@
              onclick={() => {
                tab = "revisions";
              }}>
-
              {formatOid(revisions.slice(-1)[0].id)}
-
              <span
-
                class="global-counter"
-
                style:height="22px"
-
                style:color="var(--color-foreground-contrast)">
-
                Latest
-
              </span>
+
              <Avatar
+
                publicKey={selectedRevision.author.did.replace(
+
                  "did:key:",
+
                  "",
+
                )} />
+
              {formatOid(selectedRevision.id)}
+
              {#if selectedRevision.id === revisions.slice(-1)[0].id}
+
                <span
+
                  class="global-counter"
+
                  style:height="22px"
+
                  style:color="var(--color-foreground-contrast)">
+
                  Latest
+
                </span>
+
              {/if}
+
              {#if selectedRevision.id === revisions[0].id}
+
                <span
+
                  class="global-counter"
+
                  style:height="22px"
+
                  style:color="var(--color-foreground-contrast)">
+
                  Initial
+
                </span>
+
              {/if}
            </Tab>
+

+
            <Popover
+
              popoverPadding="0"
+
              popoverPositionTop="2.5rem"
+
              popoverPositionLeft="0">
+
              {#snippet toggle(onclick)}
+
                <NakedButton variant="ghost" {onclick}>
+
                  <Icon name="chevron-down" />
+
                </NakedButton>
+
              {/snippet}
+

+
              {#snippet popover()}
+
                <Border variant="ghost">
+
                  <div style:max-width="20rem" style:padding-top="0.5rem">
+
                    {#each revisionAuthors as author}
+
                      <div class="dropdown-group">
+
                        <div
+
                          style:padding-left="0.5rem"
+
                          style:padding-bottom="0.5rem">
+
                          <NodeId {...authorForNodeId(author)} />
+
                        </div>
+
                        <DropdownList
+
                          items={orderBy(
+
                            revisions.filter(r => {
+
                              return r.author.did === author.did;
+
                            }),
+
                            "timestamp",
+
                            ["desc"],
+
                          )}>
+
                          {#snippet item(revision)}
+
                            <DropdownListItem
+
                              selected={revision.id === selectedRevision.id}
+
                              onclick={() => {
+
                                closeFocused();
+
                                selectedRevision = revision;
+
                                tab = "revisions";
+
                              }}>
+
                              <div class="global-flex txt-overflow">
+
                                <span class="global-oid">
+
                                  {formatOid(revision.id)}
+
                                </span>
+
                                {#if revision.id === revisions.slice(-1)[0].id}
+
                                  <span
+
                                    class="global-counter"
+
                                    style:height="22px"
+
                                    style:color="var(--color-foreground-contrast)">
+
                                    Latest
+
                                  </span>
+
                                {/if}
+
                                {#if revision.id === revisions[0].id}
+
                                  <span
+
                                    class="global-counter"
+
                                    style:height="22px"
+
                                    style:color="var(--color-foreground-contrast)">
+
                                    Initial
+
                                  </span>
+
                                {/if}
+
                                <span class="txt-overflow">
+
                                  {revision.description[0].body}
+
                                </span>
+
                              </div>
+
                            </DropdownListItem>
+
                          {/snippet}
+
                        </DropdownList>
+
                      </div>
+
                    {/each}
+
                  </div>
+
                </Border>
+
              {/snippet}
+
            </Popover>
          {/if}
        </div>
      </Border>
@@ -465,7 +590,6 @@
          repoDelegates={repo.delegates}
          patchId={patch.id}
          {reload}
-
          {activity}
          revision={revisions[0]}
          {config} />
      </Border>
@@ -483,10 +607,25 @@
          repoDelegates={repo.delegates}
          patchId={patch.id}
          {reload}
-
          {activity}
-
          revision={revisions.slice(-1)[0]}
+
          revision={selectedRevision}
          {config} />
      </Border>
    {/if}
  </div>
+

+
  <div style:margin-bottom="1rem">
+
    <!-- svelte-ignore a11y_click_events_have_key_events -->
+
    <div
+
      role="button"
+
      tabindex="0"
+
      class="txt-semibold global-flex"
+
      style:margin="1rem 0"
+
      style:cursor="pointer"
+
      onclick={() => (hideTimeline = !hideTimeline)}>
+
      <Icon name={hideTimeline ? "chevron-right" : "chevron-down"} />Timeline
+
    </div>
+
    <div class:hide={hideTimeline}>
+
      <PatchTimeline {activity} patchId={patch.id} />
+
    </div>
+
  </div>
</Layout>