Skip to content

Commit b58d426

Browse files
committed
implemented the labs screen
1 parent b110a7b commit b58d426

20 files changed

+257
-12
lines changed

AccessibilityTests/Sources/GeneratedAccessibilityTests.swift

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -247,6 +247,10 @@ extension AccessibilityTests {
247247
try await performAccessibilityAudit(named: "KnockRequestsListScreen_Previews")
248248
}
249249

250+
func testLabsScreen() async throws {
251+
try await performAccessibilityAudit(named: "LabsScreen_Previews")
252+
}
253+
250254
func testLeaveSpaceView() async throws {
251255
try await performAccessibilityAudit(named: "LeaveSpaceView_Previews")
252256
}

ElementX.xcodeproj/project.pbxproj

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -288,6 +288,7 @@
288288
32B7891D937377A59606EDFC /* UserFlowTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 21DD8599815136EFF5B73F38 /* UserFlowTests.swift */; };
289289
32F47002A331817F0E6BD7EB /* RoomMembershipDetailsProxyProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1434D5169F0EE319E226DA7F /* RoomMembershipDetailsProxyProtocol.swift */; };
290290
339BC18777912E1989F2F17D /* Section.swift in Sources */ = {isa = PBXBuildFile; fileRef = 584A61D9C459FAFEF038A7C0 /* Section.swift */; };
291+
33BA0964A308D2286B39976D /* LabsScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = D9C5AA3EF7EC67C01C75CEDD /* LabsScreen.swift */; };
291292
33CAC1226DFB8B5D8447D286 /* GZIP in Frameworks */ = {isa = PBXBuildFile; productRef = 1BCD21310B997A6837B854D6 /* GZIP */; };
292293
33F1FB19F222BA9930AB1A00 /* RoomListFiltersView.swift in Sources */ = {isa = PBXBuildFile; fileRef = E6372DD10DED30E7AD7BCE21 /* RoomListFiltersView.swift */; };
293294
340D39DB87F3800D53A6A621 /* EmojiPickerScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = 00245D40CD90FD71D6A05239 /* EmojiPickerScreen.swift */; };
@@ -1117,6 +1118,7 @@
11171118
C8E0FA0FF2CD6613264FA6B9 /* MessageForwardingScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = BFEA446F8618DBA79A9239CC /* MessageForwardingScreen.swift */; };
11181119
C8E11A335456FCF94A744E6E /* SpaceFlowCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = EDDE826EAB1BAB80C1104980 /* SpaceFlowCoordinator.swift */; };
11191120
C8E1E4E06B7C7A3A8246FC9B /* MediaEventsTimelineScreenCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8512B82404B1751D0BCC82D2 /* MediaEventsTimelineScreenCoordinator.swift */; };
1121+
C900127318820AD04D6C90B8 /* LabsScreenModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5E43D8784B0054C048060FEB /* LabsScreenModels.swift */; };
11201122
C915347779B3C7FDD073A87A /* AVMetadataMachineReadableCodeObjectExtensionsTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 93E1FF0DFBB3768F79FDBF6D /* AVMetadataMachineReadableCodeObjectExtensionsTest.swift */; };
11211123
C969A62F3D9F14318481A33B /* KnockedRoomProxy.swift in Sources */ = {isa = PBXBuildFile; fileRef = 858DA81F2ACF484B7CAD6AE4 /* KnockedRoomProxy.swift */; };
11221124
C97325EFDCCEE457432A9E82 /* MessageText.swift in Sources */ = {isa = PBXBuildFile; fileRef = E1E0B4A34E69BD2132BEC521 /* MessageText.swift */; };
@@ -1160,10 +1162,12 @@
11601162
D104B27C5DA0626B41CE78D3 /* CurrentValuePublisher.swift in Sources */ = {isa = PBXBuildFile; fileRef = 127C8472672A5BA09EF1ACF8 /* CurrentValuePublisher.swift */; };
11611163
D10BA4F041DC58580A440A32 /* RoomRolesAndPermissionsScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = B2B1DC3B3FB40A7F4AE9B7BF /* RoomRolesAndPermissionsScreen.swift */; };
11621164
D12F440F7973F1489F61389D /* NotificationSettingsScreenModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0F64447FF544298A6A3BEF85 /* NotificationSettingsScreenModels.swift */; };
1165+
D150D6E96CA6CA09FA50E13C /* LabsScreenCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4CF17EFB2833B4CE5C06E7F8 /* LabsScreenCoordinator.swift */; };
11631166
D18B70975644C24F60656C0D /* KnockRequestProxyProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = C07851F4EA81AA3339806A7B /* KnockRequestProxyProtocol.swift */; };
11641167
D19A748E95E2FAB2940570F0 /* CallScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = E4103AB4340F2974D690A12A /* CallScreen.swift */; };
11651168
D2048FD56760BDABA3DB5FC2 /* AppLockServiceProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 26EAAB54C6CE91D64B69A9F8 /* AppLockServiceProtocol.swift */; };
11661169
D22345698F6548C1EE960940 /* IdentityConfirmedScreenModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3DBE70FFB7936F35811772C1 /* IdentityConfirmedScreenModels.swift */; };
1170+
D23BA23864EA7BA3F353C0D1 /* LabsScreenViewModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = CF847A34FC4C8C937CD39E08 /* LabsScreenViewModelProtocol.swift */; };
11671171
D2466C6BC8CAD8FADD7BF89B /* RoomPreviewProxyMock.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6695C64F066628411EAD21E9 /* RoomPreviewProxyMock.swift */; };
11681172
D26093BB80B69092B0E9AC7C /* PinnedItemsIndicatorView.swift in Sources */ = {isa = PBXBuildFile; fileRef = E66763BD54A3A1D9C6E6F2F1 /* PinnedItemsIndicatorView.swift */; };
11691173
D2825E013A8ECFB66D9A1DE6 /* RoomChangeRolesScreenViewModelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8F841F219ACDFC1D3F42FEFB /* RoomChangeRolesScreenViewModelTests.swift */; };
@@ -1288,6 +1292,7 @@
12881292
EB9F4688006B52E69DF5358F /* BlankFormCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1C7F63EB1525E697CAEB002B /* BlankFormCoordinator.swift */; };
12891293
EBE13FAB4E29738AC41BD3E5 /* InfoPlistReader.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6A580295A56B55A856CC4084 /* InfoPlistReader.swift */; };
12901294
EC09E502A21E4EAA8B367AB8 /* ReportContentScreenViewModelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 30EA681527A8FE65E4C8E9A9 /* ReportContentScreenViewModelTests.swift */; };
1295+
EC1A0E85CEE50BF0C64EEFA5 /* LabsScreenViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = A4D9DF4F2DF3507F99B5B97B /* LabsScreenViewModel.swift */; };
12911296
EC280623A42904341363EAAF /* Collections in Frameworks */ = {isa = PBXBuildFile; productRef = A20EA00CCB9DBE0FFB17DD09 /* Collections */; };
12921297
EC3320639828BED8B3E5F2C6 /* EncryptionResetScreenViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5875F7C0A2398E9F134B1284 /* EncryptionResetScreenViewModel.swift */; };
12931298
ED3E91E6166E4923791ACA84 /* ResolveVerifiedUserSendFailureScreenViewModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 56852036214ABA9D7D305768 /* ResolveVerifiedUserSendFailureScreenViewModelProtocol.swift */; };
@@ -1912,6 +1917,7 @@
19121917
4C8D988E82A8DFA13BE46F7C /* pl */ = {isa = PBXFileReference; lastKnownFileType = text.plist.stringsdict; name = pl; path = pl.lproj/Localizable.stringsdict; sourceTree = "<group>"; };
19131918
4CD6AC7546E8D7E5C73CEA48 /* ElementX.app */ = {isa = PBXFileReference; includeInIndex = 0; lastKnownFileType = wrapper.application; path = ElementX.app; sourceTree = BUILT_PRODUCTS_DIR; };
19141919
4CDDDDD9FE1A699D23A5E096 /* LoginScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LoginScreen.swift; sourceTree = "<group>"; };
1920+
4CF17EFB2833B4CE5C06E7F8 /* LabsScreenCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LabsScreenCoordinator.swift; sourceTree = "<group>"; };
19151921
4D3A7375AB22721C436EB056 /* ComposerToolbarModels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ComposerToolbarModels.swift; sourceTree = "<group>"; };
19161922
4D635709C1D6D37C225AD40E /* RoomPowerLevelProxyProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomPowerLevelProxyProtocol.swift; sourceTree = "<group>"; };
19171923
4E2245243369B99216C7D84E /* ImageCache.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ImageCache.swift; sourceTree = "<group>"; };
@@ -1991,6 +1997,7 @@
19911997
5D53754227CEBD06358956D7 /* PinnedEventsTimelineScreenCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PinnedEventsTimelineScreenCoordinator.swift; sourceTree = "<group>"; };
19921998
5DE8D25D6A91030175D52A20 /* RoomTimelineItemProperties.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomTimelineItemProperties.swift; sourceTree = "<group>"; };
19931999
5E33FD32BBC44D703C7AE4F9 /* TextBasedRoomTimelineItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TextBasedRoomTimelineItem.swift; sourceTree = "<group>"; };
2000+
5E43D8784B0054C048060FEB /* LabsScreenModels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LabsScreenModels.swift; sourceTree = "<group>"; };
19942001
5E6DE144D887A254F4CAF203 /* UserPreference.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserPreference.swift; sourceTree = "<group>"; };
19952002
5E75948AA1FE1D1A7809931F /* AuthenticationServiceProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AuthenticationServiceProtocol.swift; sourceTree = "<group>"; };
19962003
5E9CBF577B9711CFBB4FA40D /* VoiceMessageRecordingView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VoiceMessageRecordingView.swift; sourceTree = "<group>"; };
@@ -2346,6 +2353,7 @@
23462353
A433BE28B40D418237BE37B5 /* ReportContentScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ReportContentScreen.swift; sourceTree = "<group>"; };
23472354
A436057DBEA1A23CA8CB1FD7 /* UIFont+AttributedStringBuilder.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "UIFont+AttributedStringBuilder.h"; sourceTree = "<group>"; };
23482355
A443FAE2EE820A5790C35C8D /* et */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = et; path = et.lproj/Localizable.strings; sourceTree = "<group>"; };
2356+
A4D9DF4F2DF3507F99B5B97B /* LabsScreenViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LabsScreenViewModel.swift; sourceTree = "<group>"; };
23492357
A54AAF72E821B4084B7E4298 /* PinnedEventsTimelineFlowCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PinnedEventsTimelineFlowCoordinator.swift; sourceTree = "<group>"; };
23502358
A6B19D10B102956066AF117B /* PollOptionView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PollOptionView.swift; sourceTree = "<group>"; };
23512359
A6B891A6DA826E2461DBB40F /* PHGPostHogConfiguration.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PHGPostHogConfiguration.swift; sourceTree = "<group>"; };
@@ -2576,6 +2584,7 @@
25762584
CDE3F3911FF7CC639BDE5844 /* nl */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = nl; path = nl.lproj/Localizable.strings; sourceTree = "<group>"; };
25772585
CEE20623EB4A9B88FB29F2BA /* fr */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = fr; path = fr.lproj/SAS.strings; sourceTree = "<group>"; };
25782586
CEE41494C837AA403A06A5D9 /* UnitTests.xctestplan */ = {isa = PBXFileReference; path = UnitTests.xctestplan; sourceTree = "<group>"; };
2587+
CF847A34FC4C8C937CD39E08 /* LabsScreenViewModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LabsScreenViewModelProtocol.swift; sourceTree = "<group>"; };
25792588
CFFA5E881D281810AB428EA3 /* RoomPowerLevelsProxy.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomPowerLevelsProxy.swift; sourceTree = "<group>"; };
25802589
D01FD1171FF40E34D707FD00 /* BigIcon.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BigIcon.swift; sourceTree = "<group>"; };
25812590
D03D7ECAC68C2FFB8CF01BCB /* DeactivateAccountScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DeactivateAccountScreen.swift; sourceTree = "<group>"; };
@@ -2631,6 +2640,7 @@
26312640
D93C94C30E3135BC9290DE13 /* VoiceMessageRecorderTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VoiceMessageRecorderTests.swift; sourceTree = "<group>"; };
26322641
D95E8C0EFEC0C6F96EDAA71A /* PreviewTests.xctest */ = {isa = PBXFileReference; includeInIndex = 0; lastKnownFileType = wrapper.cfbundle; path = PreviewTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
26332642
D97A4E73EA97CA08D2BB9806 /* RoomScreenTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomScreenTests.swift; sourceTree = "<group>"; };
2643+
D9C5AA3EF7EC67C01C75CEDD /* LabsScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LabsScreen.swift; sourceTree = "<group>"; };
26342644
DA14564EE143F73F7E4D1F79 /* RoomNotificationSettingsScreenModels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomNotificationSettingsScreenModels.swift; sourceTree = "<group>"; };
26352645
DA3D82522494E78746B2214E /* de */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = de; path = de.lproj/SAS.strings; sourceTree = "<group>"; };
26362646
DAB8D7926A5684E18196B538 /* VoiceMessageCache.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VoiceMessageCache.swift; sourceTree = "<group>"; };
@@ -3180,6 +3190,14 @@
31803190
path = Supplementary;
31813191
sourceTree = "<group>";
31823192
};
3193+
155D9F609E878C1875A366D4 /* View */ = {
3194+
isa = PBXGroup;
3195+
children = (
3196+
D9C5AA3EF7EC67C01C75CEDD /* LabsScreen.swift */,
3197+
);
3198+
path = View;
3199+
sourceTree = "<group>";
3200+
};
31833201
15D44FCA9475E660B7F56DB9 /* Timeline */ = {
31843202
isa = PBXGroup;
31853203
children = (
@@ -4093,6 +4111,18 @@
40934111
path = UnitTests;
40944112
sourceTree = "<group>";
40954113
};
4114+
4D963F50D7AA8FE302CA8ACF /* LabsScreen */ = {
4115+
isa = PBXGroup;
4116+
children = (
4117+
4CF17EFB2833B4CE5C06E7F8 /* LabsScreenCoordinator.swift */,
4118+
5E43D8784B0054C048060FEB /* LabsScreenModels.swift */,
4119+
A4D9DF4F2DF3507F99B5B97B /* LabsScreenViewModel.swift */,
4120+
CF847A34FC4C8C937CD39E08 /* LabsScreenViewModelProtocol.swift */,
4121+
155D9F609E878C1875A366D4 /* View */,
4122+
);
4123+
path = LabsScreen;
4124+
sourceTree = "<group>";
4125+
};
40964126
4DC0344D2EBD0AE5D71754A9 /* RoomMembershipDetails */ = {
40974127
isa = PBXGroup;
40984128
children = (
@@ -6184,6 +6214,7 @@
61846214
F12966DF3DA87FEF21348D60 /* InviteUsersScreen */,
61856215
FFD7C58CA6A7D6BBC2F584B5 /* JoinRoomScreen */,
61866216
BF0415BE807CA2BCFC210008 /* KnockRequestsListScreen */,
6217+
4D963F50D7AA8FE302CA8ACF /* LabsScreen */,
61876218
948DD12A5533BE1BC260E437 /* LocationSharing */,
61886219
73E032ADD008D63812791D97 /* LogViewerScreen */,
61896220
3D76DA5827DF9396AC90E7B4 /* ManageRoomMemberSheet */,
@@ -7840,6 +7871,11 @@
78407871
454F8DDC4442C0DE54094902 /* LABiometryType.swift in Sources */,
78417872
E468CC731C3F4D678499E52F /* LAContextMock.swift in Sources */,
78427873
D5681C80D8281560AACE0035 /* Label.swift in Sources */,
7874+
33BA0964A308D2286B39976D /* LabsScreen.swift in Sources */,
7875+
D150D6E96CA6CA09FA50E13C /* LabsScreenCoordinator.swift in Sources */,
7876+
C900127318820AD04D6C90B8 /* LabsScreenModels.swift in Sources */,
7877+
EC1A0E85CEE50BF0C64EEFA5 /* LabsScreenViewModel.swift in Sources */,
7878+
D23BA23864EA7BA3F353C0D1 /* LabsScreenViewModelProtocol.swift in Sources */,
78437879
EEAE954289DE813A61656AE0 /* LayoutDirection.swift in Sources */,
78447880
EFF735EC040BEB669AFBAB50 /* LeaveSpaceHandleProxy.swift in Sources */,
78457881
DD21CE51DF9BD04FC8155972 /* LeaveSpaceHandleSDKMock.swift in Sources */,

ElementX/Sources/FlowCoordinators/SettingsFlowCoordinator.swift

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,8 @@ class SettingsFlowCoordinator: FlowCoordinatorProtocol {
102102
presentNotificationSettings()
103103
case .advancedSettings:
104104
presentAdvancedSettings()
105+
case .labs:
106+
presentLabs()
105107
case .developerOptions:
106108
presentDeveloperOptions()
107109
case .deactivateAccount:
@@ -113,6 +115,11 @@ class SettingsFlowCoordinator: FlowCoordinatorProtocol {
113115
navigationStackCoordinator.setRootCoordinator(settingsScreenCoordinator, animated: animated)
114116
}
115117

118+
private func presentLabs() {
119+
let coordinator = LabsScreenCoordinator(parameters: .init(appSettings: flowParameters.appSettings))
120+
navigationStackCoordinator.push(coordinator)
121+
}
122+
116123
private func startEncryptionSettingsFlow(animated: Bool) {
117124
let coordinator = EncryptionSettingsFlowCoordinator(parameters: .init(userSession: flowParameters.userSession,
118125
appSettings: flowParameters.appSettings,

ElementX/Sources/Other/TestablePreview/TestablePreviewsDictionary.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@ enum TestablePreviewsDictionary {
6969
"KnockRequestsBannerView_Previews" : KnockRequestsBannerView_Previews.self,
7070
"KnockRequestsListEmptyStateView_Previews" : KnockRequestsListEmptyStateView_Previews.self,
7171
"KnockRequestsListScreen_Previews" : KnockRequestsListScreen_Previews.self,
72+
"LabsScreen_Previews" : LabsScreen_Previews.self,
7273
"LeaveSpaceView_Previews" : LeaveSpaceView_Previews.self,
7374
"LegalInformationScreen_Previews" : LegalInformationScreen_Previews.self,
7475
"LoadableImage_Previews" : LoadableImage_Previews.self,
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
//
2+
// Copyright 2022-2025 New Vector Ltd.
3+
//
4+
// SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial
5+
// Please see LICENSE files in the repository root for full details.
6+
//
7+
8+
// periphery:ignore:all - this is just a labs remove this comment once generating the final file
9+
10+
import Combine
11+
import SwiftUI
12+
13+
struct LabsScreenCoordinatorParameters {
14+
let appSettings: AppSettings
15+
}
16+
17+
final class LabsScreenCoordinator: CoordinatorProtocol {
18+
private let viewModel: LabsScreenViewModelProtocol
19+
20+
init(parameters: LabsScreenCoordinatorParameters) {
21+
viewModel = LabsScreenViewModel(labsOptions: parameters.appSettings)
22+
}
23+
24+
func start() { }
25+
26+
func toPresentable() -> AnyView {
27+
AnyView(LabsScreen(context: viewModel.context))
28+
}
29+
}
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
//
2+
// Copyright 2022-2025 New Vector Ltd.
3+
//
4+
// SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial
5+
// Please see LICENSE files in the repository root for full details.
6+
//
7+
8+
import Foundation
9+
10+
enum LabsScreenViewAction { }
11+
12+
enum LabsScreenViewModelAction { }
13+
14+
struct LabsScreenViewState: BindableState {
15+
var bindings: LabsScreenViewStateBindings
16+
}
17+
18+
// periphery: ignore - subscripts are seen as false positive
19+
@dynamicMemberLookup
20+
struct LabsScreenViewStateBindings {
21+
private let labsOptions: LabsOptionsProtocol
22+
23+
init(labsOptions: LabsOptionsProtocol) {
24+
self.labsOptions = labsOptions
25+
}
26+
27+
subscript<Setting>(dynamicMember keyPath: ReferenceWritableKeyPath<LabsOptionsProtocol, Setting>) -> Setting {
28+
get { labsOptions[keyPath: keyPath] }
29+
set { labsOptions[keyPath: keyPath] = newValue }
30+
}
31+
}
32+
33+
protocol LabsOptionsProtocol: AnyObject {
34+
var threadsEnabled: Bool { get set }
35+
}
36+
37+
extension AppSettings: LabsOptionsProtocol { }
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
//
2+
// Copyright 2022-2025 New Vector Ltd.
3+
//
4+
// SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial
5+
// Please see LICENSE files in the repository root for full details.
6+
//
7+
8+
import Combine
9+
import SwiftUI
10+
11+
typealias LabsScreenViewModelType = StateStoreViewModelV2<LabsScreenViewState, LabsScreenViewAction>
12+
13+
class LabsScreenViewModel: LabsScreenViewModelType, LabsScreenViewModelProtocol {
14+
private let actionsSubject: PassthroughSubject<LabsScreenViewModelAction, Never> = .init()
15+
var actionsPublisher: AnyPublisher<LabsScreenViewModelAction, Never> {
16+
actionsSubject.eraseToAnyPublisher()
17+
}
18+
19+
init(labsOptions: LabsOptionsProtocol) {
20+
let bindings = LabsScreenViewStateBindings(labsOptions: labsOptions)
21+
let state = LabsScreenViewState(bindings: bindings)
22+
23+
super.init(initialViewState: state)
24+
}
25+
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
//
2+
// Copyright 2022-2025 New Vector Ltd.
3+
//
4+
// SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial
5+
// Please see LICENSE files in the repository root for full details.
6+
//
7+
8+
import Combine
9+
10+
@MainActor
11+
protocol LabsScreenViewModelProtocol {
12+
var actionsPublisher: AnyPublisher<LabsScreenViewModelAction, Never> { get }
13+
var context: LabsScreenViewModelType.Context { get }
14+
}

0 commit comments

Comments
 (0)