Various UI test fixes (#370)

* Increase integration tests time limits again as they're still ocasionally failing

* Fixed NavigationRootCoordinator name in logs

* Refactor UI tests hierarchy and introduce new userFlowScreen

* Introduce a RoomTimelineControllerFactory so that it can be mocked in the UserFlow UI tests

* Start using a mock timeline controller for the UserSession flows

* Remove the WeakDictionary dependency and replce it with a plain NSMapTable in the BackgroundTaskService

* Allow multiple UITests screenshots per screen

* Prevent the view hierarchy changing when taking screenshots

* Add UserSessionScreen UI tests

* Fix label triaging workflow project identifier as per vector-im/element-ios/pull/7150

* Fix settings screen tests

* Fix roomPlainNoAvatar and roomEncryptedWithAvatar UI tests

* Fix modal server selection screen UI tests

* Fix bug report and login screen UI tests

* Fix text typing missing characters on UI tests

* Fix sliding sync configuration on integration tests

* Stop crashing if not finding a particular room through the MockClientProxy
This commit is contained in:
Stefan Ceriu
2022-12-15 15:22:39 +02:00
committed by GitHub
parent cfd563786d
commit 5b90f37f2e
66 changed files with 454 additions and 583 deletions
+1 -1
View File
@@ -32,5 +32,5 @@ jobs:
projectid: ${{ env.PROJECT_ID }} projectid: ${{ env.PROJECT_ID }}
contentid: ${{ github.event.issue.node_id }} contentid: ${{ github.event.issue.node_id }}
env: env:
PROJECT_ID: "PN_kwDOAM0swc4ABTXY" PROJECT_ID: "PVT_kwDOAM0swc4ABTXY"
GITHUB_TOKEN: ${{ secrets.ELEMENT_BOT_TOKEN }} GITHUB_TOKEN: ${{ secrets.ELEMENT_BOT_TOKEN }}
+42 -54
View File
@@ -27,6 +27,7 @@
09713669577CDA8D012EE380 /* MatrixRustSDK in Frameworks */ = {isa = PBXBuildFile; productRef = 6647C55D93508C7CE9D954A5 /* MatrixRustSDK */; }; 09713669577CDA8D012EE380 /* MatrixRustSDK in Frameworks */ = {isa = PBXBuildFile; productRef = 6647C55D93508C7CE9D954A5 /* MatrixRustSDK */; };
098CE03C6CC71A31F263FA33 /* ActivityCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = CA9D14D6F914324865C7DB9F /* ActivityCoordinator.swift */; }; 098CE03C6CC71A31F263FA33 /* ActivityCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = CA9D14D6F914324865C7DB9F /* ActivityCoordinator.swift */; };
09AAF04B27732046C755D914 /* SoftLogoutViewModelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 32C5DAA1773F57653BF1C4F9 /* SoftLogoutViewModelTests.swift */; }; 09AAF04B27732046C755D914 /* SoftLogoutViewModelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 32C5DAA1773F57653BF1C4F9 /* SoftLogoutViewModelTests.swift */; };
09C83DDDB07C28364F325209 /* MockRoomTimelineController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 52D7074991B3267B26D89B22 /* MockRoomTimelineController.swift */; };
0AE0AB1952F186EB86719B4F /* HomeScreenRoomCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED044D00F2176681CC02CD54 /* HomeScreenRoomCell.swift */; }; 0AE0AB1952F186EB86719B4F /* HomeScreenRoomCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED044D00F2176681CC02CD54 /* HomeScreenRoomCell.swift */; };
0B1F80C2BF7D223159FBA82C /* ImageAnonymizerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6045E825AE900A92D61FEFF0 /* ImageAnonymizerTests.swift */; }; 0B1F80C2BF7D223159FBA82C /* ImageAnonymizerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6045E825AE900A92D61FEFF0 /* ImageAnonymizerTests.swift */; };
0BEFE400B4802FE8C9DB39B3 /* FilePreviewViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 62BDF0FF4F59AF6EA858B70B /* FilePreviewViewModel.swift */; }; 0BEFE400B4802FE8C9DB39B3 /* FilePreviewViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 62BDF0FF4F59AF6EA858B70B /* FilePreviewViewModel.swift */; };
@@ -48,6 +49,7 @@
152AE2B8650FB23AFD2E28B9 /* MockAuthenticationServiceProxy.swift in Sources */ = {isa = PBXBuildFile; fileRef = 65C2B80DD0BF6F10BB5FA922 /* MockAuthenticationServiceProxy.swift */; }; 152AE2B8650FB23AFD2E28B9 /* MockAuthenticationServiceProxy.swift in Sources */ = {isa = PBXBuildFile; fileRef = 65C2B80DD0BF6F10BB5FA922 /* MockAuthenticationServiceProxy.swift */; };
1555A7643D85187D4851040C /* TemplateScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4549FCB53F43DB0B278374BC /* TemplateScreen.swift */; }; 1555A7643D85187D4851040C /* TemplateScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4549FCB53F43DB0B278374BC /* TemplateScreen.swift */; };
157E5FDDF419C0B2CA7E2C28 /* TimelineItemBubbledStylerView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 98A2932515EA11D3DD8A3506 /* TimelineItemBubbledStylerView.swift */; }; 157E5FDDF419C0B2CA7E2C28 /* TimelineItemBubbledStylerView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 98A2932515EA11D3DD8A3506 /* TimelineItemBubbledStylerView.swift */; };
158A2D528CC78C4E7A8ED608 /* MockRoomTimelineControllerFactory.swift in Sources */ = {isa = PBXBuildFile; fileRef = 71556206CD5E8B1F53F07178 /* MockRoomTimelineControllerFactory.swift */; };
15D867E638BFD0E5E71DB1EF /* List.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2AFEF3AC64B1358083F76B8B /* List.swift */; }; 15D867E638BFD0E5E71DB1EF /* List.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2AFEF3AC64B1358083F76B8B /* List.swift */; };
165A883C29998EC779465068 /* SoftLogoutViewModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6BC38904A9663F7FAFD47457 /* SoftLogoutViewModelProtocol.swift */; }; 165A883C29998EC779465068 /* SoftLogoutViewModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6BC38904A9663F7FAFD47457 /* SoftLogoutViewModelProtocol.swift */; };
1702981A8085BE4FB0EC001B /* Application.swift in Sources */ = {isa = PBXBuildFile; fileRef = D33116993D54FADC0C721C1F /* Application.swift */; }; 1702981A8085BE4FB0EC001B /* Application.swift in Sources */ = {isa = PBXBuildFile; fileRef = D33116993D54FADC0C721C1F /* Application.swift */; };
@@ -86,6 +88,7 @@
297CD0A27C87B0C50FF192EE /* RoomTimelineViewFactoryProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = EEE384418EB1FEDFA62C9CD0 /* RoomTimelineViewFactoryProtocol.swift */; }; 297CD0A27C87B0C50FF192EE /* RoomTimelineViewFactoryProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = EEE384418EB1FEDFA62C9CD0 /* RoomTimelineViewFactoryProtocol.swift */; };
29E20505F321071E8375F99B /* BuildSettings.swift in Sources */ = {isa = PBXBuildFile; fileRef = 263B3B811C2B900F12C6F695 /* BuildSettings.swift */; }; 29E20505F321071E8375F99B /* BuildSettings.swift in Sources */ = {isa = PBXBuildFile; fileRef = 263B3B811C2B900F12C6F695 /* BuildSettings.swift */; };
29EE1791E0AFA1ABB7F23D2F /* SwiftyBeaver in Frameworks */ = {isa = PBXBuildFile; productRef = A981A4CA233FB5C13B9CA690 /* SwiftyBeaver */; }; 29EE1791E0AFA1ABB7F23D2F /* SwiftyBeaver in Frameworks */ = {isa = PBXBuildFile; productRef = A981A4CA233FB5C13B9CA690 /* SwiftyBeaver */; };
2ABF11717C64054CEF2819A3 /* RoomTimelineController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9F85164F9475FF2867F71AAA /* RoomTimelineController.swift */; };
2B9AEEC12B1BBE5BD61D0F5E /* UserSessionFlowCoordinatorStateMachine.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3429142FE11930422E7CC1A0 /* UserSessionFlowCoordinatorStateMachine.swift */; }; 2B9AEEC12B1BBE5BD61D0F5E /* UserSessionFlowCoordinatorStateMachine.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3429142FE11930422E7CC1A0 /* UserSessionFlowCoordinatorStateMachine.swift */; };
2BA59D0AEFB4B82A2EC2A326 /* KeychainAccess in Frameworks */ = {isa = PBXBuildFile; productRef = 78A5A8DE1E2B09C978C7F3B0 /* KeychainAccess */; }; 2BA59D0AEFB4B82A2EC2A326 /* KeychainAccess in Frameworks */ = {isa = PBXBuildFile; productRef = 78A5A8DE1E2B09C978C7F3B0 /* KeychainAccess */; };
2BAA5B222856068158D0B3C6 /* MatrixRustSDK in Frameworks */ = {isa = PBXBuildFile; productRef = B1E8B697DF78FE7F61FC6CA4 /* MatrixRustSDK */; }; 2BAA5B222856068158D0B3C6 /* MatrixRustSDK in Frameworks */ = {isa = PBXBuildFile; productRef = B1E8B697DF78FE7F61FC6CA4 /* MatrixRustSDK */; };
@@ -101,7 +104,6 @@
3097A0A867D2B19CE32DAE58 /* UIKitBackgroundTaskService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3DF1FFC3336EB23374BBBFCC /* UIKitBackgroundTaskService.swift */; }; 3097A0A867D2B19CE32DAE58 /* UIKitBackgroundTaskService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3DF1FFC3336EB23374BBBFCC /* UIKitBackgroundTaskService.swift */; };
323F36D880363C473B81A9EA /* MediaProxyProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = FC3D31C2DA6910AA0079678A /* MediaProxyProtocol.swift */; }; 323F36D880363C473B81A9EA /* MediaProxyProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = FC3D31C2DA6910AA0079678A /* MediaProxyProtocol.swift */; };
3274219F7F26A5C6C2C55630 /* FilePreviewViewModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = C3F652E88106B855A2A55ADE /* FilePreviewViewModelProtocol.swift */; }; 3274219F7F26A5C6C2C55630 /* FilePreviewViewModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = C3F652E88106B855A2A55ADE /* FilePreviewViewModelProtocol.swift */; };
32BA37B01B05261FCF2D4B45 /* WeakDictionaryKeyReference.swift in Sources */ = {isa = PBXBuildFile; fileRef = 090CA61A835C151CEDF8F372 /* WeakDictionaryKeyReference.swift */; };
33CAC1226DFB8B5D8447D286 /* SwiftState in Frameworks */ = {isa = PBXBuildFile; productRef = 3853B78FB8531B83936C5DA6 /* SwiftState */; }; 33CAC1226DFB8B5D8447D286 /* SwiftState in Frameworks */ = {isa = PBXBuildFile; productRef = 3853B78FB8531B83936C5DA6 /* SwiftState */; };
33D630461FC4562CC767EE9F /* FileCache.swift in Sources */ = {isa = PBXBuildFile; fileRef = A5B0B1226DA8DB55918B34CD /* FileCache.swift */; }; 33D630461FC4562CC767EE9F /* FileCache.swift in Sources */ = {isa = PBXBuildFile; fileRef = A5B0B1226DA8DB55918B34CD /* FileCache.swift */; };
340D39DB87F3800D53A6A621 /* EmojiPickerScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = 00245D40CD90FD71D6A05239 /* EmojiPickerScreen.swift */; }; 340D39DB87F3800D53A6A621 /* EmojiPickerScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = 00245D40CD90FD71D6A05239 /* EmojiPickerScreen.swift */; };
@@ -114,6 +116,7 @@
36AC963F2F04069B7FF1AA0C /* UIConstants.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9E6D88E8AFFBF2C1D589C0FA /* UIConstants.swift */; }; 36AC963F2F04069B7FF1AA0C /* UIConstants.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9E6D88E8AFFBF2C1D589C0FA /* UIConstants.swift */; };
36C10EDEDC0466E3A9D63132 /* VideoRoomTimelineItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = A4B5B19A10D3F7C2BC5315DF /* VideoRoomTimelineItem.swift */; }; 36C10EDEDC0466E3A9D63132 /* VideoRoomTimelineItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = A4B5B19A10D3F7C2BC5315DF /* VideoRoomTimelineItem.swift */; };
38546A6010A2CF240EC9AF73 /* BindableState.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6EA1D2CBAEA5D0BD00B90D1B /* BindableState.swift */; }; 38546A6010A2CF240EC9AF73 /* BindableState.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6EA1D2CBAEA5D0BD00B90D1B /* BindableState.swift */; };
38896D54D6D675534E606195 /* RoomTimelineControllerFactory.swift in Sources */ = {isa = PBXBuildFile; fileRef = E6FCC416A3BFE73DF7B3E6BF /* RoomTimelineControllerFactory.swift */; };
388FD50AC66E9E684DDFA9D8 /* ServerSelectionScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = E5D2C0950F8196232D88045C /* ServerSelectionScreen.swift */; }; 388FD50AC66E9E684DDFA9D8 /* ServerSelectionScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = E5D2C0950F8196232D88045C /* ServerSelectionScreen.swift */; };
38C76D586404C1FDED095F3A /* LoginModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = 31B01468022EC826CB2FD2C0 /* LoginModels.swift */; }; 38C76D586404C1FDED095F3A /* LoginModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = 31B01468022EC826CB2FD2C0 /* LoginModels.swift */; };
3910D3A2EF98587C0E7B9CCB /* EmojiMartEmoji.swift in Sources */ = {isa = PBXBuildFile; fileRef = 11F7F3CF7E70518BD7D25E04 /* EmojiMartEmoji.swift */; }; 3910D3A2EF98587C0E7B9CCB /* EmojiMartEmoji.swift in Sources */ = {isa = PBXBuildFile; fileRef = 11F7F3CF7E70518BD7D25E04 /* EmojiMartEmoji.swift */; };
@@ -136,7 +139,6 @@
440123E29E2F9B001A775BBE /* TimelineItemProxy.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2D505843AB66822EB91F0DF0 /* TimelineItemProxy.swift */; }; 440123E29E2F9B001A775BBE /* TimelineItemProxy.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2D505843AB66822EB91F0DF0 /* TimelineItemProxy.swift */; };
447E8580A0A2569E32529E17 /* MockRoomTimelineProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8D6094DEAAEB388E1AE118C6 /* MockRoomTimelineProvider.swift */; }; 447E8580A0A2569E32529E17 /* MockRoomTimelineProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8D6094DEAAEB388E1AE118C6 /* MockRoomTimelineProvider.swift */; };
44AE0752E001D1D10605CD88 /* Swipe.swift in Sources */ = {isa = PBXBuildFile; fileRef = A9FDA5344F7C4C6E4E863E13 /* Swipe.swift */; }; 44AE0752E001D1D10605CD88 /* Swipe.swift in Sources */ = {isa = PBXBuildFile; fileRef = A9FDA5344F7C4C6E4E863E13 /* Swipe.swift */; };
457465EC436703E8C76133A4 /* WeakDictionaryReference.swift in Sources */ = {isa = PBXBuildFile; fileRef = C7955B20E2E6DA68E5BC0AB9 /* WeakDictionaryReference.swift */; };
46562110EE202E580A5FFD9C /* RoomScreenViewModelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 93CF7B19FFCF8EFBE0A8696A /* RoomScreenViewModelTests.swift */; }; 46562110EE202E580A5FFD9C /* RoomScreenViewModelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 93CF7B19FFCF8EFBE0A8696A /* RoomScreenViewModelTests.swift */; };
490E606044B18985055FF690 /* SettingsUITests.swift in Sources */ = {isa = PBXBuildFile; fileRef = E3E29F98CF0E960689A410E3 /* SettingsUITests.swift */; }; 490E606044B18985055FF690 /* SettingsUITests.swift in Sources */ = {isa = PBXBuildFile; fileRef = E3E29F98CF0E960689A410E3 /* SettingsUITests.swift */; };
492274DA6691EE985C2FCCAA /* GZIP in Frameworks */ = {isa = PBXBuildFile; productRef = 1BCD21310B997A6837B854D6 /* GZIP */; }; 492274DA6691EE985C2FCCAA /* GZIP in Frameworks */ = {isa = PBXBuildFile; productRef = 1BCD21310B997A6837B854D6 /* GZIP */; };
@@ -161,6 +163,7 @@
54C774874BED4A8FAD1F22FE /* AnalyticsConfiguration.swift in Sources */ = {isa = PBXBuildFile; fileRef = D77B3D4950F1707E66E4A45A /* AnalyticsConfiguration.swift */; }; 54C774874BED4A8FAD1F22FE /* AnalyticsConfiguration.swift in Sources */ = {isa = PBXBuildFile; fileRef = D77B3D4950F1707E66E4A45A /* AnalyticsConfiguration.swift */; };
563A05B43207D00A6B698211 /* OIDCService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9010EE0CC913D095887EF36E /* OIDCService.swift */; }; 563A05B43207D00A6B698211 /* OIDCService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9010EE0CC913D095887EF36E /* OIDCService.swift */; };
56F0A22972A3BB519DA2261C /* HomeScreenViewModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 24F5530B2212862FA4BEFF2D /* HomeScreenViewModelProtocol.swift */; }; 56F0A22972A3BB519DA2261C /* HomeScreenViewModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 24F5530B2212862FA4BEFF2D /* HomeScreenViewModelProtocol.swift */; };
588411C8FD72B2A2DFE5F7DE /* XCUIElement.swift in Sources */ = {isa = PBXBuildFile; fileRef = E992D7B8BE54B2AB454613AF /* XCUIElement.swift */; };
59F940FCBE6BC343AECEF75E /* ImageCache.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4E2245243369B99216C7D84E /* ImageCache.swift */; }; 59F940FCBE6BC343AECEF75E /* ImageCache.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4E2245243369B99216C7D84E /* ImageCache.swift */; };
5B8B51CEC4717AF487794685 /* NotificationServiceProxy.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0B490675B8E31423AF116BDA /* NotificationServiceProxy.swift */; }; 5B8B51CEC4717AF487794685 /* NotificationServiceProxy.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0B490675B8E31423AF116BDA /* NotificationServiceProxy.swift */; };
5C02841B2A86327B2C377682 /* NotificationConstants.swift in Sources */ = {isa = PBXBuildFile; fileRef = C830A64609CBD152F06E0457 /* NotificationConstants.swift */; }; 5C02841B2A86327B2C377682 /* NotificationConstants.swift in Sources */ = {isa = PBXBuildFile; fileRef = C830A64609CBD152F06E0457 /* NotificationConstants.swift */; };
@@ -192,7 +195,6 @@
67E391A2E00709FB41903B36 /* MockMediaProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6920A4869821BF72FFC58842 /* MockMediaProvider.swift */; }; 67E391A2E00709FB41903B36 /* MockMediaProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6920A4869821BF72FFC58842 /* MockMediaProvider.swift */; };
6832733838C57A7D3FE8FEB5 /* DTCoreText in Frameworks */ = {isa = PBXBuildFile; productRef = 36B7FC232711031AA2B0D188 /* DTCoreText */; }; 6832733838C57A7D3FE8FEB5 /* DTCoreText in Frameworks */ = {isa = PBXBuildFile; productRef = 36B7FC232711031AA2B0D188 /* DTCoreText */; };
68AC3C84E2B438036B174E30 /* EmoteRoomTimelineView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 471EB7D96AFEA8D787659686 /* EmoteRoomTimelineView.swift */; }; 68AC3C84E2B438036B174E30 /* EmoteRoomTimelineView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 471EB7D96AFEA8D787659686 /* EmoteRoomTimelineView.swift */; };
690ED5315B401238A3249DCB /* README.md in Resources */ = {isa = PBXBuildFile; fileRef = 3FDFF4C1153D263BAB93C1F3 /* README.md */; };
69BCBB4FB2DC3D61A28D3FD8 /* TimelineStyle.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8DC2C9E0E15C79BBDA80F0A2 /* TimelineStyle.swift */; }; 69BCBB4FB2DC3D61A28D3FD8 /* TimelineStyle.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8DC2C9E0E15C79BBDA80F0A2 /* TimelineStyle.swift */; };
6A0E7551E0D1793245F34CDD /* ClientError.swift in Sources */ = {isa = PBXBuildFile; fileRef = D09A267106B9585D3D0CFC0D /* ClientError.swift */; }; 6A0E7551E0D1793245F34CDD /* ClientError.swift in Sources */ = {isa = PBXBuildFile; fileRef = D09A267106B9585D3D0CFC0D /* ClientError.swift */; };
6AC1DC1EAD9F7568360DA1BA /* ServerSelectionModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = A30A1758E2B73EF38E7C42F8 /* ServerSelectionModels.swift */; }; 6AC1DC1EAD9F7568360DA1BA /* ServerSelectionModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = A30A1758E2B73EF38E7C42F8 /* ServerSelectionModels.swift */; };
@@ -201,7 +203,6 @@
6C9F6C7F2B35288C4230EF3F /* FilePreviewModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = 55EA4B03F92F31EAA83B3F7B /* FilePreviewModels.swift */; }; 6C9F6C7F2B35288C4230EF3F /* FilePreviewModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = 55EA4B03F92F31EAA83B3F7B /* FilePreviewModels.swift */; };
6CA81428F0970785CDCC5E86 /* UserNotificationToastView.swift in Sources */ = {isa = PBXBuildFile; fileRef = F31A4E5941ACBA4BB9FEF94C /* UserNotificationToastView.swift */; }; 6CA81428F0970785CDCC5E86 /* UserNotificationToastView.swift in Sources */ = {isa = PBXBuildFile; fileRef = F31A4E5941ACBA4BB9FEF94C /* UserNotificationToastView.swift */; };
6D046D653DA28ADF1E6E59A4 /* BackgroundTaskServiceProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = AAE73D571D4F9C36DD45255A /* BackgroundTaskServiceProtocol.swift */; }; 6D046D653DA28ADF1E6E59A4 /* BackgroundTaskServiceProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = AAE73D571D4F9C36DD45255A /* BackgroundTaskServiceProtocol.swift */; };
6DF37000571B1BC6D134CC9E /* WeakDictionary.swift in Sources */ = {isa = PBXBuildFile; fileRef = 304FFD608DB6E612075AB1B4 /* WeakDictionary.swift */; };
6E6E0AAF6C44C0B117EBBE5A /* SlidingSyncViewProxy.swift in Sources */ = {isa = PBXBuildFile; fileRef = 41F3B445BD6EF1C751806B22 /* SlidingSyncViewProxy.swift */; }; 6E6E0AAF6C44C0B117EBBE5A /* SlidingSyncViewProxy.swift in Sources */ = {isa = PBXBuildFile; fileRef = 41F3B445BD6EF1C751806B22 /* SlidingSyncViewProxy.swift */; };
6EA61FCA55D950BDE326A1A7 /* ImageAnonymizer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 12A626D74BBE9F4A60763B45 /* ImageAnonymizer.swift */; }; 6EA61FCA55D950BDE326A1A7 /* ImageAnonymizer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 12A626D74BBE9F4A60763B45 /* ImageAnonymizer.swift */; };
6F2AB43A1EFAD8A97AF41A15 /* DeviceKit in Frameworks */ = {isa = PBXBuildFile; productRef = A7CA6F33C553805035C3B114 /* DeviceKit */; }; 6F2AB43A1EFAD8A97AF41A15 /* DeviceKit in Frameworks */ = {isa = PBXBuildFile; productRef = A7CA6F33C553805035C3B114 /* DeviceKit */; };
@@ -226,7 +227,6 @@
7756C4E90CABE6F14F7920A0 /* BugReportUITests.swift in Sources */ = {isa = PBXBuildFile; fileRef = C6FEA87EA3752203065ECE27 /* BugReportUITests.swift */; }; 7756C4E90CABE6F14F7920A0 /* BugReportUITests.swift in Sources */ = {isa = PBXBuildFile; fileRef = C6FEA87EA3752203065ECE27 /* BugReportUITests.swift */; };
77D7DAA41AAB36800C1F2E2D /* RoomTimelineProviderProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 095AED4CF56DFF3EB7BB84C8 /* RoomTimelineProviderProtocol.swift */; }; 77D7DAA41AAB36800C1F2E2D /* RoomTimelineProviderProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 095AED4CF56DFF3EB7BB84C8 /* RoomTimelineProviderProtocol.swift */; };
77FACC29F98FE2E65BBB6A5F /* ServerSelectionUITests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 054F469E433864CC6FE6EE8E /* ServerSelectionUITests.swift */; }; 77FACC29F98FE2E65BBB6A5F /* ServerSelectionUITests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 054F469E433864CC6FE6EE8E /* ServerSelectionUITests.swift */; };
78B71D53C1FC55FB7A9B75F0 /* RoomTimelineController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 24B0C97D2F560BCB72BE73B1 /* RoomTimelineController.swift */; };
78BF60C696FFED63AAF58D10 /* SoftLogoutViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 22D46DB0CC6C55EBA7AE67A3 /* SoftLogoutViewModel.swift */; }; 78BF60C696FFED63AAF58D10 /* SoftLogoutViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 22D46DB0CC6C55EBA7AE67A3 /* SoftLogoutViewModel.swift */; };
7963F98CDFDEAC75E072BD81 /* TextRoomTimelineItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = F6A8C632CEF4600107792899 /* TextRoomTimelineItem.swift */; }; 7963F98CDFDEAC75E072BD81 /* TextRoomTimelineItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = F6A8C632CEF4600107792899 /* TextRoomTimelineItem.swift */; };
7A71AEF419904209BB8C2833 /* UserAgentBuilder.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F2529D434C750ED78ADF1ED /* UserAgentBuilder.swift */; }; 7A71AEF419904209BB8C2833 /* UserAgentBuilder.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F2529D434C750ED78ADF1ED /* UserAgentBuilder.swift */; };
@@ -238,6 +238,7 @@
7E3C34BC10936AD4F77975F4 /* EmojiMartJSONLoader.swift in Sources */ = {isa = PBXBuildFile; fileRef = 39001365B76B89983FDB7AD8 /* EmojiMartJSONLoader.swift */; }; 7E3C34BC10936AD4F77975F4 /* EmojiMartJSONLoader.swift in Sources */ = {isa = PBXBuildFile; fileRef = 39001365B76B89983FDB7AD8 /* EmojiMartJSONLoader.swift */; };
7E7DF1867F98B0D10A6C0A63 /* FileCacheTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = F3648F2FADEF2672D6A0D489 /* FileCacheTests.swift */; }; 7E7DF1867F98B0D10A6C0A63 /* FileCacheTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = F3648F2FADEF2672D6A0D489 /* FileCacheTests.swift */; };
7E91BAC17963ED41208F489B /* UserSessionStore.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E8BDC092D817B68CD9040C5 /* UserSessionStore.swift */; }; 7E91BAC17963ED41208F489B /* UserSessionStore.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E8BDC092D817B68CD9040C5 /* UserSessionStore.swift */; };
7ECF12D5DCD69F67BD3E3842 /* RoomTimelineControllerFactoryProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 18FE0CDF1FFA92EA7EE17B0B /* RoomTimelineControllerFactoryProtocol.swift */; };
7F08F4BC1312075E2B5EAEFA /* AuthenticationServiceProxy.swift in Sources */ = {isa = PBXBuildFile; fileRef = CF48AF076424DBC1615C74AD /* AuthenticationServiceProxy.swift */; }; 7F08F4BC1312075E2B5EAEFA /* AuthenticationServiceProxy.swift in Sources */ = {isa = PBXBuildFile; fileRef = CF48AF076424DBC1615C74AD /* AuthenticationServiceProxy.swift */; };
7F61F9ACD5EC9E845EF3EFBF /* BugReportServiceTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = EFFD3200F9960D4996159F10 /* BugReportServiceTests.swift */; }; 7F61F9ACD5EC9E845EF3EFBF /* BugReportServiceTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = EFFD3200F9960D4996159F10 /* BugReportServiceTests.swift */; };
7F64FA937B95924B3A44EC12 /* OnboardingScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = AB8E75B9CB6C78BE8D09B1AF /* OnboardingScreen.swift */; }; 7F64FA937B95924B3A44EC12 /* OnboardingScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = AB8E75B9CB6C78BE8D09B1AF /* OnboardingScreen.swift */; };
@@ -246,7 +247,6 @@
80D00A7C62AAB44F54725C43 /* PermalinkBuilder.swift in Sources */ = {isa = PBXBuildFile; fileRef = F754E66A8970963B15B2A41E /* PermalinkBuilder.swift */; }; 80D00A7C62AAB44F54725C43 /* PermalinkBuilder.swift in Sources */ = {isa = PBXBuildFile; fileRef = F754E66A8970963B15B2A41E /* PermalinkBuilder.swift */; };
8196A2E71ACC902DD69F24EE /* UserNotificationControllerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0DE6C5C756E1393202BA95CD /* UserNotificationControllerTests.swift */; }; 8196A2E71ACC902DD69F24EE /* UserNotificationControllerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0DE6C5C756E1393202BA95CD /* UserNotificationControllerTests.swift */; };
83E5054739949181CA981193 /* LoginCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD667C4BB98CF4F3FE2CE3B0 /* LoginCoordinator.swift */; }; 83E5054739949181CA981193 /* LoginCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD667C4BB98CF4F3FE2CE3B0 /* LoginCoordinator.swift */; };
841172E1576A863F4450132D /* WeakKeyDictionary.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0ADFDC712027931F2216668 /* WeakKeyDictionary.swift */; };
85AFBB433AD56704A880F8A0 /* FramePreferenceKey.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4798B3B7A1E8AE3901CEE8C6 /* FramePreferenceKey.swift */; }; 85AFBB433AD56704A880F8A0 /* FramePreferenceKey.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4798B3B7A1E8AE3901CEE8C6 /* FramePreferenceKey.swift */; };
86675910612A12409262DFBD /* SessionVerificationStateMachineTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = A1C22B1B5FA3A765EADB2CC9 /* SessionVerificationStateMachineTests.swift */; }; 86675910612A12409262DFBD /* SessionVerificationStateMachineTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = A1C22B1B5FA3A765EADB2CC9 /* SessionVerificationStateMachineTests.swift */; };
8691186F9B99BCDDB7CACDD8 /* KeychainController.swift in Sources */ = {isa = PBXBuildFile; fileRef = E36CB905A2B9EC2C92A2DA7C /* KeychainController.swift */; }; 8691186F9B99BCDDB7CACDD8 /* KeychainController.swift in Sources */ = {isa = PBXBuildFile; fileRef = E36CB905A2B9EC2C92A2DA7C /* KeychainController.swift */; };
@@ -290,7 +290,6 @@
9A47B7EFE3793760EEF68FFE /* UITestScreenIdentifier.swift in Sources */ = {isa = PBXBuildFile; fileRef = CC6FE34A0A47D010BBB4D4D4 /* UITestScreenIdentifier.swift */; }; 9A47B7EFE3793760EEF68FFE /* UITestScreenIdentifier.swift in Sources */ = {isa = PBXBuildFile; fileRef = CC6FE34A0A47D010BBB4D4D4 /* UITestScreenIdentifier.swift */; };
9AC5F8142413862A9E3A2D98 /* KeychainAccess in Frameworks */ = {isa = PBXBuildFile; productRef = 020597E28A4BC8E1BE8EDF6E /* KeychainAccess */; }; 9AC5F8142413862A9E3A2D98 /* KeychainAccess in Frameworks */ = {isa = PBXBuildFile; productRef = 020597E28A4BC8E1BE8EDF6E /* KeychainAccess */; };
9B582B3EEFEA615D4A6FBF1A /* TimelineReactionsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 351E89CE2ED9B73C5CC47955 /* TimelineReactionsView.swift */; }; 9B582B3EEFEA615D4A6FBF1A /* TimelineReactionsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 351E89CE2ED9B73C5CC47955 /* TimelineReactionsView.swift */; };
9B8DE1D424E37581C7D99CCC /* RoomTimelineControllerProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = CC7CCC6DE5FA623E31BA8546 /* RoomTimelineControllerProtocol.swift */; };
9BD3A773186291560DF92B62 /* RoomTimelineProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 66F2402D738694F98729A441 /* RoomTimelineProvider.swift */; }; 9BD3A773186291560DF92B62 /* RoomTimelineProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 66F2402D738694F98729A441 /* RoomTimelineProvider.swift */; };
9BE7A9CF6C593251D734B461 /* MockServerSelectionScreenState.swift in Sources */ = {isa = PBXBuildFile; fileRef = A0A20AE75FF4FF35B1FF6CA7 /* MockServerSelectionScreenState.swift */; }; 9BE7A9CF6C593251D734B461 /* MockServerSelectionScreenState.swift in Sources */ = {isa = PBXBuildFile; fileRef = A0A20AE75FF4FF35B1FF6CA7 /* MockServerSelectionScreenState.swift */; };
9C45CE85325CD591DADBC4CA /* ElementXTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = DBFEAC3AC691CBB84983E275 /* ElementXTests.swift */; }; 9C45CE85325CD591DADBC4CA /* ElementXTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = DBFEAC3AC691CBB84983E275 /* ElementXTests.swift */; };
@@ -324,7 +323,6 @@
AA050DF4AEE54A641BA7CA22 /* RoomSummaryProviderProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 10CC626F97AD70FF0420C115 /* RoomSummaryProviderProtocol.swift */; }; AA050DF4AEE54A641BA7CA22 /* RoomSummaryProviderProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 10CC626F97AD70FF0420C115 /* RoomSummaryProviderProtocol.swift */; };
AAF0BBED840DF4A53EE85E77 /* MatrixRustSDK in Frameworks */ = {isa = PBXBuildFile; productRef = C2C69B8BA5A9702E7A8BC08F /* MatrixRustSDK */; }; AAF0BBED840DF4A53EE85E77 /* MatrixRustSDK in Frameworks */ = {isa = PBXBuildFile; productRef = C2C69B8BA5A9702E7A8BC08F /* MatrixRustSDK */; };
AB34401E4E1CAD5D2EC3072B /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 9760103CF316DF68698BCFE6 /* LaunchScreen.storyboard */; }; AB34401E4E1CAD5D2EC3072B /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 9760103CF316DF68698BCFE6 /* LaunchScreen.storyboard */; };
AB4C5D62A21AD712811CE8CD /* XCUIElement.swift in Sources */ = {isa = PBXBuildFile; fileRef = 68232D336E2B546AD95B78B5 /* XCUIElement.swift */; };
ABF3FAB234AD3565B214309B /* TimelineSenderAvatarView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0BC588051E6572A1AF51D738 /* TimelineSenderAvatarView.swift */; }; ABF3FAB234AD3565B214309B /* TimelineSenderAvatarView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0BC588051E6572A1AF51D738 /* TimelineSenderAvatarView.swift */; };
AC5CC8250CEAE57B73900C57 /* UserNotificationModalView.swift in Sources */ = {isa = PBXBuildFile; fileRef = CD80F22830C2360F3F39DDCE /* UserNotificationModalView.swift */; }; AC5CC8250CEAE57B73900C57 /* UserNotificationModalView.swift in Sources */ = {isa = PBXBuildFile; fileRef = CD80F22830C2360F3F39DDCE /* UserNotificationModalView.swift */; };
AC69B6DF15FC451AB2945036 /* UserSessionStoreProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = BEBA759D1347CFFB3D84ED1F /* UserSessionStoreProtocol.swift */; }; AC69B6DF15FC451AB2945036 /* UserSessionStoreProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = BEBA759D1347CFFB3D84ED1F /* UserSessionStoreProtocol.swift */; };
@@ -335,9 +333,11 @@
B064D42BA087649ACAE462E8 /* SoftLogoutUITests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 55F30E764BED111C81739844 /* SoftLogoutUITests.swift */; }; B064D42BA087649ACAE462E8 /* SoftLogoutUITests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 55F30E764BED111C81739844 /* SoftLogoutUITests.swift */; };
B09514A0A3EB3C19A4FD0B71 /* SoftLogoutScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2CCBDE671A613B3EB70794C4 /* SoftLogoutScreen.swift */; }; B09514A0A3EB3C19A4FD0B71 /* SoftLogoutScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2CCBDE671A613B3EB70794C4 /* SoftLogoutScreen.swift */; };
B14BC354E56616B6B7D9A3D7 /* NotificationServiceExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 27A1AD6389A4659AF0CEAE62 /* NotificationServiceExtension.swift */; }; B14BC354E56616B6B7D9A3D7 /* NotificationServiceExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 27A1AD6389A4659AF0CEAE62 /* NotificationServiceExtension.swift */; };
B22D857D1E8FCA6DD74A58E3 /* UserSessionScreenTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = F899D02CF26EA7675EEBE74C /* UserSessionScreenTests.swift */; };
B245583C63F8F90357B87FAE /* Kingfisher in Frameworks */ = {isa = PBXBuildFile; productRef = 50009897F60FAE7D63EF5E5B /* Kingfisher */; }; B245583C63F8F90357B87FAE /* Kingfisher in Frameworks */ = {isa = PBXBuildFile; productRef = 50009897F60FAE7D63EF5E5B /* Kingfisher */; };
B2F8E01ABA1BA30265B4ECBE /* RoundedCornerShape.swift in Sources */ = {isa = PBXBuildFile; fileRef = 839E2C35DF3F9C7B54C3CE49 /* RoundedCornerShape.swift */; }; B2F8E01ABA1BA30265B4ECBE /* RoundedCornerShape.swift in Sources */ = {isa = PBXBuildFile; fileRef = 839E2C35DF3F9C7B54C3CE49 /* RoundedCornerShape.swift */; };
B3357B00F1AA930E54F76609 /* Strings.swift in Sources */ = {isa = PBXBuildFile; fileRef = 47EBB5D698CE9A25BB553A2D /* Strings.swift */; }; B3357B00F1AA930E54F76609 /* Strings.swift in Sources */ = {isa = PBXBuildFile; fileRef = 47EBB5D698CE9A25BB553A2D /* Strings.swift */; };
B444F9C184A377C1B481F07F /* XCUIElement.swift in Sources */ = {isa = PBXBuildFile; fileRef = E992D7B8BE54B2AB454613AF /* XCUIElement.swift */; };
B4AAB3257A83B73F53FB2689 /* StateStoreViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6F3DFE5B444F131648066F05 /* StateStoreViewModel.swift */; }; B4AAB3257A83B73F53FB2689 /* StateStoreViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6F3DFE5B444F131648066F05 /* StateStoreViewModel.swift */; };
B5111BAF5F601C139EBBD8BB /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 01C4C7DB37597D7D8379511A /* Assets.xcassets */; }; B5111BAF5F601C139EBBD8BB /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 01C4C7DB37597D7D8379511A /* Assets.xcassets */; };
B5903E48CF43259836BF2DBF /* EncryptedRoomTimelineView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 56C1BCB9E83B09A45387FCA2 /* EncryptedRoomTimelineView.swift */; }; B5903E48CF43259836BF2DBF /* EncryptedRoomTimelineView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 56C1BCB9E83B09A45387FCA2 /* EncryptedRoomTimelineView.swift */; };
@@ -413,7 +413,7 @@
E481C8FDCB6C089963C95344 /* DeviceKit in Frameworks */ = {isa = PBXBuildFile; productRef = BC01130651CB23340B899032 /* DeviceKit */; }; E481C8FDCB6C089963C95344 /* DeviceKit in Frameworks */ = {isa = PBXBuildFile; productRef = BC01130651CB23340B899032 /* DeviceKit */; };
E5895C74615CBE8462FB840F /* SessionVerificationCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = CCF86010A0A719A9A50EEC59 /* SessionVerificationCoordinator.swift */; }; E5895C74615CBE8462FB840F /* SessionVerificationCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = CCF86010A0A719A9A50EEC59 /* SessionVerificationCoordinator.swift */; };
E67418DACEDBC29E988E6ACD /* message.caf in Resources */ = {isa = PBXBuildFile; fileRef = ED482057AE39D5C6D9C5F3D8 /* message.caf */; }; E67418DACEDBC29E988E6ACD /* message.caf in Resources */ = {isa = PBXBuildFile; fileRef = ED482057AE39D5C6D9C5F3D8 /* message.caf */; };
E81EEC1675F2371D12A880A3 /* MockRoomTimelineController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 61ADFB893DEF81E58DF3FAB9 /* MockRoomTimelineController.swift */; }; E89536FC8C0E4B79E9842A78 /* RoomTimelineControllerProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2C0197EAE9D45A662B8847B6 /* RoomTimelineControllerProtocol.swift */; };
E8AB8D16E6D8E8E501F29BD9 /* FileCache.swift in Sources */ = {isa = PBXBuildFile; fileRef = A5B0B1226DA8DB55918B34CD /* FileCache.swift */; }; E8AB8D16E6D8E8E501F29BD9 /* FileCache.swift in Sources */ = {isa = PBXBuildFile; fileRef = A5B0B1226DA8DB55918B34CD /* FileCache.swift */; };
E96005321849DBD7C72A28F2 /* UITestsAppCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 46C208DA43CE25D13E670F40 /* UITestsAppCoordinator.swift */; }; E96005321849DBD7C72A28F2 /* UITestsAppCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 46C208DA43CE25D13E670F40 /* UITestsAppCoordinator.swift */; };
EA1E7949533E19C6D862680A /* MediaProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 885D8C42DD17625B5261BEFF /* MediaProvider.swift */; }; EA1E7949533E19C6D862680A /* MediaProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 885D8C42DD17625B5261BEFF /* MediaProvider.swift */; };
@@ -512,7 +512,6 @@
077D7C3BE199B6E5DDEC07EC /* AppCoordinatorStateMachine.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppCoordinatorStateMachine.swift; sourceTree = "<group>"; }; 077D7C3BE199B6E5DDEC07EC /* AppCoordinatorStateMachine.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppCoordinatorStateMachine.swift; sourceTree = "<group>"; };
086B997409328F091EBA43CE /* RoomScreenUITests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomScreenUITests.swift; sourceTree = "<group>"; }; 086B997409328F091EBA43CE /* RoomScreenUITests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomScreenUITests.swift; sourceTree = "<group>"; };
08F64963396A6A23538EFCEC /* is */ = {isa = PBXFileReference; lastKnownFileType = text.plist.stringsdict; name = is; path = is.lproj/Localizable.stringsdict; sourceTree = "<group>"; }; 08F64963396A6A23538EFCEC /* is */ = {isa = PBXFileReference; lastKnownFileType = text.plist.stringsdict; name = is; path = is.lproj/Localizable.stringsdict; sourceTree = "<group>"; };
090CA61A835C151CEDF8F372 /* WeakDictionaryKeyReference.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WeakDictionaryKeyReference.swift; sourceTree = "<group>"; };
09199C43BAB209C0BD89A836 /* OnboardingPageIndicator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OnboardingPageIndicator.swift; sourceTree = "<group>"; }; 09199C43BAB209C0BD89A836 /* OnboardingPageIndicator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OnboardingPageIndicator.swift; sourceTree = "<group>"; };
0950733DD4BA83EEE752E259 /* PlaceholderAvatarImage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PlaceholderAvatarImage.swift; sourceTree = "<group>"; }; 0950733DD4BA83EEE752E259 /* PlaceholderAvatarImage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PlaceholderAvatarImage.swift; sourceTree = "<group>"; };
095AED4CF56DFF3EB7BB84C8 /* RoomTimelineProviderProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomTimelineProviderProtocol.swift; sourceTree = "<group>"; }; 095AED4CF56DFF3EB7BB84C8 /* RoomTimelineProviderProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomTimelineProviderProtocol.swift; sourceTree = "<group>"; };
@@ -558,6 +557,7 @@
179423E34EE846E048E49CBF /* MediaSourceProxy.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MediaSourceProxy.swift; sourceTree = "<group>"; }; 179423E34EE846E048E49CBF /* MediaSourceProxy.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MediaSourceProxy.swift; sourceTree = "<group>"; };
184CF8C196BE143AE226628D /* DecorationTimelineItemProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DecorationTimelineItemProtocol.swift; sourceTree = "<group>"; }; 184CF8C196BE143AE226628D /* DecorationTimelineItemProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DecorationTimelineItemProtocol.swift; sourceTree = "<group>"; };
18F2958E6D247AE2516BEEE8 /* ClientProxy.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ClientProxy.swift; sourceTree = "<group>"; }; 18F2958E6D247AE2516BEEE8 /* ClientProxy.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ClientProxy.swift; sourceTree = "<group>"; };
18FE0CDF1FFA92EA7EE17B0B /* RoomTimelineControllerFactoryProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomTimelineControllerFactoryProtocol.swift; sourceTree = "<group>"; };
1941C8817E6B6971BA4415F5 /* VideoRoomTimelineView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VideoRoomTimelineView.swift; sourceTree = "<group>"; }; 1941C8817E6B6971BA4415F5 /* VideoRoomTimelineView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VideoRoomTimelineView.swift; sourceTree = "<group>"; };
1A18F6CE4D694D21E4EA9B25 /* Strings+Untranslated.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Strings+Untranslated.swift"; sourceTree = "<group>"; }; 1A18F6CE4D694D21E4EA9B25 /* Strings+Untranslated.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Strings+Untranslated.swift"; sourceTree = "<group>"; };
1A3FC45B7643298BF361CEB1 /* VideoPlayerModels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VideoPlayerModels.swift; sourceTree = "<group>"; }; 1A3FC45B7643298BF361CEB1 /* VideoPlayerModels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VideoPlayerModels.swift; sourceTree = "<group>"; };
@@ -580,7 +580,6 @@
22B384D54464FA39C6C7F6E7 /* ca */ = {isa = PBXFileReference; lastKnownFileType = text.plist.stringsdict; name = ca; path = ca.lproj/Localizable.stringsdict; sourceTree = "<group>"; }; 22B384D54464FA39C6C7F6E7 /* ca */ = {isa = PBXFileReference; lastKnownFileType = text.plist.stringsdict; name = ca; path = ca.lproj/Localizable.stringsdict; sourceTree = "<group>"; };
22D46DB0CC6C55EBA7AE67A3 /* SoftLogoutViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SoftLogoutViewModel.swift; sourceTree = "<group>"; }; 22D46DB0CC6C55EBA7AE67A3 /* SoftLogoutViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SoftLogoutViewModel.swift; sourceTree = "<group>"; };
233D5F7E5E9F49ABF3413291 /* hr */ = {isa = PBXFileReference; lastKnownFileType = text.plist.stringsdict; name = hr; path = hr.lproj/Localizable.stringsdict; sourceTree = "<group>"; }; 233D5F7E5E9F49ABF3413291 /* hr */ = {isa = PBXFileReference; lastKnownFileType = text.plist.stringsdict; name = hr; path = hr.lproj/Localizable.stringsdict; sourceTree = "<group>"; };
24B0C97D2F560BCB72BE73B1 /* RoomTimelineController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomTimelineController.swift; sourceTree = "<group>"; };
24F5530B2212862FA4BEFF2D /* HomeScreenViewModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HomeScreenViewModelProtocol.swift; sourceTree = "<group>"; }; 24F5530B2212862FA4BEFF2D /* HomeScreenViewModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HomeScreenViewModelProtocol.swift; sourceTree = "<group>"; };
2583416C8974272ADBADDBE1 /* zh-TW */ = {isa = PBXFileReference; lastKnownFileType = text.plist.stringsdict; name = "zh-TW"; path = "zh-TW.lproj/Localizable.stringsdict"; sourceTree = "<group>"; }; 2583416C8974272ADBADDBE1 /* zh-TW */ = {isa = PBXFileReference; lastKnownFileType = text.plist.stringsdict; name = "zh-TW"; path = "zh-TW.lproj/Localizable.stringsdict"; sourceTree = "<group>"; };
25F7FE40EF7490A7E09D7BE6 /* NotificationItemProxy.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationItemProxy.swift; sourceTree = "<group>"; }; 25F7FE40EF7490A7E09D7BE6 /* NotificationItemProxy.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationItemProxy.swift; sourceTree = "<group>"; };
@@ -598,6 +597,7 @@
2B37DCC9025452F46F91340E /* MockNotificationServiceProxy.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MockNotificationServiceProxy.swift; sourceTree = "<group>"; }; 2B37DCC9025452F46F91340E /* MockNotificationServiceProxy.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MockNotificationServiceProxy.swift; sourceTree = "<group>"; };
2B80895CE021B49847BD7D74 /* TemplateViewModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TemplateViewModelProtocol.swift; sourceTree = "<group>"; }; 2B80895CE021B49847BD7D74 /* TemplateViewModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TemplateViewModelProtocol.swift; sourceTree = "<group>"; };
2B9BCACD0CC4CB8E37F17732 /* lt */ = {isa = PBXFileReference; lastKnownFileType = text.plist.stringsdict; name = lt; path = lt.lproj/Localizable.stringsdict; sourceTree = "<group>"; }; 2B9BCACD0CC4CB8E37F17732 /* lt */ = {isa = PBXFileReference; lastKnownFileType = text.plist.stringsdict; name = lt; path = lt.lproj/Localizable.stringsdict; sourceTree = "<group>"; };
2C0197EAE9D45A662B8847B6 /* RoomTimelineControllerProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomTimelineControllerProtocol.swift; sourceTree = "<group>"; };
2CA028DCD4157F9A1F999827 /* BackgroundTaskProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BackgroundTaskProtocol.swift; sourceTree = "<group>"; }; 2CA028DCD4157F9A1F999827 /* BackgroundTaskProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BackgroundTaskProtocol.swift; sourceTree = "<group>"; };
2CCBDE671A613B3EB70794C4 /* SoftLogoutScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SoftLogoutScreen.swift; sourceTree = "<group>"; }; 2CCBDE671A613B3EB70794C4 /* SoftLogoutScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SoftLogoutScreen.swift; sourceTree = "<group>"; };
2CEBCB9676FCD1D0F13188DD /* StringTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StringTests.swift; sourceTree = "<group>"; }; 2CEBCB9676FCD1D0F13188DD /* StringTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StringTests.swift; sourceTree = "<group>"; };
@@ -606,7 +606,6 @@
2D505843AB66822EB91F0DF0 /* TimelineItemProxy.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TimelineItemProxy.swift; sourceTree = "<group>"; }; 2D505843AB66822EB91F0DF0 /* TimelineItemProxy.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TimelineItemProxy.swift; sourceTree = "<group>"; };
2EEB64CC6F3DF5B68736A6B4 /* AlertInfo.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AlertInfo.swift; sourceTree = "<group>"; }; 2EEB64CC6F3DF5B68736A6B4 /* AlertInfo.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AlertInfo.swift; sourceTree = "<group>"; };
2F1B28C596DE541DA0AFD16C /* lo */ = {isa = PBXFileReference; lastKnownFileType = text.plist.stringsdict; name = lo; path = lo.lproj/Localizable.stringsdict; sourceTree = "<group>"; }; 2F1B28C596DE541DA0AFD16C /* lo */ = {isa = PBXFileReference; lastKnownFileType = text.plist.stringsdict; name = lo; path = lo.lproj/Localizable.stringsdict; sourceTree = "<group>"; };
304FFD608DB6E612075AB1B4 /* WeakDictionary.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WeakDictionary.swift; sourceTree = "<group>"; };
31B01468022EC826CB2FD2C0 /* LoginModels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LoginModels.swift; sourceTree = "<group>"; }; 31B01468022EC826CB2FD2C0 /* LoginModels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LoginModels.swift; sourceTree = "<group>"; };
31D6764D6976D235926FE5FC /* HomeScreenViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HomeScreenViewModel.swift; sourceTree = "<group>"; }; 31D6764D6976D235926FE5FC /* HomeScreenViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HomeScreenViewModel.swift; sourceTree = "<group>"; };
32C5DAA1773F57653BF1C4F9 /* SoftLogoutViewModelTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SoftLogoutViewModelTests.swift; sourceTree = "<group>"; }; 32C5DAA1773F57653BF1C4F9 /* SoftLogoutViewModelTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SoftLogoutViewModelTests.swift; sourceTree = "<group>"; };
@@ -635,7 +634,6 @@
3DF1FFC3336EB23374BBBFCC /* UIKitBackgroundTaskService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UIKitBackgroundTaskService.swift; sourceTree = "<group>"; }; 3DF1FFC3336EB23374BBBFCC /* UIKitBackgroundTaskService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UIKitBackgroundTaskService.swift; sourceTree = "<group>"; };
3F40F48279322E504153AB0D /* MockClientProxy.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MockClientProxy.swift; sourceTree = "<group>"; }; 3F40F48279322E504153AB0D /* MockClientProxy.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MockClientProxy.swift; sourceTree = "<group>"; };
3F9E67AAB66638C69626866C /* UserSessionFlowCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserSessionFlowCoordinator.swift; sourceTree = "<group>"; }; 3F9E67AAB66638C69626866C /* UserSessionFlowCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserSessionFlowCoordinator.swift; sourceTree = "<group>"; };
3FDFF4C1153D263BAB93C1F3 /* README.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = README.md; sourceTree = "<group>"; };
3FEE631F3A4AFDC6652DD9DA /* RoomTimelineViewFactory.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomTimelineViewFactory.swift; sourceTree = "<group>"; }; 3FEE631F3A4AFDC6652DD9DA /* RoomTimelineViewFactory.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomTimelineViewFactory.swift; sourceTree = "<group>"; };
40B21E611DADDEF00307E7AC /* String.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = String.swift; sourceTree = "<group>"; }; 40B21E611DADDEF00307E7AC /* String.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = String.swift; sourceTree = "<group>"; };
41F3B445BD6EF1C751806B22 /* SlidingSyncViewProxy.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SlidingSyncViewProxy.swift; sourceTree = "<group>"; }; 41F3B445BD6EF1C751806B22 /* SlidingSyncViewProxy.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SlidingSyncViewProxy.swift; sourceTree = "<group>"; };
@@ -677,6 +675,7 @@
5221DFDF809142A2D6AC82B9 /* RoomScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomScreen.swift; sourceTree = "<group>"; }; 5221DFDF809142A2D6AC82B9 /* RoomScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomScreen.swift; sourceTree = "<group>"; };
5282B7A2DCD076AD2CF27F46 /* VideoPlayerViewModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VideoPlayerViewModelProtocol.swift; sourceTree = "<group>"; }; 5282B7A2DCD076AD2CF27F46 /* VideoPlayerViewModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VideoPlayerViewModelProtocol.swift; sourceTree = "<group>"; };
529513218340CC8419273165 /* tr */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = tr; path = tr.lproj/Localizable.strings; sourceTree = "<group>"; }; 529513218340CC8419273165 /* tr */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = tr; path = tr.lproj/Localizable.strings; sourceTree = "<group>"; };
52D7074991B3267B26D89B22 /* MockRoomTimelineController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MockRoomTimelineController.swift; sourceTree = "<group>"; };
53482ECA4B6633961EC224F5 /* ScrollViewAdapter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ScrollViewAdapter.swift; sourceTree = "<group>"; }; 53482ECA4B6633961EC224F5 /* ScrollViewAdapter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ScrollViewAdapter.swift; sourceTree = "<group>"; };
534A5C8FCDE2CBC50266B9F2 /* gl */ = {isa = PBXFileReference; lastKnownFileType = text.plist.stringsdict; name = gl; path = gl.lproj/Localizable.stringsdict; sourceTree = "<group>"; }; 534A5C8FCDE2CBC50266B9F2 /* gl */ = {isa = PBXFileReference; lastKnownFileType = text.plist.stringsdict; name = gl; path = gl.lproj/Localizable.stringsdict; sourceTree = "<group>"; };
536E72DCBEEC4A1FE66CFDCE /* target.yml */ = {isa = PBXFileReference; lastKnownFileType = text.yaml; path = target.yml; sourceTree = "<group>"; }; 536E72DCBEEC4A1FE66CFDCE /* target.yml */ = {isa = PBXFileReference; lastKnownFileType = text.yaml; path = target.yml; sourceTree = "<group>"; };
@@ -701,7 +700,6 @@
6045E825AE900A92D61FEFF0 /* ImageAnonymizerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ImageAnonymizerTests.swift; sourceTree = "<group>"; }; 6045E825AE900A92D61FEFF0 /* ImageAnonymizerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ImageAnonymizerTests.swift; sourceTree = "<group>"; };
607974D08BD2AF83725D817A /* RoomMessageProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomMessageProtocol.swift; sourceTree = "<group>"; }; 607974D08BD2AF83725D817A /* RoomMessageProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomMessageProtocol.swift; sourceTree = "<group>"; };
616197D81103330BF2ADD559 /* gl */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = gl; path = gl.lproj/Localizable.strings; sourceTree = "<group>"; }; 616197D81103330BF2ADD559 /* gl */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = gl; path = gl.lproj/Localizable.strings; sourceTree = "<group>"; };
61ADFB893DEF81E58DF3FAB9 /* MockRoomTimelineController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MockRoomTimelineController.swift; sourceTree = "<group>"; };
624244C398804ADC885239AA /* hu */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = hu; path = hu.lproj/Localizable.strings; sourceTree = "<group>"; }; 624244C398804ADC885239AA /* hu */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = hu; path = hu.lproj/Localizable.strings; sourceTree = "<group>"; };
62BDF0FF4F59AF6EA858B70B /* FilePreviewViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FilePreviewViewModel.swift; sourceTree = "<group>"; }; 62BDF0FF4F59AF6EA858B70B /* FilePreviewViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FilePreviewViewModel.swift; sourceTree = "<group>"; };
6390A6DC140CA3D6865A66FF /* SeparatorRoomTimelineView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SeparatorRoomTimelineView.swift; sourceTree = "<group>"; }; 6390A6DC140CA3D6865A66FF /* SeparatorRoomTimelineView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SeparatorRoomTimelineView.swift; sourceTree = "<group>"; };
@@ -711,7 +709,6 @@
6654859746B0BE9611459391 /* cs */ = {isa = PBXFileReference; lastKnownFileType = text.plist.stringsdict; name = cs; path = cs.lproj/Localizable.stringsdict; sourceTree = "<group>"; }; 6654859746B0BE9611459391 /* cs */ = {isa = PBXFileReference; lastKnownFileType = text.plist.stringsdict; name = cs; path = cs.lproj/Localizable.stringsdict; sourceTree = "<group>"; };
667DD3A9D932D7D9EB380CAA /* sk */ = {isa = PBXFileReference; lastKnownFileType = text.plist.stringsdict; name = sk; path = sk.lproj/Localizable.stringsdict; sourceTree = "<group>"; }; 667DD3A9D932D7D9EB380CAA /* sk */ = {isa = PBXFileReference; lastKnownFileType = text.plist.stringsdict; name = sk; path = sk.lproj/Localizable.stringsdict; sourceTree = "<group>"; };
66F2402D738694F98729A441 /* RoomTimelineProvider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomTimelineProvider.swift; sourceTree = "<group>"; }; 66F2402D738694F98729A441 /* RoomTimelineProvider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomTimelineProvider.swift; sourceTree = "<group>"; };
68232D336E2B546AD95B78B5 /* XCUIElement.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = XCUIElement.swift; sourceTree = "<group>"; };
6920A4869821BF72FFC58842 /* MockMediaProvider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MockMediaProvider.swift; sourceTree = "<group>"; }; 6920A4869821BF72FFC58842 /* MockMediaProvider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MockMediaProvider.swift; sourceTree = "<group>"; };
6A1AAC8EB2992918D01874AC /* rue */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = rue; path = rue.lproj/Localizable.strings; sourceTree = "<group>"; }; 6A1AAC8EB2992918D01874AC /* rue */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = rue; path = rue.lproj/Localizable.strings; sourceTree = "<group>"; };
6A580295A56B55A856CC4084 /* InfoPlistReader.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InfoPlistReader.swift; sourceTree = "<group>"; }; 6A580295A56B55A856CC4084 /* InfoPlistReader.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InfoPlistReader.swift; sourceTree = "<group>"; };
@@ -727,6 +724,7 @@
6F3DFE5B444F131648066F05 /* StateStoreViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StateStoreViewModel.swift; sourceTree = "<group>"; }; 6F3DFE5B444F131648066F05 /* StateStoreViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StateStoreViewModel.swift; sourceTree = "<group>"; };
6FB31A32C93D94930B253FBF /* PermalinkBuilderTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PermalinkBuilderTests.swift; sourceTree = "<group>"; }; 6FB31A32C93D94930B253FBF /* PermalinkBuilderTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PermalinkBuilderTests.swift; sourceTree = "<group>"; };
6FC5015B9634698BDB8701AF /* it */ = {isa = PBXFileReference; lastKnownFileType = text.plist.stringsdict; name = it; path = it.lproj/Localizable.stringsdict; sourceTree = "<group>"; }; 6FC5015B9634698BDB8701AF /* it */ = {isa = PBXFileReference; lastKnownFileType = text.plist.stringsdict; name = it; path = it.lproj/Localizable.stringsdict; sourceTree = "<group>"; };
71556206CD5E8B1F53F07178 /* MockRoomTimelineControllerFactory.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MockRoomTimelineControllerFactory.swift; sourceTree = "<group>"; };
71BC7CA1BC1041E93077BBA1 /* HomeScreenModels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HomeScreenModels.swift; sourceTree = "<group>"; }; 71BC7CA1BC1041E93077BBA1 /* HomeScreenModels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HomeScreenModels.swift; sourceTree = "<group>"; };
71D52BAA5BADB06E5E8C295D /* Assets.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Assets.swift; sourceTree = "<group>"; }; 71D52BAA5BADB06E5E8C295D /* Assets.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Assets.swift; sourceTree = "<group>"; };
72D03D36422177EF01905D20 /* ca */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ca; path = ca.lproj/Localizable.strings; sourceTree = "<group>"; }; 72D03D36422177EF01905D20 /* ca */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ca; path = ca.lproj/Localizable.strings; sourceTree = "<group>"; };
@@ -762,7 +760,6 @@
892E29C98C4E8182C9037F84 /* TimelineStyler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TimelineStyler.swift; sourceTree = "<group>"; }; 892E29C98C4E8182C9037F84 /* TimelineStyler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TimelineStyler.swift; sourceTree = "<group>"; };
8A9AE4967817E9608E22EB44 /* pt-BR */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "pt-BR"; path = "pt-BR.lproj/Localizable.strings"; sourceTree = "<group>"; }; 8A9AE4967817E9608E22EB44 /* pt-BR */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "pt-BR"; path = "pt-BR.lproj/Localizable.strings"; sourceTree = "<group>"; };
8AC1A01C3A745BDF1D3697D3 /* SessionVerificationScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SessionVerificationScreen.swift; sourceTree = "<group>"; }; 8AC1A01C3A745BDF1D3697D3 /* SessionVerificationScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SessionVerificationScreen.swift; sourceTree = "<group>"; };
8B9A55AC2FB0FE0AEAA3DF1F /* LICENSE */ = {isa = PBXFileReference; path = LICENSE; sourceTree = "<group>"; };
8C0AA893D6F8A2F563E01BB9 /* in */ = {isa = PBXFileReference; lastKnownFileType = text.plist.stringsdict; name = in; path = in.lproj/Localizable.stringsdict; sourceTree = "<group>"; }; 8C0AA893D6F8A2F563E01BB9 /* in */ = {isa = PBXFileReference; lastKnownFileType = text.plist.stringsdict; name = in; path = in.lproj/Localizable.stringsdict; sourceTree = "<group>"; };
8D6094DEAAEB388E1AE118C6 /* MockRoomTimelineProvider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MockRoomTimelineProvider.swift; sourceTree = "<group>"; }; 8D6094DEAAEB388E1AE118C6 /* MockRoomTimelineProvider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MockRoomTimelineProvider.swift; sourceTree = "<group>"; };
8D8169443E5AC5FF71BFB3DB /* cs */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = cs; path = cs.lproj/Localizable.strings; sourceTree = "<group>"; }; 8D8169443E5AC5FF71BFB3DB /* cs */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = cs; path = cs.lproj/Localizable.strings; sourceTree = "<group>"; };
@@ -804,6 +801,7 @@
9CE3C90E487B255B735D73C8 /* RoomScreenViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomScreenViewModel.swift; sourceTree = "<group>"; }; 9CE3C90E487B255B735D73C8 /* RoomScreenViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomScreenViewModel.swift; sourceTree = "<group>"; };
9D7D706FFF438CAF16F44D8C /* ServerSelectionCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ServerSelectionCoordinator.swift; sourceTree = "<group>"; }; 9D7D706FFF438CAF16F44D8C /* ServerSelectionCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ServerSelectionCoordinator.swift; sourceTree = "<group>"; };
9E6D88E8AFFBF2C1D589C0FA /* UIConstants.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UIConstants.swift; sourceTree = "<group>"; }; 9E6D88E8AFFBF2C1D589C0FA /* UIConstants.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UIConstants.swift; sourceTree = "<group>"; };
9F85164F9475FF2867F71AAA /* RoomTimelineController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomTimelineController.swift; sourceTree = "<group>"; };
A00C7A331B72C0F05C00392F /* RoomScreenViewModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomScreenViewModelProtocol.swift; sourceTree = "<group>"; }; A00C7A331B72C0F05C00392F /* RoomScreenViewModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomScreenViewModelProtocol.swift; sourceTree = "<group>"; };
A05707BF550D770168A406DB /* LoginViewModelTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LoginViewModelTests.swift; sourceTree = "<group>"; }; A05707BF550D770168A406DB /* LoginViewModelTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LoginViewModelTests.swift; sourceTree = "<group>"; };
A057F2FDC14866C3026A89A4 /* NotificationManagerProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationManagerProtocol.swift; sourceTree = "<group>"; }; A057F2FDC14866C3026A89A4 /* NotificationManagerProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationManagerProtocol.swift; sourceTree = "<group>"; };
@@ -891,7 +889,6 @@
C687844F60BFF532D49A994C /* AnalyticsTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AnalyticsTests.swift; sourceTree = "<group>"; }; C687844F60BFF532D49A994C /* AnalyticsTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AnalyticsTests.swift; sourceTree = "<group>"; };
C6FEA87EA3752203065ECE27 /* BugReportUITests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BugReportUITests.swift; sourceTree = "<group>"; }; C6FEA87EA3752203065ECE27 /* BugReportUITests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BugReportUITests.swift; sourceTree = "<group>"; };
C75EF87651B00A176AB08E97 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; }; C75EF87651B00A176AB08E97 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
C7955B20E2E6DA68E5BC0AB9 /* WeakDictionaryReference.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WeakDictionaryReference.swift; sourceTree = "<group>"; };
C830A64609CBD152F06E0457 /* NotificationConstants.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationConstants.swift; sourceTree = "<group>"; }; C830A64609CBD152F06E0457 /* NotificationConstants.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationConstants.swift; sourceTree = "<group>"; };
C88508B6F7974CFABEC4B261 /* ar */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ar; path = ar.lproj/Localizable.strings; sourceTree = "<group>"; }; C88508B6F7974CFABEC4B261 /* ar */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ar; path = ar.lproj/Localizable.strings; sourceTree = "<group>"; };
C888BCD78E2A55DCE364F160 /* MediaProviderProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MediaProviderProtocol.swift; sourceTree = "<group>"; }; C888BCD78E2A55DCE364F160 /* MediaProviderProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MediaProviderProtocol.swift; sourceTree = "<group>"; };
@@ -908,7 +905,6 @@
CBF9AEA706926DD0DA2B954C /* JoinedRoomSize+MemberCount.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "JoinedRoomSize+MemberCount.swift"; sourceTree = "<group>"; }; CBF9AEA706926DD0DA2B954C /* JoinedRoomSize+MemberCount.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "JoinedRoomSize+MemberCount.swift"; sourceTree = "<group>"; };
CC680E0E79D818706CB28CF8 /* fr */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = fr; path = fr.lproj/Localizable.strings; sourceTree = "<group>"; }; CC680E0E79D818706CB28CF8 /* fr */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = fr; path = fr.lproj/Localizable.strings; sourceTree = "<group>"; };
CC6FE34A0A47D010BBB4D4D4 /* UITestScreenIdentifier.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UITestScreenIdentifier.swift; sourceTree = "<group>"; }; CC6FE34A0A47D010BBB4D4D4 /* UITestScreenIdentifier.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UITestScreenIdentifier.swift; sourceTree = "<group>"; };
CC7CCC6DE5FA623E31BA8546 /* RoomTimelineControllerProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomTimelineControllerProtocol.swift; sourceTree = "<group>"; };
CCF86010A0A719A9A50EEC59 /* SessionVerificationCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SessionVerificationCoordinator.swift; sourceTree = "<group>"; }; CCF86010A0A719A9A50EEC59 /* SessionVerificationCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SessionVerificationCoordinator.swift; sourceTree = "<group>"; };
CD80F22830C2360F3F39DDCE /* UserNotificationModalView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserNotificationModalView.swift; sourceTree = "<group>"; }; CD80F22830C2360F3F39DDCE /* UserNotificationModalView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserNotificationModalView.swift; sourceTree = "<group>"; };
CDB3227C7A74B734924942E9 /* RoomSummaryProvider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomSummaryProvider.swift; sourceTree = "<group>"; }; CDB3227C7A74B734924942E9 /* RoomSummaryProvider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomSummaryProvider.swift; sourceTree = "<group>"; };
@@ -918,7 +914,6 @@
D06DFD894157A4C93A02D8B5 /* lo */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = lo; path = lo.lproj/Localizable.strings; sourceTree = "<group>"; }; D06DFD894157A4C93A02D8B5 /* lo */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = lo; path = lo.lproj/Localizable.strings; sourceTree = "<group>"; };
D09A267106B9585D3D0CFC0D /* ClientError.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ClientError.swift; sourceTree = "<group>"; }; D09A267106B9585D3D0CFC0D /* ClientError.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ClientError.swift; sourceTree = "<group>"; };
D0A45283CF1DB96E583BECA6 /* ImageRoomTimelineView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ImageRoomTimelineView.swift; sourceTree = "<group>"; }; D0A45283CF1DB96E583BECA6 /* ImageRoomTimelineView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ImageRoomTimelineView.swift; sourceTree = "<group>"; };
D0ADFDC712027931F2216668 /* WeakKeyDictionary.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WeakKeyDictionary.swift; sourceTree = "<group>"; };
D1651A532305027D3F605E2B /* VideoPlayerCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VideoPlayerCoordinator.swift; sourceTree = "<group>"; }; D1651A532305027D3F605E2B /* VideoPlayerCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VideoPlayerCoordinator.swift; sourceTree = "<group>"; };
D1A9CCCF53495CF3D7B19FCE /* MockSessionVerificationControllerProxy.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MockSessionVerificationControllerProxy.swift; sourceTree = "<group>"; }; D1A9CCCF53495CF3D7B19FCE /* MockSessionVerificationControllerProxy.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MockSessionVerificationControllerProxy.swift; sourceTree = "<group>"; };
D263254AFE5B7993FFBBF324 /* NSE.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = NSE.entitlements; sourceTree = "<group>"; }; D263254AFE5B7993FFBBF324 /* NSE.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = NSE.entitlements; sourceTree = "<group>"; };
@@ -963,9 +958,11 @@
E5E94DCFEE803E5ABAE8ACCE /* KeychainControllerProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = KeychainControllerProtocol.swift; sourceTree = "<group>"; }; E5E94DCFEE803E5ABAE8ACCE /* KeychainControllerProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = KeychainControllerProtocol.swift; sourceTree = "<group>"; };
E5F2B6443D1ED8602F328539 /* ru */ = {isa = PBXFileReference; lastKnownFileType = text.plist.stringsdict; name = ru; path = ru.lproj/Localizable.stringsdict; sourceTree = "<group>"; }; E5F2B6443D1ED8602F328539 /* ru */ = {isa = PBXFileReference; lastKnownFileType = text.plist.stringsdict; name = ru; path = ru.lproj/Localizable.stringsdict; sourceTree = "<group>"; };
E6281B199D8A8F0892490C2E /* OnboardingCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OnboardingCoordinator.swift; sourceTree = "<group>"; }; E6281B199D8A8F0892490C2E /* OnboardingCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OnboardingCoordinator.swift; sourceTree = "<group>"; };
E6FCC416A3BFE73DF7B3E6BF /* RoomTimelineControllerFactory.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomTimelineControllerFactory.swift; sourceTree = "<group>"; };
E8294DB9E95C0C0630418466 /* ru */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ru; path = ru.lproj/Localizable.strings; sourceTree = "<group>"; }; E8294DB9E95C0C0630418466 /* ru */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ru; path = ru.lproj/Localizable.strings; sourceTree = "<group>"; };
E8CA187FE656EE5A3F6C7DE5 /* UIFont+AttributedStringBuilder.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "UIFont+AttributedStringBuilder.m"; sourceTree = "<group>"; }; E8CA187FE656EE5A3F6C7DE5 /* UIFont+AttributedStringBuilder.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "UIFont+AttributedStringBuilder.m"; sourceTree = "<group>"; };
E96ED747FF90332EA1333C22 /* RoomTimelineItemFixtures.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomTimelineItemFixtures.swift; sourceTree = "<group>"; }; E96ED747FF90332EA1333C22 /* RoomTimelineItemFixtures.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomTimelineItemFixtures.swift; sourceTree = "<group>"; };
E992D7B8BE54B2AB454613AF /* XCUIElement.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = XCUIElement.swift; sourceTree = "<group>"; };
E9D059BFE329BE09B6D96A9F /* ro */ = {isa = PBXFileReference; lastKnownFileType = text.plist.stringsdict; name = ro; path = ro.lproj/Localizable.stringsdict; sourceTree = "<group>"; }; E9D059BFE329BE09B6D96A9F /* ro */ = {isa = PBXFileReference; lastKnownFileType = text.plist.stringsdict; name = ro; path = ro.lproj/Localizable.stringsdict; sourceTree = "<group>"; };
EB3B237387B8288A5A938F1B /* UserAgentBuilderTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserAgentBuilderTests.swift; sourceTree = "<group>"; }; EB3B237387B8288A5A938F1B /* UserAgentBuilderTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserAgentBuilderTests.swift; sourceTree = "<group>"; };
EBE5502760CF6CA2D7201883 /* ja */ = {isa = PBXFileReference; lastKnownFileType = text.plist.stringsdict; name = ja; path = ja.lproj/Localizable.stringsdict; sourceTree = "<group>"; }; EBE5502760CF6CA2D7201883 /* ja */ = {isa = PBXFileReference; lastKnownFileType = text.plist.stringsdict; name = ja; path = ja.lproj/Localizable.stringsdict; sourceTree = "<group>"; };
@@ -998,6 +995,7 @@
F754E66A8970963B15B2A41E /* PermalinkBuilder.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PermalinkBuilder.swift; sourceTree = "<group>"; }; F754E66A8970963B15B2A41E /* PermalinkBuilder.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PermalinkBuilder.swift; sourceTree = "<group>"; };
F77C060C2ACC4CB7336A29E7 /* EmoteRoomTimelineItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EmoteRoomTimelineItem.swift; sourceTree = "<group>"; }; F77C060C2ACC4CB7336A29E7 /* EmoteRoomTimelineItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EmoteRoomTimelineItem.swift; sourceTree = "<group>"; };
F875D71347DC81EAE7687446 /* NavigationRootCoordinatorTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NavigationRootCoordinatorTests.swift; sourceTree = "<group>"; }; F875D71347DC81EAE7687446 /* NavigationRootCoordinatorTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NavigationRootCoordinatorTests.swift; sourceTree = "<group>"; };
F899D02CF26EA7675EEBE74C /* UserSessionScreenTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserSessionScreenTests.swift; sourceTree = "<group>"; };
F9212AE02CBDD692C56A879F /* TimelineTableViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TimelineTableViewController.swift; sourceTree = "<group>"; }; F9212AE02CBDD692C56A879F /* TimelineTableViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TimelineTableViewController.swift; sourceTree = "<group>"; };
F9E785D5137510481733A3E8 /* TextRoomTimelineView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TextRoomTimelineView.swift; sourceTree = "<group>"; }; F9E785D5137510481733A3E8 /* TextRoomTimelineView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TextRoomTimelineView.swift; sourceTree = "<group>"; };
FA154570F693D93513E584C1 /* RoomMessageFactory.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomMessageFactory.swift; sourceTree = "<group>"; }; FA154570F693D93513E584C1 /* RoomMessageFactory.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomMessageFactory.swift; sourceTree = "<group>"; };
@@ -1171,19 +1169,6 @@
path = View; path = View;
sourceTree = "<group>"; sourceTree = "<group>";
}; };
2064C5712E5DBF0A2D57A833 /* WeakDictionary */ = {
isa = PBXGroup;
children = (
8B9A55AC2FB0FE0AEAA3DF1F /* LICENSE */,
3FDFF4C1153D263BAB93C1F3 /* README.md */,
304FFD608DB6E612075AB1B4 /* WeakDictionary.swift */,
090CA61A835C151CEDF8F372 /* WeakDictionaryKeyReference.swift */,
C7955B20E2E6DA68E5BC0AB9 /* WeakDictionaryReference.swift */,
D0ADFDC712027931F2216668 /* WeakKeyDictionary.swift */,
);
path = WeakDictionary;
sourceTree = "<group>";
};
24FD174C31912A5FACFEAFB5 /* SupportingFiles */ = { 24FD174C31912A5FACFEAFB5 /* SupportingFiles */ = {
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
@@ -1234,6 +1219,19 @@
path = UITests; path = UITests;
sourceTree = "<group>"; sourceTree = "<group>";
}; };
2F2FED77226A43559F009463 /* TimelineController */ = {
isa = PBXGroup;
children = (
52D7074991B3267B26D89B22 /* MockRoomTimelineController.swift */,
71556206CD5E8B1F53F07178 /* MockRoomTimelineControllerFactory.swift */,
9F85164F9475FF2867F71AAA /* RoomTimelineController.swift */,
E6FCC416A3BFE73DF7B3E6BF /* RoomTimelineControllerFactory.swift */,
18FE0CDF1FFA92EA7EE17B0B /* RoomTimelineControllerFactoryProtocol.swift */,
2C0197EAE9D45A662B8847B6 /* RoomTimelineControllerProtocol.swift */,
);
path = TimelineController;
sourceTree = "<group>";
};
323160803A296713F839540B /* View */ = { 323160803A296713F839540B /* View */ = {
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
@@ -1382,6 +1380,7 @@
A40C19719687984FD9478FBE /* Task.swift */, A40C19719687984FD9478FBE /* Task.swift */,
287FC98AF2664EAD79C0D902 /* UIDevice.swift */, 287FC98AF2664EAD79C0D902 /* UIDevice.swift */,
227AC5D71A4CE43512062243 /* URL.swift */, 227AC5D71A4CE43512062243 /* URL.swift */,
E992D7B8BE54B2AB454613AF /* XCUIElement.swift */,
); );
path = Extensions; path = Extensions;
sourceTree = "<group>"; sourceTree = "<group>";
@@ -1450,7 +1449,6 @@
44D8C8431416EB8DFEC7E235 /* ApplicationTests.swift */, 44D8C8431416EB8DFEC7E235 /* ApplicationTests.swift */,
2D256FEE2F1AF1E51D39B622 /* LoginTests.swift */, 2D256FEE2F1AF1E51D39B622 /* LoginTests.swift */,
9C4048041C1A6B20CB97FD18 /* TestMeasurementParser.swift */, 9C4048041C1A6B20CB97FD18 /* TestMeasurementParser.swift */,
68232D336E2B546AD95B78B5 /* XCUIElement.swift */,
); );
path = Sources; path = Sources;
sourceTree = "<group>"; sourceTree = "<group>";
@@ -1881,6 +1879,7 @@
6D4777F0142E330A75C46FE4 /* SessionVerificationUITests.swift */, 6D4777F0142E330A75C46FE4 /* SessionVerificationUITests.swift */,
E3E29F98CF0E960689A410E3 /* SettingsUITests.swift */, E3E29F98CF0E960689A410E3 /* SettingsUITests.swift */,
55F30E764BED111C81739844 /* SoftLogoutUITests.swift */, 55F30E764BED111C81739844 /* SoftLogoutUITests.swift */,
F899D02CF26EA7675EEBE74C /* UserSessionScreenTests.swift */,
); );
path = Sources; path = Sources;
sourceTree = "<group>"; sourceTree = "<group>";
@@ -2152,14 +2151,6 @@
path = View; path = View;
sourceTree = "<group>"; sourceTree = "<group>";
}; };
CEC90ED84EDEB86B209053E7 /* Vendor */ = {
isa = PBXGroup;
children = (
2064C5712E5DBF0A2D57A833 /* WeakDictionary */,
);
path = Vendor;
sourceTree = "<group>";
};
D958761758AA1110476DE6A3 /* SessionVerification */ = { D958761758AA1110476DE6A3 /* SessionVerification */ = {
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
@@ -2251,7 +2242,6 @@
C0937E3B06A8F0E2DB7C8241 /* Other */, C0937E3B06A8F0E2DB7C8241 /* Other */,
2ECFF6B05DAA37EB10DBF7E8 /* UITests */, 2ECFF6B05DAA37EB10DBF7E8 /* UITests */,
337015ADFBA3AB96660DB3A6 /* Generated */, 337015ADFBA3AB96660DB3A6 /* Generated */,
CEC90ED84EDEB86B209053E7 /* Vendor */,
); );
path = Sources; path = Sources;
sourceTree = "<group>"; sourceTree = "<group>";
@@ -2296,14 +2286,12 @@
FCDF06BDB123505F0334B4F9 /* Timeline */ = { FCDF06BDB123505F0334B4F9 /* Timeline */ = {
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
61ADFB893DEF81E58DF3FAB9 /* MockRoomTimelineController.swift */,
8D6094DEAAEB388E1AE118C6 /* MockRoomTimelineProvider.swift */, 8D6094DEAAEB388E1AE118C6 /* MockRoomTimelineProvider.swift */,
24B0C97D2F560BCB72BE73B1 /* RoomTimelineController.swift */,
CC7CCC6DE5FA623E31BA8546 /* RoomTimelineControllerProtocol.swift */,
66F2402D738694F98729A441 /* RoomTimelineProvider.swift */, 66F2402D738694F98729A441 /* RoomTimelineProvider.swift */,
095AED4CF56DFF3EB7BB84C8 /* RoomTimelineProviderProtocol.swift */, 095AED4CF56DFF3EB7BB84C8 /* RoomTimelineProviderProtocol.swift */,
2D505843AB66822EB91F0DF0 /* TimelineItemProxy.swift */, 2D505843AB66822EB91F0DF0 /* TimelineItemProxy.swift */,
3EA31CC7012EA2A5653DAFC9 /* Fixtures */, 3EA31CC7012EA2A5653DAFC9 /* Fixtures */,
2F2FED77226A43559F009463 /* TimelineController */,
5A7A7D6D373D411C8C48B881 /* TimeLineItemContent */, 5A7A7D6D373D411C8C48B881 /* TimeLineItemContent */,
95BE1C7CB2C80344FF0BE724 /* TimelineItems */, 95BE1C7CB2C80344FF0BE724 /* TimelineItems */,
); );
@@ -2603,7 +2591,6 @@
AB34401E4E1CAD5D2EC3072B /* LaunchScreen.storyboard in Resources */, AB34401E4E1CAD5D2EC3072B /* LaunchScreen.storyboard in Resources */,
5F5488FBC9CFEB6F433D74A4 /* Localizable.strings in Resources */, 5F5488FBC9CFEB6F433D74A4 /* Localizable.strings in Resources */,
0EA6537A07E2DC882AEA5962 /* Localizable.stringsdict in Resources */, 0EA6537A07E2DC882AEA5962 /* Localizable.stringsdict in Resources */,
690ED5315B401238A3249DCB /* README.md in Resources */,
CE1694C7BB93C3311524EF28 /* Untranslated.strings in Resources */, CE1694C7BB93C3311524EF28 /* Untranslated.strings in Resources */,
2797C9D9BA642370F1C85D78 /* Untranslated.stringsdict in Resources */, 2797C9D9BA642370F1C85D78 /* Untranslated.stringsdict in Resources */,
CCAA0671B46EAFD0BB528E2C /* apple_emojis_data.json in Resources */, CCAA0671B46EAFD0BB528E2C /* apple_emojis_data.json in Resources */,
@@ -2932,7 +2919,8 @@
AEE3981A0F090208E4445808 /* MockNotificationServiceProxy.swift in Sources */, AEE3981A0F090208E4445808 /* MockNotificationServiceProxy.swift in Sources */,
51DB67C5B5BC68B0A6FF54D4 /* MockRoomProxy.swift in Sources */, 51DB67C5B5BC68B0A6FF54D4 /* MockRoomProxy.swift in Sources */,
2352C541AF857241489756FF /* MockRoomSummaryProvider.swift in Sources */, 2352C541AF857241489756FF /* MockRoomSummaryProvider.swift in Sources */,
E81EEC1675F2371D12A880A3 /* MockRoomTimelineController.swift in Sources */, 09C83DDDB07C28364F325209 /* MockRoomTimelineController.swift in Sources */,
158A2D528CC78C4E7A8ED608 /* MockRoomTimelineControllerFactory.swift in Sources */,
447E8580A0A2569E32529E17 /* MockRoomTimelineProvider.swift in Sources */, 447E8580A0A2569E32529E17 /* MockRoomTimelineProvider.swift in Sources */,
9BE7A9CF6C593251D734B461 /* MockServerSelectionScreenState.swift in Sources */, 9BE7A9CF6C593251D734B461 /* MockServerSelectionScreenState.swift in Sources */,
D034A195A3494E38BF060485 /* MockSessionVerificationControllerProxy.swift in Sources */, D034A195A3494E38BF060485 /* MockSessionVerificationControllerProxy.swift in Sources */,
@@ -2980,8 +2968,10 @@
A7FD7B992E6EE6E5A8429197 /* RoomSummaryDetails.swift in Sources */, A7FD7B992E6EE6E5A8429197 /* RoomSummaryDetails.swift in Sources */,
983896D611ABF52A5C37498D /* RoomSummaryProvider.swift in Sources */, 983896D611ABF52A5C37498D /* RoomSummaryProvider.swift in Sources */,
AA050DF4AEE54A641BA7CA22 /* RoomSummaryProviderProtocol.swift in Sources */, AA050DF4AEE54A641BA7CA22 /* RoomSummaryProviderProtocol.swift in Sources */,
78B71D53C1FC55FB7A9B75F0 /* RoomTimelineController.swift in Sources */, 2ABF11717C64054CEF2819A3 /* RoomTimelineController.swift in Sources */,
9B8DE1D424E37581C7D99CCC /* RoomTimelineControllerProtocol.swift in Sources */, 38896D54D6D675534E606195 /* RoomTimelineControllerFactory.swift in Sources */,
7ECF12D5DCD69F67BD3E3842 /* RoomTimelineControllerFactoryProtocol.swift in Sources */,
E89536FC8C0E4B79E9842A78 /* RoomTimelineControllerProtocol.swift in Sources */,
4E945AD6862C403F74E57755 /* RoomTimelineItemFactory.swift in Sources */, 4E945AD6862C403F74E57755 /* RoomTimelineItemFactory.swift in Sources */,
13C77FDF17C4C6627CFFC205 /* RoomTimelineItemFactoryProtocol.swift in Sources */, 13C77FDF17C4C6627CFFC205 /* RoomTimelineItemFactoryProtocol.swift in Sources */,
70558528EF68CAAEF09972D5 /* RoomTimelineItemFixtures.swift in Sources */, 70558528EF68CAAEF09972D5 /* RoomTimelineItemFixtures.swift in Sources */,
@@ -3082,10 +3072,6 @@
36C10EDEDC0466E3A9D63132 /* VideoRoomTimelineItem.swift in Sources */, 36C10EDEDC0466E3A9D63132 /* VideoRoomTimelineItem.swift in Sources */,
64F43D7390DA2A0AFD6BA911 /* VideoRoomTimelineView.swift in Sources */, 64F43D7390DA2A0AFD6BA911 /* VideoRoomTimelineView.swift in Sources */,
6FC10A00D268FCD48B631E37 /* ViewFrameReader.swift in Sources */, 6FC10A00D268FCD48B631E37 /* ViewFrameReader.swift in Sources */,
6DF37000571B1BC6D134CC9E /* WeakDictionary.swift in Sources */,
32BA37B01B05261FCF2D4B45 /* WeakDictionaryKeyReference.swift in Sources */,
457465EC436703E8C76133A4 /* WeakDictionaryReference.swift in Sources */,
841172E1576A863F4450132D /* WeakKeyDictionary.swift in Sources */,
); );
runOnlyForDeploymentPostprocessing = 0; runOnlyForDeploymentPostprocessing = 0;
}; };
@@ -3116,6 +3102,8 @@
0ED951768EC443A8728DE1D7 /* TimelineStyle.swift in Sources */, 0ED951768EC443A8728DE1D7 /* TimelineStyle.swift in Sources */,
9A47B7EFE3793760EEF68FFE /* UITestScreenIdentifier.swift in Sources */, 9A47B7EFE3793760EEF68FFE /* UITestScreenIdentifier.swift in Sources */,
35C57543D245E82CBFE15DF0 /* URL.swift in Sources */, 35C57543D245E82CBFE15DF0 /* URL.swift in Sources */,
B22D857D1E8FCA6DD74A58E3 /* UserSessionScreenTests.swift in Sources */,
588411C8FD72B2A2DFE5F7DE /* XCUIElement.swift in Sources */,
); );
runOnlyForDeploymentPostprocessing = 0; runOnlyForDeploymentPostprocessing = 0;
}; };
@@ -3127,7 +3115,7 @@
23B2CD5A06B16055BDDD0994 /* ApplicationTests.swift in Sources */, 23B2CD5A06B16055BDDD0994 /* ApplicationTests.swift in Sources */,
07240B7159A3990C4C2E8FFC /* LoginTests.swift in Sources */, 07240B7159A3990C4C2E8FFC /* LoginTests.swift in Sources */,
290FDB0FFDC2F1DDF660343E /* TestMeasurementParser.swift in Sources */, 290FDB0FFDC2F1DDF660343E /* TestMeasurementParser.swift in Sources */,
AB4C5D62A21AD712811CE8CD /* XCUIElement.swift in Sources */, B444F9C184A377C1B481F07F /* XCUIElement.swift in Sources */,
); );
runOnlyForDeploymentPostprocessing = 0; runOnlyForDeploymentPostprocessing = 0;
}; };
@@ -219,7 +219,8 @@ class AppCoordinator: AppCoordinatorProtocol {
let navigationSplitCoordinator = NavigationSplitCoordinator(placeholderCoordinator: SplashScreenCoordinator()) let navigationSplitCoordinator = NavigationSplitCoordinator(placeholderCoordinator: SplashScreenCoordinator())
let userSessionFlowCoordinator = UserSessionFlowCoordinator(userSession: userSession, let userSessionFlowCoordinator = UserSessionFlowCoordinator(userSession: userSession,
navigationSplitCoordinator: navigationSplitCoordinator, navigationSplitCoordinator: navigationSplitCoordinator,
bugReportService: bugReportService) bugReportService: bugReportService,
roomTimelineControllerFactory: RoomTimelineControllerFactory())
userSessionFlowCoordinator.callback = { [weak self] action in userSessionFlowCoordinator.callback = { [weak self] action in
switch action { switch action {
@@ -57,9 +57,9 @@ class NavigationRootCoordinator: ObservableObject, CoordinatorProtocol, CustomSt
var description: String { var description: String {
if let rootCoordinator = rootModule?.coordinator { if let rootCoordinator = rootModule?.coordinator {
return "SingleScreenCoordinator(\(rootCoordinator)" return "NavigationRootCoordinator(\(rootCoordinator)"
} else { } else {
return "SingleScreenCoordinator(Empty)" return "NavigationRootCoordinator(Empty)"
} }
} }
@@ -0,0 +1,62 @@
//
// Copyright 2022 New Vector Ltd
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
import XCTest
extension XCUIElement {
func clearAndTypeText(_ text: String) {
let maxAttemptCount = 10
var attemptCount = 0
repeat {
tap()
guard let currentValue = value as? String else {
XCTFail("Tried to clear and type text into a non string value")
return
}
let deleteString = String(repeating: XCUIKeyboardKey.delete.rawValue, count: currentValue.count)
typeText(deleteString)
typeText(text)
if !exists { // Break if the element in question doesn't exist anymore
break
}
guard let newValue = value as? String else {
XCTFail("Tried to clear and type text into a non string value")
return
}
if newValue == String(repeating: "•", count: text.count) { // Secure entry text field
break
}
if newValue == text.trimmingCharacters(in: .whitespacesAndNewlines) {
break
}
attemptCount += 1
if attemptCount > maxAttemptCount {
XCTFail("Failed clearAndTypeText after \(maxAttemptCount) attempts.")
return
}
} while true
}
}
@@ -83,6 +83,7 @@ struct HomeScreenRoomCell: View {
context.send(viewAction: .loadRoomData(roomIdentifier: room.id)) context.send(viewAction: .loadRoomData(roomIdentifier: room.id))
} }
} }
.accessibilityIdentifier("roomName:\(room.name)")
} }
var lastMessageFont: Font { var lastMessageFont: Font {
@@ -20,7 +20,7 @@ import UIKit
/// /// UIKitBackgroundTaskService is a concrete implementation of BackgroundTaskServiceProtocol using a given `ApplicationProtocol` instance. /// /// UIKitBackgroundTaskService is a concrete implementation of BackgroundTaskServiceProtocol using a given `ApplicationProtocol` instance.
class UIKitBackgroundTaskService: BackgroundTaskServiceProtocol { class UIKitBackgroundTaskService: BackgroundTaskServiceProtocol {
private let applicationBlock: () -> ApplicationProtocol? private let applicationBlock: () -> ApplicationProtocol?
private var reusableTasks: WeakDictionary<String, UIKitBackgroundTask> = WeakDictionary() private var reusableTasks = NSMapTable<NSString, UIKitBackgroundTask>(keyOptions: .strongMemory, valueOptions: .weakMemory)
private var application: ApplicationProtocol? { private var application: ApplicationProtocol? {
applicationBlock() applicationBlock()
@@ -50,7 +50,7 @@ class UIKitBackgroundTaskService: BackgroundTaskServiceProtocol {
var result: BackgroundTaskProtocol? var result: BackgroundTaskProtocol?
if isReusable { if isReusable {
if let oldTask = reusableTasks[name], oldTask.isRunning { if let oldTask = reusableTasks.object(forKey: name as NSString), oldTask.isRunning {
oldTask.reuse() oldTask.reuse()
result = oldTask result = oldTask
} else { } else {
@@ -59,11 +59,11 @@ class UIKitBackgroundTaskService: BackgroundTaskServiceProtocol {
application: application, application: application,
expirationHandler: { [weak self] task in expirationHandler: { [weak self] task in
guard let self else { return } guard let self else { return }
self.reusableTasks[task.name] = nil self.reusableTasks.removeObject(forKey: task.name as NSString)
expirationHandler?() expirationHandler?()
}) { }) {
created = true created = true
reusableTasks[name] = newTask reusableTasks.setObject(newTask, forKey: name as NSString)
result = newTask result = newTask
} }
} }
@@ -41,7 +41,12 @@ class MockClientProxy: ClientProxyProtocol {
func restartSync() { } func restartSync() { }
func roomForIdentifier(_ identifier: String) async -> RoomProxyProtocol? { func roomForIdentifier(_ identifier: String) async -> RoomProxyProtocol? {
nil guard let room = roomSummaryProvider?.roomListPublisher.value.first(where: { $0.id == identifier }),
let displayName = room.asFilled?.name else {
return nil
}
return MockRoomProxy(displayName: displayName)
} }
func loadUserDisplayName() async -> Result<String, ClientProxyError> { func loadUserDisplayName() async -> Result<String, ClientProxyError> {
@@ -55,7 +55,7 @@ class MockRoomSummaryProvider: RoomSummaryProviderProtocol {
isDirect: true, isDirect: true,
avatarURLString: nil, avatarURLString: nil,
lastMessage: AttributedString("Prosciutto beef ribs pancetta filet mignon kevin hamburger, chuck ham venison picanha. Beef ribs chislic turkey biltong tenderloin."), lastMessage: AttributedString("Prosciutto beef ribs pancetta filet mignon kevin hamburger, chuck ham venison picanha. Beef ribs chislic turkey biltong tenderloin."),
lastMessageTimestamp: .now, lastMessageTimestamp: .distantPast,
unreadNotificationCount: 4)), unreadNotificationCount: 4)),
.filled(details: RoomSummaryDetails(id: "2", .filled(details: RoomSummaryDetails(id: "2",
name: "Second room", name: "Second room",
@@ -69,7 +69,7 @@ class MockRoomSummaryProvider: RoomSummaryProviderProtocol {
isDirect: true, isDirect: true,
avatarURLString: nil, avatarURLString: nil,
lastMessage: try? AttributedString(markdown: "**@mock:client.com**: T-bone beef ribs bacon"), lastMessage: try? AttributedString(markdown: "**@mock:client.com**: T-bone beef ribs bacon"),
lastMessageTimestamp: .now, lastMessageTimestamp: .distantPast,
unreadNotificationCount: 0)), unreadNotificationCount: 0)),
.empty(id: "3") .empty(id: "3")
] ]
@@ -0,0 +1,28 @@
//
// Copyright 2022 New Vector Ltd
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
import Foundation
struct MockRoomTimelineControllerFactory: RoomTimelineControllerFactoryProtocol {
func buildRoomTimelineController(userId: String,
roomProxy: RoomProxyProtocol,
timelineItemFactory: RoomTimelineItemFactoryProtocol,
mediaProvider: MediaProviderProtocol) -> RoomTimelineControllerProtocol {
let timelineController = MockRoomTimelineController()
timelineController.timelineItems = RoomTimelineItemFixtures.largeChunk
return timelineController
}
}
@@ -32,19 +32,20 @@ class RoomTimelineController: RoomTimelineControllerProtocol {
} }
} }
let roomId: String
let callbacks = PassthroughSubject<RoomTimelineControllerCallback, Never>() let callbacks = PassthroughSubject<RoomTimelineControllerCallback, Never>()
private(set) var timelineItems = [RoomTimelineItemProtocol]() private(set) var timelineItems = [RoomTimelineItemProtocol]()
var roomId: String {
roomProxy.id
}
init(userId: String, init(userId: String,
roomId: String, roomProxy: RoomProxyProtocol,
timelineProvider: RoomTimelineProviderProtocol, timelineProvider: RoomTimelineProviderProtocol,
timelineItemFactory: RoomTimelineItemFactoryProtocol, timelineItemFactory: RoomTimelineItemFactoryProtocol,
mediaProvider: MediaProviderProtocol, mediaProvider: MediaProviderProtocol) {
roomProxy: RoomProxyProtocol) {
self.userId = userId self.userId = userId
self.roomId = roomId
self.timelineProvider = timelineProvider self.timelineProvider = timelineProvider
self.timelineItemFactory = timelineItemFactory self.timelineItemFactory = timelineItemFactory
self.mediaProvider = mediaProvider self.mediaProvider = mediaProvider
@@ -0,0 +1,30 @@
//
// Copyright 2022 New Vector Ltd
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
import Foundation
struct RoomTimelineControllerFactory: RoomTimelineControllerFactoryProtocol {
func buildRoomTimelineController(userId: String,
roomProxy: RoomProxyProtocol,
timelineItemFactory: RoomTimelineItemFactoryProtocol,
mediaProvider: MediaProviderProtocol) -> RoomTimelineControllerProtocol {
RoomTimelineController(userId: userId,
roomProxy: roomProxy,
timelineProvider: RoomTimelineProvider(roomProxy: roomProxy),
timelineItemFactory: timelineItemFactory,
mediaProvider: mediaProvider)
}
}
@@ -14,20 +14,12 @@
// limitations under the License. // limitations under the License.
// //
import XCTest import Foundation
extension XCUIElement { @MainActor
func clearAndTypeText(_ text: String) { protocol RoomTimelineControllerFactoryProtocol {
guard let stringValue = value as? String else { func buildRoomTimelineController(userId: String,
XCTFail("Tried to clear and type text into a non string value") roomProxy: RoomProxyProtocol,
return timelineItemFactory: RoomTimelineItemFactoryProtocol,
} mediaProvider: MediaProviderProtocol) -> RoomTimelineControllerProtocol
tap()
let deleteString = String(repeating: XCUIKeyboardKey.delete.rawValue, count: stringValue.count)
typeText(deleteString)
typeText(text)
}
} }
@@ -26,6 +26,7 @@ class UserSessionFlowCoordinator: CoordinatorProtocol {
private let userSession: UserSessionProtocol private let userSession: UserSessionProtocol
private let navigationSplitCoordinator: NavigationSplitCoordinator private let navigationSplitCoordinator: NavigationSplitCoordinator
private let bugReportService: BugReportServiceProtocol private let bugReportService: BugReportServiceProtocol
private let roomTimelineControllerFactory: RoomTimelineControllerFactoryProtocol
private let emojiProvider: EmojiProviderProtocol = EmojiProvider() private let emojiProvider: EmojiProviderProtocol = EmojiProvider()
private let sidebarNavigationStackCoordinator: NavigationStackCoordinator private let sidebarNavigationStackCoordinator: NavigationStackCoordinator
@@ -33,11 +34,15 @@ class UserSessionFlowCoordinator: CoordinatorProtocol {
var callback: ((UserSessionFlowCoordinatorAction) -> Void)? var callback: ((UserSessionFlowCoordinatorAction) -> Void)?
init(userSession: UserSessionProtocol, navigationSplitCoordinator: NavigationSplitCoordinator, bugReportService: BugReportServiceProtocol) { init(userSession: UserSessionProtocol,
navigationSplitCoordinator: NavigationSplitCoordinator,
bugReportService: BugReportServiceProtocol,
roomTimelineControllerFactory: RoomTimelineControllerFactoryProtocol) {
stateMachine = UserSessionFlowCoordinatorStateMachine() stateMachine = UserSessionFlowCoordinatorStateMachine()
self.userSession = userSession self.userSession = userSession
self.navigationSplitCoordinator = navigationSplitCoordinator self.navigationSplitCoordinator = navigationSplitCoordinator
self.bugReportService = bugReportService self.bugReportService = bugReportService
self.roomTimelineControllerFactory = roomTimelineControllerFactory
sidebarNavigationStackCoordinator = NavigationStackCoordinator(navigationSplitCoordinator: navigationSplitCoordinator) sidebarNavigationStackCoordinator = NavigationStackCoordinator(navigationSplitCoordinator: navigationSplitCoordinator)
detailNavigationStackCoordinator = NavigationStackCoordinator(navigationSplitCoordinator: navigationSplitCoordinator) detailNavigationStackCoordinator = NavigationStackCoordinator(navigationSplitCoordinator: navigationSplitCoordinator)
@@ -150,13 +155,11 @@ class UserSessionFlowCoordinator: CoordinatorProtocol {
mediaProvider: userSession.mediaProvider, mediaProvider: userSession.mediaProvider,
roomProxy: roomProxy, roomProxy: roomProxy,
attributedStringBuilder: AttributedStringBuilder()) attributedStringBuilder: AttributedStringBuilder())
let timelineController = RoomTimelineController(userId: userId, let timelineController = roomTimelineControllerFactory.buildRoomTimelineController(userId: userId,
roomId: roomIdentifier, roomProxy: roomProxy,
timelineProvider: RoomTimelineProvider(roomProxy: roomProxy), timelineItemFactory: timelineItemFactory,
timelineItemFactory: timelineItemFactory, mediaProvider: userSession.mediaProvider)
mediaProvider: userSession.mediaProvider,
roomProxy: roomProxy)
let parameters = RoomScreenCoordinatorParameters(navigationStackCoordinator: detailNavigationStackCoordinator, let parameters = RoomScreenCoordinatorParameters(navigationStackCoordinator: detailNavigationStackCoordinator,
timelineController: timelineController, timelineController: timelineController,
@@ -36,6 +36,7 @@ enum UITestScreenIdentifier: String {
case roomSmallTimelineIncomingAndSmallPagination case roomSmallTimelineIncomingAndSmallPagination
case roomSmallTimelineLargePagination case roomSmallTimelineLargePagination
case sessionVerification case sessionVerification
case userSessionScreen
} }
extension UITestScreenIdentifier: CustomStringConvertible { extension UITestScreenIdentifier: CustomStringConvertible {
@@ -18,58 +18,64 @@ import SwiftUI
import UIKit import UIKit
class UITestsAppCoordinator: AppCoordinatorProtocol { class UITestsAppCoordinator: AppCoordinatorProtocol {
private var currentRootCoordinator: CoordinatorProtocol? private let navigationRootCoordinator: NavigationRootCoordinator
private let navigationStackCoordinator: NavigationStackCoordinator private var mockScreens: [MockScreen] = []
let notificationManager: NotificationManagerProtocol? = nil var notificationManager: NotificationManagerProtocol?
init() { init() {
UIView.setAnimationsEnabled(false) UIView.setAnimationsEnabled(false)
navigationStackCoordinator = NavigationStackCoordinator() navigationRootCoordinator = NavigationRootCoordinator()
mockScreens = UITestScreenIdentifier.allCases.map { MockScreen(id: $0, navigationRootCoordinator: navigationRootCoordinator) }
ServiceLocator.shared.register(userNotificationController: MockUserNotificationController()) ServiceLocator.shared.register(userNotificationController: MockUserNotificationController())
} }
func start() { func start() {
let screens = mockScreens() let rootCoordinator = UITestsRootCoordinator(mockScreens: mockScreens) { id in
let rootCoordinator = UITestsRootCoordinator(mockScreens: screens) { id in guard let screen = self.mockScreens.first(where: { $0.id == id }) else {
guard let screen = screens.first(where: { $0.id == id }) else {
fatalError() fatalError()
} }
// Store the initial coordinator so that it stays alive if drops it self.navigationRootCoordinator.setRootCoordinator(screen.coordinator)
// For example when replacing the root in the authentication flows
self.currentRootCoordinator = screen.coordinator
self.navigationStackCoordinator.setRootCoordinator(screen.coordinator)
} }
navigationStackCoordinator.setRootCoordinator(rootCoordinator) navigationRootCoordinator.setRootCoordinator(rootCoordinator)
Bundle.elementFallbackLanguage = "en" Bundle.elementFallbackLanguage = "en"
} }
func toPresentable() -> AnyView {
navigationStackCoordinator.toPresentable()
}
private func mockScreens() -> [MockScreen] { func toPresentable() -> AnyView {
UITestScreenIdentifier.allCases.map { MockScreen(id: $0, navigationStackCoordinator: navigationStackCoordinator) } navigationRootCoordinator.toPresentable()
} }
} }
@MainActor @MainActor
class MockScreen: Identifiable { class MockScreen: Identifiable {
let id: UITestScreenIdentifier let id: UITestScreenIdentifier
let navigationStackCoordinator: NavigationStackCoordinator
private let navigationRootCoordinator: NavigationRootCoordinator
private var retainedState = [Any]()
init(id: UITestScreenIdentifier, navigationRootCoordinator: NavigationRootCoordinator) {
self.id = id
self.navigationRootCoordinator = navigationRootCoordinator
}
lazy var coordinator: CoordinatorProtocol = { lazy var coordinator: CoordinatorProtocol = {
switch id { switch id {
case .login: case .login:
return LoginCoordinator(parameters: .init(authenticationService: MockAuthenticationServiceProxy(), let navigationStackCoordinator = NavigationStackCoordinator()
navigationStackCoordinator: navigationStackCoordinator)) let coordinator = LoginCoordinator(parameters: .init(authenticationService: MockAuthenticationServiceProxy(),
navigationStackCoordinator: navigationStackCoordinator))
navigationStackCoordinator.setRootCoordinator(coordinator)
return navigationStackCoordinator
case .serverSelection: case .serverSelection:
return ServerSelectionCoordinator(parameters: .init(authenticationService: MockAuthenticationServiceProxy(), let navigationStackCoordinator = NavigationStackCoordinator()
userNotificationController: MockUserNotificationController(), let coordinator = ServerSelectionCoordinator(parameters: .init(authenticationService: MockAuthenticationServiceProxy(),
isModallyPresented: true)) userNotificationController: MockUserNotificationController(),
isModallyPresented: true))
navigationStackCoordinator.setRootCoordinator(coordinator)
return navigationStackCoordinator
case .serverSelectionNonModal: case .serverSelectionNonModal:
return ServerSelectionCoordinator(parameters: .init(authenticationService: MockAuthenticationServiceProxy(), return ServerSelectionCoordinator(parameters: .init(authenticationService: MockAuthenticationServiceProxy(),
userNotificationController: MockUserNotificationController(), userNotificationController: MockUserNotificationController(),
@@ -78,8 +84,12 @@ class MockScreen: Identifiable {
return AnalyticsPromptCoordinator(parameters: .init(userSession: MockUserSession(clientProxy: MockClientProxy(userIdentifier: "@mock:client.com"), return AnalyticsPromptCoordinator(parameters: .init(userSession: MockUserSession(clientProxy: MockClientProxy(userIdentifier: "@mock:client.com"),
mediaProvider: MockMediaProvider()))) mediaProvider: MockMediaProvider())))
case .authenticationFlow: case .authenticationFlow:
return AuthenticationCoordinator(authenticationService: MockAuthenticationServiceProxy(), let navigationStackCoordinator = NavigationStackCoordinator()
navigationStackCoordinator: navigationStackCoordinator) let coordinator = AuthenticationCoordinator(authenticationService: MockAuthenticationServiceProxy(),
navigationStackCoordinator: navigationStackCoordinator)
retainedState.append(coordinator)
navigationStackCoordinator.setRootCoordinator(coordinator)
return navigationStackCoordinator
case .softLogout: case .softLogout:
let credentials = SoftLogoutCredentials(userId: "@mock:matrix.org", let credentials = SoftLogoutCredentials(userId: "@mock:matrix.org",
homeserverName: "matrix.org", homeserverName: "matrix.org",
@@ -93,47 +103,66 @@ class MockScreen: Identifiable {
case .simpleUpgrade: case .simpleUpgrade:
return TemplateCoordinator(parameters: .init(promptType: .upgrade)) return TemplateCoordinator(parameters: .init(promptType: .upgrade))
case .home: case .home:
let navigationStackCoordinator = NavigationStackCoordinator()
let session = MockUserSession(clientProxy: MockClientProxy(userIdentifier: "@mock:matrix.org"), let session = MockUserSession(clientProxy: MockClientProxy(userIdentifier: "@mock:matrix.org"),
mediaProvider: MockMediaProvider()) mediaProvider: MockMediaProvider())
return HomeScreenCoordinator(parameters: .init(userSession: session, let coordinator = HomeScreenCoordinator(parameters: .init(userSession: session,
attributedStringBuilder: AttributedStringBuilder(), attributedStringBuilder: AttributedStringBuilder(),
bugReportService: MockBugReportService(), bugReportService: MockBugReportService(),
navigationStackCoordinator: navigationStackCoordinator)) navigationStackCoordinator: navigationStackCoordinator))
navigationStackCoordinator.setRootCoordinator(coordinator)
return navigationStackCoordinator
case .settings: case .settings:
return SettingsCoordinator(parameters: .init(navigationStackCoordinator: navigationStackCoordinator, let navigationStackCoordinator = NavigationStackCoordinator()
userNotificationController: MockUserNotificationController(), let coordinator = SettingsCoordinator(parameters: .init(navigationStackCoordinator: navigationStackCoordinator,
userSession: MockUserSession(clientProxy: MockClientProxy(userIdentifier: "@mock:client.com"), userNotificationController: MockUserNotificationController(),
mediaProvider: MockMediaProvider()), userSession: MockUserSession(clientProxy: MockClientProxy(userIdentifier: "@mock:client.com"),
bugReportService: MockBugReportService())) mediaProvider: MockMediaProvider()),
bugReportService: MockBugReportService()))
navigationStackCoordinator.setRootCoordinator(coordinator)
return navigationStackCoordinator
case .bugReport: case .bugReport:
return BugReportCoordinator(parameters: .init(bugReportService: MockBugReportService(), let navigationStackCoordinator = NavigationStackCoordinator()
userNotificationController: MockUserNotificationController(), let coordinator = BugReportCoordinator(parameters: .init(bugReportService: MockBugReportService(),
screenshot: nil, userNotificationController: MockUserNotificationController(),
isModallyPresented: false)) screenshot: nil,
isModallyPresented: true))
navigationStackCoordinator.setRootCoordinator(coordinator)
return navigationStackCoordinator
case .bugReportWithScreenshot: case .bugReportWithScreenshot:
return BugReportCoordinator(parameters: .init(bugReportService: MockBugReportService(), let navigationStackCoordinator = NavigationStackCoordinator()
userNotificationController: MockUserNotificationController(), let coordinator = BugReportCoordinator(parameters: .init(bugReportService: MockBugReportService(),
screenshot: Asset.Images.appLogo.image, userNotificationController: MockUserNotificationController(),
isModallyPresented: false)) screenshot: Asset.Images.appLogo.image,
isModallyPresented: false))
navigationStackCoordinator.setRootCoordinator(coordinator)
return navigationStackCoordinator
case .onboarding: case .onboarding:
return OnboardingCoordinator() return OnboardingCoordinator()
case .roomPlainNoAvatar: case .roomPlainNoAvatar:
let navigationStackCoordinator = NavigationStackCoordinator()
let parameters = RoomScreenCoordinatorParameters(navigationStackCoordinator: navigationStackCoordinator, let parameters = RoomScreenCoordinatorParameters(navigationStackCoordinator: navigationStackCoordinator,
timelineController: MockRoomTimelineController(), timelineController: MockRoomTimelineController(),
mediaProvider: MockMediaProvider(), mediaProvider: MockMediaProvider(),
roomName: "Some room name", roomName: "Some room name",
roomAvatarUrl: nil, roomAvatarUrl: nil,
emojiProvider: EmojiProvider()) emojiProvider: EmojiProvider())
return RoomScreenCoordinator(parameters: parameters) let coordinator = RoomScreenCoordinator(parameters: parameters)
navigationStackCoordinator.setRootCoordinator(coordinator)
return navigationStackCoordinator
case .roomEncryptedWithAvatar: case .roomEncryptedWithAvatar:
let navigationStackCoordinator = NavigationStackCoordinator()
let parameters = RoomScreenCoordinatorParameters(navigationStackCoordinator: navigationStackCoordinator, let parameters = RoomScreenCoordinatorParameters(navigationStackCoordinator: navigationStackCoordinator,
timelineController: MockRoomTimelineController(), timelineController: MockRoomTimelineController(),
mediaProvider: MockMediaProvider(), mediaProvider: MockMediaProvider(),
roomName: "Some room name", roomName: "Some room name",
roomAvatarUrl: "mock_url", roomAvatarUrl: "mock_url",
emojiProvider: EmojiProvider()) emojiProvider: EmojiProvider())
return RoomScreenCoordinator(parameters: parameters) let coordinator = RoomScreenCoordinator(parameters: parameters)
navigationStackCoordinator.setRootCoordinator(coordinator)
return navigationStackCoordinator
case .roomSmallTimeline: case .roomSmallTimeline:
let navigationStackCoordinator = NavigationStackCoordinator()
let timelineController = MockRoomTimelineController() let timelineController = MockRoomTimelineController()
timelineController.timelineItems = RoomTimelineItemFixtures.smallChunk timelineController.timelineItems = RoomTimelineItemFixtures.smallChunk
let parameters = RoomScreenCoordinatorParameters(navigationStackCoordinator: navigationStackCoordinator, let parameters = RoomScreenCoordinatorParameters(navigationStackCoordinator: navigationStackCoordinator,
@@ -142,8 +171,12 @@ class MockScreen: Identifiable {
roomName: "New room", roomName: "New room",
roomAvatarUrl: "mock_url", roomAvatarUrl: "mock_url",
emojiProvider: EmojiProvider()) emojiProvider: EmojiProvider())
return RoomScreenCoordinator(parameters: parameters) let coordinator = RoomScreenCoordinator(parameters: parameters)
navigationStackCoordinator.setRootCoordinator(coordinator)
return navigationStackCoordinator
case .roomSmallTimelineIncomingAndSmallPagination: case .roomSmallTimelineIncomingAndSmallPagination:
let navigationStackCoordinator = NavigationStackCoordinator()
let timelineController = MockRoomTimelineController() let timelineController = MockRoomTimelineController()
timelineController.timelineItems = RoomTimelineItemFixtures.smallChunk timelineController.timelineItems = RoomTimelineItemFixtures.smallChunk
timelineController.backPaginationResponses = [RoomTimelineItemFixtures.singleMessageChunk] timelineController.backPaginationResponses = [RoomTimelineItemFixtures.singleMessageChunk]
@@ -155,8 +188,13 @@ class MockScreen: Identifiable {
roomName: "Small timeline", roomName: "Small timeline",
roomAvatarUrl: "mock_url", roomAvatarUrl: "mock_url",
emojiProvider: EmojiProvider()) emojiProvider: EmojiProvider())
return RoomScreenCoordinator(parameters: parameters) let coordinator = RoomScreenCoordinator(parameters: parameters)
navigationStackCoordinator.setRootCoordinator(coordinator)
return navigationStackCoordinator
case .roomSmallTimelineLargePagination: case .roomSmallTimelineLargePagination:
let navigationStackCoordinator = NavigationStackCoordinator()
let timelineController = MockRoomTimelineController() let timelineController = MockRoomTimelineController()
timelineController.timelineItems = RoomTimelineItemFixtures.smallChunk timelineController.timelineItems = RoomTimelineItemFixtures.smallChunk
timelineController.backPaginationResponses = [RoomTimelineItemFixtures.largeChunk] timelineController.backPaginationResponses = [RoomTimelineItemFixtures.largeChunk]
@@ -166,15 +204,28 @@ class MockScreen: Identifiable {
roomName: "Small timeline, paginating", roomName: "Small timeline, paginating",
roomAvatarUrl: "mock_url", roomAvatarUrl: "mock_url",
emojiProvider: EmojiProvider()) emojiProvider: EmojiProvider())
return RoomScreenCoordinator(parameters: parameters) let coordinator = RoomScreenCoordinator(parameters: parameters)
navigationStackCoordinator.setRootCoordinator(coordinator)
return navigationStackCoordinator
case .sessionVerification: case .sessionVerification:
let parameters = SessionVerificationCoordinatorParameters(sessionVerificationControllerProxy: MockSessionVerificationControllerProxy()) let parameters = SessionVerificationCoordinatorParameters(sessionVerificationControllerProxy: MockSessionVerificationControllerProxy())
return SessionVerificationCoordinator(parameters: parameters) return SessionVerificationCoordinator(parameters: parameters)
case .userSessionScreen:
let navigationSplitCoordinator = NavigationSplitCoordinator(placeholderCoordinator: SplashScreenCoordinator())
let clientProxy = MockClientProxy(userIdentifier: "@mock:client.com", roomSummaryProvider: MockRoomSummaryProvider(state: .loaded))
let coordinator = UserSessionFlowCoordinator(userSession: MockUserSession(clientProxy: clientProxy, mediaProvider: MockMediaProvider()),
navigationSplitCoordinator: navigationSplitCoordinator,
bugReportService: MockBugReportService(),
roomTimelineControllerFactory: MockRoomTimelineControllerFactory())
coordinator.start()
retainedState.append(coordinator)
return navigationSplitCoordinator
} }
}() }()
init(id: UITestScreenIdentifier, navigationStackCoordinator: NavigationStackCoordinator) {
self.id = id
self.navigationStackCoordinator = navigationStackCoordinator
}
} }
@@ -31,8 +31,7 @@ struct UITestsRootCoordinator: CoordinatorProtocol {
} }
.accessibilityIdentifier(coordinator.id.rawValue) .accessibilityIdentifier(coordinator.id.rawValue)
} }
.padding(.top, 50) // Add some top padding so the iPad split screen button isn't tapped by mistake
.listStyle(.plain) .listStyle(.plain)
.navigationTitle("Screens")
.navigationViewStyle(.stack)
} }
} }
-21
View File
@@ -1,21 +0,0 @@
MIT License
Copyright (c) 2016 Nicholas Cross
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
-1
View File
@@ -1 +0,0 @@
Files copied over from [nicholascross/WeakDictionary](https://github.com/nicholascross/WeakDictionary) because of a lack SPM support.
@@ -1,116 +0,0 @@
// MIT License
//
// Copyright (c) 2016 Nicholas Cross
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
import Foundation
public struct WeakDictionary<Key: Hashable, Value: AnyObject> {
private var storage: [Key: WeakDictionaryReference<Value>]
public init() {
self.init(storage: [Key: WeakDictionaryReference<Value>]())
}
public init(dictionary: [Key: Value]) {
var newStorage = [Key: WeakDictionaryReference<Value>]()
dictionary.forEach { key, value in newStorage[key] = WeakDictionaryReference<Value>(value: value) }
self.init(storage: newStorage)
}
private init(storage: [Key: WeakDictionaryReference<Value>]) {
self.storage = storage
}
public mutating func reap() {
storage = weakDictionary().storage
}
public func weakDictionary() -> WeakDictionary<Key, Value> {
self[startIndex..<endIndex]
}
public func dictionary() -> [Key: Value] {
var newStorage = [Key: Value]()
storage.forEach { key, value in
if let retainedValue = value.value {
newStorage[key] = retainedValue
}
}
return newStorage
}
}
extension WeakDictionary: Collection {
public typealias Index = DictionaryIndex<Key, WeakDictionaryReference<Value>>
public var startIndex: Index {
storage.startIndex
}
public var endIndex: Index {
storage.endIndex
}
public func index(after index: Index) -> Index {
storage.index(after: index)
}
public subscript(position: Index) -> (Key, WeakDictionaryReference<Value>) {
return storage[position]
}
public subscript(key: Key) -> Value? {
get {
guard let valueRef = storage[key] else {
return nil
}
return valueRef.value
}
set {
guard let value = newValue else {
storage[key] = nil
return
}
storage[key] = WeakDictionaryReference<Value>(value: value)
}
}
public subscript(bounds: Range<Index>) -> WeakDictionary<Key, Value> {
let subStorage = storage[bounds.lowerBound..<bounds.upperBound]
var newStorage = [Key: WeakDictionaryReference<Value>]()
subStorage.filter { _, value in value.value != nil }
.forEach { key, value in newStorage[key] = value }
return WeakDictionary<Key, Value>(storage: newStorage)
}
}
public extension Dictionary where Value: AnyObject {
func weakDictionary() -> WeakDictionary<Key, Value> {
WeakDictionary<Key, Value>(dictionary: self)
}
}
@@ -1,53 +0,0 @@
// MIT License
//
// Copyright (c) 2016 Nicholas Cross
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
import Foundation
public struct WeakDictionaryKey<Key: AnyObject & Hashable, Value: AnyObject>: Hashable {
private weak var baseKey: Key?
private let hash: Int
private var retainedValue: Value?
private let nilKeyHash = UUID().hashValue
public init(key: Key, value: Value? = nil) {
baseKey = key
retainedValue = value
hash = key.hashValue
}
public static func == (lhs: WeakDictionaryKey, rhs: WeakDictionaryKey) -> Bool {
(lhs.baseKey != nil && rhs.baseKey != nil && lhs.baseKey == rhs.baseKey)
|| lhs.hashValue == rhs.hashValue
}
public func hash(into hasher: inout Hasher) {
if baseKey == nil {
hasher.combine(nilKeyHash)
} else {
hasher.combine(baseKey)
}
}
public var key: Key? {
baseKey
}
}
@@ -1,35 +0,0 @@
// MIT License
//
// Copyright (c) 2016 Nicholas Cross
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
import Foundation
public struct WeakDictionaryReference<Value: AnyObject> {
private weak var referencedValue: Value?
init(value: Value) {
referencedValue = value
}
public var value: Value? {
referencedValue
}
}
@@ -1,136 +0,0 @@
// MIT License
//
// Copyright (c) 2016 Nicholas Cross
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
import Foundation
public struct WeakKeyDictionary<Key: AnyObject & Hashable, Value: AnyObject> {
private var storage: WeakDictionary<WeakDictionaryKey<Key, Value>, Value>
private let valuesRetainedByKey: Bool
public init(valuesRetainedByKey: Bool = false) {
self.init(
storage: WeakDictionary<WeakDictionaryKey<Key, Value>, Value>(),
valuesRetainedByKey: valuesRetainedByKey
)
}
public init(dictionary: [Key: Value], valuesRetainedByKey: Bool = false) {
var newStorage = WeakDictionary<WeakDictionaryKey<Key, Value>, Value>()
dictionary.forEach { key, value in
var keyRef: WeakDictionaryKey<Key, Value>!
if valuesRetainedByKey {
keyRef = WeakDictionaryKey<Key, Value>(key: key, value: value)
} else {
keyRef = WeakDictionaryKey<Key, Value>(key: key)
}
newStorage[keyRef] = value
}
self.init(storage: newStorage, valuesRetainedByKey: valuesRetainedByKey)
}
private init(storage: WeakDictionary<WeakDictionaryKey<Key, Value>, Value>, valuesRetainedByKey: Bool = false) {
self.storage = storage
self.valuesRetainedByKey = valuesRetainedByKey
}
public mutating func reap() {
storage = weakKeyDictionary().storage
}
public func weakDictionary() -> WeakDictionary<Key, Value> {
dictionary().weakDictionary()
}
public func weakKeyDictionary() -> WeakKeyDictionary<Key, Value> {
self[startIndex..<endIndex]
}
public func dictionary() -> [Key: Value] {
var newStorage = [Key: Value]()
storage.forEach { key, value in
if let retainedKey = key.key, let retainedValue = value.value {
newStorage[retainedKey] = retainedValue
}
}
return newStorage
}
}
extension WeakKeyDictionary: Collection {
public typealias Index = DictionaryIndex<WeakDictionaryKey<Key, Value>, WeakDictionaryReference<Value>>
public var startIndex: Index {
storage.startIndex
}
public var endIndex: Index {
storage.endIndex
}
public func index(after index: Index) -> Index {
storage.index(after: index)
}
public subscript(position: Index) -> (WeakDictionaryKey<Key, Value>, WeakDictionaryReference<Value>) {
return storage[position]
}
public subscript(key: Key) -> Value? {
get {
storage[WeakDictionaryKey<Key, Value>(key: key)]
}
set {
let retainedValue = valuesRetainedByKey ? newValue : nil
let weakKey = WeakDictionaryKey<Key, Value>(key: key, value: retainedValue)
storage[weakKey] = newValue
}
}
public subscript(bounds: Range<Index>) -> WeakKeyDictionary<Key, Value> {
let subStorage = storage[bounds.lowerBound..<bounds.upperBound]
var newStorage = WeakDictionary<WeakDictionaryKey<Key, Value>, Value>()
subStorage.filter { key, value in key.key != nil && value.value != nil }
.forEach { key, value in newStorage[key] = value.value }
return WeakKeyDictionary<Key, Value>(storage: newStorage)
}
}
public extension WeakDictionary where Key: AnyObject {
func weakKeyDictionary(valuesRetainedByKey: Bool = false) -> WeakKeyDictionary<Key, Value> {
WeakKeyDictionary<Key, Value>(dictionary: dictionary(), valuesRetainedByKey: valuesRetainedByKey)
}
}
public extension Dictionary where Key: AnyObject, Value: AnyObject {
func weakKeyDictionary(valuesRetainedByKey: Bool = false) -> WeakKeyDictionary<Key, Value> {
WeakKeyDictionary<Key, Value>(dictionary: self, valuesRetainedByKey: valuesRetainedByKey)
}
}
+1 -1
View File
@@ -128,7 +128,7 @@ targets:
sources: sources:
- path: ../Sources - path: ../Sources
excludes: excludes:
- Screens/Templates - Other/Extensions/XCUIElement.swift
- path: ../Resources - path: ../Resources
- path: ../SupportingFiles - path: ../SupportingFiles
- path: ../../Tools/Scripts/Templates/SimpleScreenExample/ElementX - path: ../../Tools/Scripts/Templates/SimpleScreenExample/ElementX
@@ -31,7 +31,7 @@ class ApplicationTests: XCTestCase {
return return
} }
let expectedDuration = 4.0 let expectedDuration = 5.0
XCTAssertLessThanOrEqual(actualDuration, expectedDuration) XCTAssertLessThanOrEqual(actualDuration, expectedDuration)
} }
} }
+8 -5
View File
@@ -17,7 +17,7 @@
import XCTest import XCTest
class LoginTests: XCTestCase { class LoginTests: XCTestCase {
let expectedDuration = 30.0 let expectedDuration = 32.0
func testLoginFlow() throws { func testLoginFlow() throws {
let parser = TestMeasurementParser() let parser = TestMeasurementParser()
@@ -52,6 +52,11 @@ class LoginTests: XCTestCase {
homeserverTextField.clearAndTypeText(app.homeserver) homeserverTextField.clearAndTypeText(app.homeserver)
let slidingSyncTextField = app.textFields["slidingSyncProxyAddressTextField"]
XCTAssertTrue(slidingSyncTextField.waitForExistence(timeout: 5.0))
slidingSyncTextField.clearAndTypeText(app.homeserver)
let confirmButton = app.buttons["confirmButton"] let confirmButton = app.buttons["confirmButton"]
XCTAssertTrue(confirmButton.exists) XCTAssertTrue(confirmButton.exists)
confirmButton.tap() confirmButton.tap()
@@ -59,14 +64,12 @@ class LoginTests: XCTestCase {
let usernameTextField = app.textFields["usernameTextField"] let usernameTextField = app.textFields["usernameTextField"]
XCTAssertTrue(usernameTextField.exists) XCTAssertTrue(usernameTextField.exists)
usernameTextField.tap() usernameTextField.clearAndTypeText(app.username)
usernameTextField.typeText(app.username)
let passwordTextField = app.secureTextFields["passwordTextField"] let passwordTextField = app.secureTextFields["passwordTextField"]
XCTAssertTrue(passwordTextField.exists) XCTAssertTrue(passwordTextField.exists)
passwordTextField.tap() passwordTextField.clearAndTypeText(app.password)
passwordTextField.typeText(app.password)
let nextButton = app.buttons["nextButton"] let nextButton = app.buttons["nextButton"]
XCTAssertTrue(nextButton.exists) XCTAssertTrue(nextButton.exists)
@@ -57,3 +57,4 @@ targets:
sources: sources:
- path: ../Sources - path: ../Sources
- path: ../SupportingFiles - path: ../SupportingFiles
- path: ../../ElementX/Sources/Other/Extensions/XCUIElement.swift
+8 -3
View File
@@ -41,10 +41,15 @@ extension XCUIApplication {
/// Assert screenshot for a screen with the given identifier. Does not fail if a screenshot is newly created. /// Assert screenshot for a screen with the given identifier. Does not fail if a screenshot is newly created.
/// - Parameter identifier: Identifier of the UI test screen /// - Parameter identifier: Identifier of the UI test screen
func assertScreenshot(_ identifier: UITestScreenIdentifier) { func assertScreenshot(_ identifier: UITestScreenIdentifier, step: Int? = nil) {
let failure = verifySnapshot(matching: screenshot().image, var snapshotName = identifier.rawValue
if let step {
snapshotName += "-\(step)"
}
let failure = verifySnapshot(matching: XCUIScreen.main.screenshot().image,
as: .image(precision: 0.99, perceptualPrecision: 0.98, scale: nil), as: .image(precision: 0.99, perceptualPrecision: 0.98, scale: nil),
named: identifier.rawValue, named: snapshotName,
testName: testName) testName: testName)
if let failure, if let failure,
@@ -29,10 +29,9 @@ class AuthenticationCoordinatorUITests: XCTestCase {
app.buttons["getStartedButton"].tap() app.buttons["getStartedButton"].tap()
// Login Screen: Enter valid credentials // Login Screen: Enter valid credentials
app.textFields["usernameTextField"].tap()
app.typeText("alice\n") app.textFields["usernameTextField"].clearAndTypeText("alice\n")
app.secureTextFields["passwordTextField"].tap() app.secureTextFields["passwordTextField"].clearAndTypeText("12345678")
app.typeText("12345678")
app.assertScreenshot(.authenticationFlow) app.assertScreenshot(.authenticationFlow)
@@ -52,10 +51,8 @@ class AuthenticationCoordinatorUITests: XCTestCase {
app.buttons["getStartedButton"].tap() app.buttons["getStartedButton"].tap()
// Login Screen: Enter invalid credentials // Login Screen: Enter invalid credentials
app.textFields["usernameTextField"].tap() app.textFields["usernameTextField"].clearAndTypeText("alice")
app.typeText("alice") app.secureTextFields["passwordTextField"].clearAndTypeText("87654321")
app.secureTextFields["passwordTextField"].tap()
app.typeText("87654321")
// Login Screen: Tap next // Login Screen: Tap next
let nextButton = app.buttons["nextButton"] let nextButton = app.buttons["nextButton"]
@@ -80,9 +77,7 @@ class AuthenticationCoordinatorUITests: XCTestCase {
app.buttons["editServerButton"].tap() app.buttons["editServerButton"].tap()
// Server Selection: Clear the default and enter OIDC server. // Server Selection: Clear the default and enter OIDC server.
app.textFields["addressTextField"].tap() app.textFields["addressTextField"].clearAndTypeText("company.com")
app.textFields["addressTextField"].buttons.element.tap()
app.typeText("company.com")
// Dismiss server screen. // Dismiss server screen.
app.buttons["confirmButton"].tap() app.buttons["confirmButton"].tap()
+2 -4
View File
@@ -46,13 +46,11 @@ class BugReportUITests: XCTestCase {
app.goToScreenWithIdentifier(.bugReport) app.goToScreenWithIdentifier(.bugReport)
// type 4 chars // type 4 chars
app.textViews["reportTextView"].tap() app.textViews["reportTextView"].clearAndTypeText("Text")
app.textViews["reportTextView"].typeText("Test")
XCTAssertFalse(app.buttons["sendButton"].isEnabled) XCTAssertFalse(app.buttons["sendButton"].isEnabled)
// type one more char and see the button enabled // type one more char and see the button enabled
app.textViews["reportTextView"].tap() app.textViews["reportTextView"].clearAndTypeText("Longer text")
app.textViews["reportTextView"].typeText("-")
XCTAssert(app.buttons["sendButton"].isEnabled) XCTAssert(app.buttons["sendButton"].isEnabled)
} }
+4 -8
View File
@@ -40,11 +40,9 @@ class LoginScreenUITests: XCTestCase {
app.assertScreenshot(.login) app.assertScreenshot(.login)
// When typing in a username and password. // When typing in a username and password.
app.textFields.element.tap() app.textFields.element.clearAndTypeText("@test:matrix.org")
app.typeText("@test:matrix.org")
app.secureTextFields.element.tap() app.secureTextFields.element.clearAndTypeText("12345678")
app.typeText("12345678")
// Then the form should be ready to submit. // Then the form should be ready to submit.
validateNextButtonIsEnabled(for: "matrix.org with credentials entered") validateNextButtonIsEnabled(for: "matrix.org with credentials entered")
@@ -56,8 +54,7 @@ class LoginScreenUITests: XCTestCase {
app.goToScreenWithIdentifier(.login) app.goToScreenWithIdentifier(.login)
// When entering a username on a homeserver that only supports OIDC. // When entering a username on a homeserver that only supports OIDC.
app.textFields.element.tap() app.textFields.element.clearAndTypeText("@test:company.com\n")
app.typeText("@test:company.com\n")
// Then the screen should be configured for OIDC. // Then the screen should be configured for OIDC.
let state = "an OIDC only server" let state = "an OIDC only server"
@@ -72,8 +69,7 @@ class LoginScreenUITests: XCTestCase {
app.goToScreenWithIdentifier(.login) app.goToScreenWithIdentifier(.login)
// When entering a username on a homeserver with an unsupported flow. // When entering a username on a homeserver with an unsupported flow.
app.textFields.element.tap() app.textFields.element.clearAndTypeText("@test:server.net\n")
app.typeText("@test:server.net\n")
// Then the screen should not allow login to continue. // Then the screen should not allow login to continue.
let state = "an unsupported server" let state = "an unsupported server"
+1 -3
View File
@@ -66,9 +66,7 @@ class ServerSelectionUITests: XCTestCase {
app.goToScreenWithIdentifier(.serverSelection) app.goToScreenWithIdentifier(.serverSelection)
// When typing in an invalid homeserver // When typing in an invalid homeserver
app.textFields[textFieldIdentifier].tap() app.textFields[textFieldIdentifier].clearAndTypeText("thisisbad\n") // The tests only accept an address from LoginHomeserver.mockXYZ
app.textFields.element.buttons.element.tap()
app.typeText("thisisbad\n") // The tests only accept an address from LoginHomeserver.mockXYZ
// Then an error should be shown and the confirmation button disabled. // Then an error should be shown and the confirmation button disabled.
XCTAssertEqual(app.textFields[textFieldIdentifier].value as? String, "thisisbad", "The text field should show the entered server.") XCTAssertEqual(app.textFields[textFieldIdentifier].value as? String, "thisisbad", "The text field should show the entered server.")
@@ -0,0 +1,38 @@
//
// Copyright 2022 New Vector Ltd
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
import ElementX
import XCTest
@MainActor
class UserSessionScreenTests: XCTestCase {
func testUserSessionFlows() async throws {
let roomName = "First room"
let app = Application.launch()
app.goToScreenWithIdentifier(.userSessionScreen)
app.assertScreenshot(.userSessionScreen, step: 1)
app.buttons["roomName:\(roomName)"].tap()
XCTAssert(app.staticTexts[roomName].exists)
try await Task.sleep(for: .seconds(1))
app.assertScreenshot(.userSessionScreen, step: 2)
}
}
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1 version https://git-lfs.github.com/spec/v1
oid sha256:6b5fb88d76d9d6b0c2ab6f9f96d80cac1cb41cfa7e938b2cf9746553c7ef55fc oid sha256:9902bf55f027c729fd31b790d875699bf4a2e0f2852b9ceb2178c84bc8aca226
size 208681 size 211684
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1 version https://git-lfs.github.com/spec/v1
oid sha256:ce6df94c886ae302976ab1748fc000fdaf535a8178b5415f9e44f87f2c5677a7 oid sha256:1fbf57e59072a7e06026a69a0858ed9f65a72e0bfa4fabdf4de6a28e1bc4b364
size 208028 size 211052
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1 version https://git-lfs.github.com/spec/v1
oid sha256:9c957491840909920efbb8b445cecb039e0cfe50127918bace68d34bcf1b0501 oid sha256:27d058762e6eafc940c71b8e4edeef26f6ccad34e086ad6a0f0a30252848485f
size 101235 size 93290
@@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:d90a2dd77853c9707a2805b480983dc46d92d1606e22a61ff18ad12a0cb70228
size 123022
@@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:89c5cd9ca5283ec107581a2e45b3f904fad92119848eb9bd7d8c3c7295802a75
size 334531
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1 version https://git-lfs.github.com/spec/v1
oid sha256:0305582dd212396d3443d10e675a5e2dcb9e964e6543acb0033d4f58e3c66be6 oid sha256:dd603c2e38d5281190788cfa06425a512587fbb49a32d5d895361533ab48419a
size 296035 size 373824
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1 version https://git-lfs.github.com/spec/v1
oid sha256:5beeaa7dea7a8d7cc8e6acb8928dd2b72fda9caa8a03e79d230e8a31392be58c oid sha256:066c66947a2d47092dde8db56d885cd62127f24a817a06198e2ab0d29fa61857
size 295025 size 371508
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1 version https://git-lfs.github.com/spec/v1
oid sha256:ed05c76fb48fb1440ae419caed6833c3d25858513b85417d19921cac444cc781 oid sha256:97980472cdf36a0d07109fc066bd8184013b0a99cbbd164e82dbfb0a20cbc09f
size 125722 size 115670
@@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:3de2e5153d1b685c253df7f20d91a5355015fae183f4882315c56fe4eede0889
size 112151
@@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:6aaa8bf274c693ca1fd3dffd4fbeab41df2698e401bb1c16f9bd6190d694a0df
size 334188
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1 version https://git-lfs.github.com/spec/v1
oid sha256:ba9218275999d949200c620d5019bb03e99935081a70c6e7151217b1787e9ccb oid sha256:0a34acc9936b4fbff9aad17617ee77dd8c89356d652b2a7132f5bb7d20c4f715
size 207960 size 210981
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1 version https://git-lfs.github.com/spec/v1
oid sha256:82b057602fc6b76294eed9232a9fa9f5b9f8348bff50ba5cdd05a9299674b1dc oid sha256:ec8c0bdbf78d2bd1019cd8319aed419fd729be3d8be566b729d171cc21adec8b
size 207307 size 210340
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1 version https://git-lfs.github.com/spec/v1
oid sha256:a5bafccc43ded94082a5182afe1af60e3a17f0d943ac981c704f313914eaa640 oid sha256:cbbb771047c24948ad5b38308273fc1262667bdaafcf0bac61704b3186f66f1d
size 101898 size 93992
@@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:25ba24b61f830ca4a975957059dd912f587a06436e9bc1899a01bec845e4125c
size 123049
@@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:df9c30fd83057e62b3ac28d820bae1ad17e520270e21ef1a4c1429a181877ee4
size 334367
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1 version https://git-lfs.github.com/spec/v1
oid sha256:74b59a7a3f639eefa579333d77e301c4fb417889846b82c828242bcb87822ecc oid sha256:f7322585bdb968fa0ad5244e5ca05401e7b32e3c27a0e3b1abb4f74f2cc736f9
size 295099 size 372873
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1 version https://git-lfs.github.com/spec/v1
oid sha256:ade4638eba012fdae7d0b60dd92b634a2dce225f4e24d52e53abf7617838a9ef oid sha256:bf8edaf502cb0a8ea89699280a31ef2a8505b2107fb67d81975b9a63813bdd2e
size 294155 size 370584
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1 version https://git-lfs.github.com/spec/v1
oid sha256:4fdad77450c1fdf345f2c8f94fd36148f984819bb5e99f0079e72d9efaa03e34 oid sha256:063feeb819831472533b47c11eb8a69924843fea616ef3f56651274fd8f970c9
size 125447 size 115397
@@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:7b31c6c701af4e18f3bee3e28ce2d43044934f9a16dfb8726dadc233a616a27e
size 112187
@@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:d340ed581bb489d166f6d358cde52fd1a5c735faba60fb921bc71fc68489ef3d
size 334229
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1 version https://git-lfs.github.com/spec/v1
oid sha256:df627a68a56f879f53298d8af24e6c66cf8cbf77745c94a50e365fce7f1f8922 oid sha256:aa4dc34fbb2b7412232fb048d1ddde465f949784bc4e9af0374d7cae490a5dd3
size 208173 size 211181
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1 version https://git-lfs.github.com/spec/v1
oid sha256:58ac026654258e9713f5f5877f35de33e117c54405ec40aa90c4328414eeac79 oid sha256:ca335bfdc0d02a56eb7584e9f18004361abcb0365c30733861bbd20b7a385b3b
size 207519 size 210546
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1 version https://git-lfs.github.com/spec/v1
oid sha256:c20831ac18ee32022faf98abe3866d67581a3b466ed9eb7ceaa20bff6dfc9ec5 oid sha256:df1a88376fa6e083729329fcf221093c4704d900de8acc40600a61b7fd812a2c
size 102302 size 94430
@@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:a1713e05e0292fcd03384f297d171fe9f7494c4ca7d82c65bff68c490a5cf398
size 124142
@@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:48524ce3e3adfbb8cf6db5d24af0ab50a188daf015cbab033fcecc6eeafd8439
size 335408
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1 version https://git-lfs.github.com/spec/v1
oid sha256:6170f6628637496185cd3d89509735bd91ecc9a00e6e9e449e79d4f09f19fc96 oid sha256:794a4b78bd5e5cda370bfac8168d19951ef5005c5d9267d372b9b55c9accfa4b
size 295475 size 373232
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1 version https://git-lfs.github.com/spec/v1
oid sha256:e4da4a01c13823486548c8e24926e7cae5f3e779597c39aaaddd57393c743c7a oid sha256:39a5f3d31a13112058a4b4c3d0b83066ff1e3a546b65e82234970b76748812ed
size 294447 size 370940
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1 version https://git-lfs.github.com/spec/v1
oid sha256:b643263191776badaf326c825ed53af855836443b9ec9dbede5e9ee6063bafac oid sha256:d4b3f25e56c50b01e3ce87c4bd0537e752664e23b7b761a5bdb1e2b88ed4dc35
size 127431 size 117371
@@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:dfbeb2402f34533a88a49185d5642188fe38821a090e6e34ad550b413b5fa912
size 116841
@@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:04ab9dbb2bb167bbe6d4b8a6c9c392477b8b387f79313f0a9ecdc099ef7c0f97
size 339899
+1
View File
@@ -68,3 +68,4 @@ targets:
- path: ../../ElementX/Sources/Other/Extensions/FileManager.swift - path: ../../ElementX/Sources/Other/Extensions/FileManager.swift
- path: ../../ElementX/Sources/Other/InfoPlistReader.swift - path: ../../ElementX/Sources/Other/InfoPlistReader.swift
- path: ../../ElementX/Sources/Other/Extensions/URL.swift - path: ../../ElementX/Sources/Other/Extensions/URL.swift
- path: ../../ElementX/Sources/Other/Extensions/XCUIElement.swift