feat: replace Modal with BottomModal in SelectableTextSheet component

This commit is contained in:
lawvs 2025-06-26 03:29:31 +08:00
parent 9251204f19
commit b5a81f379b
1 changed files with 7 additions and 81 deletions

View File

@ -7,7 +7,6 @@ import * as React from "react"
import type { LayoutChangeEvent } from "react-native"
import {
Clipboard,
Modal,
Pressable,
ScrollView,
StyleSheet,
@ -27,6 +26,7 @@ import Animated, {
import { useSafeAreaInsets } from "react-native-safe-area-context"
import { useColor } from "react-native-uikit-colors"
import { BottomModal } from "@/src/components/ui/modal/BottomModal"
import { AiCuteReIcon } from "@/src/icons/ai_cute_re"
import { CloseCuteReIcon } from "@/src/icons/close_cute_re"
import { CopyCuteReIcon } from "@/src/icons/copy_cute_re"
@ -192,65 +192,19 @@ const SelectableTextSheet: FC<{
text: string
}> = ({ visible, onClose, text }) => {
const insets = useSafeAreaInsets()
const translateY = useSharedValue(500)
const [isRendered, setIsRendered] = React.useState(visible)
const textColor = useColor("label")
const sheetAnimatedStyle = useAnimatedStyle(() => ({
transform: [{ translateY: translateY.value }],
}))
React.useEffect(() => {
if (visible) {
setIsRendered(true)
translateY.value = withSpring(0, {
damping: 20,
stiffness: 150,
overshootClamping: true,
})
} else {
if (isRendered) {
translateY.value = withTiming(800, { duration: 250 })
setTimeout(() => {
setIsRendered(false)
}, 250)
}
}
}, [visible, isRendered, translateY])
if (!isRendered) {
return null
}
const handleClose = () => {
onClose()
}
const handleCopyAll = () => {
Clipboard.setString(text)
Haptics.notificationAsync(Haptics.NotificationFeedbackType.Success)
handleClose()
onClose()
}
return (
// Wrap in a View to avoid rendering issues with Modal on Android
<View>
<Modal
transparent
visible={isRendered}
onRequestClose={handleClose}
animationType="fade"
statusBarTranslucent
navigationBarTranslucent
>
<Pressable onPress={handleClose} style={StyleSheet.absoluteFill}>
<View className="bg-black/40" style={StyleSheet.absoluteFill} />
</Pressable>
<Animated.View
className="bg-system-background absolute inset-x-0 bottom-0 max-h-[70%] overflow-hidden rounded-t-2xl border-t-zinc-200 p-4 dark:border-t-zinc-800"
style={[{ paddingBottom: insets.bottom + 10 }, sheetAnimatedStyle]}
>
<BottomModal visible={visible} onClose={onClose}>
<View className="p-4" style={{ paddingBottom: insets.bottom + 10 }}>
<View className="mb-4 flex-row items-center justify-between">
<TouchableOpacity
onPress={handleCopyAll}
@ -260,7 +214,7 @@ const SelectableTextSheet: FC<{
</TouchableOpacity>
<Text className="text-label text-lg font-semibold">AI Summary</Text>
<TouchableOpacity
onPress={handleClose}
onPress={onClose}
className="rounded-full bg-zinc-100 p-2 active:opacity-80 dark:bg-zinc-800"
>
<CloseCuteReIcon width={18} height={18} color={textColor} />
@ -269,8 +223,8 @@ const SelectableTextSheet: FC<{
<ScrollView showsVerticalScrollIndicator={false}>
<SelectableText className="text-label text-base leading-6">{text}</SelectableText>
</ScrollView>
</Animated.View>
</Modal>
</View>
</BottomModal>
</View>
)
}
@ -301,32 +255,4 @@ const styles = StyleSheet.create({
borderWidth: 0.5,
elevation: 2,
},
sheetContainer: {
position: "absolute",
bottom: 0,
left: 0,
right: 0,
maxHeight: "70%",
borderTopLeftRadius: 20,
borderTopRightRadius: 20,
paddingHorizontal: 16,
paddingTop: 16,
overflow: "hidden",
},
sheetHeader: {
alignItems: "center",
paddingBottom: 10,
borderBottomWidth: StyleSheet.hairlineWidth,
},
sheetTitle: {
fontSize: 18,
fontWeight: "600",
},
textScrollView: {
marginVertical: 15,
},
selectableText: {
fontSize: 16,
lineHeight: 24,
},
})