Files
fusion/plugins/fusion-plugin-even-realities-glasses/src/notifications/diff.ts
Fusion 089c139bad feat(FN-3743): add polling task notifications for even realities plugin
Commits merged:
- feat(FN-3743): add polling task notifications for even realities plugin

Files changed:
.../fusion-plugin-even-realities-glasses/README.md |  27 +++
 .../package.json                                   |   2 +
 .../src/__tests__/cards.test.ts                    |  82 +++------
 .../src/__tests__/diff.test.ts                     |  76 ++++++++
 .../src/__tests__/notification-card.test.ts        |  40 +++++
 .../src/__tests__/notification-routes.test.ts      |  78 ++++++++
 .../src/__tests__/notification-store.test.ts       |  71 ++++++++
 .../src/__tests__/notifier.test.ts                 | 138 +++++++++-----
 .../src/__tests__/transport.test.ts                |   4 +-
 .../src/agent-actions.ts                           |   4 +-
 .../src/cards.ts                                   | 127 ++++++++++---
 .../src/index.ts                                   |  22 ++-
 .../src/notifications/diff.ts                      |  77 ++++++++
 .../src/notifications/store.ts                     |  46 +++++
 .../src/notifications/types.ts                     |  19 ++
 .../src/notifier.ts                                | 199 +++++++++++++--------
 .../src/routes/notification-routes.ts              | 103 +++++++++++
 pnpm-lock.yaml                                     |  31 +++-
 18 files changed, 929 insertions(+), 217 deletions(-)

Fusion-Task-Id: FN-3743
2026-05-08 16:35:22 -07:00

78 lines
2.0 KiB
TypeScript

import type { Task, Column } from "@fusion/core";
import type { NotificationEvent, Snapshot } from "./types.js";
export function diffSnapshots(
prev: Snapshot,
next: ReadonlyArray<Task>,
opts: { notifyOnColumns: ReadonlySet<Column>; alsoNotifyOnDone?: boolean },
): NotificationEvent[] {
const events: NotificationEvent[] = [];
for (const task of next) {
const previous = prev.get(task.id);
if (!previous) {
if (opts.notifyOnColumns.has(task.column)) {
events.push({
taskId: task.id,
reason: "new-task",
column: task.column,
previousColumn: null,
updatedAt: task.updatedAt,
});
}
continue;
}
if (previous.lastColumn === task.column) continue;
if (opts.notifyOnColumns.has(task.column)) {
events.push({
taskId: task.id,
reason: "entered-column",
column: task.column,
previousColumn: previous.lastColumn,
updatedAt: task.updatedAt,
});
} else if (opts.notifyOnColumns.has(previous.lastColumn)) {
events.push({
taskId: task.id,
reason: "left-column",
column: task.column,
previousColumn: previous.lastColumn,
updatedAt: task.updatedAt,
});
}
if (task.column === "done" && opts.alsoNotifyOnDone) {
events.push({
taskId: task.id,
reason: "completed",
column: task.column,
previousColumn: previous.lastColumn,
updatedAt: task.updatedAt,
});
}
}
return events.sort((a, b) => {
if (a.updatedAt !== b.updatedAt) return a.updatedAt.localeCompare(b.updatedAt);
if (a.taskId !== b.taskId) return a.taskId.localeCompare(b.taskId);
return reasonOrder(a.reason) - reasonOrder(b.reason);
});
}
function reasonOrder(reason: NotificationEvent["reason"]): number {
switch (reason) {
case "entered-column":
return 0;
case "new-task":
return 1;
case "left-column":
return 2;
case "completed":
return 3;
default:
return 9;
}
}