Add support for active call item rendering in timeline (#5775)

* feat(timeline): Add support for active call item rendering in timeline

* Update active call as per design (show raw count of members)

* fixup project files

* revert unexpected generated mocks change

* code review

* Record preview snapshots

* revert changes on project.yml

* post rebase fix
This commit is contained in:
Valere Fedronic
2026-07-22 16:13:46 +02:00
committed by GitHub
parent 94313173f0
commit 0f72fe3511
23 changed files with 329 additions and 51 deletions
@@ -11,10 +11,21 @@ import Foundation
nonisolated struct CallNotificationRoomTimelineItem: RoomTimelineItemProtocol, Equatable {
let id: TimelineItemIdentifier
let timestamp: Date
let sender: TimelineItemSender
let isDM: Bool
let isDeclinedByMe: Bool
let isDeclined: Bool
let isVoiceCall: Bool
/// Represents the state of the call notification - either tombstoned (ended) or active (ongoing)
enum CallState: Equatable {
/// A tombstoned/ended call notification
case tombstoned(isDeclinedByMe: Bool, isDeclined: Bool)
/// An active/ongoing call notification
case active(activeMembers: [String],
isJoined: Bool,
callStartTimestamp: Date?)
}
let callState: CallState
var properties = RoomTimelineItemProperties()
}
@@ -71,8 +71,14 @@ nonisolated struct RoomTimelineItemFactory: RoomTimelineItemFactoryProtocol {
isOutgoing: isOutgoing)
case .callInvite:
return buildCallInviteTimelineItem(for: eventItemProxy)
case .rtcNotification(let callIntent, let declinedBy, _, _, _):
return buildCallNotificationTimelineItem(for: eventItemProxy, isDM: isDM, callIntent: callIntent, declinedBy: declinedBy)
case .rtcNotification(let callIntent, let declinedBy, let activeMembers, let callStartMillis, let isJoined):
return buildCallNotificationTimelineItem(for: eventItemProxy,
isDM: isDM,
callIntent: callIntent,
declinedBy: declinedBy,
activeMembers: activeMembers,
callStartTimestampMillis: callStartMillis,
isJoined: isJoined)
}
}
@@ -853,15 +859,25 @@ nonisolated struct RoomTimelineItemFactory: RoomTimelineItemFactoryProtocol {
private func buildCallNotificationTimelineItem(for eventItemProxy: EventTimelineItemProxy,
isDM: Bool,
callIntent: String?,
declinedBy: [String]) -> RoomTimelineItemProtocol {
declinedBy: [String],
activeMembers: [String],
callStartTimestampMillis: UInt64?,
isJoined: Bool) -> RoomTimelineItemProtocol {
let isVoiceCall = callIntent == CallIntent.audio.rawValue
let callStartTimestamp = callStartTimestampMillis.map { Date(timeIntervalSince1970: TimeInterval($0 / 1000)) }
return CallNotificationRoomTimelineItem(id: eventItemProxy.id,
timestamp: eventItemProxy.timestamp,
sender: eventItemProxy.sender,
isDM: isDM,
isDeclinedByMe: declinedBy.contains(userID),
isDeclined: !declinedBy.isEmpty,
isVoiceCall: isVoiceCall,
properties: .init())
callState: activeMembers.count > 0 ?
.active(activeMembers: activeMembers,
isJoined: isJoined,
callStartTimestamp: callStartTimestamp)
:
.tombstoned(isDeclinedByMe: declinedBy.contains(userID),
isDeclined: declinedBy.count > 0))
}
// MARK: - State Events