Refine hitslop
This commit is contained in:
@@ -1,4 +1,5 @@
|
|||||||
import {memo} from 'react'
|
import {memo} from 'react'
|
||||||
|
import {type Insets} from 'react-native'
|
||||||
import {type AppBskyFeedDefs} from '@atproto/api'
|
import {type AppBskyFeedDefs} from '@atproto/api'
|
||||||
import {msg, Trans} from '@lingui/macro'
|
import {msg, Trans} from '@lingui/macro'
|
||||||
import {useLingui} from '@lingui/react'
|
import {useLingui} from '@lingui/react'
|
||||||
@@ -18,10 +19,12 @@ export const BookmarkButton = memo(function BookmarkButton({
|
|||||||
post,
|
post,
|
||||||
big,
|
big,
|
||||||
logContext,
|
logContext,
|
||||||
|
hitSlop,
|
||||||
}: {
|
}: {
|
||||||
post: Shadow<AppBskyFeedDefs.PostView>
|
post: Shadow<AppBskyFeedDefs.PostView>
|
||||||
big?: boolean
|
big?: boolean
|
||||||
logContext: 'FeedItem' | 'PostThreadItem' | 'Post' | 'ImmersiveVideo'
|
logContext: 'FeedItem' | 'PostThreadItem' | 'Post' | 'ImmersiveVideo'
|
||||||
|
hitSlop?: Insets
|
||||||
}): React.ReactNode {
|
}): React.ReactNode {
|
||||||
const t = useTheme()
|
const t = useTheme()
|
||||||
const {_} = useLingui()
|
const {_} = useLingui()
|
||||||
@@ -122,7 +125,8 @@ export const BookmarkButton = memo(function BookmarkButton({
|
|||||||
? _(msg`Remove from saved posts`)
|
? _(msg`Remove from saved posts`)
|
||||||
: _(msg`Add to saved posts`)
|
: _(msg`Add to saved posts`)
|
||||||
}
|
}
|
||||||
onPress={onHandlePress}>
|
onPress={onHandlePress}
|
||||||
|
hitSlop={hitSlop}>
|
||||||
<PostControlButtonIcon
|
<PostControlButtonIcon
|
||||||
fill={isBookmarked ? t.palette.primary_500 : undefined}
|
fill={isBookmarked ? t.palette.primary_500 : undefined}
|
||||||
icon={isBookmarked ? BookmarkFilled : Bookmark}
|
icon={isBookmarked ? BookmarkFilled : Bookmark}
|
||||||
|
|||||||
@@ -1,13 +1,14 @@
|
|||||||
import {createContext, useContext, useMemo} from 'react'
|
import {createContext, useContext, useMemo} from 'react'
|
||||||
import {type GestureResponderEvent, type View} from 'react-native'
|
import {type GestureResponderEvent, type Insets, type View} from 'react-native'
|
||||||
|
|
||||||
import {POST_CTRL_HITSLOP} from '#/lib/constants'
|
|
||||||
import {useHaptics} from '#/lib/haptics'
|
import {useHaptics} from '#/lib/haptics'
|
||||||
import {atoms as a, useTheme} from '#/alf'
|
import {atoms as a, useTheme} from '#/alf'
|
||||||
import {Button, type ButtonProps} from '#/components/Button'
|
import {Button, type ButtonProps} from '#/components/Button'
|
||||||
import {type Props as SVGIconProps} from '#/components/icons/common'
|
import {type Props as SVGIconProps} from '#/components/icons/common'
|
||||||
import {Text, type TextProps} from '#/components/Typography'
|
import {Text, type TextProps} from '#/components/Typography'
|
||||||
|
|
||||||
|
export const DEFAULT_HITSLOP = {top: 5, bottom: 10, left: 10, right: 10}
|
||||||
|
|
||||||
const PostControlContext = createContext<{
|
const PostControlContext = createContext<{
|
||||||
big?: boolean
|
big?: boolean
|
||||||
active?: boolean
|
active?: boolean
|
||||||
@@ -25,12 +26,13 @@ export function PostControlButton({
|
|||||||
active,
|
active,
|
||||||
activeColor,
|
activeColor,
|
||||||
...props
|
...props
|
||||||
}: ButtonProps & {
|
}: Omit<ButtonProps, 'hitSlop'> & {
|
||||||
ref?: React.Ref<View>
|
ref?: React.Ref<View>
|
||||||
active?: boolean
|
active?: boolean
|
||||||
big?: boolean
|
big?: boolean
|
||||||
color?: string
|
color?: string
|
||||||
activeColor?: string
|
activeColor?: string
|
||||||
|
hitSlop?: Insets
|
||||||
}) {
|
}) {
|
||||||
const t = useTheme()
|
const t = useTheme()
|
||||||
const playHaptic = useHaptics()
|
const playHaptic = useHaptics()
|
||||||
@@ -83,8 +85,11 @@ export function PostControlButton({
|
|||||||
shape="round"
|
shape="round"
|
||||||
variant="ghost"
|
variant="ghost"
|
||||||
color="secondary"
|
color="secondary"
|
||||||
hitSlop={POST_CTRL_HITSLOP}
|
{...props}
|
||||||
{...props}>
|
hitSlop={{
|
||||||
|
...DEFAULT_HITSLOP,
|
||||||
|
...(props.hitSlop || {}),
|
||||||
|
}}>
|
||||||
{typeof children === 'function' ? (
|
{typeof children === 'function' ? (
|
||||||
args => (
|
args => (
|
||||||
<PostControlContext.Provider value={ctx}>
|
<PostControlContext.Provider value={ctx}>
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import {memo, useMemo, useState} from 'react'
|
import {memo, useMemo, useState} from 'react'
|
||||||
|
import {type Insets} from 'react-native'
|
||||||
import {
|
import {
|
||||||
type AppBskyFeedDefs,
|
type AppBskyFeedDefs,
|
||||||
type AppBskyFeedPost,
|
type AppBskyFeedPost,
|
||||||
@@ -28,6 +29,7 @@ let PostMenuButton = ({
|
|||||||
timestamp,
|
timestamp,
|
||||||
threadgateRecord,
|
threadgateRecord,
|
||||||
onShowLess,
|
onShowLess,
|
||||||
|
hitSlop,
|
||||||
}: {
|
}: {
|
||||||
testID: string
|
testID: string
|
||||||
post: Shadow<AppBskyFeedDefs.PostView>
|
post: Shadow<AppBskyFeedDefs.PostView>
|
||||||
@@ -39,6 +41,7 @@ let PostMenuButton = ({
|
|||||||
timestamp: string
|
timestamp: string
|
||||||
threadgateRecord?: AppBskyFeedThreadgate.Record
|
threadgateRecord?: AppBskyFeedThreadgate.Record
|
||||||
onShowLess?: (interaction: AppBskyFeedDefs.Interaction) => void
|
onShowLess?: (interaction: AppBskyFeedDefs.Interaction) => void
|
||||||
|
hitSlop?: Insets
|
||||||
}): React.ReactNode => {
|
}): React.ReactNode => {
|
||||||
const {_} = useLingui()
|
const {_} = useLingui()
|
||||||
|
|
||||||
@@ -66,7 +69,8 @@ let PostMenuButton = ({
|
|||||||
testID="postDropdownBtn"
|
testID="postDropdownBtn"
|
||||||
big={big}
|
big={big}
|
||||||
label={props.accessibilityLabel}
|
label={props.accessibilityLabel}
|
||||||
{...props}>
|
{...props}
|
||||||
|
hitSlop={hitSlop}>
|
||||||
<PostControlButtonIcon icon={DotsHorizontal} />
|
<PostControlButtonIcon icon={DotsHorizontal} />
|
||||||
</PostControlButton>
|
</PostControlButton>
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import {memo, useMemo, useState} from 'react'
|
import {memo, useMemo, useState} from 'react'
|
||||||
|
import {type Insets} from 'react-native'
|
||||||
import {
|
import {
|
||||||
type AppBskyFeedDefs,
|
type AppBskyFeedDefs,
|
||||||
type AppBskyFeedPost,
|
type AppBskyFeedPost,
|
||||||
@@ -34,6 +35,7 @@ let ShareMenuButton = ({
|
|||||||
timestamp,
|
timestamp,
|
||||||
threadgateRecord,
|
threadgateRecord,
|
||||||
onShare,
|
onShare,
|
||||||
|
hitSlop,
|
||||||
}: {
|
}: {
|
||||||
testID: string
|
testID: string
|
||||||
post: Shadow<AppBskyFeedDefs.PostView>
|
post: Shadow<AppBskyFeedDefs.PostView>
|
||||||
@@ -43,6 +45,7 @@ let ShareMenuButton = ({
|
|||||||
timestamp: string
|
timestamp: string
|
||||||
threadgateRecord?: AppBskyFeedThreadgate.Record
|
threadgateRecord?: AppBskyFeedThreadgate.Record
|
||||||
onShare: () => void
|
onShare: () => void
|
||||||
|
hitSlop?: Insets
|
||||||
}): React.ReactNode => {
|
}): React.ReactNode => {
|
||||||
const {_} = useLingui()
|
const {_} = useLingui()
|
||||||
const gate = useGate()
|
const gate = useGate()
|
||||||
@@ -92,7 +95,8 @@ let ShareMenuButton = ({
|
|||||||
big={big}
|
big={big}
|
||||||
label={props.accessibilityLabel}
|
label={props.accessibilityLabel}
|
||||||
{...props}
|
{...props}
|
||||||
onLongPress={native(onNativeLongPress)}>
|
onLongPress={native(onNativeLongPress)}
|
||||||
|
hitSlop={hitSlop}>
|
||||||
<PostControlButtonIcon icon={ShareIcon} />
|
<PostControlButtonIcon icon={ShareIcon} />
|
||||||
</PostControlButton>
|
</PostControlButton>
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ import {
|
|||||||
useProgressGuideControls,
|
useProgressGuideControls,
|
||||||
} from '#/state/shell/progress-guide'
|
} from '#/state/shell/progress-guide'
|
||||||
import * as Toast from '#/view/com/util/Toast'
|
import * as Toast from '#/view/com/util/Toast'
|
||||||
import {atoms as a, useBreakpoints} from '#/alf'
|
import {atoms as a, flatten, useBreakpoints} from '#/alf'
|
||||||
import {Reply as Bubble} from '#/components/icons/Reply'
|
import {Reply as Bubble} from '#/components/icons/Reply'
|
||||||
import {formatPostStatCount} from '#/components/PostControls/util'
|
import {formatPostStatCount} from '#/components/PostControls/util'
|
||||||
import {BookmarkButton} from './BookmarkButton'
|
import {BookmarkButton} from './BookmarkButton'
|
||||||
@@ -187,6 +187,11 @@ let PostControls = ({
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const secondaryControlSpacingStyles = flatten([
|
||||||
|
a.gap_xs,
|
||||||
|
(big || gtPhone) && a.gap_sm,
|
||||||
|
])
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<View
|
<View
|
||||||
style={[
|
style={[
|
||||||
@@ -289,8 +294,15 @@ let PostControls = ({
|
|||||||
{/* Spacer! */}
|
{/* Spacer! */}
|
||||||
<View />
|
<View />
|
||||||
</View>
|
</View>
|
||||||
<View style={[a.flex_row, a.justify_end, (big || gtPhone) && a.gap_sm]}>
|
<View style={[a.flex_row, a.justify_end, secondaryControlSpacingStyles]}>
|
||||||
<BookmarkButton post={post} big={big} logContext={logContext} />
|
<BookmarkButton
|
||||||
|
post={post}
|
||||||
|
big={big}
|
||||||
|
logContext={logContext}
|
||||||
|
hitSlop={{
|
||||||
|
right: secondaryControlSpacingStyles.gap / 2,
|
||||||
|
}}
|
||||||
|
/>
|
||||||
<ShareMenuButton
|
<ShareMenuButton
|
||||||
testID="postShareBtn"
|
testID="postShareBtn"
|
||||||
post={post}
|
post={post}
|
||||||
@@ -300,6 +312,10 @@ let PostControls = ({
|
|||||||
timestamp={post.indexedAt}
|
timestamp={post.indexedAt}
|
||||||
threadgateRecord={threadgateRecord}
|
threadgateRecord={threadgateRecord}
|
||||||
onShare={onShare}
|
onShare={onShare}
|
||||||
|
hitSlop={{
|
||||||
|
left: secondaryControlSpacingStyles.gap / 2,
|
||||||
|
right: secondaryControlSpacingStyles.gap / 2,
|
||||||
|
}}
|
||||||
/>
|
/>
|
||||||
<PostMenuButton
|
<PostMenuButton
|
||||||
testID="postDropdownBtn"
|
testID="postDropdownBtn"
|
||||||
@@ -312,6 +328,9 @@ let PostControls = ({
|
|||||||
timestamp={post.indexedAt}
|
timestamp={post.indexedAt}
|
||||||
threadgateRecord={threadgateRecord}
|
threadgateRecord={threadgateRecord}
|
||||||
onShowLess={onShowLess}
|
onShowLess={onShowLess}
|
||||||
|
hitSlop={{
|
||||||
|
left: secondaryControlSpacingStyles.gap / 2,
|
||||||
|
}}
|
||||||
/>
|
/>
|
||||||
</View>
|
</View>
|
||||||
</View>
|
</View>
|
||||||
|
|||||||
@@ -124,7 +124,6 @@ export const createHitslop = (size: number): Insets => ({
|
|||||||
export const HITSLOP_10 = createHitslop(10)
|
export const HITSLOP_10 = createHitslop(10)
|
||||||
export const HITSLOP_20 = createHitslop(20)
|
export const HITSLOP_20 = createHitslop(20)
|
||||||
export const HITSLOP_30 = createHitslop(30)
|
export const HITSLOP_30 = createHitslop(30)
|
||||||
export const POST_CTRL_HITSLOP = {top: 5, bottom: 10, left: 10, right: 10}
|
|
||||||
export const LANG_DROPDOWN_HITSLOP = {top: 10, bottom: 10, left: 4, right: 4}
|
export const LANG_DROPDOWN_HITSLOP = {top: 10, bottom: 10, left: 4, right: 4}
|
||||||
export const BACK_HITSLOP = HITSLOP_30
|
export const BACK_HITSLOP = HITSLOP_30
|
||||||
export const MAX_POST_LINES = 25
|
export const MAX_POST_LINES = 25
|
||||||
|
|||||||
Reference in New Issue
Block a user