From 85989fda3cd30b419ec6d49e93b7bc807f1a4bfb Mon Sep 17 00:00:00 2001 From: Scott Nonnenberg Date: Thu, 31 Mar 2022 18:06:56 -0700 Subject: [PATCH] More peeking of group calls to prevent out-of-date member info --- .../conversation/Timeline.stories.tsx | 1 + ts/components/conversation/Timeline.tsx | 15 ++++++++++++- ts/services/audioRecorder.ts | 1 - ts/state/ducks/calling.ts | 22 +++++++++++++++++++ 4 files changed, 37 insertions(+), 2 deletions(-) diff --git a/ts/components/conversation/Timeline.stories.tsx b/ts/components/conversation/Timeline.stories.tsx index 8a6efe1d5..aad38e222 100644 --- a/ts/components/conversation/Timeline.stories.tsx +++ b/ts/components/conversation/Timeline.stories.tsx @@ -417,6 +417,7 @@ const actions = () => ({ unblurAvatar: action('unblurAvatar'), peekGroupCallForTheFirstTime: action('peekGroupCallForTheFirstTime'), + peekGroupCallIfItHasMembers: action('peekGroupCallIfItHasMembers'), }); const renderItem = ({ diff --git a/ts/components/conversation/Timeline.tsx b/ts/components/conversation/Timeline.tsx index 019a9a7c2..dd03adf17 100644 --- a/ts/components/conversation/Timeline.tsx +++ b/ts/components/conversation/Timeline.tsx @@ -46,6 +46,7 @@ import { setScrollBottom, } from '../../util/scrollUtil'; import { LastSeenIndicator } from './LastSeenIndicator'; +import { MINUTE } from '../../util/durations'; const AT_BOTTOM_THRESHOLD = 15; const AT_BOTTOM_DETECTOR_STYLE = { height: AT_BOTTOM_THRESHOLD }; @@ -162,6 +163,7 @@ export type PropsActionsType = { onDelete: (conversationId: string) => unknown; onUnblock: (conversationId: string) => unknown; peekGroupCallForTheFirstTime: (conversationId: string) => unknown; + peekGroupCallIfItHasMembers: (conversationId: string) => unknown; removeMember: (conversationId: string) => unknown; selectMessage: (messageId: string, conversationId: string) => unknown; clearSelectedMessage: () => unknown; @@ -221,6 +223,7 @@ const getActions = createSelector( 'onDelete', 'onUnblock', 'peekGroupCallForTheFirstTime', + 'peekGroupCallIfItHasMembers', 'removeMember', 'selectMessage', 'clearSelectedMessage', @@ -281,6 +284,7 @@ export class Timeline extends React.Component< private hasRecentlyScrolledTimeout?: NodeJS.Timeout; private delayedPeekTimeout?: NodeJS.Timeout; + private peekInterval?: NodeJS.Timeout; override state: StateType = { hasRecentlyScrolled: true, @@ -562,18 +566,27 @@ export class Timeline extends React.Component< this.delayedPeekTimeout = setTimeout(() => { const { id, peekGroupCallForTheFirstTime } = this.props; + this.delayedPeekTimeout = undefined; peekGroupCallForTheFirstTime(id); }, 500); + + this.peekInterval = setInterval(() => { + const { id, peekGroupCallIfItHasMembers } = this.props; + peekGroupCallIfItHasMembers(id); + }, MINUTE); } public override componentWillUnmount(): void { - const { delayedPeekTimeout } = this; + const { delayedPeekTimeout, peekInterval } = this; window.unregisterForActive(this.markNewestBottomVisibleMessageRead); this.intersectionObserver?.disconnect(); clearTimeoutIfNecessary(delayedPeekTimeout); + if (peekInterval) { + clearInterval(peekInterval); + } } public override getSnapshotBeforeUpdate( diff --git a/ts/services/audioRecorder.ts b/ts/services/audioRecorder.ts index 41be88a03..b634c1211 100644 --- a/ts/services/audioRecorder.ts +++ b/ts/services/audioRecorder.ts @@ -102,7 +102,6 @@ export class RecorderClass { async stop(): Promise { if (!this.recorder) { - log.warn('Recorder/stop: Called with no recorder'); return; } diff --git a/ts/state/ducks/calling.ts b/ts/state/ducks/calling.ts index 2cd879d2b..80470ee75 100644 --- a/ts/state/ducks/calling.ts +++ b/ts/state/ducks/calling.ts @@ -372,6 +372,10 @@ const doGroupCallPeek = ( return; } + log.info( + `doGroupCallPeek/groupv2(${conversation.groupId}): Found ${peekInfo.deviceCount} devices` + ); + await calling.updateCallHistoryForGroupCall(conversationId, peekInfo); const formattedPeekInfo = calling.formatGroupCallPeekInfoForRedux(peekInfo); @@ -988,6 +992,23 @@ function peekGroupCallForTheFirstTime( }; } +function peekGroupCallIfItHasMembers( + conversationId: string +): ThunkAction { + return (dispatch, getState) => { + const call = getOwn(getState().calling.callsByConversation, conversationId); + const shouldPeek = + call && + call.callMode === CallMode.Group && + call.joinState === GroupCallJoinState.NotJoined && + call.peekInfo && + call.peekInfo.deviceCount > 0; + if (shouldPeek) { + doGroupCallPeek(conversationId, dispatch, getState); + } + }; +} + function peekNotConnectedGroupCall( payload: PeekNotConnectedGroupCallType ): ThunkAction { @@ -1310,6 +1331,7 @@ export const actions = { openSystemPreferencesAction, outgoingCall, peekGroupCallForTheFirstTime, + peekGroupCallIfItHasMembers, peekNotConnectedGroupCall, receiveIncomingDirectCall, receiveIncomingGroupCall,