feat(mobile): refactor ItemPressable usage and styles

- Replaced TouchableOpacity with ItemPressable in multiple components for improved interaction handling.
- Introduced a new UnStyled option in ItemPressableStyle to allow for customizable styling.
- Updated ItemPressable implementation in RelativeDateTime, EntryNormalItem, and CategoryGrouped components to enhance touch feedback and visual consistency.

Signed-off-by: Innei <tukon479@gmail.com>
This commit is contained in:
Innei 2025-04-17 00:38:44 +08:00
parent ece26375a6
commit 70ef539788
No known key found for this signature in database
GPG Key ID: 0F62D33977F021F7
7 changed files with 40 additions and 25 deletions

View File

@ -57,8 +57,4 @@ class ItemPressableView: ExpoView {
}
}
extension ItemPressableView: UIGestureRecognizerDelegate {
func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldReceive touch: UITouch) -> Bool {
return touch.view == gestureRecognizer.view
}
}
extension ItemPressableView: UIGestureRecognizerDelegate {}

View File

@ -2,9 +2,11 @@ import dayjs from "dayjs"
import { useEffect, useMemo, useState } from "react"
import { useTranslation } from "react-i18next"
import type { TextProps } from "react-native"
import { Pressable } from "react-native"
import Animated, { FadeOut } from "react-native-reanimated"
import { ItemPressableStyle } from "../pressable/enum"
import { ItemPressable } from "../pressable/ItemPressable"
const formatTemplateString = "lll"
const formatTime = (
@ -76,7 +78,9 @@ export const RelativeDateTime = ({
}, [date, displayAbsoluteTimeAfterDay, dateFormatTemplate, mode])
return (
<Pressable
<ItemPressable
touchHighlight={false}
itemStyle={ItemPressableStyle.UnStyled}
hitSlop={10}
onPress={() => {
setMode((mode) => (mode === "relative" ? "absolute" : "relative"))
@ -87,6 +91,6 @@ export const RelativeDateTime = ({
? `${relative}${t("space")}${postfixText ?? t("words.ago")}`
: memoizedFormatTime}
</Animated.Text>
</Pressable>
</ItemPressable>
)
}

View File

@ -21,20 +21,26 @@ const NativeItemPressable = requireNativeView<
cssInterop(NativeItemPressable, {
className: "style",
})
export const ItemPressable: FC<ItemPressableProps> = memo(
({ children, itemStyle = ItemPressableStyle.Grouped, ...props }) => {
({ children, itemStyle = ItemPressableStyle.Grouped, className, ...props }) => {
const isUnStyled = itemStyle === ItemPressableStyle.UnStyled
return (
<NativeItemPressable
className={cn(
"relative overflow-hidden",
{...props}
className={
isUnStyled
? className
: cn(
"relative overflow-hidden",
itemStyle === ItemPressableStyle.Plain
? "bg-system-background"
: "bg-secondary-system-grouped-background",
props.className,
)}
touchHighlight={props.touchHighlight}
style={props.style}
itemStyle === ItemPressableStyle.Plain
? "bg-system-background"
: "bg-secondary-system-grouped-background",
className,
)
}
touchHighlight={props.touchHighlight ?? true}
onItemPress={() => {
props.onPress?.()
}}

View File

@ -67,6 +67,7 @@ export const ItemPressable: FC<ItemPressableProps> = memo(
}, 100)
})
}, [setIsPressing])
const isUnStyled = itemStyle === ItemPressableStyle.UnStyled
return (
<GestureDetector gesture={tapGesture}>
@ -77,7 +78,10 @@ export const ItemPressable: FC<ItemPressableProps> = memo(
onLongPress={composeEventHandlers(props.onLongPress, () => {})}
delayLongPress={props.delayLongPress ?? 100}
className={cn("relative overflow-hidden", props.className)}
style={StyleSheet.flatten([props.style, { backgroundColor: itemNormalColor }])}
style={StyleSheet.flatten([
props.style,
!isUnStyled && { backgroundColor: itemNormalColor },
])}
>
{useTypeScriptHappyCallback(
(props) => {

View File

@ -1,4 +1,5 @@
export enum ItemPressableStyle {
UnStyled,
Plain,
Grouped,
}

View File

@ -2,7 +2,7 @@ import { FeedViewType } from "@follow/constants"
import { tracker } from "@follow/tracker"
import { cn, formatEstimatedMins, formatTimeToSeconds } from "@follow/utils"
import { memo, useCallback, useMemo } from "react"
import { StyleSheet, Text, TouchableOpacity, View } from "react-native"
import { StyleSheet, Text, View } from "react-native"
import { useUISettingKey } from "@/src/atoms/settings/ui"
import { ThemedBlurView } from "@/src/components/common/ThemedBlurView"
@ -148,7 +148,9 @@ export const EntryNormalItem = memo(
))}
{audio && (
<TouchableOpacity
<ItemPressable
touchHighlight={false}
itemStyle={ItemPressableStyle.UnStyled}
className="absolute inset-0 flex items-center justify-center"
onPress={() => {
if (isLoading) return
@ -174,7 +176,7 @@ export const EntryNormalItem = memo(
<PlayCuteFiIcon color="white" width={24} height={24} />
)}
</View>
</TouchableOpacity>
</ItemPressable>
)}
</View>
)}

View File

@ -1,6 +1,6 @@
import { cn } from "@follow/utils"
import { memo, useState } from "react"
import { Text, TouchableOpacity, View } from "react-native"
import { Text, View } from "react-native"
import Animated, { useAnimatedStyle, useSharedValue, withSpring } from "react-native-reanimated"
import { GROUPED_LIST_MARGIN } from "@/src/components/ui/grouped/constants"
@ -68,7 +68,9 @@ export const CategoryGrouped = memo(
"rounded-b-[10px]": isLast && !expanded,
})}
>
<TouchableOpacity
<ItemPressable
touchHighlight={false}
itemStyle={ItemPressableStyle.UnStyled}
hitSlop={10}
onPress={() => {
rotateSharedValue.value = withSpring(expanded ? 0 : 90, {})
@ -79,7 +81,7 @@ export const CategoryGrouped = memo(
<Animated.View style={rotateStyle} className="ml-2">
<RightCuteFiIcon color={secondaryLabelColor} height={14} width={14} />
</Animated.View>
</TouchableOpacity>
</ItemPressable>
<Text className="text-text ml-4 font-medium">{category}</Text>
<UnreadCount unread={unreadCounts} className="text-secondary-label ml-auto text-xs" />
</ItemPressable>