168 lines
5.1 KiB
TypeScript
168 lines
5.1 KiB
TypeScript
import type { CaptureToggles, PolicyScopeType } from "#lib/api/types.js";
|
||
import { plural } from "#lib/format/shares.js";
|
||
|
||
export type ToggleKey = keyof CaptureToggles;
|
||
|
||
export const TOGGLE_LABELS: Record<ToggleKey, string> = {
|
||
backfill: "Бэкфилл",
|
||
media: "Медиа",
|
||
messages: "Сообщения",
|
||
presence: "Присутствие",
|
||
profile_history: "История профиля",
|
||
reactions: "Реакции",
|
||
self_destruct_media: "Исчезающие",
|
||
stories: "Сторис",
|
||
stt: "Расшифровка",
|
||
track_edits_deletes: "Правки, удаления",
|
||
};
|
||
|
||
export const TOGGLE_KEYS: ToggleKey[] = [
|
||
"messages",
|
||
"media",
|
||
"self_destruct_media",
|
||
"stt",
|
||
"reactions",
|
||
"track_edits_deletes",
|
||
"profile_history",
|
||
"stories",
|
||
"presence",
|
||
"backfill",
|
||
];
|
||
|
||
export const DEFAULT_LABELS: Partial<Record<PolicyScopeType, string>> = {
|
||
default_channel: "Каналы",
|
||
default_dm: "Личные чаты",
|
||
default_group: "Группы",
|
||
};
|
||
|
||
const PARENT_LABELS: Partial<Record<PolicyScopeType, string>> = {
|
||
default_channel: "у каналов",
|
||
default_dm: "у личных чатов",
|
||
default_group: "у групп",
|
||
};
|
||
|
||
const SHOWN_CHIPS = 3;
|
||
const SHORT_LIST = 2;
|
||
|
||
export interface Chip {
|
||
hint?: string;
|
||
label: string;
|
||
sign: "plus" | "minus";
|
||
}
|
||
|
||
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]);
|
||
}
|
||
|
||
const EXCEPT_LABELS: Record<ToggleKey, string> = {
|
||
backfill: "бэкфилла",
|
||
media: "медиа",
|
||
messages: "сообщений",
|
||
presence: "присутствия",
|
||
profile_history: "истории профиля",
|
||
reactions: "реакций",
|
||
self_destruct_media: "исчезающих",
|
||
stories: "сторис",
|
||
stt: "расшифровки",
|
||
track_edits_deletes: "правок и удалений",
|
||
};
|
||
|
||
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 "Всё";
|
||
}
|
||
if (on.length === 0) {
|
||
return "Ничего";
|
||
}
|
||
if (on.length === 1 && on[0] === "messages") {
|
||
return "Только сообщения";
|
||
}
|
||
if (off.length <= SHORT_LIST) {
|
||
return `Всё, кроме ${off.map((key) => EXCEPT_LABELS[key]).join(" и ")}`;
|
||
}
|
||
const names = on.slice(0, SHORT_LIST).map((key) => TOGGLE_LABELS[key]);
|
||
const rest = on.length - names.length;
|
||
return rest > 0 ? `${names.join(", ")} и ещё ${rest}` : names.join(", ");
|
||
}
|
||
|
||
export function parentLabel(
|
||
scopeType: PolicyScopeType,
|
||
title: string | null
|
||
): string {
|
||
if (scopeType === "folder") {
|
||
return `у папки «${title ?? "без названия"}»`;
|
||
}
|
||
return PARENT_LABELS[scopeType] ?? "по умолчанию";
|
||
}
|
||
|
||
function labelList(keys: ToggleKey[]): string {
|
||
return keys.map((key) => TOGGLE_LABELS[key]).join(", ");
|
||
}
|
||
|
||
function named(keys: ToggleKey[], sign: Chip["sign"]): Chip[] {
|
||
return keys.map((key) => ({ label: TOGGLE_LABELS[key], sign }));
|
||
}
|
||
|
||
function counted(keys: ToggleKey[], sign: Chip["sign"]): Chip[] {
|
||
if (keys.length === 0) {
|
||
return [];
|
||
}
|
||
if (keys.length <= SHOWN_CHIPS) {
|
||
return named(keys, sign);
|
||
}
|
||
const word = plural(keys.length, "настройка", "настройки", "настроек");
|
||
return [{ hint: labelList(keys), label: `${keys.length} ${word}`, 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: "Всё включено", sign: "plus" }];
|
||
}
|
||
if (on.length === 0) {
|
||
return [{ label: "Всё выключено", sign: "minus" }];
|
||
}
|
||
if (off.length <= SHOWN_CHIPS) {
|
||
return [{ label: "Всё", 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: "Всё включено", sign: "plus" }];
|
||
}
|
||
if (minus.length > SHOWN_CHIPS && TOGGLE_KEYS.every((key) => !rule[key])) {
|
||
return [{ label: "Всё выключено", sign: "minus" }];
|
||
}
|
||
return [...counted(plus, "plus"), ...counted(minus, "minus")];
|
||
}
|