implemented the labs screen

This commit is contained in:
Mauro Romito
2025-10-03 18:19:03 +02:00
committed by Mauro
parent b110a7ba51
commit b58d4269f4
20 changed files with 257 additions and 12 deletions
@@ -247,6 +247,10 @@ extension AccessibilityTests {
try await performAccessibilityAudit(named: "KnockRequestsListScreen_Previews")
}
func testLabsScreen() async throws {
try await performAccessibilityAudit(named: "LabsScreen_Previews")
}
func testLeaveSpaceView() async throws {
try await performAccessibilityAudit(named: "LeaveSpaceView_Previews")
}
+36
View File
@@ -288,6 +288,7 @@
32B7891D937377A59606EDFC /* UserFlowTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 21DD8599815136EFF5B73F38 /* UserFlowTests.swift */; };
32F47002A331817F0E6BD7EB /* RoomMembershipDetailsProxyProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1434D5169F0EE319E226DA7F /* RoomMembershipDetailsProxyProtocol.swift */; };
339BC18777912E1989F2F17D /* Section.swift in Sources */ = {isa = PBXBuildFile; fileRef = 584A61D9C459FAFEF038A7C0 /* Section.swift */; };
33BA0964A308D2286B39976D /* LabsScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = D9C5AA3EF7EC67C01C75CEDD /* LabsScreen.swift */; };
33CAC1226DFB8B5D8447D286 /* GZIP in Frameworks */ = {isa = PBXBuildFile; productRef = 1BCD21310B997A6837B854D6 /* GZIP */; };
33F1FB19F222BA9930AB1A00 /* RoomListFiltersView.swift in Sources */ = {isa = PBXBuildFile; fileRef = E6372DD10DED30E7AD7BCE21 /* RoomListFiltersView.swift */; };
340D39DB87F3800D53A6A621 /* EmojiPickerScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = 00245D40CD90FD71D6A05239 /* EmojiPickerScreen.swift */; };
@@ -1117,6 +1118,7 @@
C8E0FA0FF2CD6613264FA6B9 /* MessageForwardingScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = BFEA446F8618DBA79A9239CC /* MessageForwardingScreen.swift */; };
C8E11A335456FCF94A744E6E /* SpaceFlowCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = EDDE826EAB1BAB80C1104980 /* SpaceFlowCoordinator.swift */; };
C8E1E4E06B7C7A3A8246FC9B /* MediaEventsTimelineScreenCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8512B82404B1751D0BCC82D2 /* MediaEventsTimelineScreenCoordinator.swift */; };
C900127318820AD04D6C90B8 /* LabsScreenModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5E43D8784B0054C048060FEB /* LabsScreenModels.swift */; };
C915347779B3C7FDD073A87A /* AVMetadataMachineReadableCodeObjectExtensionsTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 93E1FF0DFBB3768F79FDBF6D /* AVMetadataMachineReadableCodeObjectExtensionsTest.swift */; };
C969A62F3D9F14318481A33B /* KnockedRoomProxy.swift in Sources */ = {isa = PBXBuildFile; fileRef = 858DA81F2ACF484B7CAD6AE4 /* KnockedRoomProxy.swift */; };
C97325EFDCCEE457432A9E82 /* MessageText.swift in Sources */ = {isa = PBXBuildFile; fileRef = E1E0B4A34E69BD2132BEC521 /* MessageText.swift */; };
@@ -1160,10 +1162,12 @@
D104B27C5DA0626B41CE78D3 /* CurrentValuePublisher.swift in Sources */ = {isa = PBXBuildFile; fileRef = 127C8472672A5BA09EF1ACF8 /* CurrentValuePublisher.swift */; };
D10BA4F041DC58580A440A32 /* RoomRolesAndPermissionsScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = B2B1DC3B3FB40A7F4AE9B7BF /* RoomRolesAndPermissionsScreen.swift */; };
D12F440F7973F1489F61389D /* NotificationSettingsScreenModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0F64447FF544298A6A3BEF85 /* NotificationSettingsScreenModels.swift */; };
D150D6E96CA6CA09FA50E13C /* LabsScreenCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4CF17EFB2833B4CE5C06E7F8 /* LabsScreenCoordinator.swift */; };
D18B70975644C24F60656C0D /* KnockRequestProxyProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = C07851F4EA81AA3339806A7B /* KnockRequestProxyProtocol.swift */; };
D19A748E95E2FAB2940570F0 /* CallScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = E4103AB4340F2974D690A12A /* CallScreen.swift */; };
D2048FD56760BDABA3DB5FC2 /* AppLockServiceProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 26EAAB54C6CE91D64B69A9F8 /* AppLockServiceProtocol.swift */; };
D22345698F6548C1EE960940 /* IdentityConfirmedScreenModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3DBE70FFB7936F35811772C1 /* IdentityConfirmedScreenModels.swift */; };
D23BA23864EA7BA3F353C0D1 /* LabsScreenViewModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = CF847A34FC4C8C937CD39E08 /* LabsScreenViewModelProtocol.swift */; };
D2466C6BC8CAD8FADD7BF89B /* RoomPreviewProxyMock.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6695C64F066628411EAD21E9 /* RoomPreviewProxyMock.swift */; };
D26093BB80B69092B0E9AC7C /* PinnedItemsIndicatorView.swift in Sources */ = {isa = PBXBuildFile; fileRef = E66763BD54A3A1D9C6E6F2F1 /* PinnedItemsIndicatorView.swift */; };
D2825E013A8ECFB66D9A1DE6 /* RoomChangeRolesScreenViewModelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8F841F219ACDFC1D3F42FEFB /* RoomChangeRolesScreenViewModelTests.swift */; };
@@ -1288,6 +1292,7 @@
EB9F4688006B52E69DF5358F /* BlankFormCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1C7F63EB1525E697CAEB002B /* BlankFormCoordinator.swift */; };
EBE13FAB4E29738AC41BD3E5 /* InfoPlistReader.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6A580295A56B55A856CC4084 /* InfoPlistReader.swift */; };
EC09E502A21E4EAA8B367AB8 /* ReportContentScreenViewModelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 30EA681527A8FE65E4C8E9A9 /* ReportContentScreenViewModelTests.swift */; };
EC1A0E85CEE50BF0C64EEFA5 /* LabsScreenViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = A4D9DF4F2DF3507F99B5B97B /* LabsScreenViewModel.swift */; };
EC280623A42904341363EAAF /* Collections in Frameworks */ = {isa = PBXBuildFile; productRef = A20EA00CCB9DBE0FFB17DD09 /* Collections */; };
EC3320639828BED8B3E5F2C6 /* EncryptionResetScreenViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5875F7C0A2398E9F134B1284 /* EncryptionResetScreenViewModel.swift */; };
ED3E91E6166E4923791ACA84 /* ResolveVerifiedUserSendFailureScreenViewModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 56852036214ABA9D7D305768 /* ResolveVerifiedUserSendFailureScreenViewModelProtocol.swift */; };
@@ -1912,6 +1917,7 @@
4C8D988E82A8DFA13BE46F7C /* pl */ = {isa = PBXFileReference; lastKnownFileType = text.plist.stringsdict; name = pl; path = pl.lproj/Localizable.stringsdict; sourceTree = "<group>"; };
4CD6AC7546E8D7E5C73CEA48 /* ElementX.app */ = {isa = PBXFileReference; includeInIndex = 0; lastKnownFileType = wrapper.application; path = ElementX.app; sourceTree = BUILT_PRODUCTS_DIR; };
4CDDDDD9FE1A699D23A5E096 /* LoginScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LoginScreen.swift; sourceTree = "<group>"; };
4CF17EFB2833B4CE5C06E7F8 /* LabsScreenCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LabsScreenCoordinator.swift; sourceTree = "<group>"; };
4D3A7375AB22721C436EB056 /* ComposerToolbarModels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ComposerToolbarModels.swift; sourceTree = "<group>"; };
4D635709C1D6D37C225AD40E /* RoomPowerLevelProxyProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomPowerLevelProxyProtocol.swift; sourceTree = "<group>"; };
4E2245243369B99216C7D84E /* ImageCache.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ImageCache.swift; sourceTree = "<group>"; };
@@ -1991,6 +1997,7 @@
5D53754227CEBD06358956D7 /* PinnedEventsTimelineScreenCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PinnedEventsTimelineScreenCoordinator.swift; sourceTree = "<group>"; };
5DE8D25D6A91030175D52A20 /* RoomTimelineItemProperties.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomTimelineItemProperties.swift; sourceTree = "<group>"; };
5E33FD32BBC44D703C7AE4F9 /* TextBasedRoomTimelineItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TextBasedRoomTimelineItem.swift; sourceTree = "<group>"; };
5E43D8784B0054C048060FEB /* LabsScreenModels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LabsScreenModels.swift; sourceTree = "<group>"; };
5E6DE144D887A254F4CAF203 /* UserPreference.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserPreference.swift; sourceTree = "<group>"; };
5E75948AA1FE1D1A7809931F /* AuthenticationServiceProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AuthenticationServiceProtocol.swift; sourceTree = "<group>"; };
5E9CBF577B9711CFBB4FA40D /* VoiceMessageRecordingView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VoiceMessageRecordingView.swift; sourceTree = "<group>"; };
@@ -2346,6 +2353,7 @@
A433BE28B40D418237BE37B5 /* ReportContentScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ReportContentScreen.swift; sourceTree = "<group>"; };
A436057DBEA1A23CA8CB1FD7 /* UIFont+AttributedStringBuilder.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "UIFont+AttributedStringBuilder.h"; sourceTree = "<group>"; };
A443FAE2EE820A5790C35C8D /* et */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = et; path = et.lproj/Localizable.strings; sourceTree = "<group>"; };
A4D9DF4F2DF3507F99B5B97B /* LabsScreenViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LabsScreenViewModel.swift; sourceTree = "<group>"; };
A54AAF72E821B4084B7E4298 /* PinnedEventsTimelineFlowCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PinnedEventsTimelineFlowCoordinator.swift; sourceTree = "<group>"; };
A6B19D10B102956066AF117B /* PollOptionView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PollOptionView.swift; sourceTree = "<group>"; };
A6B891A6DA826E2461DBB40F /* PHGPostHogConfiguration.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PHGPostHogConfiguration.swift; sourceTree = "<group>"; };
@@ -2576,6 +2584,7 @@
CDE3F3911FF7CC639BDE5844 /* nl */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = nl; path = nl.lproj/Localizable.strings; sourceTree = "<group>"; };
CEE20623EB4A9B88FB29F2BA /* fr */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = fr; path = fr.lproj/SAS.strings; sourceTree = "<group>"; };
CEE41494C837AA403A06A5D9 /* UnitTests.xctestplan */ = {isa = PBXFileReference; path = UnitTests.xctestplan; sourceTree = "<group>"; };
CF847A34FC4C8C937CD39E08 /* LabsScreenViewModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LabsScreenViewModelProtocol.swift; sourceTree = "<group>"; };
CFFA5E881D281810AB428EA3 /* RoomPowerLevelsProxy.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomPowerLevelsProxy.swift; sourceTree = "<group>"; };
D01FD1171FF40E34D707FD00 /* BigIcon.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BigIcon.swift; sourceTree = "<group>"; };
D03D7ECAC68C2FFB8CF01BCB /* DeactivateAccountScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DeactivateAccountScreen.swift; sourceTree = "<group>"; };
@@ -2631,6 +2640,7 @@
D93C94C30E3135BC9290DE13 /* VoiceMessageRecorderTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VoiceMessageRecorderTests.swift; sourceTree = "<group>"; };
D95E8C0EFEC0C6F96EDAA71A /* PreviewTests.xctest */ = {isa = PBXFileReference; includeInIndex = 0; lastKnownFileType = wrapper.cfbundle; path = PreviewTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
D97A4E73EA97CA08D2BB9806 /* RoomScreenTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomScreenTests.swift; sourceTree = "<group>"; };
D9C5AA3EF7EC67C01C75CEDD /* LabsScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LabsScreen.swift; sourceTree = "<group>"; };
DA14564EE143F73F7E4D1F79 /* RoomNotificationSettingsScreenModels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomNotificationSettingsScreenModels.swift; sourceTree = "<group>"; };
DA3D82522494E78746B2214E /* de */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = de; path = de.lproj/SAS.strings; sourceTree = "<group>"; };
DAB8D7926A5684E18196B538 /* VoiceMessageCache.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VoiceMessageCache.swift; sourceTree = "<group>"; };
@@ -3180,6 +3190,14 @@
path = Supplementary;
sourceTree = "<group>";
};
155D9F609E878C1875A366D4 /* View */ = {
isa = PBXGroup;
children = (
D9C5AA3EF7EC67C01C75CEDD /* LabsScreen.swift */,
);
path = View;
sourceTree = "<group>";
};
15D44FCA9475E660B7F56DB9 /* Timeline */ = {
isa = PBXGroup;
children = (
@@ -4093,6 +4111,18 @@
path = UnitTests;
sourceTree = "<group>";
};
4D963F50D7AA8FE302CA8ACF /* LabsScreen */ = {
isa = PBXGroup;
children = (
4CF17EFB2833B4CE5C06E7F8 /* LabsScreenCoordinator.swift */,
5E43D8784B0054C048060FEB /* LabsScreenModels.swift */,
A4D9DF4F2DF3507F99B5B97B /* LabsScreenViewModel.swift */,
CF847A34FC4C8C937CD39E08 /* LabsScreenViewModelProtocol.swift */,
155D9F609E878C1875A366D4 /* View */,
);
path = LabsScreen;
sourceTree = "<group>";
};
4DC0344D2EBD0AE5D71754A9 /* RoomMembershipDetails */ = {
isa = PBXGroup;
children = (
@@ -6184,6 +6214,7 @@
F12966DF3DA87FEF21348D60 /* InviteUsersScreen */,
FFD7C58CA6A7D6BBC2F584B5 /* JoinRoomScreen */,
BF0415BE807CA2BCFC210008 /* KnockRequestsListScreen */,
4D963F50D7AA8FE302CA8ACF /* LabsScreen */,
948DD12A5533BE1BC260E437 /* LocationSharing */,
73E032ADD008D63812791D97 /* LogViewerScreen */,
3D76DA5827DF9396AC90E7B4 /* ManageRoomMemberSheet */,
@@ -7840,6 +7871,11 @@
454F8DDC4442C0DE54094902 /* LABiometryType.swift in Sources */,
E468CC731C3F4D678499E52F /* LAContextMock.swift in Sources */,
D5681C80D8281560AACE0035 /* Label.swift in Sources */,
33BA0964A308D2286B39976D /* LabsScreen.swift in Sources */,
D150D6E96CA6CA09FA50E13C /* LabsScreenCoordinator.swift in Sources */,
C900127318820AD04D6C90B8 /* LabsScreenModels.swift in Sources */,
EC1A0E85CEE50BF0C64EEFA5 /* LabsScreenViewModel.swift in Sources */,
D23BA23864EA7BA3F353C0D1 /* LabsScreenViewModelProtocol.swift in Sources */,
EEAE954289DE813A61656AE0 /* LayoutDirection.swift in Sources */,
EFF735EC040BEB669AFBAB50 /* LeaveSpaceHandleProxy.swift in Sources */,
DD21CE51DF9BD04FC8155972 /* LeaveSpaceHandleSDKMock.swift in Sources */,
@@ -102,6 +102,8 @@ class SettingsFlowCoordinator: FlowCoordinatorProtocol {
presentNotificationSettings()
case .advancedSettings:
presentAdvancedSettings()
case .labs:
presentLabs()
case .developerOptions:
presentDeveloperOptions()
case .deactivateAccount:
@@ -113,6 +115,11 @@ class SettingsFlowCoordinator: FlowCoordinatorProtocol {
navigationStackCoordinator.setRootCoordinator(settingsScreenCoordinator, animated: animated)
}
private func presentLabs() {
let coordinator = LabsScreenCoordinator(parameters: .init(appSettings: flowParameters.appSettings))
navigationStackCoordinator.push(coordinator)
}
private func startEncryptionSettingsFlow(animated: Bool) {
let coordinator = EncryptionSettingsFlowCoordinator(parameters: .init(userSession: flowParameters.userSession,
appSettings: flowParameters.appSettings,
@@ -69,6 +69,7 @@ enum TestablePreviewsDictionary {
"KnockRequestsBannerView_Previews" : KnockRequestsBannerView_Previews.self,
"KnockRequestsListEmptyStateView_Previews" : KnockRequestsListEmptyStateView_Previews.self,
"KnockRequestsListScreen_Previews" : KnockRequestsListScreen_Previews.self,
"LabsScreen_Previews" : LabsScreen_Previews.self,
"LeaveSpaceView_Previews" : LeaveSpaceView_Previews.self,
"LegalInformationScreen_Previews" : LegalInformationScreen_Previews.self,
"LoadableImage_Previews" : LoadableImage_Previews.self,
@@ -0,0 +1,29 @@
//
// 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.
//
// periphery:ignore:all - this is just a labs remove this comment once generating the final file
import Combine
import SwiftUI
struct LabsScreenCoordinatorParameters {
let appSettings: AppSettings
}
final class LabsScreenCoordinator: CoordinatorProtocol {
private let viewModel: LabsScreenViewModelProtocol
init(parameters: LabsScreenCoordinatorParameters) {
viewModel = LabsScreenViewModel(labsOptions: parameters.appSettings)
}
func start() { }
func toPresentable() -> AnyView {
AnyView(LabsScreen(context: viewModel.context))
}
}
@@ -0,0 +1,37 @@
//
// 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
enum LabsScreenViewAction { }
enum LabsScreenViewModelAction { }
struct LabsScreenViewState: BindableState {
var bindings: LabsScreenViewStateBindings
}
// periphery: ignore - subscripts are seen as false positive
@dynamicMemberLookup
struct LabsScreenViewStateBindings {
private let labsOptions: LabsOptionsProtocol
init(labsOptions: LabsOptionsProtocol) {
self.labsOptions = labsOptions
}
subscript<Setting>(dynamicMember keyPath: ReferenceWritableKeyPath<LabsOptionsProtocol, Setting>) -> Setting {
get { labsOptions[keyPath: keyPath] }
set { labsOptions[keyPath: keyPath] = newValue }
}
}
protocol LabsOptionsProtocol: AnyObject {
var threadsEnabled: Bool { get set }
}
extension AppSettings: LabsOptionsProtocol { }
@@ -0,0 +1,25 @@
//
// 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 LabsScreenViewModelType = StateStoreViewModelV2<LabsScreenViewState, LabsScreenViewAction>
class LabsScreenViewModel: LabsScreenViewModelType, LabsScreenViewModelProtocol {
private let actionsSubject: PassthroughSubject<LabsScreenViewModelAction, Never> = .init()
var actionsPublisher: AnyPublisher<LabsScreenViewModelAction, Never> {
actionsSubject.eraseToAnyPublisher()
}
init(labsOptions: LabsOptionsProtocol) {
let bindings = LabsScreenViewStateBindings(labsOptions: labsOptions)
let state = LabsScreenViewState(bindings: bindings)
super.init(initialViewState: state)
}
}
@@ -0,0 +1,14 @@
//
// 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
@MainActor
protocol LabsScreenViewModelProtocol {
var actionsPublisher: AnyPublisher<LabsScreenViewModelAction, Never> { get }
var context: LabsScreenViewModelType.Context { get }
}
@@ -0,0 +1,66 @@
//
// 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 LabsScreen: View {
@Bindable var context: LabsScreenViewModel.Context
var body: some View {
Form {
header
settingsSection
}
.compoundList()
.navigationTitle(L10n.screenLabsTitle)
.navigationBarTitleDisplayMode(.inline)
}
private var header: some View {
Section {
EmptyView()
} header: {
VStack(spacing: 16) {
BigIcon(icon: \.labs, style: .default)
VStack(spacing: 8) {
Text(L10n.screenLabsHeaderTitle)
.foregroundColor(.compound.textPrimary)
.font(.compound.headingMDBold)
.multilineTextAlignment(.center)
Text(L10n.screenLabsHeaderDescription)
.font(.compound.bodyMD)
.multilineTextAlignment(.center)
.foregroundColor(.compound.textSecondary)
}
}
.frame(maxWidth: .infinity)
}
}
private var settingsSection: some View {
Section {
ListRow(label: .default(title: L10n.screenLabsEnableThreads,
icon: \.threads),
kind: .toggle($context.threadsEnabled))
}
}
}
// MARK: - Previews
struct LabsScreen_Previews: PreviewProvider, TestablePreview {
static let viewModel = LabsScreenViewModel(labsOptions: ServiceLocator.shared.settings)
static var previews: some View {
NavigationStack {
LabsScreen(context: viewModel.context)
}
}
}
@@ -41,7 +41,6 @@ protocol DeveloperOptionsProtocol: AnyObject {
var enableOnlySignedDeviceIsolationMode: Bool { get set }
var enableKeyShareOnInvite: Bool { get set }
var threadsEnabled: Bool { get set }
var spacesEnabled: Bool { get set }
var hideQuietNotificationAlerts: Bool { get set }
@@ -33,10 +33,6 @@ struct DeveloperOptionsScreen: View {
}
Section("General") {
Toggle(isOn: $context.threadsEnabled) {
Text("Threads")
}
Toggle(isOn: $context.spacesEnabled) {
Text("Spaces")
}
@@ -27,6 +27,7 @@ enum SettingsScreenCoordinatorAction {
case manageAccount(url: URL)
case notifications
case advancedSettings
case labs
case developerOptions
case deactivateAccount
}
@@ -75,6 +76,8 @@ final class SettingsScreenCoordinator: CoordinatorProtocol {
actionsSubject.send(.notifications)
case .advancedSettings:
actionsSubject.send(.advancedSettings)
case .labs:
actionsSubject.send(.labs)
case .developerOptions:
actionsSubject.send(.developerOptions)
case .logout:
@@ -20,6 +20,7 @@ enum SettingsScreenViewModelAction: Equatable {
case secureBackup
case notifications
case advancedSettings
case labs
case developerOptions
case logout
case deactivateAccount
@@ -69,6 +70,7 @@ enum SettingsScreenViewAction {
case enableDeveloperOptions
case developerOptions
case advancedSettings
case labs
case logout
case deactivateAccount
}
@@ -112,6 +112,8 @@ class SettingsScreenViewModel: SettingsScreenViewModelType, SettingsScreenViewMo
actionsSubject.send(.notifications)
case .advancedSettings:
actionsSubject.send(.advancedSettings)
case .labs:
actionsSubject.send(.labs)
case .enableDeveloperOptions:
appSettings.developerOptionsEnabled.toggle()
case .developerOptions:
@@ -137,6 +137,19 @@ struct SettingsScreen: View {
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,
icon: \.labs),
kind: .navigationLink {
context.send(viewAction: .labs)
})
ListRow(label: .default(title: L10n.commonAbout,
icon: \.info),
kind: .navigationLink {
@@ -161,13 +174,6 @@ struct SettingsScreen: View {
})
.accessibilityIdentifier(A11yIdentifiers.settingsScreen.analytics)
}
ListRow(label: .default(title: L10n.commonAdvancedSettings,
icon: \.settings),
kind: .navigationLink {
context.send(viewAction: .advancedSettings)
})
.accessibilityIdentifier(A11yIdentifiers.settingsScreen.advancedSettings)
}
}
@@ -371,6 +371,12 @@ extension PreviewTests {
}
}
func testLabsScreen() async throws {
for (index, preview) in LabsScreen_Previews._allPreviews.enumerated() {
try await assertSnapshots(matching: preview, step: index)
}
}
func testLeaveSpaceView() async throws {
for (index, preview) in LeaveSpaceView_Previews._allPreviews.enumerated() {
try await assertSnapshots(matching: preview, step: index)
@@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:f2170efb3086308662f9dca90475254c16123f856ff295c4fe9cadb308310dc6
size 109823
@@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:fe61566d43980722e18dde794154e6682dc52aae39c594c870c3da479914c412
size 122330
@@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:c9ff0be2476921e4c18a3ff885a00c8470b1d1b0005b48ac88832dc49a3f1a01
size 65214
@@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:210fdd8adf9279c35daa8992275ad436f64a96a3138687d1d6fdee38e13642e9
size 90346