johnandersen777.bsky.social/knotless
git that lives in your Atmosphere account
Forked from chadtmiller.com/knotless
0
0
<script lang="ts">
import type * as addEmail from '#lib/lexicons/dev/knotless/addEmail.ts';
import type * as removeEmail from '#lib/lexicons/dev/knotless/removeEmail.ts';
import { call } from '#lib/data.ts';
/**
* The addresses that show commits as the account's, of which it claims
* `count`: one to claim, or to take back. Only their hashes are kept,
* so they can be named but not listed.
*/
let { count }: { count: number } = $props();
let claimed = $derived(count);
let email = $state('');
// Which is under way: 'add' or 'remove'.
let busy = $state('');
let said = $state('');
let problem = $state('');
async function change(on: boolean) {
const address = email.trim();
if (!address) return;
busy = on ? 'add' : 'remove';
said = problem = '';
try {
const nsid = on ? 'dev.knotless.addEmail' : 'dev.knotless.removeEmail';
const done = await call<typeof addEmail.main | typeof removeEmail.main>(nsid, {
email: address
});
claimed = done.count;
if (on) said = done.changed ? `${address} is yours now.` : `${address} was yours already.`;
else
said = done.changed ? `${address} is no longer yours.` : `${address} was not one of yours.`;
email = '';
} catch (err) {
problem = (err as Error).message;
} finally {
busy = '';
}
}
</script>
<div class="settings-section"><h2>Emails</h2></div>
<div class="settings-form">
<p>
Commits authored with an address you claim show as yours, with your picture, on repositories you
own or push to. Your first push claims the one git commits with.
</p>
<p class="mute">
{claimed === 1 ? 'You claim 1 address.' : `You claim ${claimed} addresses.`} Each is kept only as
a hash, salted with your DID, so no one can list them, nor can these pages: name one to add it or
take it back.
</p>
<form class="field" onsubmit={(e) => (e.preventDefault(), change(true))}>
<label class="field-label" for="email">Email address</label>
<div class="inline-form">
<input
id="email"
type="email"
required
maxlength="320"
autocomplete="email"
placeholder="you@example.com"
bind:value={email}
/>
<button class="btn primary" type="submit" disabled={!!busy} aria-busy={busy === 'add'}
>{busy === 'add' ? 'Adding…' : 'Add'}</button
>
<button
class="btn"
type="button"
disabled={!!busy}
aria-busy={busy === 'remove'}
onclick={() => change(false)}>{busy === 'remove' ? 'Removing…' : 'Remove'}</button
>
</div>
</form>
{#if said}<p role="status">{said}</p>{/if}
{#if problem}<p class="problem" role="alert">{problem}</p>{/if}
</div>