From c513c31a42488da22435d6b023ae73dfcd6596f8 Mon Sep 17 00:00:00 2001 From: Doljinsuren Enkhbayar Date: Tue, 9 Apr 2024 17:36:22 +0800 Subject: [PATCH 01/57] created chat ui --- package.json | 1 + src/features/Core/MainStack.js | 4 + src/features/Core/screens/ChatScreen.js | 96 ++++++++++++++++++++++ src/features/Core/screens/MainScreen.js | 7 +- src/features/Core/screens/MessageScreen.js | 70 ++++++++++++++++ 5 files changed, 177 insertions(+), 1 deletion(-) create mode 100644 src/features/Core/screens/ChatScreen.js create mode 100644 src/features/Core/screens/MessageScreen.js diff --git a/package.json b/package.json index 945bc074..eeb6f7fa 100644 --- a/package.json +++ b/package.json @@ -77,6 +77,7 @@ "react-native-geolocation-service": "^5.3.0-beta.1", "react-native-gesture-handler": "^1.10.3", "react-native-get-random-values": "^1.9.0", + "react-native-gifted-chat": "^2.4.0", "react-native-google-places-autocomplete": "^2.2.0", "react-native-image-picker": "^4.4.0", "react-native-image-resizer": "^1.4.5", diff --git a/src/features/Core/MainStack.js b/src/features/Core/MainStack.js index ccc53376..504650db 100644 --- a/src/features/Core/MainStack.js +++ b/src/features/Core/MainStack.js @@ -9,6 +9,8 @@ import ProofScreen from 'shared/ProofScreen'; import MainScreen from './screens/MainScreen'; import SearchScreen from './screens/SearchScreen'; import IssueScreen from './screens/IssueScreen'; +import ChatScreen from './screens/ChatScreen'; +import MessageScreen from './screens/MessageScreen'; const RootStack = createStackNavigator(); @@ -30,6 +32,8 @@ const MainStack = ({ route }) => { + + diff --git a/src/features/Core/screens/ChatScreen.js b/src/features/Core/screens/ChatScreen.js new file mode 100644 index 00000000..1e89b300 --- /dev/null +++ b/src/features/Core/screens/ChatScreen.js @@ -0,0 +1,96 @@ +import React, {useState, useEffect, useCallback} from 'react'; +import {View, ScrollView, Text, Button, StyleSheet} from 'react-native'; +import {Bubble, GiftedChat, Send} from 'react-native-gifted-chat'; +// import MaterialCommunityIcons from 'react-native-vector-icons/MaterialCommunityIcons'; +import { FontAwesomeIcon } from '@fortawesome/react-native-fontawesome'; + +const ChatScreen = () => { + const [messages, setMessages] = useState([]); + + useEffect(() => { + setMessages([ + { + _id: 1, + text: 'Hello developer', + createdAt: new Date(), + user: { + _id: 2, + name: 'React Native', + avatar: 'https://placeimg.com/140/140/any', + }, + }, + { + _id: 2, + text: 'Hello world', + createdAt: new Date(), + user: { + _id: 1, + name: 'React Native', + avatar: 'https://placeimg.com/140/140/any', + }, + }, + ]); + }, []); + + const onSend = useCallback((messages = []) => { + setMessages((previousMessages) => + GiftedChat.append(previousMessages, messages), + ); + }, []); + + const renderSend = (props) => { + return ( + + + {/* */} + + + ); + }; + + const renderBubble = (props) => { + return ( + + ); + }; + + const scrollToBottomComponent = () => { + return( + + ); + } + + return ( + onSend(messages)} + user={{ + _id: 1, + }} + renderBubble={renderBubble} + alwaysShowSend + renderSend={renderSend} + scrollToBottom + scrollToBottomComponent={scrollToBottomComponent} + /> + ); +}; + +export default ChatScreen; diff --git a/src/features/Core/screens/MainScreen.js b/src/features/Core/screens/MainScreen.js index 105906ea..caa4d2f2 100644 --- a/src/features/Core/screens/MainScreen.js +++ b/src/features/Core/screens/MainScreen.js @@ -1,4 +1,4 @@ -import { faCalendarDay, faClipboardList, faFileAlt, faRoute, faUser, faWallet } from '@fortawesome/free-solid-svg-icons'; +import { faCalendarDay, faClipboardList, faFileAlt, faRoute, faUser, faWallet, faTextHeight } from '@fortawesome/free-solid-svg-icons'; import { FontAwesomeIcon } from '@fortawesome/react-native-fontawesome'; import { createBottomTabNavigator } from '@react-navigation/bottom-tabs'; import { useRoute } from '@react-navigation/native'; @@ -16,6 +16,7 @@ import { createNewOrderLocalNotificationObject, getColorCode, listenForOrdersFro import { syncDevice } from 'utils/Auth'; import { getCurrentLocation, trackDriver } from 'utils/Geo'; import IssuesScreen from './IssuesScreen'; +import MessageScreen from './MessageScreen'; const { addEventListener, removeEventListener } = EventRegister; const Tab = createBottomTabNavigator(); @@ -141,6 +142,9 @@ const MainScreen = ({ navigation, route }) => { case 'Issue': icon = faFileAlt; break; + case 'Message': + icon = faTextHeight; + break; } // You can return any component that you like here! return ; @@ -160,6 +164,7 @@ const MainScreen = ({ navigation, route }) => { {/* */} {/* */} + diff --git a/src/features/Core/screens/MessageScreen.js b/src/features/Core/screens/MessageScreen.js new file mode 100644 index 00000000..f0f1ce39 --- /dev/null +++ b/src/features/Core/screens/MessageScreen.js @@ -0,0 +1,70 @@ +import React, { useState } from 'react'; +import { FlatList, TouchableOpacity, View, Image, Text } from 'react-native'; +import { useNavigation } from '@react-navigation/native'; +import { tailwind } from 'tailwind'; + +const MessageScreen = () => { + const navigation = useNavigation(); + const [messages, setMessages] = useState([]); + + const Messages = [ + { + id: '1', + userName: 'Jenny Doe', + userImg: 'image', + messageTime: '4 mins ago', + messageText: 'Hi, How are you?', + }, + { + id: '2', + userName: 'John Doe', + userImg: 'image', + messageTime: '2 hours ago', + messageText: 'Hi, How are you?', + }, + { + id: '3', + userName: 'Ken William', + userImg: 'image', + messageTime: '1 hours ago', + messageText: 'Hi, How are you?', + }, + { + id: '4', + userName: 'Selina Paul', + userImg: 'image', + messageTime: '1 day ago', + messageText: 'Hi, How are you?', + }, + { + id: '5', + userName: 'Christy Alex', + userImg: 'image', + messageTime: '2 days ago', + messageText: 'Hi, How are you?', + }, + ]; + + return ( + + item.id} + renderItem={({ item }) => ( + navigation.navigate('ChatScreen', { userName: item.userName })}> + + {/* */} + + {item.userName} + {item.messageTime} + + {item.messageText} + + + )} + /> + + ); +}; + +export default MessageScreen; From 5b91cea40f22108d969d57cd7e30e19d5af6cf55 Mon Sep 17 00:00:00 2001 From: Doljinsuren Enkhbayar Date: Tue, 9 Apr 2024 18:03:55 +0800 Subject: [PATCH 02/57] fixed chat ui --- src/features/Core/screens/ChatScreen.js | 177 +++++++++++---------- src/features/Core/screens/MessageScreen.js | 2 +- 2 files changed, 94 insertions(+), 85 deletions(-) diff --git a/src/features/Core/screens/ChatScreen.js b/src/features/Core/screens/ChatScreen.js index 1e89b300..73e8eadd 100644 --- a/src/features/Core/screens/ChatScreen.js +++ b/src/features/Core/screens/ChatScreen.js @@ -1,96 +1,105 @@ -import React, {useState, useEffect, useCallback} from 'react'; -import {View, ScrollView, Text, Button, StyleSheet} from 'react-native'; -import {Bubble, GiftedChat, Send} from 'react-native-gifted-chat'; -// import MaterialCommunityIcons from 'react-native-vector-icons/MaterialCommunityIcons'; +import { faAngleLeft, faPhone, faPhotoVideo } from '@fortawesome/free-solid-svg-icons'; import { FontAwesomeIcon } from '@fortawesome/react-native-fontawesome'; +import { useNavigation } from '@react-navigation/native'; +import React, { useCallback, useEffect, useState } from 'react'; +import { Text, TouchableOpacity, View } from 'react-native'; +import { Bubble, GiftedChat, Send } from 'react-native-gifted-chat'; +import { tailwind } from 'tailwind'; const ChatScreen = () => { - const [messages, setMessages] = useState([]); + const navigation = useNavigation(); + const [messages, setMessages] = useState([]); - useEffect(() => { - setMessages([ - { - _id: 1, - text: 'Hello developer', - createdAt: new Date(), - user: { - _id: 2, - name: 'React Native', - avatar: 'https://placeimg.com/140/140/any', - }, - }, - { - _id: 2, - text: 'Hello world', - createdAt: new Date(), - user: { - _id: 1, - name: 'React Native', - avatar: 'https://placeimg.com/140/140/any', - }, - }, - ]); - }, []); + useEffect(() => { + setMessages([ + { + _id: 1, + text: 'Hello developer', + createdAt: new Date(), + user: { + _id: 2, + name: 'React Native', + avatar: 'https://placeimg.com/140/140/any', + }, + }, + { + _id: 2, + text: 'Hello world', + createdAt: new Date(), + user: { + _id: 1, + name: 'React Native', + avatar: 'https://placeimg.com/140/140/any', + }, + }, + ]); + }, []); - const onSend = useCallback((messages = []) => { - setMessages((previousMessages) => - GiftedChat.append(previousMessages, messages), - ); - }, []); + const onSend = useCallback((messages = []) => { + setMessages(previousMessages => GiftedChat.append(previousMessages, messages)); + }, []); - const renderSend = (props) => { - return ( - - - {/* */} - - - ); - }; + const renderSend = props => { + return ( + + + + ); + }; - const renderBubble = (props) => { - return ( - - ); - }; + const renderBubble = props => { + return ( + + ); + }; - const scrollToBottomComponent = () => { - return( - - ); - } + const scrollToBottomComponent = () => { + return ; + }; - return ( - onSend(messages)} - user={{ - _id: 1, - }} - renderBubble={renderBubble} - alwaysShowSend - renderSend={renderSend} - scrollToBottom - scrollToBottomComponent={scrollToBottomComponent} - /> - ); + return ( + + + navigation.goBack()} style={tailwind('rounded-full ')}> + + + + {'Name'} + + + + + + + + + + onSend(messages)} + user={{ + _id: 1, + }} + renderBubble={renderBubble} + alwaysShowSend + scrollToBottom + scrollToBottomComponent={scrollToBottomComponent} + /> + + + ); }; export default ChatScreen; diff --git a/src/features/Core/screens/MessageScreen.js b/src/features/Core/screens/MessageScreen.js index f0f1ce39..1c0d59bb 100644 --- a/src/features/Core/screens/MessageScreen.js +++ b/src/features/Core/screens/MessageScreen.js @@ -54,7 +54,7 @@ const MessageScreen = () => { navigation.navigate('ChatScreen', { userName: item.userName })}> {/* */} - + {item.userName} {item.messageTime} From 2b59f204cf3fc1fa7b9e60a32f16ecf4f607118b Mon Sep 17 00:00:00 2001 From: Doljinsuren Enkhbayar Date: Wed, 10 Apr 2024 13:55:07 +0800 Subject: [PATCH 03/57] improved chat ui --- src/features/Core/MainStack.js | 4 +- src/features/Core/screens/ChatScreen.js | 39 ++++++---- src/features/Core/screens/ChatsScreen.js | 84 ++++++++++++++++++++++ src/features/Core/screens/MainScreen.js | 6 +- src/features/Core/screens/MessageScreen.js | 70 ------------------ 5 files changed, 113 insertions(+), 90 deletions(-) create mode 100644 src/features/Core/screens/ChatsScreen.js delete mode 100644 src/features/Core/screens/MessageScreen.js diff --git a/src/features/Core/MainStack.js b/src/features/Core/MainStack.js index 504650db..88f9ae49 100644 --- a/src/features/Core/MainStack.js +++ b/src/features/Core/MainStack.js @@ -10,7 +10,7 @@ import MainScreen from './screens/MainScreen'; import SearchScreen from './screens/SearchScreen'; import IssueScreen from './screens/IssueScreen'; import ChatScreen from './screens/ChatScreen'; -import MessageScreen from './screens/MessageScreen'; +import ChatsScreen from './screens/ChatsScreen'; const RootStack = createStackNavigator(); @@ -33,7 +33,7 @@ const MainStack = ({ route }) => { - + diff --git a/src/features/Core/screens/ChatScreen.js b/src/features/Core/screens/ChatScreen.js index 73e8eadd..b88bb2a4 100644 --- a/src/features/Core/screens/ChatScreen.js +++ b/src/features/Core/screens/ChatScreen.js @@ -1,4 +1,4 @@ -import { faAngleLeft, faPhone, faPhotoVideo } from '@fortawesome/free-solid-svg-icons'; +import { faAngleLeft, faPhone, faVideo,faPaperPlane } from '@fortawesome/free-solid-svg-icons'; import { FontAwesomeIcon } from '@fortawesome/react-native-fontawesome'; import { useNavigation } from '@react-navigation/native'; import React, { useCallback, useEffect, useState } from 'react'; @@ -42,7 +42,9 @@ const ChatScreen = () => { const renderSend = props => { return ( - + + + ); }; @@ -70,22 +72,28 @@ const ChatScreen = () => { }; return ( - - - navigation.goBack()} style={tailwind('rounded-full ')}> - + + + navigation.goBack()}> + - - {'Name'} + + + {'name'} + + + + + + + + + + + - - - - - - - + onSend(messages)} @@ -95,6 +103,7 @@ const ChatScreen = () => { renderBubble={renderBubble} alwaysShowSend scrollToBottom + renderSend={renderSend} scrollToBottomComponent={scrollToBottomComponent} /> diff --git a/src/features/Core/screens/ChatsScreen.js b/src/features/Core/screens/ChatsScreen.js new file mode 100644 index 00000000..e9555737 --- /dev/null +++ b/src/features/Core/screens/ChatsScreen.js @@ -0,0 +1,84 @@ +import { useNavigation } from '@react-navigation/native'; +import React from 'react'; +import { Image, ScrollView, Text, TouchableOpacity, View } from 'react-native'; +import { tailwind } from 'tailwind'; + +const ChatsScreen = () => { + const navigation = useNavigation(); + + const messages = [ + { + id: 1, + imageUri: 'https://i.imgur.com/aq39RMA.jpg', + name: 'Jessica Koel', + message: "Hey, Joel, I'm here to help you out please tell me", + time: '11:26', + }, + { + id: 2, + imageUri: 'https://i.imgur.com/eMaYwXn.jpg', + name: 'Komeial Bolger', + message: 'I will send you all documents as soon as possible', + time: '12:26', + }, + { + id: 3, + imageUri: 'https://i.imgur.com/zQZSWrt.jpg', + name: 'Tamaara Suiale', + message: 'Are you going on a business trip next week?', + time: '8:26', + }, + { + id: 4, + imageUri: 'https://i.imgur.com/agRGhBc.jpg', + name: 'Sam Nielson', + message: 'I suggest starting a new business soon', + time: '7:16', + }, + { + id: 5, + imageUri: 'https://i.imgur.com/uIgDDDd.jpg', + name: 'Caroline Nexon', + message: 'We need to start a new research center.', + time: '9:26', + }, + { + id: 6, + imageUri: 'https://i.imgur.com/tT8rjKC.jpg', + name: 'Patrick Koeler', + message: 'Maybe yes', + time: '3:26', + }, + ]; + + const MessageItem = ({ imageUri, name, message, time }) => { + return ( + navigation.navigate('ChatScreen')} style={tailwind('flex flex-row bg-gray-100 mt-2 p-2 rounded mx-2')}> + + + + + + {name} + {message} + + + + {time} + + + ); + }; + + return ( + + + {messages.map(message => ( + + ))} + + + ); +}; + +export default ChatsScreen; diff --git a/src/features/Core/screens/MainScreen.js b/src/features/Core/screens/MainScreen.js index caa4d2f2..a90d7bab 100644 --- a/src/features/Core/screens/MainScreen.js +++ b/src/features/Core/screens/MainScreen.js @@ -16,7 +16,7 @@ import { createNewOrderLocalNotificationObject, getColorCode, listenForOrdersFro import { syncDevice } from 'utils/Auth'; import { getCurrentLocation, trackDriver } from 'utils/Geo'; import IssuesScreen from './IssuesScreen'; -import MessageScreen from './MessageScreen'; +import ChatsScreen from './ChatsScreen'; const { addEventListener, removeEventListener } = EventRegister; const Tab = createBottomTabNavigator(); @@ -142,7 +142,7 @@ const MainScreen = ({ navigation, route }) => { case 'Issue': icon = faFileAlt; break; - case 'Message': + case 'Chat': icon = faTextHeight; break; } @@ -164,7 +164,7 @@ const MainScreen = ({ navigation, route }) => { {/* */} {/* */} - + diff --git a/src/features/Core/screens/MessageScreen.js b/src/features/Core/screens/MessageScreen.js deleted file mode 100644 index 1c0d59bb..00000000 --- a/src/features/Core/screens/MessageScreen.js +++ /dev/null @@ -1,70 +0,0 @@ -import React, { useState } from 'react'; -import { FlatList, TouchableOpacity, View, Image, Text } from 'react-native'; -import { useNavigation } from '@react-navigation/native'; -import { tailwind } from 'tailwind'; - -const MessageScreen = () => { - const navigation = useNavigation(); - const [messages, setMessages] = useState([]); - - const Messages = [ - { - id: '1', - userName: 'Jenny Doe', - userImg: 'image', - messageTime: '4 mins ago', - messageText: 'Hi, How are you?', - }, - { - id: '2', - userName: 'John Doe', - userImg: 'image', - messageTime: '2 hours ago', - messageText: 'Hi, How are you?', - }, - { - id: '3', - userName: 'Ken William', - userImg: 'image', - messageTime: '1 hours ago', - messageText: 'Hi, How are you?', - }, - { - id: '4', - userName: 'Selina Paul', - userImg: 'image', - messageTime: '1 day ago', - messageText: 'Hi, How are you?', - }, - { - id: '5', - userName: 'Christy Alex', - userImg: 'image', - messageTime: '2 days ago', - messageText: 'Hi, How are you?', - }, - ]; - - return ( - - item.id} - renderItem={({ item }) => ( - navigation.navigate('ChatScreen', { userName: item.userName })}> - - {/* */} - - {item.userName} - {item.messageTime} - - {item.messageText} - - - )} - /> - - ); -}; - -export default MessageScreen; From f4926dbb64b33b173373761b5b65ed663dc95fe2 Mon Sep 17 00:00:00 2001 From: Doljinsuren Enkhbayar Date: Wed, 10 Apr 2024 17:45:00 +0800 Subject: [PATCH 04/57] fixed messenger container --- src/features/Core/screens/ChatScreen.js | 47 ++++++++++++++++++++----- 1 file changed, 38 insertions(+), 9 deletions(-) diff --git a/src/features/Core/screens/ChatScreen.js b/src/features/Core/screens/ChatScreen.js index b88bb2a4..3466963a 100644 --- a/src/features/Core/screens/ChatScreen.js +++ b/src/features/Core/screens/ChatScreen.js @@ -1,14 +1,15 @@ -import { faAngleLeft, faPhone, faVideo,faPaperPlane } from '@fortawesome/free-solid-svg-icons'; +import { faAngleLeft, faPaperPlane, faPhone, faUpload, faVideo } from '@fortawesome/free-solid-svg-icons'; import { FontAwesomeIcon } from '@fortawesome/react-native-fontawesome'; import { useNavigation } from '@react-navigation/native'; import React, { useCallback, useEffect, useState } from 'react'; import { Text, TouchableOpacity, View } from 'react-native'; -import { Bubble, GiftedChat, Send } from 'react-native-gifted-chat'; +import { Actions, Bubble, GiftedChat, InputToolbar, Send } from 'react-native-gifted-chat'; import { tailwind } from 'tailwind'; const ChatScreen = () => { const navigation = useNavigation(); const [messages, setMessages] = useState([]); + const [text, setText] = useState(); useEffect(() => { setMessages([ @@ -42,9 +43,7 @@ const ChatScreen = () => { const renderSend = props => { return ( - - - + ); }; @@ -71,15 +70,43 @@ const ChatScreen = () => { return ; }; + const renderActions = () => ( + { + console.log('Choose From Library'); + }, + Cancel: () => { + console.log('Cancel'); + }, + }} + optionTintColor="#222B45" + /> + ); + + const MessengerBarContainer = props => { + return ; + }; + + const AdditionalContainer = () => { + return ( + + + + + + ); + }; + return ( - + navigation.goBack()}> - {'name'} + {'Jessica Koel'} @@ -93,7 +120,7 @@ const ChatScreen = () => { - + onSend(messages)} @@ -103,8 +130,10 @@ const ChatScreen = () => { renderBubble={renderBubble} alwaysShowSend scrollToBottom - renderSend={renderSend} + renderInputToolbar={props => MessengerBarContainer(props)} + renderActions={renderActions} scrollToBottomComponent={scrollToBottomComponent} + renderSend={renderSend} /> From 1acd762925f53233d03475d07a3c5c04c762b7fb Mon Sep 17 00:00:00 2001 From: Doljinsuren Enkhbayar Date: Thu, 11 Apr 2024 10:51:44 +0800 Subject: [PATCH 05/57] changed colour --- src/features/Core/screens/ChatsScreen.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/features/Core/screens/ChatsScreen.js b/src/features/Core/screens/ChatsScreen.js index e9555737..b5efcda1 100644 --- a/src/features/Core/screens/ChatsScreen.js +++ b/src/features/Core/screens/ChatsScreen.js @@ -53,13 +53,13 @@ const ChatsScreen = () => { const MessageItem = ({ imageUri, name, message, time }) => { return ( - navigation.navigate('ChatScreen')} style={tailwind('flex flex-row bg-gray-100 mt-2 p-2 rounded mx-2')}> + navigation.navigate('ChatScreen')} style={tailwind('flex flex-row bg-gray-900 mt-2 p-2 rounded mx-2')}> - {name} + {name} {message} From 2678336bf96186ebfb0cf6137fb563c6c706a617 Mon Sep 17 00:00:00 2001 From: Doljinsuren Enkhbayar Date: Fri, 12 Apr 2024 16:20:41 +0800 Subject: [PATCH 06/57] implemented fe db --- src/features/Core/MainStack.js | 2 + src/features/Core/screens/ChannelScreen.js | 67 ++++++++++++++++ src/features/Core/screens/ChatScreen.js | 6 +- src/features/Core/screens/ChatsScreen.js | 93 ++++++++++------------ translations/en.json | 4 + 5 files changed, 119 insertions(+), 53 deletions(-) create mode 100644 src/features/Core/screens/ChannelScreen.js diff --git a/src/features/Core/MainStack.js b/src/features/Core/MainStack.js index 88f9ae49..a6882ae5 100644 --- a/src/features/Core/MainStack.js +++ b/src/features/Core/MainStack.js @@ -11,6 +11,7 @@ import SearchScreen from './screens/SearchScreen'; import IssueScreen from './screens/IssueScreen'; import ChatScreen from './screens/ChatScreen'; import ChatsScreen from './screens/ChatsScreen'; +import ChannelScreen from './screens/ChannelScreen'; const RootStack = createStackNavigator(); @@ -34,6 +35,7 @@ const MainStack = ({ route }) => { + diff --git a/src/features/Core/screens/ChannelScreen.js b/src/features/Core/screens/ChannelScreen.js new file mode 100644 index 00000000..30782a06 --- /dev/null +++ b/src/features/Core/screens/ChannelScreen.js @@ -0,0 +1,67 @@ +import { faTimes } from '@fortawesome/free-solid-svg-icons'; +import { FontAwesomeIcon } from '@fortawesome/react-native-fontawesome'; +import { useNavigation } from '@react-navigation/native'; +import { useFleetbase } from 'hooks'; +import React, { useState } from 'react'; +import { ActivityIndicator, Keyboard, KeyboardAvoidingView, Pressable, Text, TextInput, TouchableOpacity, View } from 'react-native'; +import tailwind from 'tailwind'; +import { getColorCode, logError, translate } from 'utils'; + +const ChannelScreen = () => { + const navigation = useNavigation(); + const fleetbase = useFleetbase(); + const [name, setName] = useState(); + const [isLoading, setIsLoading] = useState(false); + + const saveChannel = () => { + setIsLoading(true); + const adapter = fleetbase.getAdapter(); + return adapter + .post('chat-channels', { + name, + }) + .then(res => { + navigation.navigate('ChatScreen', { data: res }); + }) + .catch(logError); + }; + + return ( + + + + {translate('Core.ChannelScreen.title')} + navigation.goBack()} style={tailwind('mr-4')}> + + + + + + + + + {translate('Core.ChannelScreen.name')} + + + + + + {isLoading && } + {translate('Core.ChannelScreen.title')} + + + + + + + ); +}; + +export default ChannelScreen; diff --git a/src/features/Core/screens/ChatScreen.js b/src/features/Core/screens/ChatScreen.js index 3466963a..41c77f2a 100644 --- a/src/features/Core/screens/ChatScreen.js +++ b/src/features/Core/screens/ChatScreen.js @@ -6,7 +6,9 @@ import { Text, TouchableOpacity, View } from 'react-native'; import { Actions, Bubble, GiftedChat, InputToolbar, Send } from 'react-native-gifted-chat'; import { tailwind } from 'tailwind'; -const ChatScreen = () => { +const ChatScreen = ({ route }) => { + const { data, channelData } = route.params; + const navigation = useNavigation(); const [messages, setMessages] = useState([]); const [text, setText] = useState(); @@ -106,7 +108,7 @@ const ChatScreen = () => { - {'Jessica Koel'} + {data?.name} diff --git a/src/features/Core/screens/ChatsScreen.js b/src/features/Core/screens/ChatsScreen.js index b5efcda1..9825b62d 100644 --- a/src/features/Core/screens/ChatsScreen.js +++ b/src/features/Core/screens/ChatsScreen.js @@ -1,61 +1,43 @@ import { useNavigation } from '@react-navigation/native'; -import React from 'react'; +import React, { useEffect, useState } from 'react'; +import { useFleetbase } from 'hooks'; +import FastImage from 'react-native-fast-image'; +import { format } from 'date-fns'; import { Image, ScrollView, Text, TouchableOpacity, View } from 'react-native'; import { tailwind } from 'tailwind'; const ChatsScreen = () => { const navigation = useNavigation(); + const fleetbase = useFleetbase(); + const [channel, setChannel] = useState([]); - const messages = [ - { - id: 1, - imageUri: 'https://i.imgur.com/aq39RMA.jpg', - name: 'Jessica Koel', - message: "Hey, Joel, I'm here to help you out please tell me", - time: '11:26', - }, - { - id: 2, - imageUri: 'https://i.imgur.com/eMaYwXn.jpg', - name: 'Komeial Bolger', - message: 'I will send you all documents as soon as possible', - time: '12:26', - }, - { - id: 3, - imageUri: 'https://i.imgur.com/zQZSWrt.jpg', - name: 'Tamaara Suiale', - message: 'Are you going on a business trip next week?', - time: '8:26', - }, - { - id: 4, - imageUri: 'https://i.imgur.com/agRGhBc.jpg', - name: 'Sam Nielson', - message: 'I suggest starting a new business soon', - time: '7:16', - }, - { - id: 5, - imageUri: 'https://i.imgur.com/uIgDDDd.jpg', - name: 'Caroline Nexon', - message: 'We need to start a new research center.', - time: '9:26', - }, - { - id: 6, - imageUri: 'https://i.imgur.com/tT8rjKC.jpg', - name: 'Patrick Koeler', - message: 'Maybe yes', - time: '3:26', - }, - ]; + const fetchChannels = async () => { + try { + const adapter = fleetbase.getAdapter(); + const response = await adapter.get('chat-channels'); + setChannel(response); + return response; + } catch (error) { + console.error('Error fetching channel:', error); + return []; + } + }; + + const formatTime = dateTime => { + const date = new Date(dateTime); + const formattedTime = format(date, 'HH:mm'); + return formattedTime; + }; + + useEffect(() => { + fetchChannels(); + }, []); const MessageItem = ({ imageUri, name, message, time }) => { return ( navigation.navigate('ChatScreen')} style={tailwind('flex flex-row bg-gray-900 mt-2 p-2 rounded mx-2')}> - + @@ -63,19 +45,28 @@ const ChatsScreen = () => { {message} - - {time} + + {formatTime(time)} ); }; return ( - + - {messages.map(message => ( - + {channel.map(item => ( + ))} + + + navigation.navigate('ChatScreen', { channelData: item })}> + + {'create'} + + + + ); diff --git a/translations/en.json b/translations/en.json index a046b288..3add51c5 100644 --- a/translations/en.json +++ b/translations/en.json @@ -58,6 +58,10 @@ "report": "Report", "driverName": "Driver Name", "vehicleName": "Vehicle Name" + }, + "ChannelScreen": { + "name": "Name", + "title":"Create channel" } }, "Exceptions": { From 45d26b501030f7a7eca5f5fe1352d75086eb41e4 Mon Sep 17 00:00:00 2001 From: Doljinsuren Enkhbayar Date: Fri, 12 Apr 2024 18:00:19 +0800 Subject: [PATCH 07/57] added swipe --- src/features/Core/screens/ChatScreen.js | 2 +- src/features/Core/screens/ChatsScreen.js | 87 +++++++++++++++--------- 2 files changed, 54 insertions(+), 35 deletions(-) diff --git a/src/features/Core/screens/ChatScreen.js b/src/features/Core/screens/ChatScreen.js index 41c77f2a..84e41df9 100644 --- a/src/features/Core/screens/ChatScreen.js +++ b/src/features/Core/screens/ChatScreen.js @@ -103,7 +103,7 @@ const ChatScreen = ({ route }) => { return ( - navigation.goBack()}> + navigation.navigate('ChatsScreen')}> diff --git a/src/features/Core/screens/ChatsScreen.js b/src/features/Core/screens/ChatsScreen.js index 9825b62d..713d76a7 100644 --- a/src/features/Core/screens/ChatsScreen.js +++ b/src/features/Core/screens/ChatsScreen.js @@ -1,10 +1,11 @@ import { useNavigation } from '@react-navigation/native'; -import React, { useEffect, useState } from 'react'; +import { format } from 'date-fns'; import { useFleetbase } from 'hooks'; +import React, { useEffect, useState } from 'react'; +import { Text, TouchableOpacity, View } from 'react-native'; import FastImage from 'react-native-fast-image'; -import { format } from 'date-fns'; -import { Image, ScrollView, Text, TouchableOpacity, View } from 'react-native'; import { tailwind } from 'tailwind'; +import { SwipeListView} from 'react-native-swipe-list-view'; const ChatsScreen = () => { const navigation = useNavigation(); @@ -18,7 +19,7 @@ const ChatsScreen = () => { setChannel(response); return response; } catch (error) { - console.error('Error fetching channel:', error); + console.error('Error fetching channels:', error); return []; } }; @@ -33,41 +34,59 @@ const ChatsScreen = () => { fetchChannels(); }, []); - const MessageItem = ({ imageUri, name, message, time }) => { - return ( - navigation.navigate('ChatScreen')} style={tailwind('flex flex-row bg-gray-900 mt-2 p-2 rounded mx-2')}> - - - - - - {name} - {message} - - - - {formatTime(time)} - - - ); + const handleDelete = async itemId => { + try { + const adapter = fleetbase.getAdapter(); + await adapter.delete(`chat-channels/${itemId}`); + setChannel(channel.filter(item => item.id !== itemId)); + } catch (error) { + console.error('Error deleting channel:', error); + } }; + const renderItem = ({ item }) => ( + navigation.navigate('ChatScreen')} style={tailwind('flex flex-row bg-gray-900 mt-2 p-2 rounded mx-2')}> + + + + + {item.name} + {item.message} + + + {formatTime(item.created_at)} + + + ); + + const renderHiddenItem = ({ item }) => ( + + handleDelete(item.id)} style={tailwind('flex items-center w-20 bg-red-600')}> + Delete + + + ); + return ( - - {channel.map(item => ( - - ))} - - - navigation.navigate('ChatScreen', { channelData: item })}> - - {'create'} - - - + + + + navigation.navigate('ChatScreen')}> + + Create Channel + + - + ); }; From 88a811faba1bdfe4d16ea79d9ef15425addf1c2f Mon Sep 17 00:00:00 2001 From: Doljinsuren Enkhbayar Date: Fri, 12 Apr 2024 18:33:18 +0800 Subject: [PATCH 08/57] list updated --- src/features/Core/screens/ChatsScreen.js | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/src/features/Core/screens/ChatsScreen.js b/src/features/Core/screens/ChatsScreen.js index 713d76a7..04d2fee6 100644 --- a/src/features/Core/screens/ChatsScreen.js +++ b/src/features/Core/screens/ChatsScreen.js @@ -1,17 +1,26 @@ import { useNavigation } from '@react-navigation/native'; import { format } from 'date-fns'; -import { useFleetbase } from 'hooks'; +import { useFleetbase, useMountedState } from 'hooks'; import React, { useEffect, useState } from 'react'; import { Text, TouchableOpacity, View } from 'react-native'; import FastImage from 'react-native-fast-image'; import { tailwind } from 'tailwind'; -import { SwipeListView} from 'react-native-swipe-list-view'; +import { SwipeListView } from 'react-native-swipe-list-view'; const ChatsScreen = () => { const navigation = useNavigation(); + const isMounted = useMountedState(); const fleetbase = useFleetbase(); const [channel, setChannel] = useState([]); + useEffect(() => { + const unsubscribe = navigation.addListener('focus', () => { + fetchChannels(); + }); + + return unsubscribe; + }, [isMounted]); + const fetchChannels = async () => { try { const adapter = fleetbase.getAdapter(); @@ -72,12 +81,7 @@ const ChatsScreen = () => { return ( - + navigation.navigate('ChatScreen')}> From 34ada7ab36e36c1d8daa3629a9b9db74f65d0428 Mon Sep 17 00:00:00 2001 From: Doljinsuren Enkhbayar Date: Mon, 15 Apr 2024 19:13:33 +0800 Subject: [PATCH 09/57] added users function --- src/features/Core/screens/ChannelScreen.js | 41 ++++++++++----- src/features/Core/screens/ChatScreen.js | 60 ++++++++++++++++++---- src/features/Core/screens/ChatsScreen.js | 39 ++++++++++++-- src/hooks/use-fleetbase.js | 4 +- 4 files changed, 114 insertions(+), 30 deletions(-) diff --git a/src/features/Core/screens/ChannelScreen.js b/src/features/Core/screens/ChannelScreen.js index 30782a06..026c3599 100644 --- a/src/features/Core/screens/ChannelScreen.js +++ b/src/features/Core/screens/ChannelScreen.js @@ -2,28 +2,45 @@ import { faTimes } from '@fortawesome/free-solid-svg-icons'; import { FontAwesomeIcon } from '@fortawesome/react-native-fontawesome'; import { useNavigation } from '@react-navigation/native'; import { useFleetbase } from 'hooks'; -import React, { useState } from 'react'; +import React, { useEffect, useState } from 'react'; import { ActivityIndicator, Keyboard, KeyboardAvoidingView, Pressable, Text, TextInput, TouchableOpacity, View } from 'react-native'; import tailwind from 'tailwind'; import { getColorCode, logError, translate } from 'utils'; -const ChannelScreen = () => { +const ChannelScreen = ({ route }) => { const navigation = useNavigation(); const fleetbase = useFleetbase(); const [name, setName] = useState(); const [isLoading, setIsLoading] = useState(false); + const [channelId, setChannelId] = useState(); + + useEffect(() => { + if (route?.params?.channel) { + const { channel } = route.params; + setChannelId(channel.id); + console.log('channel.id:::', channel.id); + setName(channel.name); + } + }, [route]); const saveChannel = () => { - setIsLoading(true); - const adapter = fleetbase.getAdapter(); - return adapter - .post('chat-channels', { - name, - }) - .then(res => { - navigation.navigate('ChatScreen', { data: res }); - }) - .catch(logError); + if (channelId) { + return adapter + .put(`chat-channels/${channelId}`, name) + .then(res => { + navigation.navigate('ChatScreen', { data: res }); + }) + .catch(logError) + .finally(() => setIsLoading(false)); + } else { + return adapter + .post('chat-channels', name) + .then(res => { + navigation.navigate('ChatScreen', { data: res }); + }) + .catch(logError) + .finally(() => setIsLoading(false)); + } }; return ( diff --git a/src/features/Core/screens/ChatScreen.js b/src/features/Core/screens/ChatScreen.js index 84e41df9..284e00b5 100644 --- a/src/features/Core/screens/ChatScreen.js +++ b/src/features/Core/screens/ChatScreen.js @@ -1,6 +1,7 @@ -import { faAngleLeft, faPaperPlane, faPhone, faUpload, faVideo } from '@fortawesome/free-solid-svg-icons'; +import { faAngleLeft, faPaperPlane, faUpload, faUser } from '@fortawesome/free-solid-svg-icons'; import { FontAwesomeIcon } from '@fortawesome/react-native-fontawesome'; import { useNavigation } from '@react-navigation/native'; +import { useFleetbase } from 'hooks'; import React, { useCallback, useEffect, useState } from 'react'; import { Text, TouchableOpacity, View } from 'react-native'; import { Actions, Bubble, GiftedChat, InputToolbar, Send } from 'react-native-gifted-chat'; @@ -9,9 +10,49 @@ import { tailwind } from 'tailwind'; const ChatScreen = ({ route }) => { const { data, channelData } = route.params; + const fleetbase = useFleetbase(); + const getUser = useFleetbase('int/v1'); const navigation = useNavigation(); const [messages, setMessages] = useState([]); const [text, setText] = useState(); + const [users, setUsers] = useState([]); + + const fetchUsers = async () => { + try { + const adapter = getUser.getAdapter(); + const response = await adapter.get('users'); + console.log('user::::', JSON.stringify(response)); + setUsers(response.name); + return response; + } catch (error) { + console.error('Error fetching users:', error); + return []; + } + }; + + useEffect(() => { + fetchUsers(); + }, []); + + const addParticipant = async id => { + try { + const adapter = fleetbase.getAdapter(); + const res = await adapter.delete(`chat-channels/${id}/add-participant`); + console.log('res:::', JSON.stringify(res)); + } catch (error) { + console.error('Add participant:', error); + } + }; + + const removeParticipant = async participantId => { + try { + const adapter = fleetbase.getAdapter(); + const res = await adapter.delete(`chat-channels/remove-participant/${participantId}`); + console.log('res:::', JSON.stringify(res)); + } catch (error) { + console.error('Remove participant:', error); + } + }; useEffect(() => { setMessages([ @@ -107,19 +148,16 @@ const ChatScreen = ({ route }) => { - - {data?.name} - - - - - + navigation.navigate('ChannelScreen')}> + {data?.name} - - - + {users?.map(item => ( + addParticipant(item.id)}> + {user.name} + + ))} diff --git a/src/features/Core/screens/ChatsScreen.js b/src/features/Core/screens/ChatsScreen.js index 04d2fee6..48de407a 100644 --- a/src/features/Core/screens/ChatsScreen.js +++ b/src/features/Core/screens/ChatsScreen.js @@ -6,6 +6,7 @@ import { Text, TouchableOpacity, View } from 'react-native'; import FastImage from 'react-native-fast-image'; import { tailwind } from 'tailwind'; import { SwipeListView } from 'react-native-swipe-list-view'; +import { HelperUtil } from 'utils'; const ChatsScreen = () => { const navigation = useNavigation(); @@ -21,6 +22,34 @@ const ChatsScreen = () => { return unsubscribe; }, [isMounted]); + const listenForOrdersFromSocket = (channelId, callback) => { + HelperUtil.createSocketAndListen(`chat.${chatChannelRecord.public_id}`, socketEvent => { + const { event, data } = socketEvent; + switch (event) { + case 'chat.added_participant': + case 'chat.removed_participant': + case 'chat_participant.created': + case 'chat_participant.deleted': + this.channel.reloadParticipants(); + this.loadAvailableUsers(); + break; + case 'chat_message.created': + this.chat.insertChatMessageFromSocket(this.channel, data); + break; + case 'chat_log.created': + this.chat.insertChatLogFromSocket(this.channel, data); + break; + case 'chat_attachment.created': + this.chat.insertChatAttachmentFromSocket(this.channel, data); + break; + case 'chat_receipt.created': + this.chat.insertChatReceiptFromSocket(this.channel, data); + break; + } + this.handleChatFeedScroll(); + }); + }; + const fetchChannels = async () => { try { const adapter = fleetbase.getAdapter(); @@ -33,16 +62,16 @@ const ChatsScreen = () => { } }; + useEffect(() => { + fetchChannels(); + }, []); + const formatTime = dateTime => { const date = new Date(dateTime); const formattedTime = format(date, 'HH:mm'); return formattedTime; }; - useEffect(() => { - fetchChannels(); - }, []); - const handleDelete = async itemId => { try { const adapter = fleetbase.getAdapter(); @@ -84,7 +113,7 @@ const ChatsScreen = () => { - navigation.navigate('ChatScreen')}> + navigation.navigate('ChannelScreen')}> Create Channel diff --git a/src/hooks/use-fleetbase.js b/src/hooks/use-fleetbase.js index a9b04d6f..abc567d0 100644 --- a/src/hooks/use-fleetbase.js +++ b/src/hooks/use-fleetbase.js @@ -3,7 +3,7 @@ import config from 'config'; import { isObject } from 'utils'; import { get, getString } from 'utils/Storage'; -const useFleetbase = () => { +const useFleetbase = (namespace) => { let { FLEETBASE_KEY, FLEETBASE_HOST, FLEETBASE_NAMESPACE } = config; let _DRIVER = get('driver'); let _FLEETBASE_KEY = getString('_FLEETBASE_KEY'); @@ -23,7 +23,7 @@ const useFleetbase = () => { const fleetbase = new Fleetbase(FLEETBASE_KEY, { host: FLEETBASE_HOST, - namespace: FLEETBASE_NAMESPACE, + namespace: FLEETBASE_NAMESPACE ?? namespace, }); return fleetbase; From fb54d5c5b9d0b62ccc8f41504a7ebe44272e6a62 Mon Sep 17 00:00:00 2001 From: Doljinsuren Enkhbayar Date: Tue, 16 Apr 2024 12:27:06 +0800 Subject: [PATCH 10/57] fix delete button ui --- src/features/Core/screens/ChatsScreen.js | 28 +++++++++++++++++++----- 1 file changed, 23 insertions(+), 5 deletions(-) diff --git a/src/features/Core/screens/ChatsScreen.js b/src/features/Core/screens/ChatsScreen.js index 48de407a..54b55a08 100644 --- a/src/features/Core/screens/ChatsScreen.js +++ b/src/features/Core/screens/ChatsScreen.js @@ -2,7 +2,7 @@ import { useNavigation } from '@react-navigation/native'; import { format } from 'date-fns'; import { useFleetbase, useMountedState } from 'hooks'; import React, { useEffect, useState } from 'react'; -import { Text, TouchableOpacity, View } from 'react-native'; +import { Text, TouchableOpacity, View, StyleSheet } from 'react-native'; import FastImage from 'react-native-fast-image'; import { tailwind } from 'tailwind'; import { SwipeListView } from 'react-native-swipe-list-view'; @@ -83,7 +83,7 @@ const ChatsScreen = () => { }; const renderItem = ({ item }) => ( - navigation.navigate('ChatScreen')} style={tailwind('flex flex-row bg-gray-900 mt-2 p-2 rounded mx-2')}> + navigation.navigate('ChatScreen')}> { ); const renderHiddenItem = ({ item }) => ( - - handleDelete(item.id)} style={tailwind('flex items-center w-20 bg-red-600')}> + + handleDelete(item.id)} style={[styles.backRightBtn, styles.backRightBtnRight]}> Delete @@ -110,7 +110,6 @@ const ChatsScreen = () => { return ( - navigation.navigate('ChannelScreen')}> @@ -120,8 +119,27 @@ const ChatsScreen = () => { + ); }; export default ChatsScreen; + +const styles = StyleSheet.create({ + backRightBtn: { + alignItems: 'center', + bottom: 0, + justifyContent: 'center', + position: 'absolute', + top: 0, + width: 75, + }, + backRightBtnRight: { + backgroundColor: '#FF3A3A', + right: 0, + top: 8, + marginRight: 12, + marginLeft: 6, + }, +}); From dadf6c8060dc23ae9e4f306a3ac11cd9bc8a3f2d Mon Sep 17 00:00:00 2001 From: Doljinsuren Enkhbayar Date: Tue, 16 Apr 2024 14:20:20 +0800 Subject: [PATCH 11/57] Showed user list --- src/features/Core/screens/ChatScreen.js | 61 ++++++++++++++++++------- 1 file changed, 44 insertions(+), 17 deletions(-) diff --git a/src/features/Core/screens/ChatScreen.js b/src/features/Core/screens/ChatScreen.js index 284e00b5..2b4ecb99 100644 --- a/src/features/Core/screens/ChatScreen.js +++ b/src/features/Core/screens/ChatScreen.js @@ -3,7 +3,7 @@ import { FontAwesomeIcon } from '@fortawesome/react-native-fontawesome'; import { useNavigation } from '@react-navigation/native'; import { useFleetbase } from 'hooks'; import React, { useCallback, useEffect, useState } from 'react'; -import { Text, TouchableOpacity, View } from 'react-native'; +import { FlatList, Text, TouchableOpacity, View } from 'react-native'; import { Actions, Bubble, GiftedChat, InputToolbar, Send } from 'react-native-gifted-chat'; import { tailwind } from 'tailwind'; @@ -16,13 +16,14 @@ const ChatScreen = ({ route }) => { const [messages, setMessages] = useState([]); const [text, setText] = useState(); const [users, setUsers] = useState([]); + const [showUserList, setShowUserList] = useState(false); const fetchUsers = async () => { try { const adapter = getUser.getAdapter(); const response = await adapter.get('users'); - console.log('user::::', JSON.stringify(response)); - setUsers(response.name); + console.log('user::::', JSON.stringify(response.users)); + setUsers(response.users); return response; } catch (error) { console.error('Error fetching users:', error); @@ -34,11 +35,16 @@ const ChatScreen = ({ route }) => { fetchUsers(); }, []); + const toggleUserList = () => { + setShowUserList(!showUserList); // Toggle the user list visibility + }; + const addParticipant = async id => { try { const adapter = fleetbase.getAdapter(); - const res = await adapter.delete(`chat-channels/${id}/add-participant`); + const res = await adapter.post(`chat-channels/${id}/add-participant`); console.log('res:::', JSON.stringify(res)); + setShowUserList(false); } catch (error) { console.error('Add participant:', error); } @@ -142,23 +148,44 @@ const ChatScreen = ({ route }) => { }; return ( - + - navigation.navigate('ChatsScreen')}> - - - - navigation.navigate('ChannelScreen')}> - {data?.name} + + navigation.goBack()}> + - - - {users?.map(item => ( - addParticipant(item.id)}> - {user.name} + + + {'name'} + + + + + + - ))} + + + {showUserList && ( + + + item.id.toString()} + renderItem={({ item }) => ( + + addParticipant(item.id)} style={tailwind('flex flex-row items-center')}> + + + {item.name} + + + )} + /> + + + )} Date: Tue, 16 Apr 2024 14:39:11 +0800 Subject: [PATCH 12/57] added edit button --- src/features/Core/screens/ChatScreen.js | 25 ++++++++++++++----------- 1 file changed, 14 insertions(+), 11 deletions(-) diff --git a/src/features/Core/screens/ChatScreen.js b/src/features/Core/screens/ChatScreen.js index 2b4ecb99..4bf797db 100644 --- a/src/features/Core/screens/ChatScreen.js +++ b/src/features/Core/screens/ChatScreen.js @@ -1,4 +1,4 @@ -import { faAngleLeft, faPaperPlane, faUpload, faUser } from '@fortawesome/free-solid-svg-icons'; +import { faAngleLeft, faPaperPlane, faUpload, faUser, faEdit } from '@fortawesome/free-solid-svg-icons'; import { FontAwesomeIcon } from '@fortawesome/react-native-fontawesome'; import { useNavigation } from '@react-navigation/native'; import { useFleetbase } from 'hooks'; @@ -41,9 +41,9 @@ const ChatScreen = ({ route }) => { const addParticipant = async id => { try { - const adapter = fleetbase.getAdapter(); - const res = await adapter.post(`chat-channels/${id}/add-participant`); - console.log('res:::', JSON.stringify(res)); + // const adapter = fleetbase.getAdapter(); + // const res = await adapter.post(`chat-channels/${id}/add-participant`); + // console.log('res:::', JSON.stringify(res)); setShowUserList(false); } catch (error) { console.error('Add participant:', error); @@ -150,18 +150,21 @@ const ChatScreen = ({ route }) => { return ( - + navigation.goBack()}> - - - {'name'} - + + + {'name '} + navigation.navigate('ChannelScreen')}> + + + - - + + From 1ef9e1e2c1cad78273d5e27311f5dfa40c0abf66 Mon Sep 17 00:00:00 2001 From: Doljinsuren Enkhbayar Date: Tue, 16 Apr 2024 16:20:50 +0800 Subject: [PATCH 13/57] fixed update, create func --- src/features/Core/screens/ChannelScreen.js | 27 +++++++++++++--------- src/features/Core/screens/ChatScreen.js | 20 ++++++++-------- src/features/Core/screens/ChatsScreen.js | 2 +- translations/en.json | 4 +++- 4 files changed, 29 insertions(+), 24 deletions(-) diff --git a/src/features/Core/screens/ChannelScreen.js b/src/features/Core/screens/ChannelScreen.js index 026c3599..a1d4c9b7 100644 --- a/src/features/Core/screens/ChannelScreen.js +++ b/src/features/Core/screens/ChannelScreen.js @@ -15,18 +15,19 @@ const ChannelScreen = ({ route }) => { const [channelId, setChannelId] = useState(); useEffect(() => { - if (route?.params?.channel) { - const { channel } = route.params; - setChannelId(channel.id); - console.log('channel.id:::', channel.id); - setName(channel.name); + if (route?.params) { + const { data } = route.params; + setChannelId(data?.id); + setName(data?.name); } }, [route]); const saveChannel = () => { + const adapter = fleetbase.getAdapter(); + const data = { name }; if (channelId) { return adapter - .put(`chat-channels/${channelId}`, name) + .put(`chat-channels/${channelId}`, data) .then(res => { navigation.navigate('ChatScreen', { data: res }); }) @@ -34,7 +35,7 @@ const ChannelScreen = ({ route }) => { .finally(() => setIsLoading(false)); } else { return adapter - .post('chat-channels', name) + .post('chat-channels', { name }) .then(res => { navigation.navigate('ChatScreen', { data: res }); }) @@ -47,8 +48,8 @@ const ChannelScreen = ({ route }) => { - {translate('Core.ChannelScreen.title')} - navigation.goBack()} style={tailwind('mr-4')}> + {channelId ? translate('Core.ChannelScreen.update-channel') : translate('Core.ChannelScreen.title')} + navigation.navigate('ChatsScreen')} style={tailwind('mr-4')}> @@ -57,7 +58,9 @@ const ChannelScreen = ({ route }) => { - {translate('Core.ChannelScreen.name')} + + {channelId ? translate('Core.ChannelScreen.update') : translate('Core.ChannelScreen.name')} + { {isLoading && } - {translate('Core.ChannelScreen.title')} + + {channelId ? translate('Core.ChannelScreen.update-channel') : translate('Core.ChannelScreen.title')} + diff --git a/src/features/Core/screens/ChatScreen.js b/src/features/Core/screens/ChatScreen.js index 4bf797db..9f703922 100644 --- a/src/features/Core/screens/ChatScreen.js +++ b/src/features/Core/screens/ChatScreen.js @@ -8,8 +8,7 @@ import { Actions, Bubble, GiftedChat, InputToolbar, Send } from 'react-native-gi import { tailwind } from 'tailwind'; const ChatScreen = ({ route }) => { - const { data, channelData } = route.params; - + const { data, itemData } = route.params; const fleetbase = useFleetbase(); const getUser = useFleetbase('int/v1'); const navigation = useNavigation(); @@ -22,7 +21,6 @@ const ChatScreen = ({ route }) => { try { const adapter = getUser.getAdapter(); const response = await adapter.get('users'); - console.log('user::::', JSON.stringify(response.users)); setUsers(response.users); return response; } catch (error) { @@ -36,14 +34,14 @@ const ChatScreen = ({ route }) => { }, []); const toggleUserList = () => { - setShowUserList(!showUserList); // Toggle the user list visibility + setShowUserList(!showUserList); }; - const addParticipant = async id => { + const addParticipant = async participantId => { try { - // const adapter = fleetbase.getAdapter(); - // const res = await adapter.post(`chat-channels/${id}/add-participant`); - // console.log('res:::', JSON.stringify(res)); + const adapter = fleetbase.getAdapter(); + const res = await adapter.post(`chat-channels/${participantId}/add-participant`); + console.log('res:::', JSON.stringify(res)); setShowUserList(false); } catch (error) { console.error('Add participant:', error); @@ -156,9 +154,9 @@ const ChatScreen = ({ route }) => { - {'name '} - navigation.navigate('ChannelScreen')}> - + {itemData?.name || data.name}{' '} + navigation.navigate('ChannelScreen', { data: itemData })}> + diff --git a/src/features/Core/screens/ChatsScreen.js b/src/features/Core/screens/ChatsScreen.js index 54b55a08..feaec7dd 100644 --- a/src/features/Core/screens/ChatsScreen.js +++ b/src/features/Core/screens/ChatsScreen.js @@ -83,7 +83,7 @@ const ChatsScreen = () => { }; const renderItem = ({ item }) => ( - navigation.navigate('ChatScreen')}> + navigation.navigate('ChatScreen', { itemData: item })}> Date: Tue, 16 Apr 2024 17:49:14 +0800 Subject: [PATCH 14/57] add load, file upload --- src/features/Core/screens/ChatScreen.js | 92 +++++++++++++++++------- src/features/Core/screens/ChatsScreen.js | 38 +++++++--- translations/en.json | 7 +- 3 files changed, 103 insertions(+), 34 deletions(-) diff --git a/src/features/Core/screens/ChatScreen.js b/src/features/Core/screens/ChatScreen.js index 9f703922..46ecddd4 100644 --- a/src/features/Core/screens/ChatScreen.js +++ b/src/features/Core/screens/ChatScreen.js @@ -4,6 +4,7 @@ import { useNavigation } from '@react-navigation/native'; import { useFleetbase } from 'hooks'; import React, { useCallback, useEffect, useState } from 'react'; import { FlatList, Text, TouchableOpacity, View } from 'react-native'; +import { launchImageLibrary } from 'react-native-image-picker'; import { Actions, Bubble, GiftedChat, InputToolbar, Send } from 'react-native-gifted-chat'; import { tailwind } from 'tailwind'; @@ -15,6 +16,7 @@ const ChatScreen = ({ route }) => { const [messages, setMessages] = useState([]); const [text, setText] = useState(); const [users, setUsers] = useState([]); + const [channel, setChannel] = useState([]); const [showUserList, setShowUserList] = useState(false); const fetchUsers = async () => { @@ -22,15 +24,24 @@ const ChatScreen = ({ route }) => { const adapter = getUser.getAdapter(); const response = await adapter.get('users'); setUsers(response.users); - return response; } catch (error) { console.error('Error fetching users:', error); - return []; + } + }; + + const fetchChannels = async () => { + try { + const adapter = fleetbase.getAdapter(); + const response = await adapter.get('chat-channels'); + setChannel(response); + } catch (error) { + console.error('Error fetching channels:', error); } }; useEffect(() => { fetchUsers(); + fetchChannels(); }, []); const toggleUserList = () => { @@ -41,7 +52,6 @@ const ChatScreen = ({ route }) => { try { const adapter = fleetbase.getAdapter(); const res = await adapter.post(`chat-channels/${participantId}/add-participant`); - console.log('res:::', JSON.stringify(res)); setShowUserList(false); } catch (error) { console.error('Add participant:', error); @@ -52,7 +62,6 @@ const ChatScreen = ({ route }) => { try { const adapter = fleetbase.getAdapter(); const res = await adapter.delete(`chat-channels/remove-participant/${participantId}`); - console.log('res:::', JSON.stringify(res)); } catch (error) { console.error('Remove participant:', error); } @@ -101,7 +110,7 @@ const ChatScreen = ({ route }) => { {...props} wrapperStyle={{ right: { - backgroundColor: '#2e64e5', + backgroundColor: '#919498', }, }} textStyle={{ @@ -117,11 +126,47 @@ const ChatScreen = ({ route }) => { return ; }; + const uploadFile = async file => { + const formData = new FormData(); + formData.append('file', { + uri: file.uri, + name: file.name, + type: file.type, + }); + + //todo + }; + + const chooseFile = () => { + const options = { + title: 'Select File', + storageOptions: { + skipBackup: true, + path: 'images', + }, + }; + + launchImageLibrary(options, response => { + if (response.didCancel) { + console.log('User cancelled image picker'); + } else if (response.error) { + console.log('ImagePicker Error: ', response.error); + } else { + const file = { + uri: response.uri, + name: response.fileName, + type: response.type, + }; + uploadFile(file); + } + }); + }; + const renderActions = () => ( { - console.log('Choose From Library'); + chooseFile(); }, Cancel: () => { console.log('Cancel'); @@ -146,42 +191,41 @@ const ChatScreen = ({ route }) => { }; return ( - - + + navigation.goBack()}> - + - - {itemData?.name || data.name}{' '} - navigation.navigate('ChannelScreen', { data: itemData })}> - + + {itemData?.name || data.name} + {' '} + navigation.navigate('ChannelScreen', { data: itemData })}> + - + {showUserList && ( - + item.id.toString()} renderItem={({ item }) => ( - - addParticipant(item.id)} style={tailwind('flex flex-row items-center')}> - - - {item.name} - - + addParticipant(item.id)} style={tailwind('flex flex-row items-center py-2')}> + + + {item.name} + )} /> @@ -191,14 +235,14 @@ const ChatScreen = ({ route }) => { onSend(messages)} + onSend={onSend} user={{ _id: 1, }} renderBubble={renderBubble} alwaysShowSend scrollToBottom - renderInputToolbar={props => MessengerBarContainer(props)} + renderInputToolbar={MessengerBarContainer} renderActions={renderActions} scrollToBottomComponent={scrollToBottomComponent} renderSend={renderSend} diff --git a/src/features/Core/screens/ChatsScreen.js b/src/features/Core/screens/ChatsScreen.js index feaec7dd..59d830f3 100644 --- a/src/features/Core/screens/ChatsScreen.js +++ b/src/features/Core/screens/ChatsScreen.js @@ -2,17 +2,19 @@ import { useNavigation } from '@react-navigation/native'; import { format } from 'date-fns'; import { useFleetbase, useMountedState } from 'hooks'; import React, { useEffect, useState } from 'react'; -import { Text, TouchableOpacity, View, StyleSheet } from 'react-native'; +import { ActivityIndicator, StyleSheet, Text, TouchableOpacity, View } from 'react-native'; import FastImage from 'react-native-fast-image'; -import { tailwind } from 'tailwind'; import { SwipeListView } from 'react-native-swipe-list-view'; +import Toast from 'react-native-toast-message'; +import { tailwind } from 'tailwind'; import { HelperUtil } from 'utils'; const ChatsScreen = () => { const navigation = useNavigation(); const isMounted = useMountedState(); const fleetbase = useFleetbase(); - const [channel, setChannel] = useState([]); + const [channels, setChannels] = useState([]); + const [isLoading, setIsLoading] = useState(false); useEffect(() => { const unsubscribe = navigation.addListener('focus', () => { @@ -51,13 +53,16 @@ const ChatsScreen = () => { }; const fetchChannels = async () => { + setIsLoading(true); try { const adapter = fleetbase.getAdapter(); const response = await adapter.get('chat-channels'); - setChannel(response); + setChannels(response); + setIsLoading(false); return response; } catch (error) { console.error('Error fetching channels:', error); + setIsLoading(false); return []; } }; @@ -75,8 +80,13 @@ const ChatsScreen = () => { const handleDelete = async itemId => { try { const adapter = fleetbase.getAdapter(); - await adapter.delete(`chat-channels/${itemId}`); - setChannel(channel.filter(item => item.id !== itemId)); + await adapter.delete(`chat-channels/${itemId}`).then(res => { + Toast.show({ + type: 'success', + text1: `Channel deleted`, + }); + }); + setChannels(channels.filter(item => item.id !== itemId)); } catch (error) { console.error('Error deleting channel:', error); } @@ -101,7 +111,7 @@ const ChatsScreen = () => { ); const renderHiddenItem = ({ item }) => ( - + handleDelete(item.id)} style={[styles.backRightBtn, styles.backRightBtnRight]}> Delete @@ -110,6 +120,11 @@ const ChatsScreen = () => { return ( + {isLoading && ( + + + + )} navigation.navigate('ChannelScreen')}> @@ -119,7 +134,7 @@ const ChatsScreen = () => { - + ); }; @@ -142,4 +157,11 @@ const styles = StyleSheet.create({ marginRight: 12, marginLeft: 6, }, + loaderContainer: { + position: 'absolute', + top: '50%', + left: '60%', + transform: [{ translateX: -50 }, { translateY: -50 }], + zIndex: 10, + }, }); diff --git a/translations/en.json b/translations/en.json index 19c7d046..fe096769 100644 --- a/translations/en.json +++ b/translations/en.json @@ -61,9 +61,12 @@ }, "ChannelScreen": { "name": "Name", - "title":"Create channel", + "title": "Create channel", "update": "Update", - "update-channel":"Update channel" + "update-channel": "Update channel" + }, + "ChatsScreen": { + "delete": "Delete" } }, "Exceptions": { From 610eae8923eae00d441f6610d09e7eabb5afa86d Mon Sep 17 00:00:00 2001 From: Doljinsuren Enkhbayar Date: Thu, 18 Apr 2024 11:16:47 +0800 Subject: [PATCH 15/57] fixed add participant --- src/features/Core/screens/ChatScreen.js | 110 +++++++++++++++--------- 1 file changed, 68 insertions(+), 42 deletions(-) diff --git a/src/features/Core/screens/ChatScreen.js b/src/features/Core/screens/ChatScreen.js index 46ecddd4..7d7d4faa 100644 --- a/src/features/Core/screens/ChatScreen.js +++ b/src/features/Core/screens/ChatScreen.js @@ -11,7 +11,6 @@ import { tailwind } from 'tailwind'; const ChatScreen = ({ route }) => { const { data, itemData } = route.params; const fleetbase = useFleetbase(); - const getUser = useFleetbase('int/v1'); const navigation = useNavigation(); const [messages, setMessages] = useState([]); const [text, setText] = useState(); @@ -19,14 +18,47 @@ const ChatScreen = ({ route }) => { const [channel, setChannel] = useState([]); const [showUserList, setShowUserList] = useState(false); - const fetchUsers = async () => { - try { - const adapter = getUser.getAdapter(); - const response = await adapter.get('users'); - setUsers(response.users); - } catch (error) { - console.error('Error fetching users:', error); - } + useEffect(() => { + fetchUsers(itemData?.id); + fetchChannels(); + }, []); + + useEffect(() => { + setMessages([ + { + _id: 1, + text: 'Hello developer', + createdAt: new Date(), + user: { + _id: 2, + name: 'React Native', + avatar: 'https://placeimg.com/140/140/any', + }, + }, + { + _id: 2, + text: 'Hello world', + createdAt: new Date(), + user: { + _id: 1, + name: 'React Native', + avatar: 'https://placeimg.com/140/140/any', + }, + }, + ]); + }, []); + + const addChannelCreationMessage = () => { + const newMessage = { + _id: new Date().getTime(), // Use current timestamp as a unique ID + text: 'Channel created successfully', + createdAt: new Date(), + user: { + _id: 1, + name: 'System', + }, + }; + setMessages(previousMessages => GiftedChat.append(previousMessages, [newMessage])); }; const fetchChannels = async () => { @@ -34,24 +66,43 @@ const ChatScreen = ({ route }) => { const adapter = fleetbase.getAdapter(); const response = await adapter.get('chat-channels'); setChannel(response); + addChannelCreationMessage(); } catch (error) { console.error('Error fetching channels:', error); } }; - useEffect(() => { - fetchUsers(); - fetchChannels(); - }, []); - const toggleUserList = () => { setShowUserList(!showUserList); }; - const addParticipant = async participantId => { + const fetchUsers = async id => { try { const adapter = fleetbase.getAdapter(); - const res = await adapter.post(`chat-channels/${participantId}/add-participant`); + const response = await adapter.get(`chat-channels/${id}/available-participants`); + setUsers(response); + } catch (error) { + console.error('Error fetching users:', error); + } + }; + + const addParticipant = async (channelId, participantId, participantName) => { + try { + const adapter = fleetbase.getAdapter(); + const res = await adapter.post(`chat-channels/${channelId}/add-participant`, { user: participantId }); + + const newMessage = { + _id: new Date().getTime(), + text: `Added ${participantName} to this channel`, + createdAt: new Date(), + user: { + _id: 1, + name: 'System', + }, + }; + + setMessages(previousMessages => GiftedChat.append(previousMessages, [newMessage])); + setShowUserList(false); } catch (error) { console.error('Add participant:', error); @@ -67,31 +118,6 @@ const ChatScreen = ({ route }) => { } }; - useEffect(() => { - setMessages([ - { - _id: 1, - text: 'Hello developer', - createdAt: new Date(), - user: { - _id: 2, - name: 'React Native', - avatar: 'https://placeimg.com/140/140/any', - }, - }, - { - _id: 2, - text: 'Hello world', - createdAt: new Date(), - user: { - _id: 1, - name: 'React Native', - avatar: 'https://placeimg.com/140/140/any', - }, - }, - ]); - }, []); - const onSend = useCallback((messages = []) => { setMessages(previousMessages => GiftedChat.append(previousMessages, messages)); }, []); @@ -221,7 +247,7 @@ const ChatScreen = ({ route }) => { data={users} keyExtractor={item => item.id.toString()} renderItem={({ item }) => ( - addParticipant(item.id)} style={tailwind('flex flex-row items-center py-2')}> + addParticipant(itemData.id, item.id, item.name)} style={tailwind('flex flex-row items-center py-2')}> {item.name} From a4408d12d96eee54b3d9eb4a6c434a4c7700ab5e Mon Sep 17 00:00:00 2001 From: Doljinsuren Enkhbayar Date: Thu, 18 Apr 2024 12:54:49 +0800 Subject: [PATCH 16/57] Added delete function --- src/features/Core/screens/ChatScreen.js | 80 +++++++++++++++++++++++-- 1 file changed, 75 insertions(+), 5 deletions(-) diff --git a/src/features/Core/screens/ChatScreen.js b/src/features/Core/screens/ChatScreen.js index 7d7d4faa..3eb5f7de 100644 --- a/src/features/Core/screens/ChatScreen.js +++ b/src/features/Core/screens/ChatScreen.js @@ -1,11 +1,11 @@ -import { faAngleLeft, faPaperPlane, faUpload, faUser, faEdit } from '@fortawesome/free-solid-svg-icons'; +import { faAngleLeft, faEdit, faPaperPlane, faUpload, faUser, faTrash } from '@fortawesome/free-solid-svg-icons'; import { FontAwesomeIcon } from '@fortawesome/react-native-fontawesome'; import { useNavigation } from '@react-navigation/native'; import { useFleetbase } from 'hooks'; import React, { useCallback, useEffect, useState } from 'react'; -import { FlatList, Text, TouchableOpacity, View } from 'react-native'; -import { launchImageLibrary } from 'react-native-image-picker'; +import { FlatList, Image, Text, TouchableOpacity, View } from 'react-native'; import { Actions, Bubble, GiftedChat, InputToolbar, Send } from 'react-native-gifted-chat'; +import { launchImageLibrary } from 'react-native-image-picker'; import { tailwind } from 'tailwind'; const ChatScreen = ({ route }) => { @@ -17,6 +17,7 @@ const ChatScreen = ({ route }) => { const [users, setUsers] = useState([]); const [channel, setChannel] = useState([]); const [showUserList, setShowUserList] = useState(false); + const [addedParticipants, setAddedParticipants] = useState([]); useEffect(() => { fetchUsers(itemData?.id); @@ -86,11 +87,19 @@ const ChatScreen = ({ route }) => { } }; - const addParticipant = async (channelId, participantId, participantName) => { + const addParticipant = async (channelId, participantId, participantName, avatar) => { try { const adapter = fleetbase.getAdapter(); const res = await adapter.post(`chat-channels/${channelId}/add-participant`, { user: participantId }); + setAddedParticipants(prevParticipants => [ + ...prevParticipants, + { + id: participantId, + name: participantName, + avatar: avatar, + }, + ]); const newMessage = { _id: new Date().getTime(), text: `Added ${participantName} to this channel`, @@ -109,6 +118,65 @@ const ChatScreen = ({ route }) => { } }; + const deleteParticipant = async participantId => { + try { + const adapter = fleetbase.getAdapter(); + await adapter.delete(`chat-channels/remove-participant/${participantId}`); + + setAddedParticipants(prevParticipants => prevParticipants.filter(participant => participant.id !== participantId)); + + const newMessage = { + _id: new Date().getTime(), + text: `Removed participant from this channel`, + createdAt: new Date(), + user: { + _id: 1, + name: 'System', + }, + }; + setMessages(previousMessages => GiftedChat.append(previousMessages, [newMessage])); + } catch (error) { + console.error('Remove participant:', error); + } + }; + + const AddedParticipants = ({ participants, onDelete }) => { + return ( + + {participants.map(participant => ( + + + + + removeParticipant(participant.id)}> + + + + {participant.name} + + ))} + + ); + }; + const removeParticipant = async participantId => { try { const adapter = fleetbase.getAdapter(); @@ -247,7 +315,7 @@ const ChatScreen = ({ route }) => { data={users} keyExtractor={item => item.id.toString()} renderItem={({ item }) => ( - addParticipant(itemData.id, item.id, item.name)} style={tailwind('flex flex-row items-center py-2')}> + addParticipant(itemData.id, item.id, item.name, item.avatar_url)} style={tailwind('flex flex-row items-center py-2')}> {item.name} @@ -259,6 +327,8 @@ const ChatScreen = ({ route }) => { )} + + Date: Thu, 18 Apr 2024 13:57:47 +0800 Subject: [PATCH 17/57] fixed remove function --- src/features/Core/screens/ChatScreen.js | 83 ++++++++++++------------- 1 file changed, 39 insertions(+), 44 deletions(-) diff --git a/src/features/Core/screens/ChatScreen.js b/src/features/Core/screens/ChatScreen.js index 3eb5f7de..6d98c3a3 100644 --- a/src/features/Core/screens/ChatScreen.js +++ b/src/features/Core/screens/ChatScreen.js @@ -1,9 +1,9 @@ -import { faAngleLeft, faEdit, faPaperPlane, faUpload, faUser, faTrash } from '@fortawesome/free-solid-svg-icons'; +import { faAngleLeft, faEdit, faPaperPlane, faTrash, faUpload, faUser } from '@fortawesome/free-solid-svg-icons'; import { FontAwesomeIcon } from '@fortawesome/react-native-fontawesome'; import { useNavigation } from '@react-navigation/native'; import { useFleetbase } from 'hooks'; import React, { useCallback, useEffect, useState } from 'react'; -import { FlatList, Image, Text, TouchableOpacity, View } from 'react-native'; +import { Alert, FlatList, Image, Text, TouchableOpacity, View } from 'react-native'; import { Actions, Bubble, GiftedChat, InputToolbar, Send } from 'react-native-gifted-chat'; import { launchImageLibrary } from 'react-native-image-picker'; import { tailwind } from 'tailwind'; @@ -15,13 +15,11 @@ const ChatScreen = ({ route }) => { const [messages, setMessages] = useState([]); const [text, setText] = useState(); const [users, setUsers] = useState([]); - const [channel, setChannel] = useState([]); const [showUserList, setShowUserList] = useState(false); const [addedParticipants, setAddedParticipants] = useState([]); useEffect(() => { fetchUsers(itemData?.id); - fetchChannels(); }, []); useEffect(() => { @@ -51,7 +49,7 @@ const ChatScreen = ({ route }) => { const addChannelCreationMessage = () => { const newMessage = { - _id: new Date().getTime(), // Use current timestamp as a unique ID + _id: new Date().getTime(), text: 'Channel created successfully', createdAt: new Date(), user: { @@ -62,17 +60,6 @@ const ChatScreen = ({ route }) => { setMessages(previousMessages => GiftedChat.append(previousMessages, [newMessage])); }; - const fetchChannels = async () => { - try { - const adapter = fleetbase.getAdapter(); - const response = await adapter.get('chat-channels'); - setChannel(response); - addChannelCreationMessage(); - } catch (error) { - console.error('Error fetching channels:', error); - } - }; - const toggleUserList = () => { setShowUserList(!showUserList); }; @@ -81,6 +68,7 @@ const ChatScreen = ({ route }) => { try { const adapter = fleetbase.getAdapter(); const response = await adapter.get(`chat-channels/${id}/available-participants`); + console.log('response:::::::', JSON.stringify(response)); setUsers(response); } catch (error) { console.error('Error fetching users:', error); @@ -118,28 +106,6 @@ const ChatScreen = ({ route }) => { } }; - const deleteParticipant = async participantId => { - try { - const adapter = fleetbase.getAdapter(); - await adapter.delete(`chat-channels/remove-participant/${participantId}`); - - setAddedParticipants(prevParticipants => prevParticipants.filter(participant => participant.id !== participantId)); - - const newMessage = { - _id: new Date().getTime(), - text: `Removed participant from this channel`, - createdAt: new Date(), - user: { - _id: 1, - name: 'System', - }, - }; - setMessages(previousMessages => GiftedChat.append(previousMessages, [newMessage])); - } catch (error) { - console.error('Remove participant:', error); - } - }; - const AddedParticipants = ({ participants, onDelete }) => { return ( @@ -166,7 +132,7 @@ const ChatScreen = ({ route }) => { right: -4, }, ]} - onPress={() => removeParticipant(participant.id)}> + onPress={() => confirmRemove(participant.id)}> @@ -177,15 +143,45 @@ const ChatScreen = ({ route }) => { ); }; + const confirmRemove = participantId => { + Alert.alert( + 'Confirmation', + 'Are you sure you wish to remove this participant from the chat?', + [ + { + text: 'Cancel', + style: 'cancel', + }, + { + text: 'OK', + onPress: () => removeParticipant(participantId), + }, + ], + { cancelable: false } + ); + }; + const removeParticipant = async participantId => { try { const adapter = fleetbase.getAdapter(); - const res = await adapter.delete(`chat-channels/remove-participant/${participantId}`); + await adapter.delete(`chat-channels/remove-participant/${participantId}`); + + setAddedParticipants(prevParticipants => prevParticipants.filter(participant => participant.id !== participantId)); + + const newMessage = { + _id: new Date().getTime(), + text: `Removed participant from this channel`, + createdAt: new Date(), + user: { + _id: 1, + name: 'System', + }, + }; + setMessages(previousMessages => GiftedChat.append(previousMessages, [newMessage])); } catch (error) { console.error('Remove participant:', error); } }; - const onSend = useCallback((messages = []) => { setMessages(previousMessages => GiftedChat.append(previousMessages, messages)); }, []); @@ -287,7 +283,7 @@ const ChatScreen = ({ route }) => { return ( - + navigation.goBack()}> @@ -327,8 +323,7 @@ const ChatScreen = ({ route }) => { )} - - + Date: Thu, 18 Apr 2024 14:36:25 +0800 Subject: [PATCH 18/57] fixed name --- src/features/Core/screens/ChannelScreen.js | 4 ++-- src/features/Core/screens/ChatScreen.js | 14 ++++++++------ src/features/Core/screens/ChatsScreen.js | 2 +- 3 files changed, 11 insertions(+), 9 deletions(-) diff --git a/src/features/Core/screens/ChannelScreen.js b/src/features/Core/screens/ChannelScreen.js index a1d4c9b7..5c883854 100644 --- a/src/features/Core/screens/ChannelScreen.js +++ b/src/features/Core/screens/ChannelScreen.js @@ -29,7 +29,7 @@ const ChannelScreen = ({ route }) => { return adapter .put(`chat-channels/${channelId}`, data) .then(res => { - navigation.navigate('ChatScreen', { data: res }); + navigation.navigate('ChatScreen', { channelData: res }); }) .catch(logError) .finally(() => setIsLoading(false)); @@ -37,7 +37,7 @@ const ChannelScreen = ({ route }) => { return adapter .post('chat-channels', { name }) .then(res => { - navigation.navigate('ChatScreen', { data: res }); + navigation.navigate('ChatScreen', { channelData: res }); }) .catch(logError) .finally(() => setIsLoading(false)); diff --git a/src/features/Core/screens/ChatScreen.js b/src/features/Core/screens/ChatScreen.js index 6d98c3a3..abeff731 100644 --- a/src/features/Core/screens/ChatScreen.js +++ b/src/features/Core/screens/ChatScreen.js @@ -9,7 +9,7 @@ import { launchImageLibrary } from 'react-native-image-picker'; import { tailwind } from 'tailwind'; const ChatScreen = ({ route }) => { - const { data, itemData } = route.params; + const { channelData, chatsData } = route.params; const fleetbase = useFleetbase(); const navigation = useNavigation(); const [messages, setMessages] = useState([]); @@ -19,7 +19,7 @@ const ChatScreen = ({ route }) => { const [addedParticipants, setAddedParticipants] = useState([]); useEffect(() => { - fetchUsers(itemData?.id); + fetchUsers(chatsData?.id || channelData.id); }, []); useEffect(() => { @@ -289,9 +289,9 @@ const ChatScreen = ({ route }) => { - {itemData?.name || data.name} + {chatsData?.name || channelData.name} {' '} - navigation.navigate('ChannelScreen', { data: itemData })}> + navigation.navigate('ChannelScreen', { data: chatsData })}> @@ -311,7 +311,9 @@ const ChatScreen = ({ route }) => { data={users} keyExtractor={item => item.id.toString()} renderItem={({ item }) => ( - addParticipant(itemData.id, item.id, item.name, item.avatar_url)} style={tailwind('flex flex-row items-center py-2')}> + addParticipant(chatsData.id, item.id, item.name, item.avatar_url)} + style={tailwind('flex flex-row items-center py-2')}> {item.name} @@ -323,7 +325,7 @@ const ChatScreen = ({ route }) => { )} - + { }; const renderItem = ({ item }) => ( - navigation.navigate('ChatScreen', { itemData: item })}> + navigation.navigate('ChatScreen', { chatsData: item })}> Date: Thu, 18 Apr 2024 15:01:33 +0800 Subject: [PATCH 19/57] user ui fix --- src/features/Core/screens/ChatScreen.js | 40 +++++++++++++++---------- 1 file changed, 24 insertions(+), 16 deletions(-) diff --git a/src/features/Core/screens/ChatScreen.js b/src/features/Core/screens/ChatScreen.js index abeff731..a248f9f9 100644 --- a/src/features/Core/screens/ChatScreen.js +++ b/src/features/Core/screens/ChatScreen.js @@ -3,7 +3,8 @@ import { FontAwesomeIcon } from '@fortawesome/react-native-fontawesome'; import { useNavigation } from '@react-navigation/native'; import { useFleetbase } from 'hooks'; import React, { useCallback, useEffect, useState } from 'react'; -import { Alert, FlatList, Image, Text, TouchableOpacity, View } from 'react-native'; +import FastImage from 'react-native-fast-image'; +import { Alert, FlatList, Text, TouchableOpacity, View } from 'react-native'; import { Actions, Bubble, GiftedChat, InputToolbar, Send } from 'react-native-gifted-chat'; import { launchImageLibrary } from 'react-native-image-picker'; import { tailwind } from 'tailwind'; @@ -112,24 +113,31 @@ const ChatScreen = ({ route }) => { {participants.map(participant => ( - - + + + + confirmRemove(participant.id)}> @@ -312,7 +320,7 @@ const ChatScreen = ({ route }) => { keyExtractor={item => item.id.toString()} renderItem={({ item }) => ( addParticipant(chatsData.id, item.id, item.name, item.avatar_url)} + onPress={() => addParticipant(chatsData.id || channelData?.id, item.id, item.name, item.avatar_url)} style={tailwind('flex flex-row items-center py-2')}> From 985081b4a2462dc20105a9639a2c9efca48b049c Mon Sep 17 00:00:00 2001 From: Doljinsuren Enkhbayar Date: Thu, 18 Apr 2024 16:10:22 +0800 Subject: [PATCH 20/57] showed particient by modal --- src/features/Core/screens/ChatScreen.js | 62 ++++++++++++++++--------- translations/en.json | 3 +- 2 files changed, 41 insertions(+), 24 deletions(-) diff --git a/src/features/Core/screens/ChatScreen.js b/src/features/Core/screens/ChatScreen.js index a248f9f9..af60dfb3 100644 --- a/src/features/Core/screens/ChatScreen.js +++ b/src/features/Core/screens/ChatScreen.js @@ -3,11 +3,13 @@ import { FontAwesomeIcon } from '@fortawesome/react-native-fontawesome'; import { useNavigation } from '@react-navigation/native'; import { useFleetbase } from 'hooks'; import React, { useCallback, useEffect, useState } from 'react'; -import FastImage from 'react-native-fast-image'; import { Alert, FlatList, Text, TouchableOpacity, View } from 'react-native'; +import FastImage from 'react-native-fast-image'; import { Actions, Bubble, GiftedChat, InputToolbar, Send } from 'react-native-gifted-chat'; import { launchImageLibrary } from 'react-native-image-picker'; +import Modal from 'react-native-modal'; import { tailwind } from 'tailwind'; +import { translate } from 'utils'; const ChatScreen = ({ route }) => { const { channelData, chatsData } = route.params; @@ -69,7 +71,6 @@ const ChatScreen = ({ route }) => { try { const adapter = fleetbase.getAdapter(); const response = await adapter.get(`chat-channels/${id}/available-participants`); - console.log('response:::::::', JSON.stringify(response)); setUsers(response); } catch (error) { console.error('Error fetching users:', error); @@ -98,7 +99,6 @@ const ChatScreen = ({ route }) => { name: 'System', }, }; - setMessages(previousMessages => GiftedChat.append(previousMessages, [newMessage])); setShowUserList(false); @@ -150,7 +150,6 @@ const ChatScreen = ({ route }) => { ); }; - const confirmRemove = participantId => { Alert.alert( 'Confirmation', @@ -311,26 +310,43 @@ const ChatScreen = ({ route }) => { - - {showUserList && ( - - - item.id.toString()} - renderItem={({ item }) => ( - addParticipant(chatsData.id || channelData?.id, item.id, item.name, item.avatar_url)} - style={tailwind('flex flex-row items-center py-2')}> - - - {item.name} - - )} - /> - + + + {translate('Core.ChatScreen.title')}: + item.id.toString()} + renderItem={({ item }) => ( + addParticipant(chatsData.id || channelData?.id, item.id, item.name, item.avatar_url)} + style={tailwind('flex flex-row items-center py-2 border border-gray-500 rounded-lg mb-2')}> + + + + + {item.name} + + )} + /> - )} + diff --git a/translations/en.json b/translations/en.json index fe096769..66afdad3 100644 --- a/translations/en.json +++ b/translations/en.json @@ -66,7 +66,8 @@ "update-channel": "Update channel" }, "ChatsScreen": { - "delete": "Delete" + "delete": "Delete", + "title": "Select User" } }, "Exceptions": { From 86dcfdad044a882ce6696da842f38dacf9f9edb2 Mon Sep 17 00:00:00 2001 From: Doljinsuren Enkhbayar Date: Thu, 18 Apr 2024 16:39:18 +0800 Subject: [PATCH 21/57] checked if participant already added --- src/features/Core/screens/ChatScreen.js | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/features/Core/screens/ChatScreen.js b/src/features/Core/screens/ChatScreen.js index af60dfb3..f6232a9c 100644 --- a/src/features/Core/screens/ChatScreen.js +++ b/src/features/Core/screens/ChatScreen.js @@ -78,6 +78,13 @@ const ChatScreen = ({ route }) => { }; const addParticipant = async (channelId, participantId, participantName, avatar) => { + const isParticipantAdded = addedParticipants.some(participant => participant.id === participantId); + + if (isParticipantAdded) { + Alert.alert('Alert', `${participantName} is already a part of this channel.`, [{ text: 'OK' }]); + return; + } + try { const adapter = fleetbase.getAdapter(); const res = await adapter.post(`chat-channels/${channelId}/add-participant`, { user: participantId }); From 1e022c56d1b8675a9397acabc57c2a43806abee4 Mon Sep 17 00:00:00 2001 From: Doljinsuren Enkhbayar Date: Thu, 18 Apr 2024 16:47:40 +0800 Subject: [PATCH 22/57] added indicator --- src/features/Core/screens/ChatScreen.js | 70 ++++++++++++++----------- 1 file changed, 40 insertions(+), 30 deletions(-) diff --git a/src/features/Core/screens/ChatScreen.js b/src/features/Core/screens/ChatScreen.js index f6232a9c..8845bd42 100644 --- a/src/features/Core/screens/ChatScreen.js +++ b/src/features/Core/screens/ChatScreen.js @@ -3,7 +3,7 @@ import { FontAwesomeIcon } from '@fortawesome/react-native-fontawesome'; import { useNavigation } from '@react-navigation/native'; import { useFleetbase } from 'hooks'; import React, { useCallback, useEffect, useState } from 'react'; -import { Alert, FlatList, Text, TouchableOpacity, View } from 'react-native'; +import { Alert, FlatList, Text, TouchableOpacity, View, ScrollView, ActivityIndicator } from 'react-native'; import FastImage from 'react-native-fast-image'; import { Actions, Bubble, GiftedChat, InputToolbar, Send } from 'react-native-gifted-chat'; import { launchImageLibrary } from 'react-native-image-picker'; @@ -18,6 +18,7 @@ const ChatScreen = ({ route }) => { const [messages, setMessages] = useState([]); const [text, setText] = useState(); const [users, setUsers] = useState([]); + const [isLoading, setIsLoading] = useState(false); const [showUserList, setShowUserList] = useState(false); const [addedParticipants, setAddedParticipants] = useState([]); @@ -113,10 +114,9 @@ const ChatScreen = ({ route }) => { console.error('Add participant:', error); } }; - const AddedParticipants = ({ participants, onDelete }) => { return ( - + {participants.map(participant => ( @@ -154,7 +154,7 @@ const ChatScreen = ({ route }) => { {participant.name} ))} - + ); }; const confirmRemove = participantId => { @@ -325,33 +325,43 @@ const ChatScreen = ({ route }) => { useNativeDriver animationIn="slideInUp" animationOut="slideOutDown"> - + {translate('Core.ChatScreen.title')}: - item.id.toString()} - renderItem={({ item }) => ( - addParticipant(chatsData.id || channelData?.id, item.id, item.name, item.avatar_url)} - style={tailwind('flex flex-row items-center py-2 border border-gray-500 rounded-lg mb-2')}> - - - - - {item.name} - - )} - /> + + {isLoading ? ( + + + + ) : ( + item.id.toString()} + renderItem={({ item }) => ( + addParticipant(chatsData.id || channelData?.id, item.id, item.name, item.avatar_url)} + style={tailwind('flex flex-row items-center py-2 border border-gray-500 rounded-lg mb-2')}> + + + + + {item.name} + + )} + /> + )} From b058c4407d87b93750fd0927ae8de59b407b1b35 Mon Sep 17 00:00:00 2001 From: Doljinsuren Enkhbayar Date: Thu, 18 Apr 2024 17:13:02 +0800 Subject: [PATCH 23/57] fixed bug navigation, button --- src/features/Core/screens/ChannelScreen.js | 7 +++--- src/features/Core/screens/ChatScreen.js | 4 ++-- src/features/Core/screens/ChatsScreen.js | 25 ++++++++++++---------- 3 files changed, 20 insertions(+), 16 deletions(-) diff --git a/src/features/Core/screens/ChannelScreen.js b/src/features/Core/screens/ChannelScreen.js index 5c883854..f2c40f78 100644 --- a/src/features/Core/screens/ChannelScreen.js +++ b/src/features/Core/screens/ChannelScreen.js @@ -23,6 +23,7 @@ const ChannelScreen = ({ route }) => { }, [route]); const saveChannel = () => { + setIsLoading(true); const adapter = fleetbase.getAdapter(); const data = { name }; if (channelId) { @@ -32,7 +33,7 @@ const ChannelScreen = ({ route }) => { navigation.navigate('ChatScreen', { channelData: res }); }) .catch(logError) - .finally(() => setIsLoading(false)); + .finally(() => setIsLoading(false)); // End the loading indicator } else { return adapter .post('chat-channels', { name }) @@ -40,7 +41,7 @@ const ChannelScreen = ({ route }) => { navigation.navigate('ChatScreen', { channelData: res }); }) .catch(logError) - .finally(() => setIsLoading(false)); + .finally(() => setIsLoading(false)); // End the loading indicator } }; @@ -49,7 +50,7 @@ const ChannelScreen = ({ route }) => { {channelId ? translate('Core.ChannelScreen.update-channel') : translate('Core.ChannelScreen.title')} - navigation.navigate('ChatsScreen')} style={tailwind('mr-4')}> + navigation.pop(2)} style={tailwind('mr-4')}> diff --git a/src/features/Core/screens/ChatScreen.js b/src/features/Core/screens/ChatScreen.js index 8845bd42..027210fe 100644 --- a/src/features/Core/screens/ChatScreen.js +++ b/src/features/Core/screens/ChatScreen.js @@ -298,7 +298,7 @@ const ChatScreen = ({ route }) => { - navigation.goBack()}> + navigation.pop(2)}> @@ -330,7 +330,7 @@ const ChatScreen = ({ route }) => { {isLoading ? ( - + ) : ( { }; const renderItem = ({ item }) => ( - navigation.navigate('ChatScreen', { chatsData: item })}> - + navigation.navigate('ChatScreen', { chatsData: item })} + underlayColor={tailwind('bg-gray-900')}> + + + {item.name} + {item.message} + + + {formatTime(item.created_at)} + - - {item.name} - {item.message} - - - {formatTime(item.created_at)} - - + ); const renderHiddenItem = ({ item }) => ( From 638d4c2c1858fe3d3bac508ab27830f7d8ff7b4a Mon Sep 17 00:00:00 2001 From: Doljinsuren Enkhbayar Date: Thu, 18 Apr 2024 17:20:47 +0800 Subject: [PATCH 24/57] fix border --- src/features/Core/screens/ChatScreen.js | 2 +- src/features/Core/screens/ChatsScreen.js | 5 +++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/features/Core/screens/ChatScreen.js b/src/features/Core/screens/ChatScreen.js index 027210fe..dcacf94e 100644 --- a/src/features/Core/screens/ChatScreen.js +++ b/src/features/Core/screens/ChatScreen.js @@ -339,7 +339,7 @@ const ChatScreen = ({ route }) => { renderItem={({ item }) => ( addParticipant(chatsData.id || channelData?.id, item.id, item.name, item.avatar_url)} - style={tailwind('flex flex-row items-center py-2 border border-gray-500 rounded-lg mb-2')}> + style={tailwind('flex flex-row items-center py-2 bg-gray-900 rounded-lg mb-2')}> { const renderItem = ({ item }) => ( navigation.navigate('ChatScreen', { chatsData: item })} underlayColor={tailwind('bg-gray-900')}> @@ -155,10 +155,11 @@ const styles = StyleSheet.create({ }, backRightBtnRight: { backgroundColor: '#FF3A3A', - right: 0, + right: 4, top: 8, marginRight: 12, marginLeft: 6, + borderRadius: 12, }, loaderContainer: { position: 'absolute', From 5d9c4a83e3fe82a9aca8af071f864f389fe594c6 Mon Sep 17 00:00:00 2001 From: Doljinsuren Enkhbayar Date: Thu, 18 Apr 2024 19:05:07 +0800 Subject: [PATCH 25/57] change file upload --- package.json | 2 +- src/features/Core/screens/ChatScreen.js | 82 +++++++++++++++++++----- src/features/Core/screens/ChatsScreen.js | 28 -------- 3 files changed, 68 insertions(+), 44 deletions(-) diff --git a/package.json b/package.json index eeb6f7fa..a5b389b9 100644 --- a/package.json +++ b/package.json @@ -87,7 +87,7 @@ "react-native-maps": "^2.0.0-beta.14", "react-native-maps-directions": "^1.8.0", "react-native-mmkv-storage": "^0.9.0", - "react-native-modal": "^12.0.2", + "react-native-modal": "^13.0.1", "react-native-navigation-apps": "^1.0.27", "react-native-open-maps": "^0.4.0", "react-native-permissions": "^3.0.5", diff --git a/src/features/Core/screens/ChatScreen.js b/src/features/Core/screens/ChatScreen.js index dcacf94e..0ad95d3b 100644 --- a/src/features/Core/screens/ChatScreen.js +++ b/src/features/Core/screens/ChatScreen.js @@ -7,9 +7,11 @@ import { Alert, FlatList, Text, TouchableOpacity, View, ScrollView, ActivityIndi import FastImage from 'react-native-fast-image'; import { Actions, Bubble, GiftedChat, InputToolbar, Send } from 'react-native-gifted-chat'; import { launchImageLibrary } from 'react-native-image-picker'; +import RNFS from 'react-native-fs'; import Modal from 'react-native-modal'; import { tailwind } from 'tailwind'; -import { translate } from 'utils'; + +import { translate, HelperUtil } from 'utils'; const ChatScreen = ({ route }) => { const { channelData, chatsData } = route.params; @@ -24,6 +26,7 @@ const ChatScreen = ({ route }) => { useEffect(() => { fetchUsers(chatsData?.id || channelData.id); + uploadFile(); }, []); useEffect(() => { @@ -51,6 +54,33 @@ const ChatScreen = ({ route }) => { ]); }, []); + const listenForOrdersFromSocket = (channelId, callback) => { + HelperUtil.createSocketAndListen(`chat.${chatChannelRecord.public_id}`, socketEvent => { + const { event, data } = socketEvent; + switch (event) { + case 'chat.added_participant': + case 'chat.removed_participant': + case 'chat_participant.created': + case 'chat_participant.deleted': + this.channel.reloadParticipants(); + this.loadAvailableUsers(); + break; + case 'chat_message.created': + this.chat.insertChatMessageFromSocket(this.channel, data); + break; + case 'chat_log.created': + this.chat.insertChatLogFromSocket(this.channel, data); + break; + case 'chat_attachment.created': + this.chat.insertChatAttachmentFromSocket(this.channel, data); + break; + case 'chat_receipt.created': + this.chat.insertChatReceiptFromSocket(this.channel, data); + break; + } + this.handleChatFeedScroll(); + }); + }; const addChannelCreationMessage = () => { const newMessage = { _id: new Date().getTime(), @@ -64,6 +94,32 @@ const ChatScreen = ({ route }) => { setMessages(previousMessages => GiftedChat.append(previousMessages, [newMessage])); }; + + const uploadFile = async url => { + // Extract filename from URL + + console.log('res>>>>>>>>', JSON.stringify(url)); + // const fileNameParts = url?.split('/')?.pop()?.split('?'); + + const fileName = fileNameParts.length > 0 ? fileNameParts[0] : ''; + + console.log('fileName::::', JSON.stringify(url)); + // Create local file path + const localFile = `${RNFS.DocumentDirectoryPath}/${fileName}`; + + console.log('localFile::::', JSON.stringify(localFile)); + // Set up download options + const options = { + fromUrl: url, + toFile: localFile, + }; + + RNFS.uploadFiles(options).promise.then(() => { + RNFS.readDir(RNFS.DocumentDirectoryPath); + FileViewer.open(localFile); + }); + }; + const toggleUserList = () => { setShowUserList(!showUserList); }; @@ -230,15 +286,15 @@ const ChatScreen = ({ route }) => { return ; }; - const uploadFile = async file => { - const formData = new FormData(); - formData.append('file', { - uri: file.uri, - name: file.name, - type: file.type, - }); + const sentMessage = async channelId => { + try { + const adapter = fleetbase.getAdapter(); + const res = await adapter.post(`chat-channels/${channelId}/send-message`, { sender: participantId, content: content, file: file }); - //todo + setShowUserList(false); + } catch (error) { + console.error('Add participant:', error); + } }; const chooseFile = () => { @@ -256,12 +312,8 @@ const ChatScreen = ({ route }) => { } else if (response.error) { console.log('ImagePicker Error: ', response.error); } else { - const file = { - uri: response.uri, - name: response.fileName, - type: response.type, - }; - uploadFile(file); + console.log('response::::', JSON.stringify(response.assets[0])); + uploadFile(response.assets[0]); } }); }; diff --git a/src/features/Core/screens/ChatsScreen.js b/src/features/Core/screens/ChatsScreen.js index 1a6251db..25b3342a 100644 --- a/src/features/Core/screens/ChatsScreen.js +++ b/src/features/Core/screens/ChatsScreen.js @@ -24,34 +24,6 @@ const ChatsScreen = () => { return unsubscribe; }, [isMounted]); - const listenForOrdersFromSocket = (channelId, callback) => { - HelperUtil.createSocketAndListen(`chat.${chatChannelRecord.public_id}`, socketEvent => { - const { event, data } = socketEvent; - switch (event) { - case 'chat.added_participant': - case 'chat.removed_participant': - case 'chat_participant.created': - case 'chat_participant.deleted': - this.channel.reloadParticipants(); - this.loadAvailableUsers(); - break; - case 'chat_message.created': - this.chat.insertChatMessageFromSocket(this.channel, data); - break; - case 'chat_log.created': - this.chat.insertChatLogFromSocket(this.channel, data); - break; - case 'chat_attachment.created': - this.chat.insertChatAttachmentFromSocket(this.channel, data); - break; - case 'chat_receipt.created': - this.chat.insertChatReceiptFromSocket(this.channel, data); - break; - } - this.handleChatFeedScroll(); - }); - }; - const fetchChannels = async () => { setIsLoading(true); try { From 4d60a3f0300caea35b51a5b08abdfc9e82c800d8 Mon Sep 17 00:00:00 2001 From: Doljinsuren Enkhbayar Date: Fri, 19 Apr 2024 14:59:41 +0800 Subject: [PATCH 26/57] added send func --- src/features/Core/screens/ChatScreen.js | 19 +++++++++++++------ src/features/Core/screens/ChatsScreen.js | 3 ++- translations/en.json | 4 +++- 3 files changed, 18 insertions(+), 8 deletions(-) diff --git a/src/features/Core/screens/ChatScreen.js b/src/features/Core/screens/ChatScreen.js index 0ad95d3b..9ec5b403 100644 --- a/src/features/Core/screens/ChatScreen.js +++ b/src/features/Core/screens/ChatScreen.js @@ -26,7 +26,6 @@ const ChatScreen = ({ route }) => { useEffect(() => { fetchUsers(chatsData?.id || channelData.id); - uploadFile(); }, []); useEffect(() => { @@ -94,7 +93,6 @@ const ChatScreen = ({ route }) => { setMessages(previousMessages => GiftedChat.append(previousMessages, [newMessage])); }; - const uploadFile = async url => { // Extract filename from URL @@ -252,9 +250,18 @@ const ChatScreen = ({ route }) => { console.error('Remove participant:', error); } }; - const onSend = useCallback((messages = []) => { - setMessages(previousMessages => GiftedChat.append(previousMessages, messages)); - }, []); + + const onSend = async newMessage => { + try { + console.log('Sending: ', newMessage); + const adapter = fleetbase.getAdapter(); + const res = await adapter.post(`chat-channels/${chatsData?.id || channelData.id}/send-message`, { sender: "ts", content: newMessage[0].text }); + setShowUserList(false); + setMessages(previousMessages => GiftedChat.append(previousMessages, newMessage)); + } catch (error) { + console.error('Send error:', error); + } + }; const renderSend = props => { return ( @@ -428,7 +435,7 @@ const ChatScreen = ({ route }) => { renderBubble={renderBubble} alwaysShowSend scrollToBottom - renderInputToolbar={MessengerBarContainer} + renderInputToolbar={props => MessengerBarContainer(props)} renderActions={renderActions} scrollToBottomComponent={scrollToBottomComponent} renderSend={renderSend} diff --git a/src/features/Core/screens/ChatsScreen.js b/src/features/Core/screens/ChatsScreen.js index 25b3342a..d13e6cce 100644 --- a/src/features/Core/screens/ChatsScreen.js +++ b/src/features/Core/screens/ChatsScreen.js @@ -128,7 +128,8 @@ const styles = StyleSheet.create({ backRightBtnRight: { backgroundColor: '#FF3A3A', right: 4, - top: 8, + top: 10, + bottom: 2, marginRight: 12, marginLeft: 6, borderRadius: 12, diff --git a/translations/en.json b/translations/en.json index 66afdad3..e0144015 100644 --- a/translations/en.json +++ b/translations/en.json @@ -66,7 +66,9 @@ "update-channel": "Update channel" }, "ChatsScreen": { - "delete": "Delete", + "delete": "Delete" + }, + "ChatScreen": { "title": "Select User" } }, From a9ac39998188a9af0efa8e6416cd6f0bae42f762 Mon Sep 17 00:00:00 2001 From: Doljinsuren Enkhbayar Date: Fri, 19 Apr 2024 16:44:10 +0800 Subject: [PATCH 27/57] fixed send fnc --- src/features/Core/screens/ChatScreen.js | 41 +++++++------------------ 1 file changed, 11 insertions(+), 30 deletions(-) diff --git a/src/features/Core/screens/ChatScreen.js b/src/features/Core/screens/ChatScreen.js index 9ec5b403..227e88dd 100644 --- a/src/features/Core/screens/ChatScreen.js +++ b/src/features/Core/screens/ChatScreen.js @@ -1,57 +1,38 @@ import { faAngleLeft, faEdit, faPaperPlane, faTrash, faUpload, faUser } from '@fortawesome/free-solid-svg-icons'; import { FontAwesomeIcon } from '@fortawesome/react-native-fontawesome'; import { useNavigation } from '@react-navigation/native'; -import { useFleetbase } from 'hooks'; -import React, { useCallback, useEffect, useState } from 'react'; -import { Alert, FlatList, Text, TouchableOpacity, View, ScrollView, ActivityIndicator } from 'react-native'; +import { useDriver, useFleetbase } from 'hooks'; +import React, { useEffect, useState } from 'react'; +import { ActivityIndicator, Alert, FlatList, ScrollView, Text, TouchableOpacity, View } from 'react-native'; import FastImage from 'react-native-fast-image'; +import RNFS from 'react-native-fs'; import { Actions, Bubble, GiftedChat, InputToolbar, Send } from 'react-native-gifted-chat'; import { launchImageLibrary } from 'react-native-image-picker'; -import RNFS from 'react-native-fs'; import Modal from 'react-native-modal'; import { tailwind } from 'tailwind'; -import { translate, HelperUtil } from 'utils'; +import { HelperUtil, translate } from 'utils'; const ChatScreen = ({ route }) => { const { channelData, chatsData } = route.params; const fleetbase = useFleetbase(); const navigation = useNavigation(); + const driver = useDriver(); const [messages, setMessages] = useState([]); const [text, setText] = useState(); const [users, setUsers] = useState([]); const [isLoading, setIsLoading] = useState(false); const [showUserList, setShowUserList] = useState(false); const [addedParticipants, setAddedParticipants] = useState([]); + const driverUser = driver[0].attributes.user; useEffect(() => { fetchUsers(chatsData?.id || channelData.id); }, []); - useEffect(() => { - setMessages([ - { - _id: 1, - text: 'Hello developer', - createdAt: new Date(), - user: { - _id: 2, - name: 'React Native', - avatar: 'https://placeimg.com/140/140/any', - }, - }, - { - _id: 2, - text: 'Hello world', - createdAt: new Date(), - user: { - _id: 1, - name: 'React Native', - avatar: 'https://placeimg.com/140/140/any', - }, - }, - ]); - }, []); + const participantId = chatsData.participants.find(chatParticipant => { + return chatParticipant.user === driverUser; + }); const listenForOrdersFromSocket = (channelId, callback) => { HelperUtil.createSocketAndListen(`chat.${chatChannelRecord.public_id}`, socketEvent => { @@ -255,7 +236,7 @@ const ChatScreen = ({ route }) => { try { console.log('Sending: ', newMessage); const adapter = fleetbase.getAdapter(); - const res = await adapter.post(`chat-channels/${chatsData?.id || channelData.id}/send-message`, { sender: "ts", content: newMessage[0].text }); + const res = await adapter.post(`chat-channels/${chatsData?.id || channelData.id}/send-message`, { sender: participantId.id, content: newMessage[0].text }); setShowUserList(false); setMessages(previousMessages => GiftedChat.append(previousMessages, newMessage)); } catch (error) { From 860edae3aa46f0b3be16f3b30cc8393f1a753af3 Mon Sep 17 00:00:00 2001 From: Doljinsuren Enkhbayar Date: Fri, 19 Apr 2024 17:59:57 +0800 Subject: [PATCH 28/57] added socket fnc --- src/features/Core/screens/ChatScreen.js | 57 +++++++++---------------- src/services/ChatService.js | 33 ++++++++++++++ 2 files changed, 53 insertions(+), 37 deletions(-) create mode 100644 src/services/ChatService.js diff --git a/src/features/Core/screens/ChatScreen.js b/src/features/Core/screens/ChatScreen.js index 227e88dd..c58981ed 100644 --- a/src/features/Core/screens/ChatScreen.js +++ b/src/features/Core/screens/ChatScreen.js @@ -10,8 +10,9 @@ import { Actions, Bubble, GiftedChat, InputToolbar, Send } from 'react-native-gi import { launchImageLibrary } from 'react-native-image-picker'; import Modal from 'react-native-modal'; import { tailwind } from 'tailwind'; - -import { HelperUtil, translate } from 'utils'; +import { createSocketAndListen } from 'utils'; +import { translate } from 'utils'; +import ChatService from '../../../services/ChatService'; const ChatScreen = ({ route }) => { const { channelData, chatsData } = route.params; @@ -28,37 +29,40 @@ const ChatScreen = ({ route }) => { useEffect(() => { fetchUsers(chatsData?.id || channelData.id); + listenForChatFromSocket(chatsData?.id || channelData.id); }, []); const participantId = chatsData.participants.find(chatParticipant => { return chatParticipant.user === driverUser; }); - const listenForOrdersFromSocket = (channelId, callback) => { - HelperUtil.createSocketAndListen(`chat.${chatChannelRecord.public_id}`, socketEvent => { + const listenForChatFromSocket = id => { + const channelID = `chat_channel.${id}`; + + createSocketAndListen(channelID, socketEvent => { const { event, data } = socketEvent; + switch (event) { - case 'chat.added_participant': - case 'chat.removed_participant': - case 'chat_participant.created': - case 'chat_participant.deleted': - this.channel.reloadParticipants(); - this.loadAvailableUsers(); - break; case 'chat_message.created': - this.chat.insertChatMessageFromSocket(this.channel, data); + ChatService.insertChatMessageFromSocket(this.channel, data); break; + case 'chat_log.created': - this.chat.insertChatLogFromSocket(this.channel, data); + ChatService.insertChatLogFromSocket(this.channel, data); break; + case 'chat_attachment.created': - this.chat.insertChatAttachmentFromSocket(this.channel, data); + ChatService.insertChatAttachmentFromSocket(this.channel, data); break; + case 'chat_receipt.created': - this.chat.insertChatReceiptFromSocket(this.channel, data); + ChatService.insertChatReceiptFromSocket(this.channel, data); + break; + + default: + console.log(`Unhandled event type: ${event}`); break; } - this.handleChatFeedScroll(); }); }; const addChannelCreationMessage = () => { @@ -274,17 +278,6 @@ const ChatScreen = ({ route }) => { return ; }; - const sentMessage = async channelId => { - try { - const adapter = fleetbase.getAdapter(); - const res = await adapter.post(`chat-channels/${channelId}/send-message`, { sender: participantId, content: content, file: file }); - - setShowUserList(false); - } catch (error) { - console.error('Add participant:', error); - } - }; - const chooseFile = () => { const options = { title: 'Select File', @@ -324,16 +317,6 @@ const ChatScreen = ({ route }) => { return ; }; - const AdditionalContainer = () => { - return ( - - - - - - ); - }; - return ( diff --git a/src/services/ChatService.js b/src/services/ChatService.js new file mode 100644 index 00000000..a4cc7f49 --- /dev/null +++ b/src/services/ChatService.js @@ -0,0 +1,33 @@ +import { useNavigation } from '@react-navigation/native'; +import { useFleetbase } from 'hooks'; +import { get } from 'utils/Storage'; + +/** + * + * @export + * @class ChatService + */ +export default class ChatService { + /** + * Transitions to an order given the id. + * + * @static + * @param {string} + * @return {Promise} + * @memberof CartService + */ + static insertChatMessageFromSocket(channel, data) { + //todo + } + + static insertChatLogFromSocket(channel, data) { + //todo + } + static insertChatAttachmentFromSocket(channel, data) { + //todo + } + + static insertChatReceiptFromSocket(channel, data) { + //todo + } +} From ff562ff1e1c206675a0da80d0a515898574ea9f2 Mon Sep 17 00:00:00 2001 From: Doljinsuren Enkhbayar Date: Sun, 21 Apr 2024 13:41:19 +0800 Subject: [PATCH 29/57] fix some issues --- ios/Podfile.lock | 6 --- src/features/Core/screens/ChannelScreen.js | 9 +++- src/features/Core/screens/ChatScreen.js | 59 +++++++++++----------- src/features/Core/screens/ChatsScreen.js | 6 +-- translations/en.json | 3 +- 5 files changed, 42 insertions(+), 41 deletions(-) diff --git a/ios/Podfile.lock b/ios/Podfile.lock index 457b227a..a725e89e 100644 --- a/ios/Podfile.lock +++ b/ios/Podfile.lock @@ -580,8 +580,6 @@ PODS: - React-Core - RNCMaskedView (0.1.11): - React - - RNCPicker (2.6.1): - - React-Core - RNCPushNotificationIOS (1.11.0): - React-Core - RNDateTimePicker (6.7.5): @@ -739,7 +737,6 @@ DEPENDENCIES: - RNBootSplash (from `../node_modules/react-native-bootsplash`) - "RNCAsyncStorage (from `../node_modules/@react-native-async-storage/async-storage`)" - "RNCMaskedView (from `../node_modules/@react-native-community/masked-view`)" - - "RNCPicker (from `../node_modules/@react-native-picker/picker`)" - "RNCPushNotificationIOS (from `../node_modules/@react-native-community/push-notification-ios`)" - "RNDateTimePicker (from `../node_modules/@react-native-community/datetimepicker`)" - RNDeviceInfo (from `../node_modules/react-native-device-info`) @@ -903,8 +900,6 @@ EXTERNAL SOURCES: :path: "../node_modules/@react-native-async-storage/async-storage" RNCMaskedView: :path: "../node_modules/@react-native-community/masked-view" - RNCPicker: - :path: "../node_modules/@react-native-picker/picker" RNCPushNotificationIOS: :path: "../node_modules/@react-native-community/push-notification-ios" RNDateTimePicker: @@ -1014,7 +1009,6 @@ SPEC CHECKSUMS: RNBootSplash: 85f6b879c080e958afdb4c62ee04497b05fd7552 RNCAsyncStorage: 687bb9e85dd3d45b966662440dcfc0cd962347e6 RNCMaskedView: 0e1bc4bfa8365eba5fbbb71e07fbdc0555249489 - RNCPicker: b18aaf30df596e9b1738e7c1f9ee55402a229dca RNCPushNotificationIOS: 64218f3c776c03d7408284a819b2abfda1834bc8 RNDateTimePicker: 65e1d202799460b286ff5e741d8baf54695e8abd RNDeviceInfo: aad3c663b25752a52bf8fce93f2354001dd185aa diff --git a/src/features/Core/screens/ChannelScreen.js b/src/features/Core/screens/ChannelScreen.js index f2c40f78..b7a61a28 100644 --- a/src/features/Core/screens/ChannelScreen.js +++ b/src/features/Core/screens/ChannelScreen.js @@ -3,6 +3,7 @@ import { FontAwesomeIcon } from '@fortawesome/react-native-fontawesome'; import { useNavigation } from '@react-navigation/native'; import { useFleetbase } from 'hooks'; import React, { useEffect, useState } from 'react'; +import Toast from 'react-native-toast-message'; import { ActivityIndicator, Keyboard, KeyboardAvoidingView, Pressable, Text, TextInput, TouchableOpacity, View } from 'react-native'; import tailwind from 'tailwind'; import { getColorCode, logError, translate } from 'utils'; @@ -33,15 +34,19 @@ const ChannelScreen = ({ route }) => { navigation.navigate('ChatScreen', { channelData: res }); }) .catch(logError) - .finally(() => setIsLoading(false)); // End the loading indicator + .finally(() => setIsLoading(false)); } else { return adapter .post('chat-channels', { name }) .then(res => { navigation.navigate('ChatScreen', { channelData: res }); + Toast.show({ + type: 'success', + text1: `Channel created successfully`, + }); }) .catch(logError) - .finally(() => setIsLoading(false)); // End the loading indicator + .finally(() => setIsLoading(false)); } }; diff --git a/src/features/Core/screens/ChatScreen.js b/src/features/Core/screens/ChatScreen.js index c58981ed..2a1e331b 100644 --- a/src/features/Core/screens/ChatScreen.js +++ b/src/features/Core/screens/ChatScreen.js @@ -1,7 +1,7 @@ -import { faAngleLeft, faEdit, faPaperPlane, faTrash, faUpload, faUser } from '@fortawesome/free-solid-svg-icons'; +import { faAngleLeft, faEdit, faPaperPlane, faTrash, faUser } from '@fortawesome/free-solid-svg-icons'; import { FontAwesomeIcon } from '@fortawesome/react-native-fontawesome'; import { useNavigation } from '@react-navigation/native'; -import { useDriver, useFleetbase } from 'hooks'; +import { useDriver, useFleetbase, useMountedState } from 'hooks'; import React, { useEffect, useState } from 'react'; import { ActivityIndicator, Alert, FlatList, ScrollView, Text, TouchableOpacity, View } from 'react-native'; import FastImage from 'react-native-fast-image'; @@ -10,19 +10,18 @@ import { Actions, Bubble, GiftedChat, InputToolbar, Send } from 'react-native-gi import { launchImageLibrary } from 'react-native-image-picker'; import Modal from 'react-native-modal'; import { tailwind } from 'tailwind'; -import { createSocketAndListen } from 'utils'; -import { translate } from 'utils'; +import { createSocketAndListen, translate } from 'utils'; import ChatService from '../../../services/ChatService'; const ChatScreen = ({ route }) => { const { channelData, chatsData } = route.params; const fleetbase = useFleetbase(); const navigation = useNavigation(); + const isMounted = useMountedState(); const driver = useDriver(); const [messages, setMessages] = useState([]); - const [text, setText] = useState(); const [users, setUsers] = useState([]); - const [isLoading, setIsLoading] = useState(false); + const [isLoading] = useState(false); const [showUserList, setShowUserList] = useState(false); const [addedParticipants, setAddedParticipants] = useState([]); const driverUser = driver[0].attributes.user; @@ -32,10 +31,27 @@ const ChatScreen = ({ route }) => { listenForChatFromSocket(chatsData?.id || channelData.id); }, []); - const participantId = chatsData.participants.find(chatParticipant => { + useEffect(() => { + // Check for errors in the console log + console.log('Component rendered'); + + // Inspect state changes + console.log('Messages:', messages); + console.log('Users:', users); + console.log('Added Participants:', addedParticipants); + }, [messages, users, addedParticipants]); // Add dependencies as needed + + const participantId = chatsData?.participants.find(chatParticipant => { return chatParticipant.user === driverUser; }); + useEffect(() => { + const unsubscribe = navigation.addListener('focus', () => { + fetchUsers(chatsData?.id || channelData.id); + }); + + return unsubscribe; + }, [isMounted]); const listenForChatFromSocket = id => { const channelID = `chat_channel.${id}`; @@ -65,18 +81,6 @@ const ChatScreen = ({ route }) => { } }); }; - const addChannelCreationMessage = () => { - const newMessage = { - _id: new Date().getTime(), - text: 'Channel created successfully', - createdAt: new Date(), - user: { - _id: 1, - name: 'System', - }, - }; - setMessages(previousMessages => GiftedChat.append(previousMessages, [newMessage])); - }; const uploadFile = async url => { // Extract filename from URL @@ -127,7 +131,7 @@ const ChatScreen = ({ route }) => { try { const adapter = fleetbase.getAdapter(); - const res = await adapter.post(`chat-channels/${channelId}/add-participant`, { user: participantId }); + await adapter.post(`chat-channels/${channelId}/add-participant`, { user: participantId }); setAddedParticipants(prevParticipants => [ ...prevParticipants, @@ -220,7 +224,7 @@ const ChatScreen = ({ route }) => { await adapter.delete(`chat-channels/remove-participant/${participantId}`); setAddedParticipants(prevParticipants => prevParticipants.filter(participant => participant.id !== participantId)); - + fetchUsers(chatsData?.id || channelData.id); const newMessage = { _id: new Date().getTime(), text: `Removed participant from this channel`, @@ -238,9 +242,8 @@ const ChatScreen = ({ route }) => { const onSend = async newMessage => { try { - console.log('Sending: ', newMessage); const adapter = fleetbase.getAdapter(); - const res = await adapter.post(`chat-channels/${chatsData?.id || channelData.id}/send-message`, { sender: participantId.id, content: newMessage[0].text }); + await adapter.post(`chat-channels/${chatsData?.id || channelData.id}/send-message`, { sender: participantId.id, content: newMessage[0].text }); setShowUserList(false); setMessages(previousMessages => GiftedChat.append(previousMessages, newMessage)); } catch (error) { @@ -313,10 +316,6 @@ const ChatScreen = ({ route }) => { /> ); - const MessengerBarContainer = props => { - return ; - }; - return ( @@ -388,8 +387,10 @@ const ChatScreen = ({ route }) => { + + + - { renderBubble={renderBubble} alwaysShowSend scrollToBottom - renderInputToolbar={props => MessengerBarContainer(props)} + renderInputToolbar={props => } renderActions={renderActions} scrollToBottomComponent={scrollToBottomComponent} renderSend={renderSend} diff --git a/src/features/Core/screens/ChatsScreen.js b/src/features/Core/screens/ChatsScreen.js index d13e6cce..a9f0355c 100644 --- a/src/features/Core/screens/ChatsScreen.js +++ b/src/features/Core/screens/ChatsScreen.js @@ -7,7 +7,7 @@ import FastImage from 'react-native-fast-image'; import { SwipeListView } from 'react-native-swipe-list-view'; import Toast from 'react-native-toast-message'; import { tailwind } from 'tailwind'; -import { HelperUtil } from 'utils'; +import { HelperUtil, translate } from 'utils'; const ChatsScreen = () => { const navigation = useNavigation(); @@ -88,7 +88,7 @@ const ChatsScreen = () => { const renderHiddenItem = ({ item }) => ( handleDelete(item.id)} style={[styles.backRightBtn, styles.backRightBtnRight]}> - Delete + {translate('Core.ChatsScreen.delete')} ); @@ -104,7 +104,7 @@ const ChatsScreen = () => { navigation.navigate('ChannelScreen')}> - Create Channel + {translate('Core.ChatsScreen.create-channel')} diff --git a/translations/en.json b/translations/en.json index e0144015..41d9bebf 100644 --- a/translations/en.json +++ b/translations/en.json @@ -66,7 +66,8 @@ "update-channel": "Update channel" }, "ChatsScreen": { - "delete": "Delete" + "delete": "Delete", + "create-channel": "Create channel" }, "ChatScreen": { "title": "Select User" From f43fae07b6c5780aeab04edc1886210d762e13a6 Mon Sep 17 00:00:00 2001 From: Doljinsuren Enkhbayar Date: Sun, 21 Apr 2024 16:51:26 +0800 Subject: [PATCH 30/57] added chat history --- src/features/Core/screens/ChannelScreen.js | 4 +- src/features/Core/screens/ChatScreen.js | 92 ++++++++++++++++++---- src/features/Core/screens/ChatsScreen.js | 2 +- 3 files changed, 79 insertions(+), 19 deletions(-) diff --git a/src/features/Core/screens/ChannelScreen.js b/src/features/Core/screens/ChannelScreen.js index b7a61a28..43723794 100644 --- a/src/features/Core/screens/ChannelScreen.js +++ b/src/features/Core/screens/ChannelScreen.js @@ -31,7 +31,7 @@ const ChannelScreen = ({ route }) => { return adapter .put(`chat-channels/${channelId}`, data) .then(res => { - navigation.navigate('ChatScreen', { channelData: res }); + navigation.navigate('ChatScreen', { channel: res }); }) .catch(logError) .finally(() => setIsLoading(false)); @@ -39,7 +39,7 @@ const ChannelScreen = ({ route }) => { return adapter .post('chat-channels', { name }) .then(res => { - navigation.navigate('ChatScreen', { channelData: res }); + navigation.navigate('ChatScreen', { channel: res }); Toast.show({ type: 'success', text1: `Channel created successfully`, diff --git a/src/features/Core/screens/ChatScreen.js b/src/features/Core/screens/ChatScreen.js index 2a1e331b..0302a8b6 100644 --- a/src/features/Core/screens/ChatScreen.js +++ b/src/features/Core/screens/ChatScreen.js @@ -14,7 +14,7 @@ import { createSocketAndListen, translate } from 'utils'; import ChatService from '../../../services/ChatService'; const ChatScreen = ({ route }) => { - const { channelData, chatsData } = route.params; + const { channel } = route.params; const fleetbase = useFleetbase(); const navigation = useNavigation(); const isMounted = useMountedState(); @@ -27,10 +27,58 @@ const ChatScreen = ({ route }) => { const driverUser = driver[0].attributes.user; useEffect(() => { - fetchUsers(chatsData?.id || channelData.id); - listenForChatFromSocket(chatsData?.id || channelData.id); + fetchUsers(channel?.id); + + // const newMessage = { + // _id: new Date().getTime(), + // text: `Added ${participantName} to this channel`, + // createdAt: new Date(), + // user: { + // _id: 1, + // name: 'System', + // }, + // }; + + // setMessages(previousMessages => GiftedChat.append(previousMessages, [newMessage])); + listenForChatFromSocket(channel?.id); + console.log('Messages: ', messages); }, []); + useEffect(() => { + const messages = parseMessages(channel.feed); + setMessages(messages); + }, [route.params]); + + useEffect(() => { + console.log('channel------->>>', JSON.stringify(channel)); + console.log('Messages: ', messages); + }, [messages]); + + const parseMessages = (messages) => { + return messages + .sort((a, b) => new Date(b.created_at) - new Date(a.created_at)) + .map((message, index) => { + return parseMessage(message, index) + }); + }; + + const parseMessage = (message, index) => { + const isSystem = message.type == "log"; + const user = + isSystem + ? { _id: index, name: 'System' } + : { _id: index, name: message.data.sender.name, avatar: message.data.sender.avatar }; + + return { + _id: message.data.id, + text: isSystem ? message.data.resolved_content : message.data.content, + createdAt: message.data.updated_at, + system: isSystem, + user, + }; + } + + useEffect(() => { // Check for errors in the console log console.log('Component rendered'); @@ -41,13 +89,13 @@ const ChatScreen = ({ route }) => { console.log('Added Participants:', addedParticipants); }, [messages, users, addedParticipants]); // Add dependencies as needed - const participantId = chatsData?.participants.find(chatParticipant => { + const participantId = channel?.participants.find(chatParticipant => { return chatParticipant.user === driverUser; }); useEffect(() => { const unsubscribe = navigation.addListener('focus', () => { - fetchUsers(chatsData?.id || channelData.id); + fetchUsers(channel?.id); }); return unsubscribe; @@ -60,19 +108,19 @@ const ChatScreen = ({ route }) => { switch (event) { case 'chat_message.created': - ChatService.insertChatMessageFromSocket(this.channel, data); + ChatService.insertChatMessageFromSocket(data); break; case 'chat_log.created': - ChatService.insertChatLogFromSocket(this.channel, data); + ChatService.insertChatLogFromSocket(data); break; case 'chat_attachment.created': - ChatService.insertChatAttachmentFromSocket(this.channel, data); + ChatService.insertChatAttachmentFromSocket(data); break; case 'chat_receipt.created': - ChatService.insertChatReceiptFromSocket(this.channel, data); + ChatService.insertChatReceiptFromSocket(data); break; default: @@ -82,6 +130,18 @@ const ChatScreen = ({ route }) => { }); }; + const fetchChannel = channelId => { + const newMessage = { + _id: new Date().getTime(), + text: `Removed participant from this channel`, + createdAt: new Date(), + user: { + _id: 1, + name: 'System', + }, + }; + }; + const uploadFile = async url => { // Extract filename from URL @@ -145,6 +205,7 @@ const ChatScreen = ({ route }) => { _id: new Date().getTime(), text: `Added ${participantName} to this channel`, createdAt: new Date(), + system: true, user: { _id: 1, name: 'System', @@ -224,7 +285,7 @@ const ChatScreen = ({ route }) => { await adapter.delete(`chat-channels/remove-participant/${participantId}`); setAddedParticipants(prevParticipants => prevParticipants.filter(participant => participant.id !== participantId)); - fetchUsers(chatsData?.id || channelData.id); + fetchUsers(channel?.id); const newMessage = { _id: new Date().getTime(), text: `Removed participant from this channel`, @@ -243,7 +304,7 @@ const ChatScreen = ({ route }) => { const onSend = async newMessage => { try { const adapter = fleetbase.getAdapter(); - await adapter.post(`chat-channels/${chatsData?.id || channelData.id}/send-message`, { sender: participantId.id, content: newMessage[0].text }); + await adapter.post(`chat-channels/${channel?.id}/send-message`, { sender: participantId.id, content: newMessage[0].text }); setShowUserList(false); setMessages(previousMessages => GiftedChat.append(previousMessages, newMessage)); } catch (error) { @@ -325,9 +386,8 @@ const ChatScreen = ({ route }) => { - {chatsData?.name || channelData.name} - {' '} - navigation.navigate('ChannelScreen', { data: chatsData })}> + {channel?.name} {' '} + navigation.navigate('ChannelScreen', { data: channel })}> @@ -360,7 +420,7 @@ const ChatScreen = ({ route }) => { keyExtractor={item => item.id.toString()} renderItem={({ item }) => ( addParticipant(chatsData.id || channelData?.id, item.id, item.name, item.avatar_url)} + onPress={() => addParticipant(channel.id, item.id, item.name, item.avatar_url)} style={tailwind('flex flex-row items-center py-2 bg-gray-900 rounded-lg mb-2')}> { - + { const renderItem = ({ item }) => ( navigation.navigate('ChatScreen', { chatsData: item })} + onPress={() => navigation.navigate('ChatScreen', { channel: item })} underlayColor={tailwind('bg-gray-900')}> Date: Sun, 21 Apr 2024 19:02:18 +0800 Subject: [PATCH 31/57] fixed issues for add and remove participants --- src/features/Core/screens/ChatScreen.js | 159 ++++++++---------------- src/features/Core/screens/MainScreen.js | 1 + 2 files changed, 56 insertions(+), 104 deletions(-) diff --git a/src/features/Core/screens/ChatScreen.js b/src/features/Core/screens/ChatScreen.js index 0302a8b6..a0117c7d 100644 --- a/src/features/Core/screens/ChatScreen.js +++ b/src/features/Core/screens/ChatScreen.js @@ -14,9 +14,10 @@ import { createSocketAndListen, translate } from 'utils'; import ChatService from '../../../services/ChatService'; const ChatScreen = ({ route }) => { - const { channel } = route.params; + const { channel: channelProps } = route.params; const fleetbase = useFleetbase(); const navigation = useNavigation(); + const [channel, setChannel] = useState(channelProps) const isMounted = useMountedState(); const driver = useDriver(); const [messages, setMessages] = useState([]); @@ -26,68 +27,55 @@ const ChatScreen = ({ route }) => { const [addedParticipants, setAddedParticipants] = useState([]); const driverUser = driver[0].attributes.user; + const adapter = fleetbase.getAdapter(); + useEffect(() => { + setChannel(channelProps) + }, [route.params]); + + useEffect(()=>{ + + if(!channel) return; + console.log("Channel: ", channel) fetchUsers(channel?.id); - // const newMessage = { - // _id: new Date().getTime(), - // text: `Added ${participantName} to this channel`, - // createdAt: new Date(), - // user: { - // _id: 1, - // name: 'System', - // }, - // }; - - // setMessages(previousMessages => GiftedChat.append(previousMessages, [newMessage])); - listenForChatFromSocket(channel?.id); - console.log('Messages: ', messages); - }, []); + const channelID = `chat.${channel.id}`; - useEffect(() => { + console.log('Socket: ', channelID); + + createSocketAndListen(channelID, socketEvent => { + console.log('Socket event: ', socketEvent); + const { event, data } = socketEvent; + + reloadChannel(channel?.id).then((res)=>{ + console.log("Channel :", channel) + }) + }); const messages = parseMessages(channel.feed); setMessages(messages); - }, [route.params]); + }, [channel]) - useEffect(() => { - console.log('channel------->>>', JSON.stringify(channel)); - console.log('Messages: ', messages); - }, [messages]); - - const parseMessages = (messages) => { + const parseMessages = messages => { return messages .sort((a, b) => new Date(b.created_at) - new Date(a.created_at)) .map((message, index) => { - return parseMessage(message, index) + return parseMessage(message, index); }); }; const parseMessage = (message, index) => { - const isSystem = message.type == "log"; - const user = - isSystem - ? { _id: index, name: 'System' } - : { _id: index, name: message.data.sender.name, avatar: message.data.sender.avatar }; - - return { - _id: message.data.id, - text: isSystem ? message.data.resolved_content : message.data.content, - createdAt: message.data.updated_at, - system: isSystem, - user, - }; - } - - - useEffect(() => { - // Check for errors in the console log - console.log('Component rendered'); - - // Inspect state changes - console.log('Messages:', messages); - console.log('Users:', users); - console.log('Added Participants:', addedParticipants); - }, [messages, users, addedParticipants]); // Add dependencies as needed + const isSystem = message.type == 'log'; + const user = isSystem ? { _id: index, name: 'System' } : { _id: index, name: message.data.sender.name, avatar: message.data.sender.avatar }; + + return { + _id: message.data.id, + text: isSystem ? message.data.resolved_content : message.data.content, + createdAt: message.data.updated_at, + system: isSystem, + sent: true, + user, + }; + }; const participantId = channel?.participants.find(chatParticipant => { return chatParticipant.user === driverUser; @@ -100,47 +88,6 @@ const ChatScreen = ({ route }) => { return unsubscribe; }, [isMounted]); - const listenForChatFromSocket = id => { - const channelID = `chat_channel.${id}`; - - createSocketAndListen(channelID, socketEvent => { - const { event, data } = socketEvent; - - switch (event) { - case 'chat_message.created': - ChatService.insertChatMessageFromSocket(data); - break; - - case 'chat_log.created': - ChatService.insertChatLogFromSocket(data); - break; - - case 'chat_attachment.created': - ChatService.insertChatAttachmentFromSocket(data); - break; - - case 'chat_receipt.created': - ChatService.insertChatReceiptFromSocket(data); - break; - - default: - console.log(`Unhandled event type: ${event}`); - break; - } - }); - }; - - const fetchChannel = channelId => { - const newMessage = { - _id: new Date().getTime(), - text: `Removed participant from this channel`, - createdAt: new Date(), - user: { - _id: 1, - name: 'System', - }, - }; - }; const uploadFile = async url => { // Extract filename from URL @@ -173,7 +120,6 @@ const ChatScreen = ({ route }) => { const fetchUsers = async id => { try { - const adapter = fleetbase.getAdapter(); const response = await adapter.get(`chat-channels/${id}/available-participants`); setUsers(response); } catch (error) { @@ -181,8 +127,17 @@ const ChatScreen = ({ route }) => { } }; + const reloadChannel = async id => { + try { + const res = await adapter.get(`chat-channels/${id}`) + setChannel(res) + } catch (error) { + console.error("Error: ", error) + } + } + const addParticipant = async (channelId, participantId, participantName, avatar) => { - const isParticipantAdded = addedParticipants.some(participant => participant.id === participantId); + const isParticipantAdded = channel.participants.some(participant => participant.id === participantId); if (isParticipantAdded) { Alert.alert('Alert', `${participantName} is already a part of this channel.`, [{ text: 'OK' }]); @@ -193,19 +148,14 @@ const ChatScreen = ({ route }) => { const adapter = fleetbase.getAdapter(); await adapter.post(`chat-channels/${channelId}/add-participant`, { user: participantId }); - setAddedParticipants(prevParticipants => [ - ...prevParticipants, - { - id: participantId, - name: participantName, - avatar: avatar, - }, - ]); + await reloadChannel(channel.id) + const newMessage = { _id: new Date().getTime(), text: `Added ${participantName} to this channel`, createdAt: new Date(), system: true, + sent: true, user: { _id: 1, name: 'System', @@ -218,7 +168,7 @@ const ChatScreen = ({ route }) => { console.error('Add participant:', error); } }; - const AddedParticipants = ({ participants, onDelete }) => { + const renderPartificants = ({ participants, onDelete }) => { return ( {participants.map(participant => ( @@ -285,7 +235,7 @@ const ChatScreen = ({ route }) => { await adapter.delete(`chat-channels/remove-participant/${participantId}`); setAddedParticipants(prevParticipants => prevParticipants.filter(participant => participant.id !== participantId)); - fetchUsers(channel?.id); + await reloadChannel(channel.id) const newMessage = { _id: new Date().getTime(), text: `Removed participant from this channel`, @@ -386,7 +336,7 @@ const ChatScreen = ({ route }) => { - {channel?.name} {' '} + {channel?.name}{' '} navigation.navigate('ChannelScreen', { data: channel })}> @@ -448,7 +398,8 @@ const ChatScreen = ({ route }) => { - + {renderPartificants({ + participants: channel?.participants || [], onDelete: removeParticipant})} Date: Sun, 21 Apr 2024 19:03:28 +0800 Subject: [PATCH 32/57] remove duplicate adapter instances --- src/features/Core/screens/ChatScreen.js | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/features/Core/screens/ChatScreen.js b/src/features/Core/screens/ChatScreen.js index a0117c7d..1852ba9d 100644 --- a/src/features/Core/screens/ChatScreen.js +++ b/src/features/Core/screens/ChatScreen.js @@ -145,7 +145,6 @@ const ChatScreen = ({ route }) => { } try { - const adapter = fleetbase.getAdapter(); await adapter.post(`chat-channels/${channelId}/add-participant`, { user: participantId }); await reloadChannel(channel.id) @@ -231,7 +230,6 @@ const ChatScreen = ({ route }) => { const removeParticipant = async participantId => { try { - const adapter = fleetbase.getAdapter(); await adapter.delete(`chat-channels/remove-participant/${participantId}`); setAddedParticipants(prevParticipants => prevParticipants.filter(participant => participant.id !== participantId)); @@ -253,7 +251,6 @@ const ChatScreen = ({ route }) => { const onSend = async newMessage => { try { - const adapter = fleetbase.getAdapter(); await adapter.post(`chat-channels/${channel?.id}/send-message`, { sender: participantId.id, content: newMessage[0].text }); setShowUserList(false); setMessages(previousMessages => GiftedChat.append(previousMessages, newMessage)); From 2598d84204d4132fb8684f5e3d385f15c2db15e5 Mon Sep 17 00:00:00 2001 From: Doljinsuren Enkhbayar Date: Sun, 21 Apr 2024 19:03:59 +0800 Subject: [PATCH 33/57] remove unused state --- src/features/Core/screens/ChatScreen.js | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/features/Core/screens/ChatScreen.js b/src/features/Core/screens/ChatScreen.js index 1852ba9d..6153e943 100644 --- a/src/features/Core/screens/ChatScreen.js +++ b/src/features/Core/screens/ChatScreen.js @@ -24,7 +24,6 @@ const ChatScreen = ({ route }) => { const [users, setUsers] = useState([]); const [isLoading] = useState(false); const [showUserList, setShowUserList] = useState(false); - const [addedParticipants, setAddedParticipants] = useState([]); const driverUser = driver[0].attributes.user; const adapter = fleetbase.getAdapter(); @@ -232,7 +231,6 @@ const ChatScreen = ({ route }) => { try { await adapter.delete(`chat-channels/remove-participant/${participantId}`); - setAddedParticipants(prevParticipants => prevParticipants.filter(participant => participant.id !== participantId)); await reloadChannel(channel.id) const newMessage = { _id: new Date().getTime(), From b84dba5b2dd8e7675dc4b904510ee1f2e993b1a7 Mon Sep 17 00:00:00 2001 From: Doljinsuren Enkhbayar Date: Mon, 22 Apr 2024 10:22:23 +0800 Subject: [PATCH 34/57] checked name length --- src/features/Core/screens/ChatScreen.js | 42 ++++++++++++------------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/src/features/Core/screens/ChatScreen.js b/src/features/Core/screens/ChatScreen.js index 6153e943..28e9c3a4 100644 --- a/src/features/Core/screens/ChatScreen.js +++ b/src/features/Core/screens/ChatScreen.js @@ -11,13 +11,12 @@ import { launchImageLibrary } from 'react-native-image-picker'; import Modal from 'react-native-modal'; import { tailwind } from 'tailwind'; import { createSocketAndListen, translate } from 'utils'; -import ChatService from '../../../services/ChatService'; const ChatScreen = ({ route }) => { const { channel: channelProps } = route.params; const fleetbase = useFleetbase(); const navigation = useNavigation(); - const [channel, setChannel] = useState(channelProps) + const [channel, setChannel] = useState(channelProps); const isMounted = useMountedState(); const driver = useDriver(); const [messages, setMessages] = useState([]); @@ -29,13 +28,12 @@ const ChatScreen = ({ route }) => { const adapter = fleetbase.getAdapter(); useEffect(() => { - setChannel(channelProps) + setChannel(channelProps); }, [route.params]); - - useEffect(()=>{ - if(!channel) return; - console.log("Channel: ", channel) + useEffect(() => { + if (!channel) return; + console.log('Channel: ', channel); fetchUsers(channel?.id); const channelID = `chat.${channel.id}`; @@ -45,14 +43,15 @@ const ChatScreen = ({ route }) => { createSocketAndListen(channelID, socketEvent => { console.log('Socket event: ', socketEvent); const { event, data } = socketEvent; - - reloadChannel(channel?.id).then((res)=>{ - console.log("Channel :", channel) - }) + console.log('Socket event: ', event, data); + reloadChannel(channel?.id).then(res => { + console.log('Channel :', channel); + }); }); + const messages = parseMessages(channel.feed); setMessages(messages); - }, [channel]) + }, [channel]); const parseMessages = messages => { return messages @@ -128,12 +127,12 @@ const ChatScreen = ({ route }) => { const reloadChannel = async id => { try { - const res = await adapter.get(`chat-channels/${id}`) - setChannel(res) + const res = await adapter.get(`chat-channels/${id}`); + setChannel(res); } catch (error) { - console.error("Error: ", error) + console.error('Error: ', error); } - } + }; const addParticipant = async (channelId, participantId, participantName, avatar) => { const isParticipantAdded = channel.participants.some(participant => participant.id === participantId); @@ -146,8 +145,7 @@ const ChatScreen = ({ route }) => { try { await adapter.post(`chat-channels/${channelId}/add-participant`, { user: participantId }); - await reloadChannel(channel.id) - + await reloadChannel(channel.id); const newMessage = { _id: new Date().getTime(), text: `Added ${participantName} to this channel`, @@ -203,7 +201,7 @@ const ChatScreen = ({ route }) => { - {participant.name} + {participant.name.length > 7 ? participant.name.substring(0, 7) + '..' : participant.name} ))} @@ -231,7 +229,7 @@ const ChatScreen = ({ route }) => { try { await adapter.delete(`chat-channels/remove-participant/${participantId}`); - await reloadChannel(channel.id) + await reloadChannel(channel.id); const newMessage = { _id: new Date().getTime(), text: `Removed participant from this channel`, @@ -394,7 +392,9 @@ const ChatScreen = ({ route }) => { {renderPartificants({ - participants: channel?.participants || [], onDelete: removeParticipant})} + participants: channel?.participants || [], + onDelete: removeParticipant, + })} Date: Mon, 22 Apr 2024 17:46:20 +0800 Subject: [PATCH 35/57] removed unused file --- src/features/Core/screens/ChatScreen.js | 17 +++---------- src/features/Core/screens/MainScreen.js | 1 - src/services/ChatService.js | 33 ------------------------- 3 files changed, 3 insertions(+), 48 deletions(-) delete mode 100644 src/services/ChatService.js diff --git a/src/features/Core/screens/ChatScreen.js b/src/features/Core/screens/ChatScreen.js index 28e9c3a4..37ca5131 100644 --- a/src/features/Core/screens/ChatScreen.js +++ b/src/features/Core/screens/ChatScreen.js @@ -36,11 +36,9 @@ const ChatScreen = ({ route }) => { console.log('Channel: ', channel); fetchUsers(channel?.id); - const channelID = `chat.${channel.id}`; + console.log('Socket channel id: ', channel.id); - console.log('Socket: ', channelID); - - createSocketAndListen(channelID, socketEvent => { + createSocketAndListen(channel.id, socketEvent => { console.log('Socket event: ', socketEvent); const { event, data } = socketEvent; console.log('Socket event: ', event, data); @@ -79,14 +77,6 @@ const ChatScreen = ({ route }) => { return chatParticipant.user === driverUser; }); - useEffect(() => { - const unsubscribe = navigation.addListener('focus', () => { - fetchUsers(channel?.id); - }); - - return unsubscribe; - }, [isMounted]); - const uploadFile = async url => { // Extract filename from URL @@ -258,7 +248,7 @@ const ChatScreen = ({ route }) => { const renderSend = props => { return ( - + ); }; @@ -407,7 +397,6 @@ const ChatScreen = ({ route }) => { alwaysShowSend scrollToBottom renderInputToolbar={props => } - renderActions={renderActions} scrollToBottomComponent={scrollToBottomComponent} renderSend={renderSend} /> diff --git a/src/features/Core/screens/MainScreen.js b/src/features/Core/screens/MainScreen.js index b0815a97..a90d7bab 100644 --- a/src/features/Core/screens/MainScreen.js +++ b/src/features/Core/screens/MainScreen.js @@ -17,7 +17,6 @@ import { syncDevice } from 'utils/Auth'; import { getCurrentLocation, trackDriver } from 'utils/Geo'; import IssuesScreen from './IssuesScreen'; import ChatsScreen from './ChatsScreen'; -import { createSocketAndListen } from '../../../utils/Helper'; const { addEventListener, removeEventListener } = EventRegister; const Tab = createBottomTabNavigator(); diff --git a/src/services/ChatService.js b/src/services/ChatService.js deleted file mode 100644 index a4cc7f49..00000000 --- a/src/services/ChatService.js +++ /dev/null @@ -1,33 +0,0 @@ -import { useNavigation } from '@react-navigation/native'; -import { useFleetbase } from 'hooks'; -import { get } from 'utils/Storage'; - -/** - * - * @export - * @class ChatService - */ -export default class ChatService { - /** - * Transitions to an order given the id. - * - * @static - * @param {string} - * @return {Promise} - * @memberof CartService - */ - static insertChatMessageFromSocket(channel, data) { - //todo - } - - static insertChatLogFromSocket(channel, data) { - //todo - } - static insertChatAttachmentFromSocket(channel, data) { - //todo - } - - static insertChatReceiptFromSocket(channel, data) { - //todo - } -} From 6f0527e0d614aab3b935295748fd8c57743f08af Mon Sep 17 00:00:00 2001 From: Doljinsuren Enkhbayar Date: Tue, 23 Apr 2024 17:20:53 +0800 Subject: [PATCH 36/57] removed unused line --- src/features/Core/screens/ChatScreen.js | 40 ++++++++++++------------- 1 file changed, 19 insertions(+), 21 deletions(-) diff --git a/src/features/Core/screens/ChatScreen.js b/src/features/Core/screens/ChatScreen.js index 37ca5131..37ee8bfa 100644 --- a/src/features/Core/screens/ChatScreen.js +++ b/src/features/Core/screens/ChatScreen.js @@ -1,7 +1,7 @@ import { faAngleLeft, faEdit, faPaperPlane, faTrash, faUser } from '@fortawesome/free-solid-svg-icons'; import { FontAwesomeIcon } from '@fortawesome/react-native-fontawesome'; import { useNavigation } from '@react-navigation/native'; -import { useDriver, useFleetbase, useMountedState } from 'hooks'; +import { useDriver, useFleetbase } from 'hooks'; import React, { useEffect, useState } from 'react'; import { ActivityIndicator, Alert, FlatList, ScrollView, Text, TouchableOpacity, View } from 'react-native'; import FastImage from 'react-native-fast-image'; @@ -17,12 +17,11 @@ const ChatScreen = ({ route }) => { const fleetbase = useFleetbase(); const navigation = useNavigation(); const [channel, setChannel] = useState(channelProps); - const isMounted = useMountedState(); - const driver = useDriver(); const [messages, setMessages] = useState([]); const [users, setUsers] = useState([]); const [isLoading] = useState(false); const [showUserList, setShowUserList] = useState(false); + const driver = useDriver(); const driverUser = driver[0].attributes.user; const adapter = fleetbase.getAdapter(); @@ -33,24 +32,29 @@ const ChatScreen = ({ route }) => { useEffect(() => { if (!channel) return; - console.log('Channel: ', channel); fetchUsers(channel?.id); - console.log('Socket channel id: ', channel.id); - - createSocketAndListen(channel.id, socketEvent => { - console.log('Socket event: ', socketEvent); - const { event, data } = socketEvent; - console.log('Socket event: ', event, data); - reloadChannel(channel?.id).then(res => { - console.log('Channel :', channel); - }); - }); - const messages = parseMessages(channel.feed); setMessages(messages); }, [channel]); + // Listen for new channels via Socket Connection + useEffect(() => { + // Assuming createSocketAndListen returns a Promise that resolves with socketEvent + createSocketAndListen(channel.id) + .then(socketEvent => { + console.log('Socket channel id: ', channel.id); + console.log('Socket event: ', socketEvent); + const { event, data } = socketEvent; + console.log('Socket event: ', event, data); + return reloadChannel(channel?.id); // Return the Promise chain + }) + .then(res => { + console.log('Channel :', channel); + }) + .catch(error => console.log('error:::', JSON.stringify(error))); + }, [channel]); // Make sure to include channel in the dependency array if it's used inside the effect + const parseMessages = messages => { return messages .sort((a, b) => new Date(b.created_at) - new Date(a.created_at)) @@ -271,10 +275,6 @@ const ChatScreen = ({ route }) => { ); }; - const scrollToBottomComponent = () => { - return ; - }; - const chooseFile = () => { const options = { title: 'Select File', @@ -395,9 +395,7 @@ const ChatScreen = ({ route }) => { }} renderBubble={renderBubble} alwaysShowSend - scrollToBottom renderInputToolbar={props => } - scrollToBottomComponent={scrollToBottomComponent} renderSend={renderSend} /> From 1ac810c57a15077bbef4609c843e041b169e7082 Mon Sep 17 00:00:00 2001 From: Doljinsuren Enkhbayar Date: Wed, 24 Apr 2024 20:15:23 +0800 Subject: [PATCH 37/57] fix chat id --- src/features/Core/screens/ChatScreen.js | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/src/features/Core/screens/ChatScreen.js b/src/features/Core/screens/ChatScreen.js index 37ee8bfa..0ca8eb07 100644 --- a/src/features/Core/screens/ChatScreen.js +++ b/src/features/Core/screens/ChatScreen.js @@ -38,10 +38,17 @@ const ChatScreen = ({ route }) => { setMessages(messages); }, [channel]); - // Listen for new channels via Socket Connection useEffect(() => { - // Assuming createSocketAndListen returns a Promise that resolves with socketEvent - createSocketAndListen(channel.id) + if (!channel) return; + + async function subscribeChannels() { + const event = await createSocketAndListen(`chat.${channel.id}`, event => { + console.log('Event: ', event); + }); + + console.log('Event: ', event); + } + createSocketAndListen(`chat.${channel.id}`) .then(socketEvent => { console.log('Socket channel id: ', channel.id); console.log('Socket event: ', socketEvent); @@ -49,10 +56,9 @@ const ChatScreen = ({ route }) => { console.log('Socket event: ', event, data); return reloadChannel(channel?.id); // Return the Promise chain }) - .then(res => { - console.log('Channel :', channel); - }) .catch(error => console.log('error:::', JSON.stringify(error))); + + subscribeChannels(); }, [channel]); // Make sure to include channel in the dependency array if it's used inside the effect const parseMessages = messages => { From 1c446b468534f8d8a7a10425dd138d4c4617707f Mon Sep 17 00:00:00 2001 From: Doljinsuren Enkhbayar Date: Thu, 25 Apr 2024 17:23:17 +0800 Subject: [PATCH 38/57] fixed socket data --- babel.config.js | 1 + package.json | 3 +- src/features/Core/screens/ChatScreen.js | 32 ++++------ src/utils/Helper.js | 79 ++++++++++++++++++------- 4 files changed, 72 insertions(+), 43 deletions(-) diff --git a/babel.config.js b/babel.config.js index 688f890e..599d5ad0 100644 --- a/babel.config.js +++ b/babel.config.js @@ -2,6 +2,7 @@ module.exports = { presets: ['module:metro-react-native-babel-preset'], plugins: [ '@babel/plugin-transform-async-generator-functions', + '@babel/plugin-transform-async-to-generator', 'react-native-reanimated/plugin', 'preval', [ diff --git a/package.json b/package.json index a5b389b9..2df83e07 100644 --- a/package.json +++ b/package.json @@ -105,7 +105,7 @@ "react-native-webview": "^13.6.0", "react-native-youtube": "^2.0.2", "react-redux": "^7.2.5", - "socketcluster-client": "^16.0.4", + "socketcluster-client": "^17.1.1", "tailwind-rn": "^3.0.1", "tailwindcss": "^2.2.4", "uuid": "^9.0.0" @@ -113,6 +113,7 @@ "devDependencies": { "@babel/core": "^7.20.0", "@babel/plugin-transform-async-generator-functions": "^7.22.15", + "@babel/plugin-transform-async-to-generator": "^7.24.1", "@babel/preset-env": "^7.20.0", "@babel/runtime": "^7.20.0", "@react-native/eslint-config": "^0.72.2", diff --git a/src/features/Core/screens/ChatScreen.js b/src/features/Core/screens/ChatScreen.js index 0ca8eb07..9b06df8b 100644 --- a/src/features/Core/screens/ChatScreen.js +++ b/src/features/Core/screens/ChatScreen.js @@ -32,7 +32,7 @@ const ChatScreen = ({ route }) => { useEffect(() => { if (!channel) return; - fetchUsers(channel?.id); + // fetchUsers(channel?.id); const messages = parseMessages(channel.feed); setMessages(messages); @@ -41,25 +41,15 @@ const ChatScreen = ({ route }) => { useEffect(() => { if (!channel) return; - async function subscribeChannels() { - const event = await createSocketAndListen(`chat.${channel.id}`, event => { - console.log('Event: ', event); - }); - - console.log('Event: ', event); - } - createSocketAndListen(`chat.${channel.id}`) - .then(socketEvent => { - console.log('Socket channel id: ', channel.id); - console.log('Socket event: ', socketEvent); - const { event, data } = socketEvent; - console.log('Socket event: ', event, data); - return reloadChannel(channel?.id); // Return the Promise chain - }) - .catch(error => console.log('error:::', JSON.stringify(error))); - - subscribeChannels(); - }, [channel]); // Make sure to include channel in the dependency array if it's used inside the effect + console.log(`[Connecting to socket on channel chat.${channel.id}]`); + createSocketAndListen(`chat.${channel.id}`, socketEvent => { + console.log('Socket channel id: ', channel.id); + console.log('Socket event: ', socketEvent); + const { event, data } = socketEvent; + console.log('Socket event: ', event, data); + return reloadChannel(channel?.id); + }); + }, [channel]); const parseMessages = messages => { return messages @@ -173,7 +163,7 @@ const ChatScreen = ({ route }) => { { - // eslint-disable-next-line no-unused-vars - for await (let event of socket.listener('error')) { - console.log('[Socket Error]', event); - } - })(); - - // Listen for socket connection - (async () => { - // eslint-disable-next-line no-unused-vars - for await (let event of socket.listener('connect')) { - console.log('[Socket Connected]', event); - } - })(); + // // Listen for socket connection errors + // (async () => { + // // eslint-disable-next-line no-unused-vars + // for await (let event of socket.listener('error')) { + // console.log('[Socket Error]', event); + // } + // })(); + + // // Listen for socket connection + // (async () => { + // // eslint-disable-next-line no-unused-vars + // for await (let event of socket.listener('connect')) { + // console.log('[Socket Connected]', event); + // } + // })(); // create channel from channel id const channel = socket.subscribe(channelId); @@ -523,14 +523,51 @@ export default class HelperUtil { // subscribe to channel await channel.listener('subscribe').once(); - // listen to incoming data with callback - (async () => { - for await (let output of channel) { - if (typeof callback === 'function') { - callback(output); + const handleAsyncIteration = async asyncIterable => { + console.log('[handleAsyncIteration]'); + const iterator = asyncIterable[Symbol.asyncIterator](); + + const processNext = async () => { + console.log('[processNext]'); + try { + const { value, done } = await iterator.next(); + console.log('[processNext is done?]', done); + console.log('[processNext has value]', JSON.stringify(value)); + if (done) { + // If no more data, exit the function + return; + } + + // Process the value + console.log('[processNext has value]', JSON.stringify(value)); + if (typeof callback === 'function') { + callback(value); + } + + // Recursively process the next item + return processNext(); + } catch (error) { + console.error('Error during async iteration:', error); + // Optionally, handle the error or re-throw it + // throw error; } - } + }; + + // Start processing + return processNext(); + }; + + (async () => { + await handleAsyncIteration(channel); })(); + // // listen to incoming data with callback + // (async () => { + // for await (let output of channel) { + // if (typeof callback === 'function') { + // callback(output); + // } + // } + // })(); } static async listenForOrdersFromSocket(channelId, callback) { From f292267058d66e70f2e350d804add1a34ce48a23 Mon Sep 17 00:00:00 2001 From: Doljinsuren Enkhbayar Date: Fri, 26 Apr 2024 13:32:54 +0800 Subject: [PATCH 39/57] fix android ui --- src/features/Core/screens/ChatScreen.js | 12 +++++++----- src/features/Core/screens/ChatsScreen.js | 8 +++++--- 2 files changed, 12 insertions(+), 8 deletions(-) diff --git a/src/features/Core/screens/ChatScreen.js b/src/features/Core/screens/ChatScreen.js index 9b06df8b..f5a7fb25 100644 --- a/src/features/Core/screens/ChatScreen.js +++ b/src/features/Core/screens/ChatScreen.js @@ -3,7 +3,7 @@ import { FontAwesomeIcon } from '@fortawesome/react-native-fontawesome'; import { useNavigation } from '@react-navigation/native'; import { useDriver, useFleetbase } from 'hooks'; import React, { useEffect, useState } from 'react'; -import { ActivityIndicator, Alert, FlatList, ScrollView, Text, TouchableOpacity, View } from 'react-native'; +import { ActivityIndicator, Alert, FlatList, ScrollView, Text, TouchableOpacity, View, Platform } from 'react-native'; import FastImage from 'react-native-fast-image'; import RNFS from 'react-native-fs'; import { Actions, Bubble, GiftedChat, InputToolbar, Send } from 'react-native-gifted-chat'; @@ -12,6 +12,8 @@ import Modal from 'react-native-modal'; import { tailwind } from 'tailwind'; import { createSocketAndListen, translate } from 'utils'; +const isAndroid = Platform.OS === 'android'; + const ChatScreen = ({ route }) => { const { channel: channelProps } = route.params; const fleetbase = useFleetbase(); @@ -156,9 +158,9 @@ const ChatScreen = ({ route }) => { }; const renderPartificants = ({ participants, onDelete }) => { return ( - + {participants.map(participant => ( - + { {channel?.name}{' '} navigation.navigate('ChannelScreen', { data: channel })}> - + - + diff --git a/src/features/Core/screens/ChatsScreen.js b/src/features/Core/screens/ChatsScreen.js index 3ae2a511..84331091 100644 --- a/src/features/Core/screens/ChatsScreen.js +++ b/src/features/Core/screens/ChatsScreen.js @@ -2,12 +2,14 @@ import { useNavigation } from '@react-navigation/native'; import { format } from 'date-fns'; import { useFleetbase, useMountedState } from 'hooks'; import React, { useEffect, useState } from 'react'; -import { ActivityIndicator, StyleSheet, Text, TouchableOpacity, View, TouchableHighlight } from 'react-native'; +import { ActivityIndicator, StyleSheet, Text, TouchableHighlight, TouchableOpacity, View, Platform } from 'react-native'; import FastImage from 'react-native-fast-image'; import { SwipeListView } from 'react-native-swipe-list-view'; import Toast from 'react-native-toast-message'; import { tailwind } from 'tailwind'; -import { HelperUtil, translate } from 'utils'; +import { translate } from 'utils'; + +const isAndroid = Platform.OS === 'android'; const ChatsScreen = () => { const navigation = useNavigation(); @@ -78,7 +80,7 @@ const ChatsScreen = () => { {item.name} {item.message} - + {formatTime(item.created_at)} From c158394f97be11f1783a75cd102912c6f6d9e3b1 Mon Sep 17 00:00:00 2001 From: Doljinsuren Enkhbayar Date: Mon, 29 Apr 2024 16:43:40 +0800 Subject: [PATCH 40/57] added file upload --- src/features/Core/screens/ChatScreen.js | 92 +++++++++++++------------ 1 file changed, 49 insertions(+), 43 deletions(-) diff --git a/src/features/Core/screens/ChatScreen.js b/src/features/Core/screens/ChatScreen.js index f5a7fb25..a95649fb 100644 --- a/src/features/Core/screens/ChatScreen.js +++ b/src/features/Core/screens/ChatScreen.js @@ -3,9 +3,8 @@ import { FontAwesomeIcon } from '@fortawesome/react-native-fontawesome'; import { useNavigation } from '@react-navigation/native'; import { useDriver, useFleetbase } from 'hooks'; import React, { useEffect, useState } from 'react'; -import { ActivityIndicator, Alert, FlatList, ScrollView, Text, TouchableOpacity, View, Platform } from 'react-native'; +import { ActivityIndicator, Alert, FlatList, Platform, ScrollView, Text, TouchableOpacity, View } from 'react-native'; import FastImage from 'react-native-fast-image'; -import RNFS from 'react-native-fs'; import { Actions, Bubble, GiftedChat, InputToolbar, Send } from 'react-native-gifted-chat'; import { launchImageLibrary } from 'react-native-image-picker'; import Modal from 'react-native-modal'; @@ -17,6 +16,8 @@ const isAndroid = Platform.OS === 'android'; const ChatScreen = ({ route }) => { const { channel: channelProps } = route.params; const fleetbase = useFleetbase(); + const fleetbases = useFleetbase('int/'); + const adapter = fleetbase.getAdapter(); const navigation = useNavigation(); const [channel, setChannel] = useState(channelProps); const [messages, setMessages] = useState([]); @@ -26,16 +27,13 @@ const ChatScreen = ({ route }) => { const driver = useDriver(); const driverUser = driver[0].attributes.user; - const adapter = fleetbase.getAdapter(); - useEffect(() => { setChannel(channelProps); }, [route.params]); useEffect(() => { if (!channel) return; - // fetchUsers(channel?.id); - + fetchUsers(channel?.id); const messages = parseMessages(channel.feed); setMessages(messages); }, [channel]); @@ -80,27 +78,55 @@ const ChatScreen = ({ route }) => { }); const uploadFile = async url => { - // Extract filename from URL - - console.log('res>>>>>>>>', JSON.stringify(url)); - // const fileNameParts = url?.split('/')?.pop()?.split('?'); - - const fileName = fileNameParts.length > 0 ? fileNameParts[0] : ''; + try { + const adapter = fleetbases.getAdapter(); + JSON.parse('fetchImage', JSON.stringify(url.uri)); + const photo = await fetchImage(url.uri); + JSON.parse('fetchImage', JSON.stringify(photo)); + const res = await adapter.post('files/upload', { photo }); + console.log('res:::::::', JSON.stringify(res)); + } catch (error) { + console.error('File upload failed:', JSON.stringify(error)); - console.log('fileName::::', JSON.stringify(url)); - // Create local file path - const localFile = `${RNFS.DocumentDirectoryPath}/${fileName}`; + return; + } + }; - console.log('localFile::::', JSON.stringify(localFile)); - // Set up download options + const chooseFile = () => { const options = { - fromUrl: url, - toFile: localFile, + title: 'Select File', + storageOptions: { + skipBackup: true, + path: 'images', + }, }; + launchImageLibrary(options, response => { + if (response.didCancel) { + console.log('User cancelled image picker'); + } else if (response.error) { + console.log('ImagePicker Error: ', response.error); + } else { + console.log('response::::', JSON.stringify(response.assets[0])); + uploadFile(response.assets[0]); + } + }); + }; + + const fetchImage = async uri => { + const imageResponse = await fetch(uri); + const imageBlob = await imageResponse.blob(); + const base64Data = await blobToBase64(imageBlob); + return base64Data; + }; - RNFS.uploadFiles(options).promise.then(() => { - RNFS.readDir(RNFS.DocumentDirectoryPath); - FileViewer.open(localFile); + const blobToBase64 = blob => { + return new Promise((resolve, reject) => { + const reader = new FileReader(); + reader.onerror = reject; + reader.onload = () => { + resolve(String(reader.result)); + }; + reader.readAsDataURL(blob); }); }; @@ -273,27 +299,6 @@ const ChatScreen = ({ route }) => { ); }; - const chooseFile = () => { - const options = { - title: 'Select File', - storageOptions: { - skipBackup: true, - path: 'images', - }, - }; - - launchImageLibrary(options, response => { - if (response.didCancel) { - console.log('User cancelled image picker'); - } else if (response.error) { - console.log('ImagePicker Error: ', response.error); - } else { - console.log('response::::', JSON.stringify(response.assets[0])); - uploadFile(response.assets[0]); - } - }); - }; - const renderActions = () => ( { alwaysShowSend renderInputToolbar={props => } renderSend={renderSend} + renderActions={renderActions} /> From 742b0a922e59aa795f179943274f9b56b96acbb2 Mon Sep 17 00:00:00 2001 From: Doljinsuren Enkhbayar Date: Mon, 29 Apr 2024 19:13:21 +0800 Subject: [PATCH 41/57] fix uploadFile body. --- src/features/Core/screens/ChatScreen.js | 56 ++++++++++++++----------- 1 file changed, 31 insertions(+), 25 deletions(-) diff --git a/src/features/Core/screens/ChatScreen.js b/src/features/Core/screens/ChatScreen.js index a95649fb..af852331 100644 --- a/src/features/Core/screens/ChatScreen.js +++ b/src/features/Core/screens/ChatScreen.js @@ -16,7 +16,7 @@ const isAndroid = Platform.OS === 'android'; const ChatScreen = ({ route }) => { const { channel: channelProps } = route.params; const fleetbase = useFleetbase(); - const fleetbases = useFleetbase('int/'); + const fleetbases = useFleetbase('int/v1'); const adapter = fleetbase.getAdapter(); const navigation = useNavigation(); const [channel, setChannel] = useState(channelProps); @@ -77,18 +77,36 @@ const ChatScreen = ({ route }) => { return chatParticipant.user === driverUser; }); + const header = adapter.setHeaders({ + headers: { + 'Content-Type': 'multipart/form-data', + }, + }); + const uploadFile = async url => { try { + console.log('url::::::', JSON.stringify(url)); + console.log('header::::', JSON.stringify(header)); const adapter = fleetbases.getAdapter(); - JSON.parse('fetchImage', JSON.stringify(url.uri)); - const photo = await fetchImage(url.uri); - JSON.parse('fetchImage', JSON.stringify(photo)); - const res = await adapter.post('files/upload', { photo }); - console.log('res:::::::', JSON.stringify(res)); - } catch (error) { - console.error('File upload failed:', JSON.stringify(error)); - return; + const formData = new FormData(); + formData.append('file', { + uri: url.uri, + type: url.type, + name: url.name, + }); + + console.log(''); + + const res = await adapter.post('files/upload', { + method: 'post', + body: formData, + headers: header, + }); + + console.log('File upload successful:', res); + } catch (error) { + console.error('File upload failed:', error); } }; @@ -100,23 +118,11 @@ const ChatScreen = ({ route }) => { path: 'images', }, }; - launchImageLibrary(options, response => { - if (response.didCancel) { - console.log('User cancelled image picker'); - } else if (response.error) { - console.log('ImagePicker Error: ', response.error); - } else { - console.log('response::::', JSON.stringify(response.assets[0])); - uploadFile(response.assets[0]); - } + const images = launchImageLibrary(options, response => { + console.log('response.assets[0]::::', JSON.stringify(response.assets[0])); + uploadFile(response.assets[0]); }); - }; - - const fetchImage = async uri => { - const imageResponse = await fetch(uri); - const imageBlob = await imageResponse.blob(); - const base64Data = await blobToBase64(imageBlob); - return base64Data; + console.log('images', JSON.stringify(images)); }; const blobToBase64 = blob => { From 375ad83cf57c8b152c992846e833fe2f8af8ad0b Mon Sep 17 00:00:00 2001 From: Doljinsuren Enkhbayar Date: Mon, 29 Apr 2024 19:43:51 +0800 Subject: [PATCH 42/57] added axiosClient --- src/features/Core/screens/ChatScreen.js | 29 ++++++++++++------------- 1 file changed, 14 insertions(+), 15 deletions(-) diff --git a/src/features/Core/screens/ChatScreen.js b/src/features/Core/screens/ChatScreen.js index af852331..8aaef9d3 100644 --- a/src/features/Core/screens/ChatScreen.js +++ b/src/features/Core/screens/ChatScreen.js @@ -1,6 +1,8 @@ import { faAngleLeft, faEdit, faPaperPlane, faTrash, faUser } from '@fortawesome/free-solid-svg-icons'; import { FontAwesomeIcon } from '@fortawesome/react-native-fontawesome'; import { useNavigation } from '@react-navigation/native'; +import axios from 'axios'; +import config from 'config'; import { useDriver, useFleetbase } from 'hooks'; import React, { useEffect, useState } from 'react'; import { ActivityIndicator, Alert, FlatList, Platform, ScrollView, Text, TouchableOpacity, View } from 'react-native'; @@ -12,12 +14,15 @@ import { tailwind } from 'tailwind'; import { createSocketAndListen, translate } from 'utils'; const isAndroid = Platform.OS === 'android'; +let { FLEETBASE_KEY } = config; const ChatScreen = ({ route }) => { const { channel: channelProps } = route.params; const fleetbase = useFleetbase(); const fleetbases = useFleetbase('int/v1'); const adapter = fleetbase.getAdapter(); + + const adapterInt = fleetbases.getAdapter(); const navigation = useNavigation(); const [channel, setChannel] = useState(channelProps); const [messages, setMessages] = useState([]); @@ -77,17 +82,17 @@ const ChatScreen = ({ route }) => { return chatParticipant.user === driverUser; }); - const header = adapter.setHeaders({ - headers: { - 'Content-Type': 'multipart/form-data', - }, - }); - const uploadFile = async url => { try { + const axiosClient = axios.create({ + baseURL: `${adapterInt.host}/${adapterInt.namespace}`, + headers: { + Authorization: `Bearer ${FLEETBASE_KEY}`, + 'User-Agent': '@fleetbase/sdk;node', + }, + }); console.log('url::::::', JSON.stringify(url)); - console.log('header::::', JSON.stringify(header)); - const adapter = fleetbases.getAdapter(); + console.log('adapter::::', adapter); const formData = new FormData(); formData.append('file', { @@ -96,13 +101,7 @@ const ChatScreen = ({ route }) => { name: url.name, }); - console.log(''); - - const res = await adapter.post('files/upload', { - method: 'post', - body: formData, - headers: header, - }); + const res = await axiosClient.post('files/upload', formData); console.log('File upload successful:', res); } catch (error) { From 28296a8db1c3be7d106a962f482b0cc6af72ef2c Mon Sep 17 00:00:00 2001 From: Doljinsuren Enkhbayar Date: Mon, 29 Apr 2024 23:42:25 +0800 Subject: [PATCH 43/57] fixed auth token --- src/features/Core/screens/ChatScreen.js | 33 ++++++++++++++++--------- 1 file changed, 21 insertions(+), 12 deletions(-) diff --git a/src/features/Core/screens/ChatScreen.js b/src/features/Core/screens/ChatScreen.js index 8aaef9d3..b83fe46e 100644 --- a/src/features/Core/screens/ChatScreen.js +++ b/src/features/Core/screens/ChatScreen.js @@ -12,6 +12,8 @@ import { launchImageLibrary } from 'react-native-image-picker'; import Modal from 'react-native-modal'; import { tailwind } from 'tailwind'; import { createSocketAndListen, translate } from 'utils'; +import { isObject } from 'utils'; +import { get } from 'utils/Storage'; const isAndroid = Platform.OS === 'android'; let { FLEETBASE_KEY } = config; @@ -83,29 +85,36 @@ const ChatScreen = ({ route }) => { }); const uploadFile = async url => { + let _DRIVER = get('driver'); + + const axiosClient = axios.create({ + baseURL: `${adapterInt.host}/${adapterInt.namespace}`, + headers: { + Authorization: isObject(_DRIVER) && typeof _DRIVER.token === 'string' ? `Bearer ${_DRIVER.token}` : `Bearer ${FLEETBASE_KEY}`, + 'User-Agent': '@fleetbase/sdk;node', + 'Content-Type': 'multipart/form-data', + Accept: 'multipart/form-data', + }, + }); + try { - const axiosClient = axios.create({ - baseURL: `${adapterInt.host}/${adapterInt.namespace}`, - headers: { - Authorization: `Bearer ${FLEETBASE_KEY}`, - 'User-Agent': '@fleetbase/sdk;node', - }, - }); console.log('url::::::', JSON.stringify(url)); - console.log('adapter::::', adapter); + + if (!url || !url.uri || !url.type || !url.fileName) { + throw new Error('Invalid file URL'); + } const formData = new FormData(); formData.append('file', { uri: url.uri, type: url.type, - name: url.name, + name: url.fileName, }); const res = await axiosClient.post('files/upload', formData); - - console.log('File upload successful:', res); + console.log('Upload response:', res.data); } catch (error) { - console.error('File upload failed:', error); + console.error('Error uploading file:', error); } }; From 1ac66399f6535b6436d6a1d85414edb87f6d365a Mon Sep 17 00:00:00 2001 From: Doljinsuren Enkhbayar Date: Tue, 30 Apr 2024 10:47:05 +0800 Subject: [PATCH 44/57] removed unused line --- src/features/Core/screens/ChatScreen.js | 32 +++---------------------- 1 file changed, 3 insertions(+), 29 deletions(-) diff --git a/src/features/Core/screens/ChatScreen.js b/src/features/Core/screens/ChatScreen.js index b83fe46e..354abdb8 100644 --- a/src/features/Core/screens/ChatScreen.js +++ b/src/features/Core/screens/ChatScreen.js @@ -23,7 +23,6 @@ const ChatScreen = ({ route }) => { const fleetbase = useFleetbase(); const fleetbases = useFleetbase('int/v1'); const adapter = fleetbase.getAdapter(); - const adapterInt = fleetbases.getAdapter(); const navigation = useNavigation(); const [channel, setChannel] = useState(channelProps); @@ -126,21 +125,8 @@ const ChatScreen = ({ route }) => { path: 'images', }, }; - const images = launchImageLibrary(options, response => { - console.log('response.assets[0]::::', JSON.stringify(response.assets[0])); - uploadFile(response.assets[0]); - }); - console.log('images', JSON.stringify(images)); - }; - - const blobToBase64 = blob => { - return new Promise((resolve, reject) => { - const reader = new FileReader(); - reader.onerror = reject; - reader.onload = () => { - resolve(String(reader.result)); - }; - reader.readAsDataURL(blob); + launchImageLibrary(options, response => { + uploadFile(response?.assets[0]); }); }; @@ -178,25 +164,13 @@ const ChatScreen = ({ route }) => { await adapter.post(`chat-channels/${channelId}/add-participant`, { user: participantId }); await reloadChannel(channel.id); - const newMessage = { - _id: new Date().getTime(), - text: `Added ${participantName} to this channel`, - createdAt: new Date(), - system: true, - sent: true, - user: { - _id: 1, - name: 'System', - }, - }; - setMessages(previousMessages => GiftedChat.append(previousMessages, [newMessage])); setShowUserList(false); } catch (error) { console.error('Add participant:', error); } }; - const renderPartificants = ({ participants, onDelete }) => { + const renderPartificants = ({ participants }) => { return ( {participants.map(participant => ( From 9f452c1766bfc5c5fbc9a441979de118a5d4fcb3 Mon Sep 17 00:00:00 2001 From: Doljinsuren Enkhbayar Date: Tue, 30 Apr 2024 10:58:46 +0800 Subject: [PATCH 45/57] If no image is selected, the condition is checked --- src/features/Core/screens/ChatScreen.js | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/features/Core/screens/ChatScreen.js b/src/features/Core/screens/ChatScreen.js index 354abdb8..b3e8a07e 100644 --- a/src/features/Core/screens/ChatScreen.js +++ b/src/features/Core/screens/ChatScreen.js @@ -126,7 +126,13 @@ const ChatScreen = ({ route }) => { }, }; launchImageLibrary(options, response => { - uploadFile(response?.assets[0]); + if (response.didCancel) { + if (!response) return; + } else if (response.error) { + console.log('ImagePicker Error: ', response.error); + } else { + uploadFile(response?.assets[0]); + } }); }; From 4ecf2c80e1e4c38995f38dd6a015a3804793d666 Mon Sep 17 00:00:00 2001 From: Doljinsuren Enkhbayar Date: Tue, 30 Apr 2024 15:18:00 +0800 Subject: [PATCH 46/57] added attach pic --- src/features/Core/screens/ChatScreen.js | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/src/features/Core/screens/ChatScreen.js b/src/features/Core/screens/ChatScreen.js index b3e8a07e..ea7fd582 100644 --- a/src/features/Core/screens/ChatScreen.js +++ b/src/features/Core/screens/ChatScreen.js @@ -11,8 +11,7 @@ import { Actions, Bubble, GiftedChat, InputToolbar, Send } from 'react-native-gi import { launchImageLibrary } from 'react-native-image-picker'; import Modal from 'react-native-modal'; import { tailwind } from 'tailwind'; -import { createSocketAndListen, translate } from 'utils'; -import { isObject } from 'utils'; +import { createSocketAndListen, isObject, translate } from 'utils'; import { get } from 'utils/Storage'; const isAndroid = Platform.OS === 'android'; @@ -28,6 +27,7 @@ const ChatScreen = ({ route }) => { const [channel, setChannel] = useState(channelProps); const [messages, setMessages] = useState([]); const [users, setUsers] = useState([]); + const [uploadedImageUrl, setUploadedImageUrl] = useState(null); const [isLoading] = useState(false); const [showUserList, setShowUserList] = useState(false); const driver = useDriver(); @@ -67,8 +67,9 @@ const ChatScreen = ({ route }) => { const parseMessage = (message, index) => { const isSystem = message.type == 'log'; - const user = isSystem ? { _id: index, name: 'System' } : { _id: index, name: message.data.sender.name, avatar: message.data.sender.avatar }; + const user = isSystem ? { _id: index, name: 'System' } : { _id: index, name: message?.data?.sender?.name, avatar: message?.data?.sender?.avatar }; + console.log('message.data.content', JSON.stringify(message)); return { _id: message.data.id, text: isSystem ? message.data.resolved_content : message.data.content, @@ -97,8 +98,6 @@ const ChatScreen = ({ route }) => { }); try { - console.log('url::::::', JSON.stringify(url)); - if (!url || !url.uri || !url.type || !url.fileName) { throw new Error('Invalid file URL'); } @@ -110,6 +109,13 @@ const ChatScreen = ({ route }) => { name: url.fileName, }); + const message = { + _id: Math.random().toString(36).substring(2, 15), + createdAt: new Date(), + image: url.uri, + }; + + setMessages(previousMessages => GiftedChat.append(previousMessages, message)); const res = await axiosClient.post('files/upload', formData); console.log('Upload response:', res.data); } catch (error) { @@ -299,9 +305,6 @@ const ChatScreen = ({ route }) => { 'Choose From Library': () => { chooseFile(); }, - Cancel: () => { - console.log('Cancel'); - }, }} optionTintColor="#222B45" /> From 5308d752c10f493a82cdb038ffb6d06466aad651 Mon Sep 17 00:00:00 2001 From: Doljinsuren Enkhbayar Date: Wed, 1 May 2024 14:34:35 +0800 Subject: [PATCH 47/57] fix api --- src/features/Core/screens/ChatScreen.js | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/features/Core/screens/ChatScreen.js b/src/features/Core/screens/ChatScreen.js index ea7fd582..4fe7fb8f 100644 --- a/src/features/Core/screens/ChatScreen.js +++ b/src/features/Core/screens/ChatScreen.js @@ -69,7 +69,6 @@ const ChatScreen = ({ route }) => { const isSystem = message.type == 'log'; const user = isSystem ? { _id: index, name: 'System' } : { _id: index, name: message?.data?.sender?.name, avatar: message?.data?.sender?.avatar }; - console.log('message.data.content', JSON.stringify(message)); return { _id: message.data.id, text: isSystem ? message.data.resolved_content : message.data.content, @@ -115,8 +114,12 @@ const ChatScreen = ({ route }) => { image: url.uri, }; - setMessages(previousMessages => GiftedChat.append(previousMessages, message)); const res = await axiosClient.post('files/upload', formData); + + await adapter.post(`chat-channels/${channel?.id}/send-message`, { sender: participantId.id, content: res.data.file.original_filename }); + + setMessages(previousMessages => GiftedChat.append(previousMessages, message)); + console.log('Upload response:', res.data); } catch (error) { console.error('Error uploading file:', error); From d64efa9490f9724435ff0c33a51247ab7cda319f Mon Sep 17 00:00:00 2001 From: Doljinsuren Enkhbayar Date: Wed, 1 May 2024 18:46:42 +0800 Subject: [PATCH 48/57] added open, download action --- src/features/Core/screens/ChatScreen.js | 55 +++++++++++++++++++++++-- 1 file changed, 51 insertions(+), 4 deletions(-) diff --git a/src/features/Core/screens/ChatScreen.js b/src/features/Core/screens/ChatScreen.js index 4fe7fb8f..d6e76fc3 100644 --- a/src/features/Core/screens/ChatScreen.js +++ b/src/features/Core/screens/ChatScreen.js @@ -1,21 +1,22 @@ -import { faAngleLeft, faEdit, faPaperPlane, faTrash, faUser } from '@fortawesome/free-solid-svg-icons'; +import { faAngleLeft, faEdit, faPaperPlane, faTrash, faUser, faFile } from '@fortawesome/free-solid-svg-icons'; import { FontAwesomeIcon } from '@fortawesome/react-native-fontawesome'; import { useNavigation } from '@react-navigation/native'; import axios from 'axios'; import config from 'config'; import { useDriver, useFleetbase } from 'hooks'; import React, { useEffect, useState } from 'react'; -import { ActivityIndicator, Alert, FlatList, Platform, ScrollView, Text, TouchableOpacity, View } from 'react-native'; +import { ActivityIndicator, Alert, FlatList, Platform, ScrollView, Text, TouchableOpacity, View, KeyboardAvoidingView } from 'react-native'; import FastImage from 'react-native-fast-image'; import { Actions, Bubble, GiftedChat, InputToolbar, Send } from 'react-native-gifted-chat'; import { launchImageLibrary } from 'react-native-image-picker'; import Modal from 'react-native-modal'; +import RNFS from 'react-native-fs'; import { tailwind } from 'tailwind'; import { createSocketAndListen, isObject, translate } from 'utils'; import { get } from 'utils/Storage'; const isAndroid = Platform.OS === 'android'; -let { FLEETBASE_KEY } = config; +let { FLEETBASE_KEY, FLEETBASE_HOST } = config; const ChatScreen = ({ route }) => { const { channel: channelProps } = route.params; @@ -115,7 +116,9 @@ const ChatScreen = ({ route }) => { }; const res = await axiosClient.post('files/upload', formData); - + const imageUrl = res.data.file; + JSON.stringify('imageUrl::::::', JSON.stringify(imageUrl)); + setUploadedImageUrl(imageUrl); await adapter.post(`chat-channels/${channel?.id}/send-message`, { sender: participantId.id, content: res.data.file.original_filename }); setMessages(previousMessages => GiftedChat.append(previousMessages, message)); @@ -284,6 +287,49 @@ const ChatScreen = ({ route }) => { ); }; + const openMedia = async url => { + const fileNameParts = url?.split('/')?.pop()?.split('?'); + console.log('fileNameParts:::', JSON.stringify(fileNameParts)); + const fileName = fileNameParts.length > 0 ? fileNameParts[0] : ''; + + const localFile = `${RNFS.DocumentDirectoryPath}/${fileName}`; + + const options = { + fromUrl: url, + toFile: localFile, + }; + + RNFS.downloadFile(options).promise.then(() => { + RNFS.readDir(RNFS.DocumentDirectoryPath); + FileViewer.open(localFile); + }); + }; + + const checkIsImage = item => { + if (item && item.content_type) { + return item.content_type.startsWith('image/'); + } + }; + + const renderDocumentItem = image => { + return ( + + { + openMedia(`${FLEETBASE_HOST}${image?.url}`); + }}> + {checkIsImage(image?.original_filename) ? ( + + ) : ( + + + + )} + + + ); + }; + const renderBubble = props => { return ( { color: '#fff', }, }} + onPress={() => renderDocumentItem(uploadedImageUrl)} /> ); }; From 45d40f305f909dafeb0f688fc7717dc1a90ab8e1 Mon Sep 17 00:00:00 2001 From: Doljinsuren Enkhbayar Date: Fri, 3 May 2024 12:25:03 +0800 Subject: [PATCH 49/57] removed axioas --- src/features/Core/screens/ChatScreen.js | 37 +++++++------------------ 1 file changed, 10 insertions(+), 27 deletions(-) diff --git a/src/features/Core/screens/ChatScreen.js b/src/features/Core/screens/ChatScreen.js index d6e76fc3..4ccfee15 100644 --- a/src/features/Core/screens/ChatScreen.js +++ b/src/features/Core/screens/ChatScreen.js @@ -1,29 +1,25 @@ -import { faAngleLeft, faEdit, faPaperPlane, faTrash, faUser, faFile } from '@fortawesome/free-solid-svg-icons'; +import { faAngleLeft, faEdit, faFile, faPaperPlane, faTrash, faUser } from '@fortawesome/free-solid-svg-icons'; import { FontAwesomeIcon } from '@fortawesome/react-native-fontawesome'; import { useNavigation } from '@react-navigation/native'; -import axios from 'axios'; import config from 'config'; import { useDriver, useFleetbase } from 'hooks'; import React, { useEffect, useState } from 'react'; -import { ActivityIndicator, Alert, FlatList, Platform, ScrollView, Text, TouchableOpacity, View, KeyboardAvoidingView } from 'react-native'; +import { ActivityIndicator, Alert, FlatList, Platform, ScrollView, Text, TouchableOpacity, View } from 'react-native'; import FastImage from 'react-native-fast-image'; +import RNFS from 'react-native-fs'; import { Actions, Bubble, GiftedChat, InputToolbar, Send } from 'react-native-gifted-chat'; import { launchImageLibrary } from 'react-native-image-picker'; import Modal from 'react-native-modal'; -import RNFS from 'react-native-fs'; import { tailwind } from 'tailwind'; -import { createSocketAndListen, isObject, translate } from 'utils'; -import { get } from 'utils/Storage'; +import { createSocketAndListen, translate } from 'utils'; const isAndroid = Platform.OS === 'android'; -let { FLEETBASE_KEY, FLEETBASE_HOST } = config; +let { FLEETBASE_HOST } = config; const ChatScreen = ({ route }) => { const { channel: channelProps } = route.params; const fleetbase = useFleetbase(); - const fleetbases = useFleetbase('int/v1'); const adapter = fleetbase.getAdapter(); - const adapterInt = fleetbases.getAdapter(); const navigation = useNavigation(); const [channel, setChannel] = useState(channelProps); const [messages, setMessages] = useState([]); @@ -85,18 +81,6 @@ const ChatScreen = ({ route }) => { }); const uploadFile = async url => { - let _DRIVER = get('driver'); - - const axiosClient = axios.create({ - baseURL: `${adapterInt.host}/${adapterInt.namespace}`, - headers: { - Authorization: isObject(_DRIVER) && typeof _DRIVER.token === 'string' ? `Bearer ${_DRIVER.token}` : `Bearer ${FLEETBASE_KEY}`, - 'User-Agent': '@fleetbase/sdk;node', - 'Content-Type': 'multipart/form-data', - Accept: 'multipart/form-data', - }, - }); - try { if (!url || !url.uri || !url.type || !url.fileName) { throw new Error('Invalid file URL'); @@ -115,15 +99,14 @@ const ChatScreen = ({ route }) => { image: url.uri, }; - const res = await axiosClient.post('files/upload', formData); - const imageUrl = res.data.file; - JSON.stringify('imageUrl::::::', JSON.stringify(imageUrl)); + const res = await adapter.post('files', formData); + const imageUrl = res.url; setUploadedImageUrl(imageUrl); - await adapter.post(`chat-channels/${channel?.id}/send-message`, { sender: participantId.id, content: res.data.file.original_filename }); + await adapter.post(`chat-channels/${channel?.id}/send-message`, { sender: participantId.id, content: res.original_filename }); setMessages(previousMessages => GiftedChat.append(previousMessages, message)); - console.log('Upload response:', res.data); + console.log('Upload response:', res); } catch (error) { console.error('Error uploading file:', error); } @@ -439,7 +422,7 @@ const ChatScreen = ({ route }) => { onSend(messages)} user={{ _id: 1, }} From 682ed3138b873a98625859eb4951f91bfaa8b7e7 Mon Sep 17 00:00:00 2001 From: Doljinsuren Enkhbayar Date: Fri, 3 May 2024 16:30:07 +0800 Subject: [PATCH 50/57] fixed image download --- src/features/Core/screens/ChatScreen.js | 55 +++++-------------------- 1 file changed, 11 insertions(+), 44 deletions(-) diff --git a/src/features/Core/screens/ChatScreen.js b/src/features/Core/screens/ChatScreen.js index 4ccfee15..60b34f16 100644 --- a/src/features/Core/screens/ChatScreen.js +++ b/src/features/Core/screens/ChatScreen.js @@ -1,12 +1,10 @@ -import { faAngleLeft, faEdit, faFile, faPaperPlane, faTrash, faUser } from '@fortawesome/free-solid-svg-icons'; +import { faAngleLeft, faEdit, faPaperPlane, faTrash, faUser } from '@fortawesome/free-solid-svg-icons'; import { FontAwesomeIcon } from '@fortawesome/react-native-fontawesome'; import { useNavigation } from '@react-navigation/native'; -import config from 'config'; import { useDriver, useFleetbase } from 'hooks'; import React, { useEffect, useState } from 'react'; -import { ActivityIndicator, Alert, FlatList, Platform, ScrollView, Text, TouchableOpacity, View } from 'react-native'; +import { ActivityIndicator, Alert, FlatList, Image, Platform, ScrollView, Text, TouchableOpacity, View } from 'react-native'; import FastImage from 'react-native-fast-image'; -import RNFS from 'react-native-fs'; import { Actions, Bubble, GiftedChat, InputToolbar, Send } from 'react-native-gifted-chat'; import { launchImageLibrary } from 'react-native-image-picker'; import Modal from 'react-native-modal'; @@ -14,7 +12,6 @@ import { tailwind } from 'tailwind'; import { createSocketAndListen, translate } from 'utils'; const isAndroid = Platform.OS === 'android'; -let { FLEETBASE_HOST } = config; const ChatScreen = ({ route }) => { const { channel: channelProps } = route.params; @@ -80,6 +77,8 @@ const ChatScreen = ({ route }) => { return chatParticipant.user === driverUser; }); + const channelUsers = channel?.participants.map(item => item.id); + const uploadFile = async url => { try { if (!url || !url.uri || !url.type || !url.fileName) { @@ -270,45 +269,11 @@ const ChatScreen = ({ route }) => { ); }; - const openMedia = async url => { - const fileNameParts = url?.split('/')?.pop()?.split('?'); - console.log('fileNameParts:::', JSON.stringify(fileNameParts)); - const fileName = fileNameParts.length > 0 ? fileNameParts[0] : ''; - - const localFile = `${RNFS.DocumentDirectoryPath}/${fileName}`; - - const options = { - fromUrl: url, - toFile: localFile, - }; - - RNFS.downloadFile(options).promise.then(() => { - RNFS.readDir(RNFS.DocumentDirectoryPath); - FileViewer.open(localFile); - }); - }; - - const checkIsImage = item => { - if (item && item.content_type) { - return item.content_type.startsWith('image/'); - } - }; - - const renderDocumentItem = image => { + const renderImage = async image => { + console.log('item', image); return ( - { - openMedia(`${FLEETBASE_HOST}${image?.url}`); - }}> - {checkIsImage(image?.original_filename) ? ( - - ) : ( - - - - )} - + console.warn('Image failed to load')} /> ); }; @@ -327,7 +292,9 @@ const ChatScreen = ({ route }) => { color: '#fff', }, }} - onPress={() => renderDocumentItem(uploadedImageUrl)} + onPress={() => { + renderImage(uploadedImageUrl); + }} /> ); }; @@ -424,7 +391,7 @@ const ChatScreen = ({ route }) => { messages={messages} onSend={messages => onSend(messages)} user={{ - _id: 1, + _id: channelUsers?.id, }} renderBubble={renderBubble} alwaysShowSend From 526932b2c79b70e2c86a0969de4893a76cc46d6d Mon Sep 17 00:00:00 2001 From: Doljinsuren Enkhbayar Date: Fri, 3 May 2024 18:17:47 +0800 Subject: [PATCH 51/57] changed chat position --- src/features/Core/screens/ChatScreen.js | 57 +++++++++++++++++-------- 1 file changed, 39 insertions(+), 18 deletions(-) diff --git a/src/features/Core/screens/ChatScreen.js b/src/features/Core/screens/ChatScreen.js index 60b34f16..8a46ef3f 100644 --- a/src/features/Core/screens/ChatScreen.js +++ b/src/features/Core/screens/ChatScreen.js @@ -279,24 +279,45 @@ const ChatScreen = ({ route }) => { }; const renderBubble = props => { - return ( - { - renderImage(uploadedImageUrl); - }} - /> - ); + if (props?.currentMessage?.user._id === participantId?.id) { + return ( + { + renderImage(uploadedImageUrl); + }} + /> + ); + } else { + return ( + { + renderImage(uploadedImageUrl); + }} + /> + ); + } }; const renderActions = () => ( From 7afb0dd3dcfb0dfe588cd2adc4764704791a34c0 Mon Sep 17 00:00:00 2001 From: Doljinsuren Enkhbayar Date: Mon, 6 May 2024 17:20:19 +0800 Subject: [PATCH 52/57] fixed participent, attachment --- src/features/Core/screens/ChatScreen.js | 88 ++++++++----------------- 1 file changed, 26 insertions(+), 62 deletions(-) diff --git a/src/features/Core/screens/ChatScreen.js b/src/features/Core/screens/ChatScreen.js index 8a46ef3f..6427d691 100644 --- a/src/features/Core/screens/ChatScreen.js +++ b/src/features/Core/screens/ChatScreen.js @@ -118,7 +118,11 @@ const ChatScreen = ({ route }) => { skipBackup: true, path: 'images', }, + quality: 0.5, + maxWidth: 800, + maxHeight: 600, }; + launchImageLibrary(options, response => { if (response.didCancel) { if (!response) return; @@ -152,8 +156,8 @@ const ChatScreen = ({ route }) => { } }; - const addParticipant = async (channelId, participantId, participantName, avatar) => { - const isParticipantAdded = channel.participants.some(participant => participant.id === participantId); + const addParticipant = async (channelId, participantId, participantName) => { + const isParticipantAdded = channel.participants.some(participant => participant.user === participantId); if (isParticipantAdded) { Alert.alert('Alert', `${participantName} is already a part of this channel.`, [{ text: 'OK' }]); @@ -170,6 +174,7 @@ const ChatScreen = ({ route }) => { console.error('Add participant:', error); } }; + const renderPartificants = ({ participants }) => { return ( @@ -234,18 +239,7 @@ const ChatScreen = ({ route }) => { const removeParticipant = async participantId => { try { await adapter.delete(`chat-channels/remove-participant/${participantId}`); - await reloadChannel(channel.id); - const newMessage = { - _id: new Date().getTime(), - text: `Removed participant from this channel`, - createdAt: new Date(), - user: { - _id: 1, - name: 'System', - }, - }; - setMessages(previousMessages => GiftedChat.append(previousMessages, [newMessage])); } catch (error) { console.error('Remove participant:', error); } @@ -279,57 +273,27 @@ const ChatScreen = ({ route }) => { }; const renderBubble = props => { - if (props?.currentMessage?.user._id === participantId?.id) { - return ( - { - renderImage(uploadedImageUrl); - }} - /> - ); - } else { - return ( - { - renderImage(uploadedImageUrl); - }} - /> - ); - } + return ( + { + renderImage(uploadedImageUrl); + }} + /> + ); }; - const renderActions = () => ( - { - chooseFile(); - }, - }} - optionTintColor="#222B45" - /> - ); + const renderActions = () => chooseFile()} optionTintColor="#222B45" />; return ( From d5e011b9d5538dd3fb40ba7f73a268961a28be99 Mon Sep 17 00:00:00 2001 From: Doljinsuren Enkhbayar Date: Tue, 7 May 2024 11:48:52 +0800 Subject: [PATCH 53/57] changed name --- src/features/Core/screens/ChatScreen.js | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/features/Core/screens/ChatScreen.js b/src/features/Core/screens/ChatScreen.js index 6427d691..c5c9b967 100644 --- a/src/features/Core/screens/ChatScreen.js +++ b/src/features/Core/screens/ChatScreen.js @@ -73,10 +73,12 @@ const ChatScreen = ({ route }) => { }; }; - const participantId = channel?.participants.find(chatParticipant => { + const currentParticipant = channel?.participants.find(chatParticipant => { return chatParticipant.user === driverUser; }); + console.log('currentParticipant', currentParticipant); + const channelUsers = channel?.participants.map(item => item.id); const uploadFile = async url => { @@ -101,7 +103,7 @@ const ChatScreen = ({ route }) => { const res = await adapter.post('files', formData); const imageUrl = res.url; setUploadedImageUrl(imageUrl); - await adapter.post(`chat-channels/${channel?.id}/send-message`, { sender: participantId.id, content: res.original_filename }); + await adapter.post(`chat-channels/${channel?.id}/send-message`, { sender: currentParticipant.id, content: res.original_filename }); setMessages(previousMessages => GiftedChat.append(previousMessages, message)); @@ -247,7 +249,7 @@ const ChatScreen = ({ route }) => { const onSend = async newMessage => { try { - await adapter.post(`chat-channels/${channel?.id}/send-message`, { sender: participantId.id, content: newMessage[0].text }); + await adapter.post(`chat-channels/${channel?.id}/send-message`, { sender: currentParticipant.id, content: newMessage[0].text }); setShowUserList(false); setMessages(previousMessages => GiftedChat.append(previousMessages, newMessage)); } catch (error) { @@ -267,7 +269,7 @@ const ChatScreen = ({ route }) => { console.log('item', image); return ( - console.warn('Image failed to load')} /> + console.warn('Image failed to load')} /> ); }; From 96003f097f2a38ae157d483099062dffd44c1e13 Mon Sep 17 00:00:00 2001 From: Doljinsuren Enkhbayar Date: Tue, 7 May 2024 17:40:45 +0800 Subject: [PATCH 54/57] fixed base64, image viewer. --- src/features/Core/screens/ChatScreen.js | 39 ++++++++++--------------- 1 file changed, 15 insertions(+), 24 deletions(-) diff --git a/src/features/Core/screens/ChatScreen.js b/src/features/Core/screens/ChatScreen.js index c5c9b967..9d7cc294 100644 --- a/src/features/Core/screens/ChatScreen.js +++ b/src/features/Core/screens/ChatScreen.js @@ -3,7 +3,7 @@ import { FontAwesomeIcon } from '@fortawesome/react-native-fontawesome'; import { useNavigation } from '@react-navigation/native'; import { useDriver, useFleetbase } from 'hooks'; import React, { useEffect, useState } from 'react'; -import { ActivityIndicator, Alert, FlatList, Image, Platform, ScrollView, Text, TouchableOpacity, View } from 'react-native'; +import { ActivityIndicator, Alert, FlatList, Platform, ScrollView, Text, TouchableOpacity, View } from 'react-native'; import FastImage from 'react-native-fast-image'; import { Actions, Bubble, GiftedChat, InputToolbar, Send } from 'react-native-gifted-chat'; import { launchImageLibrary } from 'react-native-image-picker'; @@ -64,11 +64,12 @@ const ChatScreen = ({ route }) => { const user = isSystem ? { _id: index, name: 'System' } : { _id: index, name: message?.data?.sender?.name, avatar: message?.data?.sender?.avatar }; return { - _id: message.data.id, + _id: message?.data?.id, text: isSystem ? message.data.resolved_content : message.data.content, createdAt: message.data.updated_at, system: isSystem, sent: true, + image: message?.data?.attachments?.length > 0 ? message.data.attachments[0].url : '', user, }; }; @@ -83,31 +84,19 @@ const ChatScreen = ({ route }) => { const uploadFile = async url => { try { - if (!url || !url.uri || !url.type || !url.fileName) { - throw new Error('Invalid file URL'); - } - - const formData = new FormData(); - formData.append('file', { - uri: url.uri, - type: url.type, - name: url.fileName, + const resBase64 = await adapter.post('files/base64', { + data: url.base64, + file_name: url.fileName, + subject_id: channel.id, + subject_type: 'chat_attachment', + type: 'chat_channel', }); - const message = { - _id: Math.random().toString(36).substring(2, 15), - createdAt: new Date(), - image: url.uri, - }; + const messageRes = await adapter.post(`chat-channels/${channel?.id}/send-message`, { sender: currentParticipant.id, content: resBase64.original_filename, file: resBase64.id }); - const res = await adapter.post('files', formData); - const imageUrl = res.url; - setUploadedImageUrl(imageUrl); - await adapter.post(`chat-channels/${channel?.id}/send-message`, { sender: currentParticipant.id, content: res.original_filename }); + setMessages(previousMessages => GiftedChat.append(previousMessages, parseMessage({ data: messageRes }, messageRes.id))); - setMessages(previousMessages => GiftedChat.append(previousMessages, message)); - - console.log('Upload response:', res); + console.log('Upload response:', resBase64); } catch (error) { console.error('Error uploading file:', error); } @@ -123,6 +112,7 @@ const ChatScreen = ({ route }) => { quality: 0.5, maxWidth: 800, maxHeight: 600, + includeBase64: true, }; launchImageLibrary(options, response => { @@ -220,6 +210,7 @@ const ChatScreen = ({ route }) => { ); }; + const confirmRemove = participantId => { Alert.alert( 'Confirmation', @@ -266,7 +257,7 @@ const ChatScreen = ({ route }) => { }; const renderImage = async image => { - console.log('item', image); + console.log('item:::', image); return ( console.warn('Image failed to load')} /> From bf59bd3b5765536a54d4fa69f03f21d2bb34cfc1 Mon Sep 17 00:00:00 2001 From: Doljinsuren Enkhbayar Date: Tue, 7 May 2024 17:48:25 +0800 Subject: [PATCH 55/57] removed log --- src/features/Core/screens/ChatScreen.js | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/features/Core/screens/ChatScreen.js b/src/features/Core/screens/ChatScreen.js index 9d7cc294..f12d332a 100644 --- a/src/features/Core/screens/ChatScreen.js +++ b/src/features/Core/screens/ChatScreen.js @@ -78,8 +78,6 @@ const ChatScreen = ({ route }) => { return chatParticipant.user === driverUser; }); - console.log('currentParticipant', currentParticipant); - const channelUsers = channel?.participants.map(item => item.id); const uploadFile = async url => { @@ -257,7 +255,6 @@ const ChatScreen = ({ route }) => { }; const renderImage = async image => { - console.log('item:::', image); return ( console.warn('Image failed to load')} /> From e97bc509b8a2ec22d498a5652916e625caa9acf6 Mon Sep 17 00:00:00 2001 From: Doljinsuren Enkhbayar Date: Wed, 8 May 2024 17:38:49 +0800 Subject: [PATCH 56/57] fixed image download, viewer --- src/features/Core/screens/ChatScreen.js | 74 +++++++++++++++---------- 1 file changed, 44 insertions(+), 30 deletions(-) diff --git a/src/features/Core/screens/ChatScreen.js b/src/features/Core/screens/ChatScreen.js index f12d332a..1fbcb158 100644 --- a/src/features/Core/screens/ChatScreen.js +++ b/src/features/Core/screens/ChatScreen.js @@ -5,6 +5,8 @@ import { useDriver, useFleetbase } from 'hooks'; import React, { useEffect, useState } from 'react'; import { ActivityIndicator, Alert, FlatList, Platform, ScrollView, Text, TouchableOpacity, View } from 'react-native'; import FastImage from 'react-native-fast-image'; +import FileViewer from 'react-native-file-viewer'; +import RNFS from 'react-native-fs'; import { Actions, Bubble, GiftedChat, InputToolbar, Send } from 'react-native-gifted-chat'; import { launchImageLibrary } from 'react-native-image-picker'; import Modal from 'react-native-modal'; @@ -21,7 +23,6 @@ const ChatScreen = ({ route }) => { const [channel, setChannel] = useState(channelProps); const [messages, setMessages] = useState([]); const [users, setUsers] = useState([]); - const [uploadedImageUrl, setUploadedImageUrl] = useState(null); const [isLoading] = useState(false); const [showUserList, setShowUserList] = useState(false); const driver = useDriver(); @@ -34,6 +35,7 @@ const ChatScreen = ({ route }) => { useEffect(() => { if (!channel) return; fetchUsers(channel?.id); + console.log('channel.feed', JSON.stringify(channel.feed)); const messages = parseMessages(channel.feed); setMessages(messages); }, [channel]); @@ -90,11 +92,13 @@ const ChatScreen = ({ route }) => { type: 'chat_channel', }); - const messageRes = await adapter.post(`chat-channels/${channel?.id}/send-message`, { sender: currentParticipant.id, content: resBase64.original_filename, file: resBase64.id }); + await adapter.post(`chat-channels/${channel?.id}/send-message`, { + sender: currentParticipant?.id, + content: resBase64.original_filename, + file: resBase64.id, + }); setMessages(previousMessages => GiftedChat.append(previousMessages, parseMessage({ data: messageRes }, messageRes.id))); - - console.log('Upload response:', resBase64); } catch (error) { console.error('Error uploading file:', error); } @@ -124,6 +128,23 @@ const ChatScreen = ({ route }) => { }); }; + const openMedia = async url => { + const fileNameParts = url?.split('/')?.pop()?.split('?'); + const fileName = fileNameParts.length > 0 ? fileNameParts[0] : ''; + + const localFile = `${RNFS.DocumentDirectoryPath}/${fileName}`; + + const options = { + fromUrl: url, + toFile: localFile, + }; + + RNFS.downloadFile(options).promise.then(() => { + RNFS.readDir(RNFS.DocumentDirectoryPath); + FileViewer.open(localFile); + }); + }; + const toggleUserList = () => { setShowUserList(!showUserList); }; @@ -254,33 +275,26 @@ const ChatScreen = ({ route }) => { ); }; - const renderImage = async image => { - return ( - - console.warn('Image failed to load')} /> - - ); - }; - const renderBubble = props => { - return ( - { - renderImage(uploadedImageUrl); - }} - /> - ); + if (props.currentMessage.image) { + return ( + openMedia(props.currentMessage.image)}> + + + ); + } else { + return ( + + ); + } }; const renderActions = () => chooseFile()} optionTintColor="#222B45" />; From 06afe4bd78fadcfcb974e1390477c86fe790c69a Mon Sep 17 00:00:00 2001 From: Doljinsuren Enkhbayar Date: Thu, 9 May 2024 14:45:52 +0800 Subject: [PATCH 57/57] fixed chat text moving --- src/features/Core/screens/ChatScreen.js | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/src/features/Core/screens/ChatScreen.js b/src/features/Core/screens/ChatScreen.js index 1fbcb158..f79ac018 100644 --- a/src/features/Core/screens/ChatScreen.js +++ b/src/features/Core/screens/ChatScreen.js @@ -35,7 +35,6 @@ const ChatScreen = ({ route }) => { useEffect(() => { if (!channel) return; fetchUsers(channel?.id); - console.log('channel.feed', JSON.stringify(channel.feed)); const messages = parseMessages(channel.feed); setMessages(messages); }, [channel]); @@ -63,6 +62,7 @@ const ChatScreen = ({ route }) => { const parseMessage = (message, index) => { const isSystem = message.type == 'log'; + const user = isSystem ? { _id: index, name: 'System' } : { _id: index, name: message?.data?.sender?.name, avatar: message?.data?.sender?.avatar }; return { @@ -92,7 +92,7 @@ const ChatScreen = ({ route }) => { type: 'chat_channel', }); - await adapter.post(`chat-channels/${channel?.id}/send-message`, { + const messageRes = await adapter.post(`chat-channels/${channel?.id}/send-message`, { sender: currentParticipant?.id, content: resBase64.original_filename, file: resBase64.id, @@ -261,7 +261,8 @@ const ChatScreen = ({ route }) => { try { await adapter.post(`chat-channels/${channel?.id}/send-message`, { sender: currentParticipant.id, content: newMessage[0].text }); setShowUserList(false); - setMessages(previousMessages => GiftedChat.append(previousMessages, newMessage)); + setMessages(previousMessages => GiftedChat.append(previousMessages, { + ...newMessage, sent: false})); } catch (error) { console.error('Send error:', error); } @@ -286,9 +287,9 @@ const ChatScreen = ({ route }) => { return (