Add alt text validation option to user preferences (supersedes #913) (#914)

* Add alt text validation option to user preferences

* Fix typos/linting issues

* Update accessibility setting to match styles

* Update the required alt text reminder to go away once it's added

---------

Co-authored-by: Emma Fuller <emma@emmafuller.dev>
zio/stable
Paul Frazee 2023-07-03 15:58:07 -05:00 committed by GitHub
parent bc55241c9a
commit 696bffe832
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 76 additions and 3 deletions

View File

@ -23,6 +23,10 @@ export class GalleryModel {
return this.images.length return this.images.length
} }
get needsAltText() {
return this.images.some(image => image.altText.trim() === '')
}
async add(image_: Omit<RNImage, 'size'>) { async add(image_: Omit<RNImage, 'size'>) {
if (this.size >= 4) { if (this.size >= 4) {
return return

View File

@ -53,6 +53,7 @@ export class PreferencesModel {
homeFeedRepliesThreshold: number = 2 homeFeedRepliesThreshold: number = 2
homeFeedRepostsEnabled: boolean = true homeFeedRepostsEnabled: boolean = true
homeFeedQuotePostsEnabled: boolean = true homeFeedQuotePostsEnabled: boolean = true
requireAltTextEnabled: boolean = false
// used to linearize async modifications to state // used to linearize async modifications to state
lock = new AwaitLock() lock = new AwaitLock()
@ -72,6 +73,7 @@ export class PreferencesModel {
homeFeedRepliesThreshold: this.homeFeedRepliesThreshold, homeFeedRepliesThreshold: this.homeFeedRepliesThreshold,
homeFeedRepostsEnabled: this.homeFeedRepostsEnabled, homeFeedRepostsEnabled: this.homeFeedRepostsEnabled,
homeFeedQuotePostsEnabled: this.homeFeedQuotePostsEnabled, homeFeedQuotePostsEnabled: this.homeFeedQuotePostsEnabled,
requireAltTextEnabled: this.requireAltTextEnabled,
} }
} }
@ -152,6 +154,13 @@ export class PreferencesModel {
) { ) {
this.homeFeedQuotePostsEnabled = v.homeFeedQuotePostsEnabled this.homeFeedQuotePostsEnabled = v.homeFeedQuotePostsEnabled
} }
// check if requiring alt text is enabled in preferences, then hydrate
if (
hasProp(v, 'requireAltTextEnabled') &&
typeof v.requireAltTextEnabled === 'boolean'
) {
this.requireAltTextEnabled = v.requireAltTextEnabled
}
} }
} }
@ -467,4 +476,8 @@ export class PreferencesModel {
toggleHomeFeedQuotePostsEnabled() { toggleHomeFeedQuotePostsEnabled() {
this.homeFeedQuotePostsEnabled = !this.homeFeedQuotePostsEnabled this.homeFeedQuotePostsEnabled = !this.homeFeedQuotePostsEnabled
} }
toggleRequireAltTextEnabled() {
this.requireAltTextEnabled = !this.requireAltTextEnabled
}
} }

View File

@ -156,6 +156,9 @@ export const ComposePost = observer(function ComposePost({
if (isProcessing || rt.graphemeLength > MAX_GRAPHEME_LENGTH) { if (isProcessing || rt.graphemeLength > MAX_GRAPHEME_LENGTH) {
return return
} }
if (store.preferences.requireAltTextEnabled && gallery.needsAltText) {
return
}
setError('') setError('')
@ -220,8 +223,14 @@ export const ComposePost = observer(function ComposePost({
) )
const canPost = useMemo( const canPost = useMemo(
() => graphemeLength <= MAX_GRAPHEME_LENGTH, () =>
[graphemeLength], graphemeLength <= MAX_GRAPHEME_LENGTH &&
(!store.preferences.requireAltTextEnabled || !gallery.needsAltText),
[
graphemeLength,
store.preferences.requireAltTextEnabled,
gallery.needsAltText,
],
) )
const selectTextInputPlaceholder = replyTo ? 'Write your reply' : `What's up?` const selectTextInputPlaceholder = replyTo ? 'Write your reply' : `What's up?`
@ -282,6 +291,20 @@ export const ComposePost = observer(function ComposePost({
<Text style={pal.text}>{processingState}</Text> <Text style={pal.text}>{processingState}</Text>
</View> </View>
) : undefined} ) : undefined}
{store.preferences.requireAltTextEnabled && gallery.needsAltText && (
<View style={[styles.reminderLine, pal.viewLight]}>
<View style={styles.errorIcon}>
<FontAwesomeIcon
icon="exclamation"
style={{color: colors.red4}}
size={10}
/>
</View>
<Text style={[pal.text, s.flex1]}>
One or more images is missing alt text.
</Text>
</View>
)}
{error !== '' && ( {error !== '' && (
<View style={styles.errorLine}> <View style={styles.errorLine}>
<View style={styles.errorIcon}> <View style={styles.errorIcon}>
@ -415,6 +438,15 @@ const styles = StyleSheet.create({
paddingVertical: 6, paddingVertical: 6,
marginVertical: 6, marginVertical: 6,
}, },
reminderLine: {
flexDirection: 'row',
alignItems: 'center',
borderRadius: 6,
marginHorizontal: 15,
paddingHorizontal: 8,
paddingVertical: 6,
marginBottom: 6,
},
errorIcon: { errorIcon: {
borderWidth: 1, borderWidth: 1,
borderColor: colors.red4, borderColor: colors.red4,

View File

@ -5,18 +5,21 @@ import {Button, ButtonType} from './Button'
import {useTheme} from 'lib/ThemeContext' import {useTheme} from 'lib/ThemeContext'
import {choose} from 'lib/functions' import {choose} from 'lib/functions'
import {colors} from 'lib/styles' import {colors} from 'lib/styles'
import {TypographyVariant} from 'lib/ThemeContext'
export function ToggleButton({ export function ToggleButton({
type = 'default-light', type = 'default-light',
label, label,
isSelected, isSelected,
style, style,
labelType,
onPress, onPress,
}: { }: {
type?: ButtonType type?: ButtonType
label: string label: string
isSelected: boolean isSelected: boolean
style?: StyleProp<ViewStyle> style?: StyleProp<ViewStyle>
labelType?: TypographyVariant
onPress?: () => void onPress?: () => void
}) { }) {
const theme = useTheme() const theme = useTheme()
@ -143,7 +146,7 @@ export function ToggleButton({
/> />
</View> </View>
{label === '' ? null : ( {label === '' ? null : (
<Text type="button" style={[labelStyle, styles.label]}> <Text type={labelType || 'button'} style={[labelStyle, styles.label]}>
{label} {label}
</Text> </Text>
)} )}

View File

@ -330,6 +330,22 @@ export const SettingsScreen = withAuthRequired(
</TouchableOpacity> </TouchableOpacity>
<View style={styles.spacer20} /> <View style={styles.spacer20} />
<Text type="xl-bold" style={[pal.text, styles.heading]}>
Accessibility
</Text>
<View style={[pal.view, styles.toggleCard]}>
<ToggleButton
type="default-light"
label="Require alt text on images"
labelType="lg"
isSelected={store.preferences.requireAltTextEnabled}
onPress={store.preferences.toggleRequireAltTextEnabled}
/>
</View>
<View style={styles.spacer20} />
<Text type="xl-bold" style={[pal.text, styles.heading]}> <Text type="xl-bold" style={[pal.text, styles.heading]}>
Appearance Appearance
</Text> </Text>
@ -633,6 +649,11 @@ const styles = StyleSheet.create({
paddingHorizontal: 18, paddingHorizontal: 18,
marginBottom: 1, marginBottom: 1,
}, },
toggleCard: {
paddingVertical: 8,
paddingHorizontal: 6,
marginBottom: 1,
},
avi: { avi: {
marginRight: 12, marginRight: 12,
}, },