react-native-altibbi 0.1.3 → 0.1.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,87 @@
1
+ import React, { useRef, useState } from 'react';
2
+ import { TBIPublisher, TBISession, TBISubscriber, TBISubscriberView, } from 'react-native-altibbi';
3
+ import { Dimensions, View, Text } from 'react-native';
4
+ const Video = (props) => {
5
+ const data = props.route.params.event;
6
+ const voip = props.route.params.voip;
7
+ const [audio, setAudio] = useState(true);
8
+ const [video, setVideo] = useState(!voip);
9
+ const [camera, setCamera] = useState('front');
10
+ const sessionRef = useRef(null);
11
+ const toggleVideo = () => setVideo((prev) => !prev);
12
+ const toggleAudio = () => setAudio((prev) => !prev);
13
+ const switchCamera = () => setCamera((prev) => {
14
+ if (prev === 'front') {
15
+ return 'back';
16
+ }
17
+ else {
18
+ return 'front';
19
+ }
20
+ });
21
+ const renderSubscribers = (subscribers) => {
22
+ if (subscribers && subscribers.length > 0) {
23
+ const { width: screenWidth, height: screenHeight } = Dimensions.get('window');
24
+ return subscribers.map((streamId) => (React.createElement(TBISubscriberView, { streamId: streamId, style: { width: screenWidth, height: screenHeight } })));
25
+ }
26
+ };
27
+ return (React.createElement(TBISession, { options: {
28
+ androidZOrder: 'onTop',
29
+ androidOnTop: 'publisher',
30
+ }, ref: (ref) => (sessionRef.current = ref), apiKey: data.api_key, sessionId: data.call_id, token: data.token, eventHandlers: {
31
+ streamDestroyed: (event) => { },
32
+ error: (event) => { },
33
+ otrnError: (event) => { },
34
+ } },
35
+ React.createElement(TBISubscriber, { eventHandlers: {
36
+ error: (event) => { },
37
+ otrnError: (event) => { },
38
+ } }, renderSubscribers),
39
+ React.createElement(TBIPublisher, { style: {
40
+ position: 'absolute',
41
+ width: 100,
42
+ height: 100,
43
+ top: 0,
44
+ margin: 5,
45
+ right: 0,
46
+ }, properties: {
47
+ cameraPosition: camera,
48
+ publishVideo: video,
49
+ publishAudio: audio,
50
+ enableDtx: true,
51
+ }, eventHandlers: {
52
+ streamDestroyed: (event) => { },
53
+ error: (event) => { },
54
+ otrnError: (event) => { },
55
+ } }),
56
+ React.createElement(View, { style: {
57
+ flexDirection: 'row',
58
+ padding: 8,
59
+ position: 'absolute',
60
+ backgroundColor: 'white',
61
+ bottom: 0,
62
+ left: 0,
63
+ right: 0,
64
+ justifyContent: 'center',
65
+ } },
66
+ React.createElement(Text, { style: {
67
+ fontSize: 20,
68
+ marginRight: 10,
69
+ color: video ? 'blue' : 'red',
70
+ }, onPress: () => toggleVideo() },
71
+ "video (",
72
+ video ? 'T' : 'F',
73
+ ")"),
74
+ React.createElement(Text, { style: {
75
+ fontSize: 20,
76
+ marginRight: 10,
77
+ color: audio ? 'blue' : 'red',
78
+ }, onPress: () => toggleAudio() },
79
+ "audio (",
80
+ audio ? 'T' : 'F',
81
+ ")"),
82
+ React.createElement(Text, { style: { fontSize: 20, marginRight: 10 }, onPress: () => switchCamera() },
83
+ "camera (",
84
+ camera,
85
+ ")"))));
86
+ };
87
+ export default Video;
@@ -0,0 +1,108 @@
1
+ import React, { useEffect } from 'react';
2
+ import { View, Text, ActivityIndicator } from 'react-native';
3
+ import { TBIConstants, TBISocketEvent, TBISocketMember, } from 'react-native-altibbi';
4
+ import { cancelConsultation } from 'react-native-altibbi';
5
+ import { getLastConsultation } from 'react-native-altibbi';
6
+ import { TBISocket } from 'react-native-altibbi';
7
+ const WaitingRoom = (props) => {
8
+ const { channel, socketParams, consultationId } = props?.route?.params;
9
+ const instance = TBISocket.getInstance();
10
+ const disconnect = () => instance?.disconnect();
11
+ const log = (line) => {
12
+ console.log(line);
13
+ };
14
+ const onConnectionStateChange = (currentState, previousState) => {
15
+ log(`onConnectionStateChange. previousState=${previousState} newState=${currentState}`);
16
+ };
17
+ const onError = (message, code, error) => {
18
+ log(`onError: ${message} code: ${code} exception: ${error}`);
19
+ };
20
+ const onEvent = (eventData) => {
21
+ if (eventData && eventData.eventName === 'call-status') {
22
+ let event = JSON.parse(eventData.data);
23
+ if (event.status === 'in_progress') {
24
+ getCurrentConsultationInfo();
25
+ }
26
+ }
27
+ };
28
+ const getCurrentConsultationInfo = () => {
29
+ getLastConsultation().then((res) => {
30
+ console.log(res);
31
+ redirectToNext(res.data[0]);
32
+ });
33
+ };
34
+ const onSubscriptionSucceeded = (channelName, data) => {
35
+ log(`onSubscriptionSucceeded: ${channelName} data: ${JSON.stringify(data)}`);
36
+ };
37
+ const onSubscriptionCount = (channelName, subscriptionCount) => {
38
+ log(`onSubscriptionCount: ${subscriptionCount}, channelName: ${channelName}`);
39
+ };
40
+ const onSubscriptionError = (channelName, message, e) => {
41
+ log(`onSubscriptionError: ${message}, channelName: ${channelName} e: ${e}`);
42
+ };
43
+ const onDecryptionFailure = (eventName, reason) => {
44
+ log(`onDecryptionFailure: ${eventName} reason: ${reason}`);
45
+ };
46
+ const onMemberAdded = (channelName, member) => {
47
+ log(`onMemberAdded: ${channelName} user: ${member}`);
48
+ };
49
+ const onMemberRemoved = (channelName, member) => {
50
+ log(`onMemberRemoved: ${channelName} user: ${member}`);
51
+ };
52
+ const connect = async () => {
53
+ try {
54
+ await instance.init({
55
+ ...socketParams,
56
+ ...{
57
+ onConnectionStateChange,
58
+ onError,
59
+ onEvent,
60
+ onSubscriptionSucceeded,
61
+ onSubscriptionError,
62
+ onDecryptionFailure,
63
+ onMemberAdded,
64
+ onMemberRemoved,
65
+ onSubscriptionCount,
66
+ },
67
+ });
68
+ await instance.subscribe({ channelName: channel });
69
+ await instance.connect();
70
+ }
71
+ catch (e) {
72
+ throw new Error(`${e}`);
73
+ }
74
+ };
75
+ const redirectToNext = (parmas) => {
76
+ if (parmas.status === 'in_progress') {
77
+ if (parmas.chatConfig) {
78
+ props.navigation.navigate('ChatRoom', {
79
+ event: parmas.chatConfig,
80
+ });
81
+ }
82
+ else if (parmas.videoConfig) {
83
+ props.navigation.navigate('Video', {
84
+ event: parmas.videoConfig,
85
+ });
86
+ }
87
+ else if (parmas.voipConfig) {
88
+ props.navigation.navigate('Video', {
89
+ event: parmas.voipConfig,
90
+ voip: true,
91
+ });
92
+ }
93
+ }
94
+ };
95
+ useEffect(() => {
96
+ redirectToNext(props?.route?.params);
97
+ connect().then();
98
+ }, []);
99
+ return (React.createElement(View, null,
100
+ React.createElement(Text, { style: { marginVertical: 20, fontSize: 20 } }, "Waiting For Doctor"),
101
+ React.createElement(ActivityIndicator, { size: 'large' }),
102
+ React.createElement(Text, { onPress: () => {
103
+ cancelConsultation(consultationId).then(() => {
104
+ props.navigation.goBack();
105
+ });
106
+ }, style: { color: 'blue', fontSize: 20 } }, "Cancel current consultation")));
107
+ };
108
+ export default WaitingRoom;
@@ -0,0 +1,247 @@
1
+ import { TBIConstants } from './service';
2
+ export const Methods = {
3
+ get: 'GET',
4
+ post: 'POST',
5
+ delete: 'DELETE',
6
+ put: 'PUT',
7
+ };
8
+ const fetchData = (url, request, timeout) => Promise.race([
9
+ fetch(url, request).catch((error) => {
10
+ throw Error(`Fetch Error ${error}`);
11
+ }),
12
+ new Promise((_, reject) => setTimeout(() => reject(new Error('request timeout')), timeout)),
13
+ ]).catch((e) => {
14
+ throw Error(`Fetch Error : ${e}`);
15
+ });
16
+ export const request = async ({ method, data, endPoint, path, type, fileName, download, }) => {
17
+ if (!TBIConstants.baseURL) {
18
+ return {
19
+ message: 'Add your baseURL to Init',
20
+ };
21
+ }
22
+ const headers = {
23
+ 'Content-Type': 'application/json',
24
+ 'Authorization': `Bearer ${TBIConstants.token}`,
25
+ 'accept-language': TBIConstants.language,
26
+ };
27
+ let url = `${TBIConstants.baseURL}/v1/${endPoint}`;
28
+ let body;
29
+ if (method === Methods.get) {
30
+ url = url + '?' + new URLSearchParams(data).toString();
31
+ }
32
+ else if (path) {
33
+ const formData = new FormData();
34
+ formData.append('file', {
35
+ uri: path,
36
+ type: type,
37
+ name: fileName,
38
+ });
39
+ body = formData;
40
+ headers['Content-Type'] = 'multipart/form-data';
41
+ }
42
+ else {
43
+ if (data && data.expand) {
44
+ url = url + '?' + new URLSearchParams({ expand: data.expand }).toString();
45
+ }
46
+ body = JSON.stringify(data);
47
+ }
48
+ const requestConfig = {
49
+ method,
50
+ headers,
51
+ body,
52
+ };
53
+ const timeOut = path ? 180000 : 30000;
54
+ const apiResponse = await fetchData(url, requestConfig, timeOut);
55
+ if (download) {
56
+ return apiResponse;
57
+ }
58
+ const response = await apiResponse.text();
59
+ const responseData = response ? JSON.parse(response) : '';
60
+ return {
61
+ status: apiResponse.status,
62
+ data: responseData,
63
+ };
64
+ };
65
+ export const getUser = async (user_id) => {
66
+ const response = await request({
67
+ method: Methods.get,
68
+ data: {},
69
+ endPoint: `users/${user_id}`,
70
+ });
71
+ if (response.status === 200) {
72
+ return response;
73
+ }
74
+ throw Error(JSON.stringify(response));
75
+ };
76
+ export const getUsers = async (page = 1, perPage = 20) => {
77
+ const response = await request({
78
+ method: Methods.get,
79
+ data: { page, 'per-page': perPage },
80
+ endPoint: `users`,
81
+ });
82
+ if (response.status === 200) {
83
+ return response;
84
+ }
85
+ throw Error(JSON.stringify(response));
86
+ };
87
+ export const createUser = async (user) => {
88
+ const response = await request({
89
+ method: Methods.post,
90
+ data: user,
91
+ endPoint: `users`,
92
+ });
93
+ if (response.status === 201) {
94
+ return response;
95
+ }
96
+ throw Error(JSON.stringify(response));
97
+ };
98
+ export const updateUser = async (user, user_id) => {
99
+ const response = await request({
100
+ method: Methods.put,
101
+ data: user,
102
+ endPoint: `users/${user_id}`,
103
+ });
104
+ if (response.status === 201) {
105
+ return response;
106
+ }
107
+ throw Error(JSON.stringify(response));
108
+ };
109
+ export const deleteUser = async (user_id) => {
110
+ const response = await request({
111
+ method: Methods.delete,
112
+ data: {},
113
+ endPoint: `users/${user_id}`,
114
+ });
115
+ if (response.status === 204) {
116
+ return response;
117
+ }
118
+ throw Error(JSON.stringify(response));
119
+ };
120
+ export const createConsultation = async ({ question, medium, user_id, mediaIds, followUpId, }) => {
121
+ if (!question || !medium || !user_id) {
122
+ throw Error('missing field');
123
+ }
124
+ const data = {
125
+ question,
126
+ medium,
127
+ user_id,
128
+ media_ids: mediaIds,
129
+ expand: 'pusherAppKey,parentConsultation,consultations,user,media,pusherChannel,' +
130
+ 'chatConfig,chatHistory,voipConfig,videoConfig,recommendation',
131
+ followUpId,
132
+ };
133
+ const response = await request({
134
+ method: Methods.post,
135
+ data,
136
+ endPoint: `consultations`,
137
+ });
138
+ if (response.status === 201) {
139
+ return response;
140
+ }
141
+ throw Error(JSON.stringify(response));
142
+ };
143
+ export const getConsultationInfo = async (consultation_id) => {
144
+ const response = await request({
145
+ method: Methods.get,
146
+ data: {
147
+ expand: 'pusherAppKey,parentConsultation,consultations,user,media,pusherChannel,' +
148
+ 'chatConfig,chatHistory,voipConfig,videoConfig,recommendation',
149
+ },
150
+ endPoint: `consultations/${consultation_id}`,
151
+ });
152
+ if (response.status === 200) {
153
+ if (response.data && response.data.pusherAppKey) {
154
+ response.data.socketParams = {
155
+ apiKey: response.data.pusherAppKey,
156
+ cluster: 'eu',
157
+ authEndpoint: `${TBIConstants.baseURL}/v1/auth/pusher?access-token=${TBIConstants.token}`,
158
+ };
159
+ }
160
+ return response;
161
+ }
162
+ throw Error(JSON.stringify(response));
163
+ };
164
+ export const getLastConsultation = async () => {
165
+ const response = await request({
166
+ method: Methods.get,
167
+ data: {
168
+ 'per-page': 1,
169
+ 'sort': '-id',
170
+ 'expand': 'pusherAppKey,parentConsultation,consultations,user,media,pusherChannel,' +
171
+ 'chatConfig,chatHistory,voipConfig,videoConfig,recommendation',
172
+ },
173
+ endPoint: `consultations`,
174
+ });
175
+ if (response.status === 200) {
176
+ if (response.data && response.data[0] && response.data[0].pusherAppKey) {
177
+ response.data[0].socketParams = {
178
+ apiKey: response?.data?.[0]?.pusherAppKey,
179
+ cluster: 'eu',
180
+ authEndpoint: `${TBIConstants.baseURL}/v1/auth/pusher?access-token=${TBIConstants.token}`,
181
+ };
182
+ }
183
+ return response;
184
+ }
185
+ throw Error(JSON.stringify(response));
186
+ };
187
+ export const getConsultationList = async (user_id, page = 1, perPage = 20) => {
188
+ if (!user_id) {
189
+ throw Error('missing user id');
190
+ }
191
+ const response = await request({
192
+ method: Methods.get,
193
+ data: {
194
+ page,
195
+ 'per-page': perPage,
196
+ 'filter[user_id]': user_id,
197
+ 'expand': 'pusherAppKey,parentConsultation,consultations,user,media,pusherChannel,' +
198
+ 'chatConfig,chatHistory,voipConfig,videoConfig,recommendation',
199
+ },
200
+ endPoint: `consultations`,
201
+ });
202
+ if (response.status === 200) {
203
+ return response;
204
+ }
205
+ throw Error(JSON.stringify(response));
206
+ };
207
+ export const deleteConsultation = async (consultation_id) => {
208
+ const response = await request({
209
+ method: Methods.delete,
210
+ data: {},
211
+ endPoint: `consultations/${consultation_id}`,
212
+ });
213
+ if (response.status === 204) {
214
+ return response;
215
+ }
216
+ throw Error(JSON.stringify(response));
217
+ };
218
+ export const cancelConsultation = async (consultation_id) => {
219
+ const response = await request({
220
+ method: Methods.post,
221
+ data: {},
222
+ endPoint: `consultations/${consultation_id}/cancel`,
223
+ });
224
+ if (response.status === 200) {
225
+ return response;
226
+ }
227
+ throw Error(JSON.stringify(response));
228
+ };
229
+ export const uploadMedia = async (path, type, fileName) => {
230
+ const response = await request({
231
+ method: Methods.post,
232
+ endPoint: `media`,
233
+ data: {},
234
+ path,
235
+ type,
236
+ fileName,
237
+ });
238
+ if (response.status === 200) {
239
+ return response;
240
+ }
241
+ throw Error(JSON.stringify(response));
242
+ };
243
+ export const getPrescription = (consultation_id) => request({
244
+ method: Methods.get,
245
+ endPoint: `consultations/${consultation_id}/download-prescription`,
246
+ download: true,
247
+ });
@@ -0,0 +1,19 @@
1
+ export const materialStatusArray = [
2
+ 'single',
3
+ 'married',
4
+ 'divorced',
5
+ 'widow',
6
+ ];
7
+ export const bloodTypeArray = [
8
+ 'A+',
9
+ 'B+',
10
+ 'AB+',
11
+ 'O+',
12
+ 'A-',
13
+ 'B-',
14
+ 'AB-',
15
+ 'O-',
16
+ ];
17
+ export const boolStringArray = ['yes', 'no'];
18
+ export const genderTypeArray = ['male', 'female'];
19
+ export const MediumArray = ['chat', 'gsm', 'voip', 'video'];
@@ -0,0 +1,10 @@
1
+ import OT, { OTPublisher, OTSession, OTSubscriber, OTSubscriberView, } from './video';
2
+ export { OTSession as TBISession, OTPublisher as TBIPublisher, OTSubscriber as TBISubscriber, OTSubscriberView as TBISubscriberView, OT as TBIVideo, };
3
+ export { default as AltibbiChat } from '@sendbird/chat';
4
+ export { BaseChannel, ChannelType, PushTriggerOption, RestrictedUser, User, ConnectionHandler, } from '@sendbird/chat';
5
+ export { GroupChannel, GroupChannelHandler, GroupChannelModule, } from '@sendbird/chat/groupChannel';
6
+ export { BaseMessage, ReactionEvent, ThreadInfoUpdateEvent, } from '@sendbird/chat/message';
7
+ export { uploadMedia, getUser, getUsers, createUser, updateUser, deleteUser, getConsultationList, getConsultationInfo, getLastConsultation, createConsultation, deleteConsultation, cancelConsultation, getPrescription, } from './connection';
8
+ export { TBIConstants, init } from './service';
9
+ export { TBISocket, TBISocketChannel, TBISocketMember, TBISocketEvent, } from './scoket';
10
+ export { materialStatusArray, bloodTypeArray, boolStringArray, genderTypeArray, MediumArray, } from './data';