diff --git a/src/components/Icon.svelte b/src/components/Icon.svelte
index 9c25b75..b2213e8 100644
--- a/src/components/Icon.svelte
+++ b/src/components/Icon.svelte
@@ -8,14 +8,17 @@
styleDisplay?: string;
styleVerticalAlign?: string;
name:
- | "attachment"
| "arrow-left"
| "arrow-right"
+ | "arrow-right-hollow"
+ | "attachment"
| "checkmark"
| "chevron-down"
| "chevron-right"
| "collapse-panel"
| "comment"
+ | "comment-checkmark"
+ | "comment-cross"
| "copy"
| "cross"
| "dashboard"
@@ -28,8 +31,10 @@
| "home"
| "inbox"
| "issue"
+ | "label"
| "lock"
| "markdown"
+ | "merge"
| "moon"
| "more-vertical"
| "none"
@@ -45,6 +50,7 @@
| "seedling-filled"
| "settings"
| "sun"
+ | "user"
| "warning";
}
@@ -115,6 +121,24 @@
+ {:else if name === "arrow-right-hollow"}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
{:else if name === "attachment"}
@@ -188,6 +212,72 @@
+ {:else if name === "comment-checkmark"}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {:else if name === "comment-cross"}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
{:else if name === "copy"}
@@ -387,6 +477,36 @@
+ {:else if name === "label"}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
{:else if name === "lock"}
@@ -415,6 +535,16 @@
+ {:else if name === "merge"}
+
+
+
{:else if name === "moon"}
@@ -751,6 +881,27 @@
+ {:else if name === "user"}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
{:else if name === "warning"}
diff --git a/src/components/PatchTimeline.svelte b/src/components/PatchTimeline.svelte
new file mode 100644
index 0000000..28d6c69
--- /dev/null
+++ b/src/components/PatchTimeline.svelte
@@ -0,0 +1,302 @@
+
+
+
+
+
+ {#each timeline as op}
+ {#if op.type === "revision"}
+ {#if op.id === patchId}
+
+
+
+
+
+
+
opened patch
+
+ {formatTimestamp(op.timestamp)}
+
+
+
+ {:else}
+
+
+
+
+
+
+
created a new revision
+
+ {formatTimestamp(op.timestamp)}
+
+
+
+ {/if}
+ {:else if op.type === "lifecycle"}
+
+
+
+
+
+
+ {#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}
+
+ {formatTimestamp(op.timestamp)}
+
+
+
+ {:else if op.type === "label" && 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 label{changed.added.length > 1 ? "s" : ""}
+ {#each changed.added as label}
+
{label}
+ {/each}
+ {/if}
+ {#if changed.removed.length}
+ removed label{changed.removed.length > 1 ? "s" : ""}
+ {#each changed.removed as label}
+
{label}
+ {/each}
+ {/if}
+
+ {formatTimestamp(op.timestamp)}
+
+
+
+ {/if}
+ {:else if op.type === "assign" && op.previous && op.previous.type === op.type}
+ {@const changed = itemDiff(op.previous?.assignees ?? [], op.assignees)}
+ {#if changed.added.length || changed.removed.length}
+
+
+
+
+
+
+ {#if changed.added.length}
+ assigned
+ {#each changed.added as assignee}
+ {#await invoke
( "alias", { nid: publicKeyFromDid(assignee) }, ) then alias}
+
+ {/await}
+ {/each}
+ {/if}
+ {#if changed.removed.length}
+ unassigned
+ {#each changed.removed as assignee}
+ {#await invoke( "alias", { nid: publicKeyFromDid(assignee) }, ) then alias}
+
+ {/await}
+ {/each}
+ {/if}
+
+ {formatTimestamp(op.timestamp)}
+
+
+
+ {/if}
+ {:else if op.type === "merge"}
+
+
+
+
+
+
+
+ merged patch at revision
+
+
+ {formatTimestamp(op.timestamp)}
+
+
+
+ {:else if op.type === "edit"}
+ {#if op.previous && op.previous.type === op.type}
+
+
+
+
+
+
+ changed title
+
{op.previous.title}
+ -> {op.title}
+
+ {formatTimestamp(op.timestamp)}
+
+
+
+ {/if}
+ {:else if op.type === "review"}
+
+ {#if op.verdict === "accept"}
+
+
+
+
+
+ accepted revision
+
+ {formatTimestamp(op.timestamp)}
+
+
+ {:else}
+
+
+
+
+
+ rejected revision
+
+ {formatTimestamp(op.timestamp)}
+
+
+ {/if}
+
+ {:else if op.type === "review.comment"}
+
+
+
+
+
+
+ {op.reply_to ? "replied to a comment" : "commented"} on review
+
+ {formatTimestamp(op.timestamp)}
+
+
+
+ {:else if op.type === "revision.comment"}
+
+
+
+
+
+
+ {op.replyTo ? "replied to a comment" : "commented"} on revision
+
+ {formatTimestamp(op.timestamp)}
+
+
+
+ {/if}
+ {/each}
+
diff --git a/src/components/PatchTimelineLifecycleAction.svelte b/src/components/PatchTimelineLifecycleAction.svelte
deleted file mode 100644
index dde07a8..0000000
--- a/src/components/PatchTimelineLifecycleAction.svelte
+++ /dev/null
@@ -1,28 +0,0 @@
-
-
-
-
-
-
- changed status to
-
- {formatTimestamp(op.timestamp)}
-
-
-
diff --git a/src/views/repo/Patch.svelte b/src/views/repo/Patch.svelte
index d931b66..5045fd5 100644
--- a/src/views/repo/Patch.svelte
+++ b/src/views/repo/Patch.svelte
@@ -1,10 +1,10 @@