Advertisement
devil2010

Untitled

Jun 2nd, 2022
186
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 36.00 KB | None | 0 0
  1.  
  2. import React, { useEffect, useState, useCallback, useRef, useMemo, useContext } from 'react';
  3. import { useFocusEffect } from '@react-navigation/native';
  4. import {
  5. StyleSheet, View, Text, Dimensions,
  6. TouchableOpacity, SearchBar, StatusBar,
  7. FlatList, Button,
  8. PlatformColor, Image, Icon,
  9. Platform, Keyboard,
  10. ImageBackground,
  11. InteractionManager,
  12. Pressable,
  13. KeyboardAvoidingView,
  14. PermissionsAndroid,
  15. LayoutAnimation,
  16. UIManager,
  17. SafeAreaView,
  18. TextInput,
  19. TouchableHighlight
  20. } from "react-native";
  21. import TrackPlayer from 'react-native-track-player';
  22. import ViewOverflow from 'react-native-view-overflow'
  23. import {SwipeButtonsContainer, SwipeProvider, SwipeItem} from '../../libraries/swipetoreply/swipeIndex';
  24. import RNAndroidKeyboardAdjust from 'rn-android-keyboard-adjust'
  25. import * as Animatable from 'react-native-animatable';
  26. import * as ApiConstant from '../../network/ApiConstant'
  27. import OverlayContainer from '../../customview/OverlayContainer'
  28. import ContextMenu from "react-native-context-menu-view";
  29. import MaterialCommunityIcons from 'react-native-vector-icons/MaterialCommunityIcons';
  30. import MaterialIcons from 'react-native-vector-icons/MaterialIcons'
  31. import { DefaultNavigationBackButton } from '../../appcomponent/DefaultNavigationBackButton';
  32. import { ThemeContext } from '../../context/ThemeContext';
  33. import uuid from 'react-native-uuid'
  34. import * as RootNavigation from '../../utils/navigation/RootNavigation';
  35. import {
  36. GiftedChat, Bubble, Send, SendIcon, InputToolbar, Actions, Composer,
  37. Avatar, SystemMessage, Message, MessageImage, MessageText, Day, Time, utils,
  38. AccessoryBar, TypingIndicator
  39. } from 'react-native-gifted-chat/';
  40. import { useDebounce } from '../../appcomponent/debound';
  41. import ImageModal from 'react-native-image-modal'
  42. import { ActivityIndicator } from 'react-native-paper';
  43. import { useSafeAreaInsets } from 'react-native-safe-area-context';
  44. import { useKeyboard } from '@react-native-community/hooks'
  45. import { ChatEmojiKeyboardInput } from '../../appcomponent/chatcomponent/ChatEmojiKeyboardInput';
  46. import { ChatMoreKeyboardInput } from '../../appcomponent/chatcomponent/ChatMoreKeyboardInput';
  47. import { ChatMultiImage } from '../../appcomponent/chatcomponent/ChatMultiImage';
  48. import { ChatImage } from '../../appcomponent/chatcomponent/ChatImage';
  49. import { ChatVideo } from '../../appcomponent/chatcomponent/ChatVideo';
  50. import { ChatVoiceKeyboardInput } from '../../appcomponent/chatcomponent/ChatVoiceKeyboardInput';
  51. import { Overlay } from 'react-native-elements';
  52. import { ImageViewerContext } from '../../context/ImageViewerContext';
  53. import { MentionInput } from '../../appcomponent/chatcomponent/MentionInput';
  54. import FastImage from 'react-native-fast-image';
  55. import { ChatSticker } from '../../appcomponent/chatcomponent/ChatSticker';
  56. import { ChatVoice } from '../../appcomponent/chatcomponent/ChatVoice';
  57. import { ChatReply } from '../../appcomponent/chatcomponent/ChatReply';
  58. import KeyboardSpacer from 'react-native-keyboard-spacer';
  59. import CustomComposer from '../../customview/CustomComposer';
  60. import { mentionRegEx, replaceMentionValues } from 'react-native-controlled-mentions';
  61. import { ChatMentionView } from '../../appcomponent/chatcomponent/ChatMentionView';
  62. import { useMentions } from 'react-native-controlled-mentions/'
  63.  
  64. const dimensions = Dimensions.get('window');
  65. const KeyboardAccessoryView = Keyboard.KeyboardAccessoryView;
  66. const DefaultKeyboardHeight = 300
  67. const KEYBOARD_SYSTEM = null
  68. const KEYBOARD_EMOJI = 1
  69. const KEYBOARD_MORE = 2
  70. const KEYBOARD_VOICE = 3
  71.  
  72. var lastClickButtonTime = 0 //for avoid click multiply time into button continues
  73. const CLICK_THRESHOLD = 700
  74.  
  75. const currentUser = {
  76. _id: 1,
  77. name: 'do dung',
  78. avatar: 'https://avatars.githubusercontent.com/u/8202437'
  79. }
  80.  
  81. export default function ChatScreen({ navigation }) {
  82. const { theme } = React.useContext(ThemeContext)
  83. const { viewImages } = React.useContext(ImageViewerContext)
  84. const insets = useSafeAreaInsets()
  85. const keyboardHandler = useKeyboard()
  86. const inputRef = useRef()
  87.  
  88. const [isLoadMore, setLoadMore] = React.useState(false)
  89. const [messages, setMessage] = React.useState([])
  90. const [replyMessage, setReplyMessage] = React.useState()
  91. const [text, setText] = useState('');
  92. const [isTyping, setIsTyping] = useState(false)
  93. const [isSwiping, setSwiping] = useState(false)
  94. const [customKeyboard, setCustomKeyboard] = useState(KEYBOARD_SYSTEM)
  95.  
  96.  
  97. const getKbHeight = (keyboardHandler.keyboardHeight == 0 ? DefaultKeyboardHeight
  98. : keyboardHandler.keyboardHeight) - insets.bottom
  99.  
  100. const { textInputProps, triggers } = useMentions({
  101. value: text,
  102. onChange: setText,
  103.  
  104. triggersConfig,
  105. patternsConfig,
  106. });
  107.  
  108. useEffect(() => {
  109. UIManager.setLayoutAnimationEnabledExperimental && UIManager.setLayoutAnimationEnabledExperimental(true);
  110. navigation.setOptions({
  111. headerLeft: props => <DefaultNavigationBackButton navigation={navigation} />,
  112. headerTitle: props => <ChatHeader name={'Chat'} desc={'Online'} />,
  113. headerRight: props => <CallHeader {...props} />,
  114. headerStyle: {
  115. backgroundColor: theme.navBackground,
  116. borderBottomWidth: 1,
  117. borderBottomColor: '#E8E8E8',
  118. },
  119. headerTintColor: theme.navigationButton,
  120. headerTitleAlign: 'center',
  121. headerBackVisible: false
  122. })
  123. setMessage(messagesSample.sort((a, b) => b.createdAt - a.createdAt))
  124. requestPermission()
  125. return () => {
  126. TrackPlayer.stop()
  127. RNAndroidKeyboardAdjust.setAdjustResize()
  128. }
  129. }, [])
  130.  
  131. useEffect(() => {
  132. if (keyboardHandler.keyboardShown) {
  133. if (customKeyboard != KEYBOARD_SYSTEM) {
  134. setCustomKeyboard(KEYBOARD_SYSTEM)
  135. }
  136. }
  137. }, [keyboardHandler.keyboardShown])
  138.  
  139. const requestPermission = async () => {
  140. // await PermissionsAndroid.requestMultiple([
  141. // PermissionsAndroid.PERMISSIONS.RECORD_AUDIO,
  142. // ]);
  143. };
  144.  
  145. const hideReplyView = () => {
  146. setReplyMessage()
  147. }
  148.  
  149. const handleLoadMore = () => {
  150. setLoadMore(true)
  151. console.log('handleLoadMore')
  152. setMessage(prev => GiftedChat.prepend(prev, loadMoreSample))
  153. }
  154.  
  155. const onSend = React.useCallback((messages = []) => {
  156. hideReplyView()
  157. appendMessage(messages)
  158. })
  159.  
  160. const onSelectEmoji = React.useCallback((emoji) => {
  161. const message = [{
  162. _id: uuid.v4(),
  163. user: currentUser,
  164. createdAt: new Date(),
  165. sticker: ApiConstant.MAIN_SERVER + emoji.Data,
  166. }]
  167. appendMessage(message)
  168. })
  169.  
  170. const onSendVoice = React.useCallback((voiceUrl) => {
  171. const message = [{
  172. _id: uuid.v4(),
  173. user: currentUser,
  174. createdAt: new Date(),
  175. voice: voiceUrl,
  176. }]
  177. appendMessage(message)
  178. })
  179.  
  180. const onReply = React.useCallback((message) => {
  181. appendMessage(message)
  182. })
  183.  
  184. const appendMessage = (message) => {
  185. LayoutAnimation.configureNext(LayoutAnimation.Presets.easeInEaseOut);
  186. setMessage(prev => GiftedChat.append(prev, message))
  187. if (message[0].user._id == currentUser._id) {
  188. inputRef.current.scrollToBottom()
  189. }
  190. }
  191.  
  192. const renderUserName = (props) => {
  193. const { user = {} } = props.currentMessage
  194. const { user: pUser = {} } = props.previousMessage
  195. const isSameUser = pUser._id === user._id
  196. const isSelf = user._id === 1
  197. const isSameDate = utils.isSameDay(props.currentMessage, props.previousMessage)
  198. const shouldNotRenderName = (isSameUser && isSameDate) || isSelf
  199. return shouldNotRenderName ? (
  200. <View />
  201. ) : (
  202. <Text
  203. style={{
  204. marginBottom: 4,
  205. color: theme.defaultText,
  206. fontSize: 12
  207. }}>
  208. {user.name}
  209. </Text>
  210. )
  211. }
  212.  
  213. const renderBubble = (props) => {
  214. return (
  215. <View>
  216. {renderUserName(props)}
  217. {/* <Animatable.View animation="slideInUp" duration={200} easing='ease-in-out'> */}
  218. <ContextMenu
  219. // preview={<View style={{ width: 100, height: 100, backgroundColor: 'green'}} />}
  220. style={{
  221. backgroundColor: 'transparent'
  222. }}
  223. previewBackgroundColor='transparent'
  224. actions={[
  225. { title: 'Pin', systemIcon: 'pin' },
  226. { title: 'Edit', systemIcon: 'pencil' },
  227. {
  228. title: 'Delete',
  229. destructive: true,
  230. inlineChildren: true,
  231. systemIcon: 'trash',
  232. },
  233. ]}
  234. onCancel={() => {
  235. }}
  236. onPress={(e) => {
  237. if (e.nativeEvent.index == 0) {
  238. setReplyMessage(props.currentMessage)
  239. inputRef.current.textInput.focus()
  240. } else if (e.nativeEvent.index == 2) {
  241. setMessage(prevMessage => prevMessage.filter(mes => mes._id != props.currentMessage._id))
  242. }
  243. }}>
  244.  
  245. {props.currentMessage.text ? <Bubble
  246. {...props}
  247. containerStyle={{
  248. left: {
  249. backgroundColor: 'transparent',
  250. marginRight: 60,
  251. },
  252. right: {
  253. backgroundColor: 'transparent',
  254. marginLeft: 60
  255. }
  256. }}
  257. wrapperStyle={{
  258. left: {
  259. borderRadius: 8,
  260. backgroundColor: theme.leftChatBubbleBg,
  261. marginRight: 0,
  262. },
  263. right: {
  264. borderRadius: 8,
  265. backgroundColor: theme.rightChatBubbleBg,
  266. marginLeft: 0
  267. },
  268. }}
  269. textStyle={{
  270. left: {
  271. color: 'black',
  272. padding: 4
  273. },
  274. right: {
  275. color: theme.rightChatBubbleText,
  276. padding: 4
  277. },
  278. }}
  279. /> : null}
  280.  
  281. {renderMultiImageView(props)}
  282. {renderImageView(props)}
  283. {renderVideoView(props)}
  284. {renderSticker(props)}
  285. {renderVoice(props)}
  286. </ContextMenu>
  287. {/* </Animatable.View> */}
  288. </View>
  289. )
  290. }
  291.  
  292. const renderAvatar = (props) => {
  293. const { user = {} } = props.currentMessage
  294. const { user: pUser = {} } = props.previousMessage
  295. const isSameUser = pUser._id === user._id
  296. const isSelf = user._id === 1
  297. const isSameDate = utils.isSameDay(props.currentMessage, props.previousMessage)
  298. const shouldNotRenderName = (isSameUser && isSameDate) || isSelf
  299. if (shouldNotRenderName) return <View />
  300. return (
  301. <Avatar
  302. {...props}
  303. containerStyle={{
  304. left: {
  305. marginTop: 19,
  306. marginRight: 0,
  307. }
  308. }}
  309. imageStyle={{
  310. left: {
  311. backgroundColor: 'lightgray',
  312. }
  313. }}
  314. />
  315. );
  316. }
  317.  
  318. const renderInputToolbar = (props) => {
  319. return <InputToolbar
  320. {...props}
  321. containerStyle={{
  322. alignContent: 'center',
  323. justifyContent: 'center',
  324. alignItems: 'center',
  325. backgroundColor: theme.navBackground,
  326. }}
  327. placeholder='Message...'
  328. />
  329. }
  330.  
  331. const renderComposer = (props) => {
  332. return <>
  333. <CustomComposer
  334. {...props}
  335. containerStyle={{
  336. justifyContent: 'center',
  337. alignContent: 'center'
  338. }}
  339. textInputMentionProps={textInputProps}
  340. textInputStyle={{
  341. backgroundColor: theme.chatInputTextBg,
  342. borderRadius: 10,
  343. paddingTop: 10,
  344. paddingLeft: 10,
  345. paddingRight: 40,
  346. fontSize: 16,
  347. marginLeft: 12,
  348. marginRight: 15,
  349. }} />
  350. <Actions
  351. {...props}
  352. containerStyle={{
  353. position: 'absolute',
  354. right: 60,
  355. alignSelf: 'center'
  356. }}
  357. icon={() => <MaterialCommunityIcons
  358. size={25}
  359. color={theme.chatSendBtn}
  360. name={customKeyboard == KEYBOARD_EMOJI ? 'keyboard' : 'emoticon-happy'} />}
  361. onPressActionButton={() => {
  362. handleChangeKeyboardType(KEYBOARD_EMOJI)
  363. }} />
  364. </>
  365. }
  366.  
  367. const renderActions = (props) => {
  368. if(props.text.length > 0) return <View/>
  369. return <Actions
  370. {...props}
  371. icon={() => <MaterialIcons
  372. size={25}
  373. style={{
  374. alignSelf: 'center',
  375. alignItems: 'center',
  376. justifyContent: 'center',
  377. alignContent: 'center'
  378. }}
  379. color={theme.chatSendBtn}
  380. name={'more-horiz'} />}
  381. onPressActionButton={() => {
  382. handleChangeKeyboardType(KEYBOARD_MORE)
  383. }}/>
  384. }
  385.  
  386. const renderReplyButton = (
  387. <SwipeButtonsContainer
  388. style={{
  389. alignSelf: 'center',
  390. alignContent: 'center',
  391. justifyContent: 'center',
  392. // aspectRatio: 1,
  393. flex: 1,
  394. flexDirection: 'row',
  395. paddingRight: 20
  396. // padding: 10,
  397. }}>
  398. <Animatable.View
  399. animation='bounceInUp'>
  400. <MaterialCommunityIcons size={28} name={'reply-circle'} color={theme.mainBlue} />
  401. </Animatable.View>
  402. </SwipeButtonsContainer>
  403. );
  404.  
  405. const renderMessage = (props) => {
  406. return props.currentMessage.system ?
  407. <Message
  408. {...props} />
  409. :
  410. <SwipeItem
  411. disableSwipeIfNoButton
  412. onSwipeInitial={() => {
  413. setSwiping(true)
  414. }}
  415. onMovedToOrigin={isReply => {
  416. setSwiping(false)
  417. if (isReply) {
  418. setReplyMessage(props.currentMessage)
  419. inputRef.current.textInput.focus()
  420. }
  421. }}
  422. rightButtons={renderReplyButton}
  423. style={{
  424. flex: 1,
  425. }}>
  426. <Message
  427. {...props} />
  428. </SwipeItem>
  429. }
  430.  
  431. const renderSendBtn = props => {
  432. return (
  433. <Send {...props}
  434. containerStyle={{
  435. justifyContent: 'center',
  436. alignSelf: 'center',
  437. marginRight: 12
  438. }}>
  439.  
  440. {!props.text ?
  441. <TouchableOpacity
  442. onPress={() => {
  443. handleChangeKeyboardType(KEYBOARD_VOICE)
  444. }}>
  445. <MaterialCommunityIcons
  446. size={25}
  447. style={{
  448. marginTop: 2
  449. }}
  450. color={theme.chatSendBtn}
  451. name={'microphone'} />
  452. </TouchableOpacity> :
  453.  
  454. <MaterialCommunityIcons
  455. size={25}
  456. style={{
  457. marginTop: 2
  458. }}
  459. color={theme.chatSendBtn}
  460. name={'send'} />}
  461.  
  462. </Send>
  463. );
  464. }
  465.  
  466. const renderLoadEarlier = (props) => {
  467. if (isLoadMore) {
  468. return <ActivityIndicator {...props} style={{ margin: 10 }} />
  469. }
  470. return null
  471. }
  472.  
  473. const renderSystemMessage = props => {
  474. return (
  475. <SystemMessage
  476. {...props}
  477. containerStyle={{
  478. marginBottom: 15,
  479. }}
  480. textStyle={{
  481. fontStyle: 'italic',
  482. fontSize: 12,
  483. color: 'gray'
  484. }}
  485. />
  486. );
  487. }
  488.  
  489. const renderMessageText = props => {
  490. return (
  491. <MessageText
  492. {...props}
  493. />
  494. );
  495. }
  496.  
  497. const renderCustomView = (props) => {
  498. // if(props.currentMessage.images){
  499. // renderMultiImageView()
  500. // }
  501. return null
  502. };
  503.  
  504. const renderMultiImageView = (props) => {
  505. if (props.currentMessage.images) {
  506. return <ChatMultiImage {...props} />
  507. }
  508. return null
  509. }
  510.  
  511. const renderVideoView = (props) => {
  512. if (props.currentMessage.video) {
  513. return <ChatVideo {...props} />
  514. }
  515. return null
  516. }
  517.  
  518. const renderImageView = (props) => {
  519. if (props.currentMessage.image) {
  520. return <ChatImage {...props} />
  521. }
  522. return null
  523. }
  524.  
  525. const renderVoice = (props) => {
  526. if (props.currentMessage.voice) {
  527. return <ChatVoice {...props} />
  528. }
  529. return null
  530. }
  531.  
  532. const renderSticker = (props) => {
  533. if (props.currentMessage.sticker) {
  534. return <ChatSticker {...props} />
  535. }
  536. return null
  537. }
  538.  
  539. const renderChatEmpty = () => {
  540. return <View
  541. style={{
  542. transform: [{ scaleY: -1 }],
  543. flex: 1,
  544. color: 'gray',
  545. fontStyle: 'italic',
  546. justifyContent: 'center',
  547. alignItems: 'center'
  548. }}>
  549. <Text style={{
  550. color: 'gray',
  551. fontStyle: 'italic'
  552. }}>No messages yet</Text>
  553. </View>
  554. }
  555.  
  556. const renderTime = (props) => {
  557. // console.log(props.currentMessage.text)
  558. if (!props.currentMessage.text) { return null }
  559. if (utils.isSameUser(props.currentMessage, props.nextMessage)
  560. && utils.isSameDay(props.currentMessage, props.nextMessage)) {
  561. return null
  562. }
  563. return <Time
  564. {...props}
  565. timeTextStyle={{
  566. left: {
  567. color: 'darkgray',
  568. paddingLeft: 4,
  569. textAlign: 'left',
  570. },
  571. right: {
  572. }
  573. }} />
  574. }
  575.  
  576. const renderFooter = (props) => {
  577. return <View>
  578. <TypingIndicator isTyping={isTyping} />
  579. </View>
  580. }
  581.  
  582. const renderChatFooter = (props) => {
  583. return <>
  584. <ChatMentionView suggestions={users} {...triggers.mention} />
  585. {replyMessage ? <ChatReply {...props} message={replyMessage} hideReplyView={hideReplyView} /> : null}
  586. </>
  587. }
  588.  
  589. const renderAccessory = (props) => {
  590. if (customKeyboard == KEYBOARD_EMOJI) return <ChatEmojiKeyboardInput width={dimensions.width} height={getKbHeight} onSelectEmoji={onSelectEmoji} />
  591. if (customKeyboard == KEYBOARD_MORE) return <ChatMoreKeyboardInput width={dimensions.width} height={getKbHeight} />
  592. if (customKeyboard == KEYBOARD_VOICE) return <ChatVoiceKeyboardInput width={dimensions.width} height={getKbHeight} onSendVoice={onSendVoice} />
  593. return null
  594. }
  595.  
  596. const renderScrollToBottom = (props) => {
  597. return <MaterialCommunityIcons name={'arrow-down'} size={20} color={'white'} />
  598. }
  599.  
  600. const handleChangeKeyboardType = (newKeyboardType) => {
  601. if(new Date().getTime() - lastClickButtonTime < CLICK_THRESHOLD) {
  602. return
  603. }
  604. if (customKeyboard == KEYBOARD_SYSTEM) {
  605. // RNAndroidKeyboardAdjust.setAdjustNothing()
  606. setCustomKeyboard(newKeyboardType)
  607. if (keyboardHandler.keyboardShown) {
  608. try { Keyboard.dismiss() } catch (error) { console.log(error) }
  609. } else {
  610. //force android show when click button + keboard not show
  611. if (Platform.OS == 'android') {
  612. // inputRef.current.setMinInputToolbarHeight(getKbHeight)
  613. }
  614. }
  615. //ios always modify container height
  616. // if(Platform.OS == 'ios'){
  617. inputRef.current.setMinInputToolbarHeight(getKbHeight)
  618. // RNAndroidKeyboardAdjust.setAdjustResize()
  619. // }
  620. inputRef.current.scrollToBottom()
  621. setTimeout(() => {
  622. // RNAndroidKeyboardAdjust.setAdjustResize()
  623. }, 800);
  624.  
  625. } else {
  626. if (customKeyboard == newKeyboardType) {
  627. // RNAndroidKeyboardAdjust.setAdjustNothing()
  628. if (!keyboardHandler.keyboardShown) {
  629. try { inputRef.current.textInput.focus() } catch (error) { console.log(error) }
  630. // if(Platform.OS == 'android'){
  631. // inputRef.current.setMinInputToolbarHeight(getKbHeight)
  632. // }
  633. } else {
  634. // inputRef.current.setMinInputToolbarHeight(0)
  635. }
  636. setTimeout(() => {
  637. setCustomKeyboard(KEYBOARD_SYSTEM)
  638. }, 50);
  639.  
  640. } else {
  641. // RNAndroidKeyboardAdjust.setAdjustResize()
  642. setCustomKeyboard(newKeyboardType)
  643. }
  644. }
  645. lastClickButtonTime = new Date().getTime()
  646. }
  647.  
  648. return (
  649. <ImageBackground
  650. // source={require('../../assets/link_light.png')}
  651. style={{
  652. flex: 1,
  653. backgroundColor: theme.navBackground,
  654. }}>
  655.  
  656. <GiftedChat
  657. text={text}
  658. onInputTextChanged={setText}
  659. ref={inputRef}
  660. bottomOffset={insets.bottom}
  661. renderBubble={renderBubble}
  662. renderLoading={() => <ActivityIndicator size="small" color="#0000ff" />}
  663. renderInputToolbar={renderInputToolbar}
  664. renderComposer={renderComposer}
  665. timeFormat='LT'
  666. locale='vi'
  667. dateFormat='DD/MM/YYYY'
  668. renderSend={renderSendBtn}
  669. renderAvatar={renderAvatar}
  670. renderActions={renderActions}
  671. renderMessage={renderMessage}
  672. renderMessageText={renderMessageText}
  673. renderSystemMessage={renderSystemMessage}
  674. renderChatEmpty={renderChatEmpty}
  675. renderTime={renderTime}
  676. renderAccessory={renderAccessory}
  677. accessoryStyle={{ height: customKeyboard != KEYBOARD_SYSTEM ? getKbHeight : 0 }}
  678. // minInputToolbarHeight={ customKeyboard != KEYBOARD_SYSTEM ? getKbHeight : 44 }
  679. renderChatFooter={renderChatFooter}
  680. renderCustomView={renderCustomView}
  681. renderMessageVideo={() => { }}
  682. messagesContainerStyle={{
  683. backgroundColor: theme.background
  684. }}
  685. parsePatterns={(linkStyle) => [
  686. {
  687. pattern: /#(\w+)/,
  688. style: linkStyle,
  689. onPress: (tag) => console.log(`Pressed on hashtag: ${tag}`),
  690. },
  691. {
  692. pattern: mentionRegEx,
  693. style: {fontWeight: 'bold', color: theme.mainOrangeColor},
  694. renderText: (value) => replaceMentionValues(value, ({name}) => `@${name}`),
  695. onPress: (value) => alert(`clicked: ${value}`)
  696. },
  697. ]}
  698. extraData={{ replyMessage, isLoadMore, customKeyboard, isSwiping}}
  699. isTyping={isTyping}
  700. messages={messages}
  701. onSend={messages => onSend(messages)}
  702. onLongPress={() => { }}
  703. onPressAvatar={() => {
  704. setIsTyping(!isTyping)
  705. }}
  706. listViewProps={{
  707. contentContainerStyle: { flexGrow: 1, justifyContent: "flex-end" },
  708. keyboardDismissMode: 'on-drag',
  709. nestedScrollEnabled: true,
  710. scrollEnabled: !isSwiping,
  711. // initialNumToRender: 15,
  712. showsVerticalScrollIndicator: true
  713. }}
  714. maxInputLength={500}
  715. textInputProps={{
  716. keyboardAppearance: theme.keyboard,
  717. autoCorrect: false,
  718. autoCapitalize: 'none',
  719. autoGrow: true,
  720. }}
  721. shouldUpdateMessage={() => {
  722. return true;
  723. }}
  724. maxComposerHeight={100}
  725. disableComposer={false}
  726. user={currentUser}
  727. // showAvatarForEveryMessage
  728. isCustomViewBottom
  729. inverted
  730. infiniteScroll
  731. // alignTop
  732. alwaysShowSend
  733. scrollToBottom
  734. scrollToBottomComponent={renderScrollToBottom}
  735. scrollToBottomStyle={{
  736. backgroundColor: theme.mainOrangeColor,
  737. bottom: 22
  738. }}
  739. onLoadEarlier={handleLoadMore}
  740. // loadEarlier={true}
  741. // isLoadingEarlier={isLoadMore}
  742. renderLoadEarlier={renderLoadEarlier}
  743. // showUserAvatar
  744. renderAvatarOnTop
  745. renderUsernameOnMessage={false}
  746. // forceGetKeyboardHeight={customKeyboard != KEYBOARD_SYSTEM}
  747. // wrapInSafeArea={Platform.OS === 'android'}
  748. keyboardShouldPersistTaps={'handled'}
  749. isKeyboardInternallyHandled={customKeyboard == KEYBOARD_SYSTEM || !keyboardHandler.keyboardShown}
  750. // isKeyboardInternallyHandled={false}
  751. />
  752. </ImageBackground>
  753. )
  754. }
  755.  
  756.  
  757. const ChatHeader = (props) => {
  758. const { theme } = React.useContext(ThemeContext)
  759.  
  760. return (
  761. <TouchableOpacity style={{
  762. }} onPress={() => {
  763. // RootNavigation.push("Setting")
  764. }}>
  765. <View style={{
  766. flexDirection: 'column',
  767. justifyContent: 'center',
  768. alignItems: 'center'
  769. }}>
  770. <Text
  771. numberOfLines={1}
  772. ellipsizeMode='tail'
  773. style={{
  774. maxWidth: 120,
  775. fontSize: 17,
  776. fontWeight: '700',
  777. color: theme.defaultText
  778. }}>{props.name}</Text>
  779. {/* <LinearGradient colors={['transparent']}> */}
  780. <Text
  781. numberOfLines={1}
  782. ellipsizeMode='tail'
  783. style={{
  784. marginTop: 2,
  785. maxWidth: 120,
  786. fontSize: 11,
  787. fontWeight: '600',
  788. color: 'gray'
  789. }}>{props.desc}</Text>
  790. {/* </LinearGradient> */}
  791. </View>
  792. </TouchableOpacity>
  793. )
  794. }
  795.  
  796. const CallHeader = (props) => {
  797. const { theme } = React.useContext(ThemeContext)
  798. return (
  799. <View style={{
  800. flexDirection: 'row',
  801. justifyContent: 'center',
  802. alignItems: 'center'
  803. }}>
  804. <TouchableOpacity onPress={() => {
  805. }}>
  806. <MaterialIcons name='phone-forwarded' color={theme.navigationButton} size={24} style={{ marginRight: 24 }} />
  807. </TouchableOpacity>
  808. <TouchableOpacity onPress={() => {
  809. RootNavigation.navigate('GroupCall')
  810. }}>
  811. <MaterialIcons name='videocam' color={theme.navigationButton} size={28} style={{ marginBottom: 3 }} />
  812. </TouchableOpacity>
  813.  
  814. </View>
  815.  
  816. )
  817. }
  818.  
  819. const messagesSample = [
  820. {
  821. _id: 'fap',
  822. createdAt: new Date(new Date().getTime() - 1000),
  823. user: {
  824. _id: 2,
  825. name: 'React dsad',
  826. },
  827. voice: 'https://www.chosic.com/wp-content/uploads/2021/07/The-Epic-Hero-Epic-Cinematic-Keys-of-Moon-Music.mp3'
  828. },
  829. {
  830. _id: 'fap1',
  831. createdAt: new Date(),
  832. user: currentUser,
  833. // text: 'nhu cac'
  834. voice: 'https://codeskulptor-demos.commondatastorage.googleapis.com/GalaxyInvaders/theme_01.mp3'
  835. },
  836. {
  837. _id: 2,
  838. text: 'Hello developer 2',
  839. sent: true,
  840. createdAt: new Date(Date.UTC(2016, 5, 12, 17, 20, 0)),
  841. user: {
  842. _id: 2,
  843. name: 'React dsad',
  844. },
  845. },
  846. {
  847. _id: 3,
  848. // text: 'Hi! ',
  849. createdAt: new Date(Date.UTC(2011, 2, 13, 17, 20, 0)),
  850. sent: true,
  851. received: true,
  852. peding: true,
  853. user: {
  854. _id: 1,
  855. name: 'React Native',
  856. avatar: 'https://placeimg.com/140/140/any',
  857. },
  858. image: 'https://picsum.photos/id/33/900/900'
  859. },
  860. {
  861. _id: 4,
  862. text: 'This is a quick reply. Do you love Gifted Chat? (radio) KEEP IT',
  863. createdAt: new Date(Date.UTC(2016, 5, 14, 17, 20, 0)),
  864. user: {
  865. _id: 2,
  866. name: 'React Native',
  867. avatar: 'https://placeimg.com/140/140/any',
  868. }
  869. },
  870. {
  871. _id: 5,
  872. text: 'This is a quick reply. Do you love Gifted Chat? (checkbox)',
  873. createdAt: new Date(Date.UTC(2016, 5, 15, 17, 20, 0)),
  874. user: {
  875. _id: 2,
  876. name: 'React Native',
  877. avatar: 'https://placeimg.com/140/140/any',
  878. }
  879. },
  880. {
  881. _id: 6,
  882. text: 'Come on!',
  883. createdAt: new Date(Date.UTC(2016, 5, 16, 18, 22, 0)),
  884. user: {
  885. _id: 2,
  886. name: 'React Native',
  887. avatar: 'https://placeimg.com/140/140/any',
  888. },
  889. },
  890. {
  891. _id: 7,
  892. text: 'Come on!13',
  893. createdAt: new Date(Date.UTC(2016, 5, 16, 18, 23, 0)),
  894. pending: true,
  895. user: {
  896. _id: 2,
  897. name: 'React Native',
  898. avatar: 'https://placeimg.com/140/140/any',
  899. },
  900. },
  901. {
  902. _id: 8,
  903. // text: 'cac',
  904. createdAt: new Date(Date.UTC(2016, 5, 16, 18, 25, 0)),
  905. user: {
  906. _id: 5,
  907. name: 'dmm',
  908. avatar: 'https://placeimg.com/140/140/any',
  909. },
  910. images: ['https://picsum.photos/id/1/900/900','https://picsum.photos/id/2/900/900','https://picsum.photos/id/3/900/900'],
  911. },
  912. {
  913. _id: 9,
  914. // text: '',
  915. createdAt: new Date(Date.UTC(2016, 5, 18, 19, 20, 0)),
  916. // image : 'https://placeimg.com/140/140/any',
  917. video: {
  918. uri: 'https://file-examples.com/storage/feb8f98f1d627c0dc94b8cf/2017/04/file_example_MP4_1920_18MG.mp4',
  919. thumbnail: 'https://picsum.photos/id/237/900/900'
  920. },
  921. // images: ['https://placeimg.com/700/540/any', 'https://placeimg.com/960/540/any', 'https://placeimg.com/800/540/any'],
  922. sent: true,
  923. user: {
  924. _id: 6,
  925. name: 'React fap',
  926. avatar: 'https://placeimg.com/140/140/any',
  927. },
  928. },
  929. {
  930. _id: 11,
  931. // text: 'Hi! ',
  932. createdAt: new Date(Date.UTC(2016, 5, 20, 17, 20, 0)),
  933. sent: true,
  934. received: true,
  935. peding: true,
  936. user: {
  937. _id: 1,
  938. name: 'React Native',
  939. avatar: 'https://placeimg.com/333/855/any',
  940. },
  941. // image: 'https://placeimg.com/700/540/any',
  942. // sticker: 'https://link.vedax.ai/images/emotions/cat_petition_hs.png'
  943.  
  944. text: 'Hello @[David Tabaka](3r2r32) #cac'
  945. },
  946. ];
  947.  
  948. const loadMoreSample = [
  949. {
  950. _id: 2,
  951. text: 'fap1',
  952. sent: true,
  953. createdAt: new Date(Date.UTC(2016, 4, 12, 17, 20, 0)),
  954. user: {
  955. _id: 2,
  956. name: 'React dsad',
  957. },
  958. },
  959. {
  960. _id: 3,
  961. // text: 'Hi! ',
  962. createdAt: new Date(Date.UTC(2016, 3, 13, 17, 20, 0)),
  963. sent: true,
  964. received: true,
  965. peding: true,
  966. user: {
  967. _id: 8,
  968. name: 'fap2',
  969. avatar: 'https://placeimg.com/140/140/any',
  970. },
  971. image: 'https://placeimg.com/140/140/any'
  972. },
  973. {
  974. _id: 4,
  975. text: 'Cac dmm',
  976. createdAt: new Date(Date.UTC(2016, 2, 14, 17, 20, 0)),
  977. user: {
  978. _id: 3,
  979. name: 'React Native',
  980. avatar: 'https://placeimg.com/140/140/any',
  981. }
  982. },
  983. ]
  984.  
  985. const users = [
  986. {
  987. id: '1',
  988. name: 'David Tabaka',
  989. avatar: 'https://placeimg.com/140/140/any',
  990. },
  991. {
  992. id: '2',
  993. name: 'Mary',
  994. avatar: 'https://placeimg.com/140/140/any',
  995. },
  996. {
  997. id: '3',
  998. name: 'Tony',
  999. avatar: 'https://placeimg.com/140/140/any',
  1000. },
  1001. {
  1002. id: '4',
  1003. name: 'Mike',
  1004. avatar: 'https://placeimg.com/140/140/any',
  1005. },
  1006. {
  1007. id: '5',
  1008. name: 'Grey',
  1009. avatar: 'https://placeimg.com/140/140/any',
  1010. },
  1011. ];
  1012.  
  1013. const hashtags = [
  1014. {
  1015. id: 'todo',
  1016. name: 'todo',
  1017. },
  1018. {
  1019. id: 'help',
  1020. name: 'help',
  1021. },
  1022. {
  1023. id: 'loveyou',
  1024. name: 'loveyou',
  1025. },
  1026. ];
  1027.  
  1028. // Config of suggestible triggers
  1029. const triggersConfig = {
  1030. mention: {
  1031. trigger: '@',
  1032. },
  1033. hashtag: {
  1034. trigger: '#',
  1035. textStyle: {
  1036. fontWeight: 'bold',
  1037. color: 'grey',
  1038. },
  1039. },
  1040. };
  1041.  
  1042. // Config of highlightable patterns (like links, bold, italic text etc.)
  1043. const patternsConfig = {
  1044. url: {
  1045. pattern: /a/gi,
  1046. textStyle: { color: 'blue' },
  1047. },
  1048. };
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement