agora-appbuilder-core 2.3.0-beta.3 → 2.3.0-beta.6

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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "agora-appbuilder-core",
3
- "version": "2.3.0-beta.3",
3
+ "version": "2.3.0-beta.6",
4
4
  "description": "React Native template for RTE app builder",
5
5
  "main": "index.js",
6
6
  "files": [
@@ -13,7 +13,7 @@
13
13
  "deps": "cd template && npm i",
14
14
  "dev-setup": "npm run uikit && npm run deps && node devSetup.js",
15
15
  "web-build": "cd template && npm run web:build && cd .. && npm run copy-vercel",
16
- "copy-vercel": "cp vercel.json Builds/web",
16
+ "copy-vercel": "cp -r Builds/web template/dist && cp vercel.json template/dist",
17
17
  "pre-release": "cd template && cp package-lock.json _package-lock.json"
18
18
  },
19
19
  "author": {
@@ -322,7 +322,7 @@ module.exports.webSdk = series(
322
322
  module.exports.androidUnix = series(
323
323
  general.clean,
324
324
  general.createBuildDirectory,
325
- // android.gradleBuildUnix,
325
+ android.gradleBuildUnix,
326
326
  android.copyBuild,
327
327
  );
328
328
 
@@ -247,7 +247,14 @@ const Create = ({
247
247
  }
248
248
  init();
249
249
  return () => {
250
- engine.current!.destroy();
250
+ /**
251
+ * if condition add for websdk issue
252
+ * For some reason even if engine.current is defined somehow destroy gets undefined and
253
+ * causes a crash so thats why this check is needed before we call the method
254
+ */
255
+ if (engine.current.destroy) {
256
+ engine.current!.destroy();
257
+ }
251
258
  };
252
259
  }, [rtcProps.appId]);
253
260
 
@@ -59,6 +59,15 @@ const Chat = () => {
59
59
 
60
60
  const {primaryColor} = useContext(ColorContext);
61
61
 
62
+ React.useEffect(() => {
63
+ return () => {
64
+ // reset both the active tabs
65
+ setGroupActive(false);
66
+ setPrivateActive(false);
67
+ setSelectedUser(0);
68
+ };
69
+ }, []);
70
+
62
71
  const selectGroup = () => {
63
72
  setPrivateActive(false);
64
73
  setGroupActive(true);
@@ -194,6 +194,9 @@ const RtmConfigure = (props: any) => {
194
194
  const attr = await engine.current.getUserAttributesByUid(
195
195
  member.uid,
196
196
  );
197
+ if (!attr || !attr.attributes) {
198
+ throw attr;
199
+ }
197
200
  for (const key in attr.attributes) {
198
201
  if (
199
202
  attr.attributes.hasOwnProperty(key) &&
@@ -297,6 +300,9 @@ const RtmConfigure = (props: any) => {
297
300
  const backoffAttributes = backOff(
298
301
  async () => {
299
302
  const attr = await engine.current.getUserAttributesByUid(data.uid);
303
+ if (!attr || !attr.attributes) {
304
+ throw attr;
305
+ }
300
306
  for (const key in attr.attributes) {
301
307
  if (attr.attributes.hasOwnProperty(key) && attr.attributes[key]) {
302
308
  return attr;
@@ -470,7 +476,7 @@ const RtmConfigure = (props: any) => {
470
476
  queuedEvents.uid,
471
477
  queuedEvents.ts,
472
478
  );
473
- EventsQueue.dequeue();
479
+ // EventsQueue.dequeue();
474
480
  }
475
481
  }
476
482
  } catch (error) {
@@ -30,7 +30,6 @@ interface ScreenShareProviderProps {
30
30
  children: React.ReactNode;
31
31
  }
32
32
  const LiveStreamDataProvider = (props: ScreenShareProviderProps) => {
33
- const localUid = useLocalUid();
34
33
  const {renderList} = useUserList();
35
34
  const {raiseHandList} = useContext(LiveStreamContext);
36
35
  const [hostUids, setHostUids] = useState<UidType[]>([]);
@@ -41,13 +40,14 @@ const LiveStreamDataProvider = (props: ScreenShareProviderProps) => {
41
40
  const hostList = filterObject(
42
41
  renderList,
43
42
  ([k, v]) =>
44
- (v?.type === 'rtc' || v?.type === 'live') &&
43
+ (v?.type === 'rtc' ||
44
+ v?.type === 'live' ||
45
+ (v?.type === 'screenshare' && v?.video == 1)) &&
45
46
  (raiseHandList[k]
46
47
  ? raiseHandList[k]?.role == ClientRole.Broadcaster
47
48
  : true) &&
48
49
  !v?.offline,
49
50
  );
50
-
51
51
  const audienceList = filterObject(
52
52
  renderList,
53
53
  ([k, v]) =>
@@ -26,6 +26,8 @@ export const LiveStreamContextProvider: React.FC<liveStreamPropsInterface> = (
26
26
  props,
27
27
  ) => {
28
28
  const screenshareContextInstance = useScreenshare();
29
+ const screenshareContextInstanceRef = useRef<any>();
30
+ screenshareContextInstanceRef.current = screenshareContextInstance;
29
31
 
30
32
  const {renderList} = useUserList();
31
33
  const renderListRef = useRef<any>();
@@ -187,7 +189,7 @@ export const LiveStreamContextProvider: React.FC<liveStreamPropsInterface> = (
187
189
  ...prevState[data.sender],
188
190
  role:
189
191
  data.payload.value in ClientRole
190
- ? ClientRole[data.payload.value]
192
+ ? parseInt(data.payload.value)
191
193
  : ClientRole.Audience,
192
194
  },
193
195
  };
@@ -317,7 +319,8 @@ export const LiveStreamContextProvider: React.FC<liveStreamPropsInterface> = (
317
319
  ) {
318
320
  /** 2.b */
319
321
  showToast(LSNotificationObject.RAISE_HAND_APPROVED_REQUEST_RECALL);
320
- screenshareContextInstance?.stopUserScreenShare(); // This will not exist on ios
322
+ screenshareContextInstanceRef?.current?.stopUserScreenShare(); // This will not exist on ios
323
+
321
324
  // Demote user's privileges to audience
322
325
  changeClientRoleTo(ClientRole.Audience);
323
326
  }
@@ -403,7 +406,7 @@ export const LiveStreamContextProvider: React.FC<liveStreamPropsInterface> = (
403
406
  raiseHandList[localUidRef.current]?.role == ClientRole.Broadcaster &&
404
407
  raiseHandList[localUidRef.current]?.raised === RaiseHandValue.TRUE
405
408
  ) {
406
- screenshareContextInstance?.stopUserScreenShare(); // This will not exist on ios
409
+ screenshareContextInstanceRef?.current?.stopUserScreenShare(); // This will not exist on ios
407
410
  // Change role
408
411
  changeClientRoleTo(ClientRole.Audience);
409
412
  }
@@ -25,7 +25,7 @@ import {MeetingInviteInterface} from '../language/default-labels/videoCallScreen
25
25
  import Clipboard from '../subComponents/Clipboard';
26
26
 
27
27
  export enum SHARE_LINK_CONTENT_TYPE {
28
- ATTENDEE,
28
+ ATTENDEE = 1,
29
29
  HOST,
30
30
  PSTN,
31
31
  MEETING_INVITE,
@@ -45,12 +45,8 @@ interface ShareLinkProvideProps {
45
45
  }
46
46
 
47
47
  const ShareLinkProvider = (props: ShareLinkProvideProps) => {
48
- const {
49
- meetingTitle,
50
- meetingPassphrase,
51
- isSeparateHostLink,
52
- isJoinDataFetched,
53
- } = useMeetingInfo();
48
+ const {meetingTitle, meetingPassphrase, isSeparateHostLink, isHost} =
49
+ useMeetingInfo();
54
50
 
55
51
  //commmented for v1 release
56
52
  // const copiedToClipboardText = useString(
@@ -65,37 +61,40 @@ const ShareLinkProvider = (props: ShareLinkProvideProps) => {
65
61
  const meetingIdText = 'Meeting ID';
66
62
  const PSTNNumberText = 'PSTN Number';
67
63
  const PSTNPinText = 'PSTN Pin';
68
- const meetingInviteText = ({meetingName, id, url, pstn, isCallActive}) => {
64
+ const meetingInviteText = ({
65
+ meetingName,
66
+ id,
67
+ url,
68
+ pstn,
69
+ isHost,
70
+ isSeparateHostLink,
71
+ }: MeetingInviteInterface) => {
69
72
  let inviteContent = '';
70
73
  if (url) {
71
- // if host data is present generate links for both host and attendee
72
- if (url?.host) {
73
- inviteContent += `Meeting - ${meetingName}\nURL for Attendee: ${url?.attendee}\nURL for Host: ${url?.host}`;
74
- }
75
- // if host data is not present then generate link for attendee alone
76
- else {
77
- if (isCallActive) {
78
- //copy this label on videocall screen
79
- inviteContent += `Meeting - ${meetingName}\nURL for Attendee: ${url?.attendee}`;
74
+ //for host
75
+ if (isHost) {
76
+ if (isSeparateHostLink) {
77
+ //seperate link for host and attendee
78
+ inviteContent += `Meeting - ${meetingName}\nURL for Attendee: ${url?.attendee}\nURL for Host: ${url?.host}`;
80
79
  } else {
81
- //copy this label on share link screen
82
- inviteContent += `Meeting - ${meetingName}\nMeeting URL: ${url?.attendee}`;
80
+ //single link for everyone
81
+ inviteContent += `Meeting - ${meetingName}\nMeeting URL: ${url?.host}`;
83
82
  }
84
83
  }
85
- } else {
86
- // if host data is present generate meeting ID for both host and attendee
87
- if (id?.host) {
88
- inviteContent += `Meeting - ${meetingName}\nAttendee Meeting ID: ${id?.attendee}\nHost Meeting ID: ${id?.host}`;
89
- }
90
- // if host data is not present then generate meeting ID for attendee alone
84
+ //for attendee
91
85
  else {
92
- if (isCallActive) {
93
- //copy this label on videocall screen
94
- inviteContent += `Meeting - ${meetingName}\nAttendee Meeting ID: ${id?.attendee}`;
86
+ inviteContent += `Meeting - ${meetingName}\nURL for Attendee: ${url?.attendee}`;
87
+ }
88
+ } else {
89
+ if (isHost) {
90
+ if (isSeparateHostLink) {
91
+ inviteContent += `Meeting - ${meetingName}\nAttendee Meeting ID: ${id?.attendee}\nHost Meeting ID: ${id?.host}`;
95
92
  } else {
96
- //copy this label on share link screen
97
- inviteContent += `Meeting - ${meetingName}\nMeeting ID: ${id?.attendee}`;
93
+ inviteContent += `Meeting - ${meetingName}\nMeeting ID: ${id?.host}`;
98
94
  }
95
+ } else {
96
+ //copy this label on videocall screen
97
+ inviteContent += `Meeting - ${meetingName}\nAttendee Meeting ID: ${id?.attendee}`;
99
98
  }
100
99
  }
101
100
  // Adding pstn data into meeting data if present
@@ -114,15 +113,13 @@ const ShareLinkProvider = (props: ShareLinkProvideProps) => {
114
113
  url: baseURL
115
114
  ? GetMeetingInviteURL(
116
115
  baseURL,
117
- meetingPassphrase.attendee,
118
- isSeparateHostLink ? meetingPassphrase.host : undefined,
116
+ isHost,
117
+ meetingPassphrase,
118
+ isSeparateHostLink,
119
119
  )
120
120
  : undefined,
121
121
  id: !baseURL
122
- ? GetMeetingInviteID(
123
- meetingPassphrase.attendee,
124
- isSeparateHostLink ? meetingPassphrase.host : undefined,
125
- )
122
+ ? GetMeetingInviteID(isHost, meetingPassphrase, isSeparateHostLink)
126
123
  : undefined,
127
124
  pstn: meetingPassphrase?.pstn
128
125
  ? {
@@ -130,7 +127,8 @@ const ShareLinkProvider = (props: ShareLinkProvideProps) => {
130
127
  pin: meetingPassphrase.pstn.pin,
131
128
  }
132
129
  : undefined,
133
- isCallActive: isJoinDataFetched,
130
+ isHost,
131
+ isSeparateHostLink,
134
132
  });
135
133
  return stringToCopy;
136
134
  };
@@ -152,8 +152,12 @@ class CustomEvents {
152
152
  * @api public
153
153
  */
154
154
  on = (evt: string, listener: TEventCallback) => {
155
- if (!this._validateEvt(evt) || !this._validateListener(listener)) return;
156
- EventUtils.addListener(evt, listener, this.source);
155
+ try {
156
+ if (!this._validateEvt(evt) || !this._validateListener(listener)) return;
157
+ EventUtils.addListener(evt, listener, this.source);
158
+ } catch (error) {
159
+ console.log('custom-events-on error: ', error);
160
+ }
157
161
  };
158
162
 
159
163
  /**
@@ -167,16 +171,23 @@ class CustomEvents {
167
171
  * @api public
168
172
  */
169
173
  off = (evt?: string, listenerToRemove?: TEventCallback) => {
170
- if (listenerToRemove) {
171
- if (this._validateListener(listenerToRemove) && this._validateEvt(evt)) {
172
- EventUtils.removeListener(evt, listenerToRemove, this.source);
173
- }
174
- } else if (evt) {
175
- if (this._validateEvt(evt)) {
176
- EventUtils.removeAllListeners(evt, this.source);
174
+ try {
175
+ if (listenerToRemove) {
176
+ if (
177
+ this._validateListener(listenerToRemove) &&
178
+ this._validateEvt(evt)
179
+ ) {
180
+ EventUtils.removeListener(evt, listenerToRemove, this.source);
181
+ }
182
+ } else if (evt) {
183
+ if (this._validateEvt(evt)) {
184
+ EventUtils.removeAllListeners(evt, this.source);
185
+ }
186
+ } else {
187
+ EventUtils.removeAll(this.source);
177
188
  }
178
- } else {
179
- EventUtils.removeAll(this.source);
189
+ } catch (error) {
190
+ console.log('custom-events-off error: ', error);
180
191
  }
181
192
  };
182
193
 
@@ -210,12 +221,16 @@ class CustomEvents {
210
221
 
211
222
  if (level === 2 || level === 3) {
212
223
  console.log('CUSTOM_EVENT_API: Event lifecycle: persist', level);
213
- await this._persist(evt, {...payload, source: this.source});
224
+ try {
225
+ await this._persist(evt, {...payload, source: this.source});
226
+ } catch (error) {
227
+ console.log('custom-events-persist error: ', error);
228
+ }
214
229
  }
215
230
  try {
216
231
  await this._send(rtmPayload, to);
217
232
  } catch (error) {
218
- console.log('CUSTOM_EVENT_API: sendPersist sending failed. ', error);
233
+ console.log('CUSTOM_EVENT_API: sending failed. ', error);
219
234
  }
220
235
  };
221
236
  }
@@ -10,6 +10,8 @@ interface NetworkQualityStatusInterface {
10
10
  }
11
11
  export type NetworkQualities = keyof NetworkQualityStatusInterface;
12
12
  export interface MeetingInviteInterface {
13
+ isHost: boolean;
14
+ isSeparateHostLink: boolean;
13
15
  meetingName?: string;
14
16
  pstn?: {
15
17
  number: string;
@@ -17,11 +19,11 @@ export interface MeetingInviteInterface {
17
19
  };
18
20
  url?: {
19
21
  host?: string;
20
- attendee: string;
22
+ attendee?: string;
21
23
  };
22
24
  id?: {
23
25
  host?: string;
24
- attendee: string;
26
+ attendee?: string;
25
27
  };
26
28
  }
27
29
  export interface I18nVideoCallScreenLabelsInterface {
@@ -28,6 +28,8 @@ import useCreateMeeting from '../utils/useCreateMeeting';
28
28
  import {CreateProvider} from './create/useCreate';
29
29
  import useJoinMeeting from '../utils/useJoinMeeting';
30
30
  import SDKEvents from '../utils/SdkEvents';
31
+ import {MeetingInfoDefaultValue} from '../components/meeting-info/useMeetingInfo';
32
+ import {useSetMeetingInfo} from '../components/meeting-info/useSetMeetingInfo';
31
33
 
32
34
  const Create = () => {
33
35
  const {CreateComponent} = useFpe((data) => {
@@ -58,6 +60,7 @@ const Create = () => {
58
60
  const [hostControlCheckbox, setHostControlCheckbox] = useState(true);
59
61
  const [roomCreated, setRoomCreated] = useState(false);
60
62
  const createRoomFun = useCreateMeeting();
63
+ const {setMeetingInfo} = useSetMeetingInfo();
61
64
  const {
62
65
  meetingPassphrase: {attendee, host, pstn},
63
66
  } = useMeetingInfo();
@@ -74,7 +77,7 @@ const Create = () => {
74
77
  toggle
75
78
  ? 'Restrict Host Controls (Separate host link)'
76
79
  : 'Restrict Host Controls (Everyone is a Host)';
77
- const pstnToggle = () => 'Use PSTN (Join by dialing a number)';
80
+ const pstnToggle = (value: boolean) => 'Use PSTN (Join by dialing a number)';
78
81
  const meetingNameInputPlaceholder = useString(
79
82
  'meetingNameInputPlaceholder',
80
83
  )();
@@ -115,6 +118,7 @@ const Create = () => {
115
118
  if (roomTitle !== '') {
116
119
  setLoading(true);
117
120
  try {
121
+ setMeetingInfo(MeetingInfoDefaultValue);
118
122
  await createRoomFun(roomTitle, enablePSTN, isSeparateHostLink);
119
123
  setLoading(false);
120
124
  Toast.show({
@@ -28,6 +28,8 @@ import Error from '../subComponents/Error';
28
28
  import {useString} from '../utils/useString';
29
29
  import useNavigateTo from '../utils/useNavigateTo';
30
30
  import {useFpe} from 'fpe-api';
31
+ import {useSetMeetingInfo} from '../components/meeting-info/useSetMeetingInfo';
32
+ import {MeetingInfoDefaultValue} from '../components/meeting-info/useMeetingInfo';
31
33
 
32
34
  const Join = () => {
33
35
  //commented for v1 release
@@ -43,12 +45,13 @@ const Join = () => {
43
45
  const [error, setError] = useState<null | {name: string; message: string}>(
44
46
  null,
45
47
  );
46
-
48
+ const {setMeetingInfo} = useSetMeetingInfo();
47
49
  const createMeeting = () => {
48
50
  history.push('/create');
49
51
  };
50
52
 
51
53
  const startCall = async () => {
54
+ setMeetingInfo(MeetingInfoDefaultValue);
52
55
  navigateTo(phrase);
53
56
  };
54
57
  const {JoinComponent} = useFpe((data) => {
@@ -128,11 +128,11 @@ const VideoCall: React.FC = () => {
128
128
  }, []);
129
129
 
130
130
  useEffect(() => {
131
- try {
132
- useJoin(phrase);
133
- } catch (error) {
134
- setGlobalErrorMessage(error);
135
- }
131
+ useJoin(phrase)
132
+ .then(() => {})
133
+ .catch((error) => {
134
+ setGlobalErrorMessage(error);
135
+ });
136
136
  }, []);
137
137
 
138
138
  const data = useMeetingInfo();
@@ -30,7 +30,7 @@ export const timeNow = () => new Date().getTime();
30
30
  export const getMessageTime = (ts?: number): number => {
31
31
  if (!ts) return timeNow();
32
32
  try {
33
- const timestamp = new Date(ts).getHours();
33
+ const timestamp = new Date(ts).getTime();
34
34
  return isNaN(timestamp) ? timeNow() : timestamp;
35
35
  } catch (error) {
36
36
  return timeNow();
@@ -121,6 +121,7 @@ export const ScreenshareConfigure = (props: {children: React.ReactNode}) => {
121
121
  if (isRecordingActive) {
122
122
  executeRecordingQuery(isActive);
123
123
  }
124
+ console.log('supriya screenshare query executed');
124
125
  try {
125
126
  // @ts-ignore
126
127
  await rtc.RtcEngine.startScreenshare(
@@ -133,18 +134,18 @@ export const ScreenshareConfigure = (props: {children: React.ReactNode}) => {
133
134
  encryption as unknown as any,
134
135
  );
135
136
  isActive && setScreenshareActive(true);
137
+ if (isActive) {
138
+ CustomEvents.send(EventNames.SCREENSHARE_ATTRIBUTE, {
139
+ value: `${true}`,
140
+ level: EventLevel.LEVEL2,
141
+ });
142
+ //if local user started the screenshare then change layout to pinned
143
+ triggerChangeLayout(true, screenShareUid);
144
+ }
136
145
  } catch (e) {
137
- console.error("can't start the screen share", e);
146
+ console.error("supriya an't start the screen share", e);
138
147
  executeNormalQuery();
139
148
  }
140
- if (isActive) {
141
- CustomEvents.send(EventNames.SCREENSHARE_ATTRIBUTE, {
142
- value: `${true}`,
143
- level: EventLevel.LEVEL2,
144
- });
145
- //if local user started the screenshare then change layout to pinned
146
- triggerChangeLayout(true, screenShareUid);
147
- }
148
149
  };
149
150
 
150
151
  return (
@@ -1,28 +1,51 @@
1
1
  const GetMeetingInviteURL = (
2
2
  baseUrl: string,
3
- attendee: string,
4
- host?: string,
3
+ isHost: boolean,
4
+ meetingPassphrase: {
5
+ host?: string;
6
+ attendee?: string;
7
+ },
8
+ isSeparateHostLink: boolean,
5
9
  ) => {
6
- if (host) {
7
- return {
8
- host: `${baseUrl}/${host}`,
9
- attendee: `${baseUrl}/${attendee}`,
10
- };
10
+ if (isHost) {
11
+ if (isSeparateHostLink) {
12
+ return {
13
+ host: `${baseUrl}/${meetingPassphrase.host}`,
14
+ attendee: `${baseUrl}/${meetingPassphrase.attendee}`,
15
+ };
16
+ } else {
17
+ return {
18
+ host: `${baseUrl}/${meetingPassphrase.host}`,
19
+ };
20
+ }
11
21
  } else {
12
22
  return {
13
- attendee: `${baseUrl}/${attendee}`,
23
+ attendee: `${baseUrl}/${meetingPassphrase.attendee}`,
14
24
  };
15
25
  }
16
26
  };
17
- const GetMeetingInviteID = (attendee: string, host?: string) => {
18
- if (host) {
19
- return {
20
- host: `${host}`,
21
- attendee: `${attendee}`,
22
- };
27
+ const GetMeetingInviteID = (
28
+ isHost: boolean,
29
+ meetingPassphrase: {
30
+ host?: string;
31
+ attendee?: string;
32
+ },
33
+ isSeparateHostLink: boolean,
34
+ ) => {
35
+ if (isHost) {
36
+ if (isSeparateHostLink) {
37
+ return {
38
+ host: `${meetingPassphrase.host}`,
39
+ attendee: `${meetingPassphrase.attendee}`,
40
+ };
41
+ } else {
42
+ return {
43
+ host: `${meetingPassphrase.host}`,
44
+ };
45
+ }
23
46
  } else {
24
47
  return {
25
- attendee: `${attendee}`,
48
+ attendee: `${meetingPassphrase.attendee}`,
26
49
  };
27
50
  }
28
51
  };
@@ -56,19 +56,25 @@ export default function useJoinMeeting() {
56
56
  const {setMeetingInfo} = useSetMeetingInfo();
57
57
  const {client} = useContext(GraphQLContext);
58
58
  return async (phrase: string) => {
59
- const response = await client.query({
60
- query:
61
- store.token === null
62
- ? JOIN_CHANNEL_PHRASE
63
- : JOIN_CHANNEL_PHRASE_AND_GET_USER,
64
- variables: {
65
- passphrase: phrase,
66
- },
59
+ setMeetingInfo((prevState) => {
60
+ return {
61
+ ...prevState,
62
+ isJoinDataFetched: false,
63
+ };
67
64
  });
68
- if (response.error) {
69
- throw response.error;
70
- } else {
71
- try {
65
+ try {
66
+ const response = await client.query({
67
+ query:
68
+ store.token === null
69
+ ? JOIN_CHANNEL_PHRASE
70
+ : JOIN_CHANNEL_PHRASE_AND_GET_USER,
71
+ variables: {
72
+ passphrase: phrase,
73
+ },
74
+ });
75
+ if (response.error) {
76
+ throw response.error;
77
+ } else {
72
78
  if (response && response.data) {
73
79
  let data = response.data;
74
80
  let meetingInfo: Partial<MeetingInfoContextInterface> = {
@@ -111,10 +117,12 @@ export default function useJoinMeeting() {
111
117
  ...meetingInfo,
112
118
  };
113
119
  });
120
+ } else {
121
+ throw new Error('An error occurred in parsing the channel data.');
114
122
  }
115
- } catch (error) {
116
- throw new Error('An error occurred in parsing the channel data.');
117
123
  }
124
+ } catch (error) {
125
+ throw error;
118
126
  }
119
127
  };
120
128
  }