about summary refs log tree commit diff
path: root/src/lib/moderation/useLabelInfo.ts
blob: 0ff7e1246a562d8b666031e212c3c54bfa8b7eda (plain) (blame)
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
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
import {
  AppBskyLabelerDefs,
  ComAtprotoLabelDefs,
  InterpretedLabelValueDefinition,
  interpretLabelValueDefinition,
  LABELS,
} from '@atproto/api'
import {useLingui} from '@lingui/react'
import * as bcp47Match from 'bcp-47-match'

import {
  GlobalLabelStrings,
  useGlobalLabelStrings,
} from '#/lib/moderation/useGlobalLabelStrings'
import {useLabelDefinitions} from '#/state/preferences'

export interface LabelInfo {
  label: ComAtprotoLabelDefs.Label
  def: InterpretedLabelValueDefinition
  strings: ComAtprotoLabelDefs.LabelValueDefinitionStrings
  labeler: AppBskyLabelerDefs.LabelerViewDetailed | undefined
}

export function useLabelInfo(label: ComAtprotoLabelDefs.Label): LabelInfo {
  const {i18n} = useLingui()
  const {labelDefs, labelers} = useLabelDefinitions()
  const globalLabelStrings = useGlobalLabelStrings()
  const def = getDefinition(labelDefs, label)
  return {
    label,
    def,
    strings: getLabelStrings(i18n.locale, globalLabelStrings, def),
    labeler: labelers.find(labeler => label.src === labeler.creator.did),
  }
}

export function getDefinition(
  labelDefs: Record<string, InterpretedLabelValueDefinition[]>,
  label: ComAtprotoLabelDefs.Label,
): InterpretedLabelValueDefinition {
  // check local definitions
  const customDef =
    !label.val.startsWith('!') &&
    labelDefs[label.src]?.find(
      def => def.identifier === label.val && def.definedBy === label.src,
    )
  if (customDef) {
    return customDef
  }

  // check global definitions
  const globalDef = LABELS[label.val as keyof typeof LABELS]
  if (globalDef) {
    return globalDef
  }

  // fallback to a noop definition
  return interpretLabelValueDefinition(
    {
      identifier: label.val,
      severity: 'none',
      blurs: 'none',
      defaultSetting: 'ignore',
      locales: [],
    },
    label.src,
  )
}

export function getLabelStrings(
  locale: string,
  globalLabelStrings: GlobalLabelStrings,
  def: InterpretedLabelValueDefinition,
): ComAtprotoLabelDefs.LabelValueDefinitionStrings {
  if (!def.definedBy) {
    // global definition, look up strings
    if (def.identifier in globalLabelStrings) {
      return globalLabelStrings[
        def.identifier
      ] as ComAtprotoLabelDefs.LabelValueDefinitionStrings
    }
  } else {
    // try to find locale match in the definition's strings
    const localeMatch = def.locales.find(
      strings => bcp47Match.basicFilter(locale, strings.lang).length > 0,
    )
    if (localeMatch) {
      return localeMatch
    }
    // fall back to the zero item if no match
    if (def.locales[0]) {
      return def.locales[0]
    }
  }
  return {
    lang: locale,
    name: def.identifier,
    description: `Labeled "${def.identifier}"`,
  }
}