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

chadtmiller.com/pds.js

An atproto PDS in JavaScript, for Cloudflare Workers and Node

0
0
main
73 lines · 2.3 KB Raw History
import { Avatar } from '#/components/atoms/avatar.jsx';
import { initial, owner } from '#/lib/authors.js';
import { bytes } from '#/lib/format.js';
import { account, repoSize } from '#/lib/git.js';

/** One reading of the account, label above value. */
function Field({ label, children }) {
  return (
    <div className="min-w-0">
      <div className="text-[10px] text-faint uppercase tracking-[0.12em]">
        {label}
      </div>
      <div className="mt-1 truncate font-mono text-[12px] text-muted-foreground">
        {children}
      </div>
    </div>
  );
}

/**
 * Whose repositories these are, beside the list of them: the account, the
 * name it answers to, and the server holding it. Every repository on this
 * page is one account's, so the account is named once here rather than on
 * each row.
 */
export function AccountPanel({ repos }) {
  const profile = owner();
  const total = (repos ?? []).reduce((sum, repo) => sum + repoSize(repo), 0);

  return (
    <div className="flex flex-col gap-5">
      <div className="flex items-center gap-4 lg:flex-col lg:items-stretch">
        <Avatar
          src={profile?.avatar || undefined}
          fallback={
            <span className="text-[40px] text-faint">
              {initial(profile?.displayName || account.handle)}
            </span>
          }
          className="size-20 shrink-0 lg:size-64"
        />
        <div className="w-full min-w-0">
          <div className="truncate font-semibold text-[24px] leading-tight text-foreground">
            {profile?.displayName || account.handle}
          </div>
          <div className="truncate font-mono text-[16px] text-muted-foreground">
            {account.handle}
          </div>
        </div>
      </div>

      {profile?.description && (
        <p className="text-[13.5px] text-muted-foreground leading-relaxed">
          {profile.description}
        </p>
      )}

      <div className="flex flex-col gap-4 border-border border-t pt-5">
        <Field label="Identity">
          <span title={account.did}>{account.did}</span>
        </Field>
        <Field label="Server">
          <span title={account.pds}>
            {account.pds.replace(/^https?:\/\//, '')}
          </span>
        </Field>
        <Field label="Repositories">
          {(repos ?? []).length} · {bytes(total)}
        </Field>
      </div>
    </div>
  );
}