diff --git a/AccessibilityTests/Sources/GeneratedAccessibilityTests.swift b/AccessibilityTests/Sources/GeneratedAccessibilityTests.swift index f40724830..39fba9d3a 100644 --- a/AccessibilityTests/Sources/GeneratedAccessibilityTests.swift +++ b/AccessibilityTests/Sources/GeneratedAccessibilityTests.swift @@ -371,6 +371,10 @@ extension AccessibilityTests { try await performAccessibilityAudit(named: "MediaUploadPreviewScreen_Previews") } + func testMediaUploadQualitySettingsScreen() async throws { + try await performAccessibilityAudit(named: "MediaUploadQualitySettingsScreen_Previews") + } + func testMentionSuggestionItemView() async throws { try await performAccessibilityAudit(named: "MentionSuggestionItemView_Previews") } diff --git a/ElementX.xcodeproj/project.pbxproj b/ElementX.xcodeproj/project.pbxproj index acd1186a7..101def992 100644 --- a/ElementX.xcodeproj/project.pbxproj +++ b/ElementX.xcodeproj/project.pbxproj @@ -276,6 +276,7 @@ 2A61D2B4A225332CECA3B937 /* ReportRoomScreenViewModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = E20403084A320D588ACED200 /* ReportRoomScreenViewModelProtocol.swift */; }; 2AAB2A77F1762A2648078A30 /* InteractiveQuickLook.swift in Sources */ = {isa = PBXBuildFile; fileRef = 638A81B97D51591D0FCFA598 /* InteractiveQuickLook.swift */; }; 2AED12987603157C32C2114D /* TimelineBubbleLayout.swift in Sources */ = {isa = PBXBuildFile; fileRef = F5D8FEB1FED10E995CB002F7 /* TimelineBubbleLayout.swift */; }; + 2B3DB7659111C3DCD0FA292B /* MediaUploadQualitySettingsScreenCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = F1B0FC6A77FDFDE2BFE49E13 /* MediaUploadQualitySettingsScreenCoordinator.swift */; }; 2B52B2A5A6496C5C0F952776 /* BannedRoomProxy.swift in Sources */ = {isa = PBXBuildFile; fileRef = C30F45308428A4D9FFDB2FB8 /* BannedRoomProxy.swift */; }; 2B97BCE72D86645F1485C976 /* RoomDirectorySearchMock.swift in Sources */ = {isa = PBXBuildFile; fileRef = 894EE8F5B399A165BA2A6634 /* RoomDirectorySearchMock.swift */; }; 2BA59D0AEFB4B82A2EC2A326 /* KZFileWatchers in Frameworks */ = {isa = PBXBuildFile; productRef = A2AE110B053B55E38F8D10C7 /* KZFileWatchers */; }; @@ -1277,6 +1278,7 @@ C7ABEBECDC513F7887DACF66 /* ProgressMaskModifier.swift in Sources */ = {isa = PBXBuildFile; fileRef = 68010886142843705E342645 /* ProgressMaskModifier.swift */; }; C7CEFC1FB0547CFC8F5C84EF /* Room.swift in Sources */ = {isa = PBXBuildFile; fileRef = D78C13EF5035879B6131030F /* Room.swift */; }; C85C7A201E4CFDA477ACEBEB /* AppLockSetupSettingsScreenViewModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8610C1D21565C950BCA6A454 /* AppLockSetupSettingsScreenViewModelProtocol.swift */; }; + C8955836FCE5996156E53C04 /* MediaUploadQualitySettingsScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = 93597BF54039A6F78BF262D3 /* MediaUploadQualitySettingsScreen.swift */; }; C8A9C595038AFA2D707AC8C1 /* NotificationPermissionsScreenViewModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 20E69F67D2A70ABD08CA6D54 /* NotificationPermissionsScreenViewModelProtocol.swift */; }; C8BD80891BAD688EF2C15CDB /* MediaUploadPreviewScreenCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74DD0855F2F76D47E5555082 /* MediaUploadPreviewScreenCoordinator.swift */; }; C8D0AC22E03F652118A2BB73 /* LiveLocationRoomTimelineItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8A8DCBD0ABAADFDE5AF17E1F /* LiveLocationRoomTimelineItem.swift */; }; @@ -1371,6 +1373,7 @@ D4CB979EB4FE26AAD9F9A72B /* UserProfileScreenModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = 604A69C081B935D6A38DE6D8 /* UserProfileScreenModels.swift */; }; D4D7CCECC6C0AAFC42E165BB /* NotificationPermissionsScreenViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = BE9BBB18FB27F09032AD8769 /* NotificationPermissionsScreenViewModel.swift */; }; D4F3C5656DF09037825E9965 /* ChatsSpaceFiltersScreenModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = AEF2C15634499348A512A93A /* ChatsSpaceFiltersScreenModels.swift */; }; + D52AC68FB0F5416EF2FF1C1E /* MediaUploadQualitySettingsScreenViewModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = E8BE6111EF63F03420E975A3 /* MediaUploadQualitySettingsScreenViewModelProtocol.swift */; }; D55AF9B5B55FEED04771A461 /* RoomFlowCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9A008E57D52B07B78DFAD1BB /* RoomFlowCoordinator.swift */; }; D5B02E816B85F91AA81FA877 /* ManualClockTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2FCD606155B7B4AFC06B7635 /* ManualClockTests.swift */; }; D5B1531A72387D432939D4E0 /* RoomDirectorySearchProxyProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0516C69708D5CBDE1A8E77EC /* RoomDirectorySearchProxyProtocol.swift */; }; @@ -1382,6 +1385,7 @@ D61FCF6ABC1490F630E76AEC /* UserSettings.swift in Sources */ = {isa = PBXBuildFile; fileRef = 100DA305FE28BB3B6AEDE1FD /* UserSettings.swift */; }; D63974A88CF2BC721F109C77 /* Compound in Frameworks */ = {isa = PBXBuildFile; productRef = DCA3C4A997AD28E6918D4CE5 /* Compound */; }; D69CCEC785E6C819551B402F /* SearchScreenViewModelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5413213B56FB76C1071E2BFB /* SearchScreenViewModelTests.swift */; }; + D6C6B955768521400E39CA03 /* MediaUploadQualitySettingsScreenViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = B9346C59026725968B8C319B /* MediaUploadQualitySettingsScreenViewModel.swift */; }; D6DE764B17FB4A9A12C33BF4 /* MessageComposer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9F1DF3FFFE5ED2B8133F43A7 /* MessageComposer.swift */; }; D75C591C44C2510FDFA9C3D8 /* Macros in Frameworks */ = {isa = PBXBuildFile; productRef = AF574A0FC6F3A83D3BFFC9B3 /* Macros */; }; D7A26828D8715A17A1D52E66 /* AppSettingsTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = A11D53EE8E666C25F97B4369 /* AppSettingsTests.swift */; }; @@ -1537,6 +1541,7 @@ EF1C1A5D212B14FFCE0E7C83 /* SpaceScreenCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 094F6B21835890B470DF540C /* SpaceScreenCoordinator.swift */; }; EF47D802A404A53F15D5D4B6 /* JoinRoomScreenViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1CD7C0A2750998C2D77AD00F /* JoinRoomScreenViewModel.swift */; }; EF5009AC03212227131C8AF2 /* RoomNotificationSettingsProxyProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = E55B5EA766E89FF1F87C3ACB /* RoomNotificationSettingsProxyProtocol.swift */; }; + EF60752960985341733E9A34 /* MediaUploadQualitySettingsScreenModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = 12E62F8089AAA0FD61E756CA /* MediaUploadQualitySettingsScreenModels.swift */; }; EF890DEF0479E66548F2BA23 /* AppLockTimer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 490BEADEFB2D6B7C9F618AE8 /* AppLockTimer.swift */; }; EFB3033FE782773D4F105681 /* AccountUserDefaults.swift in Sources */ = {isa = PBXBuildFile; fileRef = 36F0A9118FF25E18D5CD6526 /* AccountUserDefaults.swift */; }; EFBBD44C0A16F017C32D2099 /* TimelineItemStatusView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 72614BFF35B8394C6E13F55A /* TimelineItemStatusView.swift */; }; @@ -1902,6 +1907,7 @@ 128501375217576AF0FE3E92 /* RoomAttachmentPicker.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomAttachmentPicker.swift; sourceTree = ""; }; 12B09A94C519227264A41208 /* RoomMembershipDetailsProxy.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomMembershipDetailsProxy.swift; sourceTree = ""; }; 12D0FBA1FE29833A915B77AE /* AccountProviderTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AccountProviderTests.swift; sourceTree = ""; }; + 12E62F8089AAA0FD61E756CA /* MediaUploadQualitySettingsScreenModels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MediaUploadQualitySettingsScreenModels.swift; sourceTree = ""; }; 1304D9191300873EADA52D6E /* IntegrationTests.xctestplan */ = {isa = PBXFileReference; path = IntegrationTests.xctestplan; sourceTree = ""; }; 130ED565A078F7E0B59D9D25 /* UNTextInputNotificationResponse+Creator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UNTextInputNotificationResponse+Creator.swift"; sourceTree = ""; }; 136F80A613B55BDD071DCEA5 /* JoinRoomScreenModels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = JoinRoomScreenModels.swift; sourceTree = ""; }; @@ -2668,6 +2674,7 @@ 9332DFE9642F0A46ECA0497B /* BlurHashEncode.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BlurHashEncode.swift; sourceTree = ""; }; 933B074F006F8E930DB98B4E /* TimelineMediaFrame.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TimelineMediaFrame.swift; sourceTree = ""; }; 9349F590E35CE514A71E6764 /* LoginHomeserver.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LoginHomeserver.swift; sourceTree = ""; }; + 93597BF54039A6F78BF262D3 /* MediaUploadQualitySettingsScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MediaUploadQualitySettingsScreen.swift; sourceTree = ""; }; 93C713D124FE915ABF47A6B7 /* TimelineView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TimelineView.swift; sourceTree = ""; }; 93CF7B19FFCF8EFBE0A8696A /* RoomScreenViewModelTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomScreenViewModelTests.swift; sourceTree = ""; }; 93E1FF0DFBB3768F79FDBF6D /* AVMetadataMachineReadableCodeObjectExtensionsTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AVMetadataMachineReadableCodeObjectExtensionsTest.swift; sourceTree = ""; }; @@ -2911,6 +2918,7 @@ B8F28602AC7AC881AED37EBA /* NavigationCoordinators.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NavigationCoordinators.swift; sourceTree = ""; }; B902EA6CD3296B0E10EE432B /* HomeScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HomeScreen.swift; sourceTree = ""; }; B91AD590B0B40718A0AA0C61 /* DeferredFulfillment.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DeferredFulfillment.swift; sourceTree = ""; }; + B9346C59026725968B8C319B /* MediaUploadQualitySettingsScreenViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MediaUploadQualitySettingsScreenViewModel.swift; sourceTree = ""; }; B9406BD5F99685C5ABDEDD93 /* LocationShareSheet.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LocationShareSheet.swift; sourceTree = ""; }; B94A6A57FE7E71F7605070AA /* NotificationToneManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationToneManager.swift; sourceTree = ""; }; B99E13633862847D8B7E2815 /* StartChatScreenModels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StartChatScreenModels.swift; sourceTree = ""; }; @@ -3182,6 +3190,7 @@ E858B68153E2C6E5800336AB /* CXCallControllerMock.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CXCallControllerMock.swift; sourceTree = ""; }; E8A1F98AE670377B20679FF5 /* MediaPlayerProvider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MediaPlayerProvider.swift; sourceTree = ""; }; E8AE4B3273BA189FDCD4055C /* UserIndicator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserIndicator.swift; sourceTree = ""; }; + E8BE6111EF63F03420E975A3 /* MediaUploadQualitySettingsScreenViewModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MediaUploadQualitySettingsScreenViewModelProtocol.swift; sourceTree = ""; }; E944F717FC10A428D027074D /* RoomPowerLevelsProxyMock.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomPowerLevelsProxyMock.swift; sourceTree = ""; }; E96792E7EE6742172DA3A35E /* AccountUserDefaultsTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AccountUserDefaultsTests.swift; sourceTree = ""; }; E9773983346838AABFAA914D /* UserSessionHook.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserSessionHook.swift; sourceTree = ""; }; @@ -3246,6 +3255,7 @@ F134D2D91DFF732FB75B2CB7 /* UserProfileScreenViewModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserProfileScreenViewModelProtocol.swift; sourceTree = ""; }; F174A5627CDB3CAF280D1880 /* EmojiPickerScreenModels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EmojiPickerScreenModels.swift; sourceTree = ""; }; F17EFA1D3D09FC2F9C5E1CB2 /* MediaProvider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MediaProvider.swift; sourceTree = ""; }; + F1B0FC6A77FDFDE2BFE49E13 /* MediaUploadQualitySettingsScreenCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MediaUploadQualitySettingsScreenCoordinator.swift; sourceTree = ""; }; F1B8500C152BC59445647DA8 /* UnsupportedRoomTimelineItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UnsupportedRoomTimelineItem.swift; sourceTree = ""; }; F229480685F30BCB96C439EC /* AdvancedSettingsScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AdvancedSettingsScreen.swift; sourceTree = ""; }; F276F31C1AEC19E52B951B62 /* SendInviteConfirmationView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SendInviteConfirmationView.swift; sourceTree = ""; }; @@ -5265,6 +5275,7 @@ CBB8EC37B802F3DD74A0205E /* DeactivateAccountScreen */, 1CA6CD0DE6F0445156361B6D /* DeveloperOptionsScreen */, 38A1C74493B816B8753F5BC2 /* LegalInformationScreen */, + B92D540BF25A95D647C271BA /* MediaUploadQualitySettingsScreen */, 91D3BE26C39545233959CDCE /* ModerationAndSafetySettingsScreen */, 441115752CA2408F26A72D11 /* NotificationSettingsEditScreen */, 7B91CB64534AD870924CCFEF /* NotificationSettingsScreen */, @@ -6623,6 +6634,18 @@ path = RoomMemberDetailsScreen; sourceTree = ""; }; + B92D540BF25A95D647C271BA /* MediaUploadQualitySettingsScreen */ = { + isa = PBXGroup; + children = ( + F1B0FC6A77FDFDE2BFE49E13 /* MediaUploadQualitySettingsScreenCoordinator.swift */, + 12E62F8089AAA0FD61E756CA /* MediaUploadQualitySettingsScreenModels.swift */, + B9346C59026725968B8C319B /* MediaUploadQualitySettingsScreenViewModel.swift */, + E8BE6111EF63F03420E975A3 /* MediaUploadQualitySettingsScreenViewModelProtocol.swift */, + C877C16D7AE44E0F1F4AF931 /* View */, + ); + path = MediaUploadQualitySettingsScreen; + sourceTree = ""; + }; BB11CF5847CA0B3BC3A7F8DA /* View */ = { isa = PBXGroup; children = ( @@ -6824,6 +6847,14 @@ path = View; sourceTree = ""; }; + C877C16D7AE44E0F1F4AF931 /* View */ = { + isa = PBXGroup; + children = ( + 93597BF54039A6F78BF262D3 /* MediaUploadQualitySettingsScreen.swift */, + ); + path = View; + sourceTree = ""; + }; CA15BB3F6C62B35AE2C281A9 /* Provider */ = { isa = PBXGroup; children = ( @@ -9197,6 +9228,11 @@ 3B0F9B57D25B07E66F15762A /* MediaUploadPreviewScreenModels.swift in Sources */, A969147E0EEE0E27EE226570 /* MediaUploadPreviewScreenViewModel.swift in Sources */, 9B872FF37DBE6BE054903831 /* MediaUploadPreviewScreenViewModelProtocol.swift in Sources */, + C8955836FCE5996156E53C04 /* MediaUploadQualitySettingsScreen.swift in Sources */, + 2B3DB7659111C3DCD0FA292B /* MediaUploadQualitySettingsScreenCoordinator.swift in Sources */, + EF60752960985341733E9A34 /* MediaUploadQualitySettingsScreenModels.swift in Sources */, + D6C6B955768521400E39CA03 /* MediaUploadQualitySettingsScreenViewModel.swift in Sources */, + D52AC68FB0F5416EF2FF1C1E /* MediaUploadQualitySettingsScreenViewModelProtocol.swift in Sources */, 8A0BD60CA4A6004DB06B5403 /* MediaUploadingPreprocessor.swift in Sources */, 8C706DA7EAC0974CA2F8F1CD /* MentionBuilder.swift in Sources */, F669B55BC237CDA5EC9332FE /* MentionSuggestionItemView.swift in Sources */, diff --git a/ElementX/Sources/Other/TestablePreview/TestablePreviewsDictionary.swift b/ElementX/Sources/Other/TestablePreview/TestablePreviewsDictionary.swift index be2653778..d1f779ee2 100644 --- a/ElementX/Sources/Other/TestablePreview/TestablePreviewsDictionary.swift +++ b/ElementX/Sources/Other/TestablePreview/TestablePreviewsDictionary.swift @@ -97,6 +97,7 @@ enum TestablePreviewsDictionary { "MatrixUserPermalink_Previews" : MatrixUserPermalink_Previews.self, "MediaEventsTimelineScreen_Previews" : MediaEventsTimelineScreen_Previews.self, "MediaUploadPreviewScreen_Previews" : MediaUploadPreviewScreen_Previews.self, + "MediaUploadQualitySettingsScreen_Previews" : MediaUploadQualitySettingsScreen_Previews.self, "MentionSuggestionItemView_Previews" : MentionSuggestionItemView_Previews.self, "MessageComposerTextField_Previews" : MessageComposerTextField_Previews.self, "MessageComposer_Previews" : MessageComposer_Previews.self, diff --git a/ElementX/Sources/Screens/Settings/MediaUploadQualitySettingsScreen/MediaUploadQualitySettingsScreenCoordinator.swift b/ElementX/Sources/Screens/Settings/MediaUploadQualitySettingsScreen/MediaUploadQualitySettingsScreenCoordinator.swift new file mode 100644 index 000000000..52106307c --- /dev/null +++ b/ElementX/Sources/Screens/Settings/MediaUploadQualitySettingsScreen/MediaUploadQualitySettingsScreenCoordinator.swift @@ -0,0 +1,26 @@ +// +// Copyright 2026 Element Creations 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 MediaUploadQualitySettingsScreenCoordinatorParameters { + let userSettings: UserSettings + let analytics: AnalyticsServiceProtocol +} + +final class MediaUploadQualitySettingsScreenCoordinator: CoordinatorProtocol { + private var viewModel: MediaUploadQualitySettingsScreenViewModelProtocol + + init(parameters: MediaUploadQualitySettingsScreenCoordinatorParameters) { + viewModel = MediaUploadQualitySettingsScreenViewModel(userSettings: parameters.userSettings, analytics: parameters.analytics) + } + + func toPresentable() -> AnyView { + AnyView(MediaUploadQualitySettingsScreen(context: viewModel.context)) + } +} diff --git a/ElementX/Sources/Screens/Settings/MediaUploadQualitySettingsScreen/MediaUploadQualitySettingsScreenModels.swift b/ElementX/Sources/Screens/Settings/MediaUploadQualitySettingsScreen/MediaUploadQualitySettingsScreenModels.swift new file mode 100644 index 000000000..8a3da915b --- /dev/null +++ b/ElementX/Sources/Screens/Settings/MediaUploadQualitySettingsScreen/MediaUploadQualitySettingsScreenModels.swift @@ -0,0 +1,30 @@ +// +// Copyright 2026 Element Creations 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 MediaUploadQualitySettingsScreenViewState: BindableState { + var bindings: MediaUploadQualitySettingsScreenViewStateBindings +} + +struct MediaUploadQualitySettingsScreenViewStateBindings { + private let userSettings: UserSettings + + init(userSettings: UserSettings) { + self.userSettings = userSettings + } + + var optimizeMediaUploads: Bool { + get { userSettings.optimizeMediaUploads } + set { userSettings.optimizeMediaUploads = newValue } + } +} + +enum MediaUploadQualitySettingsScreenViewAction { + case optimizeMediaUploadsChanged +} diff --git a/ElementX/Sources/Screens/Settings/MediaUploadQualitySettingsScreen/MediaUploadQualitySettingsScreenViewModel.swift b/ElementX/Sources/Screens/Settings/MediaUploadQualitySettingsScreen/MediaUploadQualitySettingsScreenViewModel.swift new file mode 100644 index 000000000..16a011ec1 --- /dev/null +++ b/ElementX/Sources/Screens/Settings/MediaUploadQualitySettingsScreen/MediaUploadQualitySettingsScreenViewModel.swift @@ -0,0 +1,30 @@ +// +// Copyright 2026 Element Creations 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 MediaUploadQualitySettingsScreenViewModelType = StateStoreViewModelV2 + +class MediaUploadQualitySettingsScreenViewModel: MediaUploadQualitySettingsScreenViewModelType, MediaUploadQualitySettingsScreenViewModelProtocol { + private let analytics: AnalyticsServiceProtocol + + init(userSettings: UserSettings, analytics: AnalyticsServiceProtocol) { + self.analytics = analytics + + let state = MediaUploadQualitySettingsScreenViewState(bindings: .init(userSettings: userSettings)) + super.init(initialViewState: state) + } + + override func process(viewAction: MediaUploadQualitySettingsScreenViewAction) { + 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) + } + } +} diff --git a/ElementX/Sources/Screens/Settings/MediaUploadQualitySettingsScreen/MediaUploadQualitySettingsScreenViewModelProtocol.swift b/ElementX/Sources/Screens/Settings/MediaUploadQualitySettingsScreen/MediaUploadQualitySettingsScreenViewModelProtocol.swift new file mode 100644 index 000000000..967e34ec8 --- /dev/null +++ b/ElementX/Sources/Screens/Settings/MediaUploadQualitySettingsScreen/MediaUploadQualitySettingsScreenViewModelProtocol.swift @@ -0,0 +1,12 @@ +// +// Copyright 2026 Element Creations 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 MediaUploadQualitySettingsScreenViewModelProtocol { + var context: MediaUploadQualitySettingsScreenViewModelType.Context { get } +} diff --git a/ElementX/Sources/Screens/Settings/MediaUploadQualitySettingsScreen/View/MediaUploadQualitySettingsScreen.swift b/ElementX/Sources/Screens/Settings/MediaUploadQualitySettingsScreen/View/MediaUploadQualitySettingsScreen.swift new file mode 100644 index 000000000..f33e55727 --- /dev/null +++ b/ElementX/Sources/Screens/Settings/MediaUploadQualitySettingsScreen/View/MediaUploadQualitySettingsScreen.swift @@ -0,0 +1,41 @@ +// +// Copyright 2026 Element Creations 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 MediaUploadQualitySettingsScreen: View { + @Bindable var context: MediaUploadQualitySettingsScreenViewModel.Context + + var body: some View { + Form { + Section { + ListRow(label: .plain(title: L10n.screenAdvancedSettingsMediaCompressionTitle, + description: L10n.screenAdvancedSettingsMediaCompressionDescription), + kind: .toggle($context.optimizeMediaUploads)) + .onChange(of: context.optimizeMediaUploads) { + context.send(viewAction: .optimizeMediaUploadsChanged) + } + } + } + .compoundList() + .navigationTitle(L10n.commonMediaUploadQuality) + .navigationBarTitleDisplayMode(.inline) + } +} + +// MARK: - Previews + +struct MediaUploadQualitySettingsScreen_Previews: PreviewProvider, TestablePreview { + static let viewModel = MediaUploadQualitySettingsScreenViewModel(userSettings: .mock(), analytics: AnalyticsServiceMock(.init())) + + static var previews: some View { + ElementNavigationStack { + MediaUploadQualitySettingsScreen(context: viewModel.context) + } + } +} diff --git a/PreviewTests/Sources/GeneratedPreviewTests.swift b/PreviewTests/Sources/GeneratedPreviewTests.swift index c0417ac13..64cba3601 100644 --- a/PreviewTests/Sources/GeneratedPreviewTests.swift +++ b/PreviewTests/Sources/GeneratedPreviewTests.swift @@ -648,6 +648,13 @@ extension PreviewTests { } } + @Test + func mediaUploadQualitySettingsScreen() async throws { + for (index, preview) in MediaUploadQualitySettingsScreen_Previews._allPreviews.enumerated() { + try await assertSnapshots(matching: preview, step: index) + } + } + @Test func mentionSuggestionItemView() async throws { for (index, preview) in MentionSuggestionItemView_Previews._allPreviews.enumerated() { diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/mediaUploadQualitySettingsScreen.iPad-en-GB-0.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/mediaUploadQualitySettingsScreen.iPad-en-GB-0.png new file mode 100644 index 000000000..c950075d2 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/mediaUploadQualitySettingsScreen.iPad-en-GB-0.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:b8b53d089dda5d52e3884f66c4b620b150cee70c7cbed600e25b64b9af6b7658 +size 98299 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/mediaUploadQualitySettingsScreen.iPad-pseudo-0.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/mediaUploadQualitySettingsScreen.iPad-pseudo-0.png new file mode 100644 index 000000000..2f71108a9 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/mediaUploadQualitySettingsScreen.iPad-pseudo-0.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:ef83dceec15d76c36a730962dff164e42d3e7bce026724b371a12aef5839e819 +size 104882 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/mediaUploadQualitySettingsScreen.iPhone-en-GB-0.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/mediaUploadQualitySettingsScreen.iPhone-en-GB-0.png new file mode 100644 index 000000000..3969ce29c --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/mediaUploadQualitySettingsScreen.iPhone-en-GB-0.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:c06a71353d4209a6b1b602f7338018e8e9b5e18e05434c65281a1d4508ddafac +size 52145 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/mediaUploadQualitySettingsScreen.iPhone-pseudo-0.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/mediaUploadQualitySettingsScreen.iPhone-pseudo-0.png new file mode 100644 index 000000000..bafbee717 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/mediaUploadQualitySettingsScreen.iPhone-pseudo-0.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:16340fb4568d841992eb3c360382933bfc782b66d35bed9f107b48e334c3d599 +size 64622