From a05d4678b6195cf2532ed03147b330256ee68bf6 Mon Sep 17 00:00:00 2001 From: Christopher Poile Date: Tue, 28 May 2024 17:22:09 -0400 Subject: [PATCH] add joiningChannelId to calls state to track when joining a call --- .../calls_custom_message.tsx | 32 ++++++++++++++++--- .../components/calls_custom_message/index.ts | 7 +++- .../join_call_banner/join_call_banner.tsx | 7 ++-- app/products/calls/state/actions.test.ts | 26 +++++++++++++++ app/products/calls/state/actions.ts | 8 +++++ app/products/calls/types/calls.ts | 2 ++ 6 files changed, 75 insertions(+), 7 deletions(-) diff --git a/app/products/calls/components/calls_custom_message/calls_custom_message.tsx b/app/products/calls/components/calls_custom_message/calls_custom_message.tsx index 63df3632774..e233a18cdca 100644 --- a/app/products/calls/components/calls_custom_message/calls_custom_message.tsx +++ b/app/products/calls/components/calls_custom_message/calls_custom_message.tsx @@ -8,10 +8,12 @@ import {Text, TouchableOpacity, View} from 'react-native'; import {leaveCall} from '@calls/actions'; import {leaveAndJoinWithAlert, showLimitRestrictedAlert} from '@calls/alerts'; +import {setJoiningChannelId} from '@calls/state'; import CompassIcon from '@components/compass_icon'; import FormattedRelativeTime from '@components/formatted_relative_time'; import FormattedText from '@components/formatted_text'; import FormattedTime from '@components/formatted_time'; +import Loading from '@components/loading'; import {useServerUrl} from '@context/server'; import {useTheme} from '@context/theme'; import {changeOpacity, makeStyleSheetFromTheme} from '@utils/theme'; @@ -28,6 +30,7 @@ type Props = { isMilitaryTime: boolean; limitRestrictedInfo?: LimitRestrictedInfo; ccChannelId?: string; + joiningChannelId: string | null; } const getStyleSheet = makeStyleSheetFromTheme((theme: Theme) => { @@ -121,23 +124,34 @@ const getStyleSheet = makeStyleSheetFromTheme((theme: Theme) => { }; }); -export const CallsCustomMessage = ({post, currentUser, isMilitaryTime, ccChannelId, limitRestrictedInfo}: Props) => { +export const CallsCustomMessage = ({ + post, + currentUser, + isMilitaryTime, + ccChannelId, + limitRestrictedInfo, + joiningChannelId, +}: Props) => { const intl = useIntl(); const theme = useTheme(); const style = getStyleSheet(theme); const serverUrl = useServerUrl(); const timezone = getUserTimezone(currentUser); + const joiningThisCall = Boolean(joiningChannelId === post.channelId); const alreadyInTheCall = Boolean(ccChannelId && ccChannelId === post.channelId); const isLimitRestricted = Boolean(limitRestrictedInfo?.limitRestricted); + const joiningMsg = intl.formatMessage({id: 'mobile.calls_joining', defaultMessage: 'Joining...'}); - const joinHandler = useCallback(() => { + const joinHandler = useCallback(async () => { if (isLimitRestricted) { showLimitRestrictedAlert(limitRestrictedInfo!, intl); return; } - leaveAndJoinWithAlert(intl, serverUrl, post.channelId); + setJoiningChannelId(post.channelId); + await leaveAndJoinWithAlert(intl, serverUrl, post.channelId); + setJoiningChannelId(null); }, [limitRestrictedInfo, intl, serverUrl, post.channelId]); const leaveHandler = useCallback(() => { @@ -227,6 +241,16 @@ export const CallsCustomMessage = ({post, currentUser, isMilitaryTime, ccChannel ); + const joiningButton = ( + + ); + return ( <> {title} @@ -248,7 +272,7 @@ export const CallsCustomMessage = ({post, currentUser, isMilitaryTime, ccChannel style={style.timeText} /> - {button} + {joiningThisCall ? joiningButton : button} ); diff --git a/app/products/calls/components/calls_custom_message/index.ts b/app/products/calls/components/calls_custom_message/index.ts index 6368f17b6f3..c50763bf783 100644 --- a/app/products/calls/components/calls_custom_message/index.ts +++ b/app/products/calls/components/calls_custom_message/index.ts @@ -7,7 +7,7 @@ import {distinctUntilChanged, switchMap} from 'rxjs/operators'; import {CallsCustomMessage} from '@calls/components/calls_custom_message/calls_custom_message'; import {observeIsCallLimitRestricted} from '@calls/observers'; -import {observeCurrentCall} from '@calls/state'; +import {observeCurrentCall, observeGlobalCallsState} from '@calls/state'; import {Preferences} from '@constants'; import {getDisplayNamePreferenceAsBool} from '@helpers/api/preference'; import {queryDisplayNamePreferences} from '@queries/servers/preference'; @@ -41,12 +41,17 @@ const enhanced = withObservables(['post'], ({serverUrl, post, database}: OwnProp switchMap((call) => of$(call?.channelId)), distinctUntilChanged(), ); + const joiningChannelId = observeGlobalCallsState().pipe( + switchMap((state) => of$(state?.joiningChannelId)), + distinctUntilChanged(), + ); return { currentUser, isMilitaryTime, limitRestrictedInfo: observeIsCallLimitRestricted(database, serverUrl, post.channelId), ccChannelId, + joiningChannelId, }; }); diff --git a/app/products/calls/components/join_call_banner/join_call_banner.tsx b/app/products/calls/components/join_call_banner/join_call_banner.tsx index b31b78435b5..e4d694d5b8b 100644 --- a/app/products/calls/components/join_call_banner/join_call_banner.tsx +++ b/app/products/calls/components/join_call_banner/join_call_banner.tsx @@ -7,7 +7,7 @@ import {View, Pressable} from 'react-native'; import {dismissIncomingCall} from '@calls/actions'; import {leaveAndJoinWithAlert, showLimitRestrictedAlert} from '@calls/alerts'; -import {removeIncomingCall} from '@calls/state'; +import {removeIncomingCall, setJoiningChannelId} from '@calls/state'; import CompassIcon from '@components/compass_icon'; import FormattedRelativeTime from '@components/formatted_relative_time'; import FormattedText from '@components/formatted_text'; @@ -148,7 +148,10 @@ const JoinCallBanner = ({ showLimitRestrictedAlert(limitRestrictedInfo, intl); return; } - leaveAndJoinWithAlert(intl, serverUrl, channelId); + + setJoiningChannelId(channelId); + await leaveAndJoinWithAlert(intl, serverUrl, channelId); + setJoiningChannelId(null); }; const onDismissPress = () => { diff --git a/app/products/calls/state/actions.test.ts b/app/products/calls/state/actions.test.ts index e0c96822af3..bd89327c393 100644 --- a/app/products/calls/state/actions.test.ts +++ b/app/products/calls/state/actions.test.ts @@ -19,6 +19,7 @@ import { setChannelsWithCalls, setCurrentCall, setHost, + setJoiningChannelId, setMicPermissionsErrorDismissed, setMicPermissionsGranted, setRecordingState, @@ -919,6 +920,7 @@ describe('useCallsState', () => { }; const expectedGlobalState: GlobalCallsState = { micPermissionsGranted: true, + joiningChannelId: null, }; // setup @@ -955,11 +957,35 @@ describe('useCallsState', () => { act(() => { myselfLeftCall(); userLeftCall('server1', 'channel-1', 'mySessionId'); + + // reset state to default + setMicPermissionsGranted(false); }); assert.deepEqual(result.current[0], initialCallsState); assert.deepEqual(result.current[1], null); }); + it('joining call', () => { + const initialGlobalState = DefaultGlobalCallsState; + const expectedGlobalState: GlobalCallsState = { + ...DefaultGlobalCallsState, + joiningChannelId: 'channel-1', + }; + + // setup + const {result} = renderHook(() => { + return [useGlobalCallsState()]; + }); + + // start joining call + act(() => setJoiningChannelId('channel-1')); + assert.deepEqual(result.current[0], expectedGlobalState); + + // end joining call + act(() => setJoiningChannelId(null)); + assert.deepEqual(result.current[0], initialGlobalState); + }); + it('CallQuality', async () => { const initialCallsState: CallsState = { ...DefaultCallsState, diff --git a/app/products/calls/state/actions.ts b/app/products/calls/state/actions.ts index 5ce391ec4ce..43064de98f8 100644 --- a/app/products/calls/state/actions.ts +++ b/app/products/calls/state/actions.ts @@ -564,6 +564,14 @@ export const setSpeakerPhone = (speakerphoneOn: boolean) => { } }; +export const setJoiningChannelId = (joiningChannelId: string | null) => { + const globalCallsState = getGlobalCallsState(); + setGlobalCallsState({ + ...globalCallsState, + joiningChannelId, + }); +}; + export const setAudioDeviceInfo = (info: AudioDeviceInfo) => { const call = getCurrentCall(); if (call) { diff --git a/app/products/calls/types/calls.ts b/app/products/calls/types/calls.ts index 2846ae62527..5f455b9d441 100644 --- a/app/products/calls/types/calls.ts +++ b/app/products/calls/types/calls.ts @@ -11,10 +11,12 @@ import type UserModel from '@typings/database/models/servers/user'; export type GlobalCallsState = { micPermissionsGranted: boolean; + joiningChannelId: string | null; } export const DefaultGlobalCallsState: GlobalCallsState = { micPermissionsGranted: false, + joiningChannelId: null, }; export type CallsState = {