ChatOptionsBlock.tsx 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148
  1. import React, { useCallback } from 'react';
  2. import { View, Text, TouchableOpacity, StyleSheet, Dimensions } from 'react-native';
  3. import { MaterialCommunityIcons } from '@expo/vector-icons';
  4. import * as ImagePicker from 'expo-image-picker';
  5. import { Colors } from 'src/theme';
  6. const SCREEN_HEIGHT = Dimensions.get('window').height;
  7. interface MediaFile {
  8. uri: string;
  9. type: 'image';
  10. }
  11. interface Props {
  12. blockHeight: number;
  13. closeOptions: () => void;
  14. onSendMedia: (media: MediaFile[]) => void;
  15. onSendLocation: (coords: { latitude: number; longitude: number }) => void;
  16. onShareLiveLocation: () => void;
  17. }
  18. const ChatOptionsBlock: React.FC<Props> = ({
  19. blockHeight,
  20. closeOptions,
  21. onSendMedia,
  22. onSendLocation,
  23. onShareLiveLocation
  24. }) => {
  25. const handleOpenGallery = useCallback(async () => {
  26. try {
  27. const result = await ImagePicker.launchImageLibraryAsync({
  28. mediaTypes: ImagePicker.MediaTypeOptions.Images,
  29. allowsMultipleSelection: true,
  30. quality: 1,
  31. selectionLimit: 4
  32. });
  33. if (!result.canceled && result.assets) {
  34. const files = result.assets.map((asset) => ({
  35. uri: asset.uri,
  36. type: 'image'
  37. }));
  38. onSendMedia(files);
  39. }
  40. closeOptions();
  41. } catch (err) {
  42. console.warn('Gallery error: ', err);
  43. }
  44. }, [onSendMedia, closeOptions]);
  45. const handleOpenCamera = useCallback(async () => {
  46. try {
  47. const perm = await ImagePicker.requestCameraPermissionsAsync();
  48. if (!perm.granted) {
  49. console.warn('Permission for camera not granted');
  50. return;
  51. }
  52. const result = await ImagePicker.launchCameraAsync({
  53. mediaTypes: ImagePicker.MediaTypeOptions.Images,
  54. quality: 1
  55. });
  56. if (!result.canceled && result.assets) {
  57. const files = result.assets.map((asset) => ({
  58. uri: asset.uri,
  59. type: asset.type === 'video' ? 'video' : 'image'
  60. }));
  61. onSendMedia(files);
  62. }
  63. closeOptions();
  64. } catch (err) {
  65. console.warn('Camera error: ', err);
  66. }
  67. }, [onSendMedia, closeOptions]);
  68. const handleShareLocation = useCallback(async () => {
  69. try {
  70. const coords = { latitude: 50.4501, longitude: 30.5234 };
  71. onSendLocation(coords);
  72. closeOptions();
  73. } catch (err) {
  74. console.warn('Location error: ', err);
  75. }
  76. }, [onSendLocation, closeOptions]);
  77. const handleShareLiveLocation = useCallback(() => {
  78. onShareLiveLocation();
  79. closeOptions();
  80. }, [onShareLiveLocation, closeOptions]);
  81. return (
  82. <View style={[styles.container, { height: blockHeight }]}>
  83. <View style={styles.optionRow}>
  84. <TouchableOpacity style={styles.optionItem} onPress={handleOpenGallery}>
  85. <MaterialCommunityIcons name="image" size={36} color={Colors.ORANGE} />
  86. <Text style={styles.optionLabel}>Gallery</Text>
  87. </TouchableOpacity>
  88. <TouchableOpacity style={styles.optionItem} onPress={handleOpenCamera}>
  89. <MaterialCommunityIcons name="camera" size={36} color={Colors.ORANGE} />
  90. <Text style={styles.optionLabel}>Camera</Text>
  91. </TouchableOpacity>
  92. <TouchableOpacity style={styles.optionItem} onPress={handleShareLocation}>
  93. <MaterialCommunityIcons name="map-marker" size={36} color={Colors.ORANGE} />
  94. <Text style={styles.optionLabel}>Location</Text>
  95. </TouchableOpacity>
  96. <TouchableOpacity style={styles.optionItem} onPress={handleShareLiveLocation}>
  97. <MaterialCommunityIcons name="navigation" size={36} color={Colors.ORANGE} />
  98. <Text style={styles.optionLabel}>Live</Text>
  99. </TouchableOpacity>
  100. {/* <TouchableOpacity style={styles.optionItem}>
  101. <MegaphoneIcon fill={Colors.RED} width={36} height={36} />
  102. <Text style={styles.optionLabel}>Report</Text>
  103. </TouchableOpacity> */}
  104. </View>
  105. </View>
  106. );
  107. };
  108. export default ChatOptionsBlock;
  109. const styles = StyleSheet.create({
  110. container: {
  111. backgroundColor: Colors.FILL_LIGHT
  112. },
  113. optionRow: {
  114. flexDirection: 'row',
  115. justifyContent: 'space-between',
  116. paddingHorizontal: '5%',
  117. marginVertical: 20,
  118. flexWrap: 'wrap'
  119. },
  120. optionItem: {
  121. width: '30%',
  122. paddingVertical: 8,
  123. marginBottom: 12,
  124. alignItems: 'center'
  125. },
  126. optionLabel: {
  127. marginTop: 6,
  128. fontSize: 12,
  129. color: Colors.DARK_BLUE,
  130. fontWeight: '700'
  131. }
  132. });