Something went wrong. Try again.
Monorepo for Tangled tangled.org
Something went wrong. Try again.
5.6 kB · 153 lines
TypeScript
at icy/tmrrpn
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154import type { Component } from "svelte";import type { SvelteHTMLElements } from "svelte/elements";import AtSign from "$icon/at-sign";import Ban from "$icon/ban";import CircleDot from "$icon/circle-dot";import GitMerge from "$icon/git-merge";import GitPullRequestClosed from "$icon/git-pull-request-closed";import GitPullRequestCreate from "$icon/git-pull-request-create";import MessageSquare from "$icon/message-square";import Star from "$icon/star";import UserPlus from "$icon/user-plus";import UserRoundMinus from "$icon/user-round-minus";import UserRoundArrowForward from "$lib/components/icons/UserRoundArrowForward.svelte";import type { NotificationCategory, NotificationGroups, NotificationSummary, NotificationType} from "./types";
type IconComponent = Component<SvelteHTMLElements["svg"]>;
export const SOCIAL_TYPES: NotificationType[] = ["repo_starred", "followed"];
const CATEGORIES: Record<NotificationType, NotificationCategory> = { repo_starred: "social", followed: "social", issue_created: "work", issue_commented: "work", issue_closed: "work", issue_reopen: "work", issue_assigned: "work", issue_unassigned: "work", pull_created: "work", pull_commented: "work", pull_merged: "work", pull_closed: "work", pull_reopen: "work", pull_assigned: "work", pull_unassigned: "work", user_mentioned: "work"};
const ICONS: Record<NotificationType, IconComponent> = { repo_starred: Star, followed: UserPlus, issue_created: CircleDot, issue_commented: MessageSquare, issue_closed: Ban, issue_reopen: CircleDot, issue_assigned: UserRoundArrowForward, issue_unassigned: UserRoundMinus, pull_created: GitPullRequestCreate, pull_commented: MessageSquare, pull_merged: GitMerge, pull_closed: GitPullRequestClosed, pull_reopen: GitPullRequestCreate, pull_assigned: UserRoundArrowForward, pull_unassigned: UserRoundMinus, user_mentioned: AtSign};
// the design system has no purple, and a merged pull already reads as info on// PullStatePill, so merges land on the same token here.const TONES: Record<NotificationType, string> = { repo_starred: "text-foreground-warning", followed: "text-foreground-muted", issue_created: "text-foreground-success", issue_commented: "text-foreground-muted", issue_closed: "text-foreground-muted", issue_reopen: "text-foreground-success", issue_assigned: "text-foreground-info", issue_unassigned: "text-foreground-muted", pull_created: "text-foreground-success", pull_commented: "text-foreground-muted", pull_merged: "text-foreground-info", pull_closed: "text-foreground-danger", pull_reopen: "text-foreground-success", pull_assigned: "text-foreground-info", pull_unassigned: "text-foreground-muted", user_mentioned: "text-foreground-info"};
const PHRASES: Record<NotificationType, string> = { repo_starred: "starred", followed: "followed you", issue_created: "opened an issue on", issue_commented: "commented on an issue on", issue_closed: "closed an issue on", issue_reopen: "reopened an issue on", issue_assigned: "assigned you to an issue on", issue_unassigned: "unassigned you from an issue on", pull_created: "created a PR on", pull_commented: "commented on a PR on", pull_merged: "merged a PR on", pull_closed: "closed a PR on", pull_reopen: "reopened a PR on", pull_assigned: "assigned you to a PR on", pull_unassigned: "unassigned you from a PR on", user_mentioned: "mentioned you in"};
export const notificationCategory = (type: NotificationType): NotificationCategory => CATEGORIES[type];
export const notificationIcon = (type: NotificationType): IconComponent => ICONS[type];
export const notificationTone = (type: NotificationType): string => TONES[type];
export const notificationPhrase = (notification: NotificationSummary): string => { if (notification.type === "user_mentioned" && notification.subject) { return notification.subject.kind === "issue" ? "mentioned you on an issue in" : "mentioned you on a pull request in"; } return PHRASES[notification.type];};
// the subject of the phrase, which the appview prints as owner/name after itexport const notificationTarget = (notification: NotificationSummary): string => notification.repo ? `${notification.repo.ownerHandle}/${notification.repo.name}` : "";
export const notificationHref = (notification: NotificationSummary): string => { if (notification.type === "followed") return `/${notification.actor.handle}`; const repo = notification.repo; if (!repo) return `/${notification.actor.handle}`; const base = `/${repo.ownerHandle}/${repo.name}`; const subject = notification.subject; if (!subject) return base; return `${base}/${subject.kind === "issue" ? "issues" : "pulls"}/${subject.uri}`;};
// today, the six days before it, then everything older, same buckets the go page// builds in GroupNotificationsByDateexport const groupNotificationsByDate = ( notifications: NotificationSummary[], now: Date = new Date()): NotificationGroups => { const todayStart = new Date(now.getFullYear(), now.getMonth(), now.getDate()).getTime(); const weekStart = todayStart - 6 * 24 * 60 * 60 * 1000;
const groups: NotificationGroups = { today: [], thisWeek: [], older: [] }; for (const notification of notifications) { const created = Date.parse(notification.createdAt); if (created >= todayStart) groups.today.push(notification); else if (created >= weekStart) groups.thisWeek.push(notification); else groups.older.push(notification); } return groups;};
export const isEmpty = (groups: NotificationGroups): boolean => groups.today.length === 0 && groups.thisWeek.length === 0 && groups.older.length === 0;