Radish alpha
r
Radicle desktop app
Radicle
Git (anonymous pull)
Log in to clone via SSH
Split patch view into Activity and Changes tabs
Brandon Oxendine committed 1 month ago
commit 2fbb6d691bbb923b6749db68fc018b3c9e26b2a6
parent 7c45ce8ba8557a406d8d3ca0e599fdb6a954174e
4 files changed +115 -75
modified src/components/Changes.svelte
@@ -22,7 +22,6 @@

  const { patchId, revision, rid, codeComments }: Props = $props();

-
  let hideChanges = $state(false);
  let filesExpanded = $state(true);
  let selectedCommit = $state<string>();
  let base = $state(revision.base);
@@ -32,7 +31,6 @@
    // eslint-disable-next-line @typescript-eslint/no-unused-expressions
    patchId;

-
    hideChanges = false;
    filesExpanded = true;
    selectedCommit = undefined;
    base = revision.base;
@@ -118,29 +116,20 @@

<div
  class="txt-body-m-regular global-flex"
-
  style:margin-bottom={hideChanges ? undefined : "1rem"}>
-
  <div class="global-flex">
-
    <Button variant="naked" onclick={() => (hideChanges = !hideChanges)}>
-
      <Icon name={hideChanges ? "chevron-right" : "chevron-down"} />
-
    </Button>
-
    <div class="txt-body-m-regular global-flex">Changes</div>
-
  </div>
