mirror of
https://github.com/Novaloop-AG/element-x-ios.git
synced 2026-11-04 01:20:12 +00:00
New notifications section in settings (#1273)
This commit is contained in:
@@ -61,6 +61,7 @@
|
||||
167D00CAA13FAFB822298021 /* MediaProviderTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 62A81CCC2516D9CF9322DF01 /* MediaProviderTests.swift */; };
|
||||
1702981A8085BE4FB0EC001B /* Application.swift in Sources */ = {isa = PBXBuildFile; fileRef = D33116993D54FADC0C721C1F /* Application.swift */; };
|
||||
172E6E9A612ADCF10A62CF13 /* BugReportServiceProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9A68BCE6438873D2661D93D0 /* BugReportServiceProtocol.swift */; };
|
||||
17780569FB41E9BAC60D4710 /* UNUserNotificationCenter+Settings.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9E685274772980BDEFF6691E /* UNUserNotificationCenter+Settings.swift */; };
|
||||
18867F4F1C8991EEC56EA932 /* UTType.swift in Sources */ = {isa = PBXBuildFile; fileRef = 897DF5E9A70CE05A632FC8AF /* UTType.swift */; };
|
||||
1950A80CD198BED283DFC2CE /* ClientProxy.swift in Sources */ = {isa = PBXBuildFile; fileRef = 18F2958E6D247AE2516BEEE8 /* ClientProxy.swift */; };
|
||||
19FE025AE9BA2959B6589B0D /* RoomMemberDetailsScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1CC575D1895FA62591451A93 /* RoomMemberDetailsScreen.swift */; };
|
||||
@@ -269,6 +270,7 @@
|
||||
664F77F02A57617A00FB9B24 /* XCTestCase.swift in Sources */ = {isa = PBXBuildFile; fileRef = 664F77EF2A57617A00FB9B24 /* XCTestCase.swift */; };
|
||||
6713835120D94BAA8ED7E3E5 /* MessageForwardingScreenUITests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 59846FA04E1DBBFDD8829C2A /* MessageForwardingScreenUITests.swift */; };
|
||||
67160204A8D362BB7D4AD259 /* Search.swift in Sources */ = {isa = PBXBuildFile; fileRef = 693E16574C6F7F9FA1015A8C /* Search.swift */; };
|
||||
6786C4B0936AC84D993B20BF /* NotificationSettingsScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = C5F06F2F09B2EDD067DC2174 /* NotificationSettingsScreen.swift */; };
|
||||
67C05C50AD734283374605E3 /* MatrixEntityRegex.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6AD1A853D605C2146B0DC028 /* MatrixEntityRegex.swift */; };
|
||||
67D6E0700A9C1E676F6231F8 /* Collections in Frameworks */ = {isa = PBXBuildFile; productRef = AD544C0FA48DFFB080920061 /* Collections */; };
|
||||
68184EF36396424FE19A727D /* MediaLoader.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8AFCE895ECFFA53FEE64D62B /* MediaLoader.swift */; };
|
||||
@@ -337,6 +339,7 @@
|
||||
7F08F4BC1312075E2B5EAEFA /* AuthenticationServiceProxy.swift in Sources */ = {isa = PBXBuildFile; fileRef = CF48AF076424DBC1615C74AD /* AuthenticationServiceProxy.swift */; };
|
||||
7F61F9ACD5EC9E845EF3EFBF /* BugReportServiceTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = EFFD3200F9960D4996159F10 /* BugReportServiceTests.swift */; };
|
||||
7F64FA937B95924B3A44EC12 /* OnboardingScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = AB8E75B9CB6C78BE8D09B1AF /* OnboardingScreen.swift */; };
|
||||
7F7EA51A9A43125A8CB6AC90 /* NotificationSettingsScreenViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 46D560DDA3B20C82766ACFAD /* NotificationSettingsScreenViewModel.swift */; };
|
||||
7FB0BDE26838F1A92782D5E1 /* MediaUploadPreviewScreenUITests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 39B6C8690AEA1E49FF1BAF95 /* MediaUploadPreviewScreenUITests.swift */; };
|
||||
8024BE37156FF0A95A7A3465 /* AnalyticsPromptUITests.swift in Sources */ = {isa = PBXBuildFile; fileRef = AF11DD57D9FACF2A757AB024 /* AnalyticsPromptUITests.swift */; };
|
||||
804C15D8ADE0EA7A5268F58A /* OverridableAvatarImage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 648DD1C10E4957CB791FE0B8 /* OverridableAvatarImage.swift */; };
|
||||
@@ -492,6 +495,7 @@
|
||||
AF19D65A9C60C6B2646F3210 /* RedactedRoomTimelineItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = E6E6BDF9D26DB05C88901416 /* RedactedRoomTimelineItem.swift */; };
|
||||
AF2ABA2794E376B64104C964 /* MockSoftLogoutScreenState.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5644919DB2022397D9D5825A /* MockSoftLogoutScreenState.swift */; };
|
||||
AF33B9044498211C3D82F1E1 /* UNTextInputNotificationResponse+Creator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 130ED565A078F7E0B59D9D25 /* UNTextInputNotificationResponse+Creator.swift */; };
|
||||
AF4232E6F08C3DB86FFA9BBD /* NotificationSettingsScreenUITests.swift in Sources */ = {isa = PBXBuildFile; fileRef = B83BC0DC9A2DF2DD60F9B6E9 /* NotificationSettingsScreenUITests.swift */; };
|
||||
AF8BFA37791E1756EE243E08 /* SettingsScreenCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B8F0ED874DF8C9A51B0AB6F /* SettingsScreenCoordinator.swift */; };
|
||||
B037C365CF8A58A0D149A2DB /* AuthenticationIconImage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 97755C01C3971474EFAD5367 /* AuthenticationIconImage.swift */; };
|
||||
B064D42BA087649ACAE462E8 /* SoftLogoutUITests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 55F30E764BED111C81739844 /* SoftLogoutUITests.swift */; };
|
||||
@@ -584,6 +588,7 @@
|
||||
CB6BCBF28E4B76EA08C2926D /* StateRoomTimelineItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = B16048D30F0438731C41F775 /* StateRoomTimelineItem.swift */; };
|
||||
CB99B0FA38A4AC596F38CC13 /* KeychainControllerProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = E5E94DCFEE803E5ABAE8ACCE /* KeychainControllerProtocol.swift */; };
|
||||
CBA9EDF305036039166E76FF /* StartChatScreenUITests.swift in Sources */ = {isa = PBXBuildFile; fileRef = DA2AEC1AB349A341FE13DEC1 /* StartChatScreenUITests.swift */; };
|
||||
CBD2ABE4C1A47ECD99E1488E /* NotificationSettingsScreenViewModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 421FA93BCC2840E66E4F306F /* NotificationSettingsScreenViewModelProtocol.swift */; };
|
||||
CC0D088F505F33A20DC5590F /* RoomStateEventStringBuilderTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = AEEAFB646E583655652C3D04 /* RoomStateEventStringBuilderTests.swift */; };
|
||||
CC961529F9F1854BEC3272C9 /* LayoutMocks.swift in Sources */ = {isa = PBXBuildFile; fileRef = BC8AA23D4F37CC26564F63C5 /* LayoutMocks.swift */; };
|
||||
CCAA0671B46EAFD0BB528E2C /* apple_emojis_data.json in Resources */ = {isa = PBXBuildFile; fileRef = 8FC26871038FB0E4AAE22605 /* apple_emojis_data.json */; };
|
||||
@@ -598,6 +603,7 @@
|
||||
CF3827071B0BC9638BD44F5D /* WaitlistScreenViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1AB58EF0176D4CFB1040DA22 /* WaitlistScreenViewModel.swift */; };
|
||||
CF4044A8EED5C41BC0ED6ABE /* SoftLogoutScreenViewModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = D316BB02636AF2174F2580E6 /* SoftLogoutScreenViewModelProtocol.swift */; };
|
||||
D02AA6208C7ACB9BE6332394 /* UNNotificationContent.swift in Sources */ = {isa = PBXBuildFile; fileRef = BE148A4FFEE853C5A281500C /* UNNotificationContent.swift */; };
|
||||
D12F440F7973F1489F61389D /* NotificationSettingsScreenModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0F64447FF544298A6A3BEF85 /* NotificationSettingsScreenModels.swift */; };
|
||||
D181AC8FF236B7F91C0A8C28 /* MapTiler.swift in Sources */ = {isa = PBXBuildFile; fileRef = 23AA3F4B285570805CB0CCDD /* MapTiler.swift */; };
|
||||
D2A15D03F81342A09340BD56 /* AnalyticsScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = FEFEEE93B82937B2E86F92EB /* AnalyticsScreen.swift */; };
|
||||
D2D70B5DB1A5E4AF0CD88330 /* target.yml in Resources */ = {isa = PBXBuildFile; fileRef = 033DB41C51865A2E83174E87 /* target.yml */; };
|
||||
@@ -648,6 +654,7 @@
|
||||
E2DDA49BD62F03F180A42E30 /* MapLibreStaticMapView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 592A35163B0749C66BFD6186 /* MapLibreStaticMapView.swift */; };
|
||||
E313BDD2B8813144139B2E00 /* UserDiscoveryServiceTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0287793F11C480E242B03DF5 /* UserDiscoveryServiceTest.swift */; };
|
||||
E3291AD16D7A5CB14781819C /* UserNotificationCenterProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 45D8149FDDA0315CDC553B4B /* UserNotificationCenterProtocol.swift */; };
|
||||
E3AC72E3E58F364EF15C1CC7 /* NotificationSettingsScreenViewModelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 514363244AE7D68080D44C6F /* NotificationSettingsScreenViewModelTests.swift */; };
|
||||
E3CA565A4B9704F191B191F0 /* JoinedRoomSize+MemberCount.swift in Sources */ = {isa = PBXBuildFile; fileRef = CBF9AEA706926DD0DA2B954C /* JoinedRoomSize+MemberCount.swift */; };
|
||||
E3E1E255DC8CB34BD8573E0D /* UserIndicatorControllerProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = A12D3B1BCF920880CA8BBB6B /* UserIndicatorControllerProtocol.swift */; };
|
||||
E45C9FA22BC13B477FD3B4AC /* EmojiDetection.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5D99730313BEBF08CDE81EE3 /* EmojiDetection.swift */; };
|
||||
@@ -705,6 +712,7 @@
|
||||
F656F92A63D3DC1978D79427 /* Compound in Frameworks */ = {isa = PBXBuildFile; productRef = 07FEEEDB11543A7DED420F04 /* Compound */; };
|
||||
F692D4AF571333C0D785725A /* MigrationScreenViewModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = EBBC5E7C0F8337D2A46EB2DD /* MigrationScreenViewModelProtocol.swift */; };
|
||||
F697284B9B5F2C00CFEA3B12 /* EmojiDetectionTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = A58E93D91DE3288010390DEE /* EmojiDetectionTests.swift */; };
|
||||
F6DFA23885980118AD7359C5 /* NotificationSettingsScreenCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2389732B0E115A999A069083 /* NotificationSettingsScreenCoordinator.swift */; };
|
||||
F6F49E37272AD7397CD29A01 /* HomeScreenViewModelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 505208F28007C0FEC14E1FF0 /* HomeScreenViewModelTests.swift */; };
|
||||
F7567DD6635434E8C563BF85 /* AnalyticsClientProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = E3B97591B2D3D4D67553506D /* AnalyticsClientProtocol.swift */; };
|
||||
F777C6FEE7D106136E2ED2B2 /* MessageForwardingScreenViewModelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6F6E6EDC4BBF962B2ED595A4 /* MessageForwardingScreenViewModelTests.swift */; };
|
||||
@@ -822,6 +830,7 @@
|
||||
0E8BDC092D817B68CD9040C5 /* UserSessionStore.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserSessionStore.swift; sourceTree = "<group>"; };
|
||||
0F19DBE940499D3E3DD405D8 /* RoomMemberDetailsScreenUITests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomMemberDetailsScreenUITests.swift; sourceTree = "<group>"; };
|
||||
0F5567A7EF6F2AB9473236F6 /* DocumentPicker.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DocumentPicker.swift; sourceTree = "<group>"; };
|
||||
0F64447FF544298A6A3BEF85 /* NotificationSettingsScreenModels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationSettingsScreenModels.swift; sourceTree = "<group>"; };
|
||||
0FA60F848D1C14F873F9621A /* RoomMemberDetailsScreenCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomMemberDetailsScreenCoordinator.swift; sourceTree = "<group>"; };
|
||||
0FB782CE6176A5D2C082EC5D /* WelcomeScreenScreenModels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WelcomeScreenScreenModels.swift; sourceTree = "<group>"; };
|
||||
1059E2AE7878CF7820592637 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist; path = Info.plist; sourceTree = "<group>"; };
|
||||
@@ -885,6 +894,7 @@
|
||||
225EFCA26877E75CDFE7F48D /* MapTilerStyleBuilderProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MapTilerStyleBuilderProtocol.swift; sourceTree = "<group>"; };
|
||||
22730A30C50AC2E3D5BA8642 /* InviteUsersScreenViewModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InviteUsersScreenViewModelProtocol.swift; sourceTree = "<group>"; };
|
||||
227AC5D71A4CE43512062243 /* URL.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = URL.swift; sourceTree = "<group>"; };
|
||||
2389732B0E115A999A069083 /* NotificationSettingsScreenCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationSettingsScreenCoordinator.swift; sourceTree = "<group>"; };
|
||||
23AA3F4B285570805CB0CCDD /* MapTiler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MapTiler.swift; sourceTree = "<group>"; };
|
||||
24227FF9A2797F6EA7F69CDD /* HomeScreenInvitesButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HomeScreenInvitesButton.swift; sourceTree = "<group>"; };
|
||||
2429224EB0EEA34D35CE9249 /* UserIndicatorControllerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserIndicatorControllerTests.swift; sourceTree = "<group>"; };
|
||||
@@ -956,6 +966,7 @@
|
||||
4132F882A984ED971338EE9D /* ReportContentScreenUITests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ReportContentScreenUITests.swift; sourceTree = "<group>"; };
|
||||
4176C3E20C772DE8D182863C /* LegalInformationScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LegalInformationScreen.swift; sourceTree = "<group>"; };
|
||||
421E716C521F96D24ECE69B3 /* NoticeRoomTimelineItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NoticeRoomTimelineItem.swift; sourceTree = "<group>"; };
|
||||
421FA93BCC2840E66E4F306F /* NotificationSettingsScreenViewModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationSettingsScreenViewModelProtocol.swift; sourceTree = "<group>"; };
|
||||
422724361B6555364C43281E /* RoomHeaderView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomHeaderView.swift; sourceTree = "<group>"; };
|
||||
42ADEA322D2089391E049535 /* InvitesScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InvitesScreen.swift; sourceTree = "<group>"; };
|
||||
42C64A14EE89928207E3B42B /* AnalyticsSettingsScreenModels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AnalyticsSettingsScreenModels.swift; sourceTree = "<group>"; };
|
||||
@@ -970,6 +981,7 @@
|
||||
466C71A0FED9BFF287613C82 /* RoomDetailsScreenModels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomDetailsScreenModels.swift; sourceTree = "<group>"; };
|
||||
46B59EC4B0C93254089EAACB /* MigrationScreenViewModelTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MigrationScreenViewModelTests.swift; sourceTree = "<group>"; };
|
||||
46C208DA43CE25D13E670F40 /* UITestsAppCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UITestsAppCoordinator.swift; sourceTree = "<group>"; };
|
||||
46D560DDA3B20C82766ACFAD /* NotificationSettingsScreenViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationSettingsScreenViewModel.swift; sourceTree = "<group>"; };
|
||||
47111410B6E659A697D472B5 /* RoomProxyProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomProxyProtocol.swift; sourceTree = "<group>"; };
|
||||
471EB7D96AFEA8D787659686 /* EmoteRoomTimelineView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EmoteRoomTimelineView.swift; sourceTree = "<group>"; };
|
||||
47873756E45B46683D97DC32 /* LegalInformationScreenModels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LegalInformationScreenModels.swift; sourceTree = "<group>"; };
|
||||
@@ -998,6 +1010,7 @@
|
||||
505208F28007C0FEC14E1FF0 /* HomeScreenViewModelTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HomeScreenViewModelTests.swift; sourceTree = "<group>"; };
|
||||
5098DA7799946A61E34A2373 /* FileRoomTimelineItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FileRoomTimelineItem.swift; sourceTree = "<group>"; };
|
||||
50E31AB0E77BB70E2BC77463 /* MatrixUserShareLink.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MatrixUserShareLink.swift; sourceTree = "<group>"; };
|
||||
514363244AE7D68080D44C6F /* NotificationSettingsScreenViewModelTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationSettingsScreenViewModelTests.swift; sourceTree = "<group>"; };
|
||||
51C2BCE0BC1FC69C1B36E688 /* BugReportScreenModels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BugReportScreenModels.swift; sourceTree = "<group>"; };
|
||||
51C454AE59914B551A6D02C0 /* UserProfileProxy.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserProfileProxy.swift; sourceTree = "<group>"; };
|
||||
52135BD9E0E7A091688F627A /* MessageForwardingScreenModels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MessageForwardingScreenModels.swift; sourceTree = "<group>"; };
|
||||
@@ -1189,6 +1202,7 @@
|
||||
9C698E30698EC59302A8EEBD /* NavigationStackCoordinatorTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NavigationStackCoordinatorTests.swift; sourceTree = "<group>"; };
|
||||
9C7F7DE62D33C6A26CBFCD72 /* IntegrationTests.xctest */ = {isa = PBXFileReference; includeInIndex = 0; lastKnownFileType = wrapper.cfbundle; path = IntegrationTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
9CE3C90E487B255B735D73C8 /* RoomScreenViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomScreenViewModel.swift; sourceTree = "<group>"; };
|
||||
9E685274772980BDEFF6691E /* UNUserNotificationCenter+Settings.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UNUserNotificationCenter+Settings.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>"; };
|
||||
@@ -1262,6 +1276,7 @@
|
||||
B7F0192CE2F891141A25B49F /* UITestsSignalling.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UITestsSignalling.swift; sourceTree = "<group>"; };
|
||||
B8108C8F0ACF6A7EB72D0117 /* RoomScreenCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomScreenCoordinator.swift; sourceTree = "<group>"; };
|
||||
B81B6170DB690013CEB646F4 /* MapLibreModels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MapLibreModels.swift; sourceTree = "<group>"; };
|
||||
B83BC0DC9A2DF2DD60F9B6E9 /* NotificationSettingsScreenUITests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationSettingsScreenUITests.swift; sourceTree = "<group>"; };
|
||||
B858A61F2A570DFB8DE570A7 /* AggregratedReaction.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AggregratedReaction.swift; sourceTree = "<group>"; };
|
||||
B8A3B7637DDBD6AA97AC2545 /* CameraPicker.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CameraPicker.swift; sourceTree = "<group>"; };
|
||||
B8F28602AC7AC881AED37EBA /* NavigationCoordinators.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NavigationCoordinators.swift; sourceTree = "<group>"; };
|
||||
@@ -1301,6 +1316,7 @@
|
||||
C54464351F170D570110AFCA /* WelcomeScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WelcomeScreen.swift; sourceTree = "<group>"; };
|
||||
C55D7E514F9DE4E3D72FDCAD /* SessionVerificationControllerProxy.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SessionVerificationControllerProxy.swift; sourceTree = "<group>"; };
|
||||
C5B7A755E985FA14469E86B2 /* RoomMembersListScreenUITests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomMembersListScreenUITests.swift; sourceTree = "<group>"; };
|
||||
C5F06F2F09B2EDD067DC2174 /* NotificationSettingsScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationSettingsScreen.swift; sourceTree = "<group>"; };
|
||||
C616D90B1E2F033CAA325439 /* StaticLocationScreenViewModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StaticLocationScreenViewModelProtocol.swift; sourceTree = "<group>"; };
|
||||
C618CA2B6C8758B06C88013C /* CreateRoomCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CreateRoomCoordinator.swift; sourceTree = "<group>"; };
|
||||
C687844F60BFF532D49A994C /* AnalyticsTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AnalyticsTests.swift; sourceTree = "<group>"; };
|
||||
@@ -2326,6 +2342,7 @@
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
C830A64609CBD152F06E0457 /* NotificationConstants.swift */,
|
||||
A9E072BD31B744FC34F4D368 /* Helper */,
|
||||
6EE5E2BBFBC7947CFE789B4D /* Manager */,
|
||||
832FC81F760220239E285294 /* Proxy */,
|
||||
);
|
||||
@@ -2349,6 +2366,7 @@
|
||||
09C599CB430ABF160C1EE55C /* AnalyticsSettingsScreen */,
|
||||
1CA6CD0DE6F0445156361B6D /* DeveloperOptionsScreen */,
|
||||
38A1C74493B816B8753F5BC2 /* LegalInformationScreen */,
|
||||
7B91CB64534AD870924CCFEF /* NotificationSettingsScreen */,
|
||||
B364E08924AD15820350CDD9 /* SettingsScreen */,
|
||||
);
|
||||
path = Settings;
|
||||
@@ -2420,6 +2438,7 @@
|
||||
F875D71347DC81EAE7687446 /* NavigationRootCoordinatorTests.swift */,
|
||||
78913D6E120D46138E97C107 /* NavigationSplitCoordinatorTests.swift */,
|
||||
9C698E30698EC59302A8EEBD /* NavigationStackCoordinatorTests.swift */,
|
||||
514363244AE7D68080D44C6F /* NotificationSettingsScreenViewModelTests.swift */,
|
||||
00A941F289F6AB876BA3361A /* OnboardingViewModelTests.swift */,
|
||||
6FB31A32C93D94930B253FBF /* PermalinkBuilderTests.swift */,
|
||||
086C19086DD16E9B38E25954 /* ReportContentViewModelTests.swift */,
|
||||
@@ -2568,6 +2587,18 @@
|
||||
path = View;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
7B91CB64534AD870924CCFEF /* NotificationSettingsScreen */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
2389732B0E115A999A069083 /* NotificationSettingsScreenCoordinator.swift */,
|
||||
0F64447FF544298A6A3BEF85 /* NotificationSettingsScreenModels.swift */,
|
||||
46D560DDA3B20C82766ACFAD /* NotificationSettingsScreenViewModel.swift */,
|
||||
421FA93BCC2840E66E4F306F /* NotificationSettingsScreenViewModelProtocol.swift */,
|
||||
BE7641A284D3E81DC96943E3 /* View */,
|
||||
);
|
||||
path = NotificationSettingsScreen;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
7DBC911559934065993A5FF4 /* NotificationManager */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
@@ -2792,6 +2823,7 @@
|
||||
39B6C8690AEA1E49FF1BAF95 /* MediaUploadPreviewScreenUITests.swift */,
|
||||
59846FA04E1DBBFDD8829C2A /* MessageForwardingScreenUITests.swift */,
|
||||
75910F5A36EA8FF9BAD08D18 /* MigrationScreenUITests.swift */,
|
||||
B83BC0DC9A2DF2DD60F9B6E9 /* NotificationSettingsScreenUITests.swift */,
|
||||
0C88046D6A070D9827181C4D /* OnboardingUITests.swift */,
|
||||
4132F882A984ED971338EE9D /* ReportContentScreenUITests.swift */,
|
||||
122186B7CD1BC46A9C629DD9 /* RoomDetailsEditScreenUITests.swift */,
|
||||
@@ -2970,6 +3002,14 @@
|
||||
path = View;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
A9E072BD31B744FC34F4D368 /* Helper */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
9E685274772980BDEFF6691E /* UNUserNotificationCenter+Settings.swift */,
|
||||
);
|
||||
path = Helper;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
AAFDD509929A0CCF8BCE51EB /* Authentication */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
@@ -3131,6 +3171,14 @@
|
||||
path = ServerConfirmationScreen;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
BE7641A284D3E81DC96943E3 /* View */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
C5F06F2F09B2EDD067DC2174 /* NotificationSettingsScreen.swift */,
|
||||
);
|
||||
path = View;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
C0937E3B06A8F0E2DB7C8241 /* Other */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
@@ -4037,6 +4085,7 @@
|
||||
69C7B956B74BEC3DB88224EA /* NavigationSplitCoordinatorTests.swift in Sources */,
|
||||
4BB282209EA82015D0DF8F89 /* NavigationStackCoordinatorTests.swift in Sources */,
|
||||
1B2DADC008EE211AF1DA5292 /* NotificationManagerTests.swift in Sources */,
|
||||
E3AC72E3E58F364EF15C1CC7 /* NotificationSettingsScreenViewModelTests.swift in Sources */,
|
||||
F9F6D2883BBEBB9A3789A137 /* OnboardingViewModelTests.swift in Sources */,
|
||||
27E9263DA75E266690A37EB1 /* PermalinkBuilderTests.swift in Sources */,
|
||||
D415764645491F10344FC6AC /* Publisher.swift in Sources */,
|
||||
@@ -4341,6 +4390,11 @@
|
||||
CE9530A4CA661E090635C2F2 /* NotificationItemProxy.swift in Sources */,
|
||||
652ACCF104A8CEF30788963C /* NotificationManager.swift in Sources */,
|
||||
06D3942496E9E0E655F14D21 /* NotificationManagerProtocol.swift in Sources */,
|
||||
6786C4B0936AC84D993B20BF /* NotificationSettingsScreen.swift in Sources */,
|
||||
F6DFA23885980118AD7359C5 /* NotificationSettingsScreenCoordinator.swift in Sources */,
|
||||
D12F440F7973F1489F61389D /* NotificationSettingsScreenModels.swift in Sources */,
|
||||
7F7EA51A9A43125A8CB6AC90 /* NotificationSettingsScreenViewModel.swift in Sources */,
|
||||
CBD2ABE4C1A47ECD99E1488E /* NotificationSettingsScreenViewModelProtocol.swift in Sources */,
|
||||
9A4E3D5AA44B041DAC3A0D81 /* OIDCAuthenticationPresenter.swift in Sources */,
|
||||
329571083B132E4941131835 /* OnboardingBackgroundImage.swift in Sources */,
|
||||
2CB6787E25B11711518E9588 /* OnboardingCoordinator.swift in Sources */,
|
||||
@@ -4530,6 +4584,7 @@
|
||||
22882C710BC99EC34A5024A0 /* UITestsScreenIdentifier.swift in Sources */,
|
||||
706289B086B0A6B0C211763F /* UITestsSignalling.swift in Sources */,
|
||||
D02AA6208C7ACB9BE6332394 /* UNNotificationContent.swift in Sources */,
|
||||
17780569FB41E9BAC60D4710 /* UNUserNotificationCenter+Settings.swift in Sources */,
|
||||
071A017E415AD378F2961B11 /* URL.swift in Sources */,
|
||||
90733645AE76FB33DAD28C2B /* URLSession.swift in Sources */,
|
||||
18867F4F1C8991EEC56EA932 /* UTType.swift in Sources */,
|
||||
@@ -4598,6 +4653,7 @@
|
||||
7FB0BDE26838F1A92782D5E1 /* MediaUploadPreviewScreenUITests.swift in Sources */,
|
||||
6713835120D94BAA8ED7E3E5 /* MessageForwardingScreenUITests.swift in Sources */,
|
||||
51C240F4660F7269203A9B3A /* MigrationScreenUITests.swift in Sources */,
|
||||
AF4232E6F08C3DB86FFA9BBD /* NotificationSettingsScreenUITests.swift in Sources */,
|
||||
6B15FF984906AAFCF9DC4F58 /* OnboardingUITests.swift in Sources */,
|
||||
BA0D3DDCEDD97502DAC4B6E9 /* ReportContentScreenUITests.swift in Sources */,
|
||||
F16109A6F6DF03DA26D59233 /* RoomDetailsEditScreenUITests.swift in Sources */,
|
||||
|
||||
@@ -133,12 +133,14 @@ class AppCoordinator: AppCoordinatorProtocol, AuthenticationCoordinatorDelegate,
|
||||
|
||||
// MARK: - NotificationManagerDelegate
|
||||
|
||||
func authorizationStatusUpdated(_ service: NotificationManagerProtocol, granted: Bool) {
|
||||
if granted {
|
||||
UIApplication.shared.registerForRemoteNotifications()
|
||||
}
|
||||
func registerForRemoteNotifications() {
|
||||
UIApplication.shared.registerForRemoteNotifications()
|
||||
}
|
||||
|
||||
func unregisterForRemoteNotifications() {
|
||||
UIApplication.shared.unregisterForRemoteNotifications()
|
||||
}
|
||||
|
||||
func shouldDisplayInAppNotification(_ service: NotificationManagerProtocol, content: UNNotificationContent) -> Bool {
|
||||
guard let roomId = content.roomID else {
|
||||
return true
|
||||
|
||||
@@ -26,6 +26,7 @@ final class AppSettings {
|
||||
case migratedAccounts
|
||||
case timelineStyle
|
||||
case analyticsConsentState
|
||||
case enableNotifications
|
||||
case enableInAppNotifications
|
||||
case pusherProfileTag
|
||||
case shouldCollapseRoomStateEvents
|
||||
@@ -34,6 +35,7 @@ final class AppSettings {
|
||||
case locationEventsEnabled
|
||||
case shareLocationEnabled
|
||||
case hasShownWelcomeScreen
|
||||
case notificationSettingsEnabled
|
||||
}
|
||||
|
||||
private static var suiteName: String = InfoPlistReader.main.appGroupIdentifier
|
||||
@@ -178,6 +180,9 @@ final class AppSettings {
|
||||
|
||||
// MARK: - Notifications
|
||||
|
||||
@UserPreference(key: UserDefaultsKeys.enableNotifications, defaultValue: true, storageType: .userDefaults(store))
|
||||
var enableNotifications
|
||||
|
||||
@UserPreference(key: UserDefaultsKeys.enableInAppNotifications, defaultValue: true, storageType: .userDefaults(store))
|
||||
var enableInAppNotifications
|
||||
|
||||
@@ -218,4 +223,7 @@ final class AppSettings {
|
||||
|
||||
@UserPreference(key: UserDefaultsKeys.shareLocationEnabled, defaultValue: false, storageType: .userDefaults(store))
|
||||
var shareLocationEnabled
|
||||
|
||||
@UserPreference(key: UserDefaultsKeys.notificationSettingsEnabled, defaultValue: false, storageType: .userDefaults(store))
|
||||
var notificationSettingsEnabled
|
||||
}
|
||||
|
||||
@@ -1317,4 +1317,86 @@ class UserIndicatorControllerMock: UserIndicatorControllerProtocol {
|
||||
}
|
||||
}
|
||||
}
|
||||
class UserNotificationCenterMock: UserNotificationCenterProtocol {
|
||||
var delegate: UNUserNotificationCenterDelegate?
|
||||
|
||||
//MARK: - add
|
||||
|
||||
var addThrowableError: Error?
|
||||
var addCallsCount = 0
|
||||
var addCalled: Bool {
|
||||
return addCallsCount > 0
|
||||
}
|
||||
var addReceivedRequest: UNNotificationRequest?
|
||||
var addReceivedInvocations: [UNNotificationRequest] = []
|
||||
var addClosure: ((UNNotificationRequest) async throws -> Void)?
|
||||
|
||||
func add(_ request: UNNotificationRequest) async throws {
|
||||
if let error = addThrowableError {
|
||||
throw error
|
||||
}
|
||||
addCallsCount += 1
|
||||
addReceivedRequest = request
|
||||
addReceivedInvocations.append(request)
|
||||
try await addClosure?(request)
|
||||
}
|
||||
//MARK: - requestAuthorization
|
||||
|
||||
var requestAuthorizationOptionsThrowableError: Error?
|
||||
var requestAuthorizationOptionsCallsCount = 0
|
||||
var requestAuthorizationOptionsCalled: Bool {
|
||||
return requestAuthorizationOptionsCallsCount > 0
|
||||
}
|
||||
var requestAuthorizationOptionsReceivedOptions: UNAuthorizationOptions?
|
||||
var requestAuthorizationOptionsReceivedInvocations: [UNAuthorizationOptions] = []
|
||||
var requestAuthorizationOptionsReturnValue: Bool!
|
||||
var requestAuthorizationOptionsClosure: ((UNAuthorizationOptions) async throws -> Bool)?
|
||||
|
||||
func requestAuthorization(options: UNAuthorizationOptions) async throws -> Bool {
|
||||
if let error = requestAuthorizationOptionsThrowableError {
|
||||
throw error
|
||||
}
|
||||
requestAuthorizationOptionsCallsCount += 1
|
||||
requestAuthorizationOptionsReceivedOptions = options
|
||||
requestAuthorizationOptionsReceivedInvocations.append(options)
|
||||
if let requestAuthorizationOptionsClosure = requestAuthorizationOptionsClosure {
|
||||
return try await requestAuthorizationOptionsClosure(options)
|
||||
} else {
|
||||
return requestAuthorizationOptionsReturnValue
|
||||
}
|
||||
}
|
||||
//MARK: - setNotificationCategories
|
||||
|
||||
var setNotificationCategoriesCallsCount = 0
|
||||
var setNotificationCategoriesCalled: Bool {
|
||||
return setNotificationCategoriesCallsCount > 0
|
||||
}
|
||||
var setNotificationCategoriesReceivedCategories: Set<UNNotificationCategory>?
|
||||
var setNotificationCategoriesReceivedInvocations: [Set<UNNotificationCategory>] = []
|
||||
var setNotificationCategoriesClosure: ((Set<UNNotificationCategory>) -> Void)?
|
||||
|
||||
func setNotificationCategories(_ categories: Set<UNNotificationCategory>) {
|
||||
setNotificationCategoriesCallsCount += 1
|
||||
setNotificationCategoriesReceivedCategories = categories
|
||||
setNotificationCategoriesReceivedInvocations.append(categories)
|
||||
setNotificationCategoriesClosure?(categories)
|
||||
}
|
||||
//MARK: - authorizationStatus
|
||||
|
||||
var authorizationStatusCallsCount = 0
|
||||
var authorizationStatusCalled: Bool {
|
||||
return authorizationStatusCallsCount > 0
|
||||
}
|
||||
var authorizationStatusReturnValue: UNAuthorizationStatus!
|
||||
var authorizationStatusClosure: (() async -> UNAuthorizationStatus)?
|
||||
|
||||
func authorizationStatus() async -> UNAuthorizationStatus {
|
||||
authorizationStatusCallsCount += 1
|
||||
if let authorizationStatusClosure = authorizationStatusClosure {
|
||||
return await authorizationStatusClosure()
|
||||
} else {
|
||||
return authorizationStatusReturnValue
|
||||
}
|
||||
}
|
||||
}
|
||||
// swiftlint:enable all
|
||||
|
||||
+2
@@ -31,6 +31,7 @@ struct DeveloperOptionsScreenViewStateBindings {
|
||||
var isEncryptionSyncEnabled: Bool
|
||||
var locationEventsEnabled: Bool
|
||||
var shareLocationEnabled: Bool
|
||||
var notificationSettingsEnabled: Bool
|
||||
}
|
||||
|
||||
enum DeveloperOptionsScreenViewAction {
|
||||
@@ -40,5 +41,6 @@ enum DeveloperOptionsScreenViewAction {
|
||||
case changedIsEncryptionSyncEnabled
|
||||
case changedLocationEventsEnabled
|
||||
case changedShareLocationEnabled
|
||||
case changedNotificationSettingsEnabled
|
||||
case clearCache
|
||||
}
|
||||
|
||||
+4
-1
@@ -31,7 +31,8 @@ class DeveloperOptionsScreenViewModel: DeveloperOptionsScreenViewModelType, Deve
|
||||
readReceiptsEnabled: appSettings.readReceiptsEnabled,
|
||||
isEncryptionSyncEnabled: appSettings.isEncryptionSyncEnabled,
|
||||
locationEventsEnabled: appSettings.locationEventsEnabled,
|
||||
shareLocationEnabled: appSettings.shareLocationEnabled)
|
||||
shareLocationEnabled: appSettings.shareLocationEnabled,
|
||||
notificationSettingsEnabled: appSettings.notificationSettingsEnabled)
|
||||
let state = DeveloperOptionsScreenViewState(bindings: bindings)
|
||||
|
||||
super.init(initialViewState: state)
|
||||
@@ -55,6 +56,8 @@ class DeveloperOptionsScreenViewModel: DeveloperOptionsScreenViewModelType, Deve
|
||||
appSettings.locationEventsEnabled = state.bindings.locationEventsEnabled
|
||||
case .changedShareLocationEnabled:
|
||||
appSettings.shareLocationEnabled = state.bindings.shareLocationEnabled
|
||||
case .changedNotificationSettingsEnabled:
|
||||
appSettings.notificationSettingsEnabled = state.bindings.notificationSettingsEnabled
|
||||
case .clearCache:
|
||||
callback?(.clearCache)
|
||||
}
|
||||
|
||||
+7
@@ -66,6 +66,13 @@ struct DeveloperOptionsScreen: View {
|
||||
.onChange(of: context.shareLocationEnabled) { _ in
|
||||
context.send(viewAction: .changedShareLocationEnabled)
|
||||
}
|
||||
|
||||
Toggle(isOn: $context.notificationSettingsEnabled) {
|
||||
Text("Show notification settings")
|
||||
}
|
||||
.onChange(of: context.notificationSettingsEnabled) { _ in
|
||||
context.send(viewAction: .changedNotificationSettingsEnabled)
|
||||
}
|
||||
}
|
||||
|
||||
Section {
|
||||
|
||||
+48
@@ -0,0 +1,48 @@
|
||||
//
|
||||
// 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 Combine
|
||||
import SwiftUI
|
||||
|
||||
struct NotificationSettingsScreenCoordinatorParameters {
|
||||
let userNotificationCenter: UserNotificationCenterProtocol
|
||||
}
|
||||
|
||||
enum NotificationSettingsScreenCoordinatorAction { }
|
||||
|
||||
final class NotificationSettingsScreenCoordinator: CoordinatorProtocol {
|
||||
private let parameters: NotificationSettingsScreenCoordinatorParameters
|
||||
private var viewModel: NotificationSettingsScreenViewModelProtocol
|
||||
private let actionsSubject: PassthroughSubject<NotificationSettingsScreenCoordinatorAction, Never> = .init()
|
||||
private var cancellables: Set<AnyCancellable> = .init()
|
||||
|
||||
var actions: AnyPublisher<NotificationSettingsScreenCoordinatorAction, Never> {
|
||||
actionsSubject.eraseToAnyPublisher()
|
||||
}
|
||||
|
||||
init(parameters: NotificationSettingsScreenCoordinatorParameters) {
|
||||
self.parameters = parameters
|
||||
|
||||
viewModel = NotificationSettingsScreenViewModel(appSettings: ServiceLocator.shared.settings,
|
||||
userNotificationCenter: parameters.userNotificationCenter)
|
||||
}
|
||||
|
||||
func start() { }
|
||||
|
||||
func toPresentable() -> AnyView {
|
||||
AnyView(NotificationSettingsScreen(context: viewModel.context))
|
||||
}
|
||||
}
|
||||
+53
@@ -0,0 +1,53 @@
|
||||
//
|
||||
// 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
|
||||
import UIKit
|
||||
|
||||
enum NotificationSettingsScreenViewModelAction { }
|
||||
|
||||
struct NotificationSettingsScreenViewState: BindableState {
|
||||
var bindings: NotificationSettingsScreenViewStateBindings
|
||||
var strings = NotificationSettingsScreenStrings()
|
||||
var isUserPermissionGranted: Bool?
|
||||
|
||||
var showSystemNotificationsAlert: Bool {
|
||||
bindings.enableNotifications && isUserPermissionGranted == false
|
||||
}
|
||||
}
|
||||
|
||||
struct NotificationSettingsScreenViewStateBindings {
|
||||
var enableNotifications = false
|
||||
}
|
||||
|
||||
struct NotificationSettingsScreenStrings {
|
||||
let changeYourSystemSettings: AttributedString = {
|
||||
let linkPlaceholder = "{link}"
|
||||
var text = AttributedString(L10n.screenNotificationSettingsSystemNotificationsActionRequired(linkPlaceholder))
|
||||
var linkString = AttributedString(L10n.screenNotificationSettingsSystemNotificationsActionRequiredContentLink)
|
||||
// Note: On the simulator, `UIApplication.openNotificationSettingsURLString` opens the `Settings` application instead of the application's notification settings screen.
|
||||
linkString.link = URL(string: UIApplication.openNotificationSettingsURLString)
|
||||
linkString.bold()
|
||||
text.replace(linkPlaceholder, with: linkString)
|
||||
|
||||
return text
|
||||
}()
|
||||
}
|
||||
|
||||
enum NotificationSettingsScreenViewAction {
|
||||
case linkClicked(url: URL)
|
||||
case changedEnableNotifications
|
||||
}
|
||||
+76
@@ -0,0 +1,76 @@
|
||||
//
|
||||
// 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 Combine
|
||||
import SwiftUI
|
||||
|
||||
typealias NotificationSettingsScreenViewModelType = StateStoreViewModel<NotificationSettingsScreenViewState, NotificationSettingsScreenViewAction>
|
||||
|
||||
class NotificationSettingsScreenViewModel: NotificationSettingsScreenViewModelType, NotificationSettingsScreenViewModelProtocol {
|
||||
private var actionsSubject: PassthroughSubject<NotificationSettingsScreenViewModelAction, Never> = .init()
|
||||
private let appSettings: AppSettings
|
||||
private let userNotificationCenter: UserNotificationCenterProtocol
|
||||
|
||||
var actions: AnyPublisher<NotificationSettingsScreenViewModelAction, Never> {
|
||||
actionsSubject.eraseToAnyPublisher()
|
||||
}
|
||||
|
||||
init(appSettings: AppSettings, userNotificationCenter: UserNotificationCenterProtocol) {
|
||||
self.appSettings = appSettings
|
||||
self.userNotificationCenter = userNotificationCenter
|
||||
let bindings = NotificationSettingsScreenViewStateBindings(enableNotifications: appSettings.enableNotifications)
|
||||
super.init(initialViewState: NotificationSettingsScreenViewState(bindings: bindings))
|
||||
|
||||
// Listen for changes to AppSettings.enableNotifications
|
||||
appSettings.$enableNotifications
|
||||
.weakAssign(to: \.state.bindings.enableNotifications, on: self)
|
||||
.store(in: &cancellables)
|
||||
|
||||
// Refresh authorization status uppon UIApplication.didBecomeActiveNotification notification
|
||||
NotificationCenter.default.publisher(for: UIApplication.didBecomeActiveNotification)
|
||||
.sink { [weak self] _ in
|
||||
Task {
|
||||
await self?.readSystemAuthorizationStatus()
|
||||
}
|
||||
}
|
||||
.store(in: &cancellables)
|
||||
|
||||
Task {
|
||||
await readSystemAuthorizationStatus()
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - Public
|
||||
|
||||
override func process(viewAction: NotificationSettingsScreenViewAction) {
|
||||
switch viewAction {
|
||||
case .linkClicked(let url):
|
||||
MXLog.warning("Link clicked: \(url)")
|
||||
case .changedEnableNotifications:
|
||||
toggleNotifications()
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - Private
|
||||
|
||||
func readSystemAuthorizationStatus() async {
|
||||
state.isUserPermissionGranted = await userNotificationCenter.authorizationStatus() == .authorized
|
||||
}
|
||||
|
||||
func toggleNotifications() {
|
||||
appSettings.enableNotifications.toggle()
|
||||
}
|
||||
}
|
||||
+23
@@ -0,0 +1,23 @@
|
||||
//
|
||||
// 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 Combine
|
||||
|
||||
@MainActor
|
||||
protocol NotificationSettingsScreenViewModelProtocol {
|
||||
var actions: AnyPublisher<NotificationSettingsScreenViewModelAction, Never> { get }
|
||||
var context: NotificationSettingsScreenViewModelType.Context { get }
|
||||
}
|
||||
+88
@@ -0,0 +1,88 @@
|
||||
//
|
||||
// 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 SwiftUI
|
||||
|
||||
struct NotificationSettingsScreen: View {
|
||||
@ObservedObject var context: NotificationSettingsScreenViewModel.Context
|
||||
|
||||
var body: some View {
|
||||
Form {
|
||||
if context.viewState.showSystemNotificationsAlert {
|
||||
userPermissionSection
|
||||
}
|
||||
enableNotificationSection
|
||||
}
|
||||
.compoundForm()
|
||||
.navigationTitle(L10n.screenNotificationSettingsTitle)
|
||||
.track(screen: .settingsNotifications)
|
||||
}
|
||||
|
||||
// MARK: - Private
|
||||
|
||||
private var userPermissionSection: some View {
|
||||
Section {
|
||||
HStack(alignment: .firstTextBaseline, spacing: 13) {
|
||||
Image(systemName: "exclamationmark.circle.fill")
|
||||
.foregroundColor(.compound.iconTertiaryAlpha)
|
||||
VStack(alignment: .leading, spacing: 2) {
|
||||
Text(L10n.screenNotificationSettingsSystemNotificationsTurnedOff)
|
||||
.font(.compound.bodyLG)
|
||||
.foregroundColor(.compound.textPrimary)
|
||||
Text(context.viewState.strings.changeYourSystemSettings)
|
||||
.font(.compound.bodySM)
|
||||
.foregroundColor(.compound.textSecondary)
|
||||
.tint(.compound.textPrimary)
|
||||
.environment(\.openURL, OpenURLAction { url in
|
||||
context.send(viewAction: .linkClicked(url: url))
|
||||
return .systemAction
|
||||
})
|
||||
}
|
||||
.padding(.vertical, 5)
|
||||
}
|
||||
}
|
||||
.compoundFormSection()
|
||||
}
|
||||
|
||||
private var enableNotificationSection: some View {
|
||||
Section {
|
||||
Toggle(isOn: $context.enableNotifications) {
|
||||
Text(L10n.screenNotificationSettingsEnableNotifications)
|
||||
}
|
||||
.toggleStyle(.compoundForm)
|
||||
.onChange(of: context.enableNotifications) { _ in
|
||||
context.send(viewAction: .changedEnableNotifications)
|
||||
}
|
||||
}
|
||||
.compoundFormSection()
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - Previews
|
||||
|
||||
struct NotificationSettingsScreen_Previews: PreviewProvider {
|
||||
static let viewModel: NotificationSettingsScreenViewModel = {
|
||||
let appSettings = AppSettings()
|
||||
let notificationCenter = UserNotificationCenterMock()
|
||||
notificationCenter.authorizationStatusReturnValue = .notDetermined
|
||||
var viewModel = NotificationSettingsScreenViewModel(appSettings: appSettings, userNotificationCenter: notificationCenter)
|
||||
return viewModel
|
||||
}()
|
||||
|
||||
static var previews: some View {
|
||||
NotificationSettingsScreen(context: viewModel.context)
|
||||
}
|
||||
}
|
||||
@@ -59,6 +59,8 @@ final class SettingsScreenCoordinator: CoordinatorProtocol {
|
||||
self.presentDeveloperOptions()
|
||||
case .logout:
|
||||
self.callback?(.logout)
|
||||
case .notifications:
|
||||
self.presentNotificationSettings()
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -136,4 +138,12 @@ final class SettingsScreenCoordinator: CoordinatorProtocol {
|
||||
private func showSuccess(label: String) {
|
||||
parameters.userIndicatorController?.submitIndicator(UserIndicator(title: label))
|
||||
}
|
||||
|
||||
private func presentNotificationSettings() {
|
||||
let notificationParameters = NotificationSettingsScreenCoordinatorParameters(
|
||||
userNotificationCenter: UNUserNotificationCenter.current()
|
||||
)
|
||||
let coordinator = NotificationSettingsScreenCoordinator(parameters: notificationParameters)
|
||||
parameters.navigationStackCoordinator?.push(coordinator)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,6 +24,7 @@ enum SettingsScreenViewModelAction {
|
||||
case about
|
||||
case sessionVerification
|
||||
case developerOptions
|
||||
case notifications
|
||||
case logout
|
||||
}
|
||||
|
||||
@@ -34,6 +35,7 @@ struct SettingsScreenViewState: BindableState {
|
||||
var userAvatarURL: URL?
|
||||
var userDisplayName: String?
|
||||
var showSessionVerificationSection: Bool
|
||||
var showNotificationSettings: Bool
|
||||
var showDeveloperOptions: Bool
|
||||
}
|
||||
|
||||
@@ -50,4 +52,5 @@ enum SettingsScreenViewAction {
|
||||
case logout
|
||||
case changedTimelineStyle
|
||||
case developerOptions
|
||||
case notifications
|
||||
}
|
||||
|
||||
@@ -40,6 +40,7 @@ class SettingsScreenViewModel: SettingsScreenViewModelType, SettingsScreenViewMo
|
||||
deviceID: userSession.deviceID,
|
||||
userID: userSession.userID,
|
||||
showSessionVerificationSection: showSessionVerificationSection,
|
||||
showNotificationSettings: appSettings.notificationSettingsEnabled,
|
||||
showDeveloperOptions: appSettings.canShowDeveloperOptions),
|
||||
imageProvider: userSession.mediaProvider)
|
||||
|
||||
@@ -51,6 +52,10 @@ class SettingsScreenViewModel: SettingsScreenViewModelType, SettingsScreenViewMo
|
||||
.weakAssign(to: \.state.userAvatarURL, on: self)
|
||||
.store(in: &cancellables)
|
||||
|
||||
appSettings.$notificationSettingsEnabled
|
||||
.weakAssign(to: \.state.showNotificationSettings, on: self)
|
||||
.store(in: &cancellables)
|
||||
|
||||
Task {
|
||||
await userSession.clientProxy.loadUserAvatarURL()
|
||||
}
|
||||
@@ -92,6 +97,8 @@ class SettingsScreenViewModel: SettingsScreenViewModelType, SettingsScreenViewMo
|
||||
callback?(.sessionVerification)
|
||||
case .changedTimelineStyle:
|
||||
appSettings.timelineStyle = state.bindings.timelineStyle
|
||||
case .notifications:
|
||||
callback?(.notifications)
|
||||
case .developerOptions:
|
||||
callback?(.developerOptions)
|
||||
}
|
||||
|
||||
@@ -113,6 +113,15 @@ struct SettingsScreen: View {
|
||||
context.send(viewAction: .changedTimelineStyle)
|
||||
}
|
||||
|
||||
// Notifications
|
||||
if context.viewState.showNotificationSettings {
|
||||
Button { context.send(viewAction: .notifications) } label: {
|
||||
Label(L10n.screenNotificationSettingsTitle, systemImage: "bell")
|
||||
}
|
||||
.buttonStyle(.compoundForm(accessory: .navigationLink))
|
||||
.accessibilityIdentifier("notificationsButton")
|
||||
}
|
||||
|
||||
// Analytics
|
||||
Button { context.send(viewAction: .analytics) } label: {
|
||||
Label(L10n.commonAnalytics, systemImage: "chart.bar")
|
||||
@@ -194,6 +203,7 @@ struct SettingsScreen_Previews: PreviewProvider {
|
||||
static let viewModel = {
|
||||
let userSession = MockUserSession(clientProxy: MockClientProxy(userID: "@userid:example.com"),
|
||||
mediaProvider: MockMediaProvider())
|
||||
ServiceLocator.shared.settings.notificationSettingsEnabled = true
|
||||
return SettingsScreenViewModel(userSession: userSession,
|
||||
appSettings: ServiceLocator.shared.settings)
|
||||
}()
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
//
|
||||
// Copyright 2023 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
|
||||
import UserNotifications
|
||||
|
||||
extension UNUserNotificationCenter {
|
||||
func authorizationStatus() async -> UNAuthorizationStatus {
|
||||
await notificationSettings().authorizationStatus
|
||||
}
|
||||
}
|
||||
@@ -24,7 +24,9 @@ class NotificationManager: NSObject, NotificationManagerProtocol {
|
||||
private let appSettings: AppSettings
|
||||
|
||||
private var userSession: UserSessionProtocol?
|
||||
|
||||
private var cancellables = Set<AnyCancellable>()
|
||||
private var notificationsEnabled = false
|
||||
|
||||
init(notificationCenter: UserNotificationCenterProtocol,
|
||||
appSettings: AppSettings) {
|
||||
self.notificationCenter = notificationCenter
|
||||
@@ -50,15 +52,35 @@ class NotificationManager: NSObject, NotificationManagerProtocol {
|
||||
options: [])
|
||||
notificationCenter.setNotificationCategories([messageCategory, inviteCategory])
|
||||
notificationCenter.delegate = self
|
||||
|
||||
notificationsEnabled = appSettings.enableNotifications
|
||||
MXLog.info("[NotificationManager] app setting 'enableNotifications' is '\(notificationsEnabled)'")
|
||||
|
||||
// Listen for changes to AppSettings.enableNotifications
|
||||
appSettings.$enableNotifications
|
||||
.sink { [weak self] newValue in
|
||||
self?.enableNotifications(newValue)
|
||||
}
|
||||
.store(in: &cancellables)
|
||||
|
||||
// Request authorization uppon UIApplication.didBecomeActiveNotification notification
|
||||
NotificationCenter.default.publisher(for: UIApplication.didBecomeActiveNotification)
|
||||
.sink { [weak self] _ in
|
||||
self?.requestAuthorization()
|
||||
}
|
||||
.store(in: &cancellables)
|
||||
}
|
||||
|
||||
|
||||
func requestAuthorization() {
|
||||
guard appSettings.enableNotifications, !userSession.isNil else { return }
|
||||
Task {
|
||||
do {
|
||||
let granted = try await notificationCenter.requestAuthorization(options: [.alert, .sound, .badge])
|
||||
MXLog.info("[NotificationManager] permission granted: \(granted)")
|
||||
let permissionGranted = try await notificationCenter.requestAuthorization(options: [.alert, .sound, .badge])
|
||||
MXLog.info("[NotificationManager] permission granted: \(permissionGranted)")
|
||||
await MainActor.run {
|
||||
self.delegate?.authorizationStatusUpdated(self, granted: granted)
|
||||
if permissionGranted {
|
||||
self.delegate?.registerForRemoteNotifications()
|
||||
}
|
||||
}
|
||||
} catch {
|
||||
MXLog.error("[NotificationManager] request authorization failed: \(error)")
|
||||
@@ -136,6 +158,17 @@ class NotificationManager: NSObject, NotificationManagerProtocol {
|
||||
appSettings.pusherProfileTag = newTag
|
||||
return newTag
|
||||
}
|
||||
|
||||
private func enableNotifications(_ enable: Bool) {
|
||||
guard notificationsEnabled != enable else { return }
|
||||
notificationsEnabled = enable
|
||||
MXLog.info("[NotificationManager] app setting 'enableNotifications' changed to '\(enable)'")
|
||||
if enable {
|
||||
requestAuthorization()
|
||||
} else {
|
||||
delegate?.unregisterForRemoteNotifications()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - UNUserNotificationCenterDelegate
|
||||
|
||||
@@ -18,8 +18,6 @@ import Foundation
|
||||
import UserNotifications
|
||||
|
||||
protocol NotificationManagerDelegate: AnyObject {
|
||||
func authorizationStatusUpdated(_ service: NotificationManagerProtocol,
|
||||
granted: Bool)
|
||||
func shouldDisplayInAppNotification(_ service: NotificationManagerProtocol,
|
||||
content: UNNotificationContent) -> Bool
|
||||
func notificationTapped(_ service: NotificationManagerProtocol,
|
||||
@@ -27,6 +25,8 @@ protocol NotificationManagerDelegate: AnyObject {
|
||||
func handleInlineReply(_ service: NotificationManagerProtocol,
|
||||
content: UNNotificationContent,
|
||||
replyText: String) async
|
||||
func registerForRemoteNotifications()
|
||||
func unregisterForRemoteNotifications()
|
||||
}
|
||||
|
||||
// MARK: - NotificationManagerProtocol
|
||||
|
||||
@@ -22,4 +22,8 @@ protocol UserNotificationCenterProtocol: AnyObject {
|
||||
func add(_ request: UNNotificationRequest) async throws
|
||||
func requestAuthorization(options: UNAuthorizationOptions) async throws -> Bool
|
||||
func setNotificationCategories(_ categories: Set<UNNotificationCategory>)
|
||||
func authorizationStatus() async -> UNAuthorizationStatus
|
||||
}
|
||||
|
||||
// sourcery: AutoMockable
|
||||
extension UserNotificationCenterProtocol { }
|
||||
|
||||
@@ -191,6 +191,11 @@ class MockScreen: Identifiable {
|
||||
isModallyPresented: false))
|
||||
navigationStackCoordinator.setRootCoordinator(coordinator)
|
||||
return navigationStackCoordinator
|
||||
case .notificationSettingsScreen:
|
||||
let userNotificationCenter = UserNotificationCenterMock()
|
||||
userNotificationCenter.authorizationStatusReturnValue = .denied
|
||||
let parameters = NotificationSettingsScreenCoordinatorParameters(userNotificationCenter: userNotificationCenter)
|
||||
return NotificationSettingsScreenCoordinator(parameters: parameters)
|
||||
case .onboarding:
|
||||
return OnboardingCoordinator()
|
||||
case .roomPlainNoAvatar:
|
||||
|
||||
@@ -34,6 +34,7 @@ enum UITestsScreenIdentifier: String {
|
||||
case settings
|
||||
case bugReport
|
||||
case bugReportWithScreenshot
|
||||
case notificationSettingsScreen
|
||||
case onboarding
|
||||
case roomPlainNoAvatar
|
||||
case roomEncryptedWithAvatar
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
//
|
||||
// Copyright 2023 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 NotificationSettingsScreenUITests: XCTestCase { }
|
||||
@@ -179,8 +179,12 @@ final class NotificationManagerTests: XCTestCase {
|
||||
}
|
||||
|
||||
extension NotificationManagerTests: NotificationManagerDelegate {
|
||||
func authorizationStatusUpdated(_ service: ElementX.NotificationManagerProtocol, granted: Bool) {
|
||||
authorizationStatusWasGranted = granted
|
||||
func registerForRemoteNotifications() {
|
||||
authorizationStatusWasGranted = true
|
||||
}
|
||||
|
||||
func unregisterForRemoteNotifications() {
|
||||
authorizationStatusWasGranted = false
|
||||
}
|
||||
|
||||
func shouldDisplayInAppNotification(_ service: ElementX.NotificationManagerProtocol, content: UNNotificationContent) -> Bool {
|
||||
|
||||
@@ -36,4 +36,9 @@ class UserNotificationCenterSpy: UserNotificationCenterProtocol {
|
||||
func setNotificationCategories(_ categories: Set<UNNotificationCategory>) {
|
||||
notificationCategoriesValue = categories
|
||||
}
|
||||
|
||||
var authorizationStatusValue: UNAuthorizationStatus?
|
||||
func authorizationStatus() async -> UNAuthorizationStatus {
|
||||
authorizationStatusValue ?? UNAuthorizationStatus.denied
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,50 @@
|
||||
//
|
||||
// Copyright 2023 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
|
||||
|
||||
@testable import ElementX
|
||||
|
||||
@MainActor
|
||||
class NotificationSettingsScreenViewModelTests: XCTestCase {
|
||||
private var viewModel: NotificationSettingsScreenViewModelProtocol!
|
||||
private var context: NotificationSettingsScreenViewModelType.Context!
|
||||
private var appSettings: AppSettings!
|
||||
private var userNotificationCenter: UserNotificationCenterMock!
|
||||
|
||||
@MainActor override func setUpWithError() throws {
|
||||
AppSettings.reset()
|
||||
|
||||
userNotificationCenter = UserNotificationCenterMock()
|
||||
userNotificationCenter.authorizationStatusReturnValue = .authorized
|
||||
appSettings = AppSettings()
|
||||
viewModel = NotificationSettingsScreenViewModel(appSettings: appSettings,
|
||||
userNotificationCenter: userNotificationCenter)
|
||||
context = viewModel.context
|
||||
}
|
||||
|
||||
func testEnableNotifications() {
|
||||
appSettings.enableNotifications = false
|
||||
context.send(viewAction: .changedEnableNotifications)
|
||||
XCTAssertTrue(appSettings.enableNotifications)
|
||||
}
|
||||
|
||||
func testOptOut() {
|
||||
appSettings.enableNotifications = true
|
||||
context.send(viewAction: .changedEnableNotifications)
|
||||
XCTAssertFalse(appSettings.enableNotifications)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user