Add ability to reply, repost (without quote post), and like posts using VoiceOver (#765)

Co-authored-by: Paul Frazee <pfrazee@gmail.com>
zio/stable
Ollie H 2023-05-30 17:50:56 -07:00 committed by GitHub
parent 7458b6f600
commit a9a661ab58
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 138 additions and 30 deletions

View File

@ -1,4 +1,4 @@
import React from 'react'
import React, {useCallback, useMemo} from 'react'
import {observer} from 'mobx-react-lite'
import {Linking, StyleSheet, View} from 'react-native'
import Clipboard from '@react-native-clipboard/clipboard'
@ -133,6 +133,40 @@ export const PostThreadItem = observer(function PostThreadItem({
)
}, [item, store])
const accessibilityActions = useMemo(
() => [
{
name: 'reply',
label: 'Reply',
},
{
name: 'repost',
label: item.post.viewer?.repost ? 'Undo repost' : 'Repost',
},
{name: 'like', label: item.post.viewer?.like ? 'Unlike' : 'Like'},
],
[item.post.viewer?.like, item.post.viewer?.repost],
)
const onAccessibilityAction = useCallback(
event => {
switch (event.nativeEvent.actionName) {
case 'like':
onPressToggleLike()
break
case 'reply':
onPressReply()
break
case 'repost':
onPressToggleRepost()
break
default:
break
}
},
[onPressReply, onPressToggleLike, onPressToggleRepost],
)
if (!record) {
return <ErrorMessage message="Invalid or unsupported post record" />
}
@ -154,7 +188,9 @@ export const PostThreadItem = observer(function PostThreadItem({
<PostHider
testID={`postThreadItem-by-${item.post.author.handle}`}
style={[styles.outer, styles.outerHighlighted, pal.border, pal.view]}
moderation={item.moderation.thread}>
moderation={item.moderation.thread}
accessibilityActions={accessibilityActions}
onAccessibilityAction={onAccessibilityAction}>
<View style={styles.layout}>
<View style={styles.layoutAvi}>
<Link
@ -324,7 +360,9 @@ export const PostThreadItem = observer(function PostThreadItem({
pal.view,
item._showParentReplyLine && styles.noTopBorder,
]}
moderation={item.moderation.thread}>
moderation={item.moderation.thread}
accessibilityActions={accessibilityActions}
onAccessibilityAction={onAccessibilityAction}>
{item._showParentReplyLine && (
<View
style={[

View File

@ -1,4 +1,4 @@
import React, {useState, useEffect} from 'react'
import React, {useCallback, useEffect, useMemo, useState} from 'react'
import {
ActivityIndicator,
Linking,
@ -205,11 +205,47 @@ const PostLoaded = observer(
)
}, [item, setDeleted, store])
const accessibilityActions = useMemo(
() => [
{
name: 'reply',
label: 'Reply',
},
{
name: 'repost',
label: item.post.viewer?.repost ? 'Undo repost' : 'Repost',
},
{name: 'like', label: item.post.viewer?.like ? 'Unlike' : 'Like'},
],
[item.post.viewer?.like, item.post.viewer?.repost],
)
const onAccessibilityAction = useCallback(
event => {
switch (event.nativeEvent.actionName) {
case 'like':
onPressToggleLike()
break
case 'reply':
onPressReply()
break
case 'repost':
onPressToggleRepost()
break
default:
break
}
},
[onPressReply, onPressToggleLike, onPressToggleRepost],
)
return (
<PostHider
href={itemHref}
style={[styles.outer, pal.view, pal.border, style]}
moderation={item.moderation.list}>
moderation={item.moderation.list}
accessibilityActions={accessibilityActions}
onAccessibilityAction={onAccessibilityAction}>
{showReplyLine && <View style={styles.replyLine} />}
<View style={styles.layout}>
<View style={styles.layoutAvi}>

View File

@ -1,4 +1,4 @@
import React, {useMemo, useState} from 'react'
import React, {useCallback, useMemo, useState} from 'react'
import {observer} from 'mobx-react-lite'
import {Linking, StyleSheet, View} from 'react-native'
import Clipboard from '@react-native-clipboard/clipboard'
@ -158,12 +158,48 @@ export const FeedItem = observer(function ({
moderation = {behavior: ModerationBehaviorCode.Show}
}
const accessibilityActions = useMemo(
() => [
{
name: 'reply',
label: 'Reply',
},
{
name: 'repost',
label: item.post.viewer?.repost ? 'Undo repost' : 'Repost',
},
{name: 'like', label: item.post.viewer?.like ? 'Unlike' : 'Like'},
],
[item.post.viewer?.like, item.post.viewer?.repost],
)
const onAccessibilityAction = useCallback(
event => {
switch (event.nativeEvent.actionName) {
case 'like':
onPressToggleLike()
break
case 'reply':
onPressReply()
break
case 'repost':
onPressToggleRepost()
break
default:
break
}
},
[onPressReply, onPressToggleLike, onPressToggleRepost],
)
return (
<PostHider
testID={`feedItem-by-${item.post.author.handle}`}
style={outerStyles}
href={itemHref}
moderation={moderation}>
moderation={moderation}
accessibilityActions={accessibilityActions}
onAccessibilityAction={onAccessibilityAction}>
{isThreadChild && (
<View
style={[styles.topReplyLine, {borderColor: pal.colors.replyLine}]}

View File

@ -1,11 +1,5 @@
import React from 'react'
import {
StyleProp,
StyleSheet,
TouchableOpacity,
View,
ViewStyle,
} from 'react-native'
import React, {ComponentProps} from 'react'
import {StyleSheet, TouchableOpacity, View} from 'react-native'
import {FontAwesomeIcon} from '@fortawesome/react-native-fontawesome'
import {usePalette} from 'lib/hooks/usePalette'
import {Link} from '../Link'
@ -13,18 +7,21 @@ import {Text} from '../text/Text'
import {addStyle} from 'lib/styles'
import {ModerationBehaviorCode, ModerationBehavior} from 'lib/labeling/types'
interface Props extends ComponentProps<typeof Link> {
// testID?: string
// href?: string
// style: StyleProp<ViewStyle>
moderation: ModerationBehavior
}
export function PostHider({
testID,
href,
moderation,
style,
children,
}: React.PropsWithChildren<{
testID?: string
href?: string
moderation: ModerationBehavior
style: StyleProp<ViewStyle>
}>) {
...props
}: Props) {
const pal = usePalette('default')
const [override, setOverride] = React.useState(false)
const bg = override ? pal.viewLight : pal.view
@ -70,7 +67,14 @@ export function PostHider({
// NOTE: any further label enforcement should occur in ContentContainer
return (
<Link testID={testID} style={style} href={href} noFeedback>
<Link
testID={testID}
style={style}
href={href}
noFeedback
accessible={true}
accessibilityRole="none"
{...props}>
{children}
</Link>
)

View File

@ -191,9 +191,7 @@ export function PostCtrls(opts: PostCtrlsOpts) {
onPress={onPressToggleLikeWrapper}
accessibilityRole="button"
accessibilityLabel={opts.isLiked ? 'Unlike' : 'Like'}
accessibilityHint={
opts.isReposted ? 'Removes like from the post' : 'Like the post'
}>
accessibilityHint="">
{opts.isLiked ? (
<HeartIconSolid
style={styles.ctrlIconLiked}

View File

@ -50,11 +50,7 @@ export const RepostButton = ({
style={styles.control}
accessibilityRole="button"
accessibilityLabel={isReposted ? 'Undo repost' : 'Repost'}
accessibilityHint={
isReposted
? `Remove your repost of the post`
: `Repost or quote post the post`
}>
accessibilityHint="">
<RepostIcon
style={
isReposted