-
  {#if !hideChanges}
-
    <div style:margin-left="auto">
-
      <Button variant="naked" onclick={() => (filesExpanded = !filesExpanded)}>
-
        {#if filesExpanded === true}
-
          <Icon name="collapse-vertical" />
-
          Collapse all
-
        {:else}
-
          <Icon name="expand-vertical" />
-
          Expand all
-
        {/if}
-
      </Button>
-
    </div>
-
  {/if}
+
  style:margin-bottom="1rem"
+
  style:justify-content="flex-end">
+
  <Button variant="naked" onclick={() => (filesExpanded = !filesExpanded)}>
+
    {#if filesExpanded === true}
+
      <Icon name="collapse-vertical" />
+
      Collapse all
+
    {:else}
+
      <Icon name="expand-vertical" />
+
      Expand all
+
    {/if}
+
  </Button>
</div>

-
<div style:display={hideChanges ? "none" : "revert"}>
+
<div>
  {#await cachedListCommits(rid, revision.base, revision.head) then commits}
    <div style:margin-bottom="1rem">
      <CommitsContainer>
modified src/components/Diff.svelte
@@ -431,7 +431,6 @@
        {/if}
      </div>
      <ThreadComponent
-
        inline
        rid={codeComments.rid}
        {thread}
        reactOnComment={codeComments.reactOnComment}
modified src/components/Revision.svelte
@@ -22,10 +22,18 @@
    revision: Revision;
    config: Config;
    loadPatch: () => Promise<void>;
+
    view?: "description" | "activity" | "changes";
  }

-
  const { rid, repoDelegates, patchId, revision, config, loadPatch }: Props =
-
    $props();
+
  const {
+
    rid,
+
    repoDelegates,
+
    patchId,
+
    revision,
+
    config,
+
    loadPatch,
+
    view = "activity",
+
  }: Props = $props();

  const commentThreads = $derived(
    ((revision.discussion &&
@@ -164,35 +172,37 @@
  }
</style>

-
<div class="txt-body-m-regular patch-body">
-
  <CommentComponent
-
    caption={revision.id === patchId ? "opened patch" : "created revision"}
-
    {rid}
-
    id={revision.id}
-
    lastEdit={revision.description.length > 1
-
      ? revision.description.at(-1)
-
      : undefined}
-
    author={revision.author}
-
    reactions={revision.reactions}
-
    timestamp={revision.timestamp}
-
    body={revision.description.slice(-1)[0].body}
-
    reactOnComment={reactOnRevision}
-
    editComment={roles.isDelegateOrAuthor(
-
      config.publicKey,
-
      repoDelegates.map(delegate => delegate.did),
-
      revision.author.did,
-
    ) && editRevision}>
-
  </CommentComponent>
-
</div>
-

-
<Discussion
-
  cobId={patchId}
-
  {commentThreads}
-
  {config}
-
  {createComment}
-
  {editComment}
-
  {reactOnComment}
-
  {repoDelegates}
-
  {rid} />
-

-
<Changes {rid} {patchId} {revision} />
+
{#if view === "description"}
+
  <div class="txt-body-m-regular patch-body">
+
    <CommentComponent
+
      caption={revision.id === patchId ? "opened patch" : "created revision"}
+
      {rid}
+
      id={revision.id}
+
      lastEdit={revision.description.length > 1
+
        ? revision.description.at(-1)
+
        : undefined}
+
      author={revision.author}
+
      reactions={revision.reactions}
+
      timestamp={revision.timestamp}
+
      body={revision.description.slice(-1)[0].body}
+
      reactOnComment={reactOnRevision}
+
      editComment={roles.isDelegateOrAuthor(
+
        config.publicKey,
+
        repoDelegates.map(delegate => delegate.did),
+
        revision.author.did,
+
      ) && editRevision}>
+
    </CommentComponent>
+
  </div>
+
{:else if view === "activity"}
+
  <Discussion
+
    cobId={patchId}
+
    {commentThreads}
+
    {config}
+
    {createComment}
+
    {editComment}
+
    {reactOnComment}
+
    {repoDelegates}
+
    {rid} />
+
{:else}
+
  <Changes {rid} {patchId} {revision} />
+
{/if}
modified src/views/repo/Patch.svelte
@@ -23,6 +23,7 @@
  import { announce } from "@app/components/AnnounceSwitch.svelte";
  import Button from "@app/components/Button.svelte";
  import CheckoutPatchButton from "@app/components/CheckoutPatchButton.svelte";
+
  import DraftReviewBar from "@app/components/DraftReviewBar.svelte";
  import EditableTitle from "@app/components/EditableTitle.svelte";
  import ExternalLink from "@app/components/ExternalLink.svelte";
  import Icon from "@app/components/Icon.svelte";
@@ -59,19 +60,21 @@
  }: Props = $props();
  /* eslint-enable prefer-const */

-
  let hideTimeline = $state(true);
  const status = initialStatus;
  let tab: "patch" | "revisions" | "timeline" = $state(
    revisions.length > 1 ? "revisions" : "patch",
  );
+
  let patchView: "activity" | "changes" = $state("activity");
  let selectedRevision: Revision = $state(revisions.slice(-1)[0]);

+
  let lastPatchId = $state(patch.id);
  $effect(() => {
-
    // eslint-disable-next-line @typescript-eslint/no-unused-expressions
-
    patch.id;
-

-
    tab = revisions.length > 1 ? "revisions" : "patch";
-
    selectedRevision = revisions.slice(-1)[0];
+
    if (patch.id !== lastPatchId) {
+
      lastPatchId = patch.id;
+
      tab = revisions.length > 1 ? "revisions" : "patch";
+
      selectedRevision = revisions.slice(-1)[0];
+
      patchView = "activity";
+
    }
  });

  async function saveState(newState: Patch["state"]) {
@@ -174,6 +177,13 @@
      value => value.author.did === didFromPublicKey(config.publicKey),
    ),
  );
+
  const ownDraftReview = $derived(
+
    reviewsOfSelectedRevision.find(
+
      (value): value is DraftReview =>
+
        value.author.did === didFromPublicKey(config.publicKey) &&
+
        "draft" in value,
+
    ),
+
  );
</script>

<style>
@@ -380,21 +390,40 @@
              patchId={patch.id}
              {loadPatch}
              revision={selectedRevision}
-
              {config} />
+
              {config}
+
              view="description" />

-
            <div class="global-flex" style:margin-top="1.5rem">
+
            <div class="tabs">
              <Button
-
                variant="naked"
-
                onclick={() => (hideTimeline = !hideTimeline)}>
-
                <Icon name={hideTimeline ? "chevron-right" : "chevron-down"} />
+
                variant={patchView === "activity" ? "ghost" : "naked"}
+
                active={patchView === "activity"}
+
                onclick={() => (patchView = "activity")}>
+
                <Icon name="activity" />
+
                Activity
+
              </Button>
+
              <Button
+
                variant={patchView === "changes" ? "ghost" : "naked"}
+
                active={patchView === "changes"}
+
                onclick={() => (patchView = "changes")}>
+
                <Icon name="diff" />
+
                Changes
              </Button>
-
              <div class="txt-body-m-regular global-flex">Timeline</div>
-
            </div>
-
            <div
-
              style:display={hideTimeline ? "none" : "revert"}
-
              style:margin-top="1rem">
-
              <PatchTimeline {activity} patchId={patch.id} />
            </div>
+

+
            <RevisionComponent
+
              rid={repo.rid}
+
              repoDelegates={repo.delegates}
+
              patchId={patch.id}
+
              {loadPatch}
+
              revision={selectedRevision}
+
              {config}
+
              view={patchView} />
+

+
            {#if patchView === "activity"}
+
              <div style:margin-top="1.5rem">
+
                <PatchTimeline {activity} patchId={patch.id} />
+
              </div>
+
            {/if}
          </div>

          <div class="sidebar">
@@ -421,6 +450,19 @@
          </div>
        </div>
      </ScrollArea>
+

+
      {#if ownDraftReview}
+
        <DraftReviewBar
+
          draftReview={ownDraftReview}
+
          onChange={loadPatch}
+
          onPublish={async () => {
+
            await loadPatch();
+
          }}
+
          onCancel={() => {
+
            draftReviewStorage.delete(ownDraftReview.id);
+
            void loadPatch();
+
          }} />
+
      {/if}
    </div>
  {/if}
</Layout>