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

johnandersen777.bsky.social/knotless

git that lives in your Atmosphere account

Forked from chadtmiller.com/knotless

0
0
57 lines · 2.0 KB Raw History
<script lang="ts">
	import type { ActorView } from '#lib/lexicons/dev/knotless/defs.ts';
	import type * as repo from '#lib/lexicons/dev/knotless/repo.ts';
	import ItemFacts from '#lib/organisms/ItemFacts.svelte';
	/**
	 * What a pull or an issue will carry as it opens, in the facts line
	 * its page shows once open: the labels to put on it, of those
	 * `offered`, and with `people` the reviewers to ask, from them. Nothing
	 * is written until it opens: what is chosen is bound, `labels` by name
	 * and `reviewers` by DID, for the form to send.
	 */
	let {
		offered,
		labels = $bindable([]),
		people = [],
		reviewers = $bindable([])
	}: {
		offered: repo.Label[];
		labels?: string[];
		people?: ActorView[];
		reviewers?: ActorView['did'][];
	} = $props();
	const chosen = $derived(offered.filter((l) => labels.includes(l.name)));
	const asked = $derived(people.filter((p) => reviewers.includes(p.did)));
	const flip = <T extends string>(list: T[], one: T, removed: boolean) =>
		removed ? list.filter((x) => x !== one) : [...list, one];
	/** Its scope: what comes before its last `/`. */
	const scope = (name: string) => name.slice(0, Math.max(0, name.lastIndexOf('/')));
	/** Labels with `name` put on or taken off: an exclusive one put on takes the others of its scope off, as labelling does. */
	async function label(name: string, removed: boolean) {
		const l = offered.find((o) => o.name === name);
		const rivals = (o: string) =>
			!!l?.exclusive &&
			!removed &&
			!!scope(name) &&
			scope(o) === scope(name) &&
			!!offered.find((x) => x.name === o)?.exclusive;
		labels = flip(
			labels.filter((o) => !rivals(o)),
			name,
			removed
		);
	}
	/** Asks `did` to review it as it opens, or no longer. */
	async function ask(did: ActorView['did'], removed: boolean) {
		reviewers = flip(reviewers, did, removed);
	}
</script>

<ItemFacts
	requested={asked}
	{people}
	ask={people.length ? ask : undefined}
	labels={chosen}
	{offered}
	label={offered.length ? label : undefined}
/>