atagen

malice

public
Star0
Watch0
31606c86aa9f9ed767d591ad237830e4df6a856c
2
ssh://brewery@pls.lobotomise.me:33/atagen/malice.git

Blame: web/src/lib/quick-reactions-model.ts

5059ed753f8batagen2026-10-27 07:20 UTC1
import type { QuickEntry, QuickReaction, QuickSeparator } from './types';
5059ed753f8batagen2026-10-27 07:20 UTC2
5059ed753f8batagen2026-10-27 07:20 UTC3
export function isSeparator(entry: QuickEntry): entry is QuickSeparator {
5059ed753f8batagen2026-10-27 07:20 UTC4
  return 'separator' in entry;
5059ed753f8batagen2026-10-27 07:20 UTC5
}
5059ed753f8batagen2026-10-27 07:20 UTC6
5059ed753f8batagen2026-10-27 07:20 UTC7
export function normaliseQuick(entries: readonly QuickEntry[]): QuickEntry[] {
5059ed753f8batagen2026-10-27 07:20 UTC8
  const seen = new Set<string>();
5059ed753f8batagen2026-10-27 07:20 UTC9
  const out: QuickEntry[] = [];
5059ed753f8batagen2026-10-27 07:20 UTC10
  for (const entry of entries) {
5059ed753f8batagen2026-10-27 07:20 UTC11
    if (isSeparator(entry)) {
5059ed753f8batagen2026-10-27 07:20 UTC12
      const last = out[out.length - 1];
5059ed753f8batagen2026-10-27 07:20 UTC13
      if (last && !isSeparator(last)) out.push(entry);
5059ed753f8batagen2026-10-27 07:20 UTC14
      continue;
5059ed753f8batagen2026-10-27 07:20 UTC15
    }
5059ed753f8batagen2026-10-27 07:20 UTC16
    if (seen.has(entry.key)) continue;
5059ed753f8batagen2026-10-27 07:20 UTC17
    seen.add(entry.key);
5059ed753f8batagen2026-10-27 07:20 UTC18
    out.push(entry);
5059ed753f8batagen2026-10-27 07:20 UTC19
  }
5059ed753f8batagen2026-10-27 07:20 UTC20
  const last = out[out.length - 1];
5059ed753f8batagen2026-10-27 07:20 UTC21
  if (last && isSeparator(last)) out.pop();
5059ed753f8batagen2026-10-27 07:20 UTC22
  return out;
5059ed753f8batagen2026-10-27 07:20 UTC23
}
5059ed753f8batagen2026-10-27 07:20 UTC24
5059ed753f8batagen2026-10-27 07:20 UTC25
export function parseQuickReactions(raw: unknown): QuickEntry[] | null {
5059ed753f8batagen2026-10-27 07:20 UTC26
  if (typeof raw !== 'object' || raw === null) return null;
5059ed753f8batagen2026-10-27 07:20 UTC27
  const list = (raw as Record<string, unknown>)['reactions'];
5059ed753f8batagen2026-10-27 07:20 UTC28
  if (!Array.isArray(list)) return null;
5059ed753f8batagen2026-10-27 07:20 UTC29
  const entries: QuickEntry[] = [];
5059ed753f8batagen2026-10-27 07:20 UTC30
  for (const item of list) {
5059ed753f8batagen2026-10-27 07:20 UTC31
    if (typeof item !== 'object' || item === null) continue;
5059ed753f8batagen2026-10-27 07:20 UTC32
    const { key, shortcode, separator } = item as Record<string, unknown>;
5059ed753f8batagen2026-10-27 07:20 UTC33
    if (separator === true) {
5059ed753f8batagen2026-10-27 07:20 UTC34
      entries.push({ separator: true });
5059ed753f8batagen2026-10-27 07:20 UTC35
      continue;
5059ed753f8batagen2026-10-27 07:20 UTC36
    }
5059ed753f8batagen2026-10-27 07:20 UTC37
    if (typeof key !== 'string' || !key) continue;
5059ed753f8batagen2026-10-27 07:20 UTC38
    entries.push({ key, shortcode: typeof shortcode === 'string' ? shortcode : null });
5059ed753f8batagen2026-10-27 07:20 UTC39
  }
5059ed753f8batagen2026-10-27 07:20 UTC40
  return normaliseQuick(entries);
5059ed753f8batagen2026-10-27 07:20 UTC41
}
5059ed753f8batagen2026-10-27 07:20 UTC42
5059ed753f8batagen2026-10-27 07:20 UTC43
export function quickGroups(entries: readonly QuickEntry[]): QuickReaction[][] {
5059ed753f8batagen2026-10-27 07:20 UTC44
  const groups: QuickReaction[][] = [];
5059ed753f8batagen2026-10-27 07:20 UTC45
  let group: QuickReaction[] = [];
5059ed753f8batagen2026-10-27 07:20 UTC46
  for (const entry of entries) {
5059ed753f8batagen2026-10-27 07:20 UTC47
    if (!isSeparator(entry)) {
5059ed753f8batagen2026-10-27 07:20 UTC48
      group.push(entry);
5059ed753f8batagen2026-10-27 07:20 UTC49
      continue;
5059ed753f8batagen2026-10-27 07:20 UTC50
    }
5059ed753f8batagen2026-10-27 07:20 UTC51
    if (group.length > 0) groups.push(group);
5059ed753f8batagen2026-10-27 07:20 UTC52
    group = [];
5059ed753f8batagen2026-10-27 07:20 UTC53
  }
5059ed753f8batagen2026-10-27 07:20 UTC54
  if (group.length > 0) groups.push(group);
5059ed753f8batagen2026-10-27 07:20 UTC55
  return groups;
5059ed753f8batagen2026-10-27 07:20 UTC56
}
5059ed753f8batagen2026-10-27 07:20 UTC57
5059ed753f8batagen2026-10-27 07:20 UTC58
export function quickColumns(groups: readonly QuickReaction[][], perRow: number): number {
5059ed753f8batagen2026-10-27 07:20 UTC59
  return groups.reduce((cols, group) => Math.max(cols, Math.min(group.length, perRow)), 0);
5059ed753f8batagen2026-10-27 07:20 UTC60
}
5059ed753f8batagen2026-10-27 07:20 UTC61
5059ed753f8batagen2026-10-27 07:20 UTC62
export function sameQuick(a: readonly QuickEntry[], b: readonly QuickEntry[]): boolean {
5059ed753f8batagen2026-10-27 07:20 UTC63
  return (
5059ed753f8batagen2026-10-27 07:20 UTC64
    a.length === b.length &&
5059ed753f8batagen2026-10-27 07:20 UTC65
    a.every((entry, i) => {
5059ed753f8batagen2026-10-27 07:20 UTC66
      const other = b[i];
5059ed753f8batagen2026-10-27 07:20 UTC67
      return isSeparator(entry) ? isSeparator(other) : !isSeparator(other) && entry.key === other.key;
5059ed753f8batagen2026-10-27 07:20 UTC68
    })
5059ed753f8batagen2026-10-27 07:20 UTC69
  );
5059ed753f8batagen2026-10-27 07:20 UTC70
}