import { useState } from "react"; import { addEmail, removeEmail, resendVerificationEmail, setPrimaryEmail } from "~/fns/account-security"; import type { getSecuritySettings } from "~/fns/account-security"; import { useAction } from "~/hooks/use-action"; import { Button } from "~/ui/Button"; import { TextField } from "~/ui/Field"; import { ErrorBanner } from "~/ui/Callout"; import { Badge } from "~/ui/Badge"; import { Panel } from "~/ui/Panel"; type AccountEmail = Awaited>["emails"][number]; type Notice = { text: string; devMailUrl?: string | null }; type RowProps = { entry: AccountEmail; hasPassword: boolean; onNotice: (notice: Notice) => void }; function openDevMail(url: string | null) { if (url) window.open(url, "_blank", "noopener"); } function EmailRow({ entry, hasPassword, onNotice }: RowProps) { const resend = useAction(resendVerificationEmail, { invalidate: false }); const remove = useAction(removeEmail); const makePrimary = useAction(setPrimaryEmail); const [confirming, setConfirming] = useState<"primary" | "remove" | null>(null); const error = resend.error ?? remove.error ?? makePrimary.error; const canMakePrimary = !entry.primary && entry.verified; async function promote(password: string) { if (await makePrimary.run({ data: { email: entry.email, password } })) { setConfirming(null); onNotice({ text: `${entry.email} is now your primary address.` }); } } async function drop(password: string) { if (await remove.run({ data: { email: entry.email, password } })) { setConfirming(null); onNotice({ text: `${entry.email} was removed.` }); } } return (
  • {entry.email} {entry.primary && Primary} {entry.verified ? Verified : Unverified}
    {!entry.verified && ( )} {canMakePrimary && !confirming && ( )} {!entry.primary && !confirming && ( )}
    {confirming && (
    { event.preventDefault(); const password = String(new FormData(event.currentTarget).get("password") ?? ""); await (confirming === "remove" ? drop(password) : promote(password)); }} > )}
  • ); } export function EmailPanel({ emails, hasPassword }: { emails: AccountEmail[]; hasPassword: boolean }) { const add = useAction(addEmail); const [notice, setNotice] = useState(null); return (
    {notice && ( {notice.text} {notice.devMailUrl && ( <> {" "} Open dev mail preview )} )}

    Your primary address is used for sign-in and notifications. Any verified address can sign commits, match CODEOWNERS entries and receive password resets.

      {emails.map((entry) => ( ))}
    { event.preventDefault(); const formElement = event.currentTarget; const form = new FormData(formElement); const next = String(form.get("email") ?? ""); const result = await add.run({ data: { email: next, password: String(form.get("password") ?? "") } }); if (result) { formElement.reset(); setNotice({ text: `Check ${next} for a link to confirm it.`, devMailUrl: result.devMailUrl }); openDevMail(result.devMailUrl); } }} > {hasPassword && ( )}
    ); }