mirror of
https://github.com/Novaloop-AG/element-x-ios.git
synced 2026-10-31 16:24:11 +00:00
Re-organise SettingsScreen to have distinct Account/App settings. (#6288)
* Re-organise SettingsScreen to have distinct Account/App settings. * Remove the AdvancedSettingsScreen.
This commit is contained in:
@@ -11,10 +11,6 @@ extension AccessibilityTests {
|
|||||||
try await performAccessibilityAudit(named: "ActiveCallTimelineItemView_Previews")
|
try await performAccessibilityAudit(named: "ActiveCallTimelineItemView_Previews")
|
||||||
}
|
}
|
||||||
|
|
||||||
func testAdvancedSettingsScreen() async throws {
|
|
||||||
try await performAccessibilityAudit(named: "AdvancedSettingsScreen_Previews")
|
|
||||||
}
|
|
||||||
|
|
||||||
func testAnalyticsPromptScreen() async throws {
|
func testAnalyticsPromptScreen() async throws {
|
||||||
try await performAccessibilityAudit(named: "AnalyticsPromptScreen_Previews")
|
try await performAccessibilityAudit(named: "AnalyticsPromptScreen_Previews")
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -81,7 +81,6 @@
|
|||||||
09693596AA3CA4E598C0D2F1 /* ThreadTimelineScreenCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 73FEE625AB52042049DB9268 /* ThreadTimelineScreenCoordinator.swift */; };
|
09693596AA3CA4E598C0D2F1 /* ThreadTimelineScreenCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 73FEE625AB52042049DB9268 /* ThreadTimelineScreenCoordinator.swift */; };
|
||||||
09713669577CDA8D012EE380 /* MatrixRustSDK in Frameworks */ = {isa = PBXBuildFile; productRef = 6647C55D93508C7CE9D954A5 /* MatrixRustSDK */; };
|
09713669577CDA8D012EE380 /* MatrixRustSDK in Frameworks */ = {isa = PBXBuildFile; productRef = 6647C55D93508C7CE9D954A5 /* MatrixRustSDK */; };
|
||||||
09D3D7D115318CAD131B4FE7 /* ResolveVerifiedUserSendFailureScreenViewModelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 57084488B03BDB33C7B7CA0E /* ResolveVerifiedUserSendFailureScreenViewModelTests.swift */; };
|
09D3D7D115318CAD131B4FE7 /* ResolveVerifiedUserSendFailureScreenViewModelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 57084488B03BDB33C7B7CA0E /* ResolveVerifiedUserSendFailureScreenViewModelTests.swift */; };
|
||||||
09E1A358EA4205480AEF4698 /* AdvancedSettingsScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = F229480685F30BCB96C439EC /* AdvancedSettingsScreen.swift */; };
|
|
||||||
0AB4FF7645175FF1F6E942CC /* DeferredFulfillment.swift in Sources */ = {isa = PBXBuildFile; fileRef = B91AD590B0B40718A0AA0C61 /* DeferredFulfillment.swift */; };
|
0AB4FF7645175FF1F6E942CC /* DeferredFulfillment.swift in Sources */ = {isa = PBXBuildFile; fileRef = B91AD590B0B40718A0AA0C61 /* DeferredFulfillment.swift */; };
|
||||||
0ACAA31FD0399CEEBA3ECC21 /* UserDetailsEditScreenViewModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 85149F56BA333619900E2410 /* UserDetailsEditScreenViewModelProtocol.swift */; };
|
0ACAA31FD0399CEEBA3ECC21 /* UserDetailsEditScreenViewModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 85149F56BA333619900E2410 /* UserDetailsEditScreenViewModelProtocol.swift */; };
|
||||||
0AD8EF040A60D62F488C18B5 /* KnockRequestProxyMock.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7F957320D0EB7D7B4E30C79D /* KnockRequestProxyMock.swift */; };
|
0AD8EF040A60D62F488C18B5 /* KnockRequestProxyMock.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7F957320D0EB7D7B4E30C79D /* KnockRequestProxyMock.swift */; };
|
||||||
@@ -286,7 +285,6 @@
|
|||||||
2BBC0EB1E07963810A5D7423 /* ReadMarkerRoomTimelineView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 012A284622B32052015F1F89 /* ReadMarkerRoomTimelineView.swift */; };
|
2BBC0EB1E07963810A5D7423 /* ReadMarkerRoomTimelineView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 012A284622B32052015F1F89 /* ReadMarkerRoomTimelineView.swift */; };
|
||||||
2BBE320EE426A347AAE5C7DA /* IdentityConfirmationScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = 00AFC5F08734C2EA4EE79C59 /* IdentityConfirmationScreen.swift */; };
|
2BBE320EE426A347AAE5C7DA /* IdentityConfirmationScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = 00AFC5F08734C2EA4EE79C59 /* IdentityConfirmationScreen.swift */; };
|
||||||
2BC579CB5CE90CFE07CA0955 /* EditRoomAddressScreenCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 41656BC6267D55C56A2AAC08 /* EditRoomAddressScreenCoordinator.swift */; };
|
2BC579CB5CE90CFE07CA0955 /* EditRoomAddressScreenCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 41656BC6267D55C56A2AAC08 /* EditRoomAddressScreenCoordinator.swift */; };
|
||||||
2BEDEA4851E1DF901779362C /* AdvancedSettingsScreenModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = 922E498EB74CF6F5CC236F81 /* AdvancedSettingsScreenModels.swift */; };
|
|
||||||
2BFA4C6D5B3D327B02C66AB0 /* TimelineController.swift in Sources */ = {isa = PBXBuildFile; fileRef = A4216C12C0369A8AB059EDE9 /* TimelineController.swift */; };
|
2BFA4C6D5B3D327B02C66AB0 /* TimelineController.swift in Sources */ = {isa = PBXBuildFile; fileRef = A4216C12C0369A8AB059EDE9 /* TimelineController.swift */; };
|
||||||
2C289BECCCBEDBA48DC9AC67 /* ClassicAppMXAccount.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74240BE69DACAD01AA670730 /* ClassicAppMXAccount.swift */; };
|
2C289BECCCBEDBA48DC9AC67 /* ClassicAppMXAccount.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74240BE69DACAD01AA670730 /* ClassicAppMXAccount.swift */; };
|
||||||
2C4C750D0039AFABDF24236C /* TemplateScreenViewModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 342BEBC3C5FC3F9943C41C4C /* TemplateScreenViewModelProtocol.swift */; };
|
2C4C750D0039AFABDF24236C /* TemplateScreenViewModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 342BEBC3C5FC3F9943C41C4C /* TemplateScreenViewModelProtocol.swift */; };
|
||||||
@@ -337,7 +335,6 @@
|
|||||||
34320DB3C585FD34F4DEC5C8 /* HomeserverHistoryManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6D2BBDB7E80E119D5C906285 /* HomeserverHistoryManager.swift */; };
|
34320DB3C585FD34F4DEC5C8 /* HomeserverHistoryManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6D2BBDB7E80E119D5C906285 /* HomeserverHistoryManager.swift */; };
|
||||||
34357B287357BC0B9715DD51 /* UserAgentBuilder.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F2529D434C750ED78ADF1ED /* UserAgentBuilder.swift */; };
|
34357B287357BC0B9715DD51 /* UserAgentBuilder.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F2529D434C750ED78ADF1ED /* UserAgentBuilder.swift */; };
|
||||||
34390DAE0C574DAD30CCA7D9 /* DeclineAndBlockScreenViewModelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2ADF12A50186B75C68017B61 /* DeclineAndBlockScreenViewModelTests.swift */; };
|
34390DAE0C574DAD30CCA7D9 /* DeclineAndBlockScreenViewModelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2ADF12A50186B75C68017B61 /* DeclineAndBlockScreenViewModelTests.swift */; };
|
||||||
34ADC506C929D10B138EBA51 /* AdvancedSettingsScreenCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 42C58159916ABD7F454CE689 /* AdvancedSettingsScreenCoordinator.swift */; };
|
|
||||||
34C752A73717C691582DC6C7 /* UnsupportedRoomTimelineItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = F1B8500C152BC59445647DA8 /* UnsupportedRoomTimelineItem.swift */; };
|
34C752A73717C691582DC6C7 /* UnsupportedRoomTimelineItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = F1B8500C152BC59445647DA8 /* UnsupportedRoomTimelineItem.swift */; };
|
||||||
34F1261CEF6D6A00D559B520 /* SettingsScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3CFD5EB0B0EEA4549FB49784 /* SettingsScreen.swift */; };
|
34F1261CEF6D6A00D559B520 /* SettingsScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3CFD5EB0B0EEA4549FB49784 /* SettingsScreen.swift */; };
|
||||||
352C439BE0F75E101EF11FB1 /* RoomScreenModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = C2886615BEBAE33A0AA4D5F8 /* RoomScreenModels.swift */; };
|
352C439BE0F75E101EF11FB1 /* RoomScreenModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = C2886615BEBAE33A0AA4D5F8 /* RoomScreenModels.swift */; };
|
||||||
@@ -1439,7 +1436,6 @@
|
|||||||
E1428612B08ED3030EC1FEC3 /* SpacesScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = 104B7747499487538483FEAF /* SpacesScreen.swift */; };
|
E1428612B08ED3030EC1FEC3 /* SpacesScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = 104B7747499487538483FEAF /* SpacesScreen.swift */; };
|
||||||
E14E469CD97550D0FC58F3CA /* CancellableTask.swift in Sources */ = {isa = PBXBuildFile; fileRef = AE52983FAFB4E0998C00EE8A /* CancellableTask.swift */; };
|
E14E469CD97550D0FC58F3CA /* CancellableTask.swift in Sources */ = {isa = PBXBuildFile; fileRef = AE52983FAFB4E0998C00EE8A /* CancellableTask.swift */; };
|
||||||
E184FFAD32342D3D6E2F89AA /* PinnedEventsTimelineScreenCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5D53754227CEBD06358956D7 /* PinnedEventsTimelineScreenCoordinator.swift */; };
|
E184FFAD32342D3D6E2F89AA /* PinnedEventsTimelineScreenCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5D53754227CEBD06358956D7 /* PinnedEventsTimelineScreenCoordinator.swift */; };
|
||||||
E1A0752244567A25E376A2F4 /* AdvancedSettingsScreenViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = A7A1B80FE6E3BA72F9C748AD /* AdvancedSettingsScreenViewModel.swift */; };
|
|
||||||
E1C67E5D9E22135A8FEBBD60 /* StackedAvatarsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A8558D41DD4B553A752C868A /* StackedAvatarsView.swift */; };
|
E1C67E5D9E22135A8FEBBD60 /* StackedAvatarsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A8558D41DD4B553A752C868A /* StackedAvatarsView.swift */; };
|
||||||
E1CC93B1842137A8AB25B815 /* SearchBreadcrumb.swift in Sources */ = {isa = PBXBuildFile; fileRef = 095B8ED0CA87F4A0A4858719 /* SearchBreadcrumb.swift */; };
|
E1CC93B1842137A8AB25B815 /* SearchBreadcrumb.swift in Sources */ = {isa = PBXBuildFile; fileRef = 095B8ED0CA87F4A0A4858719 /* SearchBreadcrumb.swift */; };
|
||||||
E1DE8A5422643F759385290F /* AppSettings.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7BD5523BDEDB247E29228476 /* AppSettings.swift */; };
|
E1DE8A5422643F759385290F /* AppSettings.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7BD5523BDEDB247E29228476 /* AppSettings.swift */; };
|
||||||
@@ -1629,7 +1625,6 @@
|
|||||||
FC10228E73323BDC09526F97 /* LRUCache in Frameworks */ = {isa = PBXBuildFile; productRef = 1081D3630AAD3ACEDDEC3A98 /* LRUCache */; };
|
FC10228E73323BDC09526F97 /* LRUCache in Frameworks */ = {isa = PBXBuildFile; productRef = 1081D3630AAD3ACEDDEC3A98 /* LRUCache */; };
|
||||||
FC31493979ED1FDF7D5EA3F9 /* KeychainController.swift in Sources */ = {isa = PBXBuildFile; fileRef = E36CB905A2B9EC2C92A2DA7C /* KeychainController.swift */; };
|
FC31493979ED1FDF7D5EA3F9 /* KeychainController.swift in Sources */ = {isa = PBXBuildFile; fileRef = E36CB905A2B9EC2C92A2DA7C /* KeychainController.swift */; };
|
||||||
FCD3F2B82CAB29A07887A127 /* Kingfisher in Frameworks */ = {isa = PBXBuildFile; productRef = DE8DC9B3FBA402117DC4C49F /* Kingfisher */; };
|
FCD3F2B82CAB29A07887A127 /* Kingfisher in Frameworks */ = {isa = PBXBuildFile; productRef = DE8DC9B3FBA402117DC4C49F /* Kingfisher */; };
|
||||||
FCF95603F1D056B1B106A415 /* AdvancedSettingsScreenViewModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 83E2B20431F890ED64255CA1 /* AdvancedSettingsScreenViewModelProtocol.swift */; };
|
|
||||||
FD19654C18E7C6D8AC79408D /* libMatrixRustSDKMocks.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 73F3153AB9D628110878E24F /* libMatrixRustSDKMocks.a */; };
|
FD19654C18E7C6D8AC79408D /* libMatrixRustSDKMocks.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 73F3153AB9D628110878E24F /* libMatrixRustSDKMocks.a */; };
|
||||||
FD29471C72872F8B7580E3E1 /* KeychainControllerMock.swift in Sources */ = {isa = PBXBuildFile; fileRef = 39C0D861FC397AC34BCF089E /* KeychainControllerMock.swift */; };
|
FD29471C72872F8B7580E3E1 /* KeychainControllerMock.swift in Sources */ = {isa = PBXBuildFile; fileRef = 39C0D861FC397AC34BCF089E /* KeychainControllerMock.swift */; };
|
||||||
FD573B5D665824EB79EABF06 /* Observable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5327E3B3C58BEB0E65F4CF98 /* Observable.swift */; };
|
FD573B5D665824EB79EABF06 /* Observable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5327E3B3C58BEB0E65F4CF98 /* Observable.swift */; };
|
||||||
@@ -2196,7 +2191,6 @@
|
|||||||
421E716C521F96D24ECE69B3 /* NoticeRoomTimelineItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NoticeRoomTimelineItem.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>"; };
|
421FA93BCC2840E66E4F306F /* NotificationSettingsScreenViewModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationSettingsScreenViewModelProtocol.swift; sourceTree = "<group>"; };
|
||||||
42236480CF0431535EBE8387 /* CustomLayoutLabelStyle.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CustomLayoutLabelStyle.swift; sourceTree = "<group>"; };
|
42236480CF0431535EBE8387 /* CustomLayoutLabelStyle.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CustomLayoutLabelStyle.swift; sourceTree = "<group>"; };
|
||||||
42C58159916ABD7F454CE689 /* AdvancedSettingsScreenCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AdvancedSettingsScreenCoordinator.swift; sourceTree = "<group>"; };
|
|
||||||
42C64A14EE89928207E3B42B /* AnalyticsSettingsScreenModels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AnalyticsSettingsScreenModels.swift; sourceTree = "<group>"; };
|
42C64A14EE89928207E3B42B /* AnalyticsSettingsScreenModels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AnalyticsSettingsScreenModels.swift; sourceTree = "<group>"; };
|
||||||
42C8C368A611B9CB79C7F5FA /* RoomPollsHistoryScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomPollsHistoryScreen.swift; sourceTree = "<group>"; };
|
42C8C368A611B9CB79C7F5FA /* RoomPollsHistoryScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomPollsHistoryScreen.swift; sourceTree = "<group>"; };
|
||||||
430C73079A84654BF46A7FF5 /* FileMediaEventsTimelineView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FileMediaEventsTimelineView.swift; sourceTree = "<group>"; };
|
430C73079A84654BF46A7FF5 /* FileMediaEventsTimelineView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FileMediaEventsTimelineView.swift; sourceTree = "<group>"; };
|
||||||
@@ -2580,7 +2574,6 @@
|
|||||||
839E2C35DF3F9C7B54C3CE49 /* RoundedCornerShape.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoundedCornerShape.swift; sourceTree = "<group>"; };
|
839E2C35DF3F9C7B54C3CE49 /* RoundedCornerShape.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoundedCornerShape.swift; sourceTree = "<group>"; };
|
||||||
83B4E3F1265581683E4997B8 /* RoomSelectionScreenViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomSelectionScreenViewModel.swift; sourceTree = "<group>"; };
|
83B4E3F1265581683E4997B8 /* RoomSelectionScreenViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomSelectionScreenViewModel.swift; sourceTree = "<group>"; };
|
||||||
83B574805B9812C111D6215D /* Tracing.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Tracing.swift; sourceTree = "<group>"; };
|
83B574805B9812C111D6215D /* Tracing.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Tracing.swift; sourceTree = "<group>"; };
|
||||||
83E2B20431F890ED64255CA1 /* AdvancedSettingsScreenViewModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AdvancedSettingsScreenViewModelProtocol.swift; sourceTree = "<group>"; };
|
|
||||||
840182D7A61402D5947DE094 /* NotificationItemProxyMock.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationItemProxyMock.swift; sourceTree = "<group>"; };
|
840182D7A61402D5947DE094 /* NotificationItemProxyMock.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationItemProxyMock.swift; sourceTree = "<group>"; };
|
||||||
842F63AA68E8EB410B1BA29F /* MapLibreInterface.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = MapLibreInterface.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
842F63AA68E8EB410B1BA29F /* MapLibreInterface.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = MapLibreInterface.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||||
84311D707B09854D67F78BBF /* de */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = de; path = de.lproj/InfoPlist.strings; sourceTree = "<group>"; };
|
84311D707B09854D67F78BBF /* de */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = de; path = de.lproj/InfoPlist.strings; sourceTree = "<group>"; };
|
||||||
@@ -2671,7 +2664,6 @@
|
|||||||
91C8BD78F7B9247AC57FA1A3 /* RedactedRoomTimelineView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RedactedRoomTimelineView.swift; sourceTree = "<group>"; };
|
91C8BD78F7B9247AC57FA1A3 /* RedactedRoomTimelineView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RedactedRoomTimelineView.swift; sourceTree = "<group>"; };
|
||||||
91CF6F7D08228D16BA69B63B /* zh-Hant-TW */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "zh-Hant-TW"; path = "zh-Hant-TW.lproj/Localizable.strings"; sourceTree = "<group>"; };
|
91CF6F7D08228D16BA69B63B /* zh-Hant-TW */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "zh-Hant-TW"; path = "zh-Hant-TW.lproj/Localizable.strings"; sourceTree = "<group>"; };
|
||||||
91FFE1F410969ECB23FE9BB2 /* TimelineItemMenu.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TimelineItemMenu.swift; sourceTree = "<group>"; };
|
91FFE1F410969ECB23FE9BB2 /* TimelineItemMenu.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TimelineItemMenu.swift; sourceTree = "<group>"; };
|
||||||
922E498EB74CF6F5CC236F81 /* AdvancedSettingsScreenModels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AdvancedSettingsScreenModels.swift; sourceTree = "<group>"; };
|
|
||||||
92DB574F954CC2B40F7BE892 /* QRCodeScannerView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = QRCodeScannerView.swift; sourceTree = "<group>"; };
|
92DB574F954CC2B40F7BE892 /* QRCodeScannerView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = QRCodeScannerView.swift; sourceTree = "<group>"; };
|
||||||
9332DFE9642F0A46ECA0497B /* BlurHashEncode.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BlurHashEncode.swift; sourceTree = "<group>"; };
|
9332DFE9642F0A46ECA0497B /* BlurHashEncode.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BlurHashEncode.swift; sourceTree = "<group>"; };
|
||||||
933B074F006F8E930DB98B4E /* TimelineMediaFrame.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TimelineMediaFrame.swift; sourceTree = "<group>"; };
|
933B074F006F8E930DB98B4E /* TimelineMediaFrame.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TimelineMediaFrame.swift; sourceTree = "<group>"; };
|
||||||
@@ -2795,7 +2787,6 @@
|
|||||||
A768CA51A59B8A5D8C8FD599 /* AuthenticationStartScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AuthenticationStartScreen.swift; sourceTree = "<group>"; };
|
A768CA51A59B8A5D8C8FD599 /* AuthenticationStartScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AuthenticationStartScreen.swift; sourceTree = "<group>"; };
|
||||||
A7978C9EFBDD7DE39BD86726 /* RestorationTokenTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RestorationTokenTests.swift; sourceTree = "<group>"; };
|
A7978C9EFBDD7DE39BD86726 /* RestorationTokenTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RestorationTokenTests.swift; sourceTree = "<group>"; };
|
||||||
A79A78330B9329E3A99E4105 /* SearchScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SearchScreen.swift; sourceTree = "<group>"; };
|
A79A78330B9329E3A99E4105 /* SearchScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SearchScreen.swift; sourceTree = "<group>"; };
|
||||||
A7A1B80FE6E3BA72F9C748AD /* AdvancedSettingsScreenViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AdvancedSettingsScreenViewModel.swift; sourceTree = "<group>"; };
|
|
||||||
A7C4EA55DA62F9D0F984A2AE /* CollapsibleTimelineItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CollapsibleTimelineItem.swift; sourceTree = "<group>"; };
|
A7C4EA55DA62F9D0F984A2AE /* CollapsibleTimelineItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CollapsibleTimelineItem.swift; sourceTree = "<group>"; };
|
||||||
A7D452AF7B5F7E3A0A7DB54C /* SessionVerificationScreenViewModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SessionVerificationScreenViewModelProtocol.swift; sourceTree = "<group>"; };
|
A7D452AF7B5F7E3A0A7DB54C /* SessionVerificationScreenViewModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SessionVerificationScreenViewModelProtocol.swift; sourceTree = "<group>"; };
|
||||||
A7E37072597F67C4DD8CC2DB /* ComposerDraftServiceProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ComposerDraftServiceProtocol.swift; sourceTree = "<group>"; };
|
A7E37072597F67C4DD8CC2DB /* ComposerDraftServiceProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ComposerDraftServiceProtocol.swift; sourceTree = "<group>"; };
|
||||||
@@ -3259,7 +3250,6 @@
|
|||||||
F17EFA1D3D09FC2F9C5E1CB2 /* MediaProvider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MediaProvider.swift; sourceTree = "<group>"; };
|
F17EFA1D3D09FC2F9C5E1CB2 /* MediaProvider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MediaProvider.swift; sourceTree = "<group>"; };
|
||||||
F1B0FC6A77FDFDE2BFE49E13 /* MediaUploadQualitySettingsScreenCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MediaUploadQualitySettingsScreenCoordinator.swift; sourceTree = "<group>"; };
|
F1B0FC6A77FDFDE2BFE49E13 /* MediaUploadQualitySettingsScreenCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MediaUploadQualitySettingsScreenCoordinator.swift; sourceTree = "<group>"; };
|
||||||
F1B8500C152BC59445647DA8 /* UnsupportedRoomTimelineItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UnsupportedRoomTimelineItem.swift; sourceTree = "<group>"; };
|
F1B8500C152BC59445647DA8 /* UnsupportedRoomTimelineItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UnsupportedRoomTimelineItem.swift; sourceTree = "<group>"; };
|
||||||
F229480685F30BCB96C439EC /* AdvancedSettingsScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AdvancedSettingsScreen.swift; sourceTree = "<group>"; };
|
|
||||||
F276F31C1AEC19E52B951B62 /* SendInviteConfirmationView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SendInviteConfirmationView.swift; sourceTree = "<group>"; };
|
F276F31C1AEC19E52B951B62 /* SendInviteConfirmationView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SendInviteConfirmationView.swift; sourceTree = "<group>"; };
|
||||||
F288457CD4C821DF48C1B6EE /* NativeCallRoomContext.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NativeCallRoomContext.swift; sourceTree = "<group>"; };
|
F288457CD4C821DF48C1B6EE /* NativeCallRoomContext.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NativeCallRoomContext.swift; sourceTree = "<group>"; };
|
||||||
F2B94F1B0B5D9D42B15AA6E8 /* ChatsTabFlowCoordinatorStateMachine.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ChatsTabFlowCoordinatorStateMachine.swift; sourceTree = "<group>"; };
|
F2B94F1B0B5D9D42B15AA6E8 /* ChatsTabFlowCoordinatorStateMachine.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ChatsTabFlowCoordinatorStateMachine.swift; sourceTree = "<group>"; };
|
||||||
@@ -3489,14 +3479,6 @@
|
|||||||
path = VoiceMessage;
|
path = VoiceMessage;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
};
|
};
|
||||||
018074F385C9417ECBEA793E /* View */ = {
|
|
||||||
isa = PBXGroup;
|
|
||||||
children = (
|
|
||||||
F229480685F30BCB96C439EC /* AdvancedSettingsScreen.swift */,
|
|
||||||
);
|
|
||||||
path = View;
|
|
||||||
sourceTree = "<group>";
|
|
||||||
};
|
|
||||||
01C939DDDF02F155F115DEF5 /* Sources */ = {
|
01C939DDDF02F155F115DEF5 /* Sources */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
@@ -5273,7 +5255,6 @@
|
|||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
EB5B1119B5AD79297F1D49EB /* AccountSettings */,
|
EB5B1119B5AD79297F1D49EB /* AccountSettings */,
|
||||||
FF2C35C46D5B8879A71F0BAC /* AdvancedSettingsScreen */,
|
|
||||||
09C599CB430ABF160C1EE55C /* AnalyticsSettingsScreen */,
|
09C599CB430ABF160C1EE55C /* AnalyticsSettingsScreen */,
|
||||||
CBB8EC37B802F3DD74A0205E /* DeactivateAccountScreen */,
|
CBB8EC37B802F3DD74A0205E /* DeactivateAccountScreen */,
|
||||||
1CA6CD0DE6F0445156361B6D /* DeveloperOptionsScreen */,
|
1CA6CD0DE6F0445156361B6D /* DeveloperOptionsScreen */,
|
||||||
@@ -7605,18 +7586,6 @@
|
|||||||
path = View;
|
path = View;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
};
|
};
|
||||||
FF2C35C46D5B8879A71F0BAC /* AdvancedSettingsScreen */ = {
|
|
||||||
isa = PBXGroup;
|
|
||||||
children = (
|
|
||||||
42C58159916ABD7F454CE689 /* AdvancedSettingsScreenCoordinator.swift */,
|
|
||||||
922E498EB74CF6F5CC236F81 /* AdvancedSettingsScreenModels.swift */,
|
|
||||||
A7A1B80FE6E3BA72F9C748AD /* AdvancedSettingsScreenViewModel.swift */,
|
|
||||||
83E2B20431F890ED64255CA1 /* AdvancedSettingsScreenViewModelProtocol.swift */,
|
|
||||||
018074F385C9417ECBEA793E /* View */,
|
|
||||||
);
|
|
||||||
path = AdvancedSettingsScreen;
|
|
||||||
sourceTree = "<group>";
|
|
||||||
};
|
|
||||||
FF654D7FD6693839E3185FAD /* View */ = {
|
FF654D7FD6693839E3185FAD /* View */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
@@ -8739,11 +8708,6 @@
|
|||||||
4A7957D034F5D96909127881 /* AccountSettings.swift in Sources */,
|
4A7957D034F5D96909127881 /* AccountSettings.swift in Sources */,
|
||||||
EFB3033FE782773D4F105681 /* AccountUserDefaults.swift in Sources */,
|
EFB3033FE782773D4F105681 /* AccountUserDefaults.swift in Sources */,
|
||||||
21215E17C9908F1EBF621BE0 /* ActiveCallTimelineItemView.swift in Sources */,
|
21215E17C9908F1EBF621BE0 /* ActiveCallTimelineItemView.swift in Sources */,
|
||||||
09E1A358EA4205480AEF4698 /* AdvancedSettingsScreen.swift in Sources */,
|
|
||||||
34ADC506C929D10B138EBA51 /* AdvancedSettingsScreenCoordinator.swift in Sources */,
|
|
||||||
2BEDEA4851E1DF901779362C /* AdvancedSettingsScreenModels.swift in Sources */,
|
|
||||||
E1A0752244567A25E376A2F4 /* AdvancedSettingsScreenViewModel.swift in Sources */,
|
|
||||||
FCF95603F1D056B1B106A415 /* AdvancedSettingsScreenViewModelProtocol.swift in Sources */,
|
|
||||||
53C1E7F6A7D6409D89F36ED7 /* AggregatedReactionMock.swift in Sources */,
|
53C1E7F6A7D6409D89F36ED7 /* AggregatedReactionMock.swift in Sources */,
|
||||||
4219391CD2351E410554B3E8 /* AggregratedReaction.swift in Sources */,
|
4219391CD2351E410554B3E8 /* AggregratedReaction.swift in Sources */,
|
||||||
64D05250CEDE8B604119F6E6 /* Alert.swift in Sources */,
|
64D05250CEDE8B604119F6E6 /* Alert.swift in Sources */,
|
||||||
|
|||||||
@@ -85,44 +85,52 @@ class SettingsFlowCoordinator: FlowCoordinatorProtocol {
|
|||||||
switch action {
|
switch action {
|
||||||
case .dismiss:
|
case .dismiss:
|
||||||
actionsSubject.send(.dismiss)
|
actionsSubject.send(.dismiss)
|
||||||
case .logout:
|
|
||||||
actionsSubject.send(.runLogoutFlow)
|
|
||||||
case .secureBackup:
|
|
||||||
startEncryptionSettingsFlow()
|
|
||||||
case .userDetails:
|
case .userDetails:
|
||||||
presentUserDetailsEditScreen()
|
presentUserDetailsEditScreen()
|
||||||
case let .userStatusEmojiPicker(continuation):
|
case let .userStatusEmojiPicker(continuation):
|
||||||
presentEmojiPicker(emojiPickerContinuation: continuation)
|
presentEmojiPicker(emojiPickerContinuation: continuation)
|
||||||
|
|
||||||
case .addAccount:
|
case .addAccount:
|
||||||
break // Nothing to present until the add account flow exists.
|
break // Nothing to present until the add account flow exists.
|
||||||
case .linkNewDevice:
|
|
||||||
startLinkNewDeviceFlow()
|
|
||||||
case let .manageAccount(url):
|
case let .manageAccount(url):
|
||||||
presentAccountManagementURL(url)
|
presentAccountManagementURL(url)
|
||||||
case .analytics:
|
case .linkNewDevice:
|
||||||
presentAnalyticsScreen()
|
startLinkNewDeviceFlow()
|
||||||
case .appLock:
|
case .notifications:
|
||||||
presentAppLockSetupFlow()
|
presentNotificationSettings()
|
||||||
|
case .secureBackup:
|
||||||
|
startEncryptionSettingsFlow()
|
||||||
|
case .moderationAndSafety:
|
||||||
|
presentModerationAndSafetySettings()
|
||||||
case .bugReport:
|
case .bugReport:
|
||||||
bugReportFlowCoordinator = BugReportFlowCoordinator(parameters: .init(presentationMode: .push(navigationStackCoordinator),
|
bugReportFlowCoordinator = BugReportFlowCoordinator(parameters: .init(presentationMode: .push(navigationStackCoordinator),
|
||||||
userIndicatorController: flowParameters.userIndicatorController,
|
userIndicatorController: flowParameters.userIndicatorController,
|
||||||
bugReportService: flowParameters.bugReportService,
|
bugReportService: flowParameters.bugReportService,
|
||||||
userSession: flowParameters.userSession))
|
userSession: flowParameters.userSession))
|
||||||
bugReportFlowCoordinator?.start()
|
bugReportFlowCoordinator?.start()
|
||||||
case .about:
|
|
||||||
presentLegalInformationScreen()
|
case .logout:
|
||||||
case .blockedUsers:
|
actionsSubject.send(.runLogoutFlow)
|
||||||
presentBlockedUsersScreen()
|
|
||||||
case .notifications:
|
|
||||||
presentNotificationSettings()
|
|
||||||
case .advancedSettings:
|
|
||||||
presentAdvancedSettings()
|
|
||||||
case .labs:
|
|
||||||
presentLabs()
|
|
||||||
case .developerOptions:
|
|
||||||
presentDeveloperOptions()
|
|
||||||
case .deactivateAccount:
|
case .deactivateAccount:
|
||||||
presentDeactivateAccount()
|
presentDeactivateAccount()
|
||||||
|
|
||||||
|
case .mediaUploadQuality:
|
||||||
|
presentMediaUploadQualitySettings()
|
||||||
|
case .appLock:
|
||||||
|
presentAppLockSetupFlow()
|
||||||
|
case .locationSharing:
|
||||||
|
presentLocationSharingSettings()
|
||||||
|
case .analytics:
|
||||||
|
presentAnalyticsScreen()
|
||||||
|
case .labs:
|
||||||
|
presentLabs()
|
||||||
|
case .about:
|
||||||
|
presentLegalInformationScreen()
|
||||||
|
|
||||||
|
case .developerOptions:
|
||||||
|
presentDeveloperOptions()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.store(in: &cancellables)
|
.store(in: &cancellables)
|
||||||
@@ -273,11 +281,34 @@ class SettingsFlowCoordinator: FlowCoordinatorProtocol {
|
|||||||
navigationStackCoordinator.push(coordinator)
|
navigationStackCoordinator.push(coordinator)
|
||||||
}
|
}
|
||||||
|
|
||||||
private func presentAdvancedSettings() {
|
private func presentModerationAndSafetySettings() {
|
||||||
let coordinator = AdvancedSettingsScreenCoordinator(parameters: .init(userSettings: flowParameters.userSettings,
|
let parameters = ModerationAndSafetySettingsScreenCoordinatorParameters(userSession: flowParameters.userSession,
|
||||||
analytics: flowParameters.analytics,
|
userIndicatorController: flowParameters.userIndicatorController)
|
||||||
clientProxy: flowParameters.userSession.clientProxy,
|
let coordinator = ModerationAndSafetySettingsScreenCoordinator(parameters: parameters)
|
||||||
userIndicatorController: flowParameters.userIndicatorController))
|
coordinator.actionsPublisher
|
||||||
|
.sink { [weak self] action in
|
||||||
|
guard let self else { return }
|
||||||
|
|
||||||
|
switch action {
|
||||||
|
case .blockedUsers:
|
||||||
|
presentBlockedUsersScreen()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.store(in: &cancellables)
|
||||||
|
|
||||||
|
navigationStackCoordinator.push(coordinator)
|
||||||
|
}
|
||||||
|
|
||||||
|
private func presentMediaUploadQualitySettings() {
|
||||||
|
let parameters = MediaUploadQualitySettingsScreenCoordinatorParameters(userSettings: flowParameters.userSettings,
|
||||||
|
analytics: flowParameters.analytics)
|
||||||
|
let coordinator = MediaUploadQualitySettingsScreenCoordinator(parameters: parameters)
|
||||||
|
navigationStackCoordinator.push(coordinator)
|
||||||
|
}
|
||||||
|
|
||||||
|
private func presentLocationSharingSettings() {
|
||||||
|
let parameters = LocationSharingSettingsScreenCoordinatorParameters(userSettings: flowParameters.userSettings)
|
||||||
|
let coordinator = LocationSharingSettingsScreenCoordinator(parameters: parameters)
|
||||||
navigationStackCoordinator.push(coordinator)
|
navigationStackCoordinator.push(coordinator)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -11,7 +11,6 @@ enum TestablePreviewsDictionary {
|
|||||||
static let dictionary: [String: any PreviewProvider.Type] = {
|
static let dictionary: [String: any PreviewProvider.Type] = {
|
||||||
var dictionary: [String: any PreviewProvider.Type] = [
|
var dictionary: [String: any PreviewProvider.Type] = [
|
||||||
"ActiveCallTimelineItemView_Previews" : ActiveCallTimelineItemView_Previews.self,
|
"ActiveCallTimelineItemView_Previews" : ActiveCallTimelineItemView_Previews.self,
|
||||||
"AdvancedSettingsScreen_Previews" : AdvancedSettingsScreen_Previews.self,
|
|
||||||
"AnalyticsPromptScreen_Previews" : AnalyticsPromptScreen_Previews.self,
|
"AnalyticsPromptScreen_Previews" : AnalyticsPromptScreen_Previews.self,
|
||||||
"AnalyticsSettingsScreen_Previews" : AnalyticsSettingsScreen_Previews.self,
|
"AnalyticsSettingsScreen_Previews" : AnalyticsSettingsScreen_Previews.self,
|
||||||
"AppLockScreen_Previews" : AppLockScreen_Previews.self,
|
"AppLockScreen_Previews" : AppLockScreen_Previews.self,
|
||||||
|
|||||||
-32
@@ -1,32 +0,0 @@
|
|||||||
//
|
|
||||||
// Copyright 2025 Element Creations Ltd.
|
|
||||||
// Copyright 2022-2025 New Vector Ltd.
|
|
||||||
//
|
|
||||||
// SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial
|
|
||||||
// Please see LICENSE files in the repository root for full details.
|
|
||||||
//
|
|
||||||
|
|
||||||
import Combine
|
|
||||||
import SwiftUI
|
|
||||||
|
|
||||||
struct AdvancedSettingsScreenCoordinatorParameters {
|
|
||||||
let userSettings: UserSettings
|
|
||||||
let analytics: AnalyticsServiceProtocol
|
|
||||||
let clientProxy: ClientProxyProtocol
|
|
||||||
let userIndicatorController: UserIndicatorControllerProtocol
|
|
||||||
}
|
|
||||||
|
|
||||||
final class AdvancedSettingsScreenCoordinator: CoordinatorProtocol {
|
|
||||||
private var viewModel: AdvancedSettingsScreenViewModelProtocol
|
|
||||||
|
|
||||||
init(parameters: AdvancedSettingsScreenCoordinatorParameters) {
|
|
||||||
viewModel = AdvancedSettingsScreenViewModel(advancedSettings: parameters.userSettings.app,
|
|
||||||
analytics: parameters.analytics,
|
|
||||||
clientProxy: parameters.clientProxy,
|
|
||||||
userIndicatorController: parameters.userIndicatorController)
|
|
||||||
}
|
|
||||||
|
|
||||||
func toPresentable() -> AnyView {
|
|
||||||
AnyView(AdvancedSettingsScreen(context: viewModel.context))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
-65
@@ -1,65 +0,0 @@
|
|||||||
//
|
|
||||||
// Copyright 2025 Element Creations Ltd.
|
|
||||||
// Copyright 2022-2025 New Vector Ltd.
|
|
||||||
//
|
|
||||||
// SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial
|
|
||||||
// Please see LICENSE files in the repository root for full details.
|
|
||||||
//
|
|
||||||
|
|
||||||
import Foundation
|
|
||||||
import UIKit
|
|
||||||
|
|
||||||
struct AdvancedSettingsScreenViewState: BindableState {
|
|
||||||
init(timelineMediaVisibility: TimelineMediaVisibility, hideInviteAvatars: Bool, isWaitingTimelineMediaVisibility: Bool = false, isWaitingHideInviteAvatars: Bool = false, bindings: AdvancedSettingsScreenViewStateBindings) {
|
|
||||||
self.timelineMediaVisibility = timelineMediaVisibility
|
|
||||||
self.hideInviteAvatars = hideInviteAvatars
|
|
||||||
self.isWaitingTimelineMediaVisibility = isWaitingTimelineMediaVisibility
|
|
||||||
self.isWaitingHideInviteAvatars = isWaitingHideInviteAvatars
|
|
||||||
self.bindings = bindings
|
|
||||||
|
|
||||||
let linkPlaceholder = "{link}"
|
|
||||||
var footerString = AttributedString(L10n.screenAdvancedSettingsLiveLocationSectionFooter(linkPlaceholder))
|
|
||||||
var linkString = AttributedString(L10n.screenAdvancedSettingsLiveLocationSectionFooterLink)
|
|
||||||
linkString.link = URL(string: UIApplication.openSettingsURLString)
|
|
||||||
linkString.bold()
|
|
||||||
footerString.replace(linkPlaceholder, with: linkString)
|
|
||||||
liveLocationUpdateFooterAttributedString = footerString
|
|
||||||
}
|
|
||||||
|
|
||||||
let liveLocationUpdateFooterAttributedString: AttributedString
|
|
||||||
var timelineMediaVisibility: TimelineMediaVisibility
|
|
||||||
var hideInviteAvatars: Bool
|
|
||||||
var isWaitingTimelineMediaVisibility: Bool
|
|
||||||
var isWaitingHideInviteAvatars: Bool
|
|
||||||
var bindings: AdvancedSettingsScreenViewStateBindings
|
|
||||||
}
|
|
||||||
|
|
||||||
@dynamicMemberLookup
|
|
||||||
struct AdvancedSettingsScreenViewStateBindings {
|
|
||||||
private let advancedSettings: AdvancedSettingsProtocol
|
|
||||||
|
|
||||||
init(advancedSettings: AdvancedSettingsProtocol) {
|
|
||||||
self.advancedSettings = advancedSettings
|
|
||||||
}
|
|
||||||
|
|
||||||
subscript<Setting>(dynamicMember keyPath: ReferenceWritableKeyPath<AdvancedSettingsProtocol, Setting>) -> Setting {
|
|
||||||
get { advancedSettings[keyPath: keyPath] }
|
|
||||||
set { advancedSettings[keyPath: keyPath] = newValue }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
enum AdvancedSettingsScreenViewAction {
|
|
||||||
case optimizeMediaUploadsChanged
|
|
||||||
case updateTimelineMediaVisibility(TimelineMediaVisibility)
|
|
||||||
case updateHideInviteAvatars(Bool)
|
|
||||||
}
|
|
||||||
|
|
||||||
protocol AdvancedSettingsProtocol: AnyObject {
|
|
||||||
var viewSourceEnabled: Bool { get set }
|
|
||||||
var appAppearance: AppAppearance { get set }
|
|
||||||
var sharePresence: Bool { get set }
|
|
||||||
var optimizeMediaUploads: Bool { get set }
|
|
||||||
var liveLocationMinimumDistanceUpdate: Int { get set }
|
|
||||||
}
|
|
||||||
|
|
||||||
extension AppSettings: AdvancedSettingsProtocol { }
|
|
||||||
-101
@@ -1,101 +0,0 @@
|
|||||||
//
|
|
||||||
// Copyright 2025 Element Creations Ltd.
|
|
||||||
// Copyright 2022-2025 New Vector Ltd.
|
|
||||||
//
|
|
||||||
// SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial
|
|
||||||
// Please see LICENSE files in the repository root for full details.
|
|
||||||
//
|
|
||||||
|
|
||||||
import Combine
|
|
||||||
import SwiftUI
|
|
||||||
|
|
||||||
typealias AdvancedSettingsScreenViewModelType = StateStoreViewModelV2<AdvancedSettingsScreenViewState, AdvancedSettingsScreenViewAction>
|
|
||||||
|
|
||||||
class AdvancedSettingsScreenViewModel: AdvancedSettingsScreenViewModelType, AdvancedSettingsScreenViewModelProtocol {
|
|
||||||
private let analytics: AnalyticsServiceProtocol
|
|
||||||
private let clientProxy: ClientProxyProtocol
|
|
||||||
private let userIndicatorController: UserIndicatorControllerProtocol
|
|
||||||
|
|
||||||
private var timelineMediaVisibilityTask: Task<Void, Never>?
|
|
||||||
private var hideInviteAvatarsTask: Task<Void, Never>?
|
|
||||||
|
|
||||||
init(advancedSettings: AdvancedSettingsProtocol,
|
|
||||||
analytics: AnalyticsServiceProtocol,
|
|
||||||
clientProxy: ClientProxyProtocol,
|
|
||||||
userIndicatorController: UserIndicatorControllerProtocol) {
|
|
||||||
self.analytics = analytics
|
|
||||||
self.clientProxy = clientProxy
|
|
||||||
self.userIndicatorController = userIndicatorController
|
|
||||||
|
|
||||||
let state = AdvancedSettingsScreenViewState(timelineMediaVisibility: clientProxy.timelineMediaVisibilityPublisher.value,
|
|
||||||
hideInviteAvatars: clientProxy.hideInviteAvatarsPublisher.value,
|
|
||||||
bindings: .init(advancedSettings: advancedSettings))
|
|
||||||
super.init(initialViewState: state)
|
|
||||||
|
|
||||||
clientProxy.timelineMediaVisibilityPublisher
|
|
||||||
.removeDuplicates()
|
|
||||||
.receive(on: DispatchQueue.main)
|
|
||||||
.weakAssign(to: \.state.timelineMediaVisibility, on: self)
|
|
||||||
.store(in: &cancellables)
|
|
||||||
|
|
||||||
clientProxy.hideInviteAvatarsPublisher
|
|
||||||
.removeDuplicates()
|
|
||||||
.receive(on: DispatchQueue.main)
|
|
||||||
.weakAssign(to: \.state.hideInviteAvatars, on: self)
|
|
||||||
.store(in: &cancellables)
|
|
||||||
}
|
|
||||||
|
|
||||||
override func process(viewAction: AdvancedSettingsScreenViewAction) {
|
|
||||||
switch viewAction {
|
|
||||||
case .optimizeMediaUploadsChanged:
|
|
||||||
// Note: Using a view action here as sinking the UserSettings publisher tracks the initial value.
|
|
||||||
analytics.trackInteraction(name: state.bindings.optimizeMediaUploads ? .MobileSettingsOptimizeMediaUploadsEnabled : .MobileSettingsOptimizeMediaUploadsDisabled)
|
|
||||||
case let .updateHideInviteAvatars(value):
|
|
||||||
hideInviteAvatarsTask = Task { [weak self] in await self?.updateHideInviteAvatars(value) }
|
|
||||||
case let .updateTimelineMediaVisibility(value):
|
|
||||||
timelineMediaVisibilityTask = Task { [weak self] in await self?.updateTimelineMediaVisibility(value) }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private func updateTimelineMediaVisibility(_ value: TimelineMediaVisibility) async {
|
|
||||||
defer {
|
|
||||||
timelineMediaVisibilityTask = nil
|
|
||||||
state.isWaitingTimelineMediaVisibility = false
|
|
||||||
}
|
|
||||||
|
|
||||||
let previousState = state.timelineMediaVisibility
|
|
||||||
state.isWaitingTimelineMediaVisibility = true
|
|
||||||
state.timelineMediaVisibility = value
|
|
||||||
// If the other value is updating wait also for it to finish
|
|
||||||
await hideInviteAvatarsTask?.value
|
|
||||||
|
|
||||||
switch await clientProxy.setTimelineMediaVisibility(value) {
|
|
||||||
case .success:
|
|
||||||
break
|
|
||||||
case .failure:
|
|
||||||
state.timelineMediaVisibility = previousState
|
|
||||||
userIndicatorController.submitIndicator(.init(title: L10n.errorUnknown))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private func updateHideInviteAvatars(_ value: Bool) async {
|
|
||||||
defer {
|
|
||||||
hideInviteAvatarsTask = nil
|
|
||||||
state.isWaitingHideInviteAvatars = false
|
|
||||||
}
|
|
||||||
|
|
||||||
let previousState = state.hideInviteAvatars
|
|
||||||
state.isWaitingHideInviteAvatars = true
|
|
||||||
state.hideInviteAvatars = value
|
|
||||||
// If the other value is updating wait also for it to finish
|
|
||||||
await timelineMediaVisibilityTask?.value
|
|
||||||
|
|
||||||
switch await clientProxy.setHideInviteAvatars(value) {
|
|
||||||
case .success:
|
|
||||||
break
|
|
||||||
case .failure:
|
|
||||||
state.hideInviteAvatars = previousState
|
|
||||||
userIndicatorController.submitIndicator(.init(title: L10n.errorUnknown))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
-13
@@ -1,13 +0,0 @@
|
|||||||
//
|
|
||||||
// Copyright 2025 Element Creations Ltd.
|
|
||||||
// Copyright 2022-2025 New Vector Ltd.
|
|
||||||
//
|
|
||||||
// SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial
|
|
||||||
// Please see LICENSE files in the repository root for full details.
|
|
||||||
//
|
|
||||||
|
|
||||||
import Combine
|
|
||||||
|
|
||||||
protocol AdvancedSettingsScreenViewModelProtocol {
|
|
||||||
var context: AdvancedSettingsScreenViewModelType.Context { get }
|
|
||||||
}
|
|
||||||
-181
@@ -1,181 +0,0 @@
|
|||||||
//
|
|
||||||
// Copyright 2025 Element Creations Ltd.
|
|
||||||
// Copyright 2022-2025 New Vector Ltd.
|
|
||||||
//
|
|
||||||
// SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial
|
|
||||||
// Please see LICENSE files in the repository root for full details.
|
|
||||||
//
|
|
||||||
|
|
||||||
import Compound
|
|
||||||
import SwiftUI
|
|
||||||
|
|
||||||
struct AdvancedSettingsScreen: View {
|
|
||||||
static let measurementFormatter = {
|
|
||||||
let formatter = MeasurementFormatter()
|
|
||||||
formatter.unitOptions = .providedUnit
|
|
||||||
formatter.unitStyle = .short
|
|
||||||
return formatter
|
|
||||||
}()
|
|
||||||
|
|
||||||
@Bindable var context: AdvancedSettingsScreenViewModel.Context
|
|
||||||
|
|
||||||
var body: some View {
|
|
||||||
Form {
|
|
||||||
Section {
|
|
||||||
ListRow(label: .plain(title: L10n.commonAppearance),
|
|
||||||
kind: .picker(selection: $context.appAppearance,
|
|
||||||
items: AppAppearance.allCases.map { (title: $0.name, tag: $0) }))
|
|
||||||
|
|
||||||
ListRow(label: .plain(title: L10n.actionViewSource,
|
|
||||||
description: L10n.screenAdvancedSettingsViewSourceDescription),
|
|
||||||
kind: .toggle($context.viewSourceEnabled))
|
|
||||||
|
|
||||||
ListRow(label: .plain(title: L10n.screenAdvancedSettingsSharePresence,
|
|
||||||
description: L10n.screenAdvancedSettingsSharePresenceDescription),
|
|
||||||
kind: .toggle($context.sharePresence))
|
|
||||||
|
|
||||||
ListRow(label: .plain(title: L10n.screenAdvancedSettingsMediaCompressionTitle,
|
|
||||||
description: L10n.screenAdvancedSettingsMediaCompressionDescription),
|
|
||||||
kind: .toggle($context.optimizeMediaUploads))
|
|
||||||
.onChange(of: context.optimizeMediaUploads) {
|
|
||||||
context.send(viewAction: .optimizeMediaUploadsChanged)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
moderationAndSafetySection
|
|
||||||
timelineMediaSection
|
|
||||||
liveLocationSection
|
|
||||||
}
|
|
||||||
.compoundList()
|
|
||||||
.navigationTitle(L10n.commonAdvancedSettings)
|
|
||||||
.navigationBarTitleDisplayMode(.inline)
|
|
||||||
}
|
|
||||||
|
|
||||||
@ViewBuilder
|
|
||||||
private var moderationAndSafetySection: some View {
|
|
||||||
let binding = Binding(get: {
|
|
||||||
context.viewState.hideInviteAvatars
|
|
||||||
}, set: { newValue in
|
|
||||||
context.send(viewAction: .updateHideInviteAvatars(newValue))
|
|
||||||
})
|
|
||||||
|
|
||||||
Section {
|
|
||||||
ListRow(label: .plain(title: L10n.screenAdvancedSettingsHideInviteAvatarsToggleTitle),
|
|
||||||
details: context.viewState.isWaitingHideInviteAvatars ? .isWaiting(true) : nil,
|
|
||||||
kind: .toggle(binding))
|
|
||||||
.disabled(context.viewState.isWaitingHideInviteAvatars)
|
|
||||||
} header: {
|
|
||||||
Text(L10n.screenAdvancedSettingsModerationAndSafetySectionTitle)
|
|
||||||
.compoundListSectionHeader()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@ViewBuilder
|
|
||||||
private var timelineMediaSection: some View {
|
|
||||||
let binding = Binding(get: {
|
|
||||||
context.viewState.timelineMediaVisibility
|
|
||||||
}, set: { newValue in
|
|
||||||
context.send(viewAction: .updateTimelineMediaVisibility(newValue))
|
|
||||||
})
|
|
||||||
|
|
||||||
Section {
|
|
||||||
ListRow(label: .plain(title: L10n.screenAdvancedSettingsShowMediaTimelineTitle),
|
|
||||||
details: .isWaiting(context.viewState.isWaitingTimelineMediaVisibility),
|
|
||||||
kind: .inlinePicker(selection: binding,
|
|
||||||
items: TimelineMediaVisibility.items))
|
|
||||||
.disabled(context.viewState.isWaitingTimelineMediaVisibility)
|
|
||||||
} header: {
|
|
||||||
Text(L10n.screenAdvancedSettingsShowMediaTimelineTitle)
|
|
||||||
.compoundListSectionHeader()
|
|
||||||
} footer: {
|
|
||||||
Text(L10n.screenAdvancedSettingsShowMediaTimelineSubtitle)
|
|
||||||
.compoundListSectionFooter()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@ViewBuilder
|
|
||||||
private var liveLocationSection: some View {
|
|
||||||
let binding = Binding(get: {
|
|
||||||
Double(context.liveLocationMinimumDistanceUpdate)
|
|
||||||
}, set: { newValue in
|
|
||||||
context.liveLocationMinimumDistanceUpdate = Int(newValue)
|
|
||||||
})
|
|
||||||
|
|
||||||
Section {
|
|
||||||
ListRow(kind: .custom {
|
|
||||||
VStack(alignment: .leading, spacing: 0) {
|
|
||||||
Text(L10n.screenAdvancedSettingsLiveLocationUpdateDistance(context.liveLocationMinimumDistanceUpdate))
|
|
||||||
.font(.compound.bodyLG)
|
|
||||||
.foregroundStyle(.compound.textPrimary)
|
|
||||||
// The internal hidden label of the slider will read voice over
|
|
||||||
.accessibilityHidden(true)
|
|
||||||
Slider(value: binding, in: 1...100) {
|
|
||||||
Text(L10n.screenAdvancedSettingsLiveLocationUpdateDistance(context.liveLocationMinimumDistanceUpdate))
|
|
||||||
} minimumValueLabel: {
|
|
||||||
Text(Self.measurementFormatter.string(from: .init(value: 1,
|
|
||||||
unit: UnitLength.meters)))
|
|
||||||
.font(.compound.bodyLG)
|
|
||||||
.foregroundStyle(.compound.textSecondary)
|
|
||||||
.padding(.trailing, 15)
|
|
||||||
} maximumValueLabel: {
|
|
||||||
Text(Self.measurementFormatter.string(from: .init(value: 100,
|
|
||||||
unit: UnitLength.meters)))
|
|
||||||
.font(.compound.bodyLG)
|
|
||||||
.foregroundStyle(.compound.textSecondary)
|
|
||||||
.padding(.leading, 15)
|
|
||||||
}
|
|
||||||
.tint(.compound.iconAccentPrimary)
|
|
||||||
}
|
|
||||||
.padding(.horizontal, ListRowPadding.horizontal)
|
|
||||||
.padding(.vertical, ListRowPadding.vertical)
|
|
||||||
})
|
|
||||||
} header: {
|
|
||||||
VStack(alignment: .leading, spacing: 4) {
|
|
||||||
Text(L10n.screenAdvancedSettingsLiveLocationSectionTitle)
|
|
||||||
.compoundListSectionHeader()
|
|
||||||
Text(L10n.screenAdvancedSettingsLiveLocationSectionDescription)
|
|
||||||
.font(.compound.bodyMD)
|
|
||||||
.foregroundStyle(.compound.textSecondary)
|
|
||||||
}
|
|
||||||
} footer: {
|
|
||||||
Text(context.viewState.liveLocationUpdateFooterAttributedString)
|
|
||||||
.compoundListSectionFooter()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private extension AppAppearance {
|
|
||||||
var name: String {
|
|
||||||
switch self {
|
|
||||||
case .system:
|
|
||||||
L10n.themeSystem
|
|
||||||
case .light:
|
|
||||||
L10n.themeLight
|
|
||||||
case .dark:
|
|
||||||
L10n.themeDark
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// MARK: - Previews
|
|
||||||
|
|
||||||
struct AdvancedSettingsScreen_Previews: PreviewProvider, TestablePreview {
|
|
||||||
static let viewModel = AdvancedSettingsScreenViewModel(advancedSettings: AppSettings.volatile(),
|
|
||||||
analytics: AnalyticsServiceMock(.init()),
|
|
||||||
clientProxy: ClientProxyMock(.init()),
|
|
||||||
userIndicatorController: UserIndicatorControllerMock())
|
|
||||||
|
|
||||||
static var previews: some View {
|
|
||||||
ElementNavigationStack {
|
|
||||||
AdvancedSettingsScreen(context: viewModel.context)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private extension TimelineMediaVisibility {
|
|
||||||
static var items: [(title: String, tag: TimelineMediaVisibility)] {
|
|
||||||
[(title: L10n.screenAdvancedSettingsShowMediaTimelineAlwaysHide, tag: .never),
|
|
||||||
(title: L10n.screenAdvancedSettingsShowMediaTimelinePrivateRooms, tag: .privateOnly),
|
|
||||||
(title: L10n.screenAdvancedSettingsShowMediaTimelineAlwaysShow, tag: .always)]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
+22
@@ -13,12 +13,34 @@ struct ModerationAndSafetySettingsScreenCoordinatorParameters {
|
|||||||
let userIndicatorController: UserIndicatorControllerProtocol
|
let userIndicatorController: UserIndicatorControllerProtocol
|
||||||
}
|
}
|
||||||
|
|
||||||
|
enum ModerationAndSafetySettingsScreenCoordinatorAction {
|
||||||
|
case blockedUsers
|
||||||
|
}
|
||||||
|
|
||||||
final class ModerationAndSafetySettingsScreenCoordinator: CoordinatorProtocol {
|
final class ModerationAndSafetySettingsScreenCoordinator: CoordinatorProtocol {
|
||||||
private var viewModel: ModerationAndSafetySettingsScreenViewModelProtocol
|
private var viewModel: ModerationAndSafetySettingsScreenViewModelProtocol
|
||||||
|
|
||||||
|
private let actionsSubject: PassthroughSubject<ModerationAndSafetySettingsScreenCoordinatorAction, Never> = .init()
|
||||||
|
var actionsPublisher: AnyPublisher<ModerationAndSafetySettingsScreenCoordinatorAction, Never> {
|
||||||
|
actionsSubject.eraseToAnyPublisher()
|
||||||
|
}
|
||||||
|
|
||||||
|
private var cancellables = Set<AnyCancellable>()
|
||||||
|
|
||||||
init(parameters: ModerationAndSafetySettingsScreenCoordinatorParameters) {
|
init(parameters: ModerationAndSafetySettingsScreenCoordinatorParameters) {
|
||||||
viewModel = ModerationAndSafetySettingsScreenViewModel(userSession: parameters.userSession,
|
viewModel = ModerationAndSafetySettingsScreenViewModel(userSession: parameters.userSession,
|
||||||
userIndicatorController: parameters.userIndicatorController)
|
userIndicatorController: parameters.userIndicatorController)
|
||||||
|
|
||||||
|
viewModel.actionsPublisher
|
||||||
|
.sink { [weak self] action in
|
||||||
|
guard let self else { return }
|
||||||
|
|
||||||
|
switch action {
|
||||||
|
case .blockedUsers:
|
||||||
|
actionsSubject.send(.blockedUsers)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.store(in: &cancellables)
|
||||||
}
|
}
|
||||||
|
|
||||||
func toPresentable() -> AnyView {
|
func toPresentable() -> AnyView {
|
||||||
|
|||||||
@@ -19,23 +19,30 @@ struct SettingsScreenCoordinatorParameters {
|
|||||||
|
|
||||||
enum SettingsScreenCoordinatorAction {
|
enum SettingsScreenCoordinatorAction {
|
||||||
case dismiss
|
case dismiss
|
||||||
case logout
|
|
||||||
case secureBackup
|
|
||||||
case userDetails
|
case userDetails
|
||||||
case userStatusEmojiPicker(EmojiPickerScreenContinuation)
|
case userStatusEmojiPicker(EmojiPickerScreenContinuation)
|
||||||
|
|
||||||
case addAccount
|
case addAccount
|
||||||
case analytics
|
|
||||||
case appLock
|
|
||||||
case bugReport
|
|
||||||
case about
|
|
||||||
case blockedUsers
|
|
||||||
case linkNewDevice
|
|
||||||
case manageAccount(url: URL)
|
case manageAccount(url: URL)
|
||||||
|
case linkNewDevice
|
||||||
case notifications
|
case notifications
|
||||||
case advancedSettings
|
case secureBackup
|
||||||
case labs
|
case moderationAndSafety
|
||||||
case developerOptions
|
case bugReport
|
||||||
|
|
||||||
|
case logout
|
||||||
case deactivateAccount
|
case deactivateAccount
|
||||||
|
|
||||||
|
case mediaUploadQuality
|
||||||
|
case appLock
|
||||||
|
case locationSharing
|
||||||
|
case analytics
|
||||||
|
case labs
|
||||||
|
case about
|
||||||
|
|
||||||
|
case developerOptions
|
||||||
}
|
}
|
||||||
|
|
||||||
final class SettingsScreenCoordinator: CoordinatorProtocol {
|
final class SettingsScreenCoordinator: CoordinatorProtocol {
|
||||||
@@ -64,40 +71,48 @@ final class SettingsScreenCoordinator: CoordinatorProtocol {
|
|||||||
switch action {
|
switch action {
|
||||||
case .close:
|
case .close:
|
||||||
actionsSubject.send(.dismiss)
|
actionsSubject.send(.dismiss)
|
||||||
|
|
||||||
case .userDetails:
|
case .userDetails:
|
||||||
actionsSubject.send(.userDetails)
|
actionsSubject.send(.userDetails)
|
||||||
case let .userStatusEmojiPicker(continuation):
|
case let .userStatusEmojiPicker(continuation):
|
||||||
actionsSubject.send(.userStatusEmojiPicker(continuation))
|
actionsSubject.send(.userStatusEmojiPicker(continuation))
|
||||||
|
|
||||||
case .addAccount:
|
case .addAccount:
|
||||||
actionsSubject.send(.addAccount)
|
actionsSubject.send(.addAccount)
|
||||||
case .linkNewDevice:
|
|
||||||
actionsSubject.send(.linkNewDevice)
|
|
||||||
case let .manageAccount(url):
|
case let .manageAccount(url):
|
||||||
actionsSubject.send(.manageAccount(url: url))
|
actionsSubject.send(.manageAccount(url: url))
|
||||||
case .analytics:
|
case .linkNewDevice:
|
||||||
actionsSubject.send(.analytics)
|
actionsSubject.send(.linkNewDevice)
|
||||||
case .appLock:
|
|
||||||
actionsSubject.send(.appLock)
|
|
||||||
case .reportBug:
|
|
||||||
actionsSubject.send(.bugReport)
|
|
||||||
case .about:
|
|
||||||
actionsSubject.send(.about)
|
|
||||||
case .blockedUsers:
|
|
||||||
actionsSubject.send(.blockedUsers)
|
|
||||||
case .secureBackup:
|
|
||||||
actionsSubject.send(.secureBackup)
|
|
||||||
case .notifications:
|
case .notifications:
|
||||||
actionsSubject.send(.notifications)
|
actionsSubject.send(.notifications)
|
||||||
case .advancedSettings:
|
case .secureBackup:
|
||||||
actionsSubject.send(.advancedSettings)
|
actionsSubject.send(.secureBackup)
|
||||||
case .labs:
|
case .moderationAndSafety:
|
||||||
actionsSubject.send(.labs)
|
actionsSubject.send(.moderationAndSafety)
|
||||||
case .developerOptions:
|
case .reportBug:
|
||||||
actionsSubject.send(.developerOptions)
|
actionsSubject.send(.bugReport)
|
||||||
|
|
||||||
case .logout:
|
case .logout:
|
||||||
actionsSubject.send(.logout)
|
actionsSubject.send(.logout)
|
||||||
case .deactivateAccount:
|
case .deactivateAccount:
|
||||||
actionsSubject.send(.deactivateAccount)
|
actionsSubject.send(.deactivateAccount)
|
||||||
|
|
||||||
|
case .mediaUploadQuality:
|
||||||
|
actionsSubject.send(.mediaUploadQuality)
|
||||||
|
case .appLock:
|
||||||
|
actionsSubject.send(.appLock)
|
||||||
|
case .locationSharing:
|
||||||
|
actionsSubject.send(.locationSharing)
|
||||||
|
case .analytics:
|
||||||
|
actionsSubject.send(.analytics)
|
||||||
|
case .labs:
|
||||||
|
actionsSubject.send(.labs)
|
||||||
|
case .about:
|
||||||
|
actionsSubject.send(.about)
|
||||||
|
|
||||||
|
case .developerOptions:
|
||||||
|
actionsSubject.send(.developerOptions)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.store(in: &cancellables)
|
.store(in: &cancellables)
|
||||||
|
|||||||
@@ -10,23 +10,30 @@ import SwiftUI
|
|||||||
|
|
||||||
enum SettingsScreenViewModelAction {
|
enum SettingsScreenViewModelAction {
|
||||||
case close
|
case close
|
||||||
|
|
||||||
case userDetails
|
case userDetails
|
||||||
case userStatusEmojiPicker(EmojiPickerScreenContinuation)
|
case userStatusEmojiPicker(EmojiPickerScreenContinuation)
|
||||||
|
|
||||||
case addAccount
|
case addAccount
|
||||||
case linkNewDevice
|
|
||||||
case manageAccount(url: URL)
|
case manageAccount(url: URL)
|
||||||
case analytics
|
case linkNewDevice
|
||||||
case appLock
|
|
||||||
case reportBug
|
|
||||||
case about
|
|
||||||
case blockedUsers
|
|
||||||
case secureBackup
|
|
||||||
case notifications
|
case notifications
|
||||||
case advancedSettings
|
case secureBackup
|
||||||
case labs
|
case moderationAndSafety
|
||||||
case developerOptions
|
case reportBug
|
||||||
|
|
||||||
case logout
|
case logout
|
||||||
case deactivateAccount
|
case deactivateAccount
|
||||||
|
|
||||||
|
case mediaUploadQuality
|
||||||
|
case appLock
|
||||||
|
case locationSharing
|
||||||
|
case analytics
|
||||||
|
case labs
|
||||||
|
case about
|
||||||
|
|
||||||
|
case developerOptions
|
||||||
}
|
}
|
||||||
|
|
||||||
enum SettingsScreenSecuritySectionMode {
|
enum SettingsScreenSecuritySectionMode {
|
||||||
@@ -47,14 +54,13 @@ struct SettingsScreenViewState: BindableState {
|
|||||||
var securitySectionMode = SettingsScreenSecuritySectionMode.none
|
var securitySectionMode = SettingsScreenSecuritySectionMode.none
|
||||||
var showSecuritySectionBadge = false
|
var showSecuritySectionBadge = false
|
||||||
|
|
||||||
var showBlockedUsers = false
|
|
||||||
let showAnalyticsSettings: Bool
|
let showAnalyticsSettings: Bool
|
||||||
|
|
||||||
let isBugReportServiceEnabled: Bool
|
let isBugReportServiceEnabled: Bool
|
||||||
|
|
||||||
let navigationBarVisibility: Visibility
|
let navigationBarVisibility: Visibility
|
||||||
|
|
||||||
var bindings = SettingsScreenViewStateBindings()
|
var bindings: SettingsScreenViewStateBindings
|
||||||
|
|
||||||
var userStatusRowMode: SettingsScreenUserStatusRow.Mode {
|
var userStatusRowMode: SettingsScreenUserStatusRow.Mode {
|
||||||
if bindings.isShowingCustomStatusField {
|
if bindings.isShowingCustomStatusField {
|
||||||
@@ -68,6 +74,8 @@ struct SettingsScreenViewState: BindableState {
|
|||||||
}
|
}
|
||||||
|
|
||||||
struct SettingsScreenViewStateBindings {
|
struct SettingsScreenViewStateBindings {
|
||||||
|
private let userSettings: UserSettings
|
||||||
|
|
||||||
var isPresentingStatusPicker = false
|
var isPresentingStatusPicker = false
|
||||||
var customStatusEmoji: Character = "😄"
|
var customStatusEmoji: Character = "😄"
|
||||||
var isShowingCustomStatusField = false {
|
var isShowingCustomStatusField = false {
|
||||||
@@ -79,29 +87,45 @@ struct SettingsScreenViewStateBindings {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var isPresentingAccountDeactivationConfirmation = false
|
var isPresentingAccountDeactivationConfirmation = false
|
||||||
|
|
||||||
|
var appAppearance: AppAppearance {
|
||||||
|
get { userSettings.appAppearance }
|
||||||
|
set { userSettings.appAppearance = newValue }
|
||||||
|
}
|
||||||
|
|
||||||
|
init(userSettings: UserSettings) {
|
||||||
|
self.userSettings = userSettings
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
enum SettingsScreenViewAction {
|
enum SettingsScreenViewAction {
|
||||||
case close
|
case close
|
||||||
|
|
||||||
case userDetails
|
case userDetails
|
||||||
case userStatus(UserStatusAction)
|
case userStatus(UserStatusAction)
|
||||||
|
|
||||||
case addAccount
|
case addAccount
|
||||||
case analytics
|
|
||||||
case appLock
|
|
||||||
case reportBug
|
|
||||||
case about
|
|
||||||
case blockedUsers
|
|
||||||
case secureBackup
|
|
||||||
case linkNewDevice
|
|
||||||
case manageAccount(url: URL)
|
case manageAccount(url: URL)
|
||||||
|
case linkNewDevice
|
||||||
case notifications
|
case notifications
|
||||||
case enableDeveloperOptions
|
case secureBackup
|
||||||
case developerOptions
|
case moderationAndSafety
|
||||||
case advancedSettings
|
case reportBug
|
||||||
case labs
|
|
||||||
case logout
|
case logout
|
||||||
case deactivateAccount
|
case deactivateAccount
|
||||||
|
|
||||||
|
case mediaUploadQuality
|
||||||
|
case appLock
|
||||||
|
case locationSharing
|
||||||
|
case analytics
|
||||||
|
case labs
|
||||||
|
case about
|
||||||
|
|
||||||
|
case enableDeveloperOptions
|
||||||
|
case developerOptions
|
||||||
|
|
||||||
enum UserStatusAction {
|
enum UserStatusAction {
|
||||||
/// Show status picker sheet to select a preset status.
|
/// Show status picker sheet to select a preset status.
|
||||||
case pickStatus
|
case pickStatus
|
||||||
|
|||||||
@@ -35,7 +35,8 @@ class SettingsScreenViewModel: SettingsScreenViewModelType, SettingsScreenViewMo
|
|||||||
showDeveloperOptions: userSettings.developerOptionsEnabled,
|
showDeveloperOptions: userSettings.developerOptionsEnabled,
|
||||||
showAnalyticsSettings: userSettings.canPromptForAnalytics,
|
showAnalyticsSettings: userSettings.canPromptForAnalytics,
|
||||||
isBugReportServiceEnabled: isBugReportServiceEnabled,
|
isBugReportServiceEnabled: isBugReportServiceEnabled,
|
||||||
navigationBarVisibility: isInSecondaryWindow ? .hidden : .automatic),
|
navigationBarVisibility: isInSecondaryWindow ? .hidden : .automatic,
|
||||||
|
bindings: .init(userSettings: userSettings)),
|
||||||
mediaProvider: userSession.mediaProvider)
|
mediaProvider: userSession.mediaProvider)
|
||||||
|
|
||||||
userSettings.developerOptionsEnabledPublisher
|
userSettings.developerOptionsEnabledPublisher
|
||||||
@@ -77,18 +78,6 @@ class SettingsScreenViewModel: SettingsScreenViewModelType, SettingsScreenViewMo
|
|||||||
}
|
}
|
||||||
.store(in: &cancellables)
|
.store(in: &cancellables)
|
||||||
|
|
||||||
userSession.clientProxy.ignoredUsersPublisher
|
|
||||||
.receive(on: DispatchQueue.main)
|
|
||||||
.map {
|
|
||||||
guard let blockedUsers = $0 else {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
return !blockedUsers.isEmpty
|
|
||||||
}
|
|
||||||
.weakAssign(to: \.state.showBlockedUsers, on: self)
|
|
||||||
.store(in: &cancellables)
|
|
||||||
|
|
||||||
Task {
|
Task {
|
||||||
if case .success(true) = await userSession.clientProxy.isUserStatusSupported() {
|
if case .success(true) = await userSession.clientProxy.isUserStatusSupported() {
|
||||||
state.showUserStatusInput = true
|
state.showUserStatusInput = true
|
||||||
@@ -102,6 +91,7 @@ class SettingsScreenViewModel: SettingsScreenViewModelType, SettingsScreenViewMo
|
|||||||
switch viewAction {
|
switch viewAction {
|
||||||
case .close:
|
case .close:
|
||||||
actionsSubject.send(.close)
|
actionsSubject.send(.close)
|
||||||
|
|
||||||
case .userDetails:
|
case .userDetails:
|
||||||
actionsSubject.send(.userDetails)
|
actionsSubject.send(.userDetails)
|
||||||
case .userStatus(.pickStatus):
|
case .userStatus(.pickStatus):
|
||||||
@@ -118,38 +108,45 @@ class SettingsScreenViewModel: SettingsScreenViewModelType, SettingsScreenViewMo
|
|||||||
case .userStatus(.cancel):
|
case .userStatus(.cancel):
|
||||||
state.bindings.isPresentingStatusPicker = false
|
state.bindings.isPresentingStatusPicker = false
|
||||||
state.bindings.isShowingCustomStatusField = false
|
state.bindings.isShowingCustomStatusField = false
|
||||||
|
|
||||||
case .addAccount:
|
case .addAccount:
|
||||||
actionsSubject.send(.addAccount)
|
actionsSubject.send(.addAccount)
|
||||||
case .linkNewDevice:
|
|
||||||
actionsSubject.send(.linkNewDevice)
|
|
||||||
case let .manageAccount(url):
|
case let .manageAccount(url):
|
||||||
actionsSubject.send(.manageAccount(url: url))
|
actionsSubject.send(.manageAccount(url: url))
|
||||||
case .analytics:
|
case .linkNewDevice:
|
||||||
actionsSubject.send(.analytics)
|
actionsSubject.send(.linkNewDevice)
|
||||||
case .appLock:
|
|
||||||
actionsSubject.send(.appLock)
|
|
||||||
case .reportBug:
|
|
||||||
actionsSubject.send(.reportBug)
|
|
||||||
case .about:
|
|
||||||
actionsSubject.send(.about)
|
|
||||||
case .blockedUsers:
|
|
||||||
actionsSubject.send(.blockedUsers)
|
|
||||||
case .logout:
|
|
||||||
actionsSubject.send(.logout)
|
|
||||||
case .secureBackup:
|
|
||||||
actionsSubject.send(.secureBackup)
|
|
||||||
case .notifications:
|
case .notifications:
|
||||||
actionsSubject.send(.notifications)
|
actionsSubject.send(.notifications)
|
||||||
case .advancedSettings:
|
case .secureBackup:
|
||||||
actionsSubject.send(.advancedSettings)
|
actionsSubject.send(.secureBackup)
|
||||||
|
case .moderationAndSafety:
|
||||||
|
actionsSubject.send(.moderationAndSafety)
|
||||||
|
case .reportBug:
|
||||||
|
actionsSubject.send(.reportBug)
|
||||||
|
|
||||||
|
case .logout:
|
||||||
|
actionsSubject.send(.logout)
|
||||||
|
case .deactivateAccount:
|
||||||
|
actionsSubject.send(.deactivateAccount)
|
||||||
|
|
||||||
|
case .mediaUploadQuality:
|
||||||
|
actionsSubject.send(.mediaUploadQuality)
|
||||||
|
case .appLock:
|
||||||
|
actionsSubject.send(.appLock)
|
||||||
|
case .locationSharing:
|
||||||
|
actionsSubject.send(.locationSharing)
|
||||||
|
case .analytics:
|
||||||
|
actionsSubject.send(.analytics)
|
||||||
case .labs:
|
case .labs:
|
||||||
actionsSubject.send(.labs)
|
actionsSubject.send(.labs)
|
||||||
|
case .about:
|
||||||
|
actionsSubject.send(.about)
|
||||||
|
|
||||||
case .enableDeveloperOptions:
|
case .enableDeveloperOptions:
|
||||||
userSettings.developerOptionsEnabled.toggle()
|
userSettings.developerOptionsEnabled.toggle()
|
||||||
case .developerOptions:
|
case .developerOptions:
|
||||||
actionsSubject.send(.developerOptions)
|
actionsSubject.send(.developerOptions)
|
||||||
case .deactivateAccount:
|
|
||||||
actionsSubject.send(.deactivateAccount)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -13,37 +13,19 @@ import SwiftUI
|
|||||||
struct SettingsScreen: View {
|
struct SettingsScreen: View {
|
||||||
@Bindable var context: SettingsScreenViewModel.Context
|
@Bindable var context: SettingsScreenViewModel.Context
|
||||||
|
|
||||||
private var shouldHideManageAccountSection: Bool {
|
|
||||||
context.viewState.accountProfileURL == nil &&
|
|
||||||
!context.viewState.showBlockedUsers &&
|
|
||||||
!context.viewState.showLinkNewDeviceButton
|
|
||||||
}
|
|
||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
Form {
|
Form {
|
||||||
userSection
|
userSection
|
||||||
|
|
||||||
if context.viewState.showUserStatusInput {
|
|
||||||
userStatusSection
|
|
||||||
}
|
|
||||||
|
|
||||||
if context.viewState.showAddAccountButton {
|
if context.viewState.showAddAccountButton {
|
||||||
addAccountSection
|
addAccountSection
|
||||||
}
|
}
|
||||||
|
|
||||||
if !shouldHideManageAccountSection {
|
accountSettingsSection
|
||||||
manageAccountSection
|
|
||||||
}
|
|
||||||
|
|
||||||
manageMyAppSection
|
|
||||||
|
|
||||||
generalSection
|
|
||||||
|
|
||||||
signOutSection
|
signOutSection
|
||||||
|
|
||||||
if context.viewState.showDeveloperOptions {
|
appSettingsSection
|
||||||
developerOptionsSection
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
.compoundList()
|
.compoundList()
|
||||||
.navigationTitle(L10n.commonSettings)
|
.navigationTitle(L10n.commonSettings)
|
||||||
@@ -91,13 +73,11 @@ struct SettingsScreen: View {
|
|||||||
.padding(.vertical, 8)
|
.padding(.vertical, 8)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
|
||||||
}
|
if context.viewState.showUserStatusInput {
|
||||||
|
SettingsScreenUserStatusRow(mode: context.viewState.userStatusRowMode) { action in
|
||||||
private var userStatusSection: some View {
|
context.send(viewAction: .userStatus(action))
|
||||||
Section {
|
}
|
||||||
SettingsScreenUserStatusRow(mode: context.viewState.userStatusRowMode) { action in
|
|
||||||
context.send(viewAction: .userStatus(action))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -113,36 +93,7 @@ struct SettingsScreen: View {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private var manageMyAppSection: some View {
|
private var accountSettingsSection: some View {
|
||||||
Section {
|
|
||||||
ListRow(label: .default(title: L10n.screenNotificationSettingsTitle,
|
|
||||||
icon: \.notifications),
|
|
||||||
kind: .navigationLink {
|
|
||||||
context.send(viewAction: .notifications)
|
|
||||||
})
|
|
||||||
.accessibilityIdentifier(A11yIdentifiers.settingsScreen.notifications)
|
|
||||||
|
|
||||||
ListRow(label: .default(title: L10n.commonScreenLock,
|
|
||||||
icon: \.lock),
|
|
||||||
kind: .navigationLink {
|
|
||||||
context.send(viewAction: .appLock)
|
|
||||||
})
|
|
||||||
.accessibilityIdentifier(A11yIdentifiers.settingsScreen.screenLock)
|
|
||||||
|
|
||||||
switch context.viewState.securitySectionMode {
|
|
||||||
case .secureBackup:
|
|
||||||
ListRow(label: .default(title: L10n.commonEncryption,
|
|
||||||
icon: \.key),
|
|
||||||
details: context.viewState.showSecuritySectionBadge ? .icon(securitySectionBadge) : nil,
|
|
||||||
kind: .navigationLink { context.send(viewAction: .secureBackup) })
|
|
||||||
.accessibilityIdentifier(A11yIdentifiers.settingsScreen.secureBackup)
|
|
||||||
default:
|
|
||||||
EmptyView()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private var manageAccountSection: some View {
|
|
||||||
Section {
|
Section {
|
||||||
if let url = context.viewState.accountProfileURL {
|
if let url = context.viewState.accountProfileURL {
|
||||||
ListRow(label: .default(title: L10n.actionManageAccountAndDevices,
|
ListRow(label: .default(title: L10n.actionManageAccountAndDevices,
|
||||||
@@ -161,39 +112,30 @@ struct SettingsScreen: View {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
if context.viewState.showBlockedUsers {
|
ListRow(label: .default(title: L10n.screenNotificationSettingsTitle,
|
||||||
ListRow(label: .default(title: L10n.commonBlockedUsers,
|
icon: \.notifications),
|
||||||
icon: \.block),
|
kind: .navigationLink {
|
||||||
kind: .navigationLink {
|
context.send(viewAction: .notifications)
|
||||||
context.send(viewAction: .blockedUsers)
|
})
|
||||||
})
|
.accessibilityIdentifier(A11yIdentifiers.settingsScreen.notifications)
|
||||||
.accessibilityIdentifier(A11yIdentifiers.settingsScreen.blockedUsers)
|
|
||||||
|
switch context.viewState.securitySectionMode {
|
||||||
|
case .secureBackup:
|
||||||
|
ListRow(label: .default(title: L10n.commonEncryption,
|
||||||
|
icon: \.key),
|
||||||
|
details: context.viewState.showSecuritySectionBadge ? .icon(securitySectionBadge) : nil,
|
||||||
|
kind: .navigationLink { context.send(viewAction: .secureBackup) })
|
||||||
|
.accessibilityIdentifier(A11yIdentifiers.settingsScreen.secureBackup)
|
||||||
|
default:
|
||||||
|
EmptyView()
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private var generalSection: some View {
|
|
||||||
Section {
|
|
||||||
ListRow(label: .default(title: L10n.commonAdvancedSettings,
|
|
||||||
icon: \.settings),
|
|
||||||
kind: .navigationLink {
|
|
||||||
context.send(viewAction: .advancedSettings)
|
|
||||||
})
|
|
||||||
.accessibilityIdentifier(A11yIdentifiers.settingsScreen.advancedSettings)
|
|
||||||
|
|
||||||
ListRow(label: .default(title: L10n.screenAdvancedSettingsLabs,
|
ListRow(label: .default(title: L10n.commonModerationAndSafety,
|
||||||
icon: \.labs),
|
icon: \.admin),
|
||||||
kind: .navigationLink {
|
kind: .navigationLink {
|
||||||
context.send(viewAction: .labs)
|
context.send(viewAction: .moderationAndSafety)
|
||||||
})
|
})
|
||||||
|
|
||||||
ListRow(label: .default(title: L10n.commonAbout,
|
|
||||||
icon: \.info),
|
|
||||||
kind: .navigationLink {
|
|
||||||
context.send(viewAction: .about)
|
|
||||||
})
|
|
||||||
.accessibilityIdentifier(A11yIdentifiers.settingsScreen.about)
|
|
||||||
|
|
||||||
if context.viewState.isBugReportServiceEnabled {
|
if context.viewState.isBugReportServiceEnabled {
|
||||||
ListRow(label: .default(title: L10n.commonReportAProblem,
|
ListRow(label: .default(title: L10n.commonReportAProblem,
|
||||||
icon: \.chatProblem),
|
icon: \.chatProblem),
|
||||||
@@ -202,15 +144,9 @@ struct SettingsScreen: View {
|
|||||||
})
|
})
|
||||||
.accessibilityIdentifier(A11yIdentifiers.settingsScreen.reportBug)
|
.accessibilityIdentifier(A11yIdentifiers.settingsScreen.reportBug)
|
||||||
}
|
}
|
||||||
|
} header: {
|
||||||
if context.viewState.showAnalyticsSettings {
|
Text(L10n.commonAccountSettings)
|
||||||
ListRow(label: .default(title: L10n.commonAnalytics,
|
.compoundListSectionHeader()
|
||||||
icon: \.chart),
|
|
||||||
kind: .navigationLink {
|
|
||||||
context.send(viewAction: .analytics)
|
|
||||||
})
|
|
||||||
.accessibilityIdentifier(A11yIdentifiers.settingsScreen.analytics)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -232,21 +168,68 @@ struct SettingsScreen: View {
|
|||||||
context.send(viewAction: .deactivateAccount)
|
context.send(viewAction: .deactivateAccount)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
} footer: {
|
|
||||||
if !context.viewState.showDeveloperOptions {
|
|
||||||
versionSection
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private var developerOptionsSection: some View {
|
private var appSettingsSection: some View {
|
||||||
Section {
|
Section {
|
||||||
ListRow(label: .default(title: L10n.commonDeveloperOptions,
|
ListRow(label: .default(title: L10n.commonAppearance,
|
||||||
icon: \.code),
|
icon: \.darkMode),
|
||||||
|
kind: .picker(selection: $context.appAppearance,
|
||||||
|
items: AppAppearance.allCases.map { (title: $0.name, tag: $0) }))
|
||||||
|
|
||||||
|
ListRow(label: .default(title: L10n.commonMediaUploadQuality,
|
||||||
|
icon: \.image),
|
||||||
kind: .navigationLink {
|
kind: .navigationLink {
|
||||||
context.send(viewAction: .developerOptions)
|
context.send(viewAction: .mediaUploadQuality)
|
||||||
})
|
})
|
||||||
.accessibilityIdentifier(A11yIdentifiers.settingsScreen.developerOptions)
|
|
||||||
|
ListRow(label: .default(title: L10n.commonScreenLock,
|
||||||
|
icon: \.lock),
|
||||||
|
kind: .navigationLink {
|
||||||
|
context.send(viewAction: .appLock)
|
||||||
|
})
|
||||||
|
.accessibilityIdentifier(A11yIdentifiers.settingsScreen.screenLock)
|
||||||
|
|
||||||
|
ListRow(label: .default(title: L10n.commonLocationSharing,
|
||||||
|
icon: \.locationPin),
|
||||||
|
kind: .navigationLink {
|
||||||
|
context.send(viewAction: .locationSharing)
|
||||||
|
})
|
||||||
|
|
||||||
|
if context.viewState.showAnalyticsSettings {
|
||||||
|
ListRow(label: .default(title: L10n.commonAnalytics,
|
||||||
|
icon: \.chart),
|
||||||
|
kind: .navigationLink {
|
||||||
|
context.send(viewAction: .analytics)
|
||||||
|
})
|
||||||
|
.accessibilityIdentifier(A11yIdentifiers.settingsScreen.analytics)
|
||||||
|
}
|
||||||
|
|
||||||
|
ListRow(label: .default(title: L10n.screenAdvancedSettingsLabs,
|
||||||
|
icon: \.labs),
|
||||||
|
kind: .navigationLink {
|
||||||
|
context.send(viewAction: .labs)
|
||||||
|
})
|
||||||
|
|
||||||
|
ListRow(label: .default(title: L10n.commonAbout,
|
||||||
|
icon: \.info),
|
||||||
|
kind: .navigationLink {
|
||||||
|
context.send(viewAction: .about)
|
||||||
|
})
|
||||||
|
.accessibilityIdentifier(A11yIdentifiers.settingsScreen.about)
|
||||||
|
|
||||||
|
if context.viewState.showDeveloperOptions {
|
||||||
|
ListRow(label: .default(title: L10n.commonDeveloperOptions,
|
||||||
|
icon: \.code),
|
||||||
|
kind: .navigationLink {
|
||||||
|
context.send(viewAction: .developerOptions)
|
||||||
|
})
|
||||||
|
.accessibilityIdentifier(A11yIdentifiers.settingsScreen.developerOptions)
|
||||||
|
}
|
||||||
|
} header: {
|
||||||
|
Text(L10n.commonAppSettings)
|
||||||
|
.compoundListSectionHeader()
|
||||||
} footer: {
|
} footer: {
|
||||||
versionSection
|
versionSection
|
||||||
}
|
}
|
||||||
@@ -291,6 +274,19 @@ struct SettingsScreen: View {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private extension AppAppearance {
|
||||||
|
var name: String {
|
||||||
|
switch self {
|
||||||
|
case .system:
|
||||||
|
L10n.themeSystem
|
||||||
|
case .light:
|
||||||
|
L10n.themeLight
|
||||||
|
case .dark:
|
||||||
|
L10n.themeDark
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// MARK: - Previews
|
// MARK: - Previews
|
||||||
|
|
||||||
@available(iOS 26.0, *)
|
@available(iOS 26.0, *)
|
||||||
@@ -303,7 +299,7 @@ struct SettingsScreen_Previews: PreviewProvider, TestablePreview {
|
|||||||
SettingsScreen(context: viewModel.context)
|
SettingsScreen(context: viewModel.context)
|
||||||
}
|
}
|
||||||
.snapshotPreferences(expect: viewModel.context.observe(\.viewState.accountProfileURL).map { $0 != nil })
|
.snapshotPreferences(expect: viewModel.context.observe(\.viewState.accountProfileURL).map { $0 != nil })
|
||||||
.frame(height: 1200)
|
.frame(height: 1300)
|
||||||
.previewLayout(.sizeThatFits)
|
.previewLayout(.sizeThatFits)
|
||||||
.previewDisplayName("Default")
|
.previewDisplayName("Default")
|
||||||
|
|
||||||
@@ -311,7 +307,7 @@ struct SettingsScreen_Previews: PreviewProvider, TestablePreview {
|
|||||||
SettingsScreen(context: bugReportDisabledViewModel.context)
|
SettingsScreen(context: bugReportDisabledViewModel.context)
|
||||||
}
|
}
|
||||||
.snapshotPreferences(expect: bugReportDisabledViewModel.context.observe(\.viewState.accountProfileURL).map { $0 != nil })
|
.snapshotPreferences(expect: bugReportDisabledViewModel.context.observe(\.viewState.accountProfileURL).map { $0 != nil })
|
||||||
.frame(height: 1150)
|
.frame(height: 1250)
|
||||||
.previewLayout(.sizeThatFits)
|
.previewLayout(.sizeThatFits)
|
||||||
.previewDisplayName("Bug report disabled")
|
.previewDisplayName("Bug report disabled")
|
||||||
}
|
}
|
||||||
@@ -323,6 +319,7 @@ struct SettingsScreen_Previews: PreviewProvider, TestablePreview {
|
|||||||
status: .mockFocussing))))
|
status: .mockFocussing))))
|
||||||
let userSettings = UserSettings.mock()
|
let userSettings = UserSettings.mock()
|
||||||
userSettings.multiAccountEnabled = true
|
userSettings.multiAccountEnabled = true
|
||||||
|
userSettings.linkNewDeviceEnabled = true
|
||||||
return SettingsScreenViewModel(userSession: userSession,
|
return SettingsScreenViewModel(userSession: userSession,
|
||||||
userSettings: userSettings,
|
userSettings: userSettings,
|
||||||
isBugReportServiceEnabled: isBugReportServiceEnabled,
|
isBugReportServiceEnabled: isBugReportServiceEnabled,
|
||||||
|
|||||||
@@ -18,13 +18,6 @@ extension PreviewTests {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
|
||||||
func advancedSettingsScreen() async throws {
|
|
||||||
for (index, preview) in AdvancedSettingsScreen_Previews._allPreviews.enumerated() {
|
|
||||||
try await assertSnapshots(matching: preview, step: index)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
func analyticsPromptScreen() async throws {
|
func analyticsPromptScreen() async throws {
|
||||||
for (index, preview) in AnalyticsPromptScreen_Previews._allPreviews.enumerated() {
|
for (index, preview) in AnalyticsPromptScreen_Previews._allPreviews.enumerated() {
|
||||||
|
|||||||
-3
@@ -1,3 +0,0 @@
|
|||||||
version https://git-lfs.github.com/spec/v1
|
|
||||||
oid sha256:e8ebdf9faecc3f6a907749856b1626392b83fb4bfd4ea05965fa2e36c53bc21e
|
|
||||||
size 203603
|
|
||||||
-3
@@ -1,3 +0,0 @@
|
|||||||
version https://git-lfs.github.com/spec/v1
|
|
||||||
oid sha256:694ab48bbf3b7d016ee5e6923bbcf984cfc54db145cf9e7bf60360671894ca40
|
|
||||||
size 241401
|
|
||||||
-3
@@ -1,3 +0,0 @@
|
|||||||
version https://git-lfs.github.com/spec/v1
|
|
||||||
oid sha256:f12e47794c0e762f3169a2f3f79d72932e4c26aa16f4c6932570adb506b5105e
|
|
||||||
size 139589
|
|
||||||
-3
@@ -1,3 +0,0 @@
|
|||||||
version https://git-lfs.github.com/spec/v1
|
|
||||||
oid sha256:fd0a047fe7214cfd947d44e59f30af73cea884eeb30199d3c782bc2f7430d32b
|
|
||||||
size 165304
|
|
||||||
+2
-2
@@ -1,3 +1,3 @@
|
|||||||
version https://git-lfs.github.com/spec/v1
|
version https://git-lfs.github.com/spec/v1
|
||||||
oid sha256:9eeed90de894bbf66e72b23a9cfe8b8aa455e8a9ff3f509a227203b2734bd411
|
oid sha256:6bac7010123a1a0362bd97ce148379de1be158efff8a4173cbf24bae6db91f8e
|
||||||
size 208003
|
size 239301
|
||||||
|
|||||||
+2
-2
@@ -1,3 +1,3 @@
|
|||||||
version https://git-lfs.github.com/spec/v1
|
version https://git-lfs.github.com/spec/v1
|
||||||
oid sha256:daa1d62daa786fa52e35f9f9924b969a627649037cf64e6949b692de837f3f89
|
oid sha256:15740810913e01029cc6aa4b2529601d34a3469e834c45d6070122b0eeef7a67
|
||||||
size 218666
|
size 255708
|
||||||
|
|||||||
+2
-2
@@ -1,3 +1,3 @@
|
|||||||
version https://git-lfs.github.com/spec/v1
|
version https://git-lfs.github.com/spec/v1
|
||||||
oid sha256:02ddd70542f4e8963f1745ee9f65e6f42e864bad5a28dffe052de35ac2ead3aa
|
oid sha256:487b3d2c1c331d620ba5b25392f5e634fddd3066739a8f49781c018851f3721a
|
||||||
size 132702
|
size 158210
|
||||||
|
|||||||
+2
-2
@@ -1,3 +1,3 @@
|
|||||||
version https://git-lfs.github.com/spec/v1
|
version https://git-lfs.github.com/spec/v1
|
||||||
oid sha256:ef1a98de9b2ddfb490882c5a937d2d7159a0a0ab513f41a8e1a1b1b3c95d5323
|
oid sha256:06720e67dd18586e9fad302dc8bb2f130785ed17867d98cfbe16b428186be812
|
||||||
size 148131
|
size 179850
|
||||||
|
|||||||
+2
-2
@@ -1,3 +1,3 @@
|
|||||||
version https://git-lfs.github.com/spec/v1
|
version https://git-lfs.github.com/spec/v1
|
||||||
oid sha256:56417caadb44c989b9ca9032d8eb6b13e5d02cead1537eb04a2ea262c8a3ea00
|
oid sha256:483cb6201103f76f2f102442e16be41c3a6cea8fe66d1b80bb1c111609a6c9fd
|
||||||
size 218308
|
size 249597
|
||||||
|
|||||||
+2
-2
@@ -1,3 +1,3 @@
|
|||||||
version https://git-lfs.github.com/spec/v1
|
version https://git-lfs.github.com/spec/v1
|
||||||
oid sha256:450405a9646962d1889af363b6da096a651d3d40dcb9a0212cafb7c1a2695f7d
|
oid sha256:b39b2a748e16f9da207f2b732afccd521baa926e452c90ec2291d8ede6ad1679
|
||||||
size 230377
|
size 267272
|
||||||
|
|||||||
+2
-2
@@ -1,3 +1,3 @@
|
|||||||
version https://git-lfs.github.com/spec/v1
|
version https://git-lfs.github.com/spec/v1
|
||||||
oid sha256:a3dcc827b87f5b49344477648239fa7bb46c1101324fab00ac8690943369fcf6
|
oid sha256:7a06ade1aacefd2c027fd317857ce1a55ce96e7c0a264b87c0cb4352fc6b21d2
|
||||||
size 140339
|
size 165653
|
||||||
|
|||||||
+2
-2
@@ -1,3 +1,3 @@
|
|||||||
version https://git-lfs.github.com/spec/v1
|
version https://git-lfs.github.com/spec/v1
|
||||||
oid sha256:91c5820e827e06ff4c2ab55c5ff86425fe0634172e3cfc2134574a6c955fb89e
|
oid sha256:926584ed061ee942d65d348016ee15775dbf01b91ec8a8408333e48ae16a26c4
|
||||||
size 158619
|
size 189795
|
||||||
|
|||||||
Reference in New Issue
Block a user