~james/core

core/web/src/lib/components/moderation/gate.svelte.ts -rw-r--r-- 2.2 KiB
452f17b7 — james chore(import): snapshot james.dad.town/core at f70c71c7696a 16 hours ago
                                                                                
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
import { parseCanonicalResourceUri, type Nsid } from "@atcute/lexicons/syntax";
import { COMMENT_COLLECTION } from "#lib/api/comment.ts";
import {
	isAccountModeration,
	type Moderation,
	type ModerationLevel
} from "#lib/api/moderationLabels.ts";
import { PROFILE_COLLECTION } from "#lib/api/profile.ts";
import { TICKET_COLLECTION } from "#lib/api/ticket.ts";
import { getAuth } from "#lib/auth.svelte.ts";

const RECORD_NOUNS: Partial<Record<Nsid, string>> = {
	[PROFILE_COLLECTION]: "profile",
	[COMMENT_COLLECTION]: "comment",
	[TICKET_COLLECTION]: "issue"
};

const OUTCOMES: Record<ModerationLevel, string> = {
	hide: "hidden by moderators",
	warn: "flagged"
};

const subjectNoun = (moderation: Moderation): string => {
	if (isAccountModeration(moderation)) return "account";
	return RECORD_NOUNS[parseCanonicalResourceUri(moderation.target).collection] ?? "post";
};

export const moderationMessage = (moderation: Moderation): string =>
	`This ${subjectNoun(moderation)} has been ${OUTCOMES[moderation.level]}.`;

export interface ModerationGate {
	readonly moderation?: Moderation;
	readonly masked: boolean;
	readonly revealable: boolean;
	reveal(): void;
}

export const createModerationGate = (
	moderation: () => Moderation | undefined,
	isOwner: () => boolean = () => false,
	subject: () => string | undefined = () => undefined
): ModerationGate => {
	let revealedFor = $state<string>();
	const active = $derived(isOwner() ? undefined : moderation());
	const key = $derived(subject() ?? active?.target);
	const covering = $derived(
		active?.level === "warn" && key !== undefined && revealedFor === key ? undefined : active
	);

	return {
		get moderation() {
			return covering;
		},
		get masked() {
			return covering !== undefined;
		},
		get revealable() {
			return covering?.level === "warn";
		},
		reveal: () => {
			revealedFor = key;
		}
	};
};

export const createAuthorGate = (
	moderation: () => Moderation | undefined,
	author: () => string | undefined,
	subject?: () => string | undefined
): ModerationGate => {
	const auth = getAuth();
	return createModerationGate(
		moderation,
		() => {
			const did = author();
			return did !== undefined && auth?.currentDid === did;
		},
		subject
	);
};