Fix tap target size of post dropdown menus (#1180)

zio/stable
Paul Frazee 2023-08-15 15:49:52 -07:00 committed by GitHub
parent 0576caae36
commit 6ccfb1375a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 55 additions and 113 deletions

View File

@ -215,6 +215,18 @@ export const PostThreadItem = observer(function PostThreadItem({
</TimeElapsed> </TimeElapsed>
</Text> </Text>
</View> </View>
</View>
<View style={styles.meta}>
<Link
style={styles.metaItem}
href={authorHref}
title={authorTitle}>
<Text type="md" style={[pal.textLight]} numberOfLines={1}>
{sanitizeHandle(item.post.author.handle, '@')}
</Text>
</Link>
</View>
</View>
<View style={s.flex1} /> <View style={s.flex1} />
<PostDropdownBtn <PostDropdownBtn
testID="postDropdownBtn" testID="postDropdownBtn"
@ -228,20 +240,9 @@ export const PostThreadItem = observer(function PostThreadItem({
onOpenTranslate={onOpenTranslate} onOpenTranslate={onOpenTranslate}
onToggleThreadMute={onToggleThreadMute} onToggleThreadMute={onToggleThreadMute}
onDeletePost={onDeletePost} onDeletePost={onDeletePost}
style={{paddingVertical: 6, paddingHorizontal: 10}}
/> />
</View> </View>
<View style={styles.meta}>
<Link
style={styles.metaItem}
href={authorHref}
title={authorTitle}>
<Text type="md" style={[pal.textLight]} numberOfLines={1}>
{sanitizeHandle(item.post.author.handle, '@')}
</Text>
</Link>
</View>
</View>
</View>
<View style={[s.pl10, s.pr10, s.pb10]}> <View style={[s.pl10, s.pr10, s.pb10]}>
<ContentHider <ContentHider
moderation={item.moderation.content} moderation={item.moderation.content}
@ -382,7 +383,7 @@ export const PostThreadItem = observer(function PostThreadItem({
style={[ style={[
styles.layout, styles.layout,
{ {
paddingBottom: item._showChildReplyLine ? 0 : 16, paddingBottom: item._showChildReplyLine ? 0 : 8,
}, },
]}> ]}>
<View style={styles.layoutAvi}> <View style={styles.layoutAvi}>
@ -430,7 +431,9 @@ export const PostThreadItem = observer(function PostThreadItem({
</View> </View>
) : undefined} ) : undefined}
{item.post.embed && ( {item.post.embed && (
<ContentHider style={s.mb10} moderation={item.moderation.embed}> <ContentHider
style={styles.contentHider}
moderation={item.moderation.embed}>
<PostEmbeds <PostEmbeds
embed={item.post.embed} embed={item.post.embed}
moderation={item.moderation.embed} moderation={item.moderation.embed}
@ -565,7 +568,6 @@ const styles = StyleSheet.create({
flexWrap: 'wrap', flexWrap: 'wrap',
paddingBottom: 8, paddingBottom: 8,
paddingRight: 10, paddingRight: 10,
minHeight: 36,
}, },
postTextLargeContainer: { postTextLargeContainer: {
paddingHorizontal: 0, paddingHorizontal: 0,

View File

@ -266,7 +266,9 @@ const PostLoaded = observer(
</View> </View>
) : undefined} ) : undefined}
{item.post.embed ? ( {item.post.embed ? (
<ContentHider moderation={item.moderation.embed} style={s.mb10}> <ContentHider
moderation={item.moderation.embed}
style={styles.contentHider}>
<PostEmbeds <PostEmbeds
embed={item.post.embed} embed={item.post.embed}
moderation={item.moderation.embed} moderation={item.moderation.embed}
@ -315,8 +317,10 @@ const PostLoaded = observer(
const styles = StyleSheet.create({ const styles = StyleSheet.create({
outer: { outer: {
padding: 10, paddingTop: 10,
paddingRight: 15, paddingRight: 15,
paddingBottom: 5,
paddingLeft: 10,
borderTopWidth: 1, borderTopWidth: 1,
}, },
layout: { layout: {
@ -336,7 +340,6 @@ const styles = StyleSheet.create({
flexDirection: 'row', flexDirection: 'row',
alignItems: 'center', alignItems: 'center',
flexWrap: 'wrap', flexWrap: 'wrap',
paddingBottom: 8,
}, },
translateLink: { translateLink: {
marginBottom: 12, marginBottom: 12,
@ -350,7 +353,7 @@ const styles = StyleSheet.create({
borderLeftColor: colors.gray2, borderLeftColor: colors.gray2,
}, },
contentHider: { contentHider: {
marginBottom: 6, marginBottom: 2,
}, },
contentHiderChild: { contentHiderChild: {
marginTop: 6, marginTop: 6,

View File

@ -143,7 +143,7 @@ export const FeedItem = observer(function ({
borderColor: pal.colors.border, borderColor: pal.colors.border,
paddingBottom: paddingBottom:
isThreadLastChild || (!isThreadChild && !isThreadParent) isThreadLastChild || (!isThreadChild && !isThreadParent)
? 12 ? 6
: undefined, : undefined,
}, },
isThreadChild ? styles.outerSmallTop : undefined, isThreadChild ? styles.outerSmallTop : undefined,
@ -274,7 +274,6 @@ export const FeedItem = observer(function ({
testID="contentHider-post" testID="contentHider-post"
moderation={item.moderation.content} moderation={item.moderation.content}
ignoreMute ignoreMute
style={styles.contentHider}
childContainerStyle={styles.contentHiderChild}> childContainerStyle={styles.contentHiderChild}>
<PostAlerts <PostAlerts
moderation={item.moderation.content} moderation={item.moderation.content}
@ -312,7 +311,6 @@ export const FeedItem = observer(function ({
)} )}
</ContentHider> </ContentHider>
<PostCtrls <PostCtrls
style={styles.ctrls}
itemUri={itemUri} itemUri={itemUri}
itemCid={itemCid} itemCid={itemCid}
itemHref={itemHref} itemHref={itemHref}
@ -385,9 +383,6 @@ const styles = StyleSheet.create({
flexWrap: 'wrap', flexWrap: 'wrap',
paddingBottom: 4, paddingBottom: 4,
}, },
contentHider: {
marginBottom: 6,
},
contentHiderChild: { contentHiderChild: {
marginTop: 6, marginTop: 6,
}, },
@ -397,7 +392,4 @@ const styles = StyleSheet.create({
translateLink: { translateLink: {
marginBottom: 6, marginBottom: 6,
}, },
ctrls: {
marginTop: 4,
},
}) })

View File

@ -60,7 +60,6 @@ export const DropdownMenuTrigger = DropdownMenu.create(
icon="ellipsis" icon="ellipsis"
size={20} size={20}
color={defaultCtrlColor} color={defaultCtrlColor}
style={styles.ellipsis}
/> />
)} )}
</View> </View>
@ -252,9 +251,6 @@ const styles = StyleSheet.create({
height: 1, height: 1,
marginVertical: 4, marginVertical: 4,
}, },
ellipsis: {
padding: isWeb ? 0 : 10,
},
content: { content: {
backgroundColor: '#f0f0f0', backgroundColor: '#f0f0f0',
borderRadius: 8, borderRadius: 8,

View File

@ -1,6 +1,9 @@
import React from 'react' import React from 'react'
import {StyleProp, View, ViewStyle} from 'react-native'
import {FontAwesomeIcon} from '@fortawesome/react-native-fontawesome'
import {toShareUrl} from 'lib/strings/url-helpers' import {toShareUrl} from 'lib/strings/url-helpers'
import {useStores} from 'state/index' import {useStores} from 'state/index'
import {useTheme} from 'lib/ThemeContext'
import {shareUrl} from 'lib/sharing' import {shareUrl} from 'lib/sharing'
import { import {
NativeDropdown, NativeDropdown,
@ -19,6 +22,7 @@ export function PostDropdownBtn({
onOpenTranslate, onOpenTranslate,
onToggleThreadMute, onToggleThreadMute,
onDeletePost, onDeletePost,
style,
}: { }: {
testID: string testID: string
itemUri: string itemUri: string
@ -31,8 +35,11 @@ export function PostDropdownBtn({
onOpenTranslate: () => void onOpenTranslate: () => void
onToggleThreadMute: () => void onToggleThreadMute: () => void
onDeletePost: () => void onDeletePost: () => void
style?: StyleProp<ViewStyle>
}) { }) {
const store = useStores() const store = useStores()
const theme = useTheme()
const defaultCtrlColor = theme.palette.default.postCtrl
const dropdownItems: NativeDropdownItem[] = [ const dropdownItems: NativeDropdownItem[] = [
{ {
@ -146,8 +153,11 @@ export function PostDropdownBtn({
testID={testID} testID={testID}
items={dropdownItems} items={dropdownItems}
accessibilityLabel="More post options" accessibilityLabel="More post options"
accessibilityHint="" accessibilityHint="">
/> <View style={style}>
<FontAwesomeIcon icon="ellipsis" size={20} color={defaultCtrlColor} />
</View>
</NativeDropdown>
</EventStopper> </EventStopper>
) )
} }

View File

@ -6,11 +6,6 @@ import {
View, View,
ViewStyle, ViewStyle,
} from 'react-native' } from 'react-native'
// DISABLED see #135
// import {
// TriggerableAnimated,
// TriggerableAnimatedRef,
// } from './anim/TriggerableAnimated'
import {Text} from '../text/Text' import {Text} from '../text/Text'
import {PostDropdownBtn} from '../forms/PostDropdownBtn' import {PostDropdownBtn} from '../forms/PostDropdownBtn'
import {HeartIcon, HeartIconSolid, CommentBottomArrow} from 'lib/icons' import {HeartIcon, HeartIconSolid, CommentBottomArrow} from 'lib/icons'
@ -20,7 +15,6 @@ import {useTheme} from 'lib/ThemeContext'
import {useStores} from 'state/index' import {useStores} from 'state/index'
import {RepostButton} from './RepostButton' import {RepostButton} from './RepostButton'
import {Haptics} from 'lib/haptics' import {Haptics} from 'lib/haptics'
import {createHitslop} from 'lib/constants'
interface PostCtrlsOpts { interface PostCtrlsOpts {
itemUri: string itemUri: string
@ -53,44 +47,6 @@ interface PostCtrlsOpts {
onDeletePost: () => void onDeletePost: () => void
} }
const HITSLOP = createHitslop(5)
// DISABLED see #135
/*
function ctrlAnimStart(interp: Animated.Value) {
return Animated.sequence([
Animated.timing(interp, {
toValue: 1,
duration: 250,
useNativeDriver: true,
}),
Animated.delay(50),
Animated.timing(interp, {
toValue: 0,
duration: 20,
useNativeDriver: true,
}),
])
}
function ctrlAnimStyle(interp: Animated.Value) {
return {
transform: [
{
scale: interp.interpolate({
inputRange: [0, 1.0],
outputRange: [1.0, 4.0],
}),
},
],
opacity: interp.interpolate({
inputRange: [0, 1.0],
outputRange: [1.0, 0.0],
}),
}
}
*/
export function PostCtrls(opts: PostCtrlsOpts) { export function PostCtrls(opts: PostCtrlsOpts) {
const store = useStores() const store = useStores()
const theme = useTheme() const theme = useTheme()
@ -100,22 +56,11 @@ export function PostCtrls(opts: PostCtrlsOpts) {
}), }),
[theme], [theme],
) as StyleProp<ViewStyle> ) as StyleProp<ViewStyle>
// DISABLED see #135
// const repostRef = React.useRef<TriggerableAnimatedRef | null>(null)
// const likeRef = React.useRef<TriggerableAnimatedRef | null>(null)
const onRepost = useCallback(() => { const onRepost = useCallback(() => {
store.shell.closeModal() store.shell.closeModal()
if (!opts.isReposted) { if (!opts.isReposted) {
Haptics.default() Haptics.default()
opts.onPressToggleRepost().catch(_e => undefined) opts.onPressToggleRepost().catch(_e => undefined)
// DISABLED see #135
// repostRef.current?.trigger(
// {start: ctrlAnimStart, style: ctrlAnimStyle},
// async () => {
// await opts.onPressToggleRepost().catch(_e => undefined)
// setRepostMod(0)
// },
// )
} else { } else {
opts.onPressToggleRepost().catch(_e => undefined) opts.onPressToggleRepost().catch(_e => undefined)
} }
@ -146,18 +91,8 @@ export function PostCtrls(opts: PostCtrlsOpts) {
if (!opts.isLiked) { if (!opts.isLiked) {
Haptics.default() Haptics.default()
await opts.onPressToggleLike().catch(_e => undefined) await opts.onPressToggleLike().catch(_e => undefined)
// DISABLED see #135
// likeRef.current?.trigger(
// {start: ctrlAnimStart, style: ctrlAnimStyle},
// async () => {
// await opts.onPressToggleLike().catch(_e => undefined)
// setLikeMod(0)
// },
// )
// setIsLikedPressed(false)
} else { } else {
await opts.onPressToggleLike().catch(_e => undefined) await opts.onPressToggleLike().catch(_e => undefined)
// setIsLikedPressed(false)
} }
} }
@ -165,8 +100,7 @@ export function PostCtrls(opts: PostCtrlsOpts) {
<View style={[styles.ctrls, opts.style]}> <View style={[styles.ctrls, opts.style]}>
<TouchableOpacity <TouchableOpacity
testID="replyBtn" testID="replyBtn"
style={styles.ctrl} style={[styles.ctrl, !opts.big && styles.ctrlPad, {paddingLeft: 0}]}
hitSlop={HITSLOP}
onPress={opts.onPressReply} onPress={opts.onPressReply}
accessibilityRole="button" accessibilityRole="button"
accessibilityLabel={`Reply (${opts.replyCount} ${ accessibilityLabel={`Reply (${opts.replyCount} ${
@ -187,8 +121,7 @@ export function PostCtrls(opts: PostCtrlsOpts) {
<RepostButton {...opts} onRepost={onRepost} onQuote={onQuote} /> <RepostButton {...opts} onRepost={onRepost} onQuote={onQuote} />
<TouchableOpacity <TouchableOpacity
testID="likeBtn" testID="likeBtn"
style={styles.ctrl} style={[styles.ctrl, !opts.big && styles.ctrlPad]}
hitSlop={HITSLOP}
onPress={onPressToggleLikeWrapper} onPress={onPressToggleLikeWrapper}
accessibilityRole="button" accessibilityRole="button"
accessibilityLabel={`${opts.isLiked ? 'Unlike' : 'Like'} (${ accessibilityLabel={`${opts.isLiked ? 'Unlike' : 'Like'} (${
@ -232,6 +165,7 @@ export function PostCtrls(opts: PostCtrlsOpts) {
onOpenTranslate={opts.onOpenTranslate} onOpenTranslate={opts.onOpenTranslate}
onToggleThreadMute={opts.onToggleThreadMute} onToggleThreadMute={opts.onToggleThreadMute}
onDeletePost={opts.onDeletePost} onDeletePost={opts.onDeletePost}
style={styles.ctrlPad}
/> />
)} )}
{/* used for adding pad to the right side */} {/* used for adding pad to the right side */}
@ -248,8 +182,12 @@ const styles = StyleSheet.create({
ctrl: { ctrl: {
flexDirection: 'row', flexDirection: 'row',
alignItems: 'center', alignItems: 'center',
padding: 5, },
margin: -5, ctrlPad: {
paddingTop: 5,
paddingBottom: 5,
paddingLeft: 5,
paddingRight: 5,
}, },
ctrlIconLiked: { ctrlIconLiked: {
color: colors.like, color: colors.like,

View File

@ -6,9 +6,6 @@ import {useTheme} from 'lib/ThemeContext'
import {Text} from '../text/Text' import {Text} from '../text/Text'
import {pluralize} from 'lib/strings/helpers' import {pluralize} from 'lib/strings/helpers'
import {useStores} from 'state/index' import {useStores} from 'state/index'
import {createHitslop} from 'lib/constants'
const HITSLOP = createHitslop(5)
interface Props { interface Props {
isReposted: boolean isReposted: boolean
@ -47,9 +44,8 @@ export const RepostButton = ({
return ( return (
<TouchableOpacity <TouchableOpacity
testID="repostBtn" testID="repostBtn"
hitSlop={HITSLOP}
onPress={onPressToggleRepostWrapper} onPress={onPressToggleRepostWrapper}
style={styles.control} style={[styles.control, !big && styles.controlPad]}
accessibilityRole="button" accessibilityRole="button"
accessibilityLabel={`${ accessibilityLabel={`${
isReposted ? 'Undo repost' : 'Repost' isReposted ? 'Undo repost' : 'Repost'
@ -83,8 +79,9 @@ const styles = StyleSheet.create({
control: { control: {
flexDirection: 'row', flexDirection: 'row',
alignItems: 'center', alignItems: 'center',
},
controlPad: {
padding: 5, padding: 5,
margin: -5,
}, },
reposted: { reposted: {
color: colors.green3, color: colors.green3,

View File

@ -52,6 +52,7 @@ export const RepostButton = ({
<View <View
style={[ style={[
styles.control, styles.control,
!big && styles.controlPad,
(isReposted (isReposted
? styles.reposted ? styles.reposted
: defaultControlColor) as StyleProp<ViewStyle>, : defaultControlColor) as StyleProp<ViewStyle>,
@ -77,6 +78,9 @@ const styles = StyleSheet.create({
alignItems: 'center', alignItems: 'center',
gap: 4, gap: 4,
}, },
controlPad: {
padding: 5,
},
reposted: { reposted: {
color: colors.green3, color: colors.green3,
}, },