bsky-app/src/state/models/ui/preferences.ts
Paul Frazee 2fed6c4021
Add first round of labeling tools (#467)
* Rework notifications to sync locally in full and give users better control

* Fix positioning of load more btn on web

* Improve behavior of load more notifications btn

* Fix to post rendering

* Fix notification fetch abort condition

* Add start of post-hiding by labels

* Create a standard postcontainer and improve show/hide UI on posts

* Add content hiding to expanded post form

* Improve label rendering to give more context to users when appropriate

* Fix rendering bug

* Add user/profile labeling

* Implement content filtering preferences

* Filter notifications by content prefs

* Update test-pds config

* Bump deps
2023-04-12 18:26:38 -07:00

102 lines
2.6 KiB
TypeScript

import {makeAutoObservable} from 'mobx'
import {getLocales} from 'expo-localization'
import {isObj, hasProp} from 'lib/type-guards'
import {ComAtprotoLabelDefs} from '@atproto/api'
import {getLabelValueGroup} from 'lib/labeling/helpers'
import {
LabelValGroup,
UNKNOWN_LABEL_GROUP,
ILLEGAL_LABEL_GROUP,
} from 'lib/labeling/const'
const deviceLocales = getLocales()
export type LabelPreference = 'show' | 'warn' | 'hide'
export class LabelPreferencesModel {
nsfw: LabelPreference = 'warn'
gore: LabelPreference = 'hide'
hate: LabelPreference = 'hide'
spam: LabelPreference = 'hide'
impersonation: LabelPreference = 'warn'
constructor() {
makeAutoObservable(this, {}, {autoBind: true})
}
}
export class PreferencesModel {
_contentLanguages: string[] | undefined
contentLabels = new LabelPreferencesModel()
constructor() {
makeAutoObservable(this, {}, {autoBind: true})
}
// gives an array of BCP 47 language tags without region codes
get contentLanguages() {
if (this._contentLanguages) {
return this._contentLanguages
}
return deviceLocales.map(locale => locale.languageCode)
}
serialize() {
return {
contentLanguages: this._contentLanguages,
contentLabels: this.contentLabels,
}
}
hydrate(v: unknown) {
if (isObj(v)) {
if (
hasProp(v, 'contentLanguages') &&
Array.isArray(v.contentLanguages) &&
typeof v.contentLanguages.every(item => typeof item === 'string')
) {
this._contentLanguages = v.contentLanguages
}
if (hasProp(v, 'contentLabels') && typeof v.contentLabels === 'object') {
Object.assign(this.contentLabels, v.contentLabels)
}
}
}
setContentLabelPref(
key: keyof LabelPreferencesModel,
value: LabelPreference,
) {
this.contentLabels[key] = value
}
getLabelPreference(labels: ComAtprotoLabelDefs.Label[] | undefined): {
pref: LabelPreference
desc: LabelValGroup
} {
let res: {pref: LabelPreference; desc: LabelValGroup} = {
pref: 'show',
desc: UNKNOWN_LABEL_GROUP,
}
if (!labels?.length) {
return res
}
for (const label of labels) {
const group = getLabelValueGroup(label.val)
if (group.id === 'illegal') {
return {pref: 'hide', desc: ILLEGAL_LABEL_GROUP}
} else if (group.id === 'unknown') {
continue
}
let pref = this.contentLabels[group.id]
if (pref === 'hide') {
res.pref = 'hide'
res.desc = group
} else if (pref === 'warn' && res.pref === 'show') {
res.pref = 'warn'
res.desc = group
}
}
return res
}
}