mirror of
https://seed.radicle.dev/rad:z4D5UCArafTzTQpDZNQRuqswh3ury.git
synced 2026-10-18 19:10:45 +08:00
Keep every review comment in inbox summaries
Notification actions were deduplicated by operation and type, so the several code comments of one published review collapsed into one.
This commit is contained in:
@@ -1,14 +1,9 @@
|
||||
<script lang="ts">
|
||||
import type { RepoRoute } from "@app/views/repo/router";
|
||||
import type { ActionWithAuthor } from "@bindings/cob/inbox/ActionWithAuthor";
|
||||
import type { NotificationItem } from "@bindings/cob/inbox/NotificationItem";
|
||||
import type { Action as IssueAction } from "@bindings/cob/issue/Action";
|
||||
import type { Action as PatchAction } from "@bindings/cob/patch/Action";
|
||||
import type { ComponentProps } from "svelte";
|
||||
|
||||
import uniqWith from "lodash/uniqWith";
|
||||
|
||||
import { compressActions } from "@app/lib/notification";
|
||||
import { compressActions, notificationActions } from "@app/lib/notification";
|
||||
import { push } from "@app/lib/router";
|
||||
import {
|
||||
absoluteTimestamp,
|
||||
@@ -47,24 +42,9 @@
|
||||
selected = false,
|
||||
}: Props = $props();
|
||||
|
||||
type Action = ActionWithAuthor<IssueAction> | ActionWithAuthor<PatchAction>;
|
||||
|
||||
const uniqueActions = $derived.by(() => {
|
||||
return compressActions(
|
||||
uniqWith(
|
||||
notificationItems.flatMap<Action>(n => n.actions),
|
||||
(a, b) =>
|
||||
Boolean(
|
||||
a.oid === b.oid &&
|
||||
a.type === b.type &&
|
||||
a.author.did &&
|
||||
b.author.did,
|
||||
),
|
||||
).sort((a, b) => b.timestamp - a.timestamp),
|
||||
kind,
|
||||
oid,
|
||||
);
|
||||
});
|
||||
const uniqueActions = $derived(
|
||||
compressActions(notificationActions(notificationItems), kind, oid),
|
||||
);
|
||||
|
||||
const title = $derived.by(() => {
|
||||
const lastDetail = notificationItems.at(-1);
|
||||
|
||||
@@ -2,6 +2,9 @@ import type { ActionWithAuthor } from "@bindings/cob/inbox/ActionWithAuthor";
|
||||
import type { Action as IssueAction } from "@bindings/cob/issue/Action";
|
||||
import type { Action as PatchAction } from "@bindings/cob/patch/Action";
|
||||
|
||||
import isEqual from "lodash/isEqual";
|
||||
import uniqWith from "lodash/uniqWith";
|
||||
|
||||
import { emojiToTwemoji, formatOid, pluralize } from "@app/lib/utils";
|
||||
|
||||
export type Action =
|
||||
@@ -182,3 +185,14 @@ export function compressActions(
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// Actions of a notified COB, newest first. Notifications for the same COB can
|
||||
// cover overlapping ranges, so an action may appear in several of them. Only
|
||||
// identical actions are duplicates: one operation can carry several actions of
|
||||
// the same type, such as the code comments of a published review.
|
||||
export function notificationActions(items: { actions: Action[] }[]): Action[] {
|
||||
return uniqWith(
|
||||
items.flatMap(item => item.actions),
|
||||
isEqual,
|
||||
).sort((a, b) => b.timestamp - a.timestamp);
|
||||
}
|
||||
|
||||
@@ -4,7 +4,11 @@ import type { Action as PatchAction } from "@bindings/cob/patch/Action";
|
||||
import { describe, expect, test } from "vitest";
|
||||
|
||||
import type { Action as NotificationAction } from "@app/lib/notification";
|
||||
import { compressActions, createSummary } from "@app/lib/notification";
|
||||
import {
|
||||
compressActions,
|
||||
createSummary,
|
||||
notificationActions,
|
||||
} from "@app/lib/notification";
|
||||
import { formatOid } from "@app/lib/utils";
|
||||
|
||||
const oid = "e8f95f5082a8e99c290ab3908a926e1de5c97d6c";
|
||||
@@ -204,3 +208,41 @@ describe("Action summaries", () => {
|
||||
},
|
||||
);
|
||||
});
|
||||
|
||||
describe("notificationActions", () => {
|
||||
const comment = (body: string, at = timestamp) => ({
|
||||
...createAction({ type: "review.comment", body, review: oid }),
|
||||
timestamp: at,
|
||||
});
|
||||
|
||||
test("keeps an action once when two notifications include it", () => {
|
||||
const shared = comment("A review comment");
|
||||
|
||||
expect(
|
||||
notificationActions([
|
||||
{ actions: [shared] },
|
||||
{ actions: [{ ...shared }] },
|
||||
]),
|
||||
).toEqual([shared]);
|
||||
});
|
||||
|
||||
test("keeps same-type actions from one operation", () => {
|
||||
const actions = notificationActions([
|
||||
{ actions: [comment("First"), comment("Second"), comment("Third")] },
|
||||
]);
|
||||
|
||||
expect(actions).toHaveLength(3);
|
||||
expect(compressActions(actions, "patch", oid)[0].summary).toBe(
|
||||
"left 3 review comments",
|
||||
);
|
||||
});
|
||||
|
||||
test("orders actions newest first", () => {
|
||||
expect(
|
||||
notificationActions([
|
||||
{ actions: [comment("old", 1)] },
|
||||
{ actions: [comment("new", 3), comment("middle", 2)] },
|
||||
]).map(a => a.timestamp),
|
||||
).toEqual([3, 2, 1]);
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user