From 696bffe832c8ce748f2e4cc31e82764a6afb5b66 Mon Sep 17 00:00:00 2001 From: Paul Frazee Date: Mon, 3 Jul 2023 15:58:07 -0500 Subject: [PATCH] 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 --- src/state/models/media/gallery.ts | 4 +++ src/state/models/ui/preferences.ts | 13 +++++++++ src/view/com/composer/Composer.tsx | 36 ++++++++++++++++++++++-- src/view/com/util/forms/ToggleButton.tsx | 5 +++- src/view/screens/Settings.tsx | 21 ++++++++++++++ 5 files changed, 76 insertions(+), 3 deletions(-) diff --git a/src/state/models/media/gallery.ts b/src/state/models/media/gallery.ts index e53e861e..1b22fadb 100644 --- a/src/state/models/media/gallery.ts +++ b/src/state/models/media/gallery.ts @@ -23,6 +23,10 @@ export class GalleryModel { return this.images.length } + get needsAltText() { + return this.images.some(image => image.altText.trim() === '') + } + async add(image_: Omit) { if (this.size >= 4) { return diff --git a/src/state/models/ui/preferences.ts b/src/state/models/ui/preferences.ts index 28c7c566..858225a6 100644 --- a/src/state/models/ui/preferences.ts +++ b/src/state/models/ui/preferences.ts @@ -53,6 +53,7 @@ export class PreferencesModel { homeFeedRepliesThreshold: number = 2 homeFeedRepostsEnabled: boolean = true homeFeedQuotePostsEnabled: boolean = true + requireAltTextEnabled: boolean = false // used to linearize async modifications to state lock = new AwaitLock() @@ -72,6 +73,7 @@ export class PreferencesModel { homeFeedRepliesThreshold: this.homeFeedRepliesThreshold, homeFeedRepostsEnabled: this.homeFeedRepostsEnabled, homeFeedQuotePostsEnabled: this.homeFeedQuotePostsEnabled, + requireAltTextEnabled: this.requireAltTextEnabled, } } @@ -152,6 +154,13 @@ export class PreferencesModel { ) { 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() { this.homeFeedQuotePostsEnabled = !this.homeFeedQuotePostsEnabled } + + toggleRequireAltTextEnabled() { + this.requireAltTextEnabled = !this.requireAltTextEnabled + } } diff --git a/src/view/com/composer/Composer.tsx b/src/view/com/composer/Composer.tsx index caece347..c6a9ecd4 100644 --- a/src/view/com/composer/Composer.tsx +++ b/src/view/com/composer/Composer.tsx @@ -156,6 +156,9 @@ export const ComposePost = observer(function ComposePost({ if (isProcessing || rt.graphemeLength > MAX_GRAPHEME_LENGTH) { return } + if (store.preferences.requireAltTextEnabled && gallery.needsAltText) { + return + } setError('') @@ -220,8 +223,14 @@ export const ComposePost = observer(function ComposePost({ ) 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?` @@ -282,6 +291,20 @@ export const ComposePost = observer(function ComposePost({ {processingState} ) : undefined} + {store.preferences.requireAltTextEnabled && gallery.needsAltText && ( + + + + + + One or more images is missing alt text. + + + )} {error !== '' && ( @@ -415,6 +438,15 @@ const styles = StyleSheet.create({ paddingVertical: 6, marginVertical: 6, }, + reminderLine: { + flexDirection: 'row', + alignItems: 'center', + borderRadius: 6, + marginHorizontal: 15, + paddingHorizontal: 8, + paddingVertical: 6, + marginBottom: 6, + }, errorIcon: { borderWidth: 1, borderColor: colors.red4, diff --git a/src/view/com/util/forms/ToggleButton.tsx b/src/view/com/util/forms/ToggleButton.tsx index 47620d0a..02be80b3 100644 --- a/src/view/com/util/forms/ToggleButton.tsx +++ b/src/view/com/util/forms/ToggleButton.tsx @@ -5,18 +5,21 @@ import {Button, ButtonType} from './Button' import {useTheme} from 'lib/ThemeContext' import {choose} from 'lib/functions' import {colors} from 'lib/styles' +import {TypographyVariant} from 'lib/ThemeContext' export function ToggleButton({ type = 'default-light', label, isSelected, style, + labelType, onPress, }: { type?: ButtonType label: string isSelected: boolean style?: StyleProp + labelType?: TypographyVariant onPress?: () => void }) { const theme = useTheme() @@ -143,7 +146,7 @@ export function ToggleButton({ /> {label === '' ? null : ( - + {label} )} diff --git a/src/view/screens/Settings.tsx b/src/view/screens/Settings.tsx index e1fb549b..0057841b 100644 --- a/src/view/screens/Settings.tsx +++ b/src/view/screens/Settings.tsx @@ -330,6 +330,22 @@ export const SettingsScreen = withAuthRequired( + + + Accessibility + + + + + + + Appearance @@ -633,6 +649,11 @@ const styles = StyleSheet.create({ paddingHorizontal: 18, marginBottom: 1, }, + toggleCard: { + paddingVertical: 8, + paddingHorizontal: 6, + marginBottom: 1, + }, avi: { marginRight: 12, },