From e1839a369fd92018e43610056cb9b5e23c5ff3ec Mon Sep 17 00:00:00 2001 From: Jatin Nagar Date: Thu, 12 Oct 2023 13:04:58 +0530 Subject: [PATCH 01/21] fix(prebuilt): :bug: showing indicator on browser recording initialising state --- .../src/components/HMSRecordingIndicator.tsx | 2 +- .../src/components/StopRecordingModalContent.tsx | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/packages/react-native-room-kit/src/components/HMSRecordingIndicator.tsx b/packages/react-native-room-kit/src/components/HMSRecordingIndicator.tsx index b430001b0..4ed43393a 100644 --- a/packages/react-native-room-kit/src/components/HMSRecordingIndicator.tsx +++ b/packages/react-native-room-kit/src/components/HMSRecordingIndicator.tsx @@ -13,7 +13,7 @@ export const HMSRecordingIndicator = () => { const startingOrStoppingRecording = useSelector( (state: RootState) => state.app.startingOrStoppingRecording || - state.hmsStates.room?.browserRecordingState.initialising + (state.hmsStates.room?.browserRecordingState.initialising ?? false) ); const { on_surface_high: onSurfaceHighColor } = useHMSRoomColorPalette(); diff --git a/packages/react-native-room-kit/src/components/StopRecordingModalContent.tsx b/packages/react-native-room-kit/src/components/StopRecordingModalContent.tsx index a2dc04023..15aaff805 100644 --- a/packages/react-native-room-kit/src/components/StopRecordingModalContent.tsx +++ b/packages/react-native-room-kit/src/components/StopRecordingModalContent.tsx @@ -18,7 +18,9 @@ export const StopRecordingModalContent: React.FC< const dispatch = useDispatch(); const hmsInstance = useHMSInstance(); const startingOrStoppingRecording = useSelector( - (state: RootState) => state.app.startingOrStoppingRecording + (state: RootState) => + state.app.startingOrStoppingRecording || + (state.hmsStates.room?.browserRecordingState.initialising ?? false) ); const hmsRoomStyles = useHMSRoomStyleSheet((theme, typography) => ({ From 439f50e983c9e974702a34391862f084770c5ce8 Mon Sep 17 00:00:00 2001 From: Jatin Nagar Date: Thu, 12 Oct 2023 14:00:14 +0530 Subject: [PATCH 02/21] feat(prebuilt): :sparkles: added lower remote peer hand ui option in participants list --- .../src/Icons/Hand/assets/hand-off.png | Bin 0 -> 450 bytes .../src/Icons/Hand/assets/hand-off@2x.png | Bin 0 -> 820 bytes .../src/Icons/Hand/assets/hand-off@3x.png | Bin 0 -> 1230 bytes .../src/Icons/Hand/index.tsx | 16 +++++++++-- .../Participants/ParticipantsItemOptions.tsx | 26 +++++++++++++++++- 5 files changed, 38 insertions(+), 4 deletions(-) create mode 100644 packages/react-native-room-kit/src/Icons/Hand/assets/hand-off.png create mode 100644 packages/react-native-room-kit/src/Icons/Hand/assets/hand-off@2x.png create mode 100644 packages/react-native-room-kit/src/Icons/Hand/assets/hand-off@3x.png diff --git a/packages/react-native-room-kit/src/Icons/Hand/assets/hand-off.png b/packages/react-native-room-kit/src/Icons/Hand/assets/hand-off.png new file mode 100644 index 0000000000000000000000000000000000000000..bb51406ed47e88a608dfa9a4e5f08c90b553d37a GIT binary patch literal 450 zcmV;z0X_bSP)*8SCTN(TFad192y}yFgJgs74n5FusfbjmSl0VLV ze$M$Ka>0LLp63D_!5+MmQ@{-xHTo;4`_^alI~z z>2)>e4-yIQASXM`25fd~<}|Z{{LHRFQo+1#*$)08`RsD*su+Qi4=MZ-vk-|EVDJmL zUy1SWMBhOvkpf}Og%jDu#QVih>LeoWyNpW;=%QbHV3^;U>YDZ#jY!XmS(tjH$*||f sm2r|*zA02OODuYp>tN#2en4k|4_F}O-bzygZ~y=R07*qoM6N<$f-;uCZU6uP literal 0 HcmV?d00001 diff --git a/packages/react-native-room-kit/src/Icons/Hand/assets/hand-off@2x.png b/packages/react-native-room-kit/src/Icons/Hand/assets/hand-off@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..4b9a40bd187014ebe3c8db15d3d94f463cf8edce GIT binary patch literal 820 zcmV-41Izr0P)vcO)C- z>kM;2!j2&%sJ)PhZ&bg7YB!`RWm`aE0=bn6cMiJ~_M?PL0ye6oY2_n9?`vx^p#-#T z+O!HFQIhPGt&f1QEtGBzDS?6MB({}@z((l}PSWqpw(vhmV7G}&2Z2KAT?kIA521#u z)vBh)4M{DkBMvOFf@g>B8_5rOFLb1$0>kzM>Qt~IkSjg**q%jqfK&(|v9{hdflTT9 z(&{*bKyV6aNIKmr)vI)(_NOa-pCKYf5fIoD8M`MYVG02aL&irU>gqFM5#S0^%kMrC zwe^gKk0C}LtA3GezPr;;C%mA7U}tu-nsn==7v<91~1XrRiww( zcZ!{*3h}CP>Eo5ZhwjfNvkj#>=~Yg?v9G3()bm_kZ%lb4eNB(OquVd&QjJNzN~hTH zMc`$Xb#15LB{(*uw0$D^0@IHjUib*SOd2mwiTAEfoJxUbr|&XG4XJ?LjjPhf0BPe% zojm=6kK)Q_@Fw;G9ha05K7vR@Cm>EARO!q{`Ut&GBq5MtSKmt*i4YP=2#DiyY81qe z?$+wZGp@)Zs^c1(svf(PCX=*y|NSLxUY z89N%qH9squ2y8#ravGTpt*@N+6_RaolFuX?)u$%8Rrd|HG1pVpKSD~#svU7Sc-6V8 yWe&e-zgjzpY_UCpH;zeH(!Rq8Wq84Y_m00vZTADBZnv5M0000rXgWc&LCXXQ6QoQKGeN@y#~qSi6h(6MVOuKb z_nzMKhh)irpH80!C=?2XLZMJ76mkU-CluBcUQw{6a7SST|2rhYBih+fs33RvOUkcY zL5I-u=6If6_Lf8ie3FIbDlmo)V6inJ_}L2zGbxJ7406WsBGDqzGp5>eE9Kru6KM^J zc<&hR8-=+%W^-Rtp|373E?!&`%PKOZ@KIj+sT?ykJ*#d`=y*?QzSH5Iyu{YV=|9W! zUldkqn&e3H_qHU8bAyN0$;QqhKNI(m6TTwxJ#-^fAm$NzekRyH=9WM z^_s#4!l@1E*_TZqCtNKFg|p=raED4uWUwq33tB7pDm<>X&yX7!=#!N6J5Pa@+Wn=P zUVaP~zSI7iR~1tUsBSuY@MGU{&Uv%QTP_11qZqDCAd+B#m`IUo@S|?IHedA{g)0i5w6ZXH3{`v_H;OUWNek8Ttnr!qm3DvC z)(9j6{kj1B5>IHT0uBN!+5|vttOtR(j>Vke>L$z6I(Fmn7KrhgE55B>Cv@V2bfiyG zJ8#iGNeVhRy$B@HTd5R|JDNTPG7&0L66;}x5=ig$`ik_=3&hSjbw4SH!Kzq5XHuQ5 z+(06tnt2q1!7p%__u-d%uuX-!b^&DEXS#k(hZThtyd_Y~$E?xL9FKdlYb|}$REgmk zy>%45k>c#o57SU$6(iD60)_Y>t{#EK+KLf_+RtUZJ~6(g`FB zFo+dd@;WP04gw8kMKV9%tv6`}l7$$|iY)oLuDc}@XizJXdAjzKT1WeXVJPqvdd5X0 zJnpY;Ar%HI8sux86A8ukmxgCZNeU~nts%fWi-M4FYxc z15PL4=^kdL*Ix$kupiq-b|Q@pBJHq;)=m@H z!t%Apkiw#rB(H|!0(wRkctPRD5~T*Q0Qm##s}tN^_yA&)#KaP3L*d%A zRS(6Sc+*($THXqB1I0fSrmr3gSDUG0{u9U@Sz>% literal 0 HcmV?d00001 diff --git a/packages/react-native-room-kit/src/Icons/Hand/index.tsx b/packages/react-native-room-kit/src/Icons/Hand/index.tsx index 1d42a629c..884a54dec 100644 --- a/packages/react-native-room-kit/src/Icons/Hand/index.tsx +++ b/packages/react-native-room-kit/src/Icons/Hand/index.tsx @@ -4,16 +4,26 @@ import type { ImageProps } from 'react-native'; import { useHMSRoomStyle } from '../../hooks-util'; -interface HandIconProps extends Omit {} +interface HandIconProps extends Omit { + type?: 'off' | 'on'; +} -export const HandIcon: React.FC = ({ style, ...restProps }) => { +export const HandIcon: React.FC = ({ + style, + type = 'on', + ...restProps +}) => { const iconStyles = useHMSRoomStyle((theme) => ({ tintColor: theme.palette.on_surface_high, })); return ( diff --git a/packages/react-native-room-kit/src/components/Participants/ParticipantsItemOptions.tsx b/packages/react-native-room-kit/src/components/Participants/ParticipantsItemOptions.tsx index 5c334e2fa..457f8dc1b 100644 --- a/packages/react-native-room-kit/src/components/Participants/ParticipantsItemOptions.tsx +++ b/packages/react-native-room-kit/src/components/Participants/ParticipantsItemOptions.tsx @@ -8,7 +8,7 @@ import { useHMSLayoutConfig, useHMSRoomStyleSheet, } from '../../hooks-util'; -import { CameraIcon, MicIcon, PersonIcon } from '../../Icons'; +import { CameraIcon, HandIcon, MicIcon, PersonIcon } from '../../Icons'; import { ParticipantsItemOption } from './ParticipantsItemOption'; import type { RootState } from '../../redux'; import { selectCanPublishTrackForRole } from '../../hooks-sdk-selectors'; @@ -88,6 +88,18 @@ const _ParticipantsItemOptions: React.FC = ({ onItemPress(); }; + const handleLowerHandPress = () => { + if (peer.isHandRaised) { + hmsInstance + .lowerRemotePeerHand(peer) + .then((d) => console.log('Lower Remote Peer hand Success: ', d)) + .catch((e) => console.log('Lower Remote Peer hand Error: ', e)); + } else { + console.warn(`peer.isHandRaised = ${peer.isHandRaised} | peer's hand is not raised`); + } + onItemPress(); + }; + const handleAudioTogglePress = () => { if (peer.audioTrack) { hmsInstance @@ -162,6 +174,8 @@ const _ParticipantsItemOptions: React.FC = ({ offStageRoles.includes(peer.role?.name || '') && peer.isHandRaised; + const showLowerHandOption = peer.isHandRaised; + return ( <> {[ @@ -175,6 +189,16 @@ const _ParticipantsItemOptions: React.FC = ({ isActive: false, hide: !showBringOnStageOptions, }, + { + id: 'lower-hand', + icon: ( + + ), + label: 'Lower Hand', + pressHandler: handleLowerHandPress, + isActive: false, + hide: !showLowerHandOption, + }, { id: 'mute-audio', icon: , From 61c2753ebc64d204d5d2530a40a266c613228781 Mon Sep 17 00:00:00 2001 From: Jatin Nagar Date: Thu, 12 Oct 2023 19:10:44 +0530 Subject: [PATCH 03/21] initial changes --- .../Icons/Recording/assets/recording-off.png | Bin 0 -> 458 bytes .../Recording/assets/recording-off@2x.png | Bin 0 -> 812 bytes .../Recording/assets/recording-off@3x.png | Bin 0 -> 1206 bytes .../src/Icons/Recording/index.tsx | 11 ++- .../src/components/HMSNotifications.tsx | 13 +-- .../HMSRecordingStartFailedNotification.tsx | 79 ++++++++++++++++++ .../react-native-room-kit/src/hooks-util.ts | 19 +++++ .../src/redux/reducers/appState.ts | 11 ++- packages/react-native-room-kit/src/utils.ts | 1 + 9 files changed, 125 insertions(+), 9 deletions(-) create mode 100644 packages/react-native-room-kit/src/Icons/Recording/assets/recording-off.png create mode 100644 packages/react-native-room-kit/src/Icons/Recording/assets/recording-off@2x.png create mode 100644 packages/react-native-room-kit/src/Icons/Recording/assets/recording-off@3x.png create mode 100644 packages/react-native-room-kit/src/components/HMSRecordingStartFailedNotification.tsx diff --git a/packages/react-native-room-kit/src/Icons/Recording/assets/recording-off.png b/packages/react-native-room-kit/src/Icons/Recording/assets/recording-off.png new file mode 100644 index 0000000000000000000000000000000000000000..98c32544d839d552bfd5e1dfc1160faa9d6f0326 GIT binary patch literal 458 zcmV;*0X6=KP)i2SaM%;G&N{{fXdgJMEJ4c18#8IFAheCG9CN{2 z27D7bJ(DzCuY8AW6?k~GjAXkciLyCRf0X(=#o>8=%c^iZ0a^KArj*F2UG7U$roL@a&uh zDkN&%-3~bv0onle-!D0S@d^i=8(HlmGw#07*qoM6N<$f(9$Q AE&u=k literal 0 HcmV?d00001 diff --git a/packages/react-native-room-kit/src/Icons/Recording/assets/recording-off@2x.png b/packages/react-native-room-kit/src/Icons/Recording/assets/recording-off@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..a02ea896d38947b81a01294b0d5809e25f1fa5f5 GIT binary patch literal 812 zcmV+{1JnG8P)Mc{K~#7F?O2PA z+b|4efE&OgXoTwo^=*(5+zIMV5O;!RgJcu86XZI9Z-Zn5ma65REbBu_R??z=0O3HU zNIg?zC;@EPuwem2+>UmQllzb$q9j-dcldn($wn&gvIPUl9E4FfsVN1xZgZAi^t9l+1 ztc5demLs7S8(p0kcAqWLIKY~~_k8)WcXkVx#iQ2F^z#70Y;dHcWyaWl; zW&^pv`TiUN4o_;lQp7tYvcKX~sLJqnfgD)E+E{c#CH4<_WF)7>UJa?B$w$Lj#dLad zkof&B;8V`i6Z!}l1oQ>;0o@o9ZNOHq>85WZ!)fQy6X>W;4ifSUR~~zMbm|&CuhJc=gyzY7Q4beiECd4;eY(OXAra$RLnYM!h5gwt7uBtBlUd83x(`dVkI( zp`xQB>yNB9jJ1q8S&_hH39TUqIN#f>7FR8HkMGS~Ges{%0zJ)RDgo1B2bn;37uy=+ z4deosEv}46b{$8?MFFe@w49bO<1RmyOan!sgiU5o^j0@}-D@(lvb{fvdq*gmJO zTHi3|Pj^X!9?4V^!K+2bB088~H%^cp>vxhLF!o1N2PFn7^AAz#ejsTLyXTav zeHPGtJs67twS>icZl_ElSGCy6V)MQvlv7!1Wqw>di$S9EyAz>^)=mH6NIEgi2 qkVre=KN^aJ+%niWP_3ovOzsUHZYkW*}&N#-2iXkbOM|SoKEnqF2c_aK7kG-P*Ohc z>0uktk1wZ_ILSmaGcz+YGoKa!nMpa#oMVJp;mFpc3z|8Cb7qlFF=FihcaautCyfxd z=5Q~ZdN%2Lu~@uPPuRDaLv9iuf0%SpC+4+IFLhbZrmP*Mh-pXx8MP&`vp4D9VVPZ2 zCasa;fH6cQJ`d~c`-sve){;^}D^et3(iX~BB-pN0VLU2WpB9{j^7=QC%wZ**dUM?M z=Pg<1+XXw~4OwT*pLcY0)|@U)x}u}=?xHZx{Ensu9hL+;`>q_oy@8UwiJIMvBDQ#)>{etV2D z^h35D=B9Dolp^JhvI~lhxTR4U7pBAQFz`@fJs(sX@Cp41IrnSfSdzTP?V=f-p3 z?7AgycD|Zv!bbQlBTqB}T?)VbA%EC^6oEuql0PrPZ$HSBujG&P)HLg2KkFllL@W{? z={$UU5b3&3{5fk}b4mV4b^K1AXathjDXu*gc&JDj4Xfif@?@w$LkM9>(HSaGrnpw} z1${;OOL6LWhQ>)t4b+S#&yL^wIPMMkBh_(7p)rkk5atuV758Uo$19#x=aVVQeG>92 zC^WFE2u)NIMRYIM1P{7Fo^-0;>wF3d@v6a3ziX{Nm`HG2ZJZdjqj9QL1IU&bMI;2U zdKHl4y{dPkI-ey*uq4P`I^J3t0tTUA&HoXRM1s3}-Yf02f z))jG4A%cm+cJVC|*;Ue2*)EZobqJv#Z{qwgB0Zs-682pzQ|5gOkM0~=B=tsekH!=v zZ#0+SDC3Uo^3kqwE+e}dRWLC0qIA^%be0;c&ZLf)uDy4~$SUC9dZ*wYvJNjLH!Hd$yZ*(F zbu;uYnMmDnr$CD(^$z%bIvgU6|F)kpf=KZK`5zV7*?bARVw~1!HZwCbGcyx}f8FCn UMB`Va7ytkO07*qoM6N<$g1^Hh761SM literal 0 HcmV?d00001 diff --git a/packages/react-native-room-kit/src/Icons/Recording/index.tsx b/packages/react-native-room-kit/src/Icons/Recording/index.tsx index 74f75481e..e622ea364 100644 --- a/packages/react-native-room-kit/src/Icons/Recording/index.tsx +++ b/packages/react-native-room-kit/src/Icons/Recording/index.tsx @@ -4,10 +4,13 @@ import type { ImageProps } from 'react-native'; import { useHMSRoomStyle } from '../../hooks-util'; -interface RecordingIconProps extends Omit {} +interface RecordingIconProps extends Omit { + type?: 'off' | 'on'; +} export const RecordingIcon: React.FC = ({ style, + type = 'on', ...restProps }) => { const iconStyles = useHMSRoomStyle((theme) => ({ @@ -16,7 +19,11 @@ export const RecordingIcon: React.FC = ({ return ( diff --git a/packages/react-native-room-kit/src/components/HMSNotifications.tsx b/packages/react-native-room-kit/src/components/HMSNotifications.tsx index e57f55b4e..3e3469cf7 100644 --- a/packages/react-native-room-kit/src/components/HMSNotifications.tsx +++ b/packages/react-native-room-kit/src/components/HMSNotifications.tsx @@ -8,6 +8,7 @@ import { HMSLocalScreenshareNotification } from './HMSLocalScreenshareNotificati import { HMSHandRaiseNotification } from './HMSHandRaiseNotification'; import { HMSRoleChangeDeclinedNotification } from './HMSRoleChangeDeclinedNotification'; import { NotificationTypes } from '../utils'; +import { HMSRecordingStartFailedNotification } from './HMSRecordingStartFailedNotification'; export interface HMSNotificationsProps {} @@ -22,14 +23,11 @@ export const HMSNotifications: React.FC = () => { ); // notifications is a stack, first will appear last - const notifications: ( - | typeof LOCAL_SCREENSHARE_PAYLOAD - | { id: string; type: string; peer: HMSPeer } - )[] = useSelector((state: RootState) => { + const notifications = useSelector((state: RootState) => { // Latest notification will be at 0th index. const allNotifications = state.app.notifications; - let list = []; + let list: typeof allNotifications = []; if (isLocalScreenShared) { list.push(LOCAL_SCREENSHARE_PAYLOAD); @@ -117,6 +115,11 @@ export const HMSNotifications: React.FC = () => { autoDismiss={atTop} dismissDelay={10000} /> + ) : notification.type === NotificationTypes.RECORDING_START_FAILED ? ( + ) : null} ); diff --git a/packages/react-native-room-kit/src/components/HMSRecordingStartFailedNotification.tsx b/packages/react-native-room-kit/src/components/HMSRecordingStartFailedNotification.tsx new file mode 100644 index 000000000..e518d56f8 --- /dev/null +++ b/packages/react-native-room-kit/src/components/HMSRecordingStartFailedNotification.tsx @@ -0,0 +1,79 @@ +import * as React from 'react'; + +import { HMSNotification } from './HMSNotification'; +import { HandIcon, PersonIcon, RecordingIcon } from '../Icons'; +import { useDispatch, useSelector } from 'react-redux'; +import { useHMSInstance, useHMSLayoutConfig, useHMSRoomColorPalette, useHMSRoomStyleSheet } from '../hooks-util'; +import type { RootState } from '../redux'; +import { removeNotification } from '../redux/actions'; +import { StyleSheet, Text, TouchableHighlight } from 'react-native'; + +export interface HMSRecordingStartFailedNotificationProps { + id: string; + autoDismiss?: boolean; + dismissDelay?: number; +} + +export const HMSRecordingStartFailedNotification: React.FC< + HMSRecordingStartFailedNotificationProps +> = ({ id, autoDismiss, dismissDelay }) => { + const dispatch = useDispatch(); + const hmsInstance = useHMSInstance(); + + const { secondary_dim: secondaryDimColor } = useHMSRoomColorPalette(); + + const hmsRoomStyles = useHMSRoomStyleSheet((theme, typography) => ({ + button: { + backgroundColor: theme.palette.secondary_default, + }, + buttonText: { + color: theme.palette.on_secondary_high, + fontFamily: `${typography.font_family}-SemiBold`, + }, + })); + + const dismissNotification = () => { + dispatch(removeNotification(id)); + }; + + const retryStartRecording = async () => { + dismissNotification(); + // await hmsInstance.changeRoleOfPeer(peer, onStageRole, false); + }; + + return ( + } + text={`Recording failed to start`} + dismissDelay={dismissDelay} + autoDismiss={autoDismiss} + cta={ + + + Retry + + + } + onDismiss={dismissNotification} + /> + ); +}; + +const styles = StyleSheet.create({ + button: { + paddingVertical: 8, + paddingHorizontal: 16, + borderRadius: 8, + marginRight: 16, + }, + buttonText: { + fontSize: 14, + lineHeight: 20, + letterSpacing: 0.25, + }, +}); diff --git a/packages/react-native-room-kit/src/hooks-util.ts b/packages/react-native-room-kit/src/hooks-util.ts index b42340bce..3164e7171 100644 --- a/packages/react-native-room-kit/src/hooks-util.ts +++ b/packages/react-native-room-kit/src/hooks-util.ts @@ -2191,3 +2191,22 @@ export const useHMSConferencingScreenConfig = ( return selector(conferencingScreenConfig); }, equalityFn); }; + +export const useStartRecording = () => { + const dispatch = useDispatch(); + const hmsInstance = useHMSInstance(); + const reduxState = useStore(); + + const startRecording = useCallback(() => { + dispatch(setStartingOrStoppingRecording(true)); + hmsInstance + .startRTMPOrRecording({ record: true }) + .then(() => { + const allNotifications = reduxState.getState().app.notifications; + allNotifications.find((notification) => notification.type === NotificationTypes.RECORDING_START_FAILED); + }) + .catch(() => dispatch(setStartingOrStoppingRecording(false))); + }, [hmsInstance]); + + return { startRecording }; +} \ No newline at end of file diff --git a/packages/react-native-room-kit/src/redux/reducers/appState.ts b/packages/react-native-room-kit/src/redux/reducers/appState.ts index 705136be3..6003b33f0 100644 --- a/packages/react-native-room-kit/src/redux/reducers/appState.ts +++ b/packages/react-native-room-kit/src/redux/reducers/appState.ts @@ -4,6 +4,7 @@ import type { PeerTrackNode } from '../../utils/types'; import { SUPPORTED_ASPECT_RATIOS, ModalTypes } from '../../utils/types'; import { PipModes } from '../../utils/types'; import { + HMSException, HMSLocalAudioStats, HMSLocalVideoStats, HMSPeer, @@ -11,12 +12,18 @@ import { HMSRemoteVideoStats, } from '@100mslive/react-native-hms'; import { MeetingState } from '../../types'; +import { NotificationTypes } from '../../utils'; type ActionType = { payload: { [key: string]: any }; type: String; }; +type Notification = + | { id: string; type: string; } + | { id: string; type: string; peer: HMSPeer; } + | { id: string; type: string; error: HMSException; } + type IntialStateType = { peerState: PeerTrackNode[]; pipModeStatus: PipModes; @@ -48,7 +55,7 @@ type IntialStateType = { startingOrStoppingRecording: boolean; fullScreenPeerTrackNode: null | PeerTrackNode; screensharePeerTrackNodes: PeerTrackNode[]; - notifications: { id: string; type: string; peer: HMSPeer }[]; + notifications: Notification[]; activeChatBottomSheetTab: (typeof ChatBottomSheetTabs)[number]; chatFilterSheetVisible: boolean; }; @@ -77,7 +84,7 @@ const INITIAL_STATE: IntialStateType = { startingOrStoppingRecording: false, fullScreenPeerTrackNode: null, screensharePeerTrackNodes: [], - notifications: [], + notifications: [{ id: NotificationTypes.RECORDING_START_FAILED, type: NotificationTypes.RECORDING_START_FAILED }], activeChatBottomSheetTab: ChatBottomSheetTabs[0], chatFilterSheetVisible: false, }; diff --git a/packages/react-native-room-kit/src/utils.ts b/packages/react-native-room-kit/src/utils.ts index 1c49b0e81..6e881d5d9 100644 --- a/packages/react-native-room-kit/src/utils.ts +++ b/packages/react-native-room-kit/src/utils.ts @@ -27,4 +27,5 @@ export enum NotificationTypes { ROLE_CHANGE_DECLINED = 'role_change_declined', HAND_RAISE = 'hand_raise', LOCAL_SCREENSHARE = 'local_screenshare', + RECORDING_START_FAILED = 'recording_start_failed', } From 9a7c8509e0a2fe24b6529fe4145a8f06d200acc6 Mon Sep 17 00:00:00 2001 From: Jatin Nagar Date: Fri, 13 Oct 2023 14:05:52 +0530 Subject: [PATCH 04/21] refactoring and using `useStartRecording` hook --- .../src/components/HMSNotifications.tsx | 1 - .../HMSRecordingStartFailedNotification.tsx | 16 +++--- .../components/RoomSettingsModalContent.tsx | 8 +-- .../react-native-room-kit/src/hooks-util.ts | 55 ++++++++++++++++--- .../src/redux/actions/index.ts | 9 +-- .../src/redux/reducers/appState.ts | 7 +-- packages/react-native-room-kit/src/types.ts | 7 +++ 7 files changed, 70 insertions(+), 33 deletions(-) diff --git a/packages/react-native-room-kit/src/components/HMSNotifications.tsx b/packages/react-native-room-kit/src/components/HMSNotifications.tsx index 3e3469cf7..65af31f4d 100644 --- a/packages/react-native-room-kit/src/components/HMSNotifications.tsx +++ b/packages/react-native-room-kit/src/components/HMSNotifications.tsx @@ -1,7 +1,6 @@ import * as React from 'react'; import { shallowEqual, useSelector } from 'react-redux'; import { StyleSheet, View } from 'react-native'; -import type { HMSPeer } from '@100mslive/react-native-hms'; import type { RootState } from '../redux'; import { HMSLocalScreenshareNotification } from './HMSLocalScreenshareNotification'; diff --git a/packages/react-native-room-kit/src/components/HMSRecordingStartFailedNotification.tsx b/packages/react-native-room-kit/src/components/HMSRecordingStartFailedNotification.tsx index e518d56f8..9fee85eb4 100644 --- a/packages/react-native-room-kit/src/components/HMSRecordingStartFailedNotification.tsx +++ b/packages/react-native-room-kit/src/components/HMSRecordingStartFailedNotification.tsx @@ -1,10 +1,9 @@ import * as React from 'react'; import { HMSNotification } from './HMSNotification'; -import { HandIcon, PersonIcon, RecordingIcon } from '../Icons'; -import { useDispatch, useSelector } from 'react-redux'; -import { useHMSInstance, useHMSLayoutConfig, useHMSRoomColorPalette, useHMSRoomStyleSheet } from '../hooks-util'; -import type { RootState } from '../redux'; +import { RecordingIcon } from '../Icons'; +import { useDispatch } from 'react-redux'; +import { useHMSRoomColorPalette, useHMSRoomStyleSheet, useStartRecording } from '../hooks-util'; import { removeNotification } from '../redux/actions'; import { StyleSheet, Text, TouchableHighlight } from 'react-native'; @@ -18,7 +17,6 @@ export const HMSRecordingStartFailedNotification: React.FC< HMSRecordingStartFailedNotificationProps > = ({ id, autoDismiss, dismissDelay }) => { const dispatch = useDispatch(); - const hmsInstance = useHMSInstance(); const { secondary_dim: secondaryDimColor } = useHMSRoomColorPalette(); @@ -32,13 +30,13 @@ export const HMSRecordingStartFailedNotification: React.FC< }, })); - const dismissNotification = () => { - dispatch(removeNotification(id)); - }; + const dismissNotification = () => dispatch(removeNotification(id)); + + const { startRecording } = useStartRecording(); const retryStartRecording = async () => { dismissNotification(); - // await hmsInstance.changeRoleOfPeer(peer, onStageRole, false); + startRecording(); }; return ( diff --git a/packages/react-native-room-kit/src/components/RoomSettingsModalContent.tsx b/packages/react-native-room-kit/src/components/RoomSettingsModalContent.tsx index 1873f4348..2a1e95611 100644 --- a/packages/react-native-room-kit/src/components/RoomSettingsModalContent.tsx +++ b/packages/react-native-room-kit/src/components/RoomSettingsModalContent.tsx @@ -21,6 +21,7 @@ import { useHMSLayoutConfig, useHMSRoomStyleSheet, useShowChatAndParticipants, + useStartRecording, } from '../hooks-util'; import { useCanPublishScreen, useHMSActions } from '../hooks-sdk'; import { RoomSettingsModalDebugModeContent } from './RoomSettingsModalDebugModeContent'; @@ -134,6 +135,8 @@ export const RoomSettingsModalContent: React.FC< (state: RootState) => !!state.hmsStates.room?.browserRecordingState?.running ); + const { startRecording } = useStartRecording(); + const handleRecordingTogglePress = () => { if (isRecordingOn) { registerOnModalHideAction(() => { @@ -141,10 +144,7 @@ export const RoomSettingsModalContent: React.FC< }); closeRoomSettingsModal(); } else { - dispatch(setStartingOrStoppingRecording(true)); - hmsInstance - .startRTMPOrRecording({ record: true }) - .catch(() => dispatch(setStartingOrStoppingRecording(false))); + startRecording(); closeRoomSettingsModal(); } }; diff --git a/packages/react-native-room-kit/src/hooks-util.ts b/packages/react-native-room-kit/src/hooks-util.ts index 6f1b33e2f..bd1edbb81 100644 --- a/packages/react-native-room-kit/src/hooks-util.ts +++ b/packages/react-native-room-kit/src/hooks-util.ts @@ -1821,7 +1821,6 @@ export const useFilteredParticipants = (filterText: string) => { : list; if (Array.isArray(filteredList) && filteredList.length > 0) { - filteredHandRaisedPeers.push(filteredList); const offStageRoleTotalCount = offStageParticipantsTotalCounts[role.name!]; @@ -2194,17 +2193,59 @@ export const useStartRecording = () => { const dispatch = useDispatch(); const hmsInstance = useHMSInstance(); const reduxState = useStore(); + // const isRecordingOn = useSelector( + // (state: RootState) => !!state.hmsStates.room?.browserRecordingState?.running + // ); + + const removeRecordingNotification = useCallback(() => { + const allNotifications = reduxState.getState().app.notifications; + const recordingFailedNotification = allNotifications.find( + (notification) => + notification.type === NotificationTypes.RECORDING_START_FAILED + ); + + if (recordingFailedNotification) { + dispatch(removeNotification(recordingFailedNotification.id)); + } + }, []); + + const addRecordingNotification = useCallback(() => { + const allNotifications = reduxState.getState().app.notifications; + const recordingFailedNotification = allNotifications.find( + (notification) => + notification.type === NotificationTypes.RECORDING_START_FAILED + ); + + if (!recordingFailedNotification) { + dispatch( + addNotification({ + id: NotificationTypes.RECORDING_START_FAILED, + type: NotificationTypes.RECORDING_START_FAILED, + }) + ); + } + }, []); const startRecording = useCallback(() => { dispatch(setStartingOrStoppingRecording(true)); + hmsInstance .startRTMPOrRecording({ record: true }) .then(() => { - const allNotifications = reduxState.getState().app.notifications; - allNotifications.find((notification) => notification.type === NotificationTypes.RECORDING_START_FAILED); + removeRecordingNotification(); }) - .catch(() => dispatch(setStartingOrStoppingRecording(false))); - }, [hmsInstance]); + .catch((error) => { + batch(() => { + dispatch(setStartingOrStoppingRecording(false)); + // DOUBT: show error when it is because of "Recording" is already started? + addRecordingNotification(); + }); + }); + }, [removeRecordingNotification, addRecordingNotification, hmsInstance]); - return { startRecording }; -} \ No newline at end of file + return { + startRecording, + removeRecordingNotification, + addRecordingNotification, + }; +}; diff --git a/packages/react-native-room-kit/src/redux/actions/index.ts b/packages/react-native-room-kit/src/redux/actions/index.ts index a7be232f0..1d752024e 100644 --- a/packages/react-native-room-kit/src/redux/actions/index.ts +++ b/packages/react-native-room-kit/src/redux/actions/index.ts @@ -23,6 +23,7 @@ import type { } from '../../utils/types'; import actionTypes, { HmsStateActionTypes } from '../actionTypes'; import { MeetingState } from '../../types'; +import type { Notification } from '../../types'; export const setPrebuiltData = (data: { roomCode: string; @@ -306,16 +307,12 @@ export const updateScreenshareTile = ( payload: data, }); -export const addNotification = (notification: { - id: string; - type: string; - peer: HMSPeer; -}) => ({ +export const addNotification = (notification: Notification) => ({ type: actionTypes.ADD_NOTIFICATION, payload: { notification }, }); -export const removeNotification = (notificationId: string) => ({ +export const removeNotification = (notificationId: Notification['id']) => ({ type: actionTypes.REMOVE_NOTIFICATION, payload: { id: notificationId }, }); diff --git a/packages/react-native-room-kit/src/redux/reducers/appState.ts b/packages/react-native-room-kit/src/redux/reducers/appState.ts index 6003b33f0..2585dd194 100644 --- a/packages/react-native-room-kit/src/redux/reducers/appState.ts +++ b/packages/react-native-room-kit/src/redux/reducers/appState.ts @@ -4,7 +4,6 @@ import type { PeerTrackNode } from '../../utils/types'; import { SUPPORTED_ASPECT_RATIOS, ModalTypes } from '../../utils/types'; import { PipModes } from '../../utils/types'; import { - HMSException, HMSLocalAudioStats, HMSLocalVideoStats, HMSPeer, @@ -12,6 +11,7 @@ import { HMSRemoteVideoStats, } from '@100mslive/react-native-hms'; import { MeetingState } from '../../types'; +import type { Notification } from '../../types'; import { NotificationTypes } from '../../utils'; type ActionType = { @@ -19,11 +19,6 @@ type ActionType = { type: String; }; -type Notification = - | { id: string; type: string; } - | { id: string; type: string; peer: HMSPeer; } - | { id: string; type: string; error: HMSException; } - type IntialStateType = { peerState: PeerTrackNode[]; pipModeStatus: PipModes; diff --git a/packages/react-native-room-kit/src/types.ts b/packages/react-native-room-kit/src/types.ts index 7a8e0ff44..562c06071 100644 --- a/packages/react-native-room-kit/src/types.ts +++ b/packages/react-native-room-kit/src/types.ts @@ -1,3 +1,5 @@ +import type { HMSException, HMSPeer } from "@100mslive/react-native-hms"; + export enum MeetingState { NOT_JOINED, IN_PREVIEW, @@ -5,3 +7,8 @@ export enum MeetingState { MEETING_ENDED, ERROR, } + +export type Notification = + | { id: string; type: string; } + | { id: string; type: string; peer: HMSPeer; } + | { id: string; type: string; error: HMSException; } \ No newline at end of file From 57ddedcbb8a622c9462efb002e4c17a375d8fcf1 Mon Sep 17 00:00:00 2001 From: Jatin Nagar Date: Thu, 19 Oct 2023 00:24:32 +0530 Subject: [PATCH 05/21] refactor(sdk): :recycle: removed `emitRequiredKeysError` calls on ios sdk --- packages/react-native-hms/ios/HMSManager.m | 50 ++++-- .../react-native-hms/ios/HMSManager.swift | 40 ++--- packages/react-native-hms/ios/HMSRNSDK.swift | 167 +++++++++--------- 3 files changed, 144 insertions(+), 113 deletions(-) diff --git a/packages/react-native-hms/ios/HMSManager.m b/packages/react-native-hms/ios/HMSManager.m index 30f1e1c14..ac901d9c2 100644 --- a/packages/react-native-hms/ios/HMSManager.m +++ b/packages/react-native-hms/ios/HMSManager.m @@ -12,8 +12,14 @@ @interface RCT_EXTERN_MODULE (HMSManager, RCTEventEmitter) RCT_EXTERN_METHOD(cancelPreview : (NSDictionary)data : (RCTPromiseResolveBlock)resolve : (RCTPromiseRejectBlock)reject) -RCT_EXTERN_METHOD(setLocalMute : (NSDictionary)isMute) -RCT_EXTERN_METHOD(setLocalVideoMute : (NSDictionary)isMute) +RCT_EXTERN_METHOD(setLocalMute + : (NSDictionary)isMute + : (RCTPromiseResolveBlock)resolve + : (RCTPromiseRejectBlock)reject) +RCT_EXTERN_METHOD(setLocalVideoMute + : (NSDictionary)isMute + : (RCTPromiseResolveBlock)resolve + : (RCTPromiseRejectBlock)reject) RCT_EXTERN_METHOD(sendBroadcastMessage : (NSDictionary)data : (RCTPromiseResolveBlock)resolve @@ -26,7 +32,10 @@ @interface RCT_EXTERN_MODULE (HMSManager, RCTEventEmitter) : (NSDictionary)data : (RCTPromiseResolveBlock)resolve : (RCTPromiseRejectBlock)reject) -RCT_EXTERN_METHOD(setPlaybackAllowed : (NSDictionary)data) +RCT_EXTERN_METHOD(setPlaybackAllowed + : (NSDictionary)data + : (RCTPromiseResolveBlock)resolve + : (RCTPromiseRejectBlock)reject) RCT_EXTERN_METHOD(removePeer : (NSDictionary)data : (RCTPromiseResolveBlock)resolve @@ -54,7 +63,10 @@ @interface RCT_EXTERN_MODULE (HMSManager, RCTEventEmitter) : (RCTPromiseResolveBlock)resolve : (RCTPromiseRejectBlock)reject) RCT_EXTERN_METHOD(switchCamera : (NSDictionary)data) -RCT_EXTERN_METHOD(setVolume : (NSDictionary)data) +RCT_EXTERN_METHOD(setVolume + : (NSDictionary)data + : (RCTPromiseResolveBlock)resolve + : (RCTPromiseRejectBlock)reject) RCT_EXTERN_METHOD(build : (NSDictionary)data : (RCTPromiseResolveBlock)resolve @@ -63,7 +75,10 @@ @interface RCT_EXTERN_MODULE (HMSManager, RCTEventEmitter) : (NSDictionary)data : (RCTPromiseResolveBlock)resolve : (RCTPromiseRejectBlock)reject) -RCT_EXTERN_METHOD(setPlaybackForAllAudio : (NSDictionary)mute) +RCT_EXTERN_METHOD(setPlaybackForAllAudio + : (NSDictionary)mute + : (RCTPromiseResolveBlock)resolve + : (RCTPromiseRejectBlock)reject) RCT_EXTERN_METHOD(remoteMuteAllAudio : (NSDictionary)data : (RCTPromiseResolveBlock)resolve @@ -132,10 +147,22 @@ @interface RCT_EXTERN_MODULE (HMSManager, RCTEventEmitter) : (NSDictionary)data : (RCTPromiseResolveBlock)resolve : (RCTPromiseRejectBlock)reject) -RCT_EXTERN_METHOD(setAudioShareVolume : (NSDictionary)data) -RCT_EXTERN_METHOD(stopAudioShare : (NSDictionary)data) -RCT_EXTERN_METHOD(resumeAudioShare : (NSDictionary)data) -RCT_EXTERN_METHOD(pauseAudioShare : (NSDictionary)data) +RCT_EXTERN_METHOD(setAudioShareVolume + : (NSDictionary)data + : (RCTPromiseResolveBlock)resolve + : (RCTPromiseRejectBlock)reject) +RCT_EXTERN_METHOD(stopAudioShare + : (NSDictionary)data + : (RCTPromiseResolveBlock)resolve + : (RCTPromiseRejectBlock)reject) +RCT_EXTERN_METHOD(resumeAudioShare + : (NSDictionary)data + : (RCTPromiseResolveBlock)resolve + : (RCTPromiseRejectBlock)reject) +RCT_EXTERN_METHOD(pauseAudioShare + : (NSDictionary)data + : (RCTPromiseResolveBlock)resolve + : (RCTPromiseRejectBlock)reject) RCT_EXTERN_METHOD(audioShareIsPlaying : (NSDictionary)data : (RCTPromiseResolveBlock)resolve @@ -182,7 +209,10 @@ @interface RCT_EXTERN_MODULE (HMSManager, RCTEventEmitter) : (NSDictionary)data : (RCTPromiseResolveBlock)resolve : (RCTPromiseRejectBlock)reject) -RCT_EXTERN_METHOD(restrictData : (NSDictionary)data) +RCT_EXTERN_METHOD(restrictData + : (NSDictionary)data + : (RCTPromiseResolveBlock)resolve + : (RCTPromiseRejectBlock)reject) RCT_EXTERN_METHOD(getAuthTokenByRoomCode : (NSDictionary)data : (RCTPromiseResolveBlock)resolve diff --git a/packages/react-native-hms/ios/HMSManager.swift b/packages/react-native-hms/ios/HMSManager.swift index 40395825c..eedb72475 100644 --- a/packages/react-native-hms/ios/HMSManager.swift +++ b/packages/react-native-hms/ios/HMSManager.swift @@ -125,17 +125,17 @@ class HMSManager: RCTEventEmitter { // MARK: - Audio & Video Actions @objc - func setLocalMute(_ data: NSDictionary) { + func setLocalMute(_ data: NSDictionary, _ resolve: RCTPromiseResolveBlock?, _ reject: RCTPromiseRejectBlock?) { let hms = HMSHelper.getHms(data, hmsCollection) - hms?.setLocalMute(data) + hms?.setLocalMute(data, resolve, reject) } @objc - func setLocalVideoMute(_ data: NSDictionary) { + func setLocalVideoMute(_ data: NSDictionary, _ resolve: RCTPromiseResolveBlock?, _ reject: RCTPromiseRejectBlock?) { let hms = HMSHelper.getHms(data, hmsCollection) - hms?.setLocalVideoMute(data) + hms?.setLocalVideoMute(data, resolve, reject) } @objc @@ -157,10 +157,10 @@ class HMSManager: RCTEventEmitter { } @objc - func setPlaybackAllowed(_ data: NSDictionary) { + func setPlaybackAllowed(_ data: NSDictionary, _ resolve: RCTPromiseResolveBlock?, _ reject: RCTPromiseRejectBlock?) { let hms = HMSHelper.getHms(data, hmsCollection) - hms?.setPlaybackAllowed(data) + hms?.setPlaybackAllowed(data, resolve, reject) } @objc @@ -171,10 +171,10 @@ class HMSManager: RCTEventEmitter { } @objc - func setPlaybackForAllAudio(_ data: NSDictionary) { + func setPlaybackForAllAudio(_ data: NSDictionary, _ resolve: RCTPromiseResolveBlock?, _ reject: RCTPromiseRejectBlock?) { let hms = HMSHelper.getHms(data, hmsCollection) - hms?.setPlaybackForAllAudio(data) + hms?.setPlaybackForAllAudio(data, resolve, reject) } @objc @@ -185,10 +185,10 @@ class HMSManager: RCTEventEmitter { } @objc - func setVolume(_ data: NSDictionary) { + func setVolume(_ data: NSDictionary, _ resolve: RCTPromiseResolveBlock?, _ reject: RCTPromiseRejectBlock?) { let hms = HMSHelper.getHms(data, hmsCollection) - hms?.setVolume(data) + hms?.setVolume(data, resolve, reject) } @objc @@ -398,31 +398,31 @@ class HMSManager: RCTEventEmitter { } @objc - func setAudioShareVolume(_ data: NSDictionary) { + func setAudioShareVolume(_ data: NSDictionary, _ resolve: RCTPromiseResolveBlock?, _ reject: RCTPromiseRejectBlock?) { let hms = HMSHelper.getHms(data, hmsCollection) - hms?.setAudioShareVolume(data) + hms?.setAudioShareVolume(data, resolve, reject) } @objc - func stopAudioShare(_ data: NSDictionary) { + func stopAudioShare(_ data: NSDictionary, _ resolve: RCTPromiseResolveBlock?, _ reject: RCTPromiseRejectBlock?) { let hms = HMSHelper.getHms(data, hmsCollection) - hms?.stopAudioShare(data) + hms?.stopAudioShare(data, resolve, reject) } @objc - func resumeAudioShare(_ data: NSDictionary) { + func resumeAudioShare(_ data: NSDictionary, _ resolve: RCTPromiseResolveBlock?, _ reject: RCTPromiseRejectBlock?) { let hms = HMSHelper.getHms(data, hmsCollection) - hms?.resumeAudioShare(data) + hms?.resumeAudioShare(data, resolve, reject) } @objc - func pauseAudioShare(_ data: NSDictionary) { + func pauseAudioShare(_ data: NSDictionary, _ resolve: RCTPromiseResolveBlock?, _ reject: RCTPromiseRejectBlock?) { let hms = HMSHelper.getHms(data, hmsCollection) - hms?.pauseAudioShare(data) + hms?.pauseAudioShare(data, resolve, reject) } @objc @@ -497,10 +497,10 @@ class HMSManager: RCTEventEmitter { // MARK: - Restrict sending whole HMSRole object @objc - func restrictData(_ data: NSDictionary) { + func restrictData(_ data: NSDictionary, _ resolve: RCTPromiseResolveBlock?, _ reject: RCTPromiseRejectBlock?) { let hms = HMSHelper.getHms(data, hmsCollection) - hms?.restrictData(data) + hms?.restrictData(data, resolve, reject) } // MARK: - Room Code Auth Token API diff --git a/packages/react-native-hms/ios/HMSRNSDK.swift b/packages/react-native-hms/ios/HMSRNSDK.swift index 8db5ad3a7..e68c2b4d2 100644 --- a/packages/react-native-hms/ios/HMSRNSDK.swift +++ b/packages/react-native-hms/ios/HMSRNSDK.swift @@ -125,7 +125,6 @@ class HMSRNSDK: HMSUpdateListener, HMSPreviewListener { guard let role = data.value(forKey: "role") as? String else { let errorMessage = "previewForRole: " + HMSHelper.getUnavailableRequiredKey(data, ["role"]) - emitRequiredKeysError(errorMessage) reject?(errorMessage, errorMessage, nil) return } @@ -229,44 +228,48 @@ class HMSRNSDK: HMSUpdateListener, HMSPreviewListener { } } - func setLocalMute(_ data: NSDictionary) { + func setLocalMute(_ data: NSDictionary, _ resolve: RCTPromiseResolveBlock?, _ reject: RCTPromiseRejectBlock?) { guard let isMute = data.value(forKey: "isMute") as? Bool else { let errorMessage = "setLocalMute: " + HMSHelper.getUnavailableRequiredKey(data, ["isMute"]) - emitRequiredKeysError(errorMessage) + reject?(errorMessage, errorMessage, nil) return } DispatchQueue.main.async { [weak self] in if let audioTrack = self?.hms?.localPeer?.localAudioTrack() { audioTrack.setMute(isMute) - } else if let tracks = self?.previewForRoleTracks { - if let audioTrack = tracks.first(where: { $0.kind == HMSTrackKind.audio }) as? HMSLocalAudioTrack { - audioTrack.setMute(isMute) - } + resolve?(true) + } else if let tracks = self?.previewForRoleTracks, let audioTrack = tracks.first(where: { $0.kind == HMSTrackKind.audio }) as? HMSLocalAudioTrack { + audioTrack.setMute(isMute) + resolve?(true) } else { - print(#function, "No local audio track available for setting mute state.") + let errorMessage = "setLocalMute: No local audio track available for setting mute state." + print(#function, errorMessage) + reject?(errorMessage, errorMessage, nil) } } } - func setLocalVideoMute(_ data: NSDictionary) { + func setLocalVideoMute(_ data: NSDictionary, _ resolve: RCTPromiseResolveBlock?, _ reject: RCTPromiseRejectBlock?) { guard let isMute = data.value(forKey: "isMute") as? Bool else { let errorMessage = "setLocalVideoMute: " + HMSHelper.getUnavailableRequiredKey(data, ["isMute"]) - emitRequiredKeysError(errorMessage) + reject?(errorMessage, errorMessage, nil) return } DispatchQueue.main.async { [weak self] in if let videoTrack = self?.hms?.localPeer?.localVideoTrack() { videoTrack.setMute(isMute) - } else if let tracks = self?.previewForRoleTracks { - if let videoTrack = tracks.first(where: { $0.kind == HMSTrackKind.video }) as? HMSLocalVideoTrack { - videoTrack.setMute(isMute) - } + resolve?(true) + } else if let tracks = self?.previewForRoleTracks, let videoTrack = tracks.first(where: { $0.kind == HMSTrackKind.video }) as? HMSLocalVideoTrack { + videoTrack.setMute(isMute) + resolve?(true) } else { - print(#function, "No local video track available for setting mute state.") + let errorMessage = "setLocalVideoMute: No local video track available for setting mute state." + print(#function, errorMessage) + reject?(errorMessage, errorMessage, nil) } } } @@ -288,24 +291,27 @@ class HMSRNSDK: HMSUpdateListener, HMSPreviewListener { func leave(_ resolve: RCTPromiseResolveBlock?, _ reject: RCTPromiseRejectBlock?) { DispatchQueue.main.async { [weak self] in guard let strongSelf = self else { - print(#function, "Could not find reference to self while executing Room leave") + let errorMessage = "\(#function): Could not find reference to self while executing Room leave" + print(#function, errorMessage) + reject?(errorMessage, errorMessage, nil) return } strongSelf.hms?.leave { [weak self] success, error in guard let strongSelf = self else { - print(#function, "Could not find reference to self when callback is received while executing Room leave") + let errorMessage = "\(#function): Could not find reference to self when callback is received while executing Room leave" + print(#function, errorMessage) + reject?(errorMessage, errorMessage, nil) return } - if success { + if let nonnilError = error { + reject?(nonnilError.localizedDescription, nonnilError.localizedDescription, nil) + } else if success { resolve?(["success": success]) strongSelf.cleanup() // resetting states and doing data cleanup } else { - if strongSelf.eventsEnableStatus[HMSConstants.ON_ERROR] == true { - strongSelf.delegate?.emitEvent(HMSConstants.ON_ERROR, ["error": HMSDecoder.getError(error), "id": strongSelf.id]) - } reject?("error in leave", "error in leave", nil) } } @@ -316,7 +322,6 @@ class HMSRNSDK: HMSUpdateListener, HMSPreviewListener { guard let message = data.value(forKey: "message") as? String else { let errorMessage = "sendBroadcastMessage: " + HMSHelper.getUnavailableRequiredKey(data, ["message"]) - emitRequiredKeysError(errorMessage) reject?(errorMessage, errorMessage, nil) return } @@ -341,7 +346,6 @@ class HMSRNSDK: HMSUpdateListener, HMSPreviewListener { let targetedRoles = data.value(forKey: "roles") as? [String] else { let errorMessage = "sendGroupMessage: " + HMSHelper.getUnavailableRequiredKey(data, ["message", "roles"]) - emitRequiredKeysError(errorMessage) reject?(errorMessage, errorMessage, nil) return } @@ -366,7 +370,6 @@ class HMSRNSDK: HMSUpdateListener, HMSPreviewListener { let peerId = data.value(forKey: "peerId") as? String else { let errorMessage = "sendDirectMessage: " + HMSHelper.getUnavailableRequiredKey(data, ["message", "peerId"]) - emitRequiredKeysError(errorMessage) reject?(errorMessage, errorMessage, nil) return } @@ -394,7 +397,6 @@ class HMSRNSDK: HMSUpdateListener, HMSPreviewListener { guard let request = self?.recentRoleChangeRequest else { let errorMessage = "acceptRoleChange: recentRoleChangeRequest not found" - self?.emitRequiredKeysError(errorMessage) reject?(errorMessage, errorMessage, nil) return } @@ -417,7 +419,6 @@ class HMSRNSDK: HMSUpdateListener, HMSPreviewListener { let role = data.value(forKey: "role") as? String else { let errorMessage = "changeRole: " + HMSHelper.getUnavailableRequiredKey(data, ["peerId", "role"]) - emitRequiredKeysError(errorMessage) reject?(errorMessage, errorMessage, nil) return } @@ -452,7 +453,6 @@ class HMSRNSDK: HMSUpdateListener, HMSPreviewListener { guard let toRoleString = data.object(forKey: "toRole") as? String else { let errorMessage = "changeRolesOfAllPeers: " + HMSHelper.getUnavailableRequiredKey(data, ["toRole"]) - emitRequiredKeysError(errorMessage) reject?(errorMessage, errorMessage, nil) return } @@ -461,7 +461,6 @@ class HMSRNSDK: HMSUpdateListener, HMSPreviewListener { guard let toRole = HMSHelper.getRoleFromRoleName(toRoleString, roles: self?.hms?.roles) else { let errorMessage = "changeRolesOfAllPeers: " + HMSHelper.getUnavailableRequiredKey(data, ["toRole"]) - self?.emitRequiredKeysError(errorMessage) reject?(errorMessage, errorMessage, nil) return } @@ -487,7 +486,6 @@ class HMSRNSDK: HMSUpdateListener, HMSPreviewListener { guard let trackId = data.value(forKey: "trackId") as? String else { let errorMessage = "changeTrackState: " + HMSHelper.getUnavailableRequiredKey(data, ["trackId"]) - emitRequiredKeysError(errorMessage) reject?(errorMessage, errorMessage, nil) return } @@ -517,7 +515,6 @@ class HMSRNSDK: HMSUpdateListener, HMSPreviewListener { guard let mute = data.value(forKey: "mute") as? Bool else { let errorMessage = "changeTrackStateForRoles: " + HMSHelper.getUnavailableRequiredKey(data, ["mute"]) - emitRequiredKeysError(errorMessage) reject?(errorMessage, errorMessage, nil) return } @@ -550,7 +547,6 @@ class HMSRNSDK: HMSUpdateListener, HMSPreviewListener { guard let trackId = data.value(forKey: "trackId") as? String else { let errorMessage = "isMute: " + HMSHelper.getUnavailableRequiredKey(data, ["trackId"]) - emitRequiredKeysError(errorMessage) reject?(errorMessage, errorMessage, nil) return } @@ -580,7 +576,6 @@ class HMSRNSDK: HMSUpdateListener, HMSPreviewListener { guard let peerId = data.value(forKey: "peerId") as? String else { let errorMessage = "removePeer: " + HMSHelper.getUnavailableRequiredKey(data, ["peerId"]) - emitRequiredKeysError(errorMessage) reject?(errorMessage, errorMessage, nil) return } @@ -612,7 +607,6 @@ class HMSRNSDK: HMSUpdateListener, HMSPreviewListener { let reason = data.value(forKey: "reason") as? String else { let errorMessage = "endRoom: " + HMSHelper.getUnavailableRequiredKey(data, ["lock", "reason"]) - emitRequiredKeysError(errorMessage) reject?(errorMessage, errorMessage, nil) return } @@ -633,7 +627,6 @@ class HMSRNSDK: HMSUpdateListener, HMSPreviewListener { guard let trackId = data.value(forKey: "trackId") as? String else { let errorMessage = "isPlaybackAllowed: " + HMSHelper.getUnavailableRequiredKey(data, ["trackId"]) - emitRequiredKeysError(errorMessage) reject?(errorMessage, errorMessage, nil) return } @@ -660,29 +653,35 @@ class HMSRNSDK: HMSUpdateListener, HMSPreviewListener { } } - func setPlaybackAllowed(_ data: NSDictionary) { + func setPlaybackAllowed(_ data: NSDictionary, _ resolve: RCTPromiseResolveBlock?, _ reject: RCTPromiseRejectBlock?) { guard let trackId = data.value(forKey: "trackId") as? String, let playbackAllowed = data.value(forKey: "playbackAllowed") as? Bool else { let errorMessage = "setPlaybackAllowed: " + HMSHelper.getUnavailableRequiredKey(data, ["trackId", "playbackAllowed"]) - emitRequiredKeysError(errorMessage) + reject?(errorMessage, errorMessage, nil) return } + DispatchQueue.main.async { [weak self] in guard let remotePeers = self?.hms?.remotePeers else { + let errorMessage = "setPlaybackAllowed: No remote peers found" + reject?(errorMessage, errorMessage, nil) return } + let remoteAudioTrack = HMSHelper.getRemoteAudioTrackFromTrackId(trackId, remotePeers) let remoteVideoTrack = HMSHelper.getRemoteVideoTrackFromTrackId(trackId, remotePeers) + if remoteAudioTrack != nil { - if playbackAllowed { - remoteAudioTrack?.setPlaybackAllowed(playbackAllowed) - } else { - remoteAudioTrack?.setPlaybackAllowed(playbackAllowed) - } + remoteAudioTrack?.setPlaybackAllowed(playbackAllowed) + resolve?(true) } else if remoteVideoTrack != nil { remoteVideoTrack?.setPlaybackAllowed(playbackAllowed) + resolve?(true) + } else { + let errorMessage = "setPlaybackAllowed: No remote audio or video track to set playback" + reject?(errorMessage, errorMessage, nil) } } } @@ -691,7 +690,6 @@ class HMSRNSDK: HMSUpdateListener, HMSPreviewListener { guard let metadata = data.value(forKey: "metadata") as? String else { let errorMessage = "changeMetadata: " + HMSHelper.getUnavailableRequiredKey(data, ["metadata"]) - emitRequiredKeysError(errorMessage) reject?(errorMessage, errorMessage, nil) return } @@ -707,23 +705,27 @@ class HMSRNSDK: HMSUpdateListener, HMSPreviewListener { }) } - func setVolume(_ data: NSDictionary) { + func setVolume(_ data: NSDictionary, _ resolve: RCTPromiseResolveBlock?, _ reject: RCTPromiseRejectBlock?) { guard let trackId = data.value(forKey: "trackId") as? String, let volume = data.value(forKey: "volume") as? Double else { let errorMessage = "setVolume: " + HMSHelper.getUnavailableRequiredKey(data, ["trackId", "volume"]) - emitRequiredKeysError(errorMessage) + reject?(errorMessage, errorMessage, nil) return } DispatchQueue.main.async { [weak self] in guard let strongSelf = self else { return } - let remotePeers = self?.hms?.remotePeers + let remotePeers = strongSelf.hms?.remotePeers let remoteAudioTrack = HMSHelper.getRemoteAudioAuxiliaryTrackFromTrackId(trackId, remotePeers) if remoteAudioTrack != nil { remoteAudioTrack?.setVolume(volume) + resolve?(true) + } else { + let errorMessage = "setVolume: No remote audio track not available" + reject?(errorMessage, errorMessage, nil) } } } @@ -732,7 +734,6 @@ class HMSRNSDK: HMSUpdateListener, HMSPreviewListener { guard let record = data.value(forKey: "record") as? Bool else { let errorMessage = "startRTMPOrRecording: " + HMSHelper.getUnavailableRequiredKey(data, ["record"]) - emitRequiredKeysError(errorMessage) reject?(errorMessage, errorMessage, nil) return } @@ -747,6 +748,7 @@ class HMSRNSDK: HMSUpdateListener, HMSPreviewListener { meetingUrl = meetLink } else { reject?("Invalid meeting url passed", "Invalid meeting url passed", nil) + return } } @@ -811,7 +813,6 @@ class HMSRNSDK: HMSUpdateListener, HMSPreviewListener { guard let name = data.value(forKey: "name") as? String else { let errorMessage = "changeName: " + HMSHelper.getUnavailableRequiredKey(data, ["name"]) - emitRequiredKeysError(errorMessage) reject?(errorMessage, errorMessage, nil) return } @@ -843,18 +844,23 @@ class HMSRNSDK: HMSUpdateListener, HMSPreviewListener { } } - func setPlaybackForAllAudio(_ data: NSDictionary) { + func setPlaybackForAllAudio(_ data: NSDictionary, _ resolve: RCTPromiseResolveBlock?, _ reject: RCTPromiseRejectBlock?) { guard let mute = data.value(forKey: "mute") as? Bool else { - let errorMessage = "setPlaybackForAllAudio: " + HMSHelper.getUnavailableRequiredKey(data, ["setPlaybackForAllAudio"]) - emitRequiredKeysError(errorMessage) + let errorMessage = "setPlaybackForAllAudio: " + HMSHelper.getUnavailableRequiredKey(data, ["mute"]) + reject?(errorMessage, errorMessage, nil) return } DispatchQueue.main.async { [weak self] in - let remotePeers = self?.hms?.remotePeers - for peer in remotePeers ?? [] { - peer.remoteAudioTrack()?.setPlaybackAllowed(!mute) + if let remotePeers = self?.hms?.remotePeers { + for peer in remotePeers { + peer.remoteAudioTrack()?.setPlaybackAllowed(!mute) + } + resolve?(true) + } else { + let errorMessage = "setPlaybackForAllAudio: No Audio is available to set playback" + reject?(errorMessage, errorMessage, nil) } } } @@ -954,7 +960,6 @@ class HMSRNSDK: HMSUpdateListener, HMSPreviewListener { let playerNode = audioMixerSourceMap[audioNodeName] else { let errorMessage = "playAudioShare: " + HMSHelper.getUnavailableRequiredKey(data, ["audioNode", "fileUrl"]) - emitRequiredKeysError(errorMessage) reject?(errorMessage, errorMessage, nil) return } @@ -976,14 +981,14 @@ class HMSRNSDK: HMSUpdateListener, HMSPreviewListener { } } - func setAudioShareVolume(_ data: NSDictionary) { + func setAudioShareVolume(_ data: NSDictionary, _ resolve: RCTPromiseResolveBlock?, _ reject: RCTPromiseRejectBlock?) { guard let volume = data.value(forKey: "volume") as? NSNumber, let audioNodeName = data.value(forKey: "audioNode") as? String, let audioMixerSourceMap = HMSHelper.getAudioMixerSourceMap(), let playerNode = audioMixerSourceMap[audioNodeName] else { let errorMessage = "setAudioShareVolume: " + HMSHelper.getUnavailableRequiredKey(data, ["audioNode", "volume"]) - emitRequiredKeysError(errorMessage) + reject?(errorMessage, errorMessage, nil) return } if let audioMicNode = playerNode as? HMSMicNode { @@ -992,53 +997,64 @@ class HMSRNSDK: HMSUpdateListener, HMSPreviewListener { if let audioFilePlayerNode = playerNode as? HMSAudioFilePlayerNode { audioFilePlayerNode.volume = volume.floatValue } + resolve?(true) } - func stopAudioShare(_ data: NSDictionary) { + func stopAudioShare(_ data: NSDictionary, _ resolve: RCTPromiseResolveBlock?, _ reject: RCTPromiseRejectBlock?) { guard let audioNodeName = data.value(forKey: "audioNode") as? String, let audioMixerSourceMap = HMSHelper.getAudioMixerSourceMap(), let playerNode = audioMixerSourceMap[audioNodeName] else { let errorMessage = "stopAudioShare: " + HMSHelper.getUnavailableRequiredKey(data, ["audioNode"]) - emitRequiredKeysError(errorMessage) + reject?(errorMessage, errorMessage, nil) return } if let audioFilePlayerNode = playerNode as? HMSAudioFilePlayerNode { audioFilePlayerNode.stop() + resolve?(true) + } else { + let errorMessage = "stopAudioShare: HMSAudioFilePlayerNode not available!" + reject?(errorMessage, errorMessage, nil) } } - func resumeAudioShare(_ data: NSDictionary) { + func resumeAudioShare(_ data: NSDictionary, _ resolve: RCTPromiseResolveBlock?, _ reject: RCTPromiseRejectBlock?) { guard let audioNodeName = data.value(forKey: "audioNode") as? String, let audioMixerSourceMap = HMSHelper.getAudioMixerSourceMap(), let playerNode = audioMixerSourceMap[audioNodeName] else { let errorMessage = "resumeAudioShare: " + HMSHelper.getUnavailableRequiredKey(data, ["audioNode"]) - emitRequiredKeysError(errorMessage) + reject?(errorMessage, errorMessage, nil) return } if let audioFilePlayerNode = playerNode as? HMSAudioFilePlayerNode { do { try audioFilePlayerNode.resume() + resolve?(true) } catch { - if eventsEnableStatus[HMSConstants.ON_ERROR] == true { - delegate?.emitEvent(HMSConstants.ON_ERROR, ["error": ["code": 6002, "description": error.localizedDescription, "isTerminal": false, "canRetry": true, "params": ["function": #function]] as [String: Any], "id": id]) - } + reject?(error.localizedDescription, error.localizedDescription, nil) } + } else { + let errorMessage = "resumeAudioShare: HMSAudioFilePlayerNode not available!" + reject?(errorMessage, errorMessage, nil) } } - func pauseAudioShare(_ data: NSDictionary) { + func pauseAudioShare(_ data: NSDictionary, _ resolve: RCTPromiseResolveBlock?, _ reject: RCTPromiseRejectBlock?) { guard let audioNodeName = data.value(forKey: "audioNode") as? String, let audioMixerSourceMap = HMSHelper.getAudioMixerSourceMap(), let playerNode = audioMixerSourceMap[audioNodeName] else { let errorMessage = "pauseAudioShare: " + HMSHelper.getUnavailableRequiredKey(data, ["audioNode"]) - emitRequiredKeysError(errorMessage) + reject?(errorMessage, errorMessage, nil) return } if let audioFilePlayerNode = playerNode as? HMSAudioFilePlayerNode { audioFilePlayerNode.pause() + resolve?(true) + } else { + let errorMessage = "pauseAudioShare: HMSAudioFilePlayerNode not available!" + reject?(errorMessage, errorMessage, nil) } } @@ -1048,7 +1064,6 @@ class HMSRNSDK: HMSUpdateListener, HMSPreviewListener { let playerNode = audioMixerSourceMap[audioNodeName] else { let errorMessage = "pauseAudioShare: " + HMSHelper.getUnavailableRequiredKey(data, ["audioNode"]) - emitRequiredKeysError(errorMessage) reject?(errorMessage, errorMessage, nil) return } @@ -1065,7 +1080,6 @@ class HMSRNSDK: HMSUpdateListener, HMSPreviewListener { let playerNode = audioMixerSourceMap[audioNodeName] else { let errorMessage = "pauseAudioShare: " + HMSHelper.getUnavailableRequiredKey(data, ["audioNode"]) - emitRequiredKeysError(errorMessage) reject?(errorMessage, errorMessage, nil) return } @@ -1082,7 +1096,6 @@ class HMSRNSDK: HMSUpdateListener, HMSPreviewListener { let playerNode = audioMixerSourceMap[audioNodeName] else { let errorMessage = "pauseAudioShare: " + HMSHelper.getUnavailableRequiredKey(data, ["audioNode"]) - emitRequiredKeysError(errorMessage) reject?(errorMessage, errorMessage, nil) return } @@ -1104,7 +1117,6 @@ class HMSRNSDK: HMSUpdateListener, HMSPreviewListener { func enableEvent(_ data: NSDictionary, _ resolve: RCTPromiseResolveBlock?, _ reject: RCTPromiseRejectBlock?) { guard let eventType = data.value(forKey: "eventType") as? String else { let errorMessage = "enableEvent: " + HMSHelper.getUnavailableRequiredKey(data, ["eventType"]) - emitRequiredKeysError(errorMessage) reject?(errorMessage, errorMessage, nil) return } @@ -1116,7 +1128,6 @@ class HMSRNSDK: HMSUpdateListener, HMSPreviewListener { func disableEvent(_ data: NSDictionary, _ resolve: RCTPromiseResolveBlock?, _ reject: RCTPromiseRejectBlock?) { guard let eventType = data.value(forKey: "eventType") as? String else { let errorMessage = "disableEvent: " + HMSHelper.getUnavailableRequiredKey(data, ["eventType"]) - emitRequiredKeysError(errorMessage) reject?(errorMessage, errorMessage, nil) return } @@ -1125,14 +1136,15 @@ class HMSRNSDK: HMSUpdateListener, HMSPreviewListener { resolve?(["success": true, "message": "function call executed successfully"] as [String: Any]) } - func restrictData(_ data: NSDictionary) { + func restrictData(_ data: NSDictionary, _ resolve: RCTPromiseResolveBlock?, _ reject: RCTPromiseRejectBlock?) { guard let roleName = data.value(forKey: "roleName") as? String else { let errorMessage = "restrictData: " + HMSHelper.getUnavailableRequiredKey(data, ["roleName"]) - emitRequiredKeysError(errorMessage) + reject?(errorMessage, errorMessage, nil) return } HMSDecoder.setRestrictRoleData(roleName, true) + resolve?(true) } // MARK: - HMS SDK Get APIs @@ -1272,7 +1284,6 @@ class HMSRNSDK: HMSUpdateListener, HMSPreviewListener { guard let trackId = data.value(forKey: "trackId") as? String else { let errorMessage = "\(#function) " + HMSHelper.getUnavailableRequiredKey(data, ["trackId"]) - emitRequiredKeysError(errorMessage) reject?(errorMessage, errorMessage, nil) return } @@ -1284,7 +1295,6 @@ class HMSRNSDK: HMSUpdateListener, HMSPreviewListener { let remoteVideoTrack = HMSHelper.getRemoteVideoTrackFromTrackId(trackId, remotePeers) else { let errorMessage = "\(#function) " + "TRACK_NOT_FOUND" - self?.emitRequiredKeysError(errorMessage) reject?(errorMessage, errorMessage, nil) return } @@ -1297,7 +1307,6 @@ class HMSRNSDK: HMSUpdateListener, HMSPreviewListener { guard let trackId = data.value(forKey: "trackId") as? String else { let errorMessage = "\(#function) " + HMSHelper.getUnavailableRequiredKey(data, ["trackId"]) - emitRequiredKeysError(errorMessage) reject?(errorMessage, errorMessage, nil) return } @@ -1309,7 +1318,6 @@ class HMSRNSDK: HMSUpdateListener, HMSPreviewListener { let remoteAudioTrack = HMSHelper.getRemoteAudioTrackFromTrackId(trackId, remotePeers) else { let errorMessage = "\(#function) " + "TRACK_NOT_FOUND" - self?.emitRequiredKeysError(errorMessage) reject?(errorMessage, errorMessage, nil) return } @@ -1553,7 +1561,6 @@ class HMSRNSDK: HMSUpdateListener, HMSPreviewListener { guard let trackId = data.value(forKey: "trackId") as? String else { let errorMessage = "\(#function) " + HMSHelper.getUnavailableRequiredKey(data, ["trackId"]) - emitRequiredKeysError(errorMessage) reject?(errorMessage, errorMessage, nil) return } @@ -1565,7 +1572,6 @@ class HMSRNSDK: HMSUpdateListener, HMSPreviewListener { let remoteVideoTrack = HMSHelper.getRemoteVideoTrackFromTrackId(trackId, remotePeers) else { let errorMessage = "\(#function) " + "TRACK_NOT_FOUND" - self?.emitRequiredKeysError(errorMessage) reject?(errorMessage, errorMessage, nil) return } @@ -1573,7 +1579,6 @@ class HMSRNSDK: HMSUpdateListener, HMSPreviewListener { guard let layerDefinitions = remoteVideoTrack.layerDefinitions else { let errorMessage = "\(#function) " + "layer definitions not available for track: '\(trackId)' !" - self.emitRequiredKeysError(errorMessage) reject?(errorMessage, errorMessage, nil) return } @@ -1589,7 +1594,6 @@ class HMSRNSDK: HMSUpdateListener, HMSPreviewListener { guard let trackId = data.value(forKey: "trackId") as? String else { let errorMessage = "\(#function) " + HMSHelper.getUnavailableRequiredKey(data, ["trackId"]) - emitRequiredKeysError(errorMessage) reject?(errorMessage, errorMessage, nil) return } @@ -1601,7 +1605,6 @@ class HMSRNSDK: HMSUpdateListener, HMSPreviewListener { let remoteVideoTrack = HMSHelper.getRemoteVideoTrackFromTrackId(trackId, remotePeers) else { let errorMessage = "\(#function) " + "TRACK_NOT_FOUND" - self?.emitRequiredKeysError(errorMessage) reject?(errorMessage, errorMessage, nil) return } @@ -1617,7 +1620,6 @@ class HMSRNSDK: HMSUpdateListener, HMSPreviewListener { let layer = data.value(forKey: "layer") as? String else { let errorMessage = "\(#function) " + HMSHelper.getUnavailableRequiredKey(data, ["trackId", "layer"]) - emitRequiredKeysError(errorMessage) reject?(errorMessage, errorMessage, nil) return } @@ -1629,7 +1631,6 @@ class HMSRNSDK: HMSUpdateListener, HMSPreviewListener { let remoteVideoTrack = HMSHelper.getRemoteVideoTrackFromTrackId(trackId, remotePeers) else { let errorMessage = "\(#function) " + "TRACK_NOT_FOUND" - self?.emitRequiredKeysError(errorMessage) reject?(errorMessage, errorMessage, nil) return } From 54c964dc70138f15d6c7e3354af996d8ff1e34ab Mon Sep 17 00:00:00 2001 From: Jatin Nagar Date: Thu, 19 Oct 2023 00:44:48 +0530 Subject: [PATCH 06/21] refactor(sdk): :recycle: removed `emitRequiredKeysError` calls on android sdk and renamed `emitHMSSuccess` and `emitHMSMessageSuccess` methods --- .../HMSAudioshareActivity.kt | 2 +- .../java/com/reactnativehmssdk/HMSManager.kt | 20 +-- .../java/com/reactnativehmssdk/HMSRNSDK.kt | 129 ++++++++---------- .../HmsScreenshareActivity.kt | 2 +- 4 files changed, 66 insertions(+), 87 deletions(-) diff --git a/packages/react-native-hms/android/src/main/java/com/reactnativehmssdk/HMSAudioshareActivity.kt b/packages/react-native-hms/android/src/main/java/com/reactnativehmssdk/HMSAudioshareActivity.kt index d044b47a4..e2878a7af 100644 --- a/packages/react-native-hms/android/src/main/java/com/reactnativehmssdk/HMSAudioshareActivity.kt +++ b/packages/react-native-hms/android/src/main/java/com/reactnativehmssdk/HMSAudioshareActivity.kt @@ -29,7 +29,7 @@ class HMSAudioshareActivity : ComponentActivity() { override fun onSuccess() { HMSManager.hmsCollection[id]?.isAudioSharing = true HMSManager.hmsCollection[id]?.audioshareCallback?.resolve( - HMSManager.hmsCollection[id]?.emitHMSSuccess(), + HMSManager.hmsCollection[id]?.getPromiseResolveData(), ) finish() } diff --git a/packages/react-native-hms/android/src/main/java/com/reactnativehmssdk/HMSManager.kt b/packages/react-native-hms/android/src/main/java/com/reactnativehmssdk/HMSManager.kt index 8917cecf4..e7154b64a 100644 --- a/packages/react-native-hms/android/src/main/java/com/reactnativehmssdk/HMSManager.kt +++ b/packages/react-native-hms/android/src/main/java/com/reactnativehmssdk/HMSManager.kt @@ -296,10 +296,10 @@ class HMSManager(reactContext: ReactApplicationContext) : } @ReactMethod - fun setPlaybackAllowed(data: ReadableMap) { + fun setPlaybackAllowed(data: ReadableMap, callback: Promise?) { val hms = HMSHelper.getHms(data, hmsCollection) - hms?.setPlaybackAllowed(data) + hms?.setPlaybackAllowed(data, callback) } @ReactMethod @@ -343,10 +343,10 @@ class HMSManager(reactContext: ReactApplicationContext) : } @ReactMethod - fun setVolume(data: ReadableMap) { + fun setVolume(data: ReadableMap, callback: Promise?) { val hms = HMSHelper.getHms(data, hmsCollection) - hms?.setVolume(data) + hms?.setVolume(data, callback) } @ReactMethod @@ -360,10 +360,10 @@ class HMSManager(reactContext: ReactApplicationContext) : } @ReactMethod - fun setPlaybackForAllAudio(data: ReadableMap) { + fun setPlaybackForAllAudio(data: ReadableMap, callback: Promise?) { val hms = HMSHelper.getHms(data, hmsCollection) - hms?.setPlaybackForAllAudio(data) + hms?.setPlaybackForAllAudio(data, callback) } @ReactMethod @@ -575,17 +575,17 @@ class HMSManager(reactContext: ReactApplicationContext) : } @ReactMethod - fun switchAudioOutput(data: ReadableMap) { + fun switchAudioOutput(data: ReadableMap, callback: Promise?) { val hms = HMSHelper.getHms(data, hmsCollection) - hms?.switchAudioOutput(data) + hms?.switchAudioOutput(data, callback) } @ReactMethod - fun setAudioMode(data: ReadableMap) { + fun setAudioMode(data: ReadableMap, callback: Promise?) { val hms = HMSHelper.getHms(data, hmsCollection) - hms?.setAudioMode(data) + hms?.setAudioMode(data, callback) } @ReactMethod diff --git a/packages/react-native-hms/android/src/main/java/com/reactnativehmssdk/HMSRNSDK.kt b/packages/react-native-hms/android/src/main/java/com/reactnativehmssdk/HMSRNSDK.kt index e8d569827..485376116 100644 --- a/packages/react-native-hms/android/src/main/java/com/reactnativehmssdk/HMSRNSDK.kt +++ b/packages/react-native-hms/android/src/main/java/com/reactnativehmssdk/HMSRNSDK.kt @@ -147,7 +147,7 @@ class HMSRNSDK( delegate.emitEvent("ON_ERROR", data) } - fun emitHMSSuccess(message: HMSMessage? = null): ReadableMap { + fun getPromiseResolveData(message: HMSMessage? = null): ReadableMap { val hmsMessage = if (message !== null) message.message else "function call executed successfully" val data: WritableMap = Arguments.createMap() @@ -156,7 +156,7 @@ class HMSRNSDK( return data } - fun emitHMSMessageSuccess(hmsMessage: HMSMessage): ReadableMap { + fun getPromiseResolveMessageData(hmsMessage: HMSMessage): ReadableMap { val data: WritableMap = Arguments.createMap() data.putString("message", hmsMessage.message) data.putString("messageId", hmsMessage.messageId) @@ -689,7 +689,6 @@ class HMSRNSDK( ) } else { val errorMessage = "getAuthTokenByRoomCode: $requiredKeys" - self.emitRequiredKeysError(errorMessage) rejectCallback(promise, errorMessage) } } @@ -736,7 +735,7 @@ class HMSRNSDK( map.putString("id", id) delegate.emitEvent("ON_PIP_ROOM_LEAVE", map) } else { - callback?.resolve(emitHMSSuccess()) + callback?.resolve(getPromiseResolveData()) } cleanup() // resetting states and doing data cleanup } @@ -770,13 +769,12 @@ class HMSRNSDK( } override fun onSuccess(hmsMessage: HMSMessage) { - callback?.resolve(emitHMSMessageSuccess(hmsMessage)) + callback?.resolve(getPromiseResolveMessageData(hmsMessage)) } }, ) } else { val errorMessage = "sendBroadcastMessage: $requiredKeys" - self.emitRequiredKeysError(errorMessage) rejectCallback(callback, errorMessage) } } @@ -805,13 +803,12 @@ class HMSRNSDK( } override fun onSuccess(hmsMessage: HMSMessage) { - callback?.resolve(emitHMSMessageSuccess(hmsMessage)) + callback?.resolve(getPromiseResolveMessageData(hmsMessage)) } }, ) } else { val errorMessage = "sendGroupMessage: $requiredKeys" - self.emitRequiredKeysError(errorMessage) rejectCallback(callback, errorMessage) } } @@ -839,17 +836,15 @@ class HMSRNSDK( } override fun onSuccess(hmsMessage: HMSMessage) { - callback?.resolve(emitHMSMessageSuccess(hmsMessage)) + callback?.resolve(getPromiseResolveMessageData(hmsMessage)) } }, ) } else { - self.emitCustomError("PEER_NOT_FOUND") callback?.reject("101", "PEER_NOT_FOUND") } } else { val errorMessage = "sendDirectMessage: $requiredKeys" - self.emitRequiredKeysError(errorMessage) rejectCallback(callback, errorMessage) } } @@ -887,7 +882,7 @@ class HMSRNSDK( force, object : HMSActionResultListener { override fun onSuccess() { - callback?.resolve(emitHMSSuccess()) + callback?.resolve(getPromiseResolveData()) } override fun onError(error: HMSException) { @@ -898,7 +893,6 @@ class HMSRNSDK( } } else { val errorMessage = "changeRole: $requiredKeys" - self.emitRequiredKeysError(errorMessage) rejectCallback(callback, errorMessage) } } @@ -935,7 +929,7 @@ class HMSRNSDK( force, object : HMSActionResultListener { override fun onSuccess() { - promise?.resolve(emitHMSSuccess()) + promise?.resolve(getPromiseResolveData()) } override fun onError(error: HMSException) { @@ -946,7 +940,6 @@ class HMSRNSDK( } } else { val errorMessage = "changeRoleOfPeer: $requiredKeys" - self.emitRequiredKeysError(errorMessage) rejectCallback(promise, errorMessage) } } @@ -978,7 +971,7 @@ class HMSRNSDK( toHMSRole, object : HMSActionResultListener { override fun onSuccess() { - promise?.resolve(emitHMSSuccess()) + promise?.resolve(getPromiseResolveData()) } override fun onError(error: HMSException) { @@ -990,7 +983,6 @@ class HMSRNSDK( } } else { val errorMessage = "changeRoleOfPeersWithRoles: $requiredKeys" - self.emitRequiredKeysError(errorMessage) rejectCallback(promise, errorMessage) } } @@ -1014,7 +1006,7 @@ class HMSRNSDK( mute, object : HMSActionResultListener { override fun onSuccess() { - callback?.resolve(emitHMSSuccess()) + callback?.resolve(getPromiseResolveData()) } override fun onError(error: HMSException) { @@ -1025,7 +1017,6 @@ class HMSRNSDK( } } else { val errorMessage = "changeTrackState: $requiredKeys" - self.emitRequiredKeysError(errorMessage) rejectCallback(callback, errorMessage) } } @@ -1068,7 +1059,7 @@ class HMSRNSDK( encodedTargetedRoles, object : HMSActionResultListener { override fun onSuccess() { - callback?.resolve(emitHMSSuccess()) + callback?.resolve(getPromiseResolveData()) } override fun onError(error: HMSException) { @@ -1078,7 +1069,6 @@ class HMSRNSDK( ) } else { val errorMessage = "changeTrackStateForRoles: $requiredKeys" - self.emitRequiredKeysError(errorMessage) rejectCallback(callback, errorMessage) } } @@ -1099,7 +1089,6 @@ class HMSRNSDK( } } else { val errorMessage = "isMute: $requiredKeys" - self.emitRequiredKeysError(errorMessage) rejectCallback(callback, errorMessage) } } @@ -1125,7 +1114,7 @@ class HMSRNSDK( data.getString("reason") as String, object : HMSActionResultListener { override fun onSuccess() { - callback?.resolve(emitHMSSuccess()) + callback?.resolve(getPromiseResolveData()) } override fun onError(error: HMSException) { @@ -1158,7 +1147,7 @@ class HMSRNSDK( data.getBoolean("lock"), object : HMSActionResultListener { override fun onSuccess() { - callback?.resolve(emitHMSSuccess()) + callback?.resolve(getPromiseResolveData()) cleanup() // resetting states and doing data cleanup } @@ -1169,7 +1158,6 @@ class HMSRNSDK( ) } else { val errorMessage = "endRoom: $requiredKeys" - self.emitRequiredKeysError(errorMessage) rejectCallback(callback, errorMessage) } } @@ -1216,7 +1204,6 @@ class HMSRNSDK( ) } else { val errorMessage = "Missing required keys for previewForRole: $requiredKeys" - self.emitRequiredKeysError(errorMessage) rejectCallback(callback, errorMessage) } } @@ -1225,7 +1212,7 @@ class HMSRNSDK( hmsSDK?.cancelPreview() previewForRoleAudioTrack = null previewForRoleVideoTrack = null - callback?.resolve(emitHMSSuccess()) + callback?.resolve(getPromiseResolveData()) } fun acceptRoleChange(callback: Promise?) { @@ -1234,7 +1221,7 @@ class HMSRNSDK( recentRoleChangeRequest!!, object : HMSActionResultListener { override fun onSuccess() { - callback?.resolve(emitHMSSuccess()) + callback?.resolve(getPromiseResolveData()) } override fun onError(error: HMSException) { @@ -1247,7 +1234,6 @@ class HMSRNSDK( previewForRoleVideoTrack = null } else { val errorMessage = "acceptRoleChange: recentRoleChangeRequest not found" - self.emitRequiredKeysError(errorMessage) rejectCallback(callback, errorMessage) } } @@ -1270,7 +1256,7 @@ class HMSRNSDK( ) } if (customError === null) { - callback?.resolve(emitHMSSuccess()) + callback?.resolve(getPromiseResolveData()) } else { rejectCallback(callback, customError!!.message) } @@ -1278,7 +1264,7 @@ class HMSRNSDK( rejectCallback(callback, "Audio tracks not found") } - fun setPlaybackForAllAudio(data: ReadableMap) { + fun setPlaybackForAllAudio(data: ReadableMap, callback: Promise?) { val requiredKeys = HMSHelper.getUnavailableRequiredKey(data, arrayOf(Pair("mute", "Boolean"))) if (requiredKeys === null) { val mute = data.getBoolean("mute") @@ -1287,13 +1273,14 @@ class HMSRNSDK( remotePeers?.forEach() { it.audioTrack?.isPlaybackAllowed = !mute } + callback?.resolve(true) } else { val errorMessage = "setPlaybackForAllAudio: $requiredKeys" - self.emitRequiredKeysError(errorMessage) + rejectCallback(callback, errorMessage) } } - fun setPlaybackAllowed(data: ReadableMap) { + fun setPlaybackAllowed(data: ReadableMap, callback: Promise?) { val requiredKeys = HMSHelper.getUnavailableRequiredKey( data, @@ -1306,12 +1293,16 @@ class HMSRNSDK( val remoteVideoTrack = HMSHelper.getRemoteVideoTrackFromTrackId(trackId, hmsSDK?.getRoom()) if (remoteAudioTrack != null) { remoteAudioTrack.isPlaybackAllowed = playbackAllowed + callback?.resolve(true) } else if (remoteVideoTrack != null) { remoteVideoTrack.isPlaybackAllowed = playbackAllowed + callback?.resolve(true) + } else { + callback?.reject("101", "setPlaybackAllowed: No remote audio and video track found!") } } else { val errorMessage = "setPlaybackAllowed: $requiredKeys" - self.emitRequiredKeysError(errorMessage) + rejectCallback(callback, errorMessage) } } @@ -1339,7 +1330,6 @@ class HMSRNSDK( } } else { val errorMessage = "isPlaybackAllowed: $requiredKeys" - self.emitRequiredKeysError(errorMessage) rejectCallback(callback, errorMessage) } } @@ -1364,7 +1354,7 @@ class HMSRNSDK( callback?.resolve(roles) } - fun setVolume(data: ReadableMap) { + fun setVolume(data: ReadableMap, callback: Promise?) { val requiredKeys = HMSHelper.getUnavailableRequiredKey( data, @@ -1397,13 +1387,13 @@ class HMSRNSDK( } } } - this.emitCustomError("TRACK_NOT_FOUND") + callback?.reject("101", "TRACK_NOT_FOUND") } else { - this.emitCustomError("REMOTE_PEERS_NOT_FOUND") + callback?.reject("101", "REMOTE_PEERS_NOT_FOUND") } } else { val errorMessage = "setVolume: $requiredKeys" - self.emitRequiredKeysError(errorMessage) + rejectCallback(callback, errorMessage) } } @@ -1425,7 +1415,6 @@ class HMSRNSDK( callback?.reject("101", "TRACK_IDS_DO_NOT_MATCH") } else { val errorMessage = "getVolume: $requiredKeys" - self.emitRequiredKeysError(errorMessage) rejectCallback(callback, errorMessage) } } @@ -1444,7 +1433,7 @@ class HMSRNSDK( metadata, object : HMSActionResultListener { override fun onSuccess() { - callback?.resolve(emitHMSSuccess()) + callback?.resolve(getPromiseResolveData()) } override fun onError(error: HMSException) { @@ -1455,7 +1444,6 @@ class HMSRNSDK( } } else { val errorMessage = "changeMetadata: $requiredKeys" - self.emitRequiredKeysError(errorMessage) rejectCallback(callback, errorMessage) } } @@ -1473,14 +1461,13 @@ class HMSRNSDK( val config = HMSHelper.getRtmpConfig(data) if (config === null) { val errorMessage = "startRTMPOrRecording: INVALID_MEETING_URL_PASSED" - self.emitRequiredKeysError(errorMessage) rejectCallback(callback, errorMessage) } else { hmsSDK?.startRtmpOrRecording( config, object : HMSActionResultListener { override fun onSuccess() { - callback?.resolve(emitHMSSuccess()) + callback?.resolve(getPromiseResolveData()) } override fun onError(error: HMSException) { @@ -1491,7 +1478,6 @@ class HMSRNSDK( } } else { val errorMessage = "startRTMPOrRecording: $requiredKeys" - self.emitRequiredKeysError(errorMessage) rejectCallback(callback, errorMessage) } } @@ -1500,7 +1486,7 @@ class HMSRNSDK( hmsSDK?.stopRtmpAndRecording( object : HMSActionResultListener { override fun onSuccess() { - callback?.resolve(emitHMSSuccess()) + callback?.resolve(getPromiseResolveData()) } override fun onError(error: HMSException) { @@ -1534,7 +1520,7 @@ class HMSRNSDK( override fun onSuccess() { screenshareCallback = null - callback?.resolve(emitHMSSuccess()) + callback?.resolve(getPromiseResolveData()) } }, ) @@ -1549,7 +1535,7 @@ class HMSRNSDK( hlsConfig, object : HMSActionResultListener { override fun onSuccess() { - callback?.resolve(emitHMSSuccess()) + callback?.resolve(getPromiseResolveData()) } override fun onError(error: HMSException) { @@ -1564,7 +1550,7 @@ class HMSRNSDK( null, object : HMSActionResultListener { override fun onSuccess() { - callback?.resolve(emitHMSSuccess()) + callback?.resolve(getPromiseResolveData()) } override fun onError(error: HMSException) { @@ -1606,7 +1592,7 @@ class HMSRNSDK( name, object : HMSActionResultListener { override fun onSuccess() { - callback?.resolve(emitHMSSuccess()) + callback?.resolve(getPromiseResolveData()) } override fun onError(error: HMSException) { @@ -1615,12 +1601,10 @@ class HMSRNSDK( }, ) } else { - self.emitCustomError("NAME_UNDEFINED") callback?.reject("101", "NAME_UNDEFINED") } } else { val errorMessage = "changeName: $requiredKeys" - self.emitRequiredKeysError(errorMessage) rejectCallback(callback, errorMessage) } } @@ -1641,26 +1625,32 @@ class HMSRNSDK( callback?.resolve(hmsSDK?.getAudioOutputRouteType()?.name) } - fun switchAudioOutput(data: ReadableMap) { + fun switchAudioOutput(data: ReadableMap, callback: Promise?) { val requiredKeys = HMSHelper.getUnavailableRequiredKey(data, arrayOf(Pair("audioDevice", "String"))) if (requiredKeys === null) { val audioDevice = data.getString("audioDevice") - hmsSDK?.switchAudioOutput(HMSHelper.getAudioDevice(audioDevice)) + hmsSDK?.let { + it.switchAudioOutput(HMSHelper.getAudioDevice(audioDevice)) + callback?.resolve(true) + } } else { val errorMessage = "switchAudioOutput: $requiredKeys" - self.emitRequiredKeysError(errorMessage) + rejectCallback(callback, errorMessage) } } - fun setAudioMode(data: ReadableMap) { + fun setAudioMode(data: ReadableMap, callback: Promise?) { val requiredKeys = HMSHelper.getUnavailableRequiredKey(data, arrayOf(Pair("audioMode", "Int"))) if (requiredKeys === null) { val audioMode = data.getInt("audioMode") - hmsSDK?.setAudioMode(audioMode) + hmsSDK?.let { + it.setAudioMode(audioMode) + callback?.resolve(true) + } } else { val errorMessage = "setAudioMode: $requiredKeys" - self.emitRequiredKeysError(errorMessage) + rejectCallback(callback, errorMessage) } } @@ -1705,7 +1695,6 @@ class HMSRNSDK( } } else { val errorMessage = "startAudioshare: $requiredKeys" - self.emitRequiredKeysError(errorMessage) rejectCallback(callback, errorMessage) } } @@ -1725,7 +1714,7 @@ class HMSRNSDK( override fun onSuccess() { isAudioSharing = false audioshareCallback = null - callback?.resolve(emitHMSSuccess()) + callback?.resolve(getPromiseResolveData()) } }, ) @@ -1745,10 +1734,9 @@ class HMSRNSDK( val mode = HMSHelper.getAudioMixingMode(data.getString("audioMixingMode")) audioMixingMode = mode hmsSDK?.setAudioMixingMode(mode) - callback?.resolve(emitHMSSuccess()) + callback?.resolve(getPromiseResolveData()) } else { val errorMessage = "setAudioMixingMode: $requiredKeys" - self.emitRequiredKeysError(errorMessage) rejectCallback(callback, errorMessage) } } @@ -1897,11 +1885,10 @@ class HMSRNSDK( if (eventType != null) { eventsEnableStatus[eventType] = true - promise?.resolve(emitHMSSuccess()) + promise?.resolve(getPromiseResolveData()) } } else { val errorMessage = "enableEvent: $requiredKeys" - self.emitRequiredKeysError(errorMessage) rejectCallback(promise, errorMessage) } } @@ -1917,11 +1904,10 @@ class HMSRNSDK( if (eventType != null) { eventsEnableStatus[eventType] = false - promise?.resolve(emitHMSSuccess()) + promise?.resolve(getPromiseResolveData()) } } else { val errorMessage = "disableEvent: $requiredKeys" - self.emitRequiredKeysError(errorMessage) rejectCallback(promise, errorMessage) } } @@ -1936,11 +1922,10 @@ class HMSRNSDK( val roleName = data.getString("roleName") if (roleName != null) { HMSDecoder.setRestrictRoleData(roleName, true) - promise?.resolve(emitHMSSuccess()) + promise?.resolve(getPromiseResolveData()) } } else { val errorMessage = "restrictData: $requiredKeys" - self.emitRequiredKeysError(errorMessage) rejectCallback(promise, errorMessage) } } @@ -1960,7 +1945,6 @@ class HMSRNSDK( } } else { val errorMessage = "getRemoteVideoTrackFromTrackId: $requiredKeys" - self.emitRequiredKeysError(errorMessage) rejectCallback(promise, errorMessage) } } @@ -1980,7 +1964,6 @@ class HMSRNSDK( } } else { val errorMessage = "getRemoteAudioTrackFromTrackId: $requiredKeys" - self.emitRequiredKeysError(errorMessage) rejectCallback(promise, errorMessage) } } @@ -2001,7 +1984,6 @@ class HMSRNSDK( } } else { val errorMessage = "getVideoTrackLayer: $requiredKeys" - self.emitRequiredKeysError(errorMessage) rejectCallback(promise, errorMessage) } } @@ -2023,7 +2005,6 @@ class HMSRNSDK( } } else { val errorMessage = "getVideoTrackLayerDefinition: $requiredKeys" - self.emitRequiredKeysError(errorMessage) rejectCallback(promise, errorMessage) } } @@ -2055,7 +2036,6 @@ class HMSRNSDK( } } else { val errorMessage = "setVideoTrackLayer: $requiredKeys" - self.emitRequiredKeysError(errorMessage) rejectCallback(promise, errorMessage) } } @@ -2133,7 +2113,7 @@ class HMSRNSDK( savePath, ) { success -> if (flashActionOnSuccess > 0) { - cameraControl.setFlash(flashActionOnSuccess === 1) + cameraControl.setFlash(flashActionOnSuccess == 1) } if (success) { promise?.resolve(imagePath) @@ -2143,7 +2123,6 @@ class HMSRNSDK( } } else { val errorMessage = "captureImageAtMaxSupportedResolution: $requiredKeys" - self.emitRequiredKeysError(errorMessage) rejectCallback(promise, errorMessage) } } diff --git a/packages/react-native-hms/android/src/main/java/com/reactnativehmssdk/HmsScreenshareActivity.kt b/packages/react-native-hms/android/src/main/java/com/reactnativehmssdk/HmsScreenshareActivity.kt index 30ad195db..13d0c882f 100644 --- a/packages/react-native-hms/android/src/main/java/com/reactnativehmssdk/HmsScreenshareActivity.kt +++ b/packages/react-native-hms/android/src/main/java/com/reactnativehmssdk/HmsScreenshareActivity.kt @@ -27,7 +27,7 @@ class HmsScreenshareActivity : ComponentActivity() { override fun onSuccess() { HMSManager.hmsCollection[id]?.screenshareCallback?.resolve( - HMSManager.hmsCollection[id]?.emitHMSSuccess(), + HMSManager.hmsCollection[id]?.getPromiseResolveData(), ) finish() } From 2378fa06c3964f72745113dd60eb092f3a805fe6 Mon Sep 17 00:00:00 2001 From: Jatin Nagar Date: Fri, 20 Oct 2023 13:41:00 +0530 Subject: [PATCH 07/21] refactor(sdk): :recycle: removed `ON_ERROR` emit code from HMSRNSDK constructor --- .../java/com/reactnativehmssdk/HMSManager.kt | 29 +++++++++++-------- .../java/com/reactnativehmssdk/HMSRNSDK.kt | 6 ++-- 2 files changed, 21 insertions(+), 14 deletions(-) diff --git a/packages/react-native-hms/android/src/main/java/com/reactnativehmssdk/HMSManager.kt b/packages/react-native-hms/android/src/main/java/com/reactnativehmssdk/HMSManager.kt index e7154b64a..08ce09868 100644 --- a/packages/react-native-hms/android/src/main/java/com/reactnativehmssdk/HMSManager.kt +++ b/packages/react-native-hms/android/src/main/java/com/reactnativehmssdk/HMSManager.kt @@ -14,6 +14,7 @@ import com.facebook.react.bridge.* import com.facebook.react.module.annotations.ReactModule import com.facebook.react.modules.core.DeviceEventManagerModule import com.reactnativehmssdk.HMSManager.Companion.REACT_CLASS +import live.hms.video.error.HMSException import java.util.UUID @ReactModule(name = REACT_CLASS) @@ -80,22 +81,26 @@ class HMSManager(reactContext: ReactApplicationContext) : data: ReadableMap?, callback: Promise?, ) { - val hasItem = hmsCollection.containsKey("12345") - if (hasItem) { - val uuid = UUID.randomUUID() - val randomUUIDString = uuid.toString() - val sdkInstance = HMSRNSDK(data, this, randomUUIDString, reactApplicationContext) + try { + val hasItem = hmsCollection.containsKey("12345") + if (hasItem) { + val uuid = UUID.randomUUID() + val randomUUIDString = uuid.toString() + val sdkInstance = HMSRNSDK(data, this, randomUUIDString, reactApplicationContext) - hmsCollection[randomUUIDString] = sdkInstance + hmsCollection[randomUUIDString] = sdkInstance - callback?.resolve(randomUUIDString) - } else { - val randomUUIDString = "12345" - val sdkInstance = HMSRNSDK(data, this, randomUUIDString, reactApplicationContext) + callback?.resolve(randomUUIDString) + } else { + val randomUUIDString = "12345" + val sdkInstance = HMSRNSDK(data, this, randomUUIDString, reactApplicationContext) - hmsCollection[randomUUIDString] = sdkInstance + hmsCollection[randomUUIDString] = sdkInstance - callback?.resolve(randomUUIDString) + callback?.resolve(randomUUIDString) + } + } catch (e: HMSException) { + callback?.reject(e.code.toString(), e.description) } } diff --git a/packages/react-native-hms/android/src/main/java/com/reactnativehmssdk/HMSRNSDK.kt b/packages/react-native-hms/android/src/main/java/com/reactnativehmssdk/HMSRNSDK.kt index 485376116..7cc5e9dcc 100644 --- a/packages/react-native-hms/android/src/main/java/com/reactnativehmssdk/HMSRNSDK.kt +++ b/packages/react-native-hms/android/src/main/java/com/reactnativehmssdk/HMSRNSDK.kt @@ -67,10 +67,12 @@ class HMSRNSDK( if (frameworkInfo != null) { builder.setFrameworkInfo(frameworkInfo) } else { - emitCustomError("Unable to decode framework info") + val errorMessage = "Unable to decode framework info" + throw HMSException(6002, errorMessage, errorMessage, errorMessage, errorMessage, null, false) } } else { - emitCustomError("Framework info not sent in build function") + val errorMessage = "Framework info not sent in build function" + throw HMSException(6002, errorMessage, errorMessage, errorMessage, errorMessage, null, false) } if (HMSHelper.areAllRequiredKeysAvailable(data, arrayOf(Pair("logSettings", "Map")))) { From 0b355c466f801ea8e4d20cfad8967b0ad2176178 Mon Sep 17 00:00:00 2001 From: Jatin Nagar Date: Fri, 20 Oct 2023 16:44:58 +0530 Subject: [PATCH 08/21] feat(prebuilt): added notification for exception and api rejections --- .../components/HMSExceptionNotification.tsx | 76 ++++++++++++++++++ .../HMSLocalScreenshareNotification.tsx | 2 +- .../src/components/HMSNotification.tsx | 6 +- .../src/components/HMSNotifications.tsx | 20 ++++- .../HMSRecordingStartFailedNotification.tsx | 77 ------------------- .../components/PreviewForRoleChangeModal.tsx | 2 +- .../react-native-room-kit/src/hooks-util.ts | 51 +++--------- .../src/redux/reducers/appState.ts | 3 +- packages/react-native-room-kit/src/types.ts | 14 +++- packages/react-native-room-kit/src/utils.ts | 7 -- 10 files changed, 119 insertions(+), 139 deletions(-) create mode 100644 packages/react-native-room-kit/src/components/HMSExceptionNotification.tsx delete mode 100644 packages/react-native-room-kit/src/components/HMSRecordingStartFailedNotification.tsx diff --git a/packages/react-native-room-kit/src/components/HMSExceptionNotification.tsx b/packages/react-native-room-kit/src/components/HMSExceptionNotification.tsx new file mode 100644 index 000000000..8e86f0730 --- /dev/null +++ b/packages/react-native-room-kit/src/components/HMSExceptionNotification.tsx @@ -0,0 +1,76 @@ +import * as React from 'react'; + +import { HMSNotification } from './HMSNotification'; +import { AlertTriangleIcon, RecordingIcon } from '../Icons'; +import { useDispatch } from 'react-redux'; +import { useHMSRoomColorPalette, useHMSRoomStyleSheet } from '../hooks-util'; +import { removeNotification } from '../redux/actions'; +import { StyleSheet, Text, TouchableHighlight } from 'react-native'; +import type { HMSException } from '@100mslive/react-native-hms'; + +export interface HMSExceptionNotificationProps { + id: string; + exception: HMSException; + autoDismiss?: boolean; + dismissDelay?: number; +} + +export const HMSExceptionNotification: React.FC< + HMSExceptionNotificationProps +> = ({ id, exception, autoDismiss, dismissDelay }) => { + const dispatch = useDispatch(); + + // const { secondary_dim: secondaryDimColor } = useHMSRoomColorPalette(); + + // const hmsRoomStyles = useHMSRoomStyleSheet((theme, typography) => ({ + // button: { + // backgroundColor: theme.palette.secondary_default, + // }, + // buttonText: { + // color: theme.palette.on_secondary_high, + // fontFamily: `${typography.font_family}-SemiBold`, + // }, + // })); + + const dismissNotification = () => dispatch(removeNotification(id)); + + // const retryStartRecording = async () => { + // dismissNotification(); + // }; + + return ( + } + text={exception.description || 'Something went wrong!'} + dismissDelay={dismissDelay} + autoDismiss={autoDismiss} + // cta={exception.isTerminal ? + // + // + // Retry + // + // + // : undefined} + onDismiss={dismissNotification} + /> + ); +}; + +const styles = StyleSheet.create({ + button: { + paddingVertical: 8, + paddingHorizontal: 16, + borderRadius: 8, + marginRight: 16, + }, + buttonText: { + fontSize: 14, + lineHeight: 20, + letterSpacing: 0.25, + }, +}); diff --git a/packages/react-native-room-kit/src/components/HMSLocalScreenshareNotification.tsx b/packages/react-native-room-kit/src/components/HMSLocalScreenshareNotification.tsx index 0a8bb6042..dd63926f3 100644 --- a/packages/react-native-room-kit/src/components/HMSLocalScreenshareNotification.tsx +++ b/packages/react-native-room-kit/src/components/HMSLocalScreenshareNotification.tsx @@ -5,7 +5,7 @@ import { ScreenShareIcon } from '../Icons'; import { HMSDangerButton } from './HMSDangerButton'; import { HMSNotification } from './HMSNotification'; import { useHMSRoomStyle } from '../hooks-util'; -import { NotificationTypes } from '../utils'; +import { NotificationTypes } from '../types'; export interface HMSLocalScreenshareNotificationProps {} diff --git a/packages/react-native-room-kit/src/components/HMSNotification.tsx b/packages/react-native-room-kit/src/components/HMSNotification.tsx index 9ff3da5ad..2f841b6ef 100644 --- a/packages/react-native-room-kit/src/components/HMSNotification.tsx +++ b/packages/react-native-room-kit/src/components/HMSNotification.tsx @@ -18,6 +18,7 @@ export interface HMSNotificationProps { autoDismiss?: boolean; dismissDelay?: number; cta?: React.ReactElement; + dismissable?: boolean; } export const HMSNotification: React.FC = ({ @@ -30,6 +31,7 @@ export const HMSNotification: React.FC = ({ onDismiss, dismissDelay = 5000, autoDismiss = true, + dismissable = false, }) => { const dispatch = useDispatch(); @@ -45,7 +47,7 @@ export const HMSNotification: React.FC = ({ const dismissNotification = onDismiss || - (autoDismiss + (autoDismiss || dismissable ? () => { dispatch(removeNotification(id)); } @@ -77,7 +79,7 @@ export const HMSNotification: React.FC = ({ ); - if (dismissNotification) { + if (dismissNotification && autoDismiss) { return ( = () => { autoDismiss={atTop} dismissDelay={10000} /> - ) : notification.type === NotificationTypes.RECORDING_START_FAILED ? ( - + ) : 'message' in notification ? ( + } + id={notification.id} + text={notification.message} + autoDismiss={false} + dismissable={true} + /> ) : null} ); diff --git a/packages/react-native-room-kit/src/components/HMSRecordingStartFailedNotification.tsx b/packages/react-native-room-kit/src/components/HMSRecordingStartFailedNotification.tsx deleted file mode 100644 index 9fee85eb4..000000000 --- a/packages/react-native-room-kit/src/components/HMSRecordingStartFailedNotification.tsx +++ /dev/null @@ -1,77 +0,0 @@ -import * as React from 'react'; - -import { HMSNotification } from './HMSNotification'; -import { RecordingIcon } from '../Icons'; -import { useDispatch } from 'react-redux'; -import { useHMSRoomColorPalette, useHMSRoomStyleSheet, useStartRecording } from '../hooks-util'; -import { removeNotification } from '../redux/actions'; -import { StyleSheet, Text, TouchableHighlight } from 'react-native'; - -export interface HMSRecordingStartFailedNotificationProps { - id: string; - autoDismiss?: boolean; - dismissDelay?: number; -} - -export const HMSRecordingStartFailedNotification: React.FC< - HMSRecordingStartFailedNotificationProps -> = ({ id, autoDismiss, dismissDelay }) => { - const dispatch = useDispatch(); - - const { secondary_dim: secondaryDimColor } = useHMSRoomColorPalette(); - - const hmsRoomStyles = useHMSRoomStyleSheet((theme, typography) => ({ - button: { - backgroundColor: theme.palette.secondary_default, - }, - buttonText: { - color: theme.palette.on_secondary_high, - fontFamily: `${typography.font_family}-SemiBold`, - }, - })); - - const dismissNotification = () => dispatch(removeNotification(id)); - - const { startRecording } = useStartRecording(); - - const retryStartRecording = async () => { - dismissNotification(); - startRecording(); - }; - - return ( - } - text={`Recording failed to start`} - dismissDelay={dismissDelay} - autoDismiss={autoDismiss} - cta={ - - - Retry - - - } - onDismiss={dismissNotification} - /> - ); -}; - -const styles = StyleSheet.create({ - button: { - paddingVertical: 8, - paddingHorizontal: 16, - borderRadius: 8, - marginRight: 16, - }, - buttonText: { - fontSize: 14, - lineHeight: 20, - letterSpacing: 0.25, - }, -}); diff --git a/packages/react-native-room-kit/src/components/PreviewForRoleChangeModal.tsx b/packages/react-native-room-kit/src/components/PreviewForRoleChangeModal.tsx index 99fb886fa..fd66b21d1 100644 --- a/packages/react-native-room-kit/src/components/PreviewForRoleChangeModal.tsx +++ b/packages/react-native-room-kit/src/components/PreviewForRoleChangeModal.tsx @@ -17,7 +17,7 @@ import { import { setRoleChangeRequest } from '../redux/actions'; import { useHMSActions } from '../hooks-sdk'; import { parseMetadata } from '../utils/functions'; -import { NotificationTypes } from '../utils'; +import { NotificationTypes } from '../types'; import { Header } from './Header'; import { selectCanPublishTrackForRole } from '../hooks-sdk-selectors'; import { HMSPrimaryButton } from './HMSPrimaryButton'; diff --git a/packages/react-native-room-kit/src/hooks-util.ts b/packages/react-native-room-kit/src/hooks-util.ts index bd1edbb81..9d33fc686 100644 --- a/packages/react-native-room-kit/src/hooks-util.ts +++ b/packages/react-native-room-kit/src/hooks-util.ts @@ -129,7 +129,7 @@ import { import type { GridViewRefAttrs } from './components/GridView'; import { getRoomLayout } from './modules/HMSManager'; import { DEFAULT_THEME, DEFAULT_TYPOGRAPHY } from './utils/theme'; -import { NotificationTypes } from './utils'; +import { NotificationTypes } from './types'; export const useHMSListeners = ( setPeerTrackNodes: React.Dispatch> @@ -2192,60 +2192,27 @@ export const useHMSConferencingScreenConfig = ( export const useStartRecording = () => { const dispatch = useDispatch(); const hmsInstance = useHMSInstance(); - const reduxState = useStore(); - // const isRecordingOn = useSelector( - // (state: RootState) => !!state.hmsStates.room?.browserRecordingState?.running - // ); - - const removeRecordingNotification = useCallback(() => { - const allNotifications = reduxState.getState().app.notifications; - const recordingFailedNotification = allNotifications.find( - (notification) => - notification.type === NotificationTypes.RECORDING_START_FAILED - ); - - if (recordingFailedNotification) { - dispatch(removeNotification(recordingFailedNotification.id)); - } - }, []); - - const addRecordingNotification = useCallback(() => { - const allNotifications = reduxState.getState().app.notifications; - const recordingFailedNotification = allNotifications.find( - (notification) => - notification.type === NotificationTypes.RECORDING_START_FAILED - ); - - if (!recordingFailedNotification) { - dispatch( - addNotification({ - id: NotificationTypes.RECORDING_START_FAILED, - type: NotificationTypes.RECORDING_START_FAILED, - }) - ); - } - }, []); const startRecording = useCallback(() => { dispatch(setStartingOrStoppingRecording(true)); hmsInstance .startRTMPOrRecording({ record: true }) - .then(() => { - removeRecordingNotification(); - }) .catch((error) => { batch(() => { dispatch(setStartingOrStoppingRecording(false)); - // DOUBT: show error when it is because of "Recording" is already started? - addRecordingNotification(); + dispatch( + addNotification({ + id: Math.random().toString(16).slice(2), + type: NotificationTypes.EXCEPTION, + message: error.message + }) + ); }); }); - }, [removeRecordingNotification, addRecordingNotification, hmsInstance]); + }, [hmsInstance]); return { startRecording, - removeRecordingNotification, - addRecordingNotification, }; }; diff --git a/packages/react-native-room-kit/src/redux/reducers/appState.ts b/packages/react-native-room-kit/src/redux/reducers/appState.ts index 2585dd194..d7c0967de 100644 --- a/packages/react-native-room-kit/src/redux/reducers/appState.ts +++ b/packages/react-native-room-kit/src/redux/reducers/appState.ts @@ -12,7 +12,6 @@ import { } from '@100mslive/react-native-hms'; import { MeetingState } from '../../types'; import type { Notification } from '../../types'; -import { NotificationTypes } from '../../utils'; type ActionType = { payload: { [key: string]: any }; @@ -79,7 +78,7 @@ const INITIAL_STATE: IntialStateType = { startingOrStoppingRecording: false, fullScreenPeerTrackNode: null, screensharePeerTrackNodes: [], - notifications: [{ id: NotificationTypes.RECORDING_START_FAILED, type: NotificationTypes.RECORDING_START_FAILED }], + notifications: [], activeChatBottomSheetTab: ChatBottomSheetTabs[0], chatFilterSheetVisible: false, }; diff --git a/packages/react-native-room-kit/src/types.ts b/packages/react-native-room-kit/src/types.ts index 562c06071..a58975ac0 100644 --- a/packages/react-native-room-kit/src/types.ts +++ b/packages/react-native-room-kit/src/types.ts @@ -8,7 +8,15 @@ export enum MeetingState { ERROR, } +export enum NotificationTypes { + ROLE_CHANGE_DECLINED = 'role_change_declined', + HAND_RAISE = 'hand_raise', + LOCAL_SCREENSHARE = 'local_screenshare', + EXCEPTION = 'exception', +} + export type Notification = - | { id: string; type: string; } - | { id: string; type: string; peer: HMSPeer; } - | { id: string; type: string; error: HMSException; } \ No newline at end of file + | { id: string; type: NotificationTypes; } + | { id: string; type: NotificationTypes; message: string; } + | { id: string; type: NotificationTypes; peer: HMSPeer; } + | { id: string; type: NotificationTypes; exception: HMSException; } diff --git a/packages/react-native-room-kit/src/utils.ts b/packages/react-native-room-kit/src/utils.ts index 6e881d5d9..ca377108e 100644 --- a/packages/react-native-room-kit/src/utils.ts +++ b/packages/react-native-room-kit/src/utils.ts @@ -22,10 +22,3 @@ export const getJoinConfig = (): typeof DEFAULT_JOINING_CONFIG => { return config; }; - -export enum NotificationTypes { - ROLE_CHANGE_DECLINED = 'role_change_declined', - HAND_RAISE = 'hand_raise', - LOCAL_SCREENSHARE = 'local_screenshare', - RECORDING_START_FAILED = 'recording_start_failed', -} From 6281e662ebd20be01234e35fcf7f4885d5d21dcb Mon Sep 17 00:00:00 2001 From: Jatin Nagar Date: Fri, 20 Oct 2023 16:46:02 +0530 Subject: [PATCH 09/21] refactor(sdk): :recycle: removed `ON_ERROR` emit code from `join` method --- .../java/com/reactnativehmssdk/HMSRNSDK.kt | 344 +++++++++--------- 1 file changed, 172 insertions(+), 172 deletions(-) diff --git a/packages/react-native-hms/android/src/main/java/com/reactnativehmssdk/HMSRNSDK.kt b/packages/react-native-hms/android/src/main/java/com/reactnativehmssdk/HMSRNSDK.kt index 7cc5e9dcc..c1e76fa66 100644 --- a/packages/react-native-hms/android/src/main/java/com/reactnativehmssdk/HMSRNSDK.kt +++ b/packages/react-native-hms/android/src/main/java/com/reactnativehmssdk/HMSRNSDK.kt @@ -297,216 +297,212 @@ class HMSRNSDK( val config = HMSHelper.getHmsConfig(credentials) HMSCoroutineScope.launch { - try { - hmsSDK?.join( - config, - object : HMSUpdateListener { - override fun onChangeTrackStateRequest(details: HMSChangeTrackStateRequest) { - if (eventsEnableStatus["ON_CHANGE_TRACK_STATE_REQUEST"] != true) { - return - } - val decodedChangeTrackStateRequest = - HMSDecoder.getHmsChangeTrackStateRequest(details, id) - delegate.emitEvent( - "ON_CHANGE_TRACK_STATE_REQUEST", - decodedChangeTrackStateRequest, - ) + hmsSDK?.join( + config, + object : HMSUpdateListener { + override fun onChangeTrackStateRequest(details: HMSChangeTrackStateRequest) { + if (eventsEnableStatus["ON_CHANGE_TRACK_STATE_REQUEST"] != true) { + return } + val decodedChangeTrackStateRequest = + HMSDecoder.getHmsChangeTrackStateRequest(details, id) + delegate.emitEvent( + "ON_CHANGE_TRACK_STATE_REQUEST", + decodedChangeTrackStateRequest, + ) + } - override fun onRemovedFromRoom(notification: HMSRemovedFromRoom) { - super.onRemovedFromRoom(notification) - if (eventsEnableStatus["ON_REMOVED_FROM_ROOM"] != true) { - cleanup() // resetting states and doing data cleanup - return - } - val data: WritableMap = Arguments.createMap() - val requestedBy = - HMSDecoder.getHmsRemotePeer(notification.peerWhoRemoved as HMSRemotePeer?) - val roomEnded = notification.roomWasEnded - val reason = notification.reason - - data.putMap("requestedBy", requestedBy) - data.putBoolean("roomEnded", roomEnded) - data.putString("reason", reason) - data.putString("id", id) - - delegate.emitEvent("ON_REMOVED_FROM_ROOM", data) + override fun onRemovedFromRoom(notification: HMSRemovedFromRoom) { + super.onRemovedFromRoom(notification) + if (eventsEnableStatus["ON_REMOVED_FROM_ROOM"] != true) { cleanup() // resetting states and doing data cleanup + return } + val data: WritableMap = Arguments.createMap() + val requestedBy = + HMSDecoder.getHmsRemotePeer(notification.peerWhoRemoved as HMSRemotePeer?) + val roomEnded = notification.roomWasEnded + val reason = notification.reason + + data.putMap("requestedBy", requestedBy) + data.putBoolean("roomEnded", roomEnded) + data.putString("reason", reason) + data.putString("id", id) - override fun onError(error: HMSException) { - if (eventsEnableStatus["ON_ERROR"] != true) { - return - } - self.emitHMSError(error) + delegate.emitEvent("ON_REMOVED_FROM_ROOM", data) + cleanup() // resetting states and doing data cleanup + } + + override fun onError(error: HMSException) { + if (eventsEnableStatus["ON_ERROR"] != true) { + return } + self.emitHMSError(error) + } - override fun onJoin(room: HMSRoom) { - if (eventsEnableStatus["ON_JOIN"] != true) { - return - } - val roomData = HMSDecoder.getHmsRoomSubset(room) + override fun onJoin(room: HMSRoom) { + if (eventsEnableStatus["ON_JOIN"] != true) { + return + } + val roomData = HMSDecoder.getHmsRoomSubset(room) - val data: WritableMap = Arguments.createMap() + val data: WritableMap = Arguments.createMap() - data.putMap("room", roomData) - data.putString("id", id) - delegate.emitEvent("ON_JOIN", data) - } + data.putMap("room", roomData) + data.putString("id", id) + delegate.emitEvent("ON_JOIN", data) + } - override fun onPeerUpdate( - type: HMSPeerUpdate, - peer: HMSPeer, + override fun onPeerUpdate( + type: HMSPeerUpdate, + peer: HMSPeer, + ) { + if (eventsEnableStatus["3"] != true) { + return + } + if (type === HMSPeerUpdate.BECAME_DOMINANT_SPEAKER || + type === HMSPeerUpdate.NO_DOMINANT_SPEAKER ) { - if (eventsEnableStatus["3"] != true) { - return - } - if (type === HMSPeerUpdate.BECAME_DOMINANT_SPEAKER || - type === HMSPeerUpdate.NO_DOMINANT_SPEAKER - ) { - return - } - if (!networkQualityUpdatesAttached && - type === HMSPeerUpdate.NETWORK_QUALITY_UPDATED - ) { - return - } - val hmsPeer = HMSDecoder.getHmsPeerSubsetForPeerUpdateEvent(peer, type) - delegate.emitEvent("3", hmsPeer) + return } - - override fun onRoomUpdate( - type: HMSRoomUpdate, - hmsRoom: HMSRoom, + if (!networkQualityUpdatesAttached && + type === HMSPeerUpdate.NETWORK_QUALITY_UPDATED ) { - if (eventsEnableStatus["ON_ROOM_UPDATE"] != true) { - return - } + return + } + val hmsPeer = HMSDecoder.getHmsPeerSubsetForPeerUpdateEvent(peer, type) + delegate.emitEvent("3", hmsPeer) + } - val updateType = type.name - val roomData = HMSDecoder.getHmsRoomSubset(hmsRoom, type) + override fun onRoomUpdate( + type: HMSRoomUpdate, + hmsRoom: HMSRoom, + ) { + if (eventsEnableStatus["ON_ROOM_UPDATE"] != true) { + return + } + + val updateType = type.name + val roomData = HMSDecoder.getHmsRoomSubset(hmsRoom, type) - val data: WritableMap = Arguments.createMap() + val data: WritableMap = Arguments.createMap() - data.putString("type", updateType) - data.putMap("room", roomData) - data.putString("id", id) - delegate.emitEvent("ON_ROOM_UPDATE", data) + data.putString("type", updateType) + data.putMap("room", roomData) + data.putString("id", id) + delegate.emitEvent("ON_ROOM_UPDATE", data) + } + + override fun onTrackUpdate( + type: HMSTrackUpdate, + track: HMSTrack, + peer: HMSPeer, + ) { + if (eventsEnableStatus["ON_TRACK_UPDATE"] != true) { + return } + val updateType = type.name + val hmsPeer = HMSDecoder.getHmsPeerSubset(peer) + val hmsTrack = HMSDecoder.getHmsTrack(track) - override fun onTrackUpdate( - type: HMSTrackUpdate, - track: HMSTrack, - peer: HMSPeer, - ) { - if (eventsEnableStatus["ON_TRACK_UPDATE"] != true) { - return - } - val updateType = type.name - val hmsPeer = HMSDecoder.getHmsPeerSubset(peer) - val hmsTrack = HMSDecoder.getHmsTrack(track) + val data: WritableMap = Arguments.createMap() - val data: WritableMap = Arguments.createMap() + data.putMap("peer", hmsPeer) + data.putMap("track", hmsTrack) + data.putString("type", updateType) + data.putString("id", id) + delegate.emitEvent("ON_TRACK_UPDATE", data) + } - data.putMap("peer", hmsPeer) - data.putMap("track", hmsTrack) - data.putString("type", updateType) - data.putString("id", id) - delegate.emitEvent("ON_TRACK_UPDATE", data) + override fun onMessageReceived(message: HMSMessage) { + if (eventsEnableStatus["ON_MESSAGE"] != true) { + return } + val data: WritableMap = Arguments.createMap() - override fun onMessageReceived(message: HMSMessage) { - if (eventsEnableStatus["ON_MESSAGE"] != true) { - return - } - val data: WritableMap = Arguments.createMap() + data.putMap("sender", HMSDecoder.getHmsPeerSubset(message.sender)) + data.putString("message", message.message) + data.putString("messageId", message.messageId) + data.putString("type", message.type) + data.putString("time", message.serverReceiveTime.toString()) + data.putString("id", id) + data.putMap("recipient", HMSDecoder.getHmsMessageRecipient(message.recipient)) - data.putMap("sender", HMSDecoder.getHmsPeerSubset(message.sender)) - data.putString("message", message.message) - data.putString("messageId", message.messageId) - data.putString("type", message.type) - data.putString("time", message.serverReceiveTime.toString()) - data.putString("id", id) - data.putMap("recipient", HMSDecoder.getHmsMessageRecipient(message.recipient)) + delegate.emitEvent("ON_MESSAGE", data) + } - delegate.emitEvent("ON_MESSAGE", data) + override fun onReconnected() { + reconnectingStage = false + if (eventsEnableStatus["RECONNECTED"] != true) { + return } + val data: WritableMap = Arguments.createMap() + data.putString("event", "RECONNECTED") + data.putString("id", id) + delegate.emitEvent("RECONNECTED", data) + } - override fun onReconnected() { - reconnectingStage = false - if (eventsEnableStatus["RECONNECTED"] != true) { - return - } - val data: WritableMap = Arguments.createMap() - data.putString("event", "RECONNECTED") - data.putString("id", id) - delegate.emitEvent("RECONNECTED", data) + override fun onReconnecting(error: HMSException) { + reconnectingStage = true + if (eventsEnableStatus["RECONNECTING"] != true) { + return } + val data: WritableMap = Arguments.createMap() + data.putMap("error", HMSDecoder.getError(error)) + data.putString("event", "RECONNECTING") + data.putString("id", id) + delegate.emitEvent("RECONNECTING", data) + } - override fun onReconnecting(error: HMSException) { - reconnectingStage = true - if (eventsEnableStatus["RECONNECTING"] != true) { - return - } - val data: WritableMap = Arguments.createMap() - data.putMap("error", HMSDecoder.getError(error)) - data.putString("event", "RECONNECTING") - data.putString("id", id) - delegate.emitEvent("RECONNECTING", data) + override fun onRoleChangeRequest(request: HMSRoleChangeRequest) { + recentRoleChangeRequest = request + if (eventsEnableStatus["ON_ROLE_CHANGE_REQUEST"] != true) { + return } + val decodedChangeRoleRequest = HMSDecoder.getHmsRoleChangeRequest(request, id) + delegate.emitEvent("ON_ROLE_CHANGE_REQUEST", decodedChangeRoleRequest) + } - override fun onRoleChangeRequest(request: HMSRoleChangeRequest) { - recentRoleChangeRequest = request - if (eventsEnableStatus["ON_ROLE_CHANGE_REQUEST"] != true) { - return - } - val decodedChangeRoleRequest = HMSDecoder.getHmsRoleChangeRequest(request, id) - delegate.emitEvent("ON_ROLE_CHANGE_REQUEST", decodedChangeRoleRequest) + override fun onSessionStoreAvailable(sessionStore: HmsSessionStore) { + self.sessionStore = sessionStore + if (eventsEnableStatus["ON_SESSION_STORE_AVAILABLE"] != true) { + return } + val data: WritableMap = Arguments.createMap() + data.putString("id", id) + delegate.emitEvent("ON_SESSION_STORE_AVAILABLE", data) + } - override fun onSessionStoreAvailable(sessionStore: HmsSessionStore) { - self.sessionStore = sessionStore - if (eventsEnableStatus["ON_SESSION_STORE_AVAILABLE"] != true) { - return - } - val data: WritableMap = Arguments.createMap() - data.putString("id", id) - delegate.emitEvent("ON_SESSION_STORE_AVAILABLE", data) + override fun peerListUpdated( + addedPeers: ArrayList?, + removedPeers: ArrayList?, + ) { + if (eventsEnableStatus["ON_PEER_LIST_UPDATED"] != true) { + return } + val data: WritableMap = Arguments.createMap() + val addedPeersArray: WritableArray = Arguments.createArray() + val removedPeersArray: WritableArray = Arguments.createArray() - override fun peerListUpdated( - addedPeers: ArrayList?, - removedPeers: ArrayList?, - ) { - if (eventsEnableStatus["ON_PEER_LIST_UPDATED"] != true) { - return - } - val data: WritableMap = Arguments.createMap() - val addedPeersArray: WritableArray = Arguments.createArray() - val removedPeersArray: WritableArray = Arguments.createArray() - - if (addedPeers != null) { - for (peer in addedPeers) { - addedPeersArray.pushMap(HMSDecoder.getHmsPeerSubset(peer)) - } + if (addedPeers != null) { + for (peer in addedPeers) { + addedPeersArray.pushMap(HMSDecoder.getHmsPeerSubset(peer)) } + } - if (removedPeers != null) { - for (peer in removedPeers) { - removedPeersArray.pushMap(HMSDecoder.getHmsPeerSubset(peer)) - } + if (removedPeers != null) { + for (peer in removedPeers) { + removedPeersArray.pushMap(HMSDecoder.getHmsPeerSubset(peer)) } - - data.putString("id", id) - data.putArray("addedPeers", addedPeersArray) - data.putArray("removedPeers", removedPeersArray) - delegate.emitEvent("ON_PEER_LIST_UPDATED", data) } - }, - ) - } catch (e: HMSException) { - self.emitHMSError(e) - } + + data.putString("id", id) + data.putArray("addedPeers", addedPeersArray) + data.putArray("removedPeers", removedPeersArray) + delegate.emitEvent("ON_PEER_LIST_UPDATED", data) + } + }, + ) hmsSDK?.addAudioObserver( object : HMSAudioListener { @@ -1454,6 +1450,10 @@ class HMSRNSDK( data: ReadableMap, callback: Promise?, ) { + val errorMessage = "startRTMPOrRecording: Custom Temporary Error" + rejectCallback(callback, errorMessage) + return + val requiredKeys = HMSHelper.getUnavailableRequiredKey( data, From 2f936a4c1caf7a63e32e63da72ae6c0007a03e46 Mon Sep 17 00:00:00 2001 From: Jatin Nagar Date: Fri, 20 Oct 2023 16:55:02 +0530 Subject: [PATCH 10/21] add notification on ON_ERROR event when user is inside meeting --- .../src/HMSRoomSetup.tsx | 65 +++++++++++-------- 1 file changed, 38 insertions(+), 27 deletions(-) diff --git a/packages/react-native-room-kit/src/HMSRoomSetup.tsx b/packages/react-native-room-kit/src/HMSRoomSetup.tsx index 2c6c339cb..30a299b7c 100644 --- a/packages/react-native-room-kit/src/HMSRoomSetup.tsx +++ b/packages/react-native-room-kit/src/HMSRoomSetup.tsx @@ -18,6 +18,7 @@ import { batch, useDispatch, useSelector, useStore } from 'react-redux'; import { Preview } from './components'; import { + addNotification, changeMeetingState, changeStartingHLSStream, clearStore, @@ -47,7 +48,7 @@ import { replacePeerTrackNodes, peerTrackNodeExistForPeer, } from './peerTrackNodeUtils'; -import { MeetingState } from './types'; +import { MeetingState, NotificationTypes } from './types'; import { getJoinConfig } from './utils'; import { FullScreenIndicator } from './components/FullScreenIndicator'; import { HMSMeetingEnded } from './components/HMSMeetingEnded'; @@ -126,34 +127,46 @@ export const HMSRoomSetup = () => { */ useHMSSessionStore(); + const meetingJoined = meetingState === MeetingState.IN_MEETING; + // HMS Error Listener useEffect(() => { const hmsErrorHandler = (error: HMSException) => { - setLoading(false); - - // TODO: 424 error is not recoverable - // (Leave Meeting and Destroy Instance) ??? - // Inform user with Alert or Error screen and send user back - if (error.code === 424) { - Alert.alert('Error', error.description || 'Something went wrong', [ - { text: 'OK', style: 'cancel', onPress: () => {} }, - ]); - } else if ( - Platform.OS === 'android' - ? error.code === 4005 || error.code === 1003 - : error.code === 2000 - ) { - // TODO: come up with Error Handle mechanism + if (meetingJoined) { + dispatch( + addNotification({ + id: Math.random().toString(16).slice(2), + exception: error, + type: NotificationTypes.EXCEPTION, + }) + ); + } else { + setLoading(false); + + // TODO: 424 error is not recoverable // (Leave Meeting and Destroy Instance) ??? - // Clear Redux Store? - // Inform user with Alert or Error screen and send user back (Navigation) - } + // Inform user with Alert or Error screen and send user back + if (error.code === 424) { + Alert.alert('Error', error.description || 'Something went wrong', [ + { text: 'OK', style: 'cancel', onPress: () => {} }, + ]); + } else if ( + Platform.OS === 'android' + ? error.code === 4005 || error.code === 1003 + : error.code === 2000 + ) { + // TODO: come up with Error Handle mechanism + // (Leave Meeting and Destroy Instance) ??? + // Clear Redux Store? + // Inform user with Alert or Error screen and send user back (Navigation) + } - Toast.showWithGravity( - `${error?.code} ${error?.description}` || 'Something went wrong', - Toast.LONG, - Toast.TOP - ); + Toast.showWithGravity( + `${error?.code} ${error?.description}` || 'Something went wrong', + Toast.LONG, + Toast.TOP + ); + } }; hmsInstance.addEventListener( @@ -164,7 +177,7 @@ export const HMSRoomSetup = () => { return () => { hmsInstance.removeEventListener(HMSUpdateListenerActions.ON_ERROR); }; - }, [hmsInstance]); + }, [meetingJoined, hmsInstance]); // HMS Preview Listener useEffect(() => { @@ -294,8 +307,6 @@ export const HMSRoomSetup = () => { }; }, [startHLSStreaming, hmsInstance]); - const meetingJoined = meetingState === MeetingState.IN_MEETING; - // HMS Active Speaker Listener // dev-note: This is added here because we have `setPeerTrackNodes` here useHMSActiveSpeakerUpdates(setPeerTrackNodes, meetingJoined); From e38cbfb784ca5c5b3bd5748c1bf83735b2e56223 Mon Sep 17 00:00:00 2001 From: Jatin Nagar Date: Fri, 20 Oct 2023 16:55:59 +0530 Subject: [PATCH 11/21] removed temp code --- .../android/src/main/java/com/reactnativehmssdk/HMSRNSDK.kt | 4 ---- 1 file changed, 4 deletions(-) diff --git a/packages/react-native-hms/android/src/main/java/com/reactnativehmssdk/HMSRNSDK.kt b/packages/react-native-hms/android/src/main/java/com/reactnativehmssdk/HMSRNSDK.kt index c1e76fa66..e576521b9 100644 --- a/packages/react-native-hms/android/src/main/java/com/reactnativehmssdk/HMSRNSDK.kt +++ b/packages/react-native-hms/android/src/main/java/com/reactnativehmssdk/HMSRNSDK.kt @@ -1450,10 +1450,6 @@ class HMSRNSDK( data: ReadableMap, callback: Promise?, ) { - val errorMessage = "startRTMPOrRecording: Custom Temporary Error" - rejectCallback(callback, errorMessage) - return - val requiredKeys = HMSHelper.getUnavailableRequiredKey( data, From a8c9b40231b29c37ebcccae168469fdb726cd57a Mon Sep 17 00:00:00 2001 From: Jatin Nagar Date: Fri, 20 Oct 2023 17:18:36 +0530 Subject: [PATCH 12/21] =?UTF-8?q?released=20sample=20app=20version=202.3.8?= =?UTF-8?q?8=20(339)=20=E2=9A=9B=EF=B8=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../example/android/app/build.gradle | 4 ++-- .../react-native-room-kit/example/ios/Podfile.lock | 6 +++--- .../example/ios/RNExample.xcodeproj/project.pbxproj | 10 +++++----- .../example/ios/RNExample/Info.plist | 4 ++-- 4 files changed, 12 insertions(+), 12 deletions(-) diff --git a/packages/react-native-room-kit/example/android/app/build.gradle b/packages/react-native-room-kit/example/android/app/build.gradle index 745cb2826..b6e0e6238 100644 --- a/packages/react-native-room-kit/example/android/app/build.gradle +++ b/packages/react-native-room-kit/example/android/app/build.gradle @@ -136,8 +136,8 @@ android { applicationId "live.hms.rn" minSdkVersion rootProject.ext.minSdkVersion targetSdkVersion rootProject.ext.targetSdkVersion - versionCode 338 - versionName "2.3.87" + versionCode 339 + versionName "2.3.88" missingDimensionStrategy 'react-native-camera', 'general' } diff --git a/packages/react-native-room-kit/example/ios/Podfile.lock b/packages/react-native-room-kit/example/ios/Podfile.lock index 8ee3e51aa..8d4bac598 100644 --- a/packages/react-native-room-kit/example/ios/Podfile.lock +++ b/packages/react-native-room-kit/example/ios/Podfile.lock @@ -318,7 +318,7 @@ PODS: - React-Core - react-native-camera/RN (4.2.1): - React-Core - - react-native-hms (1.9.0): + - react-native-hms (1.9.1): - HMSBroadcastExtensionSDK (= 0.0.9) - HMSHLSPlayerSDK (= 0.0.2) - HMSSDK (= 1.1.0) @@ -690,7 +690,7 @@ SPEC CHECKSUMS: React-logger: a1f028f6d8639a3f364ef80419e5e862e1115250 react-native-blur: cfdad7b3c01d725ab62a8a729f42ea463998afa2 react-native-camera: 3eae183c1d111103963f3dd913b65d01aef8110f - react-native-hms: e17e01ae2d414da43fc950a2421b404ab0512fde + react-native-hms: e119fe54d8688312472d9f16d920a5c4843124f3 react-native-lottie-splash-screen: 015423265bac5f46016dff2e31c97b9590808856 react-native-safe-area-context: 61c8c484a3a9e7d1fda19f7b1794b35bbfd2262a react-native-simple-toast: bf002828cf816775a6809f7a9ec3907509bce11f @@ -720,4 +720,4 @@ SPEC CHECKSUMS: PODFILE CHECKSUM: 2f8bb268fdf8935f02cc94ce995708d84df28c61 -COCOAPODS: 1.13.0 +COCOAPODS: 1.12.1 diff --git a/packages/react-native-room-kit/example/ios/RNExample.xcodeproj/project.pbxproj b/packages/react-native-room-kit/example/ios/RNExample.xcodeproj/project.pbxproj index c6230bb96..c5c70a0ef 100644 --- a/packages/react-native-room-kit/example/ios/RNExample.xcodeproj/project.pbxproj +++ b/packages/react-native-room-kit/example/ios/RNExample.xcodeproj/project.pbxproj @@ -346,7 +346,7 @@ ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "set -e\n\nexport NODE_BINARY=node\n../node_modules/react-native/scripts/react-native-xcode.sh\n"; + shellScript = "set -e\n\nexport NODE_BINARY=node\nexport NODE_OPTIONS=--openssl-legacy-provider\n../node_modules/react-native/scripts/react-native-xcode.sh\n"; }; 3E482C27206C4DEF2FE45063 /* [CP] Check Pods Manifest.lock */ = { isa = PBXShellScriptBuildPhase; @@ -486,7 +486,7 @@ CODE_SIGN_ENTITLEMENTS = RNExample/RNExample.entitlements; CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 338; + CURRENT_PROJECT_VERSION = 339; DEVELOPMENT_TEAM = 5N85PP82A9; ENABLE_BITCODE = NO; INFOPLIST_FILE = RNExample/Info.plist; @@ -520,7 +520,7 @@ CODE_SIGN_ENTITLEMENTS = RNExample/RNExample.entitlements; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Distribution"; CODE_SIGN_STYLE = Manual; - CURRENT_PROJECT_VERSION = 338; + CURRENT_PROJECT_VERSION = 339; DEVELOPMENT_TEAM = ""; "DEVELOPMENT_TEAM[sdk=iphoneos*]" = 5N85PP82A9; INFOPLIST_FILE = RNExample/Info.plist; @@ -679,7 +679,7 @@ CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; CODE_SIGN_ENTITLEMENTS = RNExampleBroadcastUpload/RNExampleBroadcastUpload.entitlements; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 338; + CURRENT_PROJECT_VERSION = 339; DEBUG_INFORMATION_FORMAT = dwarf; DEVELOPMENT_TEAM = 5N85PP82A9; GCC_C_LANGUAGE_STANDARD = gnu11; @@ -721,7 +721,7 @@ "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Distribution"; CODE_SIGN_STYLE = Manual; COPY_PHASE_STRIP = NO; - CURRENT_PROJECT_VERSION = 338; + CURRENT_PROJECT_VERSION = 339; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; DEVELOPMENT_TEAM = ""; "DEVELOPMENT_TEAM[sdk=iphoneos*]" = 5N85PP82A9; diff --git a/packages/react-native-room-kit/example/ios/RNExample/Info.plist b/packages/react-native-room-kit/example/ios/RNExample/Info.plist index 87f91d268..0e0e5d87f 100644 --- a/packages/react-native-room-kit/example/ios/RNExample/Info.plist +++ b/packages/react-native-room-kit/example/ios/RNExample/Info.plist @@ -21,11 +21,11 @@ CFBundlePackageType APPL CFBundleShortVersionString - 2.3.87 + 2.3.88 CFBundleSignature ???? CFBundleVersion - 338 + 339 ITSAppUsesNonExemptEncryption LSRequiresIPhoneOS From ff6a0baddc98e7310c5500d5a0ca7f48c489fde9 Mon Sep 17 00:00:00 2001 From: Jatin Nagar Date: Fri, 20 Oct 2023 19:32:00 +0530 Subject: [PATCH 13/21] refactor(prebuilt): :recycle: extracted LeaveRoom and EndRoom modals out of `HMSManageLeave` component --- .../src/components/DisplayView.tsx | 6 + .../src/components/EndRoomModal.tsx | 24 ++ .../src/components/HMSManageLeave.tsx | 232 +----------------- .../src/components/LeaveRoomBottomSheet.tsx | 199 +++++++++++++++ 4 files changed, 233 insertions(+), 228 deletions(-) create mode 100644 packages/react-native-room-kit/src/components/EndRoomModal.tsx create mode 100644 packages/react-native-room-kit/src/components/LeaveRoomBottomSheet.tsx diff --git a/packages/react-native-room-kit/src/components/DisplayView.tsx b/packages/react-native-room-kit/src/components/DisplayView.tsx index f3403856a..e41b1a4c3 100644 --- a/packages/react-native-room-kit/src/components/DisplayView.tsx +++ b/packages/react-native-room-kit/src/components/DisplayView.tsx @@ -36,6 +36,8 @@ import { BottomSheet } from './BottomSheet'; import { FullScreenVideoView } from './FullScreenVideoView'; import { PreviewForRoleChangeModal } from './PreviewForRoleChangeModal'; import { ChatAndParticipantsBottomSheet } from './ChatAndParticipants'; +import { LeaveRoomBottomSheet } from './LeaveRoomBottomSheet'; +import { EndRoomModal } from './EndRoomModal'; type CapturedImagePath = { uri: string } | null; @@ -150,6 +152,10 @@ export const DisplayView: React.FC = ({ {isPipModeActive ? null : ( <> + + + + diff --git a/packages/react-native-room-kit/src/components/EndRoomModal.tsx b/packages/react-native-room-kit/src/components/EndRoomModal.tsx new file mode 100644 index 000000000..b5403120b --- /dev/null +++ b/packages/react-native-room-kit/src/components/EndRoomModal.tsx @@ -0,0 +1,24 @@ +import * as React from 'react'; + +import { ModalTypes } from '../utils/types'; +import { BottomSheet } from './BottomSheet'; +import { useModalType } from '../hooks-util'; +import { EndRoomModalContent } from './EndRoomModalContent'; + +interface EndRoomModalProps {} + +export const EndRoomModal: React.FC = () => { + const { modalVisibleType, handleModalVisibleType } = useModalType(); + + const dismissModal = () => handleModalVisibleType(ModalTypes.DEFAULT); + + return ( + + + + ); +}; diff --git a/packages/react-native-room-kit/src/components/HMSManageLeave.tsx b/packages/react-native-room-kit/src/components/HMSManageLeave.tsx index 349a4d8ad..2b63a52b1 100644 --- a/packages/react-native-room-kit/src/components/HMSManageLeave.tsx +++ b/packages/react-native-room-kit/src/components/HMSManageLeave.tsx @@ -1,15 +1,10 @@ import * as React from 'react'; -import { StyleSheet, Text, TouchableOpacity, View } from 'react-native'; -import { useSelector } from 'react-redux'; +import { View } from 'react-native'; import { LeaveIcon } from '../Icons'; -import { useHMSRoomStyleSheet, useLeaveMethods } from '../hooks-util'; -import type { RootState } from '../redux'; +import { useHMSRoomStyleSheet, useModalType } from '../hooks-util'; import { ModalTypes } from '../utils/types'; import { PressableIcon } from './PressableIcon'; -import { BottomSheet } from './BottomSheet'; -import { StopIcon } from '../Icons'; -import { EndRoomModalContent } from './EndRoomModalContent'; import { COLORS } from '../utils/theme'; export const HMSManageLeave: React.FC = (props) => { @@ -32,62 +27,15 @@ type LeaveButtonProps = }; const LeaveButton: React.FC = (props) => { - const leavePopCloseAction = React.useRef(ModalTypes.DEFAULT); - const [leavePopVisible, setLeavePopVisible] = React.useState(false); - const [leaveModalType, setLeaveModalType] = React.useState( - ModalTypes.DEFAULT - ); - - const { leave } = useLeaveMethods(false); + const { handleModalVisibleType } = useModalType(); /** * Opens the Leave Popup Menu */ const handleLeaveButtonPress = () => { - setLeavePopVisible(true); - }; - - /** - * Closes the Leave Popup Menu - * Leave Modal will open after the popup is hidden - */ - const handleLeavePress = async () => { - setLeavePopVisible(false); - await leave(); - }; - - /** - * Closes the Leave Popup Menu - * End Session Modal will open after the popup is hidden - */ - const handleEndSessionPress = async () => { - leavePopCloseAction.current = ModalTypes.END_ROOM; - setLeavePopVisible(false); - }; - - const handleEndStreamPress = async () => { - leavePopCloseAction.current = ModalTypes.END_ROOM; - setLeavePopVisible(false); + handleModalVisibleType(ModalTypes.LEAVE_ROOM); }; - /** - * Closes the Leave Popup Menu - * No action is taken when the popup is hidden - */ - const dismissPopup = () => { - leavePopCloseAction.current = ModalTypes.DEFAULT; - setLeavePopVisible(false); - }; - - /** - * Handles action to take when the leave popup is hidden - */ - const handlePopupHide = () => { - setLeaveModalType(leavePopCloseAction.current); - }; - - const dismissModal = () => setLeaveModalType(ModalTypes.DEFAULT); - const hmsRoomStyles = useHMSRoomStyleSheet((theme) => ({ button: { backgroundColor: theme.palette.alert_error_default, @@ -118,178 +66,6 @@ const LeaveButton: React.FC = (props) => { onPress: handleLeaveButtonPress, style: hmsRoomStyles.button, })} - - - - - - ); }; - -// const HEADER_CONTENT_HEIGHT = 24 + 8 + 8 + 2; // ICON_SIZE + TOP_PADDING + BOTTOM_PADDING + TOP&BOTTOM_BORDER_WIDTH -// const HEADER_HEIGHT = 8 + HEADER_CONTENT_HEIGHT + 8; // TOP_HEADER_PADDING + HEADER_CONTENT_HEIGHT + BOTTOM_HEADER_PADDING - -interface LeaveBottomSheetProps { - isVisible: boolean; - onPopupDismiss(): void; - onLeavePress(): void; - onEndSessionPress(): void; - onEndStreamPress(): void; - onPopupHide(): void; -} - -const LeaveBottomSheet: React.FC = ({ - isVisible, - onPopupDismiss, - onLeavePress, - onEndSessionPress, - onEndStreamPress, - onPopupHide, -}) => { - const canEndRoom = useSelector( - (state: RootState) => state.hmsStates.localPeer?.role?.permissions?.endRoom - ); - const canStream = useSelector( - (state: RootState) => - state.hmsStates.localPeer?.role?.permissions?.hlsStreaming - ); - - const isStreaming = useSelector( - (state: RootState) => - state.hmsStates.room?.hlsStreamingState?.running ?? false - ); - - const hmsRoomStyles = useHMSRoomStyleSheet((theme, typography) => ({ - text: { - color: theme.palette.on_surface_high, - fontFamily: `${typography.font_family}-SemiBold`, - }, - subtext: { - color: theme.palette.on_surface_low, - fontFamily: `${typography.font_family}-Regular`, - }, - endButton: { - backgroundColor: theme.palette.alert_error_dim, - }, - endText: { - color: theme.palette.alert_error_brighter, - fontFamily: `${typography.font_family}-SemiBold`, - }, - endSubtext: { - color: theme.palette.alert_error_bright, - fontFamily: `${typography.font_family}-Regular`, - }, - endIcon: { - tintColor: theme.palette.alert_error_brighter, - }, - })); - - return ( - - - - - - - - Leave - - - Others will continue after you leave. You can join the session - again. - - - - - {canStream && isStreaming ? ( - - - - - - End Stream - - - The stream will end for everyone after they’ve watched it. - - - - ) : canEndRoom ? ( - - - - - - End Session - - - The session will end for everyone in the room immediately. - - - - ) : null} - - - ); -}; - -const leavePopupStyles = StyleSheet.create({ - container: { - paddingBottom: 0, - }, - button: { - flexDirection: 'row', - padding: 24, - }, - icon: { - width: 24, - height: 24, - marginRight: 16, - }, - textContainer: { - flex: 1, - }, - text: { - fontSize: 20, - lineHeight: 24, - letterSpacing: 0.15, - }, - subtext: { - fontSize: 14, - lineHeight: 20, - letterSpacing: 0.25, - marginTop: 4, - }, -}); diff --git a/packages/react-native-room-kit/src/components/LeaveRoomBottomSheet.tsx b/packages/react-native-room-kit/src/components/LeaveRoomBottomSheet.tsx new file mode 100644 index 000000000..275683fa0 --- /dev/null +++ b/packages/react-native-room-kit/src/components/LeaveRoomBottomSheet.tsx @@ -0,0 +1,199 @@ +import * as React from 'react'; +import { StyleSheet, Text, TouchableOpacity, View } from 'react-native'; +import { useSelector } from 'react-redux'; + +import { LeaveIcon } from '../Icons'; +import { useHMSRoomStyleSheet, useLeaveMethods, useModalType } from '../hooks-util'; +import type { RootState } from '../redux'; +import { BottomSheet } from './BottomSheet'; +import { StopIcon } from '../Icons'; +import { ModalTypes } from '../utils/types'; + +// const HEADER_CONTENT_HEIGHT = 24 + 8 + 8 + 2; // ICON_SIZE + TOP_PADDING + BOTTOM_PADDING + TOP&BOTTOM_BORDER_WIDTH +// const HEADER_HEIGHT = 8 + HEADER_CONTENT_HEIGHT + 8; // TOP_HEADER_PADDING + HEADER_CONTENT_HEIGHT + BOTTOM_HEADER_PADDING + +interface LeaveRoomBottomSheetProps {} + +export const LeaveRoomBottomSheet: React.FC = () => { + const canEndRoom = useSelector( + (state: RootState) => state.hmsStates.localPeer?.role?.permissions?.endRoom + ); + const canStream = useSelector( + (state: RootState) => + state.hmsStates.localPeer?.role?.permissions?.hlsStreaming + ); + + const isStreaming = useSelector( + (state: RootState) => + state.hmsStates.room?.hlsStreamingState?.running ?? false + ); + + const hmsRoomStyles = useHMSRoomStyleSheet((theme, typography) => ({ + text: { + color: theme.palette.on_surface_high, + fontFamily: `${typography.font_family}-SemiBold`, + }, + subtext: { + color: theme.palette.on_surface_low, + fontFamily: `${typography.font_family}-Regular`, + }, + endButton: { + backgroundColor: theme.palette.alert_error_dim, + }, + endText: { + color: theme.palette.alert_error_brighter, + fontFamily: `${typography.font_family}-SemiBold`, + }, + endSubtext: { + color: theme.palette.alert_error_bright, + fontFamily: `${typography.font_family}-Regular`, + }, + endIcon: { + tintColor: theme.palette.alert_error_brighter, + }, + })); + + const leavePopCloseAction = React.useRef(ModalTypes.DEFAULT); + + const { modalVisibleType, handleModalVisibleType } = useModalType(); + + const { leave } = useLeaveMethods(false); + + /** + * Closes the Leave Popup Menu + * No action is taken when the popup is hidden + */ + const onPopupDismiss = () => { + leavePopCloseAction.current = ModalTypes.DEFAULT; + handleModalVisibleType(ModalTypes.DEFAULT); + }; + + /** + * Closes the Leave Popup Menu + * Leave Modal will open after the popup is hidden + */ + const onLeavePress = async () => { + leavePopCloseAction.current = ModalTypes.DEFAULT; + handleModalVisibleType(ModalTypes.DEFAULT); + await leave(); + }; + + /** + * Closes the Leave Popup Menu + * End Session Modal will open after the popup is hidden + */ + const onEndSessionPress = async () => { + leavePopCloseAction.current = ModalTypes.END_ROOM; + handleModalVisibleType(ModalTypes.DEFAULT); + }; + + const onEndStreamPress = async () => { + leavePopCloseAction.current = ModalTypes.END_ROOM; + handleModalVisibleType(ModalTypes.DEFAULT); + }; + + /** + * Handles action to take when the leave popup is hidden + */ + const handlePopupHide = () => { + if (leavePopCloseAction.current !== ModalTypes.DEFAULT) { + handleModalVisibleType(leavePopCloseAction.current); + } + }; + + return ( + + + + + + + + Leave + + + Others will continue after you leave. You can join the session + again. + + + + + {canStream && isStreaming ? ( + + + + + + End Stream + + + The stream will end for everyone after they’ve watched it. + + + + ) : canEndRoom ? ( + + + + + + End Session + + + The session will end for everyone in the room immediately. + + + + ) : null} + + + ); +}; + +const styles = StyleSheet.create({ + container: { + paddingBottom: 0, + }, + button: { + flexDirection: 'row', + padding: 24, + }, + icon: { + width: 24, + height: 24, + marginRight: 16, + }, + textContainer: { + flex: 1, + }, + text: { + fontSize: 20, + lineHeight: 24, + letterSpacing: 0.15, + }, + subtext: { + fontSize: 14, + lineHeight: 20, + letterSpacing: 0.25, + marginTop: 4, + }, +}); From 0831736ea9f1b1c8f13cf614c70538cd6f7ac883 Mon Sep 17 00:00:00 2001 From: Jatin Nagar Date: Fri, 20 Oct 2023 20:09:11 +0530 Subject: [PATCH 14/21] feat(prebuilt): :sparkles: added "Leave" button on `HMSExceptionNotification` --- .../components/HMSExceptionNotification.tsx | 61 ++++++++++--------- 1 file changed, 31 insertions(+), 30 deletions(-) diff --git a/packages/react-native-room-kit/src/components/HMSExceptionNotification.tsx b/packages/react-native-room-kit/src/components/HMSExceptionNotification.tsx index 8e86f0730..c3304db75 100644 --- a/packages/react-native-room-kit/src/components/HMSExceptionNotification.tsx +++ b/packages/react-native-room-kit/src/components/HMSExceptionNotification.tsx @@ -1,12 +1,14 @@ import * as React from 'react'; +import { useDispatch } from 'react-redux'; +import type { HMSException } from '@100mslive/react-native-hms'; +import { StyleSheet, Text, TouchableOpacity } from 'react-native'; import { HMSNotification } from './HMSNotification'; -import { AlertTriangleIcon, RecordingIcon } from '../Icons'; -import { useDispatch } from 'react-redux'; -import { useHMSRoomColorPalette, useHMSRoomStyleSheet } from '../hooks-util'; +import { AlertTriangleIcon } from '../Icons'; +import { useHMSRoomStyleSheet, useModalType } from '../hooks-util'; import { removeNotification } from '../redux/actions'; -import { StyleSheet, Text, TouchableHighlight } from 'react-native'; -import type { HMSException } from '@100mslive/react-native-hms'; +import { ModalTypes } from '../utils/types'; +import { COLORS } from '../utils/theme'; export interface HMSExceptionNotificationProps { id: string; @@ -19,24 +21,22 @@ export const HMSExceptionNotification: React.FC< HMSExceptionNotificationProps > = ({ id, exception, autoDismiss, dismissDelay }) => { const dispatch = useDispatch(); + const { handleModalVisibleType } = useModalType(); - // const { secondary_dim: secondaryDimColor } = useHMSRoomColorPalette(); - - // const hmsRoomStyles = useHMSRoomStyleSheet((theme, typography) => ({ - // button: { - // backgroundColor: theme.palette.secondary_default, - // }, - // buttonText: { - // color: theme.palette.on_secondary_high, - // fontFamily: `${typography.font_family}-SemiBold`, - // }, - // })); + const hmsRoomStyles = useHMSRoomStyleSheet((theme, typography) => ({ + button: { + backgroundColor: theme.palette.alert_error_default, + }, + buttonText: { + color: COLORS.WHITE, + fontFamily: `${typography.font_family}-SemiBold`, + }, + })); const dismissNotification = () => dispatch(removeNotification(id)); - // const retryStartRecording = async () => { - // dismissNotification(); - // }; + const handleLeaveRoomPress = () => + handleModalVisibleType(ModalTypes.LEAVE_ROOM); return ( - // - // Retry - // - // - // : undefined} + cta={ + exception.isTerminal ? ( + + + Leave + + + ) : undefined + } onDismiss={dismissNotification} /> ); From c9b98c7e935e81f6a085591ac679dc31a873cddf Mon Sep 17 00:00:00 2001 From: Jatin Nagar Date: Fri, 20 Oct 2023 20:28:03 +0530 Subject: [PATCH 15/21] =?UTF-8?q?released=20sample=20app=20version=202.3.8?= =?UTF-8?q?9=20(340)=20=E2=9A=9B=EF=B8=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../example/android/app/build.gradle | 4 ++-- .../example/ios/RNExample.xcodeproj/project.pbxproj | 8 ++++---- .../example/ios/RNExample/Info.plist | 4 ++-- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/packages/react-native-room-kit/example/android/app/build.gradle b/packages/react-native-room-kit/example/android/app/build.gradle index b6e0e6238..f79e44a24 100644 --- a/packages/react-native-room-kit/example/android/app/build.gradle +++ b/packages/react-native-room-kit/example/android/app/build.gradle @@ -136,8 +136,8 @@ android { applicationId "live.hms.rn" minSdkVersion rootProject.ext.minSdkVersion targetSdkVersion rootProject.ext.targetSdkVersion - versionCode 339 - versionName "2.3.88" + versionCode 340 + versionName "2.3.89" missingDimensionStrategy 'react-native-camera', 'general' } diff --git a/packages/react-native-room-kit/example/ios/RNExample.xcodeproj/project.pbxproj b/packages/react-native-room-kit/example/ios/RNExample.xcodeproj/project.pbxproj index c5c70a0ef..ba6e61ce1 100644 --- a/packages/react-native-room-kit/example/ios/RNExample.xcodeproj/project.pbxproj +++ b/packages/react-native-room-kit/example/ios/RNExample.xcodeproj/project.pbxproj @@ -486,7 +486,7 @@ CODE_SIGN_ENTITLEMENTS = RNExample/RNExample.entitlements; CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 339; + CURRENT_PROJECT_VERSION = 340; DEVELOPMENT_TEAM = 5N85PP82A9; ENABLE_BITCODE = NO; INFOPLIST_FILE = RNExample/Info.plist; @@ -520,7 +520,7 @@ CODE_SIGN_ENTITLEMENTS = RNExample/RNExample.entitlements; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Distribution"; CODE_SIGN_STYLE = Manual; - CURRENT_PROJECT_VERSION = 339; + CURRENT_PROJECT_VERSION = 340; DEVELOPMENT_TEAM = ""; "DEVELOPMENT_TEAM[sdk=iphoneos*]" = 5N85PP82A9; INFOPLIST_FILE = RNExample/Info.plist; @@ -679,7 +679,7 @@ CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; CODE_SIGN_ENTITLEMENTS = RNExampleBroadcastUpload/RNExampleBroadcastUpload.entitlements; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 339; + CURRENT_PROJECT_VERSION = 340; DEBUG_INFORMATION_FORMAT = dwarf; DEVELOPMENT_TEAM = 5N85PP82A9; GCC_C_LANGUAGE_STANDARD = gnu11; @@ -721,7 +721,7 @@ "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Distribution"; CODE_SIGN_STYLE = Manual; COPY_PHASE_STRIP = NO; - CURRENT_PROJECT_VERSION = 339; + CURRENT_PROJECT_VERSION = 340; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; DEVELOPMENT_TEAM = ""; "DEVELOPMENT_TEAM[sdk=iphoneos*]" = 5N85PP82A9; diff --git a/packages/react-native-room-kit/example/ios/RNExample/Info.plist b/packages/react-native-room-kit/example/ios/RNExample/Info.plist index 0e0e5d87f..c88817991 100644 --- a/packages/react-native-room-kit/example/ios/RNExample/Info.plist +++ b/packages/react-native-room-kit/example/ios/RNExample/Info.plist @@ -21,11 +21,11 @@ CFBundlePackageType APPL CFBundleShortVersionString - 2.3.88 + 2.3.89 CFBundleSignature ???? CFBundleVersion - 339 + 340 ITSAppUsesNonExemptEncryption LSRequiresIPhoneOS From 9b9a9b4f8cd32bc4cfe193ba98434448a1215a21 Mon Sep 17 00:00:00 2001 From: Jatin Nagar Date: Wed, 25 Oct 2023 00:30:26 +0530 Subject: [PATCH 16/21] feat(prebuilt): :sparkles: added option to handle android back button press when enabled, back button press will open leave modal instead of leaving meeting without confirmation --- .../src/screens/HMSPrebuiltScreen/index.tsx | 1 + .../react-native-room-kit/src/HMSPrebuilt.tsx | 48 ++++++------ .../src/components/Meeting.tsx | 4 + .../react-native-room-kit/src/hooks-util.ts | 75 ++++++++++++++++++- .../src/redux/actionTypes.ts | 4 + .../src/redux/actions/index.ts | 11 ++- .../src/redux/reducers/appState.ts | 8 ++ .../src/redux/reducers/userState.ts | 6 +- packages/react-native-room-kit/src/types.ts | 41 ++++++++++ 9 files changed, 171 insertions(+), 27 deletions(-) diff --git a/packages/react-native-room-kit/example/src/screens/HMSPrebuiltScreen/index.tsx b/packages/react-native-room-kit/example/src/screens/HMSPrebuiltScreen/index.tsx index 0b3ac16c8..30c971155 100644 --- a/packages/react-native-room-kit/example/src/screens/HMSPrebuiltScreen/index.tsx +++ b/packages/react-native-room-kit/example/src/screens/HMSPrebuiltScreen/index.tsx @@ -82,6 +82,7 @@ export const HMSPrebuiltScreen = () => { startAndroidForegroundService(); } }, []); + // Room Code is required to join the room if (!roomCode) { return Room Code is Required; diff --git a/packages/react-native-room-kit/src/HMSPrebuilt.tsx b/packages/react-native-room-kit/src/HMSPrebuilt.tsx index abdc3ec47..c0af817f1 100644 --- a/packages/react-native-room-kit/src/HMSPrebuilt.tsx +++ b/packages/react-native-room-kit/src/HMSPrebuilt.tsx @@ -1,5 +1,6 @@ import React, { memo } from 'react'; import { Provider } from 'react-redux'; +import { Platform } from 'react-native'; import { SafeAreaInsetsContext, SafeAreaProvider, @@ -7,29 +8,11 @@ import { import { store } from './redux/index'; import { HMSContainer } from './HMSContainer'; -import { setPrebuiltData } from './redux/actions'; -import type { HMSIOSScreenShareConfig } from './utils/types'; - -export interface HMSPrebuiltProps { - roomCode: string; - options?: { - userName?: string; - userId?: string; - endPoints?: { - init: string; - token: string; - layout: string; - }; - debugMode?: boolean; - ios?: HMSIOSScreenShareConfig; - }; - onLeave?: () => void; -} +import { useSavePropsToStore } from './hooks-util'; +import type { HMSPrebuiltProps } from './types'; const _HMSPrebuilt: React.FC = (props) => { - const { roomCode, options, onLeave } = props; - - store.dispatch(setPrebuiltData({ roomCode, options, onLeave })); + useSavePropsToStore(props, store.dispatch); // @ts-ignore Not using `useContext` hook because we don't want to subscribe to updates // We just want to check if SafeAreaProvider exists or not @@ -48,5 +31,24 @@ const _HMSPrebuilt: React.FC = (props) => { return {content}; }; -// TODO: handle props change -export const HMSPrebuilt = memo(_HMSPrebuilt); +const arePropsEqual = ( + prevProps: Readonly, + nextProps: Readonly +): boolean => { + if ( + Platform.OS === 'android' && + !Object.is(prevProps.handleBackButton, nextProps.handleBackButton) + ) { + return false; + } + + if (!Object.is(prevProps.onLeave, nextProps.onLeave)) { + return false; + } + + return true; +}; + +export const HMSPrebuilt = memo(_HMSPrebuilt, arePropsEqual); + +export { type HMSPrebuiltProps }; diff --git a/packages/react-native-room-kit/src/components/Meeting.tsx b/packages/react-native-room-kit/src/components/Meeting.tsx index 7bf0d9b44..687904c2e 100644 --- a/packages/react-native-room-kit/src/components/Meeting.tsx +++ b/packages/react-native-room-kit/src/components/Meeting.tsx @@ -8,6 +8,7 @@ import { useRTCStatsListeners } from '../utils/hooks'; import { clearPendingModalTasks, useAutoPip, + useBackButtonPress, useFetchHMSRoles, useHMSMessages, useHMSNetworkQualityUpdate, @@ -57,6 +58,9 @@ export const Meeting: React.FC = ({ peerTrackNodes }) => { useAutoPip(); + // Handle Back button press and show leave room modal + useBackButtonPress(); + // Clearing any pending modal opening tasks React.useEffect(() => { return () => { diff --git a/packages/react-native-room-kit/src/hooks-util.ts b/packages/react-native-room-kit/src/hooks-util.ts index b9ac5c802..a8c015d9b 100644 --- a/packages/react-native-room-kit/src/hooks-util.ts +++ b/packages/react-native-room-kit/src/hooks-util.ts @@ -62,7 +62,7 @@ import { useSelector, useStore, } from 'react-redux'; -import type { RootState } from './redux'; +import type { AppDispatch, RootState } from './redux'; import { addMessage, addNotification, @@ -87,12 +87,15 @@ import { setHMSLocalPeerState, setHMSRoleState, setHMSRoomState, + setHandleBackButton, setIsLocalAudioMutedState, setIsLocalVideoMutedState, setLayoutConfig, setLocalPeerTrackNode, setMiniViewPeerTrackNode, setModalType, + setOnLeaveHandler, + setPrebuiltData, setReconnecting, setRoleChangeRequest, setStartingOrStoppingRecording, @@ -112,7 +115,13 @@ import { replacePeerTrackNodesWithTrack, } from './peerTrackNodeUtils'; import { MeetingState } from './types'; -import { InteractionManager, Keyboard, Platform } from 'react-native'; +import type { HMSPrebuiltProps } from './types'; +import { + BackHandler, + InteractionManager, + Keyboard, + Platform, +} from 'react-native'; import type { ImageStyle, StyleProp, ViewStyle, TextStyle } from 'react-native'; import { NavigationContext } from '@react-navigation/native'; import { @@ -2226,3 +2235,65 @@ export const useHMSConferencingScreenConfig = ( return selector(conferencingScreenConfig); }, equalityFn); }; + +export const useBackButtonPress = () => { + const { handleModalVisibleType } = useModalType(); + + const handleBackPress = useSelector( + (state: RootState) => state.app.handleBackButton + ); + + useEffect(() => { + if (handleBackPress) { + const backPressHandler = () => { + handleModalVisibleType(ModalTypes.LEAVE_ROOM); + + /** + * When true is returned the event will not be bubbled up + * & no other back action will execute + */ + return true; + + /** + * Returning false will let the event to bubble up & let other event listeners + * or the system's default back action to be executed. + */ + // return false; + }; + + const subscription = BackHandler.addEventListener( + 'hardwareBackPress', + backPressHandler + ); + + return () => { + if (typeof subscription.remove === 'function') { + subscription.remove(); + } else { + BackHandler.removeEventListener('hardwareBackPress', backPressHandler); + } + }; + } + }, [handleBackPress, handleModalVisibleType]); +}; + +export const useSavePropsToStore = ( + props: HMSPrebuiltProps, + dispatch: AppDispatch +) => { + const { roomCode, options, onLeave, handleBackButton } = props; + + useEffect(() => { + dispatch(setPrebuiltData({ roomCode, options })); + }, [roomCode, options]); + + useEffect(() => { + dispatch(setOnLeaveHandler(onLeave)); + }, [onLeave]); + + useEffect(() => { + if (Platform.OS === 'android') { + dispatch(setHandleBackButton(handleBackButton)); + } + }, [handleBackButton]); +}; diff --git a/packages/react-native-room-kit/src/redux/actionTypes.ts b/packages/react-native-room-kit/src/redux/actionTypes.ts index 2d077674b..c1f72c447 100644 --- a/packages/react-native-room-kit/src/redux/actionTypes.ts +++ b/packages/react-native-room-kit/src/redux/actionTypes.ts @@ -84,6 +84,8 @@ const SET_ACTIVE_CHAT_BOTTOM_SHEET_TAB = 'SET_ACTIVE_CHAT_BOTTOM_SHEET_TAB'; const SET_CHAT_FILTER_SHEET_VISIBLE = 'SET_CHAT_FILTER_SHEET_VISIBLE'; +const SET_HANDLE_BACK_BUTTON = 'SET_HANDLE_BACK_BUTTON'; + export default { ADD_PINNED_MESSAGE, ADD_MESSAGE, @@ -123,11 +125,13 @@ export default { REMOVE_NOTIFICATION, SET_ACTIVE_CHAT_BOTTOM_SHEET_TAB, SET_CHAT_FILTER_SHEET_VISIBLE, + SET_HANDLE_BACK_BUTTON, }; export enum HmsStateActionTypes { CLEAR_STATES = 'CLEAR_STATES', SET_PREBUILT_DATA = 'SET_PREBUILT_DATA', + SET_ON_LEAVE_HANDLER = 'SET_ON_LEAVE_HANDLER', SET_ROOM_STATE = 'SET_ROOM_STATE', SET_LOCAL_PEER_STATE = 'SET_LOCAL_PEER_STATE', SET_ROLES_STATE = 'SET_ROLES_STATE', diff --git a/packages/react-native-room-kit/src/redux/actions/index.ts b/packages/react-native-room-kit/src/redux/actions/index.ts index a7be232f0..49f57b645 100644 --- a/packages/react-native-room-kit/src/redux/actions/index.ts +++ b/packages/react-native-room-kit/src/redux/actions/index.ts @@ -37,12 +37,16 @@ export const setPrebuiltData = (data: { }; ios?: HMSIOSScreenShareConfig; }; - onLeave?: () => void; }) => ({ type: HmsStateActionTypes.SET_PREBUILT_DATA, payload: data, }); +export const setOnLeaveHandler = (onLeave?: () => void) => ({ + type: HmsStateActionTypes.SET_ON_LEAVE_HANDLER, + payload: { onLeave }, +}); + export const clearStore = () => ({ type: HmsStateActionTypes.CLEAR_STATES, }); @@ -379,3 +383,8 @@ export const setReconnecting = (reconnecting: boolean) => ({ type: HmsStateActionTypes.SET_RECONNECTING, reconnecting, }); + +export const setHandleBackButton = (handleBackButton?: boolean) => ({ + type: actionTypes.SET_HANDLE_BACK_BUTTON, + payload: { handleBackButton }, +}); diff --git a/packages/react-native-room-kit/src/redux/reducers/appState.ts b/packages/react-native-room-kit/src/redux/reducers/appState.ts index 705136be3..c75a1d41e 100644 --- a/packages/react-native-room-kit/src/redux/reducers/appState.ts +++ b/packages/react-native-room-kit/src/redux/reducers/appState.ts @@ -51,6 +51,7 @@ type IntialStateType = { notifications: { id: string; type: string; peer: HMSPeer }[]; activeChatBottomSheetTab: (typeof ChatBottomSheetTabs)[number]; chatFilterSheetVisible: boolean; + handleBackButton: boolean; }; const INITIAL_STATE: IntialStateType = { @@ -80,6 +81,7 @@ const INITIAL_STATE: IntialStateType = { notifications: [], activeChatBottomSheetTab: ChatBottomSheetTabs[0], chatFilterSheetVisible: false, + handleBackButton: false, }; const appReducer = ( @@ -283,6 +285,12 @@ const appReducer = ( chatFilterSheetVisible: action.payload.chatFilterSheetVisible, }; } + case ActionTypes.SET_HANDLE_BACK_BUTTON: { + return { + ...state, + handleBackButton: action.payload.handleBackButton ?? INITIAL_STATE.handleBackButton, + }; + } case HmsStateActionTypes.CLEAR_STATES: return INITIAL_STATE; default: diff --git a/packages/react-native-room-kit/src/redux/reducers/userState.ts b/packages/react-native-room-kit/src/redux/reducers/userState.ts index 276c7dad8..df19814fc 100644 --- a/packages/react-native-room-kit/src/redux/reducers/userState.ts +++ b/packages/react-native-room-kit/src/redux/reducers/userState.ts @@ -78,9 +78,13 @@ const userReducer = ( state.endPoints = action.payload.options.endPoints; state.debugMode = action.payload.options.debugMode ?? false; state.iosBuildConfig = action.payload.options.ios ?? null; - state.onLeave = action.payload.onLeave; return state; + case HmsStateActionTypes.SET_ON_LEAVE_HANDLER: + return { + ...state, + onLeave: action.payload.onLeave, + }; case HmsStateActionTypes.CLEAR_STATES: return INITIAL_STATE; default: diff --git a/packages/react-native-room-kit/src/types.ts b/packages/react-native-room-kit/src/types.ts index 7a8e0ff44..80b6b96b7 100644 --- a/packages/react-native-room-kit/src/types.ts +++ b/packages/react-native-room-kit/src/types.ts @@ -1,3 +1,5 @@ +import type { HMSIOSScreenShareConfig } from "./utils/types"; + export enum MeetingState { NOT_JOINED, IN_PREVIEW, @@ -5,3 +7,42 @@ export enum MeetingState { MEETING_ENDED, ERROR, } +export interface HMSPrebuiltProps { + roomCode: string; + options?: { + userName?: string; + userId?: string; + endPoints?: { + init: string; + token: string; + layout: string; + }; + debugMode?: boolean; + ios?: HMSIOSScreenShareConfig; + }; + /** + * onLeave - Optional callback function + * + * It will be invoked when user leaves meeting or user is removed from the room + */ + onLeave?: () => void; + /** + * [Android Only] handleBackButton - `Optional` | Default value - `false` + * + * When `true`, Leave modal will open on press of back button on android + * otherwise user will leave meeting immediately without any confirmation modal opening + * + * Example usage: + * ```jsx + * const isScreenFocused = useIsFocused(); + * + * ... + * + * + * ``` + */ + handleBackButton?: boolean; +} From cd6ea86f29d4a48015c80d03f9a785eb8da55e0c Mon Sep 17 00:00:00 2001 From: Jatin Nagar Date: Wed, 25 Oct 2023 00:31:28 +0530 Subject: [PATCH 17/21] feat(example-app): :sparkles: usage of `handleBackButton` prop in `HMSPrebuilt` component --- .../example/src/screens/HMSPrebuiltScreen/index.tsx | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/packages/react-native-room-kit/example/src/screens/HMSPrebuiltScreen/index.tsx b/packages/react-native-room-kit/example/src/screens/HMSPrebuiltScreen/index.tsx index 30c971155..2a8b3d653 100644 --- a/packages/react-native-room-kit/example/src/screens/HMSPrebuiltScreen/index.tsx +++ b/packages/react-native-room-kit/example/src/screens/HMSPrebuiltScreen/index.tsx @@ -3,6 +3,7 @@ import { Platform, Text } from 'react-native'; import { NavigationProp, RouteProp, + useIsFocused, useNavigation, useRoute, } from '@react-navigation/native'; @@ -18,6 +19,9 @@ export const HMSPrebuiltScreen = () => { const screenParams = useRoute>().params; + // To handle back button press in Prebuilt, when screen is focused + const isScreenFocused = useIsFocused(); + // function to be called when meeting is ended const handleMeetingLeave = useCallback(async () => { if (Platform.OS === 'android') { @@ -93,6 +97,7 @@ export const HMSPrebuiltScreen = () => { roomCode={roomCode} options={prebuiltOptions} onLeave={handleMeetingLeave} + handleBackButton={isScreenFocused} /> ); }; From 886d5be6d2c925fa3a3a894b13f19456796c176e Mon Sep 17 00:00:00 2001 From: Jatin Nagar Date: Wed, 25 Oct 2023 13:26:41 +0530 Subject: [PATCH 18/21] feat(prebuilt): :sparkles: added option to handle auto enter pip mode --- .../react-native-room-kit/src/HMSPrebuilt.tsx | 7 +++++++ .../react-native-room-kit/src/hooks-util.ts | 21 ++++++++++++++----- .../src/redux/actionTypes.ts | 3 +++ .../src/redux/actions/index.ts | 5 +++++ .../src/redux/reducers/appState.ts | 8 +++++++ packages/react-native-room-kit/src/types.ts | 14 +++++++++++++ 6 files changed, 53 insertions(+), 5 deletions(-) diff --git a/packages/react-native-room-kit/src/HMSPrebuilt.tsx b/packages/react-native-room-kit/src/HMSPrebuilt.tsx index c0af817f1..ec7912d99 100644 --- a/packages/react-native-room-kit/src/HMSPrebuilt.tsx +++ b/packages/react-native-room-kit/src/HMSPrebuilt.tsx @@ -42,6 +42,13 @@ const arePropsEqual = ( return false; } + if ( + Platform.OS === 'android' && + !Object.is(prevProps.autoEnterPipMode, nextProps.autoEnterPipMode) + ) { + return false; + } + if (!Object.is(prevProps.onLeave, nextProps.onLeave)) { return false; } diff --git a/packages/react-native-room-kit/src/hooks-util.ts b/packages/react-native-room-kit/src/hooks-util.ts index a8c015d9b..03ed29865 100644 --- a/packages/react-native-room-kit/src/hooks-util.ts +++ b/packages/react-native-room-kit/src/hooks-util.ts @@ -83,6 +83,7 @@ import { saveUserData, setActiveChatBottomSheetTab, setActiveSpeakers, + setAutoEnterPipMode, setFullScreenPeerTrackNode, setHMSLocalPeerState, setHMSRoleState, @@ -1392,19 +1393,23 @@ export const useDisableAutoPip = () => { return disableAutoPip; }; -export const useAutoPip = (enabled: boolean = true) => { +export const useAutoPip = () => { const enableAutoPip = useEnableAutoPip(); const disableAutoPip = useDisableAutoPip(); const isHLSViewer = useIsHLSViewer(); + const autoEnterPipMode = useSelector( + (state: RootState) => state.app.autoEnterPipMode + ); + useEffect(() => { - if (enabled) { + if (autoEnterPipMode) { enableAutoPip({ aspectRatio: isHLSViewer ? [9, 16] : [16, 9] }); return disableAutoPip; } - }, [enabled, isHLSViewer, enableAutoPip, disableAutoPip]); -} + }, [autoEnterPipMode, isHLSViewer, enableAutoPip, disableAutoPip]); +}; export const useHMSActiveSpeakerUpdates = ( setPeerTrackNodes: React.Dispatch>, @@ -2281,7 +2286,7 @@ export const useSavePropsToStore = ( props: HMSPrebuiltProps, dispatch: AppDispatch ) => { - const { roomCode, options, onLeave, handleBackButton } = props; + const { roomCode, options, onLeave, handleBackButton, autoEnterPipMode } = props; useEffect(() => { dispatch(setPrebuiltData({ roomCode, options })); @@ -2296,4 +2301,10 @@ export const useSavePropsToStore = ( dispatch(setHandleBackButton(handleBackButton)); } }, [handleBackButton]); + + useEffect(() => { + if (Platform.OS === 'android') { + dispatch(setAutoEnterPipMode(autoEnterPipMode)); + } + }, [autoEnterPipMode]) }; diff --git a/packages/react-native-room-kit/src/redux/actionTypes.ts b/packages/react-native-room-kit/src/redux/actionTypes.ts index c1f72c447..897a4b062 100644 --- a/packages/react-native-room-kit/src/redux/actionTypes.ts +++ b/packages/react-native-room-kit/src/redux/actionTypes.ts @@ -86,6 +86,8 @@ const SET_CHAT_FILTER_SHEET_VISIBLE = 'SET_CHAT_FILTER_SHEET_VISIBLE'; const SET_HANDLE_BACK_BUTTON = 'SET_HANDLE_BACK_BUTTON'; +const SET_AUTO_ENTER_PIP_MODE = 'SET_AUTO_ENTER_PIP_MODE'; + export default { ADD_PINNED_MESSAGE, ADD_MESSAGE, @@ -126,6 +128,7 @@ export default { SET_ACTIVE_CHAT_BOTTOM_SHEET_TAB, SET_CHAT_FILTER_SHEET_VISIBLE, SET_HANDLE_BACK_BUTTON, + SET_AUTO_ENTER_PIP_MODE, }; export enum HmsStateActionTypes { diff --git a/packages/react-native-room-kit/src/redux/actions/index.ts b/packages/react-native-room-kit/src/redux/actions/index.ts index 49f57b645..efe21e20f 100644 --- a/packages/react-native-room-kit/src/redux/actions/index.ts +++ b/packages/react-native-room-kit/src/redux/actions/index.ts @@ -388,3 +388,8 @@ export const setHandleBackButton = (handleBackButton?: boolean) => ({ type: actionTypes.SET_HANDLE_BACK_BUTTON, payload: { handleBackButton }, }); + +export const setAutoEnterPipMode = (autoEnterPipMode?: boolean) => ({ + type: actionTypes.SET_AUTO_ENTER_PIP_MODE, + payload: { autoEnterPipMode }, +}); diff --git a/packages/react-native-room-kit/src/redux/reducers/appState.ts b/packages/react-native-room-kit/src/redux/reducers/appState.ts index c75a1d41e..5a23eaad9 100644 --- a/packages/react-native-room-kit/src/redux/reducers/appState.ts +++ b/packages/react-native-room-kit/src/redux/reducers/appState.ts @@ -52,6 +52,7 @@ type IntialStateType = { activeChatBottomSheetTab: (typeof ChatBottomSheetTabs)[number]; chatFilterSheetVisible: boolean; handleBackButton: boolean; + autoEnterPipMode: boolean; }; const INITIAL_STATE: IntialStateType = { @@ -82,6 +83,7 @@ const INITIAL_STATE: IntialStateType = { activeChatBottomSheetTab: ChatBottomSheetTabs[0], chatFilterSheetVisible: false, handleBackButton: false, + autoEnterPipMode: false, }; const appReducer = ( @@ -291,6 +293,12 @@ const appReducer = ( handleBackButton: action.payload.handleBackButton ?? INITIAL_STATE.handleBackButton, }; } + case ActionTypes.SET_AUTO_ENTER_PIP_MODE: { + return { + ...state, + autoEnterPipMode: action.payload.autoEnterPipMode ?? INITIAL_STATE.autoEnterPipMode, + }; + } case HmsStateActionTypes.CLEAR_STATES: return INITIAL_STATE; default: diff --git a/packages/react-native-room-kit/src/types.ts b/packages/react-native-room-kit/src/types.ts index 80b6b96b7..09223ed49 100644 --- a/packages/react-native-room-kit/src/types.ts +++ b/packages/react-native-room-kit/src/types.ts @@ -45,4 +45,18 @@ export interface HMSPrebuiltProps { * ``` */ handleBackButton?: boolean; + /** + * [Android Only] autoEnterPipMode - `Optional` | Default value - `false` + * + * When `true`, App will go into PIP mode automatically when user tries to leave or minimize app while it is inside room + * + * Example usage: + * ```jsx + * + * ``` + */ + autoEnterPipMode?: boolean; } From 3a08d36db3f11a547b7de6099539326226a95176 Mon Sep 17 00:00:00 2001 From: Jatin Nagar Date: Wed, 25 Oct 2023 14:27:26 +0530 Subject: [PATCH 19/21] feat(example-app): :sparkles: usage of `autoEnterPipMode` prop in `HMSPrebuilt` component --- .../example/src/screens/HMSPrebuiltScreen/index.tsx | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/react-native-room-kit/example/src/screens/HMSPrebuiltScreen/index.tsx b/packages/react-native-room-kit/example/src/screens/HMSPrebuiltScreen/index.tsx index 2a8b3d653..8624bc7c8 100644 --- a/packages/react-native-room-kit/example/src/screens/HMSPrebuiltScreen/index.tsx +++ b/packages/react-native-room-kit/example/src/screens/HMSPrebuiltScreen/index.tsx @@ -98,6 +98,7 @@ export const HMSPrebuiltScreen = () => { options={prebuiltOptions} onLeave={handleMeetingLeave} handleBackButton={isScreenFocused} + autoEnterPipMode={true} /> ); }; From 46bbc712837a057c985f152920ed372e391971ba Mon Sep 17 00:00:00 2001 From: Jatin Nagar Date: Wed, 25 Oct 2023 17:21:40 +0530 Subject: [PATCH 20/21] =?UTF-8?q?released=20sample=20app=20version=202.3.9?= =?UTF-8?q?2=20(343)=20=E2=9A=9B=EF=B8=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../example/android/app/build.gradle | 4 ++-- .../example/ios/RNExample.xcodeproj/project.pbxproj | 8 ++++---- .../example/ios/RNExample/Info.plist | 4 ++-- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/packages/react-native-room-kit/example/android/app/build.gradle b/packages/react-native-room-kit/example/android/app/build.gradle index 5dc58243b..992478656 100644 --- a/packages/react-native-room-kit/example/android/app/build.gradle +++ b/packages/react-native-room-kit/example/android/app/build.gradle @@ -136,8 +136,8 @@ android { applicationId "live.hms.rn" minSdkVersion rootProject.ext.minSdkVersion targetSdkVersion rootProject.ext.targetSdkVersion - versionCode 342 - versionName "2.3.91" + versionCode 343 + versionName "2.3.92" missingDimensionStrategy 'react-native-camera', 'general' } diff --git a/packages/react-native-room-kit/example/ios/RNExample.xcodeproj/project.pbxproj b/packages/react-native-room-kit/example/ios/RNExample.xcodeproj/project.pbxproj index 3b19197c9..71291a1ec 100644 --- a/packages/react-native-room-kit/example/ios/RNExample.xcodeproj/project.pbxproj +++ b/packages/react-native-room-kit/example/ios/RNExample.xcodeproj/project.pbxproj @@ -486,7 +486,7 @@ CODE_SIGN_ENTITLEMENTS = RNExample/RNExample.entitlements; CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 342; + CURRENT_PROJECT_VERSION = 343; DEVELOPMENT_TEAM = 5N85PP82A9; ENABLE_BITCODE = NO; INFOPLIST_FILE = RNExample/Info.plist; @@ -520,7 +520,7 @@ CODE_SIGN_ENTITLEMENTS = RNExample/RNExample.entitlements; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Distribution"; CODE_SIGN_STYLE = Manual; - CURRENT_PROJECT_VERSION = 342; + CURRENT_PROJECT_VERSION = 343; DEVELOPMENT_TEAM = ""; "DEVELOPMENT_TEAM[sdk=iphoneos*]" = 5N85PP82A9; INFOPLIST_FILE = RNExample/Info.plist; @@ -679,7 +679,7 @@ CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; CODE_SIGN_ENTITLEMENTS = RNExampleBroadcastUpload/RNExampleBroadcastUpload.entitlements; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 342; + CURRENT_PROJECT_VERSION = 343; DEBUG_INFORMATION_FORMAT = dwarf; DEVELOPMENT_TEAM = 5N85PP82A9; GCC_C_LANGUAGE_STANDARD = gnu11; @@ -721,7 +721,7 @@ "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Distribution"; CODE_SIGN_STYLE = Manual; COPY_PHASE_STRIP = NO; - CURRENT_PROJECT_VERSION = 342; + CURRENT_PROJECT_VERSION = 343; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; DEVELOPMENT_TEAM = ""; "DEVELOPMENT_TEAM[sdk=iphoneos*]" = 5N85PP82A9; diff --git a/packages/react-native-room-kit/example/ios/RNExample/Info.plist b/packages/react-native-room-kit/example/ios/RNExample/Info.plist index f5d759545..dd200a843 100644 --- a/packages/react-native-room-kit/example/ios/RNExample/Info.plist +++ b/packages/react-native-room-kit/example/ios/RNExample/Info.plist @@ -21,11 +21,11 @@ CFBundlePackageType APPL CFBundleShortVersionString - 2.3.91 + 2.3.92 CFBundleSignature ???? CFBundleVersion - 342 + 343 ITSAppUsesNonExemptEncryption LSRequiresIPhoneOS From 64180a4228702d36b550e60710140070d857a41d Mon Sep 17 00:00:00 2001 From: Jatin Nagar Date: Thu, 26 Oct 2023 14:36:32 +0530 Subject: [PATCH 21/21] feat(sdk): :sparkles: added "hls player resolution" state in zustand store --- .../com/reactnativehmssdk/HMSHLSPlayer.kt | 7 +++-- .../ios/HMSHLSPlayerManager.swift | 31 ++++++++++++------- .../components/HMSHLSPlayer/HMSHLSPlayer.tsx | 16 +++++++--- .../src/components/HMSHLSPlayer/hooks.ts | 7 +++++ .../src/components/HMSHLSPlayer/index.ts | 1 + .../src/stores/hls-player-playback-slice.ts | 3 ++ packages/react-native-hms/src/stores/types.ts | 5 +++ packages/react-native-hms/src/types.ts | 16 ++++++++-- 8 files changed, 64 insertions(+), 22 deletions(-) diff --git a/packages/react-native-hms/android/src/main/java/com/reactnativehmssdk/HMSHLSPlayer.kt b/packages/react-native-hms/android/src/main/java/com/reactnativehmssdk/HMSHLSPlayer.kt index c295845b2..52bcdfdb6 100644 --- a/packages/react-native-hms/android/src/main/java/com/reactnativehmssdk/HMSHLSPlayer.kt +++ b/packages/react-native-hms/android/src/main/java/com/reactnativehmssdk/HMSHLSPlayer.kt @@ -153,9 +153,9 @@ class HMSHLSPlayer(context: ReactContext) : FrameLayout(context) { } val data = Arguments.createMap() - data.putString("state", "onVideoSizeChanged") - data.putDouble("aspectRatio", (width / height)) - sendHLSPlaybackEventToJS(HMSHLSPlayerConstants.ON_PLAYBACK_STATE_CHANGE_EVENT, data) + data.putDouble("width", width) + data.putDouble("height", height) + sendHLSPlaybackEventToJS(HMSHLSPlayerConstants.ON_PLAYBACK_RESOLUTION_CHANGE_EVENT, data) } } }, @@ -285,6 +285,7 @@ object HMSHLSPlayerConstants { const val ON_PLAYBACK_CUE_EVENT = "ON_PLAYBACK_CUE_EVENT" const val ON_PLAYBACK_FAILURE_EVENT = "ON_PLAYBACK_FAILURE_EVENT" const val ON_PLAYBACK_STATE_CHANGE_EVENT = "ON_PLAYBACK_STATE_CHANGE_EVENT" + const val ON_PLAYBACK_RESOLUTION_CHANGE_EVENT = "ON_PLAYBACK_RESOLUTION_CHANGE_EVENT" // HLS Playback Stats Events const val HMS_HLS_STATS_EVENT = "hmsHlsStatsEvent" diff --git a/packages/react-native-hms/ios/HMSHLSPlayerManager.swift b/packages/react-native-hms/ios/HMSHLSPlayerManager.swift index 2701994bf..2d6f80d80 100644 --- a/packages/react-native-hms/ios/HMSHLSPlayerManager.swift +++ b/packages/react-native-hms/ios/HMSHLSPlayerManager.swift @@ -308,18 +308,31 @@ class HMSHLSPlayer: UIView { sendHLSPlaybackEventToJS(HMSHLSPlayerConstants.ON_PLAYBACK_FAILURE_EVENT, data) } - fileprivate func onPlaybackStateChanged(state: HMSHLSPlaybackState? = nil, videoSizeChanged: Bool = false, aspectRatio: Double? = nil) { + fileprivate func onPlaybackStateChanged(state: HMSHLSPlaybackState) { guard onHmsHlsPlaybackEvent != nil else { return } var data = [String: Any]() - data["state"] = videoSizeChanged ? "onVideoSizeChanged" : state?.description + data["state"] = state.description - if let aspectRatio = aspectRatio { - data["aspectRatio"] = aspectRatio + sendHLSPlaybackEventToJS(HMSHLSPlayerConstants.ON_PLAYBACK_STATE_CHANGE_EVENT, data) + } + + fileprivate func onResolutionChanged(videoSize: CGSize) { + if videoSize.width >= videoSize.height { + hmsHLSPlayerViewController?.videoGravity = .resizeAspect + } else { + hmsHLSPlayerViewController?.videoGravity = .resizeAspectFill } - sendHLSPlaybackEventToJS(HMSHLSPlayerConstants.ON_PLAYBACK_STATE_CHANGE_EVENT, data) + guard onHmsHlsPlaybackEvent != nil else { return } + + var data = [String: Any]() + + data["width"] = videoSize.width + data["height"] = videoSize.height + + sendHLSPlaybackEventToJS(HMSHLSPlayerConstants.ON_PLAYBACK_RESOLUTION_CHANGE_EVENT, data) } } @@ -343,12 +356,7 @@ class HLSPlaybackEventController: HMSHLSPlayerDelegate { } func onResolutionChanged(videoSize: CGSize) { - if videoSize.width >= videoSize.height { - hmsHlsPlayerDelegate?.hmsHLSPlayerViewController?.videoGravity = .resizeAspect - } else { - hmsHlsPlayerDelegate?.hmsHLSPlayerViewController?.videoGravity = .resizeAspectFill - } - hmsHlsPlayerDelegate?.onPlaybackStateChanged(videoSizeChanged: true, aspectRatio: videoSize.width/videoSize.height) + hmsHlsPlayerDelegate?.onResolutionChanged(videoSize: videoSize) } } @@ -357,6 +365,7 @@ enum HMSHLSPlayerConstants { static let ON_PLAYBACK_CUE_EVENT = "ON_PLAYBACK_CUE_EVENT" static let ON_PLAYBACK_FAILURE_EVENT = "ON_PLAYBACK_FAILURE_EVENT" static let ON_PLAYBACK_STATE_CHANGE_EVENT = "ON_PLAYBACK_STATE_CHANGE_EVENT" + static let ON_PLAYBACK_RESOLUTION_CHANGE_EVENT = "ON_PLAYBACK_RESOLUTION_CHANGE_EVENT" // HLS Playback Stats Events static let ON_STATS_EVENT_UPDATE = "ON_STATS_EVENT_UPDATE" diff --git a/packages/react-native-hms/src/components/HMSHLSPlayer/HMSHLSPlayer.tsx b/packages/react-native-hms/src/components/HMSHLSPlayer/HMSHLSPlayer.tsx index aea8002d5..7e1a5df80 100644 --- a/packages/react-native-hms/src/components/HMSHLSPlayer/HMSHLSPlayer.tsx +++ b/packages/react-native-hms/src/components/HMSHLSPlayer/HMSHLSPlayer.tsx @@ -6,6 +6,7 @@ import { setHMSHLSPlayerCue, setHMSHLSPlayerPlaybackError, setHMSHLSPlayerPlaybackState, + setHMSHLSPlayerResolution, setHMSHLSPlayerStats, setHMSHLSPlayerStatsError, } from './hooks'; @@ -198,13 +199,18 @@ const _HMSHLSPlayer: React.ForwardRefRenderFunction< event === HMSHLSPlayerPlaybackEventTypes.ON_PLAYBACK_FAILURE_EVENT ) { setHMSHLSPlayerPlaybackError(data.error); + } else if ( + event === HMSHLSPlayerPlaybackEventTypes.ON_PLAYBACK_RESOLUTION_CHANGE_EVENT + ) { + setHMSHLSPlayerResolution({...data}); + + const aspectRatio = data.width / data.height; + + if (typeof aspectRatio === 'number' && !isNaN(aspectRatio)) { + setAspectRatio(aspectRatio); + } } else { setHMSHLSPlayerPlaybackState(data.state); - if (data.state === 'onVideoSizeChanged') { - if (typeof data.aspectRatio === 'number') { - setAspectRatio(data.aspectRatio); - } - } } }; diff --git a/packages/react-native-hms/src/components/HMSHLSPlayer/hooks.ts b/packages/react-native-hms/src/components/HMSHLSPlayer/hooks.ts index e5e9b6522..f3030fa3b 100644 --- a/packages/react-native-hms/src/components/HMSHLSPlayer/hooks.ts +++ b/packages/react-native-hms/src/components/HMSHLSPlayer/hooks.ts @@ -17,6 +17,10 @@ export const useHMSHLSPlayerPlaybackState = () => { return useHMSStore((state) => state.playbackState); }; +export const useHMSHLSPlayerResolution = () => { + return useHMSStore((state) => state.resolution); +}; + export const useHMSHLSPlayerStats = () => { return useHMSHLSPlayerStatsStore( (state) => ({ @@ -89,6 +93,9 @@ export const useHMSHLSPlayerCue = ( export const setHMSHLSPlayerPlaybackState = useHMSStore.getState().setPlaybackState; +export const setHMSHLSPlayerResolution = + useHMSStore.getState().setResolution; + export const setHMSHLSPlayerCue = useHMSStore.getState().setCue; export const setHMSHLSPlayerPlaybackError = diff --git a/packages/react-native-hms/src/components/HMSHLSPlayer/index.ts b/packages/react-native-hms/src/components/HMSHLSPlayer/index.ts index 9f4d4e2ac..40f412568 100644 --- a/packages/react-native-hms/src/components/HMSHLSPlayer/index.ts +++ b/packages/react-native-hms/src/components/HMSHLSPlayer/index.ts @@ -6,4 +6,5 @@ export { useHMSHLSPlayerStats, useHMSHLSPlayerStat, useHMSHLSPlayerStatsError, + useHMSHLSPlayerResolution, } from './hooks'; diff --git a/packages/react-native-hms/src/stores/hls-player-playback-slice.ts b/packages/react-native-hms/src/stores/hls-player-playback-slice.ts index 57536d9b8..1fcfe753c 100644 --- a/packages/react-native-hms/src/stores/hls-player-playback-slice.ts +++ b/packages/react-native-hms/src/stores/hls-player-playback-slice.ts @@ -22,4 +22,7 @@ export const createHMSHLSPlayerPlaybackSlice: StateCreator< error: undefined, setPlaybackError: (error: HMSHLSPlayerPlaybackError) => set({ error }), + + resolution: undefined, + setResolution: (resolution) => set({ resolution }), }); diff --git a/packages/react-native-hms/src/stores/types.ts b/packages/react-native-hms/src/stores/types.ts index c39b1fa24..c92df2d7b 100644 --- a/packages/react-native-hms/src/stores/types.ts +++ b/packages/react-native-hms/src/stores/types.ts @@ -4,6 +4,7 @@ import type { HMSHLSPlayerPlaybackState, HMSHLSPlayerPlaybackCueEventData, HMSHLSPlayerPlaybackFailureEventData, + HMSHLSPlayerPlaybackResolutionChangeEventData, HMSHLSPlayerStatsErrorEventData, HMSHLSPlayerStatsUpdateEventData, } from '../types'; @@ -25,12 +26,16 @@ export type HMSHLSPlayerPlaybackError = | HMSHLSPlayerPlaybackFailureEventData['error'] | undefined; +export type HMSHLSPlayerResolution = HMSHLSPlayerPlaybackResolutionChangeEventData | undefined; + export interface HMSHLSPlayerPlaybackSlice { cue: HMSHLSPlayerCue; playbackState: HMSHLSPlayerPlaybackState; + resolution: HMSHLSPlayerResolution; error: HMSHLSPlayerPlaybackError; setCue(cue: HMSHLSPlayerPlaybackCue): void; setPlaybackState(playbackState: HMSHLSPlayerPlaybackState): void; + setResolution(resolution: HMSHLSPlayerResolution): void; setPlaybackError(error: HMSHLSPlayerPlaybackError): void; } diff --git a/packages/react-native-hms/src/types.ts b/packages/react-native-hms/src/types.ts index a595d4514..dedf46b88 100644 --- a/packages/react-native-hms/src/types.ts +++ b/packages/react-native-hms/src/types.ts @@ -10,6 +10,7 @@ export enum HMSHLSPlayerPlaybackEventTypes { ON_PLAYBACK_CUE_EVENT = 'ON_PLAYBACK_CUE_EVENT', ON_PLAYBACK_FAILURE_EVENT = 'ON_PLAYBACK_FAILURE_EVENT', ON_PLAYBACK_STATE_CHANGE_EVENT = 'ON_PLAYBACK_STATE_CHANGE_EVENT', + ON_PLAYBACK_RESOLUTION_CHANGE_EVENT = 'ON_PLAYBACK_RESOLUTION_CHANGE_EVENT', } export type HMSHLSPlayerPlaybackCueEventData = { @@ -34,12 +35,15 @@ export enum HMSHLSPlayerPlaybackState { PLAYING = 'playing', STOPPED = 'stopped', UNKNOWN = 'unknown', - onVideoSizeChanged = 'onVideoSizeChanged', } export type HMSHLSPlayerPlaybackStateChangeEventData = { state: HMSHLSPlayerPlaybackState; - aspectRatio: number | undefined; +}; + +export type HMSHLSPlayerPlaybackResolutionChangeEventData = { + width: number; + height: number; }; type HMSHLSPlayerPlaybackCueEvent = HMSHLSPlayerEvent< @@ -57,10 +61,16 @@ type HMSHLSPlayerPlaybackStateChangeEvent = HMSHLSPlayerEvent< HMSHLSPlayerPlaybackStateChangeEventData >; +type HMSHLSPLayerPlaybackResolutionChangeEvent = HMSHLSPlayerEvent< + HMSHLSPlayerPlaybackEventTypes.ON_PLAYBACK_RESOLUTION_CHANGE_EVENT, + HMSHLSPlayerPlaybackResolutionChangeEventData +>; + export type HMSHLSPlayerPlaybackEvent = | HMSHLSPlayerPlaybackCueEvent | HMSHLSPlayerPlaybackFailureEvent - | HMSHLSPlayerPlaybackStateChangeEvent; + | HMSHLSPlayerPlaybackStateChangeEvent + | HMSHLSPLayerPlaybackResolutionChangeEvent; // #endregion HMS HLSPlayer Playback Events