mirror of
https://github.com/alkimake/paperclip.git
synced 2026-06-16 19:00:38 +09:00
Extend read/dismissed functionality to all inbox item types
Approvals, failed runs, and join requests now have the same unread dot + archive X pattern as issues in the Mine tab: - Click the blue dot to mark as read, then X appears on hover - Desktop: animated dismiss with scale/slide transition - Mobile: swipe-to-archive via SwipeToArchive wrapper - Dismissed items are filtered out of Mine tab - Badge count excludes dismissed approvals and join requests - localStorage-backed read/dismiss state for non-issue items Co-Authored-By: Paperclip <noreply@paperclip.ing>
This commit is contained in:
parent
49c7fb7fbd
commit
2c406d3b8c
3 changed files with 327 additions and 40 deletions
|
|
@ -10,6 +10,7 @@ export const RECENT_ISSUES_LIMIT = 100;
|
|||
export const FAILED_RUN_STATUSES = new Set(["failed", "timed_out"]);
|
||||
export const ACTIONABLE_APPROVAL_STATUSES = new Set(["pending", "revision_requested"]);
|
||||
export const DISMISSED_KEY = "paperclip:inbox:dismissed";
|
||||
export const READ_ITEMS_KEY = "paperclip:inbox:read-items";
|
||||
export const INBOX_LAST_TAB_KEY = "paperclip:inbox:last-tab";
|
||||
export type InboxTab = "mine" | "recent" | "unread" | "all";
|
||||
export type InboxApprovalFilter = "all" | "actionable" | "resolved";
|
||||
|
|
@ -61,6 +62,23 @@ export function saveDismissedInboxItems(ids: Set<string>) {
|
|||
}
|
||||
}
|
||||
|
||||
export function loadReadInboxItems(): Set<string> {
|
||||
try {
|
||||
const raw = localStorage.getItem(READ_ITEMS_KEY);
|
||||
return raw ? new Set(JSON.parse(raw)) : new Set();
|
||||
} catch {
|
||||
return new Set();
|
||||
}
|
||||
}
|
||||
|
||||
export function saveReadInboxItems(ids: Set<string>) {
|
||||
try {
|
||||
localStorage.setItem(READ_ITEMS_KEY, JSON.stringify([...ids]));
|
||||
} catch {
|
||||
// Ignore localStorage failures.
|
||||
}
|
||||
}
|
||||
|
||||
export function loadLastInboxTab(): InboxTab {
|
||||
try {
|
||||
const raw = localStorage.getItem(INBOX_LAST_TAB_KEY);
|
||||
|
|
@ -237,12 +255,17 @@ export function computeInboxBadgeData({
|
|||
mineIssues: Issue[];
|
||||
dismissed: Set<string>;
|
||||
}): InboxBadgeData {
|
||||
const actionableApprovals = approvals.filter((approval) =>
|
||||
ACTIONABLE_APPROVAL_STATUSES.has(approval.status),
|
||||
const actionableApprovals = approvals.filter(
|
||||
(approval) =>
|
||||
ACTIONABLE_APPROVAL_STATUSES.has(approval.status) &&
|
||||
!dismissed.has(`approval:${approval.id}`),
|
||||
).length;
|
||||
const failedRuns = getLatestFailedRunsByAgent(heartbeatRuns).filter(
|
||||
(run) => !dismissed.has(`run:${run.id}`),
|
||||
).length;
|
||||
const visibleJoinRequests = joinRequests.filter(
|
||||
(jr) => !dismissed.has(`join:${jr.id}`),
|
||||
).length;
|
||||
const visibleMineIssues = mineIssues.length;
|
||||
const agentErrorCount = dashboard?.agents.error ?? 0;
|
||||
const monthBudgetCents = dashboard?.costs.monthBudgetCents ?? 0;
|
||||
|
|
@ -258,10 +281,10 @@ export function computeInboxBadgeData({
|
|||
const alerts = Number(showAggregateAgentError) + Number(showBudgetAlert);
|
||||
|
||||
return {
|
||||
inbox: actionableApprovals + joinRequests.length + failedRuns + visibleMineIssues + alerts,
|
||||
inbox: actionableApprovals + visibleJoinRequests + failedRuns + visibleMineIssues + alerts,
|
||||
approvals: actionableApprovals,
|
||||
failedRuns,
|
||||
joinRequests: joinRequests.length,
|
||||
joinRequests: visibleJoinRequests,
|
||||
mineIssues: visibleMineIssues,
|
||||
alerts,
|
||||
};
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue