#106: Add Analytics UI

This commit is contained in:
Doug 2022-09-02 10:49:59 +01:00 committed by Doug
parent df68174a32
commit 8e46d0e3d6
26 changed files with 1437 additions and 85 deletions

View File

@ -26,7 +26,7 @@
072BA9DBA932374CCA300125 /* MessageComposerTextField.swift in Sources */ = {isa = PBXBuildFile; fileRef = BE6C10032A77AE7DC5AA4C50 /* MessageComposerTextField.swift */; };
0B1F80C2BF7D223159FBA82C /* ImageAnonymizerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6045E825AE900A92D61FEFF0 /* ImageAnonymizerTests.swift */; };
0C38C3E771B472E27295339D /* SessionVerificationModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = E4BB9A17AC512A7EF4B106E5 /* SessionVerificationModels.swift */; };
0E8C480700870BB34A2A360F /* DTCoreText in Frameworks */ = {isa = PBXBuildFile; productRef = 36B7FC232711031AA2B0D188 /* DTCoreText */; };
0E8C480700870BB34A2A360F /* AppAuth in Frameworks */ = {isa = PBXBuildFile; productRef = 4346F63D53A346271577FD9C /* AppAuth */; };
0EA6537A07E2DC882AEA5962 /* Localizable.stringsdict in Resources */ = {isa = PBXBuildFile; fileRef = 187853A7E643995EE49FAD43 /* Localizable.stringsdict */; };
0ED951768EC443A8728DE1D7 /* TimelineStyle.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8DC2C9E0E15C79BBDA80F0A2 /* TimelineStyle.swift */; };
0EE5EBA18BA1FE10254BB489 /* UIFont+AttributedStringBuilder.m in Sources */ = {isa = PBXBuildFile; fileRef = E8CA187FE656EE5A3F6C7DE5 /* UIFont+AttributedStringBuilder.m */; };
@ -66,9 +66,9 @@
290FDB0FFDC2F1DDF660343E /* TestMeasurementParser.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9C4048041C1A6B20CB97FD18 /* TestMeasurementParser.swift */; };
297CD0A27C87B0C50FF192EE /* RoomTimelineViewFactoryProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = EEE384418EB1FEDFA62C9CD0 /* RoomTimelineViewFactoryProtocol.swift */; };
29AEE68A604940180AB9EBFF /* MockRoomSummary.swift in Sources */ = {isa = PBXBuildFile; fileRef = B6BDAC8895AB2B77B47703AE /* MockRoomSummary.swift */; };
29EE1791E0AFA1ABB7F23D2F /* GZIP in Frameworks */ = {isa = PBXBuildFile; productRef = 1BCD21310B997A6837B854D6 /* GZIP */; };
29EE1791E0AFA1ABB7F23D2F /* SwiftyBeaver in Frameworks */ = {isa = PBXBuildFile; productRef = A981A4CA233FB5C13B9CA690 /* SwiftyBeaver */; };
2A90D9F91A836E30B7D78838 /* MXLogObjcWrapper.m in Sources */ = {isa = PBXBuildFile; fileRef = 54E438DBCBDC7A41B95DDDD9 /* MXLogObjcWrapper.m */; };
2BA59D0AEFB4B82A2EC2A326 /* Introspect in Frameworks */ = {isa = PBXBuildFile; productRef = 04C28663564E008DB32B5972 /* Introspect */; };
2BA59D0AEFB4B82A2EC2A326 /* Kingfisher in Frameworks */ = {isa = PBXBuildFile; productRef = 50009897F60FAE7D63EF5E5B /* Kingfisher */; };
2BAA5B222856068158D0B3C6 /* MatrixRustSDK in Frameworks */ = {isa = PBXBuildFile; productRef = B1E8B697DF78FE7F61FC6CA4 /* MatrixRustSDK */; };
2C0CE61E5DC177938618E0B1 /* RootRouterType.swift in Sources */ = {isa = PBXBuildFile; fileRef = 90733775209F4D4D366A268F /* RootRouterType.swift */; };
2E59008365E01F0AFB3A6B24 /* ImageRoomMessage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8BF686BA36D0C2FA3C63DFDF /* ImageRoomMessage.swift */; };
@ -81,7 +81,7 @@
3097A0A867D2B19CE32DAE58 /* UIKitBackgroundTaskService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3DF1FFC3336EB23374BBBFCC /* UIKitBackgroundTaskService.swift */; };
313382FC5D38064EAAA35CB2 /* FileManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = A8D1CC633517D695FEC54208 /* FileManager.swift */; };
33B4E59D408AE6E02323EE41 /* NoticeRoomMessage.swift in Sources */ = {isa = PBXBuildFile; fileRef = CBDA364DFFC3AC71C4771251 /* NoticeRoomMessage.swift */; };
33CAC1226DFB8B5D8447D286 /* Sentry in Frameworks */ = {isa = PBXBuildFile; productRef = 67E7A6F388D3BF85767609D9 /* Sentry */; };
33CAC1226DFB8B5D8447D286 /* SwiftState in Frameworks */ = {isa = PBXBuildFile; productRef = 3853B78FB8531B83936C5DA6 /* SwiftState */; };
344AF4CBB6D8786214878642 /* NavigationRouterStoreProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B9D5F812E5AD6DC786DBC9B /* NavigationRouterStoreProtocol.swift */; };
34966D4C1C2C6D37FE3F7F50 /* SettingsCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3DD2D50A7EAA4FC78417730E /* SettingsCoordinator.swift */; };
352C439BE0F75E101EF11FB1 /* RoomScreenModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = C2886615BEBAE33A0AA4D5F8 /* RoomScreenModels.swift */; };
@ -92,6 +92,7 @@
38546A6010A2CF240EC9AF73 /* BindableState.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6EA1D2CBAEA5D0BD00B90D1B /* BindableState.swift */; };
388FD50AC66E9E684DDFA9D8 /* ServerSelectionScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = E5D2C0950F8196232D88045C /* ServerSelectionScreen.swift */; };
38C76D586404C1FDED095F3A /* LoginModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = 31B01468022EC826CB2FD2C0 /* LoginModels.swift */; };
3A64A93A651A3CB8774ADE8E /* SnapshotTesting in Frameworks */ = {isa = PBXBuildFile; productRef = 21C83087604B154AA30E9A8F /* SnapshotTesting */; };
3B770CB4DED51CC362C66D47 /* SettingsModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4990FDBDA96B88E214F92F48 /* SettingsModels.swift */; };
3C549A0BF39F8A854D45D9FD /* PostHog in Frameworks */ = {isa = PBXBuildFile; productRef = 4278261E147DB2DE5CFB7FC5 /* PostHog */; };
3C73442084BF8A6939F0F80B /* AnalyticsService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5445FCE0CE15E634FDC1A2E2 /* AnalyticsService.swift */; };
@ -108,7 +109,7 @@
46562110EE202E580A5FFD9C /* RoomScreenViewModelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 93CF7B19FFCF8EFBE0A8696A /* RoomScreenViewModelTests.swift */; };
4669804D0369FBED4E8625D1 /* ToastViewPresenter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4470B8CB654B097D807AA713 /* ToastViewPresenter.swift */; };
490E606044B18985055FF690 /* SettingsUITests.swift in Sources */ = {isa = PBXBuildFile; fileRef = E3E29F98CF0E960689A410E3 /* SettingsUITests.swift */; };
492274DA6691EE985C2FCCAA /* SnapshotTesting in Frameworks */ = {isa = PBXBuildFile; productRef = 21C83087604B154AA30E9A8F /* SnapshotTesting */; };
492274DA6691EE985C2FCCAA /* GZIP in Frameworks */ = {isa = PBXBuildFile; productRef = 1BCD21310B997A6837B854D6 /* GZIP */; };
499A26EB06C97E48C27A2DB9 /* BuildSettings.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3F87116470221880017CF522 /* BuildSettings.swift */; };
49E9B99CB6A275C7744351F0 /* LoginViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = F2D58333B377888012740101 /* LoginViewModel.swift */; };
49F2E7DD8CAACE09CEECE3E6 /* SeparatorRoomTimelineView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6390A6DC140CA3D6865A66FF /* SeparatorRoomTimelineView.swift */; };
@ -147,7 +148,7 @@
6647430A45B4A8E692909A8F /* EmoteRoomTimelineItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = F77C060C2ACC4CB7336A29E7 /* EmoteRoomTimelineItem.swift */; };
67C05C50AD734283374605E3 /* MatrixEntityRegex.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6AD1A853D605C2146B0DC028 /* MatrixEntityRegex.swift */; };
67E391A2E00709FB41903B36 /* MockMediaProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6920A4869821BF72FFC58842 /* MockMediaProvider.swift */; };
6832733838C57A7D3FE8FEB5 /* Kingfisher in Frameworks */ = {isa = PBXBuildFile; productRef = 50009897F60FAE7D63EF5E5B /* Kingfisher */; };
6832733838C57A7D3FE8FEB5 /* KeychainAccess in Frameworks */ = {isa = PBXBuildFile; productRef = 78A5A8DE1E2B09C978C7F3B0 /* KeychainAccess */; };
684BDE198AE5AA1392288A73 /* SplashScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = 32CE6D4FF64C9A3C18619224 /* SplashScreen.swift */; };
68AC3C84E2B438036B174E30 /* EmoteRoomTimelineView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 471EB7D96AFEA8D787659686 /* EmoteRoomTimelineView.swift */; };
69BCBB4FB2DC3D61A28D3FD8 /* TimelineStyle.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8DC2C9E0E15C79BBDA80F0A2 /* TimelineStyle.swift */; };
@ -162,6 +163,7 @@
706F79A39BDB32F592B8C2C7 /* UIKitBackgroundTask.swift in Sources */ = {isa = PBXBuildFile; fileRef = 92FCD9116ADDE820E4E30F92 /* UIKitBackgroundTask.swift */; };
72F6E890820FF606A7E276C8 /* SplashScreenPageView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 24A534A4619D8FEFB6439FCC /* SplashScreenPageView.swift */; };
7405B4824D45BA7C3D943E76 /* Application.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7D0CBC76C80E04345E11F2DB /* Application.swift */; };
744C029EB6C43429926A0499 /* AnalyticsPromptViewModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = C9A86C95340248A8B7BA9A43 /* AnalyticsPromptViewModelProtocol.swift */; };
74604ACFDBE7F54260E7B617 /* ApplicationProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = A8903A9F615BBD0E6D7CD133 /* ApplicationProtocol.swift */; };
755727E0B756430DFFEC4732 /* SessionVerificationViewModelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = DF05DA24F71B455E8EFEBC3B /* SessionVerificationViewModelTests.swift */; };
758BF44CA565AB0AB84F2185 /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = 7109E709A7738E6BCC4553E6 /* Localizable.strings */; };
@ -185,6 +187,7 @@
7F61F9ACD5EC9E845EF3EFBF /* BugReportServiceTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = EFFD3200F9960D4996159F10 /* BugReportServiceTests.swift */; };
7FA4227B2BAAA71560252866 /* UserIndicatorDismissal.swift in Sources */ = {isa = PBXBuildFile; fileRef = B1D1532B5D9FB0C8461A1453 /* UserIndicatorDismissal.swift */; };
7FED310F6AB7A70CBFB7C8A3 /* SettingsScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = C483956FA3D665E3842E319A /* SettingsScreen.swift */; };
8024BE37156FF0A95A7A3465 /* AnalyticsPromptUITests.swift in Sources */ = {isa = PBXBuildFile; fileRef = AF11DD57D9FACF2A757AB024 /* AnalyticsPromptUITests.swift */; };
80E04BE80A89A78FBB4863BB /* UserIndicatorViewPresentable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 193FB285430D3956B6E61E4D /* UserIndicatorViewPresentable.swift */; };
83E5054739949181CA981193 /* LoginCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD667C4BB98CF4F3FE2CE3B0 /* LoginCoordinator.swift */; };
85AFBB433AD56704A880F8A0 /* FramePreferenceKey.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4798B3B7A1E8AE3901CEE8C6 /* FramePreferenceKey.swift */; };
@ -212,9 +215,10 @@
97189E495F0E47805D1868DB /* KeychainAccess in Frameworks */ = {isa = PBXBuildFile; productRef = 2B43F2AF7456567FE37270A7 /* KeychainAccess */; };
9738F894DB1BD383BE05767A /* ElementSettings.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1027BB9A852F445B7623897F /* ElementSettings.swift */; };
978BB24F2A5D31EE59EEC249 /* UserSessionProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5F4134FEFE4EB55759017408 /* UserSessionProtocol.swift */; };
97CECF91D68235F1D13598D7 /* AnalyticsConfiguration.swift in Sources */ = {isa = PBXBuildFile; fileRef = D77B3D4950F1707E66E4A45A /* AnalyticsConfiguration.swift */; };
989029A28C9E2F828AD6658A /* AppIcon.pdf in Resources */ = {isa = PBXBuildFile; fileRef = 16DC8C5B2991724903F1FA6A /* AppIcon.pdf */; };
992F5E750F5030C4BA2D0D03 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 01C4C7DB37597D7D8379511A /* Assets.xcassets */; };
99ED42B8F8D6BFB1DBCF4C45 /* AppAuth in Frameworks */ = {isa = PBXBuildFile; productRef = 4346F63D53A346271577FD9C /* AppAuth */; };
99ED42B8F8D6BFB1DBCF4C45 /* AnalyticsEvents in Frameworks */ = {isa = PBXBuildFile; productRef = D661CAB418C075A94306A792 /* AnalyticsEvents */; };
9AC5F8142413862A9E3A2D98 /* Kingfisher in Frameworks */ = {isa = PBXBuildFile; productRef = 0DD568A494247444A4B56031 /* Kingfisher */; };
9B8DE1D424E37581C7D99CCC /* RoomTimelineControllerProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = CC7CCC6DE5FA623E31BA8546 /* RoomTimelineControllerProtocol.swift */; };
9BD3A773186291560DF92B62 /* RoomTimelineProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 66F2402D738694F98729A441 /* RoomTimelineProvider.swift */; };
@ -230,11 +234,12 @@
A0A0D2A9564BDA3FDE2E360F /* FormattedBodyText.swift in Sources */ = {isa = PBXBuildFile; fileRef = F73FF1A33198F5FAE9D34B1F /* FormattedBodyText.swift */; };
A32517FB1CA0BBCE2BC75249 /* BugReportCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = AD6C07DA7D3FF193F7419F55 /* BugReportCoordinator.swift */; };
A371629728E597C5FCA3C2B2 /* Analytics.swift in Sources */ = {isa = PBXBuildFile; fileRef = 73FC861755C6388F62B9280A /* Analytics.swift */; };
A4E885358D7DD5A072A06824 /* SwiftState in Frameworks */ = {isa = PBXBuildFile; productRef = 3853B78FB8531B83936C5DA6 /* SwiftState */; };
A4E885358D7DD5A072A06824 /* PostHog in Frameworks */ = {isa = PBXBuildFile; productRef = CCE5BF78B125320CBF3BB834 /* PostHog */; };
A50849766F056FD1DB942DEA /* AlertInfo.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2EEB64CC6F3DF5B68736A6B4 /* AlertInfo.swift */; };
A5C8F013ED9FB8AA6FEE18A7 /* InfoPlist.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6A901D95158B02CA96C79C7F /* InfoPlist.swift */; };
A5EC21A071F58FC1229C20D0 /* MemberDetailsProviderProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 09747989908EC5E4AA29F844 /* MemberDetailsProviderProtocol.swift */; };
A636D4900E0D98ED91536482 /* AppCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = CF3EDF23226895776553F04A /* AppCoordinator.swift */; };
A663FE6704CB500EBE782AE1 /* AnalyticsPromptCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = B4DE1CF8F5EFD353B1A5E36F /* AnalyticsPromptCoordinator.swift */; };
A6DEC1ADEC8FEEC206A0FA37 /* AttributedStringBuilderProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 72F37B5DA798C9AE436F2C2C /* AttributedStringBuilderProtocol.swift */; };
A7D48E44D485B143AADDB77D /* Strings+Untranslated.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1A18F6CE4D694D21E4EA9B25 /* Strings+Untranslated.swift */; };
A851635B3255C6DC07034A12 /* RoomScreenCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = B8108C8F0ACF6A7EB72D0117 /* RoomScreenCoordinator.swift */; };
@ -245,16 +250,18 @@
ABF3FAB234AD3565B214309B /* TimelineSenderAvatarView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0BC588051E6572A1AF51D738 /* TimelineSenderAvatarView.swift */; };
ACF094CF3BF02DBFA6DFDE60 /* AuthenticationCoordinatorUITests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5D2D0A6F1ABC99D29462FB84 /* AuthenticationCoordinatorUITests.swift */; };
B037C365CF8A58A0D149A2DB /* AuthenticationIconImage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 97755C01C3971474EFAD5367 /* AuthenticationIconImage.swift */; };
B245583C63F8F90357B87FAE /* SwiftyBeaver in Frameworks */ = {isa = PBXBuildFile; productRef = A981A4CA233FB5C13B9CA690 /* SwiftyBeaver */; };
B245583C63F8F90357B87FAE /* Introspect in Frameworks */ = {isa = PBXBuildFile; productRef = 04C28663564E008DB32B5972 /* Introspect */; };
B3357B00F1AA930E54F76609 /* Strings.swift in Sources */ = {isa = PBXBuildFile; fileRef = 47EBB5D698CE9A25BB553A2D /* Strings.swift */; };
B3FDB1D9CF40777695DBBD1D /* AppCoordinatorStateMachine.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5A9AB74614131D6706894E0C /* AppCoordinatorStateMachine.swift */; };
B4AAB3257A83B73F53FB2689 /* StateStoreViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6F3DFE5B444F131648066F05 /* StateStoreViewModel.swift */; };
B5111BAF5F601C139EBBD8BB /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 01C4C7DB37597D7D8379511A /* Assets.xcassets */; };
B6DA66EFC13A90846B625836 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 91DE43B8815918E590912DDA /* InfoPlist.strings */; };
B6DF6B6FA8734B70F9BF261E /* BlurHashDecode.swift in Sources */ = {isa = PBXBuildFile; fileRef = E5272BC4A60B6AD7553BACA1 /* BlurHashDecode.swift */; };
B6F92EBE04D4AABF30B9E73A /* AnalyticsPromptModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = AA8BA82CF99D843FEF680E91 /* AnalyticsPromptModels.swift */; };
B80C4FABB5529DF12436FFDA /* AppIcon.pdf in Resources */ = {isa = PBXBuildFile; fileRef = 16DC8C5B2991724903F1FA6A /* AppIcon.pdf */; };
B94368839BDB69172E28E245 /* MXLog.swift in Sources */ = {isa = PBXBuildFile; fileRef = 111B698739E3410E2CDB7144 /* MXLog.swift */; };
BB01CC19C3D3322308D1B2CF /* ServerSelectionViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 167521635A1CC27624FCEB7F /* ServerSelectionViewModel.swift */; };
BB4C6F362F75933DDDE30F3E /* InfoPlist.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6A901D95158B02CA96C79C7F /* InfoPlist.swift */; };
BB6B0B91CE11E06330017000 /* SessionVerificationScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8AC1A01C3A745BDF1D3697D3 /* SessionVerificationScreen.swift */; };
BCC3EDB7AD0902797CB4BBC2 /* MXLogger.m in Sources */ = {isa = PBXBuildFile; fileRef = EF188681D6B6068CFAEAFC3F /* MXLogger.m */; };
BCEC41FB1F2BB663183863E4 /* LoginServerInfoSection.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7D379E13DD9D987470A3C70C /* LoginServerInfoSection.swift */; };
@ -267,10 +274,11 @@
C4F69156C31A447FEFF2A47C /* DTHTMLElement+AttributedStringBuilder.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1E508AB0EDEE017FF4F6F8D1 /* DTHTMLElement+AttributedStringBuilder.swift */; };
C55A44C99F64A479ABA85B46 /* RoomScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5221DFDF809142A2D6AC82B9 /* RoomScreen.swift */; };
C76892321558E75101E68ED6 /* ReadableFrameModifier.swift in Sources */ = {isa = PBXBuildFile; fileRef = 398817652FA8ABAE0A31AC6D /* ReadableFrameModifier.swift */; };
C7B251DC896C0867C51B616D /* AnalyticsPrompt.swift in Sources */ = {isa = PBXBuildFile; fileRef = 541542F5AC323709D8563458 /* AnalyticsPrompt.swift */; };
C7CFDB4929DDD9A3B5BA085D /* BugReportViewModelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7AB7ED3A898B07976F3AA90F /* BugReportViewModelTests.swift */; };
CB137BFB3E083C33E398A6CB /* Introspect in Frameworks */ = {isa = PBXBuildFile; productRef = 5986E300FC849DEAB2EE7AEB /* Introspect */; };
CB326BAB54E9B68658909E36 /* Benchmark.swift in Sources */ = {isa = PBXBuildFile; fileRef = 49EAD710A2C16EFF7C3EA16F /* Benchmark.swift */; };
CB498F4E27AA0545DCEF0F6F /* KeychainAccess in Frameworks */ = {isa = PBXBuildFile; productRef = 78A5A8DE1E2B09C978C7F3B0 /* KeychainAccess */; };
CB498F4E27AA0545DCEF0F6F /* DTCoreText in Frameworks */ = {isa = PBXBuildFile; productRef = 36B7FC232711031AA2B0D188 /* DTCoreText */; };
CC736DA1AA8F8B9FD8785009 /* ScreenshotDetector.swift in Sources */ = {isa = PBXBuildFile; fileRef = F5C4AF6E3885730CD560311C /* ScreenshotDetector.swift */; };
CD6A72B65D3B6076F4045C30 /* PHGPostHogConfiguration.swift in Sources */ = {isa = PBXBuildFile; fileRef = A6B891A6DA826E2461DBB40F /* PHGPostHogConfiguration.swift */; };
CE1694C7BB93C3311524EF28 /* Untranslated.strings in Resources */ = {isa = PBXBuildFile; fileRef = D2F7194F440375338F8E2487 /* Untranslated.strings */; };
@ -293,9 +301,11 @@
DE4F8C4E0F1DB4832F09DE97 /* HomeScreenViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 31D6764D6976D235926FE5FC /* HomeScreenViewModel.swift */; };
DF504B10A4918F971A57BEF2 /* PostHogAnalyticsClient.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1715E3D7F53C0748AA50C91C /* PostHogAnalyticsClient.swift */; };
DFF7D6A6C26DDD40D00AE579 /* target.yml in Resources */ = {isa = PBXBuildFile; fileRef = F012CB5EE3F2B67359F6CC52 /* target.yml */; };
E01373F2043E76393A0CE073 /* AnalyticsPromptViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = A11B74ACE8D71747E1044A9C /* AnalyticsPromptViewModel.swift */; };
E0A4DCA633D174EB43AD599F /* BackgroundTaskProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2CA028DCD4157F9A1F999827 /* BackgroundTaskProtocol.swift */; };
E1DF24D085572A55C9758A2D /* Bundle.swift in Sources */ = {isa = PBXBuildFile; fileRef = B6E89E530A8E92EC44301CA1 /* Bundle.swift */; };
E3CA565A4B9704F191B191F0 /* JoinedRoomSize+MemberCount.swift in Sources */ = {isa = PBXBuildFile; fileRef = CBF9AEA706926DD0DA2B954C /* JoinedRoomSize+MemberCount.swift */; };
E47CD939D8480657D4B706C6 /* AnalyticsPromptCheckmarkItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = BA7B2E9CC5DC3B76ADC35A43 /* AnalyticsPromptCheckmarkItem.swift */; };
E481C8FDCB6C089963C95344 /* DTCoreText in Frameworks */ = {isa = PBXBuildFile; productRef = 527578916BD388A09F5A8036 /* DTCoreText */; };
E5895C74615CBE8462FB840F /* SessionVerificationCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = CCF86010A0A719A9A50EEC59 /* SessionVerificationCoordinator.swift */; };
E81EEC1675F2371D12A880A3 /* MockRoomTimelineController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 61ADFB893DEF81E58DF3FAB9 /* MockRoomTimelineController.swift */; };
@ -310,6 +320,7 @@
EEC40663922856C65D1E0DF5 /* KeychainControllerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = FDB9C37196A4C79F24CE80C6 /* KeychainControllerTests.swift */; };
EF99A92701E401C4CD5ADC50 /* SplashScreenModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = DCE978A6118C131D7F2A04B3 /* SplashScreenModels.swift */; };
F040ABFEB0A2B142D948BA12 /* Untranslated.stringsdict in Resources */ = {isa = PBXBuildFile; fileRef = F75DF9500D69A3AAF8339E69 /* Untranslated.stringsdict */; };
F0F82C3C848C865C3098AA52 /* Sentry in Frameworks */ = {isa = PBXBuildFile; productRef = 67E7A6F388D3BF85767609D9 /* Sentry */; };
F2DD8661B5C0BA2BB526FA6C /* KeychainControllerProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0CD51F9FDC91C231906D76C8 /* KeychainControllerProtocol.swift */; };
F4C3FEDB1B3A05376A1723A3 /* KeychainController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3A4427F9E0571B4E6E048A2B /* KeychainController.swift */; };
F508683B76EF7B23BB2CBD6D /* TimelineItemPlainStylerView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 94BCC8A9C73C1F838122C645 /* TimelineItemPlainStylerView.swift */; };
@ -492,6 +503,7 @@
529513218340CC8419273165 /* tr */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = tr; path = tr.lproj/Localizable.strings; 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>"; };
541542F5AC323709D8563458 /* AnalyticsPrompt.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AnalyticsPrompt.swift; sourceTree = "<group>"; };
5445FCE0CE15E634FDC1A2E2 /* AnalyticsService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AnalyticsService.swift; sourceTree = "<group>"; };
54E438DBCBDC7A41B95DDDD9 /* MXLogObjcWrapper.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MXLogObjcWrapper.m; sourceTree = "<group>"; };
55BC11560C8A2598964FFA4C /* bs */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = bs; path = bs.lproj/Localizable.strings; sourceTree = "<group>"; };
@ -616,6 +628,7 @@
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>"; };
A0A20AE75FF4FF35B1FF6CA7 /* MockServerSelectionScreenState.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MockServerSelectionScreenState.swift; sourceTree = "<group>"; };
A11B74ACE8D71747E1044A9C /* AnalyticsPromptViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AnalyticsPromptViewModel.swift; sourceTree = "<group>"; };
A1C22B1B5FA3A765EADB2CC9 /* SessionVerificationStateMachineTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SessionVerificationStateMachineTests.swift; sourceTree = "<group>"; };
A1ED7E89865201EE7D53E6DA /* SeparatorRoomTimelineItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SeparatorRoomTimelineItem.swift; sourceTree = "<group>"; };
A2B6433F516F1E6DFA0E2D89 /* vls */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = vls; path = vls.lproj/Localizable.strings; sourceTree = "<group>"; };
@ -631,6 +644,7 @@
A8D1CC633517D695FEC54208 /* FileManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FileManager.swift; sourceTree = "<group>"; };
A9873374E72AA53260AE90A2 /* fa */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = fa; path = fa.lproj/Localizable.strings; sourceTree = "<group>"; };
AA19C32BD97F45847724E09A /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/Untranslated.strings; sourceTree = "<group>"; };
AA8BA82CF99D843FEF680E91 /* AnalyticsPromptModels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AnalyticsPromptModels.swift; sourceTree = "<group>"; };
AAC9344689121887B74877AF /* UnitTests.xctest */ = {isa = PBXFileReference; includeInIndex = 0; lastKnownFileType = wrapper.cfbundle; path = UnitTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
AACE9B8E1A4AE79A7E2914F6 /* es */ = {isa = PBXFileReference; lastKnownFileType = text.plist.stringsdict; name = es; path = es.lproj/Localizable.stringsdict; sourceTree = "<group>"; };
AAE73D571D4F9C36DD45255A /* BackgroundTaskServiceProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BackgroundTaskServiceProtocol.swift; sourceTree = "<group>"; };
@ -642,6 +656,7 @@
AE225C66978648AA4AF37B45 /* te */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = te; path = te.lproj/Localizable.strings; sourceTree = "<group>"; };
AE5DDBEBBA17973ED4638823 /* de */ = {isa = PBXFileReference; lastKnownFileType = text.plist.stringsdict; name = de; path = de.lproj/Localizable.stringsdict; sourceTree = "<group>"; };
AF05352F28D4E7336228E9F4 /* ActivityIndicatorView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ActivityIndicatorView.swift; sourceTree = "<group>"; };
AF11DD57D9FACF2A757AB024 /* AnalyticsPromptUITests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AnalyticsPromptUITests.swift; sourceTree = "<group>"; };
AF25E364AE85090A70AE4644 /* AttributedStringBuilderTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AttributedStringBuilderTests.swift; sourceTree = "<group>"; };
AFABDF2E19D349DAAAC18C65 /* RoundedToastView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoundedToastView.swift; sourceTree = "<group>"; };
B08CBE1E670690ECF11C2C6A /* eu */ = {isa = PBXFileReference; lastKnownFileType = text.plist.stringsdict; name = eu; path = eu.lproj/Localizable.stringsdict; sourceTree = "<group>"; };
@ -653,6 +668,7 @@
B4173A48FD8542CD4AD3645C /* NavigationRouter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NavigationRouter.swift; sourceTree = "<group>"; };
B43AF03660F5FD4FFFA7F1CE /* TimelineItemContextMenu.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TimelineItemContextMenu.swift; sourceTree = "<group>"; };
B4C18FAAD59AE7F1462D817E /* SessionVerificationViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SessionVerificationViewModel.swift; sourceTree = "<group>"; };
B4DE1CF8F5EFD353B1A5E36F /* AnalyticsPromptCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AnalyticsPromptCoordinator.swift; sourceTree = "<group>"; };
B516212D9FE785DDD5E490D1 /* BugReportModels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BugReportModels.swift; sourceTree = "<group>"; };
B5B243E7818E5E9F6A4EDC7A /* NoticeRoomTimelineView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NoticeRoomTimelineView.swift; sourceTree = "<group>"; };
B64F3A3D0DF86ED5A241AB05 /* ActivityIndicatorView.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = ActivityIndicatorView.xib; sourceTree = "<group>"; };
@ -666,6 +682,7 @@
B83CB897B183BF3C33715F55 /* bn-IN */ = {isa = PBXFileReference; lastKnownFileType = text.plist.stringsdict; name = "bn-IN"; path = "bn-IN.lproj/Localizable.stringsdict"; sourceTree = "<group>"; };
B8A56EA2A5AE726F445CB2E3 /* eo */ = {isa = PBXFileReference; lastKnownFileType = text.plist.stringsdict; name = eo; path = eo.lproj/Localizable.stringsdict; sourceTree = "<group>"; };
B902EA6CD3296B0E10EE432B /* HomeScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HomeScreen.swift; sourceTree = "<group>"; };
BA7B2E9CC5DC3B76ADC35A43 /* AnalyticsPromptCheckmarkItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AnalyticsPromptCheckmarkItem.swift; sourceTree = "<group>"; };
BB3073CCD77D906B330BC1D6 /* Tests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Tests.swift; sourceTree = "<group>"; };
BC9B05D6B293A039EB963CA7 /* az */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = az; path = az.lproj/Localizable.strings; sourceTree = "<group>"; };
BE6C10032A77AE7DC5AA4C50 /* MessageComposerTextField.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MessageComposerTextField.swift; sourceTree = "<group>"; };
@ -684,6 +701,7 @@
C888BCD78E2A55DCE364F160 /* MediaProviderProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MediaProviderProtocol.swift; sourceTree = "<group>"; };
C91A6BC1A54CDB598EE2A81B /* UserIndicatorQueue.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserIndicatorQueue.swift; sourceTree = "<group>"; };
C95ADE8D9527523572532219 /* hu */ = {isa = PBXFileReference; lastKnownFileType = text.plist.stringsdict; name = hu; path = hu.lproj/Localizable.stringsdict; sourceTree = "<group>"; };
C9A86C95340248A8B7BA9A43 /* AnalyticsPromptViewModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AnalyticsPromptViewModelProtocol.swift; sourceTree = "<group>"; };
C9F395A2E917115C7AAF7F34 /* SplashViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SplashViewController.swift; sourceTree = "<group>"; };
CAAE4A709C0A2144C103AA0F /* ang */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ang; path = ang.lproj/Localizable.strings; sourceTree = "<group>"; };
CACA846B3E3E9A521D98B178 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/Localizable.strings; sourceTree = "<group>"; };
@ -787,16 +805,18 @@
buildActionMask = 2147483647;
files = (
2BAA5B222856068158D0B3C6 /* MatrixRustSDK in Frameworks */,
99ED42B8F8D6BFB1DBCF4C45 /* AppAuth in Frameworks */,
0E8C480700870BB34A2A360F /* DTCoreText in Frameworks */,
CB498F4E27AA0545DCEF0F6F /* KeychainAccess in Frameworks */,
6832733838C57A7D3FE8FEB5 /* Kingfisher in Frameworks */,
2BA59D0AEFB4B82A2EC2A326 /* Introspect in Frameworks */,
B245583C63F8F90357B87FAE /* SwiftyBeaver in Frameworks */,
A4E885358D7DD5A072A06824 /* SwiftState in Frameworks */,
29EE1791E0AFA1ABB7F23D2F /* GZIP in Frameworks */,
33CAC1226DFB8B5D8447D286 /* Sentry in Frameworks */,
492274DA6691EE985C2FCCAA /* SnapshotTesting in Frameworks */,
99ED42B8F8D6BFB1DBCF4C45 /* AnalyticsEvents in Frameworks */,
0E8C480700870BB34A2A360F /* AppAuth in Frameworks */,
CB498F4E27AA0545DCEF0F6F /* DTCoreText in Frameworks */,
6832733838C57A7D3FE8FEB5 /* KeychainAccess in Frameworks */,
2BA59D0AEFB4B82A2EC2A326 /* Kingfisher in Frameworks */,
B245583C63F8F90357B87FAE /* Introspect in Frameworks */,
A4E885358D7DD5A072A06824 /* PostHog in Frameworks */,
29EE1791E0AFA1ABB7F23D2F /* SwiftyBeaver in Frameworks */,
33CAC1226DFB8B5D8447D286 /* SwiftState in Frameworks */,
492274DA6691EE985C2FCCAA /* GZIP in Frameworks */,
F0F82C3C848C865C3098AA52 /* Sentry in Frameworks */,
3A64A93A651A3CB8774ADE8E /* SnapshotTesting in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@ -915,6 +935,15 @@
path = ViewModel;
sourceTree = "<group>";
};
1EEF62E8C0F7826C50264951 /* View */ = {
isa = PBXGroup;
children = (
541542F5AC323709D8563458 /* AnalyticsPrompt.swift */,
BA7B2E9CC5DC3B76ADC35A43 /* AnalyticsPromptCheckmarkItem.swift */,
);
path = View;
sourceTree = "<group>";
};
24FD174C31912A5FACFEAFB5 /* SupportingFiles */ = {
isa = PBXGroup;
children = (
@ -1402,6 +1431,7 @@
951A66D15CD44C0EACE4A951 /* Sources */ = {
isa = PBXGroup;
children = (
AF11DD57D9FACF2A757AB024 /* AnalyticsPromptUITests.swift */,
7D0CBC76C80E04345E11F2DB /* Application.swift */,
5D2D0A6F1ABC99D29462FB84 /* AuthenticationCoordinatorUITests.swift */,
C6FEA87EA3752203065ECE27 /* BugReportUITests.swift */,
@ -1633,6 +1663,18 @@
path = SessionVerification;
sourceTree = "<group>";
};
E0EEBB2F7AA1BB36FC08F606 /* AnalyticsPrompt */ = {
isa = PBXGroup;
children = (
B4DE1CF8F5EFD353B1A5E36F /* AnalyticsPromptCoordinator.swift */,
AA8BA82CF99D843FEF680E91 /* AnalyticsPromptModels.swift */,
A11B74ACE8D71747E1044A9C /* AnalyticsPromptViewModel.swift */,
C9A86C95340248A8B7BA9A43 /* AnalyticsPromptViewModelProtocol.swift */,
1EEF62E8C0F7826C50264951 /* View */,
);
path = AnalyticsPrompt;
sourceTree = "<group>";
};
E2DA161C142B7AB8CC40F752 /* Animation */ = {
isa = PBXGroup;
children = (
@ -1644,6 +1686,7 @@
E59565F441830B19DBAE567C /* Screens */ = {
isa = PBXGroup;
children = (
E0EEBB2F7AA1BB36FC08F606 /* AnalyticsPrompt */,
E74CD7681375AD2EAA34D66B /* Authentication */,
4009BE2E791C16AC6EE39A7E /* BugReport */,
B53CA9BECD3F97805E1432D0 /* HomeScreen */,
@ -1779,11 +1822,13 @@
name = UITests;
packageProductDependencies = (
B1E8B697DF78FE7F61FC6CA4 /* MatrixRustSDK */,
D661CAB418C075A94306A792 /* AnalyticsEvents */,
4346F63D53A346271577FD9C /* AppAuth */,
36B7FC232711031AA2B0D188 /* DTCoreText */,
78A5A8DE1E2B09C978C7F3B0 /* KeychainAccess */,
50009897F60FAE7D63EF5E5B /* Kingfisher */,
04C28663564E008DB32B5972 /* Introspect */,
CCE5BF78B125320CBF3BB834 /* PostHog */,
A981A4CA233FB5C13B9CA690 /* SwiftyBeaver */,
3853B78FB8531B83936C5DA6 /* SwiftState */,
1BCD21310B997A6837B854D6 /* GZIP */,
@ -2171,6 +2216,12 @@
A371629728E597C5FCA3C2B2 /* Analytics.swift in Sources */,
F7567DD6635434E8C563BF85 /* AnalyticsClientProtocol.swift in Sources */,
54C774874BED4A8FAD1F22FE /* AnalyticsConfiguration.swift in Sources */,
C7B251DC896C0867C51B616D /* AnalyticsPrompt.swift in Sources */,
E47CD939D8480657D4B706C6 /* AnalyticsPromptCheckmarkItem.swift in Sources */,
A663FE6704CB500EBE782AE1 /* AnalyticsPromptCoordinator.swift in Sources */,
B6F92EBE04D4AABF30B9E73A /* AnalyticsPromptModels.swift in Sources */,
E01373F2043E76393A0CE073 /* AnalyticsPromptViewModel.swift in Sources */,
744C029EB6C43429926A0499 /* AnalyticsPromptViewModelProtocol.swift in Sources */,
3C73442084BF8A6939F0F80B /* AnalyticsService.swift in Sources */,
EC4C31963E755EEC77BD778C /* AnalyticsSettings.swift in Sources */,
A636D4900E0D98ED91536482 /* AppCoordinator.swift in Sources */,
@ -2390,12 +2441,15 @@
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
97CECF91D68235F1D13598D7 /* AnalyticsConfiguration.swift in Sources */,
8024BE37156FF0A95A7A3465 /* AnalyticsPromptUITests.swift in Sources */,
7405B4824D45BA7C3D943E76 /* Application.swift in Sources */,
ACF094CF3BF02DBFA6DFDE60 /* AuthenticationCoordinatorUITests.swift in Sources */,
7756C4E90CABE6F14F7920A0 /* BugReportUITests.swift in Sources */,
499A26EB06C97E48C27A2DB9 /* BuildSettings.swift in Sources */,
94D0F36A87E596A93C0C178A /* Bundle.swift in Sources */,
9DC5FB22B8F86C3B51E907C1 /* HomeScreenUITests.swift in Sources */,
BB4C6F362F75933DDDE30F3E /* InfoPlist.swift in Sources */,
5C8AFBF168A41E20835F3B86 /* LoginScreenUITests.swift in Sources */,
2F1CF90A3460C153154427F0 /* RoomScreenUITests.swift in Sources */,
77FACC29F98FE2E65BBB6A5F /* ServerSelectionUITests.swift in Sources */,
@ -3202,6 +3256,16 @@
package = 80B898A3AD2AC63F3ABFC218 /* XCRemoteSwiftPackageReference "matrix-rust-components-swift" */;
productName = MatrixRustSDK;
};
CCE5BF78B125320CBF3BB834 /* PostHog */ = {
isa = XCSwiftPackageProductDependency;
package = 96495DD8554E2F39D3954354 /* XCRemoteSwiftPackageReference "posthog-ios" */;
productName = PostHog;
};
D661CAB418C075A94306A792 /* AnalyticsEvents */ = {
isa = XCSwiftPackageProductDependency;
package = AC3475112CA40C2C6E78D1EB /* XCRemoteSwiftPackageReference "matrix-analytics-events" */;
productName = AnalyticsEvents;
};
D82E84F90358CC1118E6034B /* Introspect */ = {
isa = XCSwiftPackageProductDependency;
package = 9A472EE0218FE7DCF5283429 /* XCRemoteSwiftPackageReference "SwiftUI-Introspect" */;

View File

@ -0,0 +1,123 @@
%PDF-1.7
1 0 obj
<< >>
endobj
2 0 obj
<< /Length 3 0 R >>
stream
/DeviceRGB CS
/DeviceRGB cs
q
1.000000 0.000000 -0.000000 1.000000 1.000000 -1.000000 cm
0.049479 0.742188 0.545395 scn
10.000000 23.000000 m
3.947715 23.000000 -1.000000 18.052284 -1.000000 12.000000 c
1.000000 12.000000 l
1.000000 16.947716 5.052285 21.000000 10.000000 21.000000 c
10.000000 23.000000 l
h
-1.000000 12.000000 m
-1.000000 5.947716 3.947715 1.000000 10.000000 1.000000 c
10.000000 3.000000 l
5.052285 3.000000 1.000000 7.052285 1.000000 12.000000 c
-1.000000 12.000000 l
h
10.000000 1.000000 m
16.052284 1.000000 21.000000 5.947716 21.000000 12.000000 c
19.000000 12.000000 l
19.000000 7.052285 14.947715 3.000000 10.000000 3.000000 c
10.000000 1.000000 l
h
21.000000 12.000000 m
21.000000 18.052284 16.052284 23.000000 10.000000 23.000000 c
10.000000 21.000000 l
14.947715 21.000000 19.000000 16.947716 19.000000 12.000000 c
21.000000 12.000000 l
h
f
n
Q
q
1.000000 0.000000 -0.000000 1.000000 5.545532 4.655060 cm
0.049479 0.742188 0.545395 scn
0.717378 6.153159 m
0.332610 6.549356 -0.300487 6.558620 -0.696684 6.173852 c
-1.092881 5.789084 -1.102146 5.155987 -0.717378 4.759790 c
0.717378 6.153159 l
h
3.257576 2.102139 m
2.540198 1.405455 l
2.728505 1.211555 2.987285 1.102139 3.257576 1.102139 c
3.527867 1.102139 3.786646 1.211555 3.974954 1.405455 c
3.257576 2.102139 l
h
11.626469 9.284243 m
12.011237 9.680439 12.001972 10.313537 11.605776 10.698304 c
11.209579 11.083073 10.576482 11.073808 10.191713 10.677610 c
11.626469 9.284243 l
h
-0.717378 4.759790 m
2.540198 1.405455 l
3.974954 2.798823 l
0.717378 6.153159 l
-0.717378 4.759790 l
h
3.974954 1.405455 m
11.626469 9.284243 l
10.191713 10.677610 l
2.540198 2.798823 l
3.974954 1.405455 l
h
f
n
Q
endstream
endobj
3 0 obj
1679
endobj
4 0 obj
<< /Annots []
/Type /Page
/MediaBox [ 0.000000 0.000000 22.000000 22.000000 ]
/Resources 1 0 R
/Contents 2 0 R
/Parent 5 0 R
>>
endobj
5 0 obj
<< /Kids [ 4 0 R ]
/Count 1
/Type /Pages
>>
endobj
6 0 obj
<< /Pages 5 0 R
/Type /Catalog
>>
endobj
xref
0 7
0000000000 65535 f
0000000010 00000 n
0000000034 00000 n
0000001769 00000 n
0000001792 00000 n
0000001965 00000 n
0000002039 00000 n
trailer
<< /ID [ (some) (id) ]
/Root 6 0 R
/Size 7
>>
startxref
2098
%%EOF

View File

@ -0,0 +1,16 @@
{
"images" : [
{
"filename" : "AnalyticsTick.pdf",
"idiom" : "universal"
}
],
"info" : {
"author" : "xcode",
"version" : 1
},
"properties" : {
"preserves-vector-representation" : true,
"template-rendering-intent" : "template"
}
}

View File

@ -0,0 +1,641 @@
%PDF-1.7
1 0 obj
<< /Type /XObject
/Length 2 0 R
/Group << /Type /Group
/S /Transparency
>>
/Subtype /Form
/Resources << /ExtGState << /E2 << /ca 0.400000 >>
/E1 << /ca 0.400000 >>
>> >>
/BBox [ 0.000000 0.000000 119.000000 93.000000 ]
>>
stream
/DeviceRGB CS
/DeviceRGB cs
q
1.000000 0.000000 -0.000000 1.000000 14.875000 -0.000015 cm
0.049479 0.742188 0.545395 scn
0.000000 44.521278 m
0.000000 69.109695 20.036579 89.042557 44.625000 89.042557 c
44.625000 89.042557 l
69.213417 89.042557 89.250000 69.109695 89.250000 44.521278 c
89.250000 44.521278 l
89.250000 19.932861 69.213417 0.000000 44.625000 0.000000 c
44.625000 0.000000 l
20.036579 0.000000 0.000000 19.932861 0.000000 44.521278 c
0.000000 44.521278 l
h
f
n
Q
q
1.000000 0.000000 -0.000000 1.000000 52.227402 46.594299 cm
1.000000 1.000000 1.000000 scn
0.000000 20.730219 m
0.000000 22.447567 1.395428 23.839752 3.116776 23.839752 c
14.592426 23.839752 23.895279 14.558517 23.895279 3.109533 c
23.895279 1.392185 22.499851 0.000000 20.778503 0.000000 c
19.057156 0.000000 17.661728 1.392185 17.661728 3.109533 c
17.661728 11.123821 11.149731 17.620686 3.116776 17.620686 c
1.395428 17.620686 0.000000 19.012871 0.000000 20.730219 c
h
f*
n
Q
q
-1.000000 0.000000 -0.000000 -1.000000 66.772202 42.448242 cm
1.000000 1.000000 1.000000 scn
0.000000 20.730206 m
0.000000 22.447552 1.395429 23.839737 3.116779 23.839737 c
14.592443 23.839737 23.895306 14.558502 23.895306 3.109520 c
23.895306 1.392172 22.499878 -0.000011 20.778526 -0.000011 c
19.057177 -0.000011 17.661749 1.392172 17.661749 3.109520 c
17.661749 11.123808 11.149744 17.620672 3.116779 17.620672 c
1.395429 17.620672 0.000000 19.012857 0.000000 20.730206 c
h
f*
n
Q
q
-0.000000 1.000000 -1.000000 -0.000000 57.366512 37.265598 cm
1.000000 1.000000 1.000000 scn
0.000000 20.722975 m
0.000000 22.444323 1.392186 23.839752 3.109534 23.839752 c
14.558520 23.839752 23.839758 14.536892 23.839758 3.061234 c
23.839758 1.339886 22.447573 -0.055544 20.730225 -0.055544 c
19.012875 -0.055544 17.620689 1.339886 17.620689 3.061234 c
17.620689 11.094195 11.123824 17.606197 3.109534 17.606197 c
1.392186 17.606197 0.000000 19.001625 0.000000 20.722975 c
h
f*
n
Q
q
-0.000000 -1.000000 1.000000 -0.000000 61.633194 51.777008 cm
1.000000 1.000000 1.000000 scn
0.000000 20.722975 m
0.000000 22.444324 1.392186 23.839752 3.109534 23.839752 c
14.558520 23.839752 23.839758 14.536893 23.839758 3.061237 c
23.839758 1.339888 22.447573 -0.055540 20.730225 -0.055540 c
19.012875 -0.055540 17.620689 1.339888 17.620689 3.061237 c
17.620689 11.094196 11.123824 17.606197 3.109534 17.606197 c
1.392186 17.606197 0.000000 19.001627 0.000000 20.722975 c
h
f*
n
Q
q
1.000000 0.000000 -0.000000 1.000000 28.123089 16.695465 cm
1.000000 1.000000 1.000000 scn
10.448288 0.000008 m
11.057861 0.000008 11.560491 0.448122 11.646045 1.077618 c
12.576446 7.617959 13.464069 8.514189 19.795069 9.229038 c
20.436726 9.303724 20.917965 9.826525 20.917965 10.434681 c
20.917965 11.053506 20.447418 11.554968 19.805763 11.640323 c
13.506846 12.461866 12.694082 13.262072 11.646045 19.802414 c
11.539103 20.431910 11.057861 20.869354 10.448288 20.869354 c
9.849410 20.869354 9.346780 20.431910 9.250531 19.791744 c
8.330826 13.251402 7.443202 12.355172 1.112203 11.640323 c
0.470547 11.565637 0.000000 11.053506 0.000000 10.434681 c
0.000000 9.826525 0.459853 9.314394 1.112203 9.229038 c
7.411120 8.354148 8.191800 7.607290 9.250531 1.066948 c
9.368169 0.437452 9.860105 0.000008 10.448288 0.000008 c
h
f
n
Q
q
1.000000 0.000000 -0.000000 1.000000 28.123089 15.195465 cm
0.049479 0.742188 0.545395 scn
11.646045 2.577618 m
10.903506 2.683247 l
10.902877 2.678619 l
11.646045 2.577618 l
h
19.795069 10.729038 m
19.879219 9.983770 l
19.881781 9.984068 l
19.795069 10.729038 l
h
19.805763 13.140323 m
19.904661 13.883777 l
19.902761 13.884024 l
19.805763 13.140323 l
h
11.646045 21.302414 m
12.386630 21.421087 l
12.385450 21.428030 l
11.646045 21.302414 l
h
9.250531 21.291744 m
8.508834 21.403259 l
8.507838 21.396183 l
9.250531 21.291744 l
h
1.112203 13.140323 m
1.028052 13.885592 l
1.025491 13.885293 l
1.112203 13.140323 l
h
1.112203 10.729038 m
1.215387 11.471931 l
1.209505 11.472700 l
1.112203 10.729038 l
h
9.250531 2.566948 m
8.510169 2.447100 l
8.511623 2.438120 l
8.513294 2.429176 l
9.250531 2.566948 l
h
10.448288 0.750008 m
11.450765 0.750008 12.255557 1.493191 12.389213 2.476614 c
10.902877 2.678619 l
10.865425 2.403053 10.664957 2.250008 10.448288 2.250008 c
10.448288 0.750008 l
h
12.388570 2.471989 m
12.620602 4.103085 12.844038 5.334888 13.138243 6.288948 c
13.429995 7.235054 13.776924 7.858273 14.225985 8.307880 c
15.140809 9.223818 16.666159 9.620979 19.879219 9.983774 c
19.710920 11.474303 l
16.592981 11.122249 14.509018 10.713870 13.164680 9.367895 c
12.484159 8.686545 12.039045 7.814714 11.704848 6.730967 c
11.373105 5.655174 11.136688 4.322321 10.903521 2.683245 c
12.388570 2.471989 l
h
19.881781 9.984068 m
20.873766 10.099530 21.667965 10.918526 21.667965 11.934681 c
20.167965 11.934681 l
20.167965 11.734525 19.999683 11.507918 19.708359 11.474010 c
19.881781 9.984068 l
h
21.667965 11.934681 m
21.667965 12.966555 20.881077 13.753887 19.904659 13.883774 c
19.706867 12.396872 l
20.013762 12.356048 20.167965 12.140457 20.167965 11.934681 c
21.667965 11.934681 l
h
19.902761 13.884024 m
18.330524 14.089085 17.151228 14.287123 16.235826 14.561028 c
15.331247 14.831694 14.731587 15.163220 14.286853 15.607450 c
13.840208 16.053589 13.492528 16.670565 13.191763 17.611713 c
12.888441 18.560867 12.648228 19.788363 12.386598 21.421082 c
10.905493 21.183746 l
11.167881 19.546295 11.422276 18.221136 11.762950 17.155106 c
12.106180 16.081072 12.551881 15.220337 13.226795 14.546188 c
13.903622 13.870131 14.753702 13.438795 15.805837 13.123979 c
16.847151 12.812399 18.131544 12.602333 19.708765 12.396622 c
19.902761 13.884024 l
h
12.385450 21.428030 m
12.223795 22.379583 11.461336 23.119354 10.448288 23.119354 c
10.448288 21.619354 l
10.654386 21.619354 10.854410 21.484234 10.906639 21.176800 c
12.385450 21.428030 l
h
10.448288 23.119354 m
9.455997 23.119354 8.656921 22.387987 8.508867 21.403254 c
9.992196 21.180237 l
10.036638 21.475830 10.242823 21.619354 10.448288 21.619354 c
10.448288 23.119354 l
h
8.507838 21.396183 m
8.278477 19.765110 8.056973 18.533388 7.764218 17.579443 c
7.473907 16.633463 7.127907 16.010515 6.679636 15.561167 c
5.766263 14.645599 4.241331 14.248406 1.028053 13.885587 c
1.196352 12.395059 l
4.314074 12.747088 6.398453 13.155437 7.741569 14.501781 c
8.421542 15.183390 8.865580 16.055490 9.198210 17.139366 c
9.528394 18.215273 9.762733 19.548208 9.993224 21.187307 c
8.507838 21.396183 l
h
1.025491 13.885293 m
0.028613 13.769261 -0.750000 12.956783 -0.750000 11.934681 c
0.750000 11.934681 l
0.750000 12.150229 0.912482 12.362013 1.198914 12.395352 c
1.025491 13.885293 l
h
-0.750000 11.934681 m
-0.750000 10.922595 0.016880 10.115961 1.014900 9.985377 c
1.209505 11.472700 l
0.902826 11.512827 0.750000 11.730454 0.750000 11.934681 c
-0.750000 11.934681 l
h
1.009022 9.986170 m
2.582546 9.767614 3.760892 9.563175 4.675031 9.286510 c
5.578484 9.013078 6.174878 8.682938 6.616406 8.241908 c
7.059544 7.799271 7.404263 7.187467 7.703608 6.250257 c
8.005574 5.304842 8.245770 4.080437 8.510169 2.447100 c
9.990894 2.686794 l
9.725928 4.323629 9.471515 5.645210 9.132493 6.706642 c
8.790851 7.776280 8.348207 8.632186 7.676467 9.303166 c
7.003119 9.975756 6.157125 10.405144 5.109545 10.722197 c
4.072651 11.036015 2.791318 11.253017 1.215384 11.471908 c
1.009022 9.986170 l
h
8.513294 2.429176 m
8.688872 1.489628 9.455215 0.750008 10.448288 0.750008 c
10.448288 2.250008 l
10.264993 2.250008 10.047464 2.385277 9.987769 2.704720 c
8.513294 2.429176 l
h
f
n
Q
q
1.000000 0.000000 -0.000000 1.000000 72.573807 58.608093 cm
1.000000 1.000000 1.000000 scn
8.619835 -0.000011 m
9.122732 -0.000011 9.537402 0.373419 9.607985 0.897997 c
10.375565 6.348283 11.107853 7.095141 16.330927 7.690849 c
16.860292 7.753087 17.257317 8.188755 17.257317 8.695551 c
17.257317 9.211239 16.869114 9.629124 16.339748 9.700253 c
11.143145 10.384872 10.472614 11.051710 9.607985 16.501997 c
9.519756 17.026575 9.122732 17.391113 8.619835 17.391113 c
8.125761 17.391113 7.711091 17.026575 7.631686 16.493105 c
6.872929 11.042820 6.140640 10.295961 0.917567 9.700253 c
0.388201 9.638015 0.000000 9.211239 0.000000 8.695551 c
0.000000 8.188755 0.379379 7.761978 0.917567 7.690849 c
6.114172 6.961774 6.758233 6.339392 7.631686 0.889107 c
7.728737 0.364527 8.134583 -0.000011 8.619835 -0.000011 c
h
f
n
Q
q
1.000000 0.000000 -0.000000 1.000000 72.573807 57.608093 cm
0.049479 0.742188 0.545395 scn
9.607985 1.897997 m
9.112861 1.967726 l
9.112450 1.964672 l
9.607985 1.897997 l
h
16.330927 8.690849 m
16.387587 8.194067 l
16.389311 8.194269 l
16.330927 8.690849 l
h
16.339748 10.700253 m
16.406334 11.195801 l
16.405056 11.195970 l
16.339748 10.700253 l
h
9.607985 17.501997 m
10.101830 17.580339 l
10.101059 17.584925 l
9.607985 17.501997 l
h
7.631686 17.493105 m
7.137113 17.566721 l
7.136462 17.562048 l
7.631686 17.493105 l
h
0.917567 10.700253 m
0.860907 11.197035 l
0.859183 11.196833 l
0.917567 10.700253 l
h
0.917567 8.690849 m
0.987038 9.186015 l
0.983079 9.186539 l
0.917567 8.690849 l
h
7.631686 1.889107 m
7.137843 1.809963 l
7.140029 1.798147 l
7.631686 1.889107 l
h
8.619835 0.499989 m
9.388696 0.499989 10.001672 1.074373 10.103518 1.831324 c
9.112450 1.964672 l
9.073133 1.672462 8.856770 1.499989 8.619835 1.499989 c
8.619835 0.499989 l
h
10.103099 1.828268 m
10.294624 3.188222 10.480069 4.223436 10.725984 5.028956 c
10.970345 5.829387 11.264832 6.369568 11.654185 6.763333 c
12.442908 7.560994 13.744701 7.892640 16.387587 8.194070 c
16.274267 9.187629 l
13.694078 8.893350 12.018190 8.553713 10.943106 7.466446 c
10.400556 6.917747 10.041607 6.212054 9.769561 5.320940 c
9.499068 4.434915 9.305134 3.332915 9.112870 1.967726 c
10.103099 1.828268 l
h
16.389311 8.194269 m
17.155991 8.284410 17.757317 8.920855 17.757317 9.695551 c
16.757317 9.695551 l
16.757317 9.456655 16.564592 9.221766 16.272543 9.187428 c
16.389311 8.194269 l
h
17.757317 9.695551 m
17.757317 10.482604 17.162529 11.094193 16.406334 11.195800 c
16.273165 10.204706 l
16.575699 10.164056 16.757317 9.939874 16.757317 9.695551 c
17.757317 9.695551 l
h
16.405056 11.195970 m
15.107601 11.366901 14.126670 11.532858 13.361839 11.764020 c
12.604449 11.992933 12.090017 12.277006 11.704502 12.665974 c
11.317406 13.056538 11.022324 13.591100 10.770527 14.386979 c
10.517109 15.187984 10.317721 16.219311 10.101810 17.580338 c
9.114160 17.423656 l
9.330563 16.059540 9.539227 14.963654 9.817105 14.085340 c
10.096603 13.201900 10.456060 12.505035 10.994250 11.962027 c
11.534022 11.417421 12.215625 11.065775 13.072525 10.806786 c
13.921983 10.550046 14.973595 10.375915 16.274443 10.204536 c
16.405056 11.195970 l
h
10.101059 17.584925 m
9.977288 18.320837 9.395552 18.891113 8.619835 18.891113 c
8.619835 17.891113 l
8.849913 17.891113 9.062225 17.732313 9.114909 17.419067 c
10.101059 17.584925 l
h
8.619835 18.891113 m
7.859531 18.891113 7.250215 18.326427 7.137135 17.566717 c
8.126238 17.419493 l
8.171968 17.726725 8.391990 17.891113 8.619835 17.891113 c
8.619835 18.891113 l
h
7.136462 17.562048 m
6.947139 16.202108 6.763302 15.166948 6.518592 14.361504 c
6.275430 13.561155 5.981721 13.021152 5.592998 12.627558 c
4.805452 11.830145 3.503936 11.498478 0.860908 11.197033 c
0.974226 10.203474 l
3.554271 10.497736 5.230436 10.837353 6.304493 11.924868 c
6.846570 12.473737 7.204643 13.179608 7.475406 14.070805 c
7.744622 14.956905 7.936855 16.058958 8.126910 17.424164 c
7.136462 17.562048 l
h
0.859183 11.196833 m
0.089259 11.106312 -0.500000 10.475979 -0.500000 9.695551 c
0.500000 9.695551 l
0.500000 9.946500 0.687143 10.169718 0.975950 10.203673 c
0.859183 11.196833 l
h
-0.500000 9.695551 m
-0.500000 8.923503 0.079786 8.297226 0.852054 8.195160 c
0.983079 9.186539 l
0.678971 9.226731 0.500000 9.454006 0.500000 9.695551 c
-0.500000 9.695551 l
h
0.848098 8.195699 m
2.146421 8.013546 3.126409 7.842214 3.889960 7.608789 c
4.646159 7.377612 5.157835 7.094736 5.540681 6.708459 c
5.924912 6.320785 6.217544 5.790504 6.468155 4.997945 c
6.720429 4.200129 6.919805 3.171420 7.137986 1.809986 c
8.125387 1.968225 l
7.906841 3.331934 7.698164 4.424881 7.421624 5.299438 c
7.143422 6.179253 6.786478 6.872063 6.250936 7.412404 c
5.714010 7.954142 5.035716 8.304206 4.182313 8.565100 c
3.336262 8.823746 2.287016 9.003614 0.987036 9.186000 c
0.848098 8.195699 l
h
7.140029 1.798147 m
7.274719 1.070122 7.860904 0.499989 8.619835 0.499989 c
8.619835 1.499989 l
8.408263 1.499989 8.182755 1.658932 8.123343 1.980066 c
7.140029 1.798147 l
h
f
n
Q
q
1.000000 0.000000 -0.000000 1.000000 107.227104 75.129669 cm
0.049479 0.742188 0.545395 scn
5.619252 -0.000010 m
5.947090 -0.000010 6.217412 0.238985 6.263425 0.574716 c
6.763808 4.062898 7.241186 4.540888 10.646096 4.922141 c
10.991189 4.961974 11.250008 5.240800 11.250008 5.565150 c
11.250008 5.895190 10.996941 6.162637 10.651848 6.208159 c
7.264192 6.646316 6.827075 7.073092 6.263425 10.561275 c
6.205909 10.897006 5.947090 11.130310 5.619252 11.130310 c
5.297166 11.130310 5.026845 10.897006 4.975080 10.555585 c
4.480448 7.067402 4.003070 6.589413 0.598160 6.208159 c
0.253068 6.168327 0.000000 5.895190 0.000000 5.565150 c
0.000000 5.240800 0.247316 4.967664 0.598160 4.922141 c
3.985816 4.455533 4.405678 4.057208 4.975080 0.569025 c
5.038347 0.233294 5.302918 -0.000010 5.619252 -0.000010 c
h
f
n
Q
q
1.000000 0.000000 -0.000000 1.000000 103.008408 84.868683 cm
0.049479 0.742188 0.545395 scn
3.160831 -0.000001 m
3.345240 -0.000001 3.497297 0.134433 3.523178 0.323282 c
3.804644 2.285384 4.073170 2.554254 5.988433 2.768708 c
6.182547 2.791114 6.328133 2.947954 6.328133 3.130401 c
6.328133 3.316049 6.185782 3.466487 5.991668 3.492094 c
4.086111 3.738557 3.840232 3.978619 3.523178 5.940721 c
3.490826 6.129570 3.345240 6.260803 3.160831 6.260803 c
2.979658 6.260803 2.827601 6.129570 2.798484 5.937521 c
2.520254 3.975418 2.251728 3.706549 0.336465 3.492094 c
0.142351 3.469688 0.000000 3.316049 0.000000 3.130401 c
0.000000 2.947954 0.139115 2.794315 0.336465 2.768708 c
2.242023 2.506241 2.478195 2.282184 2.798484 0.320081 c
2.834072 0.131233 2.982893 -0.000001 3.160831 -0.000001 c
h
f
n
Q
q
1.000000 0.000000 -0.000000 1.000000 103.711479 69.564484 cm
0.049479 0.742188 0.545395 scn
3.863233 0.000004 m
4.088622 0.000004 4.274468 0.164312 4.306101 0.395127 c
4.650115 2.793253 4.978312 3.121871 7.319186 3.383983 c
7.556437 3.411368 7.734375 3.603061 7.734375 3.826052 c
7.734375 4.052955 7.560391 4.236824 7.323141 4.268121 c
4.994129 4.569354 4.693611 4.862762 4.306101 7.260888 c
4.266560 7.491703 4.088622 7.652100 3.863233 7.652100 c
3.641799 7.652100 3.455953 7.491703 3.420365 7.256976 c
3.080306 4.858850 2.752109 4.530232 0.411235 4.268121 c
0.173984 4.240736 0.000000 4.052955 0.000000 3.826052 c
0.000000 3.603061 0.170030 3.415280 0.411235 3.383983 c
2.740246 3.063190 3.028902 2.789341 3.420365 0.391215 c
3.463861 0.160400 3.645753 0.000004 3.863233 0.000004 c
h
f
n
Q
q
1.000000 0.000000 -0.000000 1.000000 -0.070938 78.607880 cm
0.049479 0.742188 0.545395 scn
5.268045 -0.000012 m
5.575393 -0.000012 5.828820 0.224045 5.871957 0.538792 c
6.341066 3.808963 6.788608 4.257079 9.980709 4.614503 c
10.304233 4.651846 10.546875 4.913247 10.546875 5.217325 c
10.546875 5.526737 10.309625 5.777468 9.986101 5.820146 c
6.810176 6.230918 6.400379 6.631021 5.871957 9.901192 c
5.818036 10.215940 5.575393 10.434662 5.268045 10.434662 c
4.966090 10.434662 4.712663 10.215940 4.664135 9.895857 c
4.200418 6.625686 3.752876 6.177571 0.560775 5.820146 c
0.237251 5.782803 0.000000 5.526737 0.000000 5.217325 c
0.000000 4.913247 0.231859 4.657181 0.560775 4.614503 c
3.736700 4.177058 4.130321 3.803629 4.664135 0.533457 c
4.723447 0.218710 4.971482 -0.000012 5.268045 -0.000012 c
h
f
n
Q
q
/E1 gs
1.000000 0.000000 -0.000000 1.000000 9.772858 88.346924 cm
0.049479 0.742188 0.545395 scn
2.458421 -0.000008 m
2.601850 -0.000008 2.720115 0.104552 2.740246 0.251434 c
2.959164 1.777514 3.168016 1.986634 4.657663 2.153433 c
4.808641 2.170859 4.921874 2.292846 4.921874 2.434749 c
4.921874 2.579142 4.811157 2.696150 4.660179 2.716066 c
3.178081 2.907759 2.986843 3.094474 2.740246 4.620554 c
2.715083 4.767436 2.601850 4.869507 2.458421 4.869507 c
2.317508 4.869507 2.199242 4.767436 2.176596 4.618064 c
1.960194 3.091985 1.751342 2.882864 0.261695 2.716066 c
0.110717 2.698639 0.000000 2.579142 0.000000 2.434749 c
0.000000 2.292846 0.108201 2.173349 0.261695 2.153433 c
1.743793 1.949291 1.927482 1.775024 2.176596 0.248944 c
2.204275 0.102062 2.320024 -0.000008 2.458421 -0.000008 c
h
f
n
Q
q
/E2 gs
1.000000 0.000000 -0.000000 1.000000 13.288479 82.086121 cm
0.049479 0.742188 0.545395 scn
2.458421 -0.000008 m
2.601850 -0.000008 2.720116 0.104552 2.740247 0.251434 c
2.959164 1.777514 3.168017 1.986634 4.657664 2.153433 c
4.808642 2.170859 4.921875 2.292846 4.921875 2.434749 c
4.921875 2.579142 4.811158 2.696150 4.660181 2.716066 c
3.178082 2.907759 2.986844 3.094474 2.740247 4.620554 c
2.715084 4.767436 2.601850 4.869507 2.458421 4.869507 c
2.317509 4.869507 2.199243 4.767436 2.176596 4.618064 c
1.960195 3.091985 1.751342 2.882864 0.261695 2.716066 c
0.110717 2.698639 0.000000 2.579142 0.000000 2.434749 c
0.000000 2.292846 0.108201 2.173349 0.261695 2.153433 c
1.743793 1.949291 1.927483 1.775024 2.176596 0.248944 c
2.204276 0.102062 2.320025 -0.000008 2.458421 -0.000008 c
h
f
n
Q
endstream
endobj
2 0 obj
17245
endobj
3 0 obj
<< /Type /XObject
/Length 4 0 R
/Group << /Type /Group
/S /Transparency
>>
/Subtype /Form
/Resources << >>
/BBox [ 0.000000 0.000000 119.000000 93.000000 ]
>>
stream
/DeviceRGB CS
/DeviceRGB cs
q
1.000000 0.000000 -0.000000 1.000000 0.000000 0.000000 cm
0.000000 0.000000 0.000000 scn
0.000000 93.000000 m
119.000000 93.000000 l
119.000000 0.000000 l
0.000000 0.000000 l
0.000000 93.000000 l
h
f
n
Q
endstream
endobj
4 0 obj
234
endobj
5 0 obj
<< /XObject << /X1 1 0 R >>
/ExtGState << /E1 << /SMask << /Type /Mask
/G 3 0 R
/S /Alpha
>>
/Type /ExtGState
>> >>
>>
endobj
6 0 obj
<< /Length 7 0 R >>
stream
/DeviceRGB CS
/DeviceRGB cs
q
/E1 gs
/X1 Do
Q
endstream
endobj
7 0 obj
46
endobj
8 0 obj
<< /Annots []
/Type /Page
/MediaBox [ 0.000000 0.000000 119.000000 93.000000 ]
/Resources 5 0 R
/Contents 6 0 R
/Parent 9 0 R
>>
endobj
9 0 obj
<< /Kids [ 8 0 R ]
/Count 1
/Type /Pages
>>
endobj
10 0 obj
<< /Pages 9 0 R
/Type /Catalog
>>
endobj
xref
0 11
0000000000 65535 f
0000000010 00000 n
0000017630 00000 n
0000017654 00000 n
0000018137 00000 n
0000018159 00000 n
0000018457 00000 n
0000018559 00000 n
0000018580 00000 n
0000018754 00000 n
0000018828 00000 n
trailer
<< /ID [ (some) (id) ]
/Root 10 0 R
/Size 11
>>
startxref
18888
%%EOF

View File

@ -0,0 +1,15 @@
{
"images" : [
{
"filename" : "AnalyticsLogo.pdf",
"idiom" : "universal"
}
],
"info" : {
"author" : "xcode",
"version" : 1
},
"properties" : {
"preserves-vector-representation" : true
}
}

View File

@ -0,0 +1,6 @@
{
"info" : {
"author" : "xcode",
"version" : 1
}
}

View File

@ -286,6 +286,7 @@ class AppCoordinator: AuthenticationCoordinatorDelegate, Coordinator {
private func presentSettingsScreen() {
let parameters = SettingsCoordinatorParameters(navigationRouter: navigationRouter,
userSession: userSession,
bugReportService: bugReportService)
let coordinator = SettingsCoordinator(parameters: parameters)
coordinator.callback = { [weak self] action in

View File

@ -23,6 +23,8 @@ internal typealias AssetImageTypeAlias = ImageAsset.Image
// swiftlint:disable identifier_name line_length nesting type_body_length type_name
internal enum Asset {
internal enum Images {
internal static let analyticsCheckmark = ImageAsset(name: "Images/AnalyticsCheckmark")
internal static let analyticsLogo = ImageAsset(name: "Images/AnalyticsLogo")
internal static let serverSelectionIcon = ImageAsset(name: "Images/Server Selection Icon")
internal static let splashScreenPage1 = ImageAsset(name: "Images/Splash Screen Page 1")
internal static let splashScreenPage2 = ImageAsset(name: "Images/Splash Screen Page 2")

View File

@ -0,0 +1,73 @@
//
// Copyright 2021 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 SwiftUI
struct AnalyticsPromptCoordinatorParameters {
/// The user session to use if analytics are enabled.
let userSession: UserSessionProtocol
}
final class AnalyticsPromptCoordinator: Coordinator, Presentable {
// MARK: - Properties
// MARK: Private
private let parameters: AnalyticsPromptCoordinatorParameters
private let analyticsPromptHostingController: UIViewController
private var analyticsPromptViewModel: AnalyticsPromptViewModel
// MARK: Public
// Must be used only internally
var childCoordinators: [Coordinator] = []
var callback: (@MainActor () -> Void)?
// MARK: - Setup
init(parameters: AnalyticsPromptCoordinatorParameters) {
self.parameters = parameters
let viewModel = AnalyticsPromptViewModel(termsURL: BuildSettings.analyticsConfiguration.termsURL)
let view = AnalyticsPrompt(context: viewModel.context)
analyticsPromptViewModel = viewModel
analyticsPromptHostingController = UIHostingController(rootView: view)
}
// MARK: - Public
func start() {
MXLog.debug("Did start.")
analyticsPromptViewModel.callback = { [weak self] result in
MXLog.debug("AnalyticsPromptViewModel did complete with result: \(result).")
guard let self = self else { return }
switch result {
case .enable:
Analytics.shared.optIn(with: self.parameters.userSession)
self.callback?()
case .disable:
Analytics.shared.optOut()
self.callback?()
}
}
}
func toPresentable() -> UIViewController { analyticsPromptHostingController }
}

View File

@ -0,0 +1,63 @@
//
// Copyright 2021 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
enum AnalyticsPromptViewAction {
/// Enable analytics.
case enable
/// Disable analytics.
case disable
}
enum AnalyticsPromptViewModelAction {
/// Enable analytics.
case enable
/// Disable analytics.
case disable
}
struct AnalyticsPromptViewState: BindableState {
/// Attributed strings created from localized HTML.
let strings = AnalyticsPromptStrings()
}
/// A collection of strings for the UI that need to be parsed from HTML
struct AnalyticsPromptStrings {
let optInContent: AttributedString
let point1 = AttributedStringBuilder().fromHTML(ElementL10n.analyticsOptInListItem1) ?? AttributedString(ElementL10n.analyticsOptInListItem1)
let point2 = AttributedStringBuilder().fromHTML(ElementL10n.analyticsOptInListItem2) ?? AttributedString(ElementL10n.analyticsOptInListItem2)
init() {
// Create the opt in content with a placeholder.
let linkPlaceholder = "{link}"
var optInContent = AttributedString(ElementL10n.analyticsOptInContent(ElementInfoPlist.cfBundleName, linkPlaceholder))
guard let range = optInContent.range(of: linkPlaceholder) else {
self.optInContent = AttributedString(ElementL10n.analyticsOptInContent(ElementInfoPlist.cfBundleName,
ElementL10n.analyticsOptInContentLink))
MXLog.failure("Failed to add a link attribute to the opt in content.")
return
}
// Replace the placeholder with a link.
var link = AttributedString(ElementL10n.analyticsOptInContentLink)
link.link = BuildSettings.analyticsConfiguration.termsURL
optInContent.replaceSubrange(range, with: link)
self.optInContent = optInContent
}
}

View File

@ -0,0 +1,51 @@
//
// Copyright 2021 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 Combine
import SwiftUI
typealias AnalyticsPromptViewModelType = StateStoreViewModel<AnalyticsPromptViewState, AnalyticsPromptViewAction>
class AnalyticsPromptViewModel: AnalyticsPromptViewModelType, AnalyticsPromptViewModelProtocol {
// MARK: - Properties
// MARK: Private
private let termsURL: URL
// MARK: Public
var callback: (@MainActor (AnalyticsPromptViewModelAction) -> Void)?
// MARK: - Setup
/// Initialize a view model with the specified prompt type and app display name.
init(termsURL: URL) {
self.termsURL = termsURL
super.init(initialViewState: AnalyticsPromptViewState())
}
// MARK: - Public
override func process(viewAction: AnalyticsPromptViewAction) async {
switch viewAction {
case .enable:
callback?(.enable)
case .disable:
callback?(.disable)
}
}
}

View File

@ -0,0 +1,23 @@
//
// Copyright 2021 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
@MainActor
protocol AnalyticsPromptViewModelProtocol {
var callback: (@MainActor (AnalyticsPromptViewModelAction) -> Void)? { get set }
var context: AnalyticsPromptViewModelType.Context { get }
}

View File

@ -0,0 +1,130 @@
//
// Copyright 2021 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 SwiftUI
/// A prompt that asks the user whether they would like to enable Analytics or not.
struct AnalyticsPrompt: View {
// MARK: - Properties
// MARK: Private
private let horizontalPadding: CGFloat = 16
// MARK: Public
@ObservedObject var context: AnalyticsPromptViewModel.Context
// MARK: Views
var body: some View {
GeometryReader { geometry in
ScrollView {
Spacer()
.frame(height: UIConstants.spacerHeight(in: geometry))
mainContent
.readableFrame()
.padding(.horizontal, horizontalPadding)
.padding(.top, UIConstants.onboardingBreakerScreenTopPadding)
.padding(.bottom, 8)
}
.safeAreaInset(edge: .bottom) {
VStack {
buttons
.readableFrame()
.padding(.horizontal, horizontalPadding)
.padding(.bottom, UIConstants.actionButtonBottomPadding)
Spacer()
.frame(height: UIConstants.spacerHeight(in: geometry))
}
.padding(.top, 8)
.background(Color.element.background.ignoresSafeArea())
}
.background(Color.element.background.ignoresSafeArea())
}
.navigationBarHidden(true)
.navigationBarBackButtonHidden(true)
}
/// The main content of the screen that is shown inside the scroll view.
private var mainContent: some View {
VStack {
Image(uiImage: Asset.Images.analyticsLogo.image)
.padding(.bottom, 25)
Text(ElementL10n.analyticsOptInTitle(ElementInfoPlist.cfBundleName))
.font(.element.title2B)
.multilineTextAlignment(.center)
.foregroundColor(.element.primaryContent)
.padding(.bottom, 2)
Text(context.viewState.strings.optInContent)
.font(.element.body)
.multilineTextAlignment(.center)
.foregroundColor(.element.secondaryContent)
Divider()
.background(Color.element.quinaryContent)
.padding(.vertical, 28)
checkmarkList
}
}
/// The list of re-assurances about analytics.
private var checkmarkList: some View {
VStack(alignment: .leading) {
AnalyticsPromptCheckmarkItem(attributedString: context.viewState.strings.point1)
AnalyticsPromptCheckmarkItem(attributedString: context.viewState.strings.point1)
AnalyticsPromptCheckmarkItem(string: ElementL10n.analyticsOptInListItem3)
}
.fixedSize(horizontal: false, vertical: true)
.font(.element.body)
.foregroundColor(.element.secondaryContent)
.frame(maxWidth: .infinity)
}
/// The stack of enable/disable buttons.
private var buttons: some View {
VStack {
Button { context.send(viewAction: .enable) } label: {
Text(ElementL10n.actionEnable)
.font(.element.bodySB)
}
.buttonStyle(.elementAction(.xLarge))
.accessibilityIdentifier("enableButton")
Button { context.send(viewAction: .disable) } label: {
Text(ElementL10n.actionNotNow)
.font(.element.bodySB)
.padding(12)
}
.accessibilityIdentifier("disableButton")
}
}
}
// MARK: - Previews
struct AnalyticsPrompt_Previews: PreviewProvider {
static let viewModel = AnalyticsPromptViewModel(termsURL: BuildSettings.analyticsConfiguration.termsURL)
static var previews: some View {
AnalyticsPrompt(context: viewModel.context)
.tint(.element.accent)
}
}

View File

@ -0,0 +1,60 @@
//
// Copyright 2021 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 SwiftUI
struct AnalyticsPromptCheckmarkItem: View {
// MARK: - Properties
// MARK: Private
private let attributedString: AttributedString
// MARK: - Setup
init(attributedString: AttributedString) {
self.attributedString = attributedString
}
init(string: String) {
attributedString = AttributedString(string)
}
// MARK: - Views
var body: some View {
Label { Text(attributedString) } icon: {
Image(uiImage: Asset.Images.analyticsCheckmark.image)
.foregroundColor(.element.accent)
}
}
}
// MARK: - Previews
struct AnalyticsPromptCheckmarkItem_Previews: PreviewProvider {
static let strings = AnalyticsPromptStrings()
static var previews: some View {
VStack(alignment: .leading) {
AnalyticsPromptCheckmarkItem(attributedString: strings.point1)
AnalyticsPromptCheckmarkItem(attributedString: strings.point2)
AnalyticsPromptCheckmarkItem(attributedString: AttributedString("This is a short string."))
AnalyticsPromptCheckmarkItem(attributedString: AttributedString("This is a very long string that will be used to test the layout over multiple lines of text to ensure everything is correct."))
}
.padding()
}
}

View File

@ -51,6 +51,7 @@ class AuthenticationCoordinator: Coordinator, Presentable {
// MARK: - Private
/// Shows the splash screen as the root view in the navigation stack.
private func showSplashScreen() {
let coordinator = SplashScreenCoordinator()
@ -129,6 +130,23 @@ class AuthenticationCoordinator: Coordinator, Presentable {
}
}
private func showAnalyticsPrompt(with userSession: UserSessionProtocol) {
let parameters = AnalyticsPromptCoordinatorParameters(userSession: userSession)
let coordinator = AnalyticsPromptCoordinator(parameters: parameters)
coordinator.callback = { [weak self] in
guard let self = self else { return }
self.delegate?.authenticationCoordinator(self, didLoginWithSession: userSession)
}
coordinator.start()
add(childCoordinator: coordinator)
navigationRouter.setRootModule(coordinator, hideNavigationBar: true, animated: true) { [weak self] in
self?.remove(childCoordinator: coordinator)
}
}
/// Show a blocking activity indicator.
private func startLoading() {
activityIndicator = indicatorPresenter.present(.loading(label: ElementL10n.loading, isInteractionBlocking: true))

View File

@ -25,6 +25,9 @@ struct UIConstants {
/// The padding used between the footer and the bottom of the view.
static let actionButtonBottomPadding: CGFloat = 24
/// The padding used to the top of the view for breaker screens that don't have a navigation bar.
static let onboardingBreakerScreenTopPadding: CGFloat = 80
/// The height to use for top/bottom spacers to pad the views to fit the `maxContentHeight`.
static func spacerHeight(in geometry: GeometryProxy) -> CGFloat {
max(0, (geometry.size.height - maxContentHeight) / 2)

View File

@ -18,6 +18,7 @@ import SwiftUI
struct SettingsCoordinatorParameters {
let navigationRouter: NavigationRouterType
let userSession: UserSessionProtocol
let bugReportService: BugReportServiceProtocol
}
@ -60,6 +61,8 @@ final class SettingsCoordinator: Coordinator, Presentable {
guard let self = self else { return }
MXLog.debug("SettingsViewModel did complete with result: \(result).")
switch result {
case .toggleAnalytics:
self.toggleAnalytics()
case .reportBug:
self.presentBugReportScreen()
case .crash:
@ -82,17 +85,12 @@ final class SettingsCoordinator: Coordinator, Presentable {
// MARK: - Private
/// Show an activity indicator whilst loading.
/// - Parameters:
/// - label: The label to show on the indicator.
/// - isInteractionBlocking: Whether the indicator should block any user interaction.
private func startLoading(label: String = ElementL10n.loading, isInteractionBlocking: Bool = true) {
loadingIndicator = indicatorPresenter.present(.loading(label: label, isInteractionBlocking: isInteractionBlocking))
private func toggleAnalytics() {
if ElementSettings.shared.enableAnalytics {
Analytics.shared.optOut()
} else {
Analytics.shared.optIn(with: parameters.userSession)
}
/// Hide the currently displayed activity indicator.
private func stopLoading() {
loadingIndicator = nil
}
private func presentBugReportScreen() {
@ -115,6 +113,19 @@ final class SettingsCoordinator: Coordinator, Presentable {
}
}
/// Show an activity indicator whilst loading.
/// - Parameters:
/// - label: The label to show on the indicator.
/// - isInteractionBlocking: Whether the indicator should block any user interaction.
private func startLoading(label: String = ElementL10n.loading, isInteractionBlocking: Bool = true) {
loadingIndicator = indicatorPresenter.present(.loading(label: label, isInteractionBlocking: isInteractionBlocking))
}
/// Hide the currently displayed activity indicator.
private func stopLoading() {
loadingIndicator = nil
}
/// Show success indicator
private func showSuccess(label: String) {
statusIndicator = indicatorPresenter.present(.success(label: label))

View File

@ -21,6 +21,7 @@ import Foundation
// MARK: View model
enum SettingsViewModelAction {
case toggleAnalytics
case reportBug
case crash
case logout
@ -32,9 +33,12 @@ struct SettingsViewState: BindableState {
var bindings: SettingsViewStateBindings
}
struct SettingsViewStateBindings { }
struct SettingsViewStateBindings {
var enableAnalytics = ElementSettings.shared.enableAnalytics
}
enum SettingsViewAction {
case toggleAnalytics
case reportBug
case crash
case logout

View File

@ -40,6 +40,8 @@ class SettingsViewModel: SettingsViewModelType, SettingsViewModelProtocol {
override func process(viewAction: SettingsViewAction) async {
switch viewAction {
case .toggleAnalytics:
callback?(.toggleAnalytics)
case .reportBug:
callback?(.reportBug)
case .crash:

View File

@ -31,42 +31,13 @@ struct SettingsScreen: View {
var body: some View {
Form {
Section {
Button { context.send(viewAction: .reportBug) } label: {
Text(ElementL10n.sendBugReport)
}
.foregroundColor(Color.element.primaryContent)
.accessibilityIdentifier("reportBugButton")
if BuildSettings.settingsCrashButtonVisible {
Button("Crash the app",
role: .destructive) { context.send(viewAction: .crash)
}
.accessibilityIdentifier("crashButton")
}
}
analyticsSection
.listRowBackground(rowBackgroundColor)
userInterfaceSection
.listRowBackground(rowBackgroundColor)
Section {
Button { showingLogoutConfirmation = true } label: {
Text(ElementL10n.actionSignOut)
}
.frame(maxWidth: .infinity)
.foregroundColor(Color.element.primaryContent)
.accessibilityIdentifier("logoutButton")
.confirmationDialog(ElementL10n.actionSignOutConfirmationSimple,
isPresented: $showingLogoutConfirmation,
titleVisibility: .visible) {
Button(ElementL10n.actionSignOut,
role: .destructive) { context.send(viewAction: .logout)
}
}
} footer: {
versionText
}
logoutSection
.listRowBackground(rowBackgroundColor)
}
.introspectTableView { tableView in
@ -88,10 +59,27 @@ struct SettingsScreen: View {
colorScheme == .light ? .element.background : .element.system
}
private var analyticsSection: some View {
Section(ElementL10n.settingsAnalytics) {
Button { context.send(viewAction: .reportBug) } label: {
Text(ElementL10n.sendBugReport)
}
.foregroundColor(.element.primaryContent)
.accessibilityIdentifier("reportBugButton")
if BuildSettings.settingsCrashButtonVisible {
Button("Crash the app",
role: .destructive) { context.send(viewAction: .crash)
}
.accessibilityIdentifier("crashButton")
}
}
}
@ViewBuilder
private var userInterfaceSection: some View {
if BuildSettings.settingsShowTimelineStyle {
Section(header: Text(ElementL10n.settingsUserInterface)) {
Section(ElementL10n.settingsUserInterface) {
Picker(ElementL10n.settingsTimelineStyle, selection: $settings.timelineStyle) {
ForEach(TimelineStyle.allCases, id: \.self) { style in
Text(style.description)
@ -100,7 +88,26 @@ struct SettingsScreen: View {
}
.accessibilityIdentifier("timelineStylePicker")
}
.listRowBackground(rowBackgroundColor)
}
}
private var logoutSection: some View {
Section {
Button { showingLogoutConfirmation = true } label: {
Text(ElementL10n.actionSignOut)
}
.frame(maxWidth: .infinity)
.foregroundColor(.element.primaryContent)
.accessibilityIdentifier("logoutButton")
.confirmationDialog(ElementL10n.actionSignOutConfirmationSimple,
isPresented: $showingLogoutConfirmation,
titleVisibility: .visible) {
Button(ElementL10n.actionSignOut,
role: .destructive) { context.send(viewAction: .logout)
}
}
} footer: {
versionText
}
}
}

View File

@ -56,14 +56,14 @@ class Analytics {
// MARK: - Public
/// Opts in to analytics tracking with the supplied session.
/// - Parameter session: An optional session to use to when reading/generating the analytics ID.
/// Opts in to analytics tracking with the supplied user session.
/// - Parameter userSession: The user session to use to when reading/generating the analytics ID.
/// The session will be ignored if not running.
func optIn(with session: UserSessionProtocol) {
func optIn(with userSession: UserSessionProtocol) {
ElementSettings.shared.enableAnalytics = true
startIfEnabled()
Task { await useAnalyticsSettings(from: session) }
Task { await useAnalyticsSettings(from: userSession) }
}
/// Stops analytics tracking and calls `reset` to clear any IDs and event queues.
@ -95,16 +95,16 @@ class Analytics {
// MXLogger.setBuildVersion(ElementInfoPlist.cfBundleShortVersionString)
}
/// Use the analytics settings from the supplied session to configure analytics.
/// Use the analytics settings from the supplied user session to configure analytics.
/// For now this is only used for (pseudonymous) identification.
/// - Parameter session: The session to read analytics settings from.
func useAnalyticsSettings(from session: UserSessionProtocol) async {
/// - Parameter userSession: The user session to read analytics settings from.
func useAnalyticsSettings(from userSession: UserSessionProtocol) async {
guard
ElementSettings.shared.enableAnalytics,
!ElementSettings.shared.isIdentifiedForAnalytics
else { return }
let service = AnalyticsService(session: session)
let service = AnalyticsService(userSession: userSession)
self.service = service
switch await service.settings() {

View File

@ -17,7 +17,7 @@
import Foundation
enum AnalyticsServiceError: Error {
/// The session supplied to the service does not have a state of `MXSessionStateRunning`.
/// The user session supplied to the service does not have a state of `MXSessionStateRunning`.
case sessionIsNotRunning
/// The service failed to get or update the analytics settings event from the user's account data.
case accountDataFailure
@ -25,12 +25,12 @@ enum AnalyticsServiceError: Error {
/// A service responsible for handling the `im.vector.analytics` event from the user's account data.
class AnalyticsService {
let session: UserSessionProtocol
let userSession: UserSessionProtocol
/// Creates an analytics service with the supplied session.
/// - Parameter session: The session to use when reading analytics settings from account data.
init(session: UserSessionProtocol) {
self.session = session
/// Creates an analytics service with the supplied user session.
/// - Parameter userSession: The user session to use when reading analytics settings from account data.
init(userSession: UserSessionProtocol) {
self.userSession = userSession
}
/// The analytics settings for the current user. Calling this method will check whether the settings already
@ -41,12 +41,12 @@ class AnalyticsService {
func settings() async -> Result<AnalyticsSettings, AnalyticsServiceError> {
// Only use the session if it is running otherwise we could wipe out an existing analytics ID.
fatalWithoutUnreachableCodeWarning()
// guard session.state == .running else {
// guard userSession.state == .running else {
// MXLog.warning("Aborting attempt to read analytics settings. The session may not be up-to-date.")
// return .failure(.sessionIsNotRunning)
// }
let result: Result<AnalyticsSettings?, ClientProxyError> = await session.clientProxy.accountDataEvent(type: AnalyticsSettings.eventType)
let result: Result<AnalyticsSettings?, ClientProxyError> = await userSession.clientProxy.accountDataEvent(type: AnalyticsSettings.eventType)
switch result {
case .failure:
return .failure(.accountDataFailure)
@ -57,7 +57,7 @@ class AnalyticsService {
}
let newSettings = AnalyticsSettings.new(currentEvent: settings)
switch await session.clientProxy.setAccountData(content: newSettings, type: AnalyticsSettings.eventType) {
switch await userSession.clientProxy.setAccountData(content: newSettings, type: AnalyticsSettings.eventType) {
case .failure:
MXLog.warning("Failed to update analytics settings.")
return .failure(.accountDataFailure)

View File

@ -21,6 +21,7 @@ enum UITestScreenIdentifier: String {
case serverSelection
case serverSelectionNonModal
case authenticationFlow
case analyticsPrompt
case simpleRegular
case simpleUpgrade
case settings

View File

@ -76,6 +76,9 @@ class MockScreen: Identifiable {
case .serverSelectionNonModal:
return ServerSelectionCoordinator(parameters: .init(authenticationService: MockAuthenticationServiceProxy(),
hasModalPresentation: false))
case .analyticsPrompt:
return AnalyticsPromptCoordinator(parameters: .init(userSession: MockUserSession(clientProxy: MockClientProxy(userIdentifier: "@mock:client.com"),
mediaProvider: MockMediaProvider())))
case .authenticationFlow:
return AuthenticationCoordinator(authenticationService: MockAuthenticationServiceProxy(),
navigationRouter: navigationRouter)
@ -85,6 +88,8 @@ class MockScreen: Identifiable {
return TemplateCoordinator(parameters: .init(promptType: .upgrade))
case .settings:
return SettingsCoordinator(parameters: .init(navigationRouter: navigationRouter,
userSession: MockUserSession(clientProxy: MockClientProxy(userIdentifier: "@mock:client.com"),
mediaProvider: MockMediaProvider()),
bugReportService: MockBugReportService()))
case .bugReport:
return BugReportCoordinator(parameters: .init(bugReportService: MockBugReportService(),

View File

@ -0,0 +1,27 @@
//
// Copyright 2021 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
class AnalyticsPromptUITests: XCTestCase {
/// Verify that the prompt is displayed correctly.
func testAnalyticsPrompt() {
let app = Application.launch()
app.goToScreenWithIdentifier(.analyticsPrompt)
app.assertScreenshot(.analyticsPrompt)
}
}

View File

@ -29,6 +29,8 @@ targets:
- target: ElementX
- package: MatrixRustSDK
linkType: static
- package: AnalyticsEvents
linkType: static
- package: AppAuth
linkType: static
- package: DTCoreText
@ -39,6 +41,8 @@ targets:
linkType: static
- package: Introspect
linkType: static
- package: PostHog
linkType: static
- package: SwiftyBeaver
linkType: static
- package: SwiftState
@ -76,8 +80,10 @@ targets:
- path: ../../Tools/Scripts/Templates/SimpleScreenExample/Tests/UI
- path: ../../ElementX/Sources/BuildSettings.swift
- path: ../../ElementX/Sources/Screens/RoomScreen/View/Style/TimelineStyle.swift
- path: ../../ElementX/Sources/Services/Analytics/AnalyticsConfiguration.swift
- path: ../../ElementX/Sources/UITestScreenIdentifier.swift
- path: ../../ElementX/Sources/Generated/Strings.swift
- path: ../../ElementX/Sources/Generated/Strings+Untranslated.swift
- path: ../../ElementX/Sources/Generated/InfoPlist.swift
- path: ../../ElementX/Resources
- path: ../../ElementX/Sources/Other/Extensions/Bundle.swift