~ knotless Search/
↑↓ move↵ open⇧↵ all results

chadtmiller.com/pds.js

An atproto PDS in JavaScript, for Cloudflare Workers and Node

0
0
main
55 lines · 1.8 KB Raw History
import { AppTile } from '#/components/atoms/app-tile.jsx';
import { ListRow } from '#/components/molecules/list-row.jsx';
import { article, nsidDomain, recordNoun, timeAgo } from '#/lib/format.js';

const VERB = {
  create: 'Added',
  update: 'Updated',
  delete: 'Removed',
};

/**
 * A feed of record changes, newest first. Every row links to that change's
 * point-in-time snapshot — deletes included, since the snapshot recovers what
 * the record was.
 */
export function ActivityList({ events, recordHref, onNavigate }) {
  return (
    <div className="flex flex-col gap-1">
      {events.map((event) => {
        const label = VERB[event.action] || event.action;
        // Read the record type in plain language ("a post"), not its NSID, and
        // let the app show once below instead of repeating its domain here.
        const noun = recordNoun(event.collection);
        const href = recordHref?.(event.collection, event.rkey, event.seq);
        return (
          <ListRow
            key={`${event.seq}-${event.collection}-${event.rkey}`}
            variant="plain"
            href={href}
            onNavigate={onNavigate}
            media={
              <AppTile
                domain={nsidDomain(event.collection)}
                label={event.collection}
                size={36}
              />
            }
            title={
              <span className="font-normal text-foreground">
                <span className="font-extrabold">{label}</span> {article(noun)}{' '}
                {noun}
              </span>
            }
            description={nsidDomain(event.collection)}
            actions={
              <span className="whitespace-nowrap text-[12px] text-faint">
                {timeAgo(event.time)}
              </span>
            }
          />
        );
      })}
    </div>
  );
}