Radish alpha
r
Radicle desktop app
Radicle
Git (anonymous pull)
Log in to clone via SSH
Truncate activity items and dim timestamps
Brandon Oxendine committed 1 month ago
commit 6f9eb0b8dfa727ef08d52246fe8b37f6929413e0
parent 6375f05d7f658530a6d952f50468e7f68656124d
4 files changed +177 -122
modified src/components/IssueActivityItem.svelte
@@ -40,16 +40,28 @@
    display: flex;
    align-items: flex-start;
    gap: 0.5rem;
-
    word-break: break-word;
+
    min-width: 0;
  }
  .wrapper {
    display: flex;
    flex-wrap: wrap;
    gap: 0.25rem;
+
    min-width: 0;
+
    flex: 1 1 0;
  }
  .icon {
    padding-top: 3px;
  }
+
  .summary-line {
+
    flex: 1 1 0;
+
    min-width: 0;
+
    white-space: nowrap;
+
    overflow: hidden;
+
    text-overflow: ellipsis;
+
  }
+
  .timestamp {
+
    color: var(--color-text-quaternary);
+
  }
</style>

{#if op.type === "lifecycle"}
@@ -63,12 +75,14 @@
    </div>
    <div class="wrapper">
      <NodeId {...authorForNodeId(op.author)} />
-
      {#if op.state.status === "closed"}
-
        closed issue as {op.state.reason}
-
      {:else if op.state.status === "open"}
-
        reopened issue
-
      {/if}
-
      <div title={absoluteTimestamp(op.timestamp)}>
+
      <div class="summary-line">
+
        {#if op.state.status === "closed"}
+
          closed issue as {op.state.reason}
+
        {:else if op.state.status === "open"}
+
          reopened issue
+
        {/if}
+
      </div>
+
      <div class="timestamp" title={absoluteTimestamp(op.timestamp)}>
        {formatTimestamp(op.timestamp)}
      </div>
    </div>
@@ -80,29 +94,31 @@
    </div>
    <div class="wrapper">
      <NodeId {...authorForNodeId(op.author)} />
-
      {#if op.previous && op.previous.type === op.type}
-
        {@const changed = itemDiff(op.previous?.labels ?? [], op.labels)}
-
        {#if changed.added.length || changed.removed.length}
-
          {#if changed.added.length}
-
            added {pluralize("label", changed.removed.length)}
-
            {#each changed.added as label}
-
              <b>{label}</b>
-
            {/each}
-
          {/if}
-
          {#if changed.removed.length}
-
            removed {pluralize("label", changed.removed.length)}
-
            {#each changed.removed as label}
-
              <b>{label}</b>
-
            {/each}
+
      <div class="summary-line">
+
        {#if op.previous && op.previous.type === op.type}
+
          {@const changed = itemDiff(op.previous?.labels ?? [], op.labels)}
+
          {#if changed.added.length || changed.removed.length}
+
            {#if changed.added.length}
+
              added {pluralize("label", changed.removed.length)}
+
              {#each changed.added as label}
+
                <b>{label}</b>
+
              {/each}
+
            {/if}
+
            {#if changed.removed.length}
+
              removed {pluralize("label", changed.removed.length)}
+
              {#each changed.removed as label}
+
                <b>{label}</b>
+
              {/each}
+
            {/if}
          {/if}
+
        {:else}
+
          added {pluralize("label", op.labels.length)}
+
          {#each op.labels as label}
+
            <b>{label}</b>
+
          {/each}
        {/if}
-
      {:else}
-
        added {pluralize("label", op.labels.length)}
-
        {#each op.labels as label}
-
          <b>{label}</b>
-
        {/each}
-
      {/if}
-
      <div title={absoluteTimestamp(op.timestamp)}>
+
      </div>
+
      <div class="timestamp" title={absoluteTimestamp(op.timestamp)}>
        {formatTimestamp(op.timestamp)}
      </div>
    </div>
@@ -114,32 +130,34 @@
    </div>
    <div class="wrapper">
      <NodeId {...authorForNodeId(op.author)} />
-
      {#if op.previous && op.previous.type === op.type}
-
        {@const changed = itemDiff<Author>(
-
          op.previous?.assignees ?? [],
-
          op.assignees,
-
        )}
-
        {#if changed.added.length || changed.removed.length}
-
          {#if changed.added.length}
-
            assigned
-
            {#each changed.added as assignee}
-
              <NodeId {...authorForNodeId(assignee)} />
-
            {/each}
-
          {/if}
-
          {#if changed.removed.length}
-
            unassigned
-
            {#each changed.removed as assignee}
-
              <NodeId {...authorForNodeId(assignee)} />
-
            {/each}
+
      <div class="summary-line">
+
        {#if op.previous && op.previous.type === op.type}
+
          {@const changed = itemDiff<Author>(
+
            op.previous?.assignees ?? [],
+
            op.assignees,
+
          )}
+
          {#if changed.added.length || changed.removed.length}
+
            {#if changed.added.length}
+
              assigned
+
              {#each changed.added as assignee}
+
                <NodeId {...authorForNodeId(assignee)} />
+
              {/each}
+
            {/if}
+
            {#if changed.removed.length}
+
              unassigned
+
              {#each changed.removed as assignee}
+
                <NodeId {...authorForNodeId(assignee)} />
+
              {/each}
+
            {/if}
          {/if}
+
        {:else}
+
          assigned
+
          {#each op.assignees as assignee}
+
            <NodeId {...authorForNodeId(assignee)} />
+
          {/each}
        {/if}
-
      {:else}
-
        assigned
-
        {#each op.assignees as assignee}
-
          <NodeId {...authorForNodeId(assignee)} />
-
        {/each}
-
      {/if}
-
      <div title={absoluteTimestamp(op.timestamp)}>
+
      </div>
+
      <div class="timestamp" title={absoluteTimestamp(op.timestamp)}>
        {formatTimestamp(op.timestamp)}
      </div>
    </div>
@@ -152,10 +170,11 @@
      </div>
      <div class="wrapper">
        <NodeId {...authorForNodeId(op.author)} />
-
        changed title
-
        <s>{op.previous.title}</s>
-
        -> {op.title}
-
        <div title={absoluteTimestamp(op.timestamp)}>
+
        <div class="summary-line">
+
          changed title <s>{op.previous.title}</s>
+
          → {op.title}
+
        </div>
+
        <div class="timestamp" title={absoluteTimestamp(op.timestamp)}>
          {formatTimestamp(op.timestamp)}
        </div>
      </div>
modified src/components/PatchActivityItem.svelte
@@ -42,16 +42,28 @@
    display: flex;
    align-items: flex-start;
    gap: 0.5rem;
-
    word-break: break-word;
+
    min-width: 0;
  }
  .wrapper {
    display: flex;
    flex-wrap: wrap;
    gap: 0.25rem;
+
    min-width: 0;
+
    flex: 1 1 0;
  }
  .icon {
    padding-top: 0.1875rem;
  }
+
  .summary-line {
+
    flex: 1 1 0;
+
    min-width: 0;
+
    white-space: nowrap;
+
    overflow: hidden;
+
    text-overflow: ellipsis;
+
  }
+
  .timestamp {
+
    color: var(--color-text-quaternary);
+
  }
</style>

{#if op.type === "revision"}
@@ -62,10 +74,10 @@
      </div>
      <div class="wrapper">
        <NodeId {...authorForNodeId(op.author)} />
-
        <div>
+
        <div class="summary-line">
          opened patch <Id id={op.id} clipboard={op.id} />
        </div>
-
        <div title={absoluteTimestamp(op.timestamp)}>
+
        <div class="timestamp" title={absoluteTimestamp(op.timestamp)}>
          {formatTimestamp(op.timestamp)}
        </div>
      </div>
@@ -77,10 +89,10 @@
      </div>
      <div class="wrapper">
        <NodeId {...authorForNodeId(op.author)} />
-
        <div>
+
        <div class="summary-line">
          created revision <Id id={op.id} clipboard={op.id} />
        </div>
-
        <div title={absoluteTimestamp(op.timestamp)}>
+
        <div class="timestamp" title={absoluteTimestamp(op.timestamp)}>
          {formatTimestamp(op.timestamp)}
        </div>
      </div>
@@ -96,14 +108,16 @@
    </div>
    <div class="wrapper">
      <NodeId {...authorForNodeId(op.author)} />
-
      {#if op.state.status === "draft"}
-
        converted patch to draft
-
      {:else if op.state.status === "archived"}
-
        archived patch
-
      {:else if op.state.status === "open"}
-
        reopened patch
-
      {/if}
-
      <div title={absoluteTimestamp(op.timestamp)}>
+
      <div class="summary-line">
+
        {#if op.state.status === "draft"}
+
          converted patch to draft
+
        {:else if op.state.status === "archived"}
+
          archived patch
+
        {:else if op.state.status === "open"}
+
          reopened patch
+
        {/if}
+
      </div>
+
      <div class="timestamp" title={absoluteTimestamp(op.timestamp)}>
        {formatTimestamp(op.timestamp)}
      </div>
    </div>
@@ -115,29 +129,31 @@
    </div>
    <div class="wrapper">
      <NodeId {...authorForNodeId(op.author)} />
-
      {#if op.previous && op.previous.type === op.type}
-
        {@const changed = itemDiff(op.previous?.labels ?? [], op.labels)}
-
        {#if changed.added.length || changed.removed.length}
-
          {#if changed.added.length}
-
            added {pluralize("label", changed.added.length)}
-
            {#each changed.added as label}
-
              <b>{label}</b>
-
            {/each}
-
          {/if}
-
          {#if changed.removed.length}
-
            removed {pluralize("label", changed.removed.length)}
-
            {#each changed.removed as label}
-
              <b>{label}</b>
-
            {/each}
+
      <div class="summary-line">
+
        {#if op.previous && op.previous.type === op.type}
+
          {@const changed = itemDiff(op.previous?.labels ?? [], op.labels)}
+
          {#if changed.added.length || changed.removed.length}
+
            {#if changed.added.length}
+
              added {pluralize("label", changed.added.length)}
+
              {#each changed.added as label}
+
                <b>{label}</b>
+
              {/each}
+
            {/if}
+
            {#if changed.removed.length}
+
              removed {pluralize("label", changed.removed.length)}
+
              {#each changed.removed as label}
+
                <b>{label}</b>
+
              {/each}
+
            {/if}
          {/if}
+
        {:else}
+
          added {pluralize("label", op.labels.length)}
+
          {#each op.labels as label}
+
            <b>{label}</b>
+
          {/each}
        {/if}
-
      {:else}
-
        added {pluralize("label", op.labels.length)}
-
        {#each op.labels as label}
-
          <b>{label}</b>
-
        {/each}
-
      {/if}
-
      <div title={absoluteTimestamp(op.timestamp)}>
+
      </div>
+
      <div class="timestamp" title={absoluteTimestamp(op.timestamp)}>
        {formatTimestamp(op.timestamp)}
      </div>
    </div>
@@ -149,30 +165,32 @@
    </div>
    <div class="wrapper">
      <NodeId {...authorForNodeId(op.author)} />
-
      {#if op.previous && op.previous.type === op.type}
-
        {@const changed = itemDiff<Author>(
-
          op.previous?.assignees ?? [],
-
          op.assignees,
-
        )}
-
        {#if changed.added.length}
+
      <div class="summary-line">
+
        {#if op.previous && op.previous.type === op.type}
+
          {@const changed = itemDiff<Author>(
+
            op.previous?.assignees ?? [],
+
            op.assignees,
+
          )}
+
          {#if changed.added.length}
+
            assigned
+
            {#each changed.added as assignee}
+
              <NodeId {...authorForNodeId(assignee)} />
+
            {/each}
+
          {/if}
+
          {#if changed.removed.length}
+
            unassigned
+
            {#each changed.removed as assignee}
+
              <NodeId {...authorForNodeId(assignee)} />
+
            {/each}
+
          {/if}
+
        {:else}
          assigned
-
          {#each changed.added as assignee}
-
            <NodeId {...authorForNodeId(assignee)} />
-
          {/each}
-
        {/if}
-
        {#if changed.removed.length}
-
          unassigned
-
          {#each changed.removed as assignee}
+
          {#each op.assignees as assignee}
            <NodeId {...authorForNodeId(assignee)} />
          {/each}
        {/if}
-
      {:else}
-
        assigned
-
        {#each op.assignees as assignee}
-
          <NodeId {...authorForNodeId(assignee)} />
-
        {/each}
-
      {/if}
-
      <div title={absoluteTimestamp(op.timestamp)}>
+
      </div>
+
      <div class="timestamp" title={absoluteTimestamp(op.timestamp)}>
        {formatTimestamp(op.timestamp)}
      </div>
    </div>
@@ -184,10 +202,10 @@
    </div>
    <div class="wrapper">
      <NodeId {...authorForNodeId(op.author)} />
-
      <div>
+
      <div class="summary-line">
        merged patch at revision <Id id={op.revision} clipboard={op.revision} />
      </div>
-
      <div title={absoluteTimestamp(op.timestamp)}>
+
      <div class="timestamp" title={absoluteTimestamp(op.timestamp)}>
        {formatTimestamp(op.timestamp)}
      </div>
    </div>
@@ -200,10 +218,10 @@
      </div>
      <div class="wrapper">
        <NodeId {...authorForNodeId(op.author)} />
-
        changed title
-
        <s>{op.previous.title}</s>
-
        -> {op.title}
-
        <div title={absoluteTimestamp(op.timestamp)}>
+
        <div class="summary-line">
+
          changed title <s>{op.previous.title}</s> → {op.title}
+
        </div>
+
        <div class="timestamp" title={absoluteTimestamp(op.timestamp)}>
          {formatTimestamp(op.timestamp)}
        </div>
      </div>
@@ -217,8 +235,10 @@
      </div>
      <div class="wrapper">
        <NodeId {...authorForNodeId(op.author)} />
-
        accepted revision <Id id={op.revision} clipboard={op.revision} />
-
        <div title={absoluteTimestamp(op.timestamp)}>
+
        <div class="summary-line">
+
          accepted revision <Id id={op.revision} clipboard={op.revision} />
+
        </div>
+
        <div class="timestamp" title={absoluteTimestamp(op.timestamp)}>
          {formatTimestamp(op.timestamp)}
        </div>
      </div>
@@ -228,8 +248,10 @@
      </div>
      <div class="wrapper">
        <NodeId {...authorForNodeId(op.author)} />
-
        rejected revision <Id id={op.revision} clipboard={op.revision} />
-
        <div title={absoluteTimestamp(op.timestamp)}>
+
        <div class="summary-line">
+
          rejected revision <Id id={op.revision} clipboard={op.revision} />
+
        </div>
+
        <div class="timestamp" title={absoluteTimestamp(op.timestamp)}>
          {formatTimestamp(op.timestamp)}
        </div>
      </div>
@@ -239,8 +261,10 @@
      </div>
      <div class="wrapper">
        <NodeId {...authorForNodeId(op.author)} />
-
        reviewed revision <Id id={op.revision} clipboard={op.revision} />
-
        <div title={absoluteTimestamp(op.timestamp)}>
+
        <div class="summary-line">
+
          reviewed revision <Id id={op.revision} clipboard={op.revision} />
+
        </div>
+
        <div class="timestamp" title={absoluteTimestamp(op.timestamp)}>
          {formatTimestamp(op.timestamp)}
        </div>
      </div>
modified src/components/Revision.svelte
@@ -74,6 +74,12 @@
            return;
          }
          const previous = tracker[action.type];
+
          // The first `edit` action has nothing to diff against, so the
+
          // renderer skips it. Skip it here too so we don't leave a gap.
+
          if (action.type === "edit" && !previous) {
+
            tracker[action.type] = action;
+
            return;
+
          }
          const op: FlattenedPatchOperation = {
            ...action,
            id: operation.id,
modified src/views/repo/Issue.svelte
@@ -82,6 +82,12 @@
            return;
          }
          const previous = tracker[action.type];
+
          // The first `edit` action has nothing to diff against, so the
+
          // renderer skips it. Skip it here too so we don't leave a gap.
+
          if (action.type === "edit" && !previous) {
+
            tracker[action.type] = action;
+
            return;
+
          }
          const op: FlattenedIssueOperation = {
            ...action,
            id: operation.id,