@@ -246,8 +246,10 @@ class GroupCallLocalMemberView: GroupCallMemberView {
246246class GroupCallRemoteMemberView : GroupCallMemberView {
247247 private weak var videoView : GroupCallRemoteVideoView ?
248248
249+ var deferredReconfigTimer : Timer ?
249250 let errorView = GroupCallErrorView ( )
250251 let avatarView = AvatarImageView ( )
252+ let spinner = UIActivityIndicatorView ( style: . whiteLarge)
251253 lazy var avatarWidthConstraint = avatarView. autoSetDimension ( . width, toSize: CGFloat ( avatarDiameter) )
252254
253255 var isCallMinimized : Bool = false {
@@ -292,8 +294,11 @@ class GroupCallRemoteMemberView: GroupCallMemberView {
292294
293295 noVideoView. insertSubview ( avatarView, belowSubview: muteIndicatorImage)
294296 noVideoView. insertSubview ( errorView, belowSubview: muteIndicatorImage)
297+ noVideoView. insertSubview ( spinner, belowSubview: muteIndicatorImage)
298+
295299 avatarView. autoCenterInSuperview ( )
296300 errorView. autoPinEdgesToSuperviewEdges ( )
301+ spinner. autoCenterInSuperview ( )
297302 }
298303
299304 required init ? ( coder: NSCoder ) {
@@ -303,6 +308,7 @@ class GroupCallRemoteMemberView: GroupCallMemberView {
303308 private var hasBeenConfigured = false
304309 func configure( call: SignalCall , device: RemoteDeviceState ) {
305310 hasBeenConfigured = true
311+ deferredReconfigTimer? . invalidate ( )
306312
307313 let ( profileImage, conversationColorName) = databaseStorage. uiRead { transaction in
308314 return (
@@ -337,14 +343,37 @@ class GroupCallRemoteMemberView: GroupCallMemberView {
337343 ) . themeColor
338344
339345 configureRemoteVideo ( device: device)
346+ let isRemoteDeviceBlocked = OWSBlockingManager . shared ( ) . isAddressBlocked ( device. address)
347+ let errorDeferralInterval : TimeInterval = 5.0
348+ let addedDate = Date ( millisecondsSince1970: device. addedTime)
349+ let connectionDuration = - addedDate. timeIntervalSinceNow
340350
341351 // Hide these views. They'll be unhidden below.
342- [ errorView, avatarView, videoView] . forEach { $0? . isHidden = true }
343-
344- if !device. mediaKeysReceived {
352+ [ errorView, avatarView, videoView, spinner] . forEach { $0? . isHidden = true }
353+
354+ if !device. mediaKeysReceived, !isRemoteDeviceBlocked, connectionDuration < errorDeferralInterval {
355+ // No media keys, but that's expected since we just joined the call.
356+ // Schedule a timer to re-check and show a spinner in the meantime
357+ spinner. isHidden = false
358+ if !spinner. isAnimating { spinner. startAnimating ( ) }
359+
360+ let configuredDemuxId = device. demuxId
361+ let scheduledInterval = errorDeferralInterval - connectionDuration
362+ deferredReconfigTimer = Timer . scheduledTimer (
363+ withTimeInterval: scheduledInterval,
364+ repeats: false ,
365+ block: { [ weak self] _ in
366+ guard let self = self else { return }
367+ guard call. isGroupCall, let groupCall = call. groupCall else { return }
368+ guard let updatedState = groupCall. remoteDeviceStates. values
369+ . first ( where: { $0. demuxId == configuredDemuxId } ) else { return }
370+ self . configure ( call: call, device: updatedState)
371+ } )
372+
373+ } else if !device. mediaKeysReceived {
345374 // No media keys. Display error view
346375 errorView. isHidden = false
347- configureErrorView ( for: device. address)
376+ configureErrorView ( for: device. address, isBlocked : isRemoteDeviceBlocked )
348377
349378 } else if let videoView = videoView, device. videoTrack != nil {
350379 // We have a video track! If we don't know the mute state, show both.
@@ -382,10 +411,8 @@ class GroupCallRemoteMemberView: GroupCallMemberView {
382411 owsAssertDebug ( videoView != nil , " Missing remote video view " )
383412 }
384413
385- func configureErrorView( for address: SignalServiceAddress ) {
386- let isBlocked = OWSBlockingManager . shared ( ) . isAddressBlocked ( address)
414+ func configureErrorView( for address: SignalServiceAddress , isBlocked: Bool ) {
387415 let displayName : String
388-
389416 if address. isLocalAddress {
390417 displayName = NSLocalizedString (
391418 " GROUP_CALL_YOU_ON_ANOTHER_DEVICE " ,
0 commit comments