An ATproto social media client -- with an independent Appview.
6
fork

Configure Feed

Select the types of activity you want to include in your feed.

Mods UI fixes (#3296)

* Fix report dialog buttons on Android by adjusting styles

* Dry up label pref comp

authored by

Eric Bailey and committed by
GitHub
5f39ca31 4ff2bb7a

+388 -378
+7 -10
src/components/ReportDialog/SelectLabelerView.tsx
··· 38 38 39 39 <Divider /> 40 40 41 - <View style={[a.gap_xs, {marginHorizontal: a.p_md.padding * -1}]}> 41 + <View style={[a.gap_sm]}> 42 42 {props.labelers.map(labeler => { 43 43 return ( 44 44 <Button ··· 63 63 const {hovered, pressed} = useButtonContext() 64 64 const interacted = hovered || pressed 65 65 66 - const styles = React.useMemo(() => { 67 - return { 68 - interacted: { 69 - backgroundColor: t.palette.contrast_50, 70 - }, 71 - } 72 - }, [t]) 73 - 74 66 return ( 75 67 <LabelingServiceCard.Outer 76 - style={[a.p_md, a.rounded_sm, interacted && styles.interacted]}> 68 + style={[ 69 + a.p_md, 70 + a.rounded_sm, 71 + t.atoms.bg_contrast_25, 72 + interacted && t.atoms.bg_contrast_50, 73 + ]}> 77 74 <LabelingServiceCard.Avatar avatar={labeler.creator.avatar} /> 78 75 <LabelingServiceCard.Content> 79 76 <LabelingServiceCard.Title
+33 -47
src/components/ReportDialog/SelectReportOptionView.tsx
··· 86 86 87 87 <Divider /> 88 88 89 - <View style={[a.gap_sm, {marginHorizontal: a.p_md.padding * -1}]}> 89 + <View style={[a.gap_sm]}> 90 90 {reportOptions.map(reportOption => { 91 91 return ( 92 92 <Button ··· 102 102 })} 103 103 104 104 {(props.params.type === 'post' || props.params.type === 'account') && ( 105 - <View style={[a.pt_md, a.px_md]}> 106 - <View 105 + <View 106 + style={[ 107 + a.flex_row, 108 + a.align_center, 109 + a.justify_between, 110 + a.gap_lg, 111 + a.p_md, 112 + a.pl_lg, 113 + a.rounded_md, 114 + t.atoms.bg_contrast_900, 115 + ]}> 116 + <Text 107 117 style={[ 108 - a.flex_row, 109 - a.align_center, 110 - a.justify_between, 111 - a.gap_lg, 112 - a.p_md, 113 - a.pl_lg, 114 - a.rounded_md, 115 - t.atoms.bg_contrast_900, 118 + a.flex_1, 119 + t.atoms.text_inverted, 120 + a.italic, 121 + a.leading_snug, 116 122 ]}> 117 - <Text 118 - style={[ 119 - a.flex_1, 120 - t.atoms.text_inverted, 121 - a.italic, 122 - a.leading_snug, 123 - ]}> 124 - <Trans>Need to report a copyright violation?</Trans> 125 - </Text> 126 - <Link 127 - to={DMCA_LINK} 128 - label={_(msg`View details for reporting a copyright violation`)} 129 - size="small" 130 - variant="solid" 131 - color="secondary"> 132 - <ButtonText> 133 - <Trans>View details</Trans> 134 - </ButtonText> 135 - <ButtonIcon position="right" icon={SquareArrowTopRight} /> 136 - </Link> 137 - </View> 123 + <Trans>Need to report a copyright violation?</Trans> 124 + </Text> 125 + <Link 126 + to={DMCA_LINK} 127 + label={_(msg`View details for reporting a copyright violation`)} 128 + size="small" 129 + variant="solid" 130 + color="secondary"> 131 + <ButtonText> 132 + <Trans>View details</Trans> 133 + </ButtonText> 134 + <ButtonIcon position="right" icon={SquareArrowTopRight} /> 135 + </Link> 138 136 </View> 139 137 )} 140 138 </View> ··· 152 150 const t = useTheme() 153 151 const {hovered, pressed} = useButtonContext() 154 152 const interacted = hovered || pressed 155 - 156 - const styles = React.useMemo(() => { 157 - return { 158 - interacted: { 159 - backgroundColor: t.palette.contrast_50, 160 - }, 161 - } 162 - }, [t]) 163 153 164 154 return ( 165 155 <View ··· 171 161 a.p_md, 172 162 a.rounded_md, 173 163 {paddingRight: 70}, 174 - interacted && styles.interacted, 164 + t.atoms.bg_contrast_25, 165 + interacted && t.atoms.bg_contrast_50, 175 166 ]}> 176 167 <View style={[a.flex_1, a.gap_xs]}> 177 168 <Text style={[a.text_md, a.font_bold, t.atoms.text_contrast_medium]}> ··· 188 179 a.pr_md, 189 180 {left: 'auto'}, 190 181 ]}> 191 - <ChevronRight 192 - size="md" 193 - fill={ 194 - hovered ? t.palette.primary_500 : t.atoms.text_contrast_low.color 195 - } 196 - /> 182 + <ChevronRight size="md" fill={t.atoms.text_contrast_low.color} /> 197 183 </View> 198 184 </View> 199 185 )
+4 -2
src/components/ReportDialog/index.tsx
··· 1 1 import React from 'react' 2 2 import {Pressable, View} from 'react-native' 3 - import {Trans} from '@lingui/macro' 3 + import {msg, Trans} from '@lingui/macro' 4 + import {useLingui} from '@lingui/react' 4 5 5 6 import {ReportOption} from '#/lib/moderation/useReportOptions' 6 7 import {useMyLabelersQuery} from '#/state/queries/preferences' ··· 31 32 } 32 33 33 34 function ReportDialogInner(props: ReportDialogProps) { 35 + const {_} = useLingui() 34 36 const { 35 37 isLoading: isLabelerLoading, 36 38 data: labelers, ··· 44 46 }) 45 47 46 48 return ( 47 - <Dialog.ScrollableInner label="Report Dialog" ref={ref}> 49 + <Dialog.ScrollableInner label={_(msg`Report dialog`)} ref={ref}> 48 50 {isLoading ? ( 49 51 <View style={[a.align_center, {height: 100}]}> 50 52 <Loader size="xl" />
+6 -6
src/components/forms/TextField.tsx
··· 1 1 import React from 'react' 2 2 import { 3 - View, 3 + AccessibilityProps, 4 + StyleSheet, 4 5 TextInput, 5 6 TextInputProps, 6 7 TextStyle, 8 + View, 7 9 ViewStyle, 8 - StyleSheet, 9 - AccessibilityProps, 10 10 } from 'react-native' 11 11 12 + import {mergeRefs} from '#/lib/merge-refs' 12 13 import {HITSLOP_20} from 'lib/constants' 13 - import {useTheme, atoms as a, web, android} from '#/alf' 14 - import {Text} from '#/components/Typography' 14 + import {android, atoms as a, useTheme, web} from '#/alf' 15 15 import {useInteractionState} from '#/components/hooks/useInteractionState' 16 16 import {Props as SVGIconProps} from '#/components/icons/common' 17 - import {mergeRefs} from '#/lib/merge-refs' 17 + import {Text} from '#/components/Typography' 18 18 19 19 const Context = React.createContext<{ 20 20 inputRef: React.RefObject<TextInput> | null
-93
src/components/moderation/GlobalModerationLabelPref.tsx
··· 1 - import React from 'react' 2 - import {View} from 'react-native' 3 - import {InterpretedLabelValueDefinition, LabelPreference} from '@atproto/api' 4 - import {useLingui} from '@lingui/react' 5 - import {msg} from '@lingui/macro' 6 - 7 - import {useGlobalLabelStrings} from '#/lib/moderation/useGlobalLabelStrings' 8 - import { 9 - usePreferencesQuery, 10 - usePreferencesSetContentLabelMutation, 11 - } from '#/state/queries/preferences' 12 - 13 - import {useTheme, atoms as a} from '#/alf' 14 - import {Text} from '#/components/Typography' 15 - import * as ToggleButton from '#/components/forms/ToggleButton' 16 - 17 - export function GlobalModerationLabelPref({ 18 - labelValueDefinition, 19 - disabled, 20 - }: { 21 - labelValueDefinition: InterpretedLabelValueDefinition 22 - disabled?: boolean 23 - }) { 24 - const {_} = useLingui() 25 - const t = useTheme() 26 - 27 - const {identifier} = labelValueDefinition 28 - const {data: preferences} = usePreferencesQuery() 29 - const {mutate, variables} = usePreferencesSetContentLabelMutation() 30 - const savedPref = preferences?.moderationPrefs.labels[identifier] 31 - const pref = variables?.visibility ?? savedPref ?? 'warn' 32 - 33 - const allLabelStrings = useGlobalLabelStrings() 34 - const labelStrings = 35 - labelValueDefinition.identifier in allLabelStrings 36 - ? allLabelStrings[labelValueDefinition.identifier] 37 - : { 38 - name: labelValueDefinition.identifier, 39 - description: `Labeled "${labelValueDefinition.identifier}"`, 40 - } 41 - 42 - const labelOptions = { 43 - hide: _(msg`Hide`), 44 - warn: _(msg`Warn`), 45 - ignore: _(msg`Show`), 46 - } 47 - 48 - return ( 49 - <View 50 - style={[ 51 - a.flex_row, 52 - a.justify_between, 53 - a.gap_sm, 54 - a.py_md, 55 - a.pl_lg, 56 - a.pr_md, 57 - a.align_center, 58 - ]}> 59 - <View style={[a.gap_xs, a.flex_1]}> 60 - <Text style={[a.font_bold]}>{labelStrings.name}</Text> 61 - <Text style={[t.atoms.text_contrast_medium, a.leading_snug]}> 62 - {labelStrings.description} 63 - </Text> 64 - </View> 65 - <View style={[a.justify_center, {minHeight: 35}]}> 66 - {!disabled && ( 67 - <ToggleButton.Group 68 - label={_( 69 - msg`Configure content filtering setting for category: ${labelStrings.name.toLowerCase()}`, 70 - )} 71 - values={[pref]} 72 - onChange={newPref => 73 - mutate({ 74 - label: identifier, 75 - visibility: newPref[0] as LabelPreference, 76 - labelerDid: undefined, 77 - }) 78 - }> 79 - <ToggleButton.Button name="ignore" label={labelOptions.ignore}> 80 - {labelOptions.ignore} 81 - </ToggleButton.Button> 82 - <ToggleButton.Button name="warn" label={labelOptions.warn}> 83 - {labelOptions.warn} 84 - </ToggleButton.Button> 85 - <ToggleButton.Button name="hide" label={labelOptions.hide}> 86 - {labelOptions.hide} 87 - </ToggleButton.Button> 88 - </ToggleButton.Group> 89 - )} 90 - </View> 91 - </View> 92 - ) 93 - }
+294
src/components/moderation/LabelPreference.tsx
··· 1 + import React from 'react' 2 + import {View} from 'react-native' 3 + import {InterpretedLabelValueDefinition, LabelPreference} from '@atproto/api' 4 + import {useLingui} from '@lingui/react' 5 + import {msg, Trans} from '@lingui/macro' 6 + 7 + import {useGlobalLabelStrings} from '#/lib/moderation/useGlobalLabelStrings' 8 + import { 9 + usePreferencesQuery, 10 + usePreferencesSetContentLabelMutation, 11 + } from '#/state/queries/preferences' 12 + import {useLabelBehaviorDescription} from '#/lib/moderation/useLabelBehaviorDescription' 13 + import {getLabelStrings} from '#/lib/moderation/useLabelInfo' 14 + 15 + import {useTheme, atoms as a, useBreakpoints} from '#/alf' 16 + import {Text} from '#/components/Typography' 17 + import {InlineLink} from '#/components/Link' 18 + import {CircleInfo_Stroke2_Corner0_Rounded as CircleInfo} from '../icons/CircleInfo' 19 + import * as ToggleButton from '#/components/forms/ToggleButton' 20 + 21 + export function Outer({children}: React.PropsWithChildren<{}>) { 22 + return ( 23 + <View 24 + style={[ 25 + a.flex_row, 26 + a.gap_md, 27 + a.px_lg, 28 + a.py_lg, 29 + a.justify_between, 30 + a.flex_wrap, 31 + ]}> 32 + {children} 33 + </View> 34 + ) 35 + } 36 + 37 + export function Content({ 38 + children, 39 + name, 40 + description, 41 + }: React.PropsWithChildren<{ 42 + name: string 43 + description: string 44 + }>) { 45 + const t = useTheme() 46 + const {gtPhone} = useBreakpoints() 47 + 48 + return ( 49 + <View style={[a.gap_xs, a.flex_1]}> 50 + <Text style={[a.font_bold, gtPhone ? a.text_sm : a.text_md]}>{name}</Text> 51 + <Text style={[t.atoms.text_contrast_medium, a.leading_snug]}> 52 + {description} 53 + </Text> 54 + 55 + {children} 56 + </View> 57 + ) 58 + } 59 + 60 + export function Buttons({ 61 + name, 62 + values, 63 + onChange, 64 + ignoreLabel, 65 + warnLabel, 66 + hideLabel, 67 + }: { 68 + name: string 69 + values: ToggleButton.GroupProps['values'] 70 + onChange: ToggleButton.GroupProps['onChange'] 71 + ignoreLabel?: string 72 + warnLabel?: string 73 + hideLabel?: string 74 + }) { 75 + const {_} = useLingui() 76 + const {gtPhone} = useBreakpoints() 77 + 78 + return ( 79 + <View style={[{minHeight: 35}, gtPhone ? undefined : a.w_full]}> 80 + <ToggleButton.Group 81 + label={_( 82 + msg`Configure content filtering setting for category: ${name}`, 83 + )} 84 + values={values} 85 + onChange={onChange}> 86 + {ignoreLabel && ( 87 + <ToggleButton.Button name="ignore" label={ignoreLabel}> 88 + {ignoreLabel} 89 + </ToggleButton.Button> 90 + )} 91 + {warnLabel && ( 92 + <ToggleButton.Button name="warn" label={warnLabel}> 93 + {warnLabel} 94 + </ToggleButton.Button> 95 + )} 96 + {hideLabel && ( 97 + <ToggleButton.Button name="hide" label={hideLabel}> 98 + {hideLabel} 99 + </ToggleButton.Button> 100 + )} 101 + </ToggleButton.Group> 102 + </View> 103 + ) 104 + } 105 + 106 + /** 107 + * For use on the global Moderation screen to set prefs for a "global" label, 108 + * not scoped to a single labeler. 109 + */ 110 + export function GlobalLabelPreference({ 111 + labelDefinition, 112 + disabled, 113 + }: { 114 + labelDefinition: InterpretedLabelValueDefinition 115 + disabled?: boolean 116 + }) { 117 + const {_} = useLingui() 118 + 119 + const {identifier} = labelDefinition 120 + const {data: preferences} = usePreferencesQuery() 121 + const {mutate, variables} = usePreferencesSetContentLabelMutation() 122 + const savedPref = preferences?.moderationPrefs.labels[identifier] 123 + const pref = variables?.visibility ?? savedPref ?? 'warn' 124 + 125 + const allLabelStrings = useGlobalLabelStrings() 126 + const labelStrings = 127 + labelDefinition.identifier in allLabelStrings 128 + ? allLabelStrings[labelDefinition.identifier] 129 + : { 130 + name: labelDefinition.identifier, 131 + description: `Labeled "${labelDefinition.identifier}"`, 132 + } 133 + 134 + const labelOptions = { 135 + hide: _(msg`Hide`), 136 + warn: _(msg`Warn`), 137 + ignore: _(msg`Show`), 138 + } 139 + 140 + return ( 141 + <Outer> 142 + <Content 143 + name={labelStrings.name} 144 + description={labelStrings.description} 145 + /> 146 + {!disabled && ( 147 + <Buttons 148 + name={labelStrings.name.toLowerCase()} 149 + values={[pref]} 150 + onChange={values => { 151 + mutate({ 152 + label: identifier, 153 + visibility: values[0] as LabelPreference, 154 + labelerDid: undefined, 155 + }) 156 + }} 157 + ignoreLabel={labelOptions.ignore} 158 + warnLabel={labelOptions.warn} 159 + hideLabel={labelOptions.hide} 160 + /> 161 + )} 162 + </Outer> 163 + ) 164 + } 165 + 166 + /** 167 + * For use on individual labeler pages 168 + */ 169 + export function LabelerLabelPreference({ 170 + labelDefinition, 171 + disabled, 172 + labelerDid, 173 + }: { 174 + labelDefinition: InterpretedLabelValueDefinition 175 + disabled?: boolean 176 + labelerDid?: string 177 + }) { 178 + const {i18n} = useLingui() 179 + const t = useTheme() 180 + const {gtPhone} = useBreakpoints() 181 + 182 + const isGlobalLabel = !labelDefinition.definedBy 183 + const {identifier} = labelDefinition 184 + const {data: preferences} = usePreferencesQuery() 185 + const {mutate, variables} = usePreferencesSetContentLabelMutation() 186 + const savedPref = 187 + labelerDid && !isGlobalLabel 188 + ? preferences?.moderationPrefs.labelers.find(l => l.did === labelerDid) 189 + ?.labels[identifier] 190 + : preferences?.moderationPrefs.labels[identifier] 191 + const pref = 192 + variables?.visibility ?? 193 + savedPref ?? 194 + labelDefinition.defaultSetting ?? 195 + 'warn' 196 + 197 + // does the 'warn' setting make sense for this label? 198 + const canWarn = !( 199 + labelDefinition.blurs === 'none' && labelDefinition.severity === 'none' 200 + ) 201 + // is this label adult only? 202 + const adultOnly = labelDefinition.flags.includes('adult') 203 + // is this label disabled because it's adult only? 204 + const adultDisabled = 205 + adultOnly && !preferences?.moderationPrefs.adultContentEnabled 206 + // are there any reasons we cant configure this label here? 207 + const cantConfigure = isGlobalLabel || adultDisabled 208 + const showConfig = !disabled && (gtPhone || !cantConfigure) 209 + 210 + // adjust the pref based on whether warn is available 211 + let prefAdjusted = pref 212 + if (adultDisabled) { 213 + prefAdjusted = 'hide' 214 + } else if (!canWarn && pref === 'warn') { 215 + prefAdjusted = 'ignore' 216 + } 217 + 218 + // grab localized descriptions of the label and its settings 219 + const currentPrefLabel = useLabelBehaviorDescription( 220 + labelDefinition, 221 + prefAdjusted, 222 + ) 223 + const hideLabel = useLabelBehaviorDescription(labelDefinition, 'hide') 224 + const warnLabel = useLabelBehaviorDescription(labelDefinition, 'warn') 225 + const ignoreLabel = useLabelBehaviorDescription(labelDefinition, 'ignore') 226 + const globalLabelStrings = useGlobalLabelStrings() 227 + const labelStrings = getLabelStrings( 228 + i18n.locale, 229 + globalLabelStrings, 230 + labelDefinition, 231 + ) 232 + 233 + return ( 234 + <Outer> 235 + <Content name={labelStrings.name} description={labelStrings.description}> 236 + {cantConfigure && ( 237 + <View style={[a.flex_row, a.gap_xs, a.align_center, a.mt_xs]}> 238 + <CircleInfo size="sm" fill={t.atoms.text_contrast_high.color} /> 239 + 240 + <Text 241 + style={[t.atoms.text_contrast_medium, a.font_semibold, a.italic]}> 242 + {adultDisabled ? ( 243 + <Trans>Adult content is disabled.</Trans> 244 + ) : isGlobalLabel ? ( 245 + <Trans> 246 + Configured in{' '} 247 + <InlineLink to="/moderation" style={a.text_sm}> 248 + moderation settings 249 + </InlineLink> 250 + . 251 + </Trans> 252 + ) : null} 253 + </Text> 254 + </View> 255 + )} 256 + </Content> 257 + 258 + {showConfig && ( 259 + <View style={[gtPhone ? undefined : a.w_full]}> 260 + {cantConfigure ? ( 261 + <View 262 + style={[ 263 + {minHeight: 35}, 264 + a.px_md, 265 + a.py_md, 266 + a.rounded_sm, 267 + a.border, 268 + t.atoms.border_contrast_low, 269 + ]}> 270 + <Text style={[a.font_bold, t.atoms.text_contrast_low]}> 271 + {currentPrefLabel} 272 + </Text> 273 + </View> 274 + ) : ( 275 + <Buttons 276 + name={labelStrings.name.toLowerCase()} 277 + values={[pref]} 278 + onChange={values => { 279 + mutate({ 280 + label: identifier, 281 + visibility: values[0] as LabelPreference, 282 + labelerDid, 283 + }) 284 + }} 285 + ignoreLabel={ignoreLabel} 286 + warnLabel={canWarn ? warnLabel : undefined} 287 + hideLabel={hideLabel} 288 + /> 289 + )} 290 + </View> 291 + )} 292 + </Outer> 293 + ) 294 + }
-177
src/components/moderation/ModerationLabelPref.tsx
··· 1 - import React from 'react' 2 - import {View} from 'react-native' 3 - import {InterpretedLabelValueDefinition, LabelPreference} from '@atproto/api' 4 - import {useLingui} from '@lingui/react' 5 - import {msg, Trans} from '@lingui/macro' 6 - 7 - import {useGlobalLabelStrings} from '#/lib/moderation/useGlobalLabelStrings' 8 - import {useLabelBehaviorDescription} from '#/lib/moderation/useLabelBehaviorDescription' 9 - import { 10 - usePreferencesQuery, 11 - usePreferencesSetContentLabelMutation, 12 - } from '#/state/queries/preferences' 13 - import {getLabelStrings} from '#/lib/moderation/useLabelInfo' 14 - 15 - import {useTheme, atoms as a, useBreakpoints} from '#/alf' 16 - import {Text} from '#/components/Typography' 17 - import {InlineLink} from '#/components/Link' 18 - import {CircleInfo_Stroke2_Corner0_Rounded as CircleInfo} from '../icons/CircleInfo' 19 - import * as ToggleButton from '#/components/forms/ToggleButton' 20 - 21 - export function ModerationLabelPref({ 22 - labelValueDefinition, 23 - labelerDid, 24 - disabled, 25 - }: { 26 - labelValueDefinition: InterpretedLabelValueDefinition 27 - labelerDid: string | undefined 28 - disabled?: boolean 29 - }) { 30 - const {_, i18n} = useLingui() 31 - const t = useTheme() 32 - const {gtPhone} = useBreakpoints() 33 - 34 - const isGlobalLabel = !labelValueDefinition.definedBy 35 - const {identifier} = labelValueDefinition 36 - const {data: preferences} = usePreferencesQuery() 37 - const {mutate, variables} = usePreferencesSetContentLabelMutation() 38 - const savedPref = 39 - labelerDid && !isGlobalLabel 40 - ? preferences?.moderationPrefs.labelers.find(l => l.did === labelerDid) 41 - ?.labels[identifier] 42 - : preferences?.moderationPrefs.labels[identifier] 43 - const pref = 44 - variables?.visibility ?? 45 - savedPref ?? 46 - labelValueDefinition.defaultSetting ?? 47 - 'warn' 48 - 49 - // does the 'warn' setting make sense for this label? 50 - const canWarn = !( 51 - labelValueDefinition.blurs === 'none' && 52 - labelValueDefinition.severity === 'none' 53 - ) 54 - // is this label adult only? 55 - const adultOnly = labelValueDefinition.flags.includes('adult') 56 - // is this label disabled because it's adult only? 57 - const adultDisabled = 58 - adultOnly && !preferences?.moderationPrefs.adultContentEnabled 59 - // are there any reasons we cant configure this label here? 60 - const cantConfigure = isGlobalLabel || adultDisabled 61 - const showConfig = !disabled && (gtPhone || !cantConfigure) 62 - 63 - // adjust the pref based on whether warn is available 64 - let prefAdjusted = pref 65 - if (adultDisabled) { 66 - prefAdjusted = 'hide' 67 - } else if (!canWarn && pref === 'warn') { 68 - prefAdjusted = 'ignore' 69 - } 70 - 71 - // grab localized descriptions of the label and its settings 72 - const currentPrefLabel = useLabelBehaviorDescription( 73 - labelValueDefinition, 74 - prefAdjusted, 75 - ) 76 - const hideLabel = useLabelBehaviorDescription(labelValueDefinition, 'hide') 77 - const warnLabel = useLabelBehaviorDescription(labelValueDefinition, 'warn') 78 - const ignoreLabel = useLabelBehaviorDescription( 79 - labelValueDefinition, 80 - 'ignore', 81 - ) 82 - const globalLabelStrings = useGlobalLabelStrings() 83 - const labelStrings = getLabelStrings( 84 - i18n.locale, 85 - globalLabelStrings, 86 - labelValueDefinition, 87 - ) 88 - 89 - return ( 90 - <View 91 - style={[ 92 - a.flex_row, 93 - a.gap_md, 94 - a.px_lg, 95 - a.py_lg, 96 - a.justify_between, 97 - a.flex_wrap, 98 - ]}> 99 - <View style={[a.gap_xs, a.flex_1]}> 100 - <Text style={[a.font_bold, gtPhone ? a.text_sm : a.text_md]}> 101 - {labelStrings.name} 102 - </Text> 103 - <Text style={[t.atoms.text_contrast_medium, a.leading_snug]}> 104 - {labelStrings.description} 105 - </Text> 106 - 107 - {cantConfigure && ( 108 - <View style={[a.flex_row, a.gap_xs, a.align_center, a.mt_xs]}> 109 - <CircleInfo size="sm" fill={t.atoms.text_contrast_high.color} /> 110 - 111 - <Text 112 - style={[t.atoms.text_contrast_medium, a.font_semibold, a.italic]}> 113 - {adultDisabled ? ( 114 - <Trans>Adult content is disabled.</Trans> 115 - ) : isGlobalLabel ? ( 116 - <Trans> 117 - Configured in{' '} 118 - <InlineLink to="/moderation" style={a.text_sm}> 119 - moderation settings 120 - </InlineLink> 121 - . 122 - </Trans> 123 - ) : null} 124 - </Text> 125 - </View> 126 - )} 127 - </View> 128 - 129 - {showConfig && ( 130 - <View style={[gtPhone ? undefined : a.w_full]}> 131 - {cantConfigure ? ( 132 - <View 133 - style={[ 134 - {minHeight: 35}, 135 - a.px_md, 136 - a.py_md, 137 - a.rounded_sm, 138 - a.border, 139 - t.atoms.border_contrast_low, 140 - ]}> 141 - <Text style={[a.font_bold, t.atoms.text_contrast_low]}> 142 - {currentPrefLabel} 143 - </Text> 144 - </View> 145 - ) : ( 146 - <View style={[{minHeight: 35}]}> 147 - <ToggleButton.Group 148 - label={_( 149 - msg`Configure content filtering setting for category: ${labelStrings.name.toLowerCase()}`, 150 - )} 151 - values={[prefAdjusted]} 152 - onChange={newPref => 153 - mutate({ 154 - label: identifier, 155 - visibility: newPref[0] as LabelPreference, 156 - labelerDid, 157 - }) 158 - }> 159 - <ToggleButton.Button name="ignore" label={ignoreLabel}> 160 - {ignoreLabel} 161 - </ToggleButton.Button> 162 - {canWarn && ( 163 - <ToggleButton.Button name="warn" label={warnLabel}> 164 - {warnLabel} 165 - </ToggleButton.Button> 166 - )} 167 - <ToggleButton.Button name="hide" label={hideLabel}> 168 - {hideLabel} 169 - </ToggleButton.Button> 170 - </ToggleButton.Group> 171 - </View> 172 - )} 173 - </View> 174 - )} 175 - </View> 176 - ) 177 - }
+6 -6
src/screens/Moderation/index.tsx
··· 41 41 import {Button, ButtonText} from '#/components/Button' 42 42 import {Loader} from '#/components/Loader' 43 43 import * as LabelingService from '#/components/LabelingServiceCard' 44 - import {GlobalModerationLabelPref} from '#/components/moderation/GlobalModerationLabelPref' 44 + import {GlobalLabelPreference} from '#/components/moderation/LabelPreference' 45 45 import {useGlobalDialogsControlContext} from '#/components/dialogs/Context' 46 46 import {Props as SVGIconProps} from '#/components/icons/common' 47 47 import {BirthDateSettingsDialog} from '#/components/dialogs/BirthDateSettings' ··· 352 352 )} 353 353 {!isUnderage && adultContentEnabled && ( 354 354 <> 355 - <GlobalModerationLabelPref labelValueDefinition={LABELS.porn} /> 355 + <GlobalLabelPreference labelDefinition={LABELS.porn} /> 356 356 <Divider /> 357 - <GlobalModerationLabelPref labelValueDefinition={LABELS.sexual} /> 357 + <GlobalLabelPreference labelDefinition={LABELS.sexual} /> 358 358 <Divider /> 359 - <GlobalModerationLabelPref 360 - labelValueDefinition={LABELS['graphic-media']} 359 + <GlobalLabelPreference 360 + labelDefinition={LABELS['graphic-media']} 361 361 /> 362 362 <Divider /> 363 363 </> 364 364 )} 365 - <GlobalModerationLabelPref labelValueDefinition={LABELS.nudity} /> 365 + <GlobalLabelPreference labelDefinition={LABELS.nudity} /> 366 366 </View> 367 367 </View> 368 368
+3 -3
src/screens/Profile/Sections/Labels.tsx
··· 23 23 import {Divider} from '#/components/Divider' 24 24 import {CenteredView, ScrollView} from '#/view/com/util/Views' 25 25 import {ErrorState} from '../ErrorState' 26 - import {ModerationLabelPref} from '#/components/moderation/ModerationLabelPref' 26 + import {LabelerLabelPreference} from '#/components/moderation/LabelPreference' 27 27 import {CircleInfo_Stroke2_Corner0_Rounded as CircleInfo} from '#/components/icons/CircleInfo' 28 28 29 29 interface LabelsSectionProps { ··· 197 197 return ( 198 198 <React.Fragment key={labelDef.identifier}> 199 199 {i !== 0 && <Divider />} 200 - <ModerationLabelPref 200 + <LabelerLabelPreference 201 201 disabled={isSubscribed ? undefined : true} 202 - labelValueDefinition={labelDef} 202 + labelDefinition={labelDef} 203 203 labelerDid={labelerInfo.creator.did} 204 204 /> 205 205 </React.Fragment>
+9 -9
src/view/com/auth/SplashScreen.tsx
··· 1 1 import React from 'react' 2 2 import {View} from 'react-native' 3 + import RNPickerSelect, {PickerSelectProps} from 'react-native-picker-select' 3 4 import {useSafeAreaInsets} from 'react-native-safe-area-context' 4 - 5 - import {ErrorBoundary} from 'view/com/util/ErrorBoundary' 6 - import {CenteredView} from '../util/Views' 7 - import {Trans, msg} from '@lingui/macro' 5 + import {msg, Trans} from '@lingui/macro' 8 6 import {useLingui} from '@lingui/react' 9 - import {Logo} from '#/view/icons/Logo' 10 - import {Logotype} from '#/view/icons/Logotype' 11 - import RNPickerSelect, {PickerSelectProps} from 'react-native-picker-select' 7 + 12 8 import {sanitizeAppLanguageSetting} from '#/locale/helpers' 9 + import {APP_LANGUAGES} from '#/locale/languages' 13 10 import {useLanguagePrefs, useLanguagePrefsApi} from '#/state/preferences' 14 - import {APP_LANGUAGES} from '#/locale/languages' 11 + import {Logo} from '#/view/icons/Logo' 12 + import {Logotype} from '#/view/icons/Logotype' 13 + import {ErrorBoundary} from 'view/com/util/ErrorBoundary' 15 14 import {atoms as a, useTheme} from '#/alf' 16 - import {Text} from '#/components/Typography' 17 15 import {Button, ButtonText} from '#/components/Button' 18 16 import {ChevronBottom_Stroke2_Corner0_Rounded as ChevronDown} from '#/components/icons/Chevron' 17 + import {Text} from '#/components/Typography' 18 + import {CenteredView} from '../util/Views' 19 19 20 20 export const SplashScreen = ({ 21 21 onPressSignin,
+10 -9
src/view/com/auth/SplashScreen.web.tsx
··· 1 1 import React from 'react' 2 - import {View, Pressable} from 'react-native' 2 + import {Pressable, View} from 'react-native' 3 3 import {FontAwesomeIcon} from '@fortawesome/react-native-fontawesome' 4 - import {ErrorBoundary} from 'view/com/util/ErrorBoundary' 5 - import {CenteredView} from '../util/Views' 4 + import {msg, Trans} from '@lingui/macro' 5 + import {useLingui} from '@lingui/react' 6 + 7 + import {sanitizeAppLanguageSetting} from '#/locale/helpers' 8 + import {APP_LANGUAGES} from '#/locale/languages' 9 + import {useLanguagePrefs, useLanguagePrefsApi} from '#/state/preferences' 6 10 import {useWebMediaQueries} from 'lib/hooks/useWebMediaQueries' 7 - import {Trans, msg} from '@lingui/macro' 8 11 import {Logo} from '#/view/icons/Logo' 9 12 import {Logotype} from '#/view/icons/Logotype' 10 - import {useLingui} from '@lingui/react' 11 - import {sanitizeAppLanguageSetting} from '#/locale/helpers' 12 - import {useLanguagePrefs, useLanguagePrefsApi} from '#/state/preferences' 13 - import {APP_LANGUAGES} from '#/locale/languages' 13 + import {ErrorBoundary} from 'view/com/util/ErrorBoundary' 14 14 import {atoms as a, useTheme} from '#/alf' 15 15 import {Button, ButtonText} from '#/components/Button' 16 16 import {ChevronBottom_Stroke2_Corner0_Rounded as ChevronDown} from '#/components/icons/Chevron' 17 + import {InlineLink} from '#/components/Link' 17 18 import {Text} from '#/components/Typography' 18 - import {InlineLink} from '#/components/Link' 19 + import {CenteredView} from '../util/Views' 19 20 20 21 export const SplashScreen = ({ 21 22 onDismiss,
+16 -16
src/view/com/post-thread/PostThread.tsx
··· 1 1 import React, {useEffect, useRef} from 'react' 2 2 import {StyleSheet, useWindowDimensions, View} from 'react-native' 3 3 import {AppBskyFeedDefs} from '@atproto/api' 4 - import {Trans, msg} from '@lingui/macro' 4 + import {msg, Trans} from '@lingui/macro' 5 5 import {useLingui} from '@lingui/react' 6 6 7 - import {List, ListMethods} from '../util/List' 8 - import {PostThreadItem} from './PostThreadItem' 9 - import {ComposePrompt} from '../composer/Prompt' 10 - import {ViewHeader} from '../util/ViewHeader' 11 - import {Text} from '../util/text/Text' 12 - import {usePalette} from 'lib/hooks/usePalette' 13 - import {useSetTitle} from 'lib/hooks/useSetTitle' 7 + import {moderatePost_wrapped as moderatePost} from '#/lib/moderatePost_wrapped' 8 + import {isAndroid, isNative, isWeb} from '#/platform/detection' 14 9 import { 10 + sortThread, 11 + ThreadBlocked, 15 12 ThreadNode, 16 - ThreadPost, 17 13 ThreadNotFound, 18 - ThreadBlocked, 14 + ThreadPost, 19 15 usePostThreadQuery, 20 - sortThread, 21 16 } from '#/state/queries/post-thread' 22 - import {useWebMediaQueries} from 'lib/hooks/useWebMediaQueries' 23 - import {sanitizeDisplayName} from 'lib/strings/display-names' 24 17 import { 25 18 useModerationOpts, 26 19 usePreferencesQuery, 27 20 } from '#/state/queries/preferences' 28 21 import {useSession} from '#/state/session' 29 - import {isAndroid, isNative, isWeb} from '#/platform/detection' 30 - import {moderatePost_wrapped as moderatePost} from '#/lib/moderatePost_wrapped' 31 22 import {useInitialNumToRender} from 'lib/hooks/useInitialNumToRender' 32 - import {ListFooter, ListMaybePlaceholder} from '#/components/Lists' 23 + import {usePalette} from 'lib/hooks/usePalette' 24 + import {useSetTitle} from 'lib/hooks/useSetTitle' 25 + import {useWebMediaQueries} from 'lib/hooks/useWebMediaQueries' 26 + import {sanitizeDisplayName} from 'lib/strings/display-names' 33 27 import {cleanError} from 'lib/strings/errors' 28 + import {ListFooter, ListMaybePlaceholder} from '#/components/Lists' 29 + import {ComposePrompt} from '../composer/Prompt' 30 + import {List, ListMethods} from '../util/List' 31 + import {Text} from '../util/text/Text' 32 + import {ViewHeader} from '../util/ViewHeader' 33 + import {PostThreadItem} from './PostThreadItem' 34 34 35 35 // FlatList maintainVisibleContentPosition breaks if too many items 36 36 // are prepended. This seems to be an optimal number based on *shrug*.