169 lines
4.7 KiB
TypeScript
169 lines
4.7 KiB
TypeScript
import type { CaptureToggles, PolicyScopeType } from "#lib/api/types.js";
|
|
import { t } from "#lib/i18n/locale.svelte.js";
|
|
|
|
export type ToggleKey = keyof CaptureToggles;
|
|
|
|
type DefaultScope = "channel" | "dm" | "group";
|
|
|
|
export const TOGGLE_KEYS: ToggleKey[] = [
|
|
"messages",
|
|
"media",
|
|
"self_destruct_media",
|
|
"stt",
|
|
"reactions",
|
|
"track_edits_deletes",
|
|
"profile_history",
|
|
"stories",
|
|
"presence",
|
|
"backfill",
|
|
];
|
|
|
|
const DEFAULT_SCOPES: Partial<Record<PolicyScopeType, DefaultScope>> = {
|
|
default_channel: "channel",
|
|
default_dm: "dm",
|
|
default_group: "group",
|
|
};
|
|
|
|
const SHOWN_CHIPS = 3;
|
|
const SHORT_LIST = 2;
|
|
|
|
export interface Chip {
|
|
hint?: string;
|
|
label: string;
|
|
sign: "plus" | "minus";
|
|
}
|
|
|
|
export function toggleLabel(key: ToggleKey): string {
|
|
return t(`policy.toggle.${key}`);
|
|
}
|
|
|
|
function exceptLabel(key: ToggleKey): string {
|
|
return t(`policy.except.${key}`);
|
|
}
|
|
|
|
export function defaultLabel(scopeType: PolicyScopeType): string {
|
|
const scope = DEFAULT_SCOPES[scopeType];
|
|
return scope ? t(`policy.default.${scope}`) : "";
|
|
}
|
|
|
|
export function pickToggles(source: CaptureToggles): CaptureToggles {
|
|
return {
|
|
backfill: source.backfill,
|
|
media: source.media,
|
|
messages: source.messages,
|
|
presence: source.presence,
|
|
profile_history: source.profile_history,
|
|
reactions: source.reactions,
|
|
self_destruct_media: source.self_destruct_media,
|
|
stories: source.stories,
|
|
stt: source.stt,
|
|
track_edits_deletes: source.track_edits_deletes,
|
|
};
|
|
}
|
|
|
|
export function preset(only: ToggleKey[] | "all"): CaptureToggles {
|
|
const toggles = {} as CaptureToggles;
|
|
for (const key of TOGGLE_KEYS) {
|
|
toggles[key] = only === "all" || only.includes(key);
|
|
}
|
|
return toggles;
|
|
}
|
|
|
|
export function sameToggles(a: CaptureToggles, b: CaptureToggles): boolean {
|
|
return TOGGLE_KEYS.every((key) => a[key] === b[key]);
|
|
}
|
|
|
|
function exceptList(keys: ToggleKey[]): string {
|
|
const [first, second] = keys.map(exceptLabel);
|
|
return second === undefined
|
|
? (first ?? "")
|
|
: t("policy.summary.pair", { a: first ?? "", b: second });
|
|
}
|
|
|
|
export function summary(toggles: CaptureToggles): string {
|
|
const on = TOGGLE_KEYS.filter((key) => toggles[key]);
|
|
const off = TOGGLE_KEYS.filter((key) => !toggles[key]);
|
|
if (off.length === 0) {
|
|
return t("policy.summary.all");
|
|
}
|
|
if (on.length === 0) {
|
|
return t("policy.summary.none");
|
|
}
|
|
if (on.length === 1 && on[0] === "messages") {
|
|
return t("policy.summary.messagesOnly");
|
|
}
|
|
if (off.length <= SHORT_LIST) {
|
|
return t("policy.summary.except", { list: exceptList(off) });
|
|
}
|
|
const names = on.slice(0, SHORT_LIST).map(toggleLabel).join(", ");
|
|
const rest = on.length - SHORT_LIST;
|
|
return rest > 0 ? t("policy.summary.more", { count: rest, names }) : names;
|
|
}
|
|
|
|
export function parentLabel(
|
|
scopeType: PolicyScopeType,
|
|
title: string | null
|
|
): string {
|
|
if (scopeType === "folder") {
|
|
return t("policy.parent.folder", {
|
|
title: title ?? t("policy.parent.untitled"),
|
|
});
|
|
}
|
|
const scope = DEFAULT_SCOPES[scopeType];
|
|
return scope ? t(`policy.parent.${scope}`) : t("policy.parent.default");
|
|
}
|
|
|
|
function labelList(keys: ToggleKey[]): string {
|
|
return keys.map(toggleLabel).join(", ");
|
|
}
|
|
|
|
function named(keys: ToggleKey[], sign: Chip["sign"]): Chip[] {
|
|
return keys.map((key) => ({ label: toggleLabel(key), sign }));
|
|
}
|
|
|
|
function counted(keys: ToggleKey[], sign: Chip["sign"]): Chip[] {
|
|
if (keys.length === 0) {
|
|
return [];
|
|
}
|
|
if (keys.length <= SHOWN_CHIPS) {
|
|
return named(keys, sign);
|
|
}
|
|
return [
|
|
{
|
|
hint: labelList(keys),
|
|
label: t("policy.chip.settings", { count: keys.length }),
|
|
sign,
|
|
},
|
|
];
|
|
}
|
|
|
|
export function contentChips(rule: CaptureToggles): Chip[] {
|
|
const on = TOGGLE_KEYS.filter((key) => rule[key]);
|
|
const off = TOGGLE_KEYS.filter((key) => !rule[key]);
|
|
if (off.length === 0) {
|
|
return [{ label: t("policy.chip.allOn"), sign: "plus" }];
|
|
}
|
|
if (on.length === 0) {
|
|
return [{ label: t("policy.chip.allOff"), sign: "minus" }];
|
|
}
|
|
if (off.length <= SHOWN_CHIPS) {
|
|
return [
|
|
{ label: t("policy.summary.all"), sign: "plus" },
|
|
...named(off, "minus"),
|
|
];
|
|
}
|
|
return [...counted(on, "plus"), ...counted(off, "minus")];
|
|
}
|
|
|
|
export function diffChips(rule: CaptureToggles, base: CaptureToggles): Chip[] {
|
|
const plus = TOGGLE_KEYS.filter((key) => rule[key] && !base[key]);
|
|
const minus = TOGGLE_KEYS.filter((key) => !rule[key] && base[key]);
|
|
if (plus.length > SHOWN_CHIPS && TOGGLE_KEYS.every((key) => rule[key])) {
|
|
return [{ label: t("policy.chip.allOn"), sign: "plus" }];
|
|
}
|
|
if (minus.length > SHOWN_CHIPS && TOGGLE_KEYS.every((key) => !rule[key])) {
|
|
return [{ label: t("policy.chip.allOff"), sign: "minus" }];
|
|
}
|
|
return [...counted(plus, "plus"), ...counted(minus, "minus")];
|
|
}
|