mirror of
https://github.com/hanzo-io/team.git
synced 2026-10-30 18:56:23 +00:00
175 lines
7.5 KiB
TypeScript
175 lines
7.5 KiB
TypeScript
import { TouchableOpacity, View, StyleSheet, Modal, Pressable, Platform } from 'react-native';
|
|
import { router } from 'expo-router';
|
|
import { Text } from '@components/nativewindui/Text';
|
|
import ChevronRightIcon from '@assets/icons/ChevronRightIcon.svg';
|
|
import HollowFilesIcon from '@assets/icons/HollowFilesIcon.svg';
|
|
import { useColorScheme } from '@hooks/useColorScheme';
|
|
import { Divider } from '@components/layout/Divider';
|
|
import CrossIcon from '@assets/icons/CrossIcon.svg';
|
|
import ThreeHorizontalDots from '@assets/icons/ThreeHorizontalDots.svg';
|
|
import Animated, { Easing, useAnimatedStyle, useSharedValue, withTiming } from 'react-native-reanimated';
|
|
import { useEffect } from 'react';
|
|
import { DMChannelListItem } from '@raven/types/common/ChannelListItem';
|
|
import { useGetUser } from '@raven/lib/hooks/useGetUser';
|
|
import PinOutlineIcon from '@assets/icons/PinOutlineIcon.svg';
|
|
import UserAvatar from '@components/layout/UserAvatar';
|
|
import { useIsUserActive } from '@hooks/useIsUserActive';
|
|
|
|
type DMChannelInfoModalProps = {
|
|
channel: DMChannelListItem
|
|
isModalVisible: boolean
|
|
setModalVisible: (visible: boolean) => void
|
|
}
|
|
|
|
const DMChannelInfoModal = ({ channel, isModalVisible, setModalVisible }: DMChannelInfoModalProps) => {
|
|
|
|
// Animation values
|
|
const modalHeight = useSharedValue(0)
|
|
const modalOpacity = useSharedValue(0)
|
|
|
|
const handleCloseModal = () => {
|
|
// Animate out
|
|
modalHeight.value = withTiming(0, { duration: 100, easing: Easing.out(Easing.ease) });
|
|
modalOpacity.value = withTiming(0, { duration: 100 });
|
|
setTimeout(() => setModalVisible(false), 100)
|
|
}
|
|
|
|
const handleGoToSharedMedia = () => {
|
|
setModalVisible(false)
|
|
router.push('./view-media', {
|
|
relativeToDirectory: true
|
|
})
|
|
}
|
|
|
|
const handleGoToPins = () => {
|
|
setModalVisible(false)
|
|
router.push('./pinned-messages', {
|
|
relativeToDirectory: true
|
|
})
|
|
}
|
|
|
|
// Animated styles for the modal
|
|
const animatedModalStyle = useAnimatedStyle(() => {
|
|
return {
|
|
height: modalHeight.value,
|
|
opacity: modalOpacity.value,
|
|
}
|
|
})
|
|
|
|
// Start animation when modal becomes visible
|
|
useEffect(() => {
|
|
if (isModalVisible) {
|
|
modalHeight.value = withTiming(165, { duration: 250, easing: Easing.out(Easing.ease) })
|
|
modalOpacity.value = withTiming(1, { duration: 250 })
|
|
}
|
|
}, [isModalVisible])
|
|
|
|
const { colors } = useColorScheme()
|
|
|
|
const pinnedMessages = channel.pinned_messages_string ? channel.pinned_messages_string.split('\n').length : 0
|
|
|
|
return (
|
|
<Modal
|
|
transparent={true}
|
|
visible={isModalVisible}
|
|
onRequestClose={handleCloseModal}>
|
|
<TouchableOpacity
|
|
style={styles.modalOverlay}
|
|
activeOpacity={1}
|
|
onPressOut={handleCloseModal}>
|
|
<Animated.View style={[styles.modalContent, animatedModalStyle]} className='bg-card dark:border dark:border-border'>
|
|
<ModalHeader channel={channel} handleCloseModal={handleCloseModal} />
|
|
<Divider className='my-2 mx-1' prominent />
|
|
<Pressable onPress={handleGoToSharedMedia}
|
|
className='rounded-xl ios:active:bg-linkColor'
|
|
android_ripple={{ color: 'rgba(0,0,0,0.1)', borderless: false }}>
|
|
<View className='flex-row items-center justify-between px-2'>
|
|
<View className='flex-row items-center'>
|
|
<HollowFilesIcon height={20} width={20} fill={colors.foreground} />
|
|
<Text style={styles.modalOption}>Images and Files</Text>
|
|
</View>
|
|
<ChevronRightIcon height={24} width={24} fill={colors.foreground} strokeWidth={'1px'} />
|
|
</View>
|
|
</Pressable>
|
|
<Pressable onPress={handleGoToPins}
|
|
className='rounded-xl ios:active:bg-linkColor'
|
|
android_ripple={{ color: 'rgba(0,0,0,0.1)', borderless: false }}>
|
|
<View className='flex-row items-center justify-between px-2'>
|
|
<View className='flex-row items-center'>
|
|
<PinOutlineIcon height={20} width={20} stroke={colors.foreground} />
|
|
<Text style={styles.modalOption}>Pins</Text>
|
|
</View>
|
|
<View className='flex-row items-center gap-1'>
|
|
{pinnedMessages > 0 ?
|
|
<Text className='text-sm text-foreground font-semibold'>{pinnedMessages}</Text>
|
|
: null
|
|
}
|
|
<ChevronRightIcon height={24} width={24} fill={colors.foreground} strokeWidth={'1px'} />
|
|
</View>
|
|
</View>
|
|
</Pressable>
|
|
</Animated.View>
|
|
</TouchableOpacity>
|
|
</Modal>
|
|
)
|
|
}
|
|
|
|
const ModalHeader = ({ channel, handleCloseModal }: { channel: DMChannelListItem, handleCloseModal: () => void }) => {
|
|
const { colors } = useColorScheme()
|
|
|
|
const peer = channel.peer_user_id
|
|
const isActive = useIsUserActive(peer)
|
|
const user = useGetUser(peer)
|
|
|
|
return (
|
|
<View className='flex-row items-center justify-between p-2'>
|
|
<View className='flex-row items-center'>
|
|
<TouchableOpacity onPress={handleCloseModal} hitSlop={10}>
|
|
<CrossIcon height={20} width={20} color={colors.foreground} />
|
|
</TouchableOpacity>
|
|
{channel && <View className='flex-row items-center ml-3 gap-2'>
|
|
<UserAvatar src={user?.user_image} alt={user?.full_name ?? peer}
|
|
isActive={isActive}
|
|
availabilityStatus={user?.availability_status}
|
|
avatarProps={{ className: "w-6 h-6" }}
|
|
fallbackProps={{ className: "rounded-[4px]" }}
|
|
textProps={{ className: "text-xs font-medium" }}
|
|
imageProps={{ className: "rounded-[4px]" }}
|
|
indicatorProps={{ className: "h-2 w-2" }} />
|
|
<View className='flex-row items-center gap-1.5'>
|
|
<Text className='text-base font-semibold'>{user?.full_name ?? peer}</Text>
|
|
{user?.type === 'Bot' ? <Text className='text-xs bg-card-background font-medium text-foreground/65 rounded-md px-1.5 py-0.5'>{user?.type}</Text> : null}
|
|
</View>
|
|
</View>}
|
|
</View>
|
|
{/* <TouchableOpacity hitSlop={10}>
|
|
<ThreeHorizontalDots height={20} width={20} color={colors.foreground} />
|
|
</TouchableOpacity> */}
|
|
</View>
|
|
)
|
|
}
|
|
|
|
const styles = StyleSheet.create({
|
|
modalOverlay: {
|
|
flex: 1,
|
|
justifyContent: 'flex-start',
|
|
alignItems: 'flex-end',
|
|
backgroundColor: 'rgba(0, 0, 0, 0.5)',
|
|
paddingTop: Platform.OS === 'ios' ? 60 : 8,
|
|
},
|
|
modalContent: {
|
|
width: '95%',
|
|
borderRadius: 10,
|
|
padding: 10,
|
|
marginRight: 10,
|
|
overflow: 'hidden',
|
|
boxShadow: '0px 0px 10px 0px rgba(0, 0, 0, 0.5)',
|
|
},
|
|
modalOption: {
|
|
padding: 10,
|
|
fontSize: 16,
|
|
}
|
|
})
|
|
|
|
|
|
export default DMChannelInfoModal |