mirror of
https://github.com/laurent22/joplin.git
synced 2024-11-27 08:21:03 +02:00
Mobile: Accessibility: Improve screen reader accessibility of the tag list (#11420)
This commit is contained in:
parent
5dcbf4ce4a
commit
c9608cf4a1
@ -766,6 +766,7 @@ packages/app-mobile/components/screens/UpgradeSyncTargetScreen.js
|
||||
packages/app-mobile/components/screens/dropbox-login.js
|
||||
packages/app-mobile/components/screens/encryption-config.js
|
||||
packages/app-mobile/components/screens/status.js
|
||||
packages/app-mobile/components/screens/tags.js
|
||||
packages/app-mobile/components/side-menu-content.js
|
||||
packages/app-mobile/components/testing/TestProviderStack.js
|
||||
packages/app-mobile/components/voiceTyping/VoiceTypingDialog.js
|
||||
|
1
.gitignore
vendored
1
.gitignore
vendored
@ -742,6 +742,7 @@ packages/app-mobile/components/screens/UpgradeSyncTargetScreen.js
|
||||
packages/app-mobile/components/screens/dropbox-login.js
|
||||
packages/app-mobile/components/screens/encryption-config.js
|
||||
packages/app-mobile/components/screens/status.js
|
||||
packages/app-mobile/components/screens/tags.js
|
||||
packages/app-mobile/components/side-menu-content.js
|
||||
packages/app-mobile/components/testing/TestProviderStack.js
|
||||
packages/app-mobile/components/voiceTyping/VoiceTypingDialog.js
|
||||
|
@ -1,114 +0,0 @@
|
||||
const React = require('react');
|
||||
|
||||
const { View, Text, FlatList, StyleSheet, TouchableOpacity } = require('react-native');
|
||||
const { connect } = require('react-redux');
|
||||
const Tag = require('@joplin/lib/models/Tag').default;
|
||||
const { themeStyle } = require('../global-style');
|
||||
const { ScreenHeader } = require('../ScreenHeader');
|
||||
const { _ } = require('@joplin/lib/locale');
|
||||
const { BaseScreenComponent } = require('../base-screen');
|
||||
|
||||
class TagsScreenComponent extends BaseScreenComponent {
|
||||
static navigationOptions() {
|
||||
return { header: null };
|
||||
}
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
|
||||
this.state = {
|
||||
tags: [],
|
||||
};
|
||||
|
||||
this.tagList_renderItem = this.tagList_renderItem.bind(this);
|
||||
this.tagList_keyExtractor = this.tagList_keyExtractor.bind(this);
|
||||
this.tagItem_press = this.tagItem_press.bind(this);
|
||||
}
|
||||
|
||||
styles() {
|
||||
if (this.styles_) return this.styles_;
|
||||
|
||||
const theme = themeStyle(this.props.themeId);
|
||||
|
||||
this.styles_ = StyleSheet.create({
|
||||
listItem: {
|
||||
flexDirection: 'row',
|
||||
borderBottomWidth: 1,
|
||||
borderBottomColor: theme.dividerColor,
|
||||
alignItems: 'flex-start',
|
||||
paddingLeft: theme.marginLeft,
|
||||
paddingRight: theme.marginRight,
|
||||
paddingTop: theme.itemMarginTop,
|
||||
paddingBottom: theme.itemMarginBottom,
|
||||
},
|
||||
listItemText: {
|
||||
flex: 1,
|
||||
color: theme.color,
|
||||
fontSize: theme.fontSize,
|
||||
},
|
||||
});
|
||||
|
||||
return this.styles_;
|
||||
}
|
||||
|
||||
tagItem_press(event) {
|
||||
this.props.dispatch({ type: 'SIDE_MENU_CLOSE' });
|
||||
|
||||
this.props.dispatch({
|
||||
type: 'NAV_GO',
|
||||
routeName: 'Notes',
|
||||
tagId: event.id,
|
||||
});
|
||||
}
|
||||
|
||||
tagList_renderItem(event) {
|
||||
const tag = event.item;
|
||||
return (
|
||||
<TouchableOpacity
|
||||
onPress={() => {
|
||||
this.tagItem_press({ id: tag.id });
|
||||
}}
|
||||
>
|
||||
<View style={this.styles().listItem}>
|
||||
<Text style={this.styles().listItemText}>{tag.title}</Text>
|
||||
</View>
|
||||
</TouchableOpacity>
|
||||
);
|
||||
}
|
||||
|
||||
tagList_keyExtractor(item) {
|
||||
return item.id;
|
||||
}
|
||||
|
||||
async componentDidMount() {
|
||||
const tags = await Tag.allWithNotes();
|
||||
tags.sort((a, b) => {
|
||||
return a.title.toLowerCase() < b.title.toLowerCase() ? -1 : +1;
|
||||
});
|
||||
this.setState({ tags: tags });
|
||||
}
|
||||
|
||||
render() {
|
||||
const theme = themeStyle(this.props.themeId);
|
||||
|
||||
const rootStyle = {
|
||||
flex: 1,
|
||||
backgroundColor: theme.backgroundColor,
|
||||
};
|
||||
|
||||
return (
|
||||
<View style={rootStyle}>
|
||||
<ScreenHeader title={_('Tags')} parentComponent={this} showSearchButton={false} />
|
||||
<FlatList style={{ flex: 1 }} data={this.state.tags} renderItem={this.tagList_renderItem} keyExtractor={this.tagList_keyExtractor} />
|
||||
</View>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
const TagsScreen = connect(state => {
|
||||
return {
|
||||
themeId: state.settings.theme,
|
||||
};
|
||||
})(TagsScreenComponent);
|
||||
|
||||
module.exports = { TagsScreen };
|
100
packages/app-mobile/components/screens/tags.tsx
Normal file
100
packages/app-mobile/components/screens/tags.tsx
Normal file
@ -0,0 +1,100 @@
|
||||
import * as React from 'react';
|
||||
|
||||
import { View, Text, FlatList, StyleSheet, TouchableOpacity } from 'react-native';
|
||||
import { connect } from 'react-redux';
|
||||
import Tag from '@joplin/lib/models/Tag';
|
||||
import { themeStyle } from '../global-style';
|
||||
import { ScreenHeader } from '../ScreenHeader';
|
||||
import { _ } from '@joplin/lib/locale';
|
||||
import { AppState } from '../../utils/types';
|
||||
import { TagEntity } from '@joplin/lib/services/database/types';
|
||||
import { useCallback, useMemo, useState } from 'react';
|
||||
import { Dispatch } from 'redux';
|
||||
import useAsyncEffect from '@joplin/lib/hooks/useAsyncEffect';
|
||||
|
||||
interface Props {
|
||||
dispatch: Dispatch;
|
||||
themeId: number;
|
||||
}
|
||||
|
||||
const useStyles = (themeId: number) => {
|
||||
return useMemo(() => {
|
||||
const theme = themeStyle(themeId);
|
||||
|
||||
return StyleSheet.create({
|
||||
listItem: {
|
||||
flexDirection: 'row',
|
||||
borderBottomWidth: 1,
|
||||
borderBottomColor: theme.dividerColor,
|
||||
alignItems: 'flex-start',
|
||||
paddingLeft: theme.marginLeft,
|
||||
paddingRight: theme.marginRight,
|
||||
paddingTop: theme.itemMarginTop,
|
||||
paddingBottom: theme.itemMarginBottom,
|
||||
},
|
||||
listItemText: {
|
||||
flex: 1,
|
||||
color: theme.color,
|
||||
fontSize: theme.fontSize,
|
||||
},
|
||||
rootStyle: theme.rootStyle,
|
||||
});
|
||||
}, [themeId]);
|
||||
};
|
||||
|
||||
|
||||
const TagsScreenComponent: React.FC<Props> = props => {
|
||||
const [tags, setTags] = useState<TagEntity[]>([]);
|
||||
const styles = useStyles(props.themeId);
|
||||
|
||||
type TagItemPressEvent = { id: string };
|
||||
|
||||
useAsyncEffect(async () => {
|
||||
const tags = await Tag.allWithNotes();
|
||||
tags.sort((a, b) => {
|
||||
return a.title.toLowerCase() < b.title.toLowerCase() ? -1 : +1;
|
||||
});
|
||||
setTags(tags);
|
||||
}, []);
|
||||
|
||||
const onTagItemPress = useCallback((event: TagItemPressEvent) => {
|
||||
props.dispatch({ type: 'SIDE_MENU_CLOSE' });
|
||||
|
||||
props.dispatch({
|
||||
type: 'NAV_GO',
|
||||
routeName: 'Notes',
|
||||
tagId: event.id,
|
||||
});
|
||||
}, [props.dispatch]);
|
||||
|
||||
type RenderItemEvent = { item: TagEntity };
|
||||
const onRenderItem = useCallback(({ item }: RenderItemEvent) => {
|
||||
return (
|
||||
<TouchableOpacity
|
||||
onPress={() => onTagItemPress({ id: item.id })}
|
||||
accessibilityRole='button'
|
||||
accessibilityHint={_('Shows notes for tag')}
|
||||
>
|
||||
<View style={styles.listItem}>
|
||||
<Text style={styles.listItemText}>{item.title}</Text>
|
||||
</View>
|
||||
</TouchableOpacity>
|
||||
);
|
||||
}, [onTagItemPress, styles]);
|
||||
|
||||
return (
|
||||
<View style={styles.rootStyle}>
|
||||
<ScreenHeader title={_('Tags')} showSearchButton={false} />
|
||||
<FlatList style={{ flex: 1 }} data={tags} renderItem={onRenderItem} keyExtractor={tag => tag.id} />
|
||||
</View>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
const TagsScreen = connect((state: AppState) => {
|
||||
return {
|
||||
themeId: state.settings.theme,
|
||||
};
|
||||
})(TagsScreenComponent);
|
||||
|
||||
export default TagsScreen;
|
@ -56,7 +56,7 @@ import RevisionService from '@joplin/lib/services/RevisionService';
|
||||
import JoplinDatabase from '@joplin/lib/JoplinDatabase';
|
||||
import Database from '@joplin/lib/database';
|
||||
import NotesScreen from './components/screens/Notes';
|
||||
const { TagsScreen } = require('./components/screens/tags.js');
|
||||
import TagsScreen from './components/screens/tags';
|
||||
import ConfigScreen from './components/screens/ConfigScreen/ConfigScreen';
|
||||
const { FolderScreen } = require('./components/screens/folder.js');
|
||||
import LogScreen from './components/screens/LogScreen';
|
||||
|
Loading…
Reference in New Issue
Block a user