1
0
mirror of https://github.com/laurent22/joplin.git synced 2024-12-18 09:35:20 +02:00

Android: Accessibility: Improve voice typing dialog screen reader accessibility (#11428)

This commit is contained in:
Henry Heino 2024-11-22 02:47:46 -08:00 committed by GitHub
parent 5dfbb18838
commit db07bd208a
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

View File

@ -1,6 +1,6 @@
import * as React from 'react';
import { useState, useEffect, useCallback, useRef, useMemo } from 'react';
import { Banner, ActivityIndicator, Text } from 'react-native-paper';
import { Icon, ActivityIndicator, Text, Surface, Button } from 'react-native-paper';
import { _, languageName } from '@joplin/lib/locale';
import useAsyncEffect, { AsyncEffectEvent } from '@joplin/lib/hooks/useAsyncEffect';
import { IconSource } from 'react-native-paper/lib/typescript/components/Icon';
@ -9,6 +9,8 @@ import whisper from '../../services/voiceTyping/whisper';
import vosk from '../../services/voiceTyping/vosk';
import { AppState } from '../../utils/types';
import { connect } from 'react-redux';
import { View, StyleSheet } from 'react-native';
import AccessibleView from '../accessibility/AccessibleView';
interface Props {
locale: string;
@ -79,6 +81,30 @@ const useWhisper = ({ locale, provider, onSetPreview, onText }: UseVoiceTypingPr
return [error, mustDownloadModel, voiceTyping];
};
const styles = StyleSheet.create({
container: {
marginHorizontal: 1,
width: '100%',
maxWidth: 680,
alignSelf: 'center',
},
contentWrapper: {
flexDirection: 'row',
},
iconWrapper: {
margin: 8,
marginTop: 16,
},
content: {
marginTop: 16,
marginHorizontal: 8,
},
actionContainer: {
flexDirection: 'row',
justifyContent: 'flex-end',
},
});
const VoiceTypingDialog: React.FC<Props> = props => {
const [recorderState, setRecorderState] = useState<RecorderState>(RecorderState.Loading);
const [preview, setPreview] = useState<string>('');
@ -142,22 +168,44 @@ const VoiceTypingDialog: React.FC<Props> = props => {
return <Text variant='labelSmall'>{preview}</Text>;
};
const headerAndStatus = <Text variant='bodyMedium'>{`${_('Voice typing...')}\n${renderContent()}`}</Text>;
return (
<Banner
visible={true}
icon={renderIcon()}
actions={[
{
label: _('Done'),
onPress: onDismiss,
},
]}
<Surface>
<View style={styles.container}>
<View style={styles.contentWrapper}>
<View style={styles.iconWrapper}>
<Icon source={renderIcon()} size={40}/>
</View>
<View style={styles.content}>
<AccessibleView
// Auto-focus
refocusCounter={1}
aria-live='polite'
role='heading'
>
{headerAndStatus}
<Text>{'\n'}</Text>
<Text variant='bodyMedium'>
{_('Voice typing...')}
</Text>
</AccessibleView>
<Text
variant='bodyMedium'
// role="status" might fit better here. However, react-native
// doesn't seem to support it.
role='alert'
// Although on web, role=alert should imply aria-live=polite,
// this does not seem to be the case for React Native:
accessibilityLiveRegion='polite'
>{renderContent()}</Text>
{renderPreview()}
</Banner>
</View>
</View>
<View style={styles.actionContainer}>
<Button
onPress={onDismiss}
accessibilityHint={_('Ends voice typing')}
>{_('Done')}</Button>
</View>
</View>
</Surface>
);
};