feat: Render declined calls in DM timeline (#5512)

* feat: Render declined calls in DM timeline

* Record preview snapshots

* review: Use CallIntent constant

* review: clean-up

* Record preview snapshots

* review: Move private field to the bottom with MARK: - Private

* review: Male CallIntent a string enum to use rawValue

---------

Co-authored-by: Element CI <ci@element.io>
This commit is contained in:
Valere Fedronic
2026-05-11 13:51:30 +02:00
committed by GitHub
parent 2b3cd27129
commit ba23153ab4
10 changed files with 154 additions and 52 deletions
+4 -8
View File
@@ -746,7 +746,6 @@
7C1A7B594B2F8143F0DD0005 /* ElementXAttributeScope.swift in Sources */ = {isa = PBXBuildFile; fileRef = C024C151639C4E1B91FCC68B /* ElementXAttributeScope.swift */; }; 7C1A7B594B2F8143F0DD0005 /* ElementXAttributeScope.swift in Sources */ = {isa = PBXBuildFile; fileRef = C024C151639C4E1B91FCC68B /* ElementXAttributeScope.swift */; };
7C545FFEC9930F7247352593 /* SecurityAndPrivacyScreenViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 978092B01BEAB39F2C4389AE /* SecurityAndPrivacyScreenViewModel.swift */; }; 7C545FFEC9930F7247352593 /* SecurityAndPrivacyScreenViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 978092B01BEAB39F2C4389AE /* SecurityAndPrivacyScreenViewModel.swift */; };
7C6376192F578E0BA801BFEC /* AnalyticsSettingsScreenModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = 42C64A14EE89928207E3B42B /* AnalyticsSettingsScreenModels.swift */; }; 7C6376192F578E0BA801BFEC /* AnalyticsSettingsScreenModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = 42C64A14EE89928207E3B42B /* AnalyticsSettingsScreenModels.swift */; };
7C92C6B48879C733859B7A0D /* CallIntent.swift in Sources */ = {isa = PBXBuildFile; fileRef = 587698C8FC0076A2DC822EEA /* CallIntent.swift */; };
7C9BDF1FC7BD46C4676536AB /* AuthenticationStartScreenBackgroundImage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 682BC7BAF0EFEF512A8C5140 /* AuthenticationStartScreenBackgroundImage.swift */; }; 7C9BDF1FC7BD46C4676536AB /* AuthenticationStartScreenBackgroundImage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 682BC7BAF0EFEF512A8C5140 /* AuthenticationStartScreenBackgroundImage.swift */; };
7CD16990BA843BE9ED639129 /* ImageRoomTimelineItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3DFE4453AB0B34C203447162 /* ImageRoomTimelineItem.swift */; }; 7CD16990BA843BE9ED639129 /* ImageRoomTimelineItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3DFE4453AB0B34C203447162 /* ImageRoomTimelineItem.swift */; };
7D249465ED00988EEEC14E05 /* JoinedRoomProxyMock.swift in Sources */ = {isa = PBXBuildFile; fileRef = 867DC9530C42F7B5176BE465 /* JoinedRoomProxyMock.swift */; }; 7D249465ED00988EEEC14E05 /* JoinedRoomProxyMock.swift in Sources */ = {isa = PBXBuildFile; fileRef = 867DC9530C42F7B5176BE465 /* JoinedRoomProxyMock.swift */; };
@@ -1112,7 +1111,6 @@
BA43D782BE85C7F5F20C624A /* AttributedStringBuilderProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 72F37B5DA798C9AE436F2C2C /* AttributedStringBuilderProtocol.swift */; }; BA43D782BE85C7F5F20C624A /* AttributedStringBuilderProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 72F37B5DA798C9AE436F2C2C /* AttributedStringBuilderProtocol.swift */; };
BA48D6AFF6421D199148C0A1 /* KnockRequestsListScreenViewModelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = C9AC2CC94FA06F728883B694 /* KnockRequestsListScreenViewModelTests.swift */; }; BA48D6AFF6421D199148C0A1 /* KnockRequestsListScreenViewModelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = C9AC2CC94FA06F728883B694 /* KnockRequestsListScreenViewModelTests.swift */; };
BA4C9049BC96DED3A2F3B82E /* RoomNotificationSettingsScreenViewModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 03DD998E523D4EC93C7ED703 /* RoomNotificationSettingsScreenViewModelProtocol.swift */; }; BA4C9049BC96DED3A2F3B82E /* RoomNotificationSettingsScreenViewModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 03DD998E523D4EC93C7ED703 /* RoomNotificationSettingsScreenViewModelProtocol.swift */; };
BA6B8A60185FE238FBCE705E /* CallIntent.swift in Sources */ = {isa = PBXBuildFile; fileRef = 587698C8FC0076A2DC822EEA /* CallIntent.swift */; };
BB6BF528BC7F5B87E08C4F18 /* CameraPicker.swift in Sources */ = {isa = PBXBuildFile; fileRef = B8A3B7637DDBD6AA97AC2545 /* CameraPicker.swift */; }; BB6BF528BC7F5B87E08C4F18 /* CameraPicker.swift in Sources */ = {isa = PBXBuildFile; fileRef = B8A3B7637DDBD6AA97AC2545 /* CameraPicker.swift */; };
BB784A02BADB03C820617A46 /* TextRoomTimelineItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 90A55430639712CFACA34F43 /* TextRoomTimelineItem.swift */; }; BB784A02BADB03C820617A46 /* TextRoomTimelineItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 90A55430639712CFACA34F43 /* TextRoomTimelineItem.swift */; };
BB9B800C6094E34860E89DC5 /* AppLockSetupBiometricsScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = F8CCF9A924521DECA44778C4 /* AppLockSetupBiometricsScreen.swift */; }; BB9B800C6094E34860E89DC5 /* AppLockSetupBiometricsScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = F8CCF9A924521DECA44778C4 /* AppLockSetupBiometricsScreen.swift */; };
@@ -1178,7 +1176,6 @@
C646CFE86CA46495D6BB7448 /* ManageAuthorizedSpacesScreenViewModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74AE4F02A507882743973214 /* ManageAuthorizedSpacesScreenViewModelProtocol.swift */; }; C646CFE86CA46495D6BB7448 /* ManageAuthorizedSpacesScreenViewModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74AE4F02A507882743973214 /* ManageAuthorizedSpacesScreenViewModelProtocol.swift */; };
C67156445600FAE6430DE41E /* LocationSharingScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6F56E6E41C6DFE8054787D57 /* LocationSharingScreen.swift */; }; C67156445600FAE6430DE41E /* LocationSharingScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6F56E6E41C6DFE8054787D57 /* LocationSharingScreen.swift */; };
C67FCC854F3A6FC7A2EC04D0 /* MediaUploadPreviewScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = 70C86696AC9521F8ED88FBEB /* MediaUploadPreviewScreen.swift */; }; C67FCC854F3A6FC7A2EC04D0 /* MediaUploadPreviewScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = 70C86696AC9521F8ED88FBEB /* MediaUploadPreviewScreen.swift */; };
C6A4A679116E2FC0DFE665EF /* CallIntent.swift in Sources */ = {isa = PBXBuildFile; fileRef = 587698C8FC0076A2DC822EEA /* CallIntent.swift */; };
C6AC34B731F4F853E9D15146 /* AnalyticsConfiguration.swift in Sources */ = {isa = PBXBuildFile; fileRef = FA2397174D0DC3918A7A8A7B /* AnalyticsConfiguration.swift */; }; C6AC34B731F4F853E9D15146 /* AnalyticsConfiguration.swift in Sources */ = {isa = PBXBuildFile; fileRef = FA2397174D0DC3918A7A8A7B /* AnalyticsConfiguration.swift */; };
C6C06DDA8881260303FBA3A0 /* Date.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2141693488CE5446BB391964 /* Date.swift */; }; C6C06DDA8881260303FBA3A0 /* Date.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2141693488CE5446BB391964 /* Date.swift */; };
C76892321558E75101E68ED6 /* ReadableFrameModifier.swift in Sources */ = {isa = PBXBuildFile; fileRef = 398817652FA8ABAE0A31AC6D /* ReadableFrameModifier.swift */; }; C76892321558E75101E68ED6 /* ReadableFrameModifier.swift in Sources */ = {isa = PBXBuildFile; fileRef = 398817652FA8ABAE0A31AC6D /* ReadableFrameModifier.swift */; };
@@ -1369,6 +1366,7 @@
E794AB6ABE1FF5AF0573FEA1 /* BlurHashEncode.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9332DFE9642F0A46ECA0497B /* BlurHashEncode.swift */; }; E794AB6ABE1FF5AF0573FEA1 /* BlurHashEncode.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9332DFE9642F0A46ECA0497B /* BlurHashEncode.swift */; };
E79D79CDAFE8BEBCC3AECA54 /* AppLockScreenViewModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 08283301736A6FE9D558B2CB /* AppLockScreenViewModelProtocol.swift */; }; E79D79CDAFE8BEBCC3AECA54 /* AppLockScreenViewModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 08283301736A6FE9D558B2CB /* AppLockScreenViewModelProtocol.swift */; };
E7DB506E77CED28D6FE6203D /* ManageAuthorizedSpacesScreenModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = AD8E7C716B8DC2F71E9AC439 /* ManageAuthorizedSpacesScreenModels.swift */; }; E7DB506E77CED28D6FE6203D /* ManageAuthorizedSpacesScreenModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = AD8E7C716B8DC2F71E9AC439 /* ManageAuthorizedSpacesScreenModels.swift */; };
E81E8B7A8ADDB2A912A609F6 /* CallIntent.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6C2DB32B72EA4772E2C9E3B3 /* CallIntent.swift */; };
E82E13CC3EB923CCB8F8273C /* TimelineProxy.swift in Sources */ = {isa = PBXBuildFile; fileRef = F9E543072DE58E751F028998 /* TimelineProxy.swift */; }; E82E13CC3EB923CCB8F8273C /* TimelineProxy.swift in Sources */ = {isa = PBXBuildFile; fileRef = F9E543072DE58E751F028998 /* TimelineProxy.swift */; };
E84ADFE9696936C18C2424B5 /* SecureBackupScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84A00BB9CD12CF6AC98D5485 /* SecureBackupScreen.swift */; }; E84ADFE9696936C18C2424B5 /* SecureBackupScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84A00BB9CD12CF6AC98D5485 /* SecureBackupScreen.swift */; };
E8AE3BE5C5D2E6C91751A2A6 /* StateMachineFactory.swift in Sources */ = {isa = PBXBuildFile; fileRef = AC73285743189AE4498A51DD /* StateMachineFactory.swift */; }; E8AE3BE5C5D2E6C91751A2A6 /* StateMachineFactory.swift in Sources */ = {isa = PBXBuildFile; fileRef = AC73285743189AE4498A51DD /* StateMachineFactory.swift */; };
@@ -2123,7 +2121,6 @@
580BDCD23DD02481AB5FFB47 /* LeaveSpaceHandleSDKMock.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LeaveSpaceHandleSDKMock.swift; sourceTree = "<group>"; }; 580BDCD23DD02481AB5FFB47 /* LeaveSpaceHandleSDKMock.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LeaveSpaceHandleSDKMock.swift; sourceTree = "<group>"; };
584A61D9C459FAFEF038A7C0 /* Section.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Section.swift; sourceTree = "<group>"; }; 584A61D9C459FAFEF038A7C0 /* Section.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Section.swift; sourceTree = "<group>"; };
5875F7C0A2398E9F134B1284 /* EncryptionResetScreenViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EncryptionResetScreenViewModel.swift; sourceTree = "<group>"; }; 5875F7C0A2398E9F134B1284 /* EncryptionResetScreenViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EncryptionResetScreenViewModel.swift; sourceTree = "<group>"; };
587698C8FC0076A2DC822EEA /* CallIntent.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CallIntent.swift; sourceTree = "<group>"; };
58C2527813FDAE23E72A9063 /* AnalyticsSettingsScreenViewModelTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AnalyticsSettingsScreenViewModelTests.swift; sourceTree = "<group>"; }; 58C2527813FDAE23E72A9063 /* AnalyticsSettingsScreenViewModelTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AnalyticsSettingsScreenViewModelTests.swift; sourceTree = "<group>"; };
58D295F0081084F38DB20893 /* RoomNotificationSettingsScreenViewModelTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomNotificationSettingsScreenViewModelTests.swift; sourceTree = "<group>"; }; 58D295F0081084F38DB20893 /* RoomNotificationSettingsScreenViewModelTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomNotificationSettingsScreenViewModelTests.swift; sourceTree = "<group>"; };
592A35163B0749C66BFD6186 /* MapLibreStaticMapView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MapLibreStaticMapView.swift; sourceTree = "<group>"; }; 592A35163B0749C66BFD6186 /* MapLibreStaticMapView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MapLibreStaticMapView.swift; sourceTree = "<group>"; };
@@ -2218,6 +2215,7 @@
6B2A421198FD20AAAED20004 /* RoomChangeRolesScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomChangeRolesScreen.swift; sourceTree = "<group>"; }; 6B2A421198FD20AAAED20004 /* RoomChangeRolesScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomChangeRolesScreen.swift; sourceTree = "<group>"; };
6B5E29E9A22F45534FBD5B58 /* EmojiPickerScreenHeaderView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EmojiPickerScreenHeaderView.swift; sourceTree = "<group>"; }; 6B5E29E9A22F45534FBD5B58 /* EmojiPickerScreenHeaderView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EmojiPickerScreenHeaderView.swift; sourceTree = "<group>"; };
6C113E0CB7E15E9765B1817A /* EmojiProvider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EmojiProvider.swift; sourceTree = "<group>"; }; 6C113E0CB7E15E9765B1817A /* EmojiProvider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EmojiProvider.swift; sourceTree = "<group>"; };
6C2DB32B72EA4772E2C9E3B3 /* CallIntent.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CallIntent.swift; sourceTree = "<group>"; };
6C5BFCB7257F7A3CF70F5DA9 /* SDKGeneratedMocks.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SDKGeneratedMocks.swift; sourceTree = "<group>"; }; 6C5BFCB7257F7A3CF70F5DA9 /* SDKGeneratedMocks.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SDKGeneratedMocks.swift; sourceTree = "<group>"; };
6C8EC6EA7EDFCE46710DA306 /* AnalyticsPromptScreenViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AnalyticsPromptScreenViewModel.swift; sourceTree = "<group>"; }; 6C8EC6EA7EDFCE46710DA306 /* AnalyticsPromptScreenViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AnalyticsPromptScreenViewModel.swift; sourceTree = "<group>"; };
6C9651CD1066F239C7739240 /* NSEUserSession.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NSEUserSession.swift; sourceTree = "<group>"; }; 6C9651CD1066F239C7739240 /* NSEUserSession.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NSEUserSession.swift; sourceTree = "<group>"; };
@@ -3257,7 +3255,6 @@
06501F0E978B2D5C92771DC7 /* Logging */ = { 06501F0E978B2D5C92771DC7 /* Logging */ = {
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
587698C8FC0076A2DC822EEA /* CallIntent.swift */,
41A8571A8A071FB41778C016 /* ExtensionLogger.swift */, 41A8571A8A071FB41778C016 /* ExtensionLogger.swift */,
2711E5996016ABD6EAAEB58A /* LogLevel.swift */, 2711E5996016ABD6EAAEB58A /* LogLevel.swift */,
111B698739E3410E2CDB7144 /* MXLog.swift */, 111B698739E3410E2CDB7144 /* MXLog.swift */,
@@ -6231,6 +6228,7 @@
C142248014E08E885E323E56 /* Avatars.swift */, C142248014E08E885E323E56 /* Avatars.swift */,
E5272BC4A60B6AD7553BACA1 /* BlurHashDecode.swift */, E5272BC4A60B6AD7553BACA1 /* BlurHashDecode.swift */,
9332DFE9642F0A46ECA0497B /* BlurHashEncode.swift */, 9332DFE9642F0A46ECA0497B /* BlurHashEncode.swift */,
6C2DB32B72EA4772E2C9E3B3 /* CallIntent.swift */,
AE52983FAFB4E0998C00EE8A /* CancellableTask.swift */, AE52983FAFB4E0998C00EE8A /* CancellableTask.swift */,
127A57D053CE8C87B5EFB089 /* Consumable.swift */, 127A57D053CE8C87B5EFB089 /* Consumable.swift */,
127C8472672A5BA09EF1ACF8 /* CurrentValuePublisher.swift */, 127C8472672A5BA09EF1ACF8 /* CurrentValuePublisher.swift */,
@@ -7767,7 +7765,6 @@
F255083E18CDBFDF7E640FB1 /* Avatars.swift in Sources */, F255083E18CDBFDF7E640FB1 /* Avatars.swift in Sources */,
A8E324E700E596E36B0A311B /* BootDetectionManager.swift in Sources */, A8E324E700E596E36B0A311B /* BootDetectionManager.swift in Sources */,
9A3B0CDF097E3838FB1B9595 /* Bundle.swift in Sources */, 9A3B0CDF097E3838FB1B9595 /* Bundle.swift in Sources */,
7C92C6B48879C733859B7A0D /* CallIntent.swift in Sources */,
9295F1F5E04484E10780BCE8 /* CharacterSet.swift in Sources */, 9295F1F5E04484E10780BCE8 /* CharacterSet.swift in Sources */,
238D561CA231339C6D4D06F3 /* ClientBuilder.swift in Sources */, 238D561CA231339C6D4D06F3 /* ClientBuilder.swift in Sources */,
0BAF83521871E69D222EE8E4 /* ClientBuilderHook.swift in Sources */, 0BAF83521871E69D222EE8E4 /* ClientBuilderHook.swift in Sources */,
@@ -8008,7 +8005,6 @@
2CC3F27CD76DB00A747BEA6C /* AppSettings.swift in Sources */, 2CC3F27CD76DB00A747BEA6C /* AppSettings.swift in Sources */,
56C18ACF91DD20463B242460 /* AudioPlaybackSpeed.swift in Sources */, 56C18ACF91DD20463B242460 /* AudioPlaybackSpeed.swift in Sources */,
2F2906AE9BC3D0E79A6F98F8 /* Bundle.swift in Sources */, 2F2906AE9BC3D0E79A6F98F8 /* Bundle.swift in Sources */,
BA6B8A60185FE238FBCE705E /* CallIntent.swift in Sources */,
88A87AA16CD93F57143623F8 /* ClientBuilderHook.swift in Sources */, 88A87AA16CD93F57143623F8 /* ClientBuilderHook.swift in Sources */,
D104B27C5DA0626B41CE78D3 /* CurrentValuePublisher.swift in Sources */, D104B27C5DA0626B41CE78D3 /* CurrentValuePublisher.swift in Sources */,
66ED2E6F19B0C669EC71D4CA /* Dictionary.swift in Sources */, 66ED2E6F19B0C669EC71D4CA /* Dictionary.swift in Sources */,
@@ -8202,7 +8198,7 @@
1D2D713A5A269072D103AE37 /* CLLocationManagerProtocol.swift in Sources */, 1D2D713A5A269072D103AE37 /* CLLocationManagerProtocol.swift in Sources */,
5470E62F65AE1803BBF3D528 /* CXProviderMock.swift in Sources */, 5470E62F65AE1803BBF3D528 /* CXProviderMock.swift in Sources */,
3D0DAED550E967AB49F1758C /* CXProviderProtocol.swift in Sources */, 3D0DAED550E967AB49F1758C /* CXProviderProtocol.swift in Sources */,
C6A4A679116E2FC0DFE665EF /* CallIntent.swift in Sources */, E81E8B7A8ADDB2A912A609F6 /* CallIntent.swift in Sources */,
01B63F1A04A276B39AC17014 /* CallInviteRoomTimelineItem.swift in Sources */, 01B63F1A04A276B39AC17014 /* CallInviteRoomTimelineItem.swift in Sources */,
3D72F5F9109AAA257542456B /* CallInviteRoomTimelineView.swift in Sources */, 3D72F5F9109AAA257542456B /* CallInviteRoomTimelineView.swift in Sources */,
E5AB28123E2488F97E953AC0 /* CallNotificationRoomTimelineItem.swift in Sources */, E5AB28123E2488F97E953AC0 /* CallNotificationRoomTimelineItem.swift in Sources */,
@@ -8,7 +8,7 @@
import Foundation import Foundation
import MatrixRustSDK import MatrixRustSDK
enum CallIntent: Codable, CaseIterable { enum CallIntent: String, Codable, CaseIterable {
case video, audio case video, audio
} }
@@ -17,29 +17,17 @@ struct CallNotificationRoomTimelineView: View {
var body: some View { var body: some View {
HStack(spacing: 12) { HStack(spacing: 12) {
LoadableAvatarImage(url: timelineItem.sender.avatarURL, CompoundIcon(iconKeyPath, size: .medium, relativeTo: .compound.headingMDBold)
name: timelineItem.sender.displayName ?? timelineItem.sender.id, .foregroundStyle(.compound.iconSecondary)
contentID: timelineItem.sender.id,
avatarSize: .user(on: .timeline),
mediaProvider: context?.mediaProvider)
.accessibilityHidden(true) .accessibilityHidden(true)
VStack(alignment: .leading, spacing: 0) { Text(tileTitle)
Text(timelineItem.sender.disambiguatedDisplayName ?? timelineItem.sender.id) .font(.compound.bodyMD)
.font(.compound.bodyLGSemibold) .foregroundColor(.compound.textSecondary)
.foregroundColor(.compound.textPrimary) .labelStyle(.custom(spacing: 4))
.lineLimit(1)
.frame(maxWidth: .infinity, alignment: .leading)
Label(title: { Text(L10n.commonCallStarted) },
icon: { CompoundIcon(\.videoCallSolid, size: .medium, relativeTo: .compound.bodyMD) })
.font(.compound.bodyMD)
.foregroundColor(.compound.textSecondary)
.labelStyle(.custom(spacing: 4))
}
Spacer() Spacer()
Text(timelineItem.timestamp.formattedTime()) Text(timelineItem.timestamp.formattedTime())
.font(.compound.bodyXS) .font(.compound.bodyXS)
.foregroundColor(.compound.textSecondary) .foregroundColor(.compound.textSecondary)
@@ -49,6 +37,32 @@ struct CallNotificationRoomTimelineView: View {
.stroke(.compound.borderInteractiveSecondary, lineWidth: 1)) .stroke(.compound.borderInteractiveSecondary, lineWidth: 1))
.padding(16) .padding(16)
} }
// MARK: - Private
private var tileTitle: String {
if timelineItem.isDM {
// As per design only have declined variants in DM
if timelineItem.isDeclinedByMe {
L10n.commonCallYouDeclined
} else if timelineItem.isDeclined {
L10n.commonCallDeclined
} else {
L10n.commonCallStarted
}
} else {
L10n.commonCallStarted
}
}
private var iconKeyPath: KeyPath<CompoundIcons, Image> {
if timelineItem.isDM, timelineItem.isDeclined || timelineItem.isDeclinedByMe {
// As per design only have declined variants in DM
timelineItem.isVoiceCall ? \.voiceCallDeclinedSolid : \.videoCallDeclinedSolid
} else {
timelineItem.isVoiceCall ? \.voiceCallSolid : \.videoCallSolid
}
}
} }
struct CallNotificationRoomTimelineView_Previews: PreviewProvider, TestablePreview { struct CallNotificationRoomTimelineView_Previews: PreviewProvider, TestablePreview {
@@ -59,10 +73,84 @@ struct CallNotificationRoomTimelineView_Previews: PreviewProvider, TestablePrevi
} }
static var body: some View { static var body: some View {
CallNotificationRoomTimelineView(timelineItem: .init(id: .randomEvent, VStack(spacing: 0) {
timestamp: .mock, CallNotificationRoomTimelineView(timelineItem: .init(id: .randomEvent,
isEditable: false, timestamp: .mock,
canBeRepliedTo: false, isEditable: false,
sender: .init(id: "Bob"))) canBeRepliedTo: false,
isDM: false,
isDeclinedByMe: false,
isDeclined: false,
isVoiceCall: false))
Divider()
CallNotificationRoomTimelineView(timelineItem: .init(id: .randomEvent,
timestamp: .mock,
isEditable: false,
canBeRepliedTo: false,
isDM: true,
isDeclinedByMe: false,
isDeclined: false,
isVoiceCall: true))
Divider()
CallNotificationRoomTimelineView(timelineItem: .init(id: .randomEvent,
timestamp: .mock,
isEditable: false,
canBeRepliedTo: false,
isDM: false,
isDeclinedByMe: true,
isDeclined: true,
isVoiceCall: false))
Divider()
CallNotificationRoomTimelineView(timelineItem: .init(id: .randomEvent,
timestamp: .mock,
isEditable: false,
canBeRepliedTo: false,
isDM: true,
isDeclinedByMe: false,
isDeclined: true,
isVoiceCall: true))
Divider()
CallNotificationRoomTimelineView(timelineItem: .init(id: .randomEvent,
timestamp: .mock,
isEditable: false,
canBeRepliedTo: false,
isDM: true,
isDeclinedByMe: true,
isDeclined: true,
isVoiceCall: true))
Divider()
CallNotificationRoomTimelineView(timelineItem: .init(id: .randomEvent,
timestamp: .mock,
isEditable: false,
canBeRepliedTo: false,
isDM: true,
isDeclinedByMe: false,
isDeclined: true,
isVoiceCall: false))
Divider()
CallNotificationRoomTimelineView(timelineItem: .init(id: .randomEvent,
timestamp: .mock,
isEditable: false,
canBeRepliedTo: false,
isDM: true,
isDeclinedByMe: true,
isDeclined: true,
isVoiceCall: false))
Divider()
}
.padding()
} }
} }
@@ -14,7 +14,10 @@ struct CallNotificationRoomTimelineItem: RoomTimelineItemProtocol, Equatable {
let isEditable: Bool let isEditable: Bool
let canBeRepliedTo: Bool let canBeRepliedTo: Bool
let sender: TimelineItemSender let isDM: Bool
let isDeclinedByMe: Bool
let isDeclined: Bool
let isVoiceCall: Bool
var properties = RoomTimelineItemProperties() var properties = RoomTimelineItemProperties()
} }
@@ -69,8 +69,8 @@ struct RoomTimelineItemFactory: RoomTimelineItemFactoryProtocol {
isOutgoing: isOutgoing) isOutgoing: isOutgoing)
case .callInvite: case .callInvite:
return buildCallInviteTimelineItem(for: eventItemProxy) return buildCallInviteTimelineItem(for: eventItemProxy)
case .rtcNotification: case .rtcNotification(let callIntent, let declinedBy):
return buildCallNotificationTimelineItem(for: eventItemProxy) return buildCallNotificationTimelineItem(for: eventItemProxy, isDM: isDM, callIntent: callIntent, declinedBy: declinedBy)
} }
} }
@@ -771,12 +771,20 @@ struct RoomTimelineItemFactory: RoomTimelineItemFactoryProtocol {
sender: eventItemProxy.sender) sender: eventItemProxy.sender)
} }
private func buildCallNotificationTimelineItem(for eventItemProxy: EventTimelineItemProxy) -> RoomTimelineItemProtocol { private func buildCallNotificationTimelineItem(for eventItemProxy: EventTimelineItemProxy,
CallNotificationRoomTimelineItem(id: eventItemProxy.id, isDM: Bool,
timestamp: eventItemProxy.timestamp, callIntent: String?,
isEditable: eventItemProxy.isEditable, declinedBy: [String]) -> RoomTimelineItemProtocol {
canBeRepliedTo: eventItemProxy.canBeRepliedTo, let isVoiceCall = callIntent == CallIntent.audio.rawValue
sender: eventItemProxy.sender) return CallNotificationRoomTimelineItem(id: eventItemProxy.id,
timestamp: eventItemProxy.timestamp,
isEditable: eventItemProxy.isEditable,
canBeRepliedTo: eventItemProxy.canBeRepliedTo,
isDM: isDM,
isDeclinedByMe: declinedBy.contains(userID),
isDeclined: declinedBy.count > 0,
isVoiceCall: isVoiceCall,
properties: .init())
} }
// MARK: - State Events // MARK: - State Events
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1 version https://git-lfs.github.com/spec/v1
oid sha256:4fac458013500f28d81035b7f8150e6cc133c6ccd5c1dc1998b0c42b4a1331f1 oid sha256:4a70f54c1df8d1f12aa63cf03e270234a776954f5351934fd5e22896b9bd905a
size 76774 size 114986
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1 version https://git-lfs.github.com/spec/v1
oid sha256:f549d37e6e8ca7186715c1859228be842939004a47ef526a92f214018037d6d8 oid sha256:9504ac059c7eb268c5468e149248215284ca94bf7b883dec3e5b0c7bf58d7bb9
size 78926 size 130073
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1 version https://git-lfs.github.com/spec/v1
oid sha256:2f559b565c88eaac764235d5693544be8b8f78d7ccb7756c67af4194a06a72c9 oid sha256:c7cc09b9d56ca39c77feb4742b55660e04065b6de3f2766627faf3ade3a660a7
size 35607 size 68436
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1 version https://git-lfs.github.com/spec/v1
oid sha256:31cc0e8dc492b3aaf99612fe4d210921072631305e4b318ff3ea54b24faf25ca oid sha256:4847367fbc95bc1cf52a0c0c6dd137e28ceb6cfc8f2865eb53113540a2f12cd5
size 37809 size 87310
@@ -148,6 +148,13 @@ final class ElementCallServiceTests {
await testClock.advance(by: .seconds(100)) await testClock.advance(by: .seconds(100))
} }
} }
@Test
func callIntentRawValues() {
// Test to ensure that the implicit rawValue of the string enum matches the MSC values
#expect(CallIntent.audio.rawValue == "audio")
#expect(CallIntent.video.rawValue == "video")
}
} }
private class PKPushPayloadMock: PKPushPayload { private class PKPushPayloadMock: PKPushPayload {