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/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/package.json b/package.json
index 945bc074..2df83e07 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",
@@ -86,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",
@@ -104,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"
@@ -112,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/MainStack.js b/src/features/Core/MainStack.js
index ccc53376..a6882ae5 100644
--- a/src/features/Core/MainStack.js
+++ b/src/features/Core/MainStack.js
@@ -9,6 +9,9 @@ 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 ChatsScreen from './screens/ChatsScreen';
+import ChannelScreen from './screens/ChannelScreen';
const RootStack = createStackNavigator();
@@ -30,6 +33,9 @@ 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..43723794
--- /dev/null
+++ b/src/features/Core/screens/ChannelScreen.js
@@ -0,0 +1,95 @@
+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, { 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';
+
+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) {
+ const { data } = route.params;
+ setChannelId(data?.id);
+ setName(data?.name);
+ }
+ }, [route]);
+
+ const saveChannel = () => {
+ setIsLoading(true);
+ const adapter = fleetbase.getAdapter();
+ const data = { name };
+ if (channelId) {
+ return adapter
+ .put(`chat-channels/${channelId}`, data)
+ .then(res => {
+ navigation.navigate('ChatScreen', { channel: res });
+ })
+ .catch(logError)
+ .finally(() => setIsLoading(false));
+ } else {
+ return adapter
+ .post('chat-channels', { name })
+ .then(res => {
+ navigation.navigate('ChatScreen', { channel: res });
+ Toast.show({
+ type: 'success',
+ text1: `Channel created successfully`,
+ });
+ })
+ .catch(logError)
+ .finally(() => setIsLoading(false));
+ }
+ };
+
+ return (
+
+
+
+ {channelId ? translate('Core.ChannelScreen.update-channel') : translate('Core.ChannelScreen.title')}
+ navigation.pop(2)} style={tailwind('mr-4')}>
+
+
+
+
+
+
+
+
+
+ {channelId ? translate('Core.ChannelScreen.update') : translate('Core.ChannelScreen.name')}
+
+
+
+
+
+
+ {isLoading && }
+
+ {channelId ? translate('Core.ChannelScreen.update-channel') : translate('Core.ChannelScreen.title')}
+
+
+
+
+
+
+
+ );
+};
+
+export default ChannelScreen;
diff --git a/src/features/Core/screens/ChatScreen.js b/src/features/Core/screens/ChatScreen.js
new file mode 100644
index 00000000..f79ac018
--- /dev/null
+++ b/src/features/Core/screens/ChatScreen.js
@@ -0,0 +1,397 @@
+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 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';
+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();
+ const adapter = fleetbase.getAdapter();
+ const navigation = useNavigation();
+ const [channel, setChannel] = useState(channelProps);
+ 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;
+
+ useEffect(() => {
+ setChannel(channelProps);
+ }, [route.params]);
+
+ useEffect(() => {
+ if (!channel) return;
+ fetchUsers(channel?.id);
+ const messages = parseMessages(channel.feed);
+ setMessages(messages);
+ }, [channel]);
+
+ useEffect(() => {
+ if (!channel) return;
+
+ 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
+ .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,
+ sent: true,
+ image: message?.data?.attachments?.length > 0 ? message.data.attachments[0].url : '',
+ user,
+ };
+ };
+
+ const currentParticipant = channel?.participants.find(chatParticipant => {
+ return chatParticipant.user === driverUser;
+ });
+
+ const channelUsers = channel?.participants.map(item => item.id);
+
+ const uploadFile = async url => {
+ try {
+ 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 messageRes = 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)));
+ } catch (error) {
+ console.error('Error uploading file:', error);
+ }
+ };
+
+ const chooseFile = () => {
+ const options = {
+ title: 'Select File',
+ storageOptions: {
+ skipBackup: true,
+ path: 'images',
+ },
+ quality: 0.5,
+ maxWidth: 800,
+ maxHeight: 600,
+ includeBase64: true,
+ };
+
+ launchImageLibrary(options, response => {
+ if (response.didCancel) {
+ if (!response) return;
+ } else if (response.error) {
+ console.log('ImagePicker Error: ', response.error);
+ } else {
+ uploadFile(response?.assets[0]);
+ }
+ });
+ };
+
+ 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);
+ };
+
+ const fetchUsers = async id => {
+ try {
+ const response = await adapter.get(`chat-channels/${id}/available-participants`);
+ setUsers(response);
+ } catch (error) {
+ console.error('Error fetching users:', error);
+ }
+ };
+
+ 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) => {
+ const isParticipantAdded = channel.participants.some(participant => participant.user === participantId);
+
+ if (isParticipantAdded) {
+ Alert.alert('Alert', `${participantName} is already a part of this channel.`, [{ text: 'OK' }]);
+ return;
+ }
+
+ try {
+ await adapter.post(`chat-channels/${channelId}/add-participant`, { user: participantId });
+
+ await reloadChannel(channel.id);
+
+ setShowUserList(false);
+ } catch (error) {
+ console.error('Add participant:', error);
+ }
+ };
+
+ const renderPartificants = ({ participants }) => {
+ return (
+
+ {participants.map(participant => (
+
+
+
+
+
+
+ confirmRemove(participant.id)}>
+
+
+
+ {participant.name.length > 7 ? participant.name.substring(0, 7) + '..' : participant.name}
+
+ ))}
+
+ );
+ };
+
+ 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 {
+ await adapter.delete(`chat-channels/remove-participant/${participantId}`);
+ await reloadChannel(channel.id);
+ } catch (error) {
+ console.error('Remove participant:', error);
+ }
+ };
+
+ const onSend = async newMessage => {
+ 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, sent: false}));
+ } catch (error) {
+ console.error('Send error:', error);
+ }
+ };
+
+ const renderSend = props => {
+ return (
+
+
+
+ );
+ };
+
+ const renderBubble = props => {
+ if (props.currentMessage.image) {
+ return (
+ openMedia(props.currentMessage.image)}>
+
+
+ );
+ } else {
+ return (
+
+ );
+ }
+ };
+
+ const renderActions = () => chooseFile()} optionTintColor="#222B45" />;
+
+ return (
+
+
+
+ navigation.pop(2)}>
+
+
+
+
+ {channel?.name}{' '}
+ navigation.navigate('ChannelScreen', { data: channel })}>
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {translate('Core.ChatScreen.title')}:
+
+ {isLoading ? (
+
+
+
+ ) : (
+ item.id.toString()}
+ renderItem={({ item }) => (
+ 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')}>
+
+
+
+
+ {item.name}
+
+ )}
+ />
+ )}
+
+
+
+
+ {renderPartificants({
+ participants: channel?.participants || [],
+ onDelete: removeParticipant,
+ })}
+
+
+ onSend(messages)}
+ user={{
+ _id: channelUsers?.id,
+ }}
+ renderBubble={renderBubble}
+ alwaysShowSend
+ renderInputToolbar={props => }
+ renderSend={renderSend}
+ renderActions={renderActions}
+ />
+
+
+ );
+};
+
+export default ChatScreen;
diff --git a/src/features/Core/screens/ChatsScreen.js b/src/features/Core/screens/ChatsScreen.js
new file mode 100644
index 00000000..84331091
--- /dev/null
+++ b/src/features/Core/screens/ChatsScreen.js
@@ -0,0 +1,146 @@
+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, 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 { translate } from 'utils';
+
+const isAndroid = Platform.OS === 'android';
+
+const ChatsScreen = () => {
+ const navigation = useNavigation();
+ const isMounted = useMountedState();
+ const fleetbase = useFleetbase();
+ const [channels, setChannels] = useState([]);
+ const [isLoading, setIsLoading] = useState(false);
+
+ useEffect(() => {
+ const unsubscribe = navigation.addListener('focus', () => {
+ fetchChannels();
+ });
+
+ return unsubscribe;
+ }, [isMounted]);
+
+ const fetchChannels = async () => {
+ setIsLoading(true);
+ try {
+ const adapter = fleetbase.getAdapter();
+ const response = await adapter.get('chat-channels');
+ setChannels(response);
+ setIsLoading(false);
+ return response;
+ } catch (error) {
+ console.error('Error fetching channels:', error);
+ setIsLoading(false);
+ return [];
+ }
+ };
+
+ useEffect(() => {
+ fetchChannels();
+ }, []);
+
+ const formatTime = dateTime => {
+ const date = new Date(dateTime);
+ const formattedTime = format(date, 'HH:mm');
+ return formattedTime;
+ };
+
+ const handleDelete = async itemId => {
+ try {
+ const adapter = fleetbase.getAdapter();
+ 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);
+ }
+ };
+
+ const renderItem = ({ item }) => (
+ navigation.navigate('ChatScreen', { channel: item })}
+ underlayColor={tailwind('bg-gray-900')}>
+
+
+
+ {item.name}
+ {item.message}
+
+
+ {formatTime(item.created_at)}
+
+
+
+ );
+
+ const renderHiddenItem = ({ item }) => (
+
+ handleDelete(item.id)} style={[styles.backRightBtn, styles.backRightBtnRight]}>
+ {translate('Core.ChatsScreen.delete')}
+
+
+ );
+
+ return (
+
+ {isLoading && (
+
+
+
+ )}
+
+
+ navigation.navigate('ChannelScreen')}>
+
+ {translate('Core.ChatsScreen.create-channel')}
+
+
+
+
+
+
+ );
+};
+
+export default ChatsScreen;
+
+const styles = StyleSheet.create({
+ backRightBtn: {
+ alignItems: 'center',
+ bottom: 0,
+ justifyContent: 'center',
+ position: 'absolute',
+ top: 0,
+ width: 75,
+ },
+ backRightBtnRight: {
+ backgroundColor: '#FF3A3A',
+ right: 4,
+ top: 10,
+ bottom: 2,
+ marginRight: 12,
+ marginLeft: 6,
+ borderRadius: 12,
+ },
+ loaderContainer: {
+ position: 'absolute',
+ top: '50%',
+ left: '60%',
+ transform: [{ translateX: -50 }, { translateY: -50 }],
+ zIndex: 10,
+ },
+});
diff --git a/src/features/Core/screens/MainScreen.js b/src/features/Core/screens/MainScreen.js
index 105906ea..a90d7bab 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 ChatsScreen from './ChatsScreen';
const { addEventListener, removeEventListener } = EventRegister;
const Tab = createBottomTabNavigator();
@@ -141,6 +142,9 @@ const MainScreen = ({ navigation, route }) => {
case 'Issue':
icon = faFileAlt;
break;
+ case 'Chat':
+ 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/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;
diff --git a/src/utils/Helper.js b/src/utils/Helper.js
index 3114ad94..0e98d02e 100644
--- a/src/utils/Helper.js
+++ b/src/utils/Helper.js
@@ -501,21 +501,21 @@ export default class HelperUtil {
// Create socket connection
const socket = socketClusterClient.create(socketConnectionConfig);
- // 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);
- }
- })();
+ // // 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) {
diff --git a/translations/en.json b/translations/en.json
index a046b288..41d9bebf 100644
--- a/translations/en.json
+++ b/translations/en.json
@@ -58,6 +58,19 @@
"report": "Report",
"driverName": "Driver Name",
"vehicleName": "Vehicle Name"
+ },
+ "ChannelScreen": {
+ "name": "Name",
+ "title": "Create channel",
+ "update": "Update",
+ "update-channel": "Update channel"
+ },
+ "ChatsScreen": {
+ "delete": "Delete",
+ "create-channel": "Create channel"
+ },
+ "ChatScreen": {
+ "title": "Select User"
}
},
"Exceptions": {