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

johnandersen777.bsky.social/knotless

git that lives in your Atmosphere account

Forked from chadtmiller.com/knotless

0
0
77 lines · 2.6 KB Raw History
<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>