93 lines · 3.2 KB
import { Avatar } from "~/ui/Avatar";
import { EmptyState } from "~/ui/EmptyState";
import { RelativeTime } from "~/ui/RelativeTime";
import type { JsonValue } from "~/lib/types";
import { TextLink } from "~/ui/TextLink";

export type FeedItem = {
  id: string;
  actor: { name: string };
  repo: { owner: string; name: string } | null;
  kind: string;
  data: { [key: string]: JsonValue };
  createdAt: number;
};

function text(value: JsonValue | undefined): string {
  return typeof value === "string" || typeof value === "number" ? String(value) : "";
}

/** One-line description of an activity row, e.g. "opened pull request #4 Fix parser". */
export function describeActivity(item: Pick<FeedItem, "kind" | "data">): string {
  const { data } = item;
  switch (item.kind) {
    case "push":
      return `pushed ${text(data.total)} commit(s) to ${text(data.ref)}`;
    case "ref_created":
      return `created ${text(data.refType)} ${text(data.ref)}`;
    case "ref_deleted":
      return `deleted ${text(data.refType)} ${text(data.ref)}`;
    case "repo_created":
      return "created repository";
    case "repo_imported":
      return `imported from ${text(data.source)}`;
    case "repo_forked":
      return `forked ${text(data.source)}`;
    case "issue_opened":
      return `opened issue #${text(data.number)} ${text(data.title)}`;
    case "pull_opened":
      return `opened pull request #${text(data.number)} ${text(data.title)}`;
    case "pull_merged":