johnandersen777.bsky.social/knotless
git that lives in your Atmosphere account
Forked from chadtmiller.com/knotless
0
0
<script lang="ts">
import type { RepoView } from '#lib/lexicons/dev/knotless/defs.ts';
import type * as blockActor from '#lib/lexicons/dev/knotless/blockActor.ts';
import type * as listBlocks from '#lib/lexicons/dev/knotless/listBlocks.ts';
import type * as unblockActor from '#lib/lexicons/dev/knotless/unblockActor.ts';
import type { AtIdentifierString, AtUriString } from '@atproto/lex';
import { invalidateAll } from '$app/navigation';
import { call } from '#lib/data.ts';
import { urlPath } from '#lib/format.ts';
import Avatar from '#lib/atoms/Avatar.svelte';
import Time from '#lib/atoms/Time.svelte';
import Empty from '#lib/molecules/Empty.svelte';
/**
* The accounts the account blocks, each from all its repositories or
* from one, the latest first, with a way to unblock each; and to block
* another, from all of them or from one of its public `repos`.
*/
let { blocks, repos }: { blocks: listBlocks.Block[]; repos: RepoView[] } = $props();
let who = $state('');
let repo = $state('');
// What is under way: 'block', or the account being unblocked.
let busy = $state('');
let problem = $state('');
async function change(
nsid: 'dev.knotless.blockActor' | 'dev.knotless.unblockActor',
subject: string,
from?: string
) {
busy = nsid === 'dev.knotless.blockActor' ? 'block' : subject;
problem = '';
try {
const input = {
subject: subject as AtIdentifierString,
repo: from ? (from as AtUriString) : undefined
};
await call<typeof blockActor.main | typeof unblockActor.main>(nsid, input);
await invalidateAll();
if (nsid === 'dev.knotless.blockActor') who = '';
} catch (err) {
problem = (err as Error).message;
} finally {
busy = '';
}
}
const uriOf = (b: listBlocks.Block) =>
b.repo && (`at://${b.repo.did}/dev.knotless.repo/${b.repo.name}` as const);
</script>
<div class="settings-section"><h2>Blocked accounts</h2></div>
<div class="settings-form">
<p>
Nothing an account you block writes about your repositories shows: its pulls, issues and
comments are left out, and you hear nothing it does. Block it from all your repositories, or
from one.
</p>
<form
class="inline-form"
onsubmit={(e) => (e.preventDefault(), change('dev.knotless.blockActor', who.trim(), repo))}
>
<input
aria-label="Handle or DID to block"
required
maxlength="253"
placeholder="handle.example.com"
bind:value={who}
/>
<select aria-label="Block from" bind:value={repo}>
<option value="">All your repositories</option>
{#each repos as r (r.uri)}<option value={r.uri}>{r.name}</option>{/each}
</select>
<button class="btn" type="submit" disabled={!!busy} aria-busy={busy === 'block'}
>{busy === 'block' ? 'Blocking…' : 'Block'}</button
>
</form>
{#if problem}<p class="problem" role="alert">{problem}</p>{/if}
<div class="box">
<ul class="list">
{#each blocks as b (b.uri)}
<li>
<Avatar name={b.subject.handle} size="lg" did={b.subject.did} src={b.subject.avatar} />
<div class="grow">
<a class="clip" href="/{urlPath(b.subject.handle)}"><b>{b.subject.handle}</b></a>
<p class="meta">
{#if b.repo}<span>{`From ${b.repo.name}`}</span>{:else}<span
>From all your repositories</span
>{/if}<Time at={b.createdAt} />
</p>
</div>
<button
class="btn"
type="button"
disabled={!!busy}
aria-busy={busy === b.subject.did}
onclick={() => change('dev.knotless.unblockActor', b.subject.did, uriOf(b))}
>{busy === b.subject.did ? 'Unblocking…' : 'Unblock'}</button
>
</li>
{:else}
<li class="blank"><Empty title="No blocked accounts" /></li>
{/each}
</ul>
</div>
</div>