* 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
parent
bc55241c9a
commit
696bffe832
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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>
|
||||||
)}
|
)}
|
||||||
|
|
|
@ -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,
|
||||||
},
|
},
|
||||||
|
|
Loading…
Reference in New Issue