diff --git a/Session/Calls/Call Management/SessionCall.swift b/Session/Calls/Call Management/SessionCall.swift
index 7c71c98da..30d60b92b 100644
--- a/Session/Calls/Call Management/SessionCall.swift	
+++ b/Session/Calls/Call Management/SessionCall.swift	
@@ -87,6 +87,7 @@ public final class SessionCall: CurrentCallProtocol, WebRTCSessionDelegate {
         didSet {
             stateDidChange?()
             hasConnectedDidChange?()
+            updateCallDetailedStatus?("Call Connected")
         }
     }
 
@@ -94,6 +95,7 @@ public final class SessionCall: CurrentCallProtocol, WebRTCSessionDelegate {
         didSet {
             stateDidChange?()
             hasEndedDidChange?()
+            updateCallDetailedStatus?("")
         }
     }
 
@@ -113,6 +115,7 @@ public final class SessionCall: CurrentCallProtocol, WebRTCSessionDelegate {
     var remoteVideoStateDidChange: ((Bool) -> Void)?
     var hasStartedReconnecting: (() -> Void)?
     var hasReconnected: (() -> Void)?
+    var updateCallDetailedStatus: ((String) -> Void)?
     
     // MARK: - Derived Properties
     
@@ -249,6 +252,8 @@ public final class SessionCall: CurrentCallProtocol, WebRTCSessionDelegate {
         
         self.callInteractionId = interaction?.id
         
+        self.updateCallDetailedStatus?("Creating Call")
+        
         try? webRTCSession
             .sendPreOffer(
                 db,
@@ -259,8 +264,9 @@ public final class SessionCall: CurrentCallProtocol, WebRTCSessionDelegate {
             .retry(5)
             // Start the timeout timer for the call
             .handleEvents(receiveOutput: { [weak self] _ in self?.setupTimeoutTimer() })
-            .flatMap { _ in
-                webRTCSession
+            .flatMap { [weak self] _ in
+                self?.updateCallDetailedStatus?("Sending Call Offer")
+                return webRTCSession
                     .sendOffer(to: thread)
                     .retry(5)
             }
@@ -269,6 +275,7 @@ public final class SessionCall: CurrentCallProtocol, WebRTCSessionDelegate {
                     switch result {
                         case .finished:
                             SNLog("[Calls] Offer message sent")
+                            self?.updateCallDetailedStatus?("Sending Connection Candidates")
                         case .failure(let error):
                             SNLog("[Calls] Error initializing call after 5 retries: \(error), ending call...")
                             self?.handleCallInitializationFailed()
@@ -284,6 +291,7 @@ public final class SessionCall: CurrentCallProtocol, WebRTCSessionDelegate {
         
         if let sdp = remoteSDP {
             SNLog("[Calls] Got remote sdp already")
+            self.updateCallDetailedStatus?("Answering Call")
             webRTCSession.handleRemoteSDP(sdp, from: sessionId) // This sends an answer message internally
         }
     }
@@ -422,6 +430,18 @@ public final class SessionCall: CurrentCallProtocol, WebRTCSessionDelegate {
         isRemoteVideoEnabled = isEnabled
     }
     
+    public func iceCandidateDidSend() {
+        DispatchQueue.main.async {
+            self.updateCallDetailedStatus?("Awaiting Recipient Answer...")
+        }
+    }
+    
+    public func iceCandidateDidReceive() {
+        DispatchQueue.main.async {
+            self.updateCallDetailedStatus?("Handling Connection Candidates")
+        }
+    }
+    
     public func didReceiveHangUpSignal() {
         self.hasEnded = true
         DispatchQueue.main.async {
diff --git a/Session/Calls/CallVC.swift b/Session/Calls/CallVC.swift
index 4271ce2eb..4d207b471 100644
--- a/Session/Calls/CallVC.swift
+++ b/Session/Calls/CallVC.swift
@@ -315,7 +315,6 @@ final class CallVC: UIViewController, VideoPreviewDelegate {
         result.font = .boldSystemFont(ofSize: Values.veryLargeFontSize)
         result.themeTextColor = .textPrimary
         result.textAlignment = .center
-        result.isHidden = call.hasConnected
         
         if call.hasStartedConnecting { result.text = "callsConnecting".localized() }
         
@@ -331,6 +330,15 @@ final class CallVC: UIViewController, VideoPreviewDelegate {
         return result
     }()
     
+    private lazy var callInfoLabelStackView: UIStackView = {
+        let result: UIStackView = UIStackView(arrangedSubviews: [callInfoLabel, callDetailedInfoLabel])
+        result.axis = .vertical
+        result.spacing = Values.mediumSpacing
+        result.isHidden = call.hasConnected
+        
+        return result
+    }()
+    
     private lazy var callDurationLabel: UILabel = {
         let result = UILabel()
         result.font = .boldSystemFont(ofSize: Values.veryLargeFontSize)
@@ -359,11 +367,11 @@ final class CallVC: UIViewController, VideoPreviewDelegate {
                     remoteVideoView.alpha = isEnabled ? 1 : 0
                 }
                 
-                if self.callInfoLabel.alpha < 0.5 {
+                if self.callInfoLabelStackView.alpha < 0.5 {
                     UIView.animate(withDuration: 0.25) {
                         self.operationPanel.alpha = 1
                         self.responsePanel.alpha = 1
-                        self.callInfoLabel.alpha = 1
+                        self.callInfoLabelStackView.alpha = 1
                     }
                 }
             }
@@ -396,7 +404,7 @@ final class CallVC: UIViewController, VideoPreviewDelegate {
                 self?.durationTimer = Timer.scheduledTimer(withTimeInterval: 1, repeats: true) { _ in
                     self?.updateDuration()
                 }
-                self?.callInfoLabel.isHidden = true
+                self?.callInfoLabelStackView.isHidden = true
                 self?.callDurationLabel.isHidden = false
             }
         }
@@ -411,7 +419,7 @@ final class CallVC: UIViewController, VideoPreviewDelegate {
         
         self.call.hasStartedReconnecting = { [weak self] in
             DispatchQueue.main.async {
-                self?.callInfoLabel.isHidden = false
+                self?.callInfoLabelStackView.isHidden = false
                 self?.callDurationLabel.isHidden = true
                 self?.callInfoLabel.text = "callsReconnecting".localized()
             }
@@ -419,10 +427,16 @@ final class CallVC: UIViewController, VideoPreviewDelegate {
         
         self.call.hasReconnected = { [weak self] in
             DispatchQueue.main.async {
-                self?.callInfoLabel.isHidden = true
+                self?.callInfoLabelStackView.isHidden = true
                 self?.callDurationLabel.isHidden = false
             }
         }
+        
+        self.call.updateCallDetailedStatus = { [weak self] status in
+            DispatchQueue.main.async {
+                self?.callDetailedInfoLabel.text = status
+            }
+        }
     }
     
     required init(coder: NSCoder) { preconditionFailure("Use init(for:) instead.") }
@@ -519,10 +533,10 @@ final class CallVC: UIViewController, VideoPreviewDelegate {
         callInfoLabelContainer.pin(.top, to: .bottom, of: profilePictureView)
         callInfoLabelContainer.pin(.bottom, to: .bottom, of: profilePictureContainer)
         callInfoLabelContainer.pin([ UIView.HorizontalEdge.left, UIView.HorizontalEdge.right ], to: view)
-        callInfoLabelContainer.addSubview(callInfoLabel)
+        callInfoLabelContainer.addSubview(callInfoLabelStackView)
         callInfoLabelContainer.addSubview(callDurationLabel)
-        callInfoLabel.translatesAutoresizingMaskIntoConstraints = false
-        callInfoLabel.center(in: callInfoLabelContainer)
+        callInfoLabelStackView.translatesAutoresizingMaskIntoConstraints = false
+        callInfoLabelStackView.center(in: callInfoLabelContainer)
         callDurationLabel.translatesAutoresizingMaskIntoConstraints = false
         callDurationLabel.center(in: callInfoLabelContainer)
     }
@@ -596,7 +610,7 @@ final class CallVC: UIViewController, VideoPreviewDelegate {
     
     func handleEndCallMessage() {
         SNLog("[Calls] Ending call.")
-        self.callInfoLabel.isHidden = false
+        self.callInfoLabelStackView.isHidden = false
         self.callDurationLabel.isHidden = true
         self.callInfoLabel.text = "callsEnded".localized()
         
@@ -605,7 +619,7 @@ final class CallVC: UIViewController, VideoPreviewDelegate {
             remoteVideoView.alpha = 0
             self.operationPanel.alpha = 1
             self.responsePanel.alpha = 1
-            self.callInfoLabel.alpha = 1
+            self.callInfoLabelStackView.alpha = 1
         }
         
         Timer.scheduledTimer(withTimeInterval: 2, repeats: false) { [weak self] _ in
diff --git a/Session/Calls/WebRTC/WebRTCSession+MessageHandling.swift b/Session/Calls/WebRTC/WebRTCSession+MessageHandling.swift
index 5bac29a03..551c787e2 100644
--- a/Session/Calls/WebRTC/WebRTCSession+MessageHandling.swift
+++ b/Session/Calls/WebRTC/WebRTCSession+MessageHandling.swift
@@ -9,6 +9,7 @@ extension WebRTCSession {
     
     public func handleICECandidates(_ candidate: [RTCIceCandidate]) {
         SNLog("[Calls] Received ICE candidate message.")
+        self.delegate?.iceCandidateDidReceive()
         candidate.forEach { peerConnection?.add($0, completionHandler: { _ in  }) }
     }
     
diff --git a/Session/Calls/WebRTC/WebRTCSession.swift b/Session/Calls/WebRTC/WebRTCSession.swift
index b766b862c..57d9ed29b 100644
--- a/Session/Calls/WebRTC/WebRTCSession.swift
+++ b/Session/Calls/WebRTC/WebRTCSession.swift
@@ -12,6 +12,8 @@ public protocol WebRTCSessionDelegate: AnyObject {
     
     func webRTCIsConnected()
     func isRemoteVideoDidChange(isEnabled: Bool)
+    func iceCandidateDidSend()
+    func iceCandidateDidReceive()
     func dataChannelDidOpen()
     func didReceiveHangUpSignal()
     func reconnectIfNeeded()
@@ -339,9 +341,21 @@ public final class WebRTCSession : NSObject, RTCPeerConnectionDelegate {
             }
             .subscribe(on: DispatchQueue.global(qos: .userInitiated))
             .flatMap { [dependencies = self.dependencies] sendData in
-                MessageSender.sendImmediate(data: sendData, using: dependencies)
+                MessageSender
+                    .sendImmediate(data: sendData, using: dependencies)
+                    .retry(5)
             }
-            .sinkUntilComplete()
+            .sinkUntilComplete(
+                receiveCompletion: { [weak self] result in
+                    switch result {
+                        case .finished:
+                            SNLog("[Calls] ICE candidates sent")
+                            self?.delegate?.iceCandidateDidSend()
+                        case .failure(let error):
+                            SNLog("[Calls] Error sending ICE candidates due to error: \(error)")
+                    }
+                }
+            )
     }
     
     public func endCall(