Allow showing the developer options on any build type by tapping the settings screen version footer 7 times (a la android)

This commit is contained in:
Stefan Ceriu
2024-06-11 17:17:46 +03:00
committed by Stefan Ceriu
parent f11a610f46
commit a2faae20c2
17 changed files with 28 additions and 63 deletions
@@ -666,7 +666,7 @@ class AppCoordinator: AppCoordinatorProtocol, AuthenticationFlowCoordinatorDeleg
ServiceLocator.shared.networkMonitor ServiceLocator.shared.networkMonitor
.reachabilityPublisher .reachabilityPublisher
.removeDuplicates() .removeDuplicates()
.sink { [weak self] reachability in .sink { reachability in
MXLog.info("Reachability changed to \(reachability)") MXLog.info("Reachability changed to \(reachability)")
if reachability == .reachable { if reachability == .reachable {
+4 -12
View File
@@ -43,9 +43,7 @@ final class AppSettings {
case elementCallEncryptionEnabled case elementCallEncryptionEnabled
// Feature flags // Feature flags
case shouldCollapseRoomStateEvents
case publicSearchEnabled case publicSearchEnabled
case qrCodeLoginEnabled
} }
private static var suiteName: String = InfoPlistReader.main.appGroupIdentifier private static var suiteName: String = InfoPlistReader.main.appGroupIdentifier
@@ -78,7 +76,7 @@ final class AppSettings {
// MARK: - Application // MARK: - Application
/// Whether or not the app is a development build that isn't in production. /// Whether or not the app is a development build that isn't in production.
lazy var isDevelopmentBuild: Bool = { static var isDevelopmentBuild: Bool = {
#if DEBUG #if DEBUG
true true
#else #else
@@ -240,10 +238,7 @@ final class AppSettings {
@UserPreference(key: UserDefaultsKeys.timelineStyle, defaultValue: TimelineStyle.bubbles, storageType: .userDefaults(store)) @UserPreference(key: UserDefaultsKeys.timelineStyle, defaultValue: TimelineStyle.bubbles, storageType: .userDefaults(store))
var timelineStyle var timelineStyle
@UserPreference(key: UserDefaultsKeys.shouldCollapseRoomStateEvents, defaultValue: true, storageType: .volatile) @UserPreference(key: UserDefaultsKeys.viewSourceEnabled, defaultValue: isDevelopmentBuild, storageType: .userDefaults(store))
var shouldCollapseRoomStateEvents
@UserPreference(key: UserDefaultsKeys.viewSourceEnabled, defaultValue: false, storageType: .userDefaults(store))
var viewSourceEnabled var viewSourceEnabled
// MARK: - Element Call // MARK: - Element Call
@@ -271,12 +266,9 @@ final class AppSettings {
// MARK: - Feature Flags // MARK: - Feature Flags
@UserPreference(key: UserDefaultsKeys.publicSearchEnabled, defaultValue: false, storageType: .volatile) @UserPreference(key: UserDefaultsKeys.publicSearchEnabled, defaultValue: isDevelopmentBuild, storageType: .volatile)
var publicSearchEnabled var publicSearchEnabled
@UserPreference(key: UserDefaultsKeys.qrCodeLoginEnabled, defaultValue: false, storageType: .userDefaults(store))
var qrCodeLoginEnabled
#endif #endif
// MARK: - Shared // MARK: - Shared
@@ -86,7 +86,7 @@ class AuthenticationFlowCoordinator: FlowCoordinatorProtocol {
// MARK: - Private // MARK: - Private
private func showStartScreen() { private func showStartScreen() {
let coordinator = AuthenticationStartScreenCoordinator(parameters: .init(appSettings: appSettings)) let coordinator = AuthenticationStartScreenCoordinator()
coordinator.actions coordinator.actions
.sink { [weak self] action in .sink { [weak self] action in
@@ -17,10 +17,6 @@
import Combine import Combine
import SwiftUI import SwiftUI
struct AuthenticationStartScreenCoordinatorParameters {
let appSettings: AppSettings
}
final class AuthenticationStartScreenCoordinator: CoordinatorProtocol { final class AuthenticationStartScreenCoordinator: CoordinatorProtocol {
private var viewModel: AuthenticationStartScreenViewModelProtocol private var viewModel: AuthenticationStartScreenViewModelProtocol
private let actionsSubject: PassthroughSubject<AuthenticationStartScreenCoordinatorAction, Never> = .init() private let actionsSubject: PassthroughSubject<AuthenticationStartScreenCoordinatorAction, Never> = .init()
@@ -30,8 +26,8 @@ final class AuthenticationStartScreenCoordinator: CoordinatorProtocol {
actionsSubject.eraseToAnyPublisher() actionsSubject.eraseToAnyPublisher()
} }
init(parameters: AuthenticationStartScreenCoordinatorParameters) { init() {
viewModel = AuthenticationStartScreenViewModel(appSettings: parameters.appSettings) viewModel = AuthenticationStartScreenViewModel()
} }
// MARK: - Public // MARK: - Public
@@ -26,17 +26,9 @@ class AuthenticationStartScreenViewModel: AuthenticationStartScreenViewModelType
actionsSubject.eraseToAnyPublisher() actionsSubject.eraseToAnyPublisher()
} }
init(appSettings: AppSettings) { init() {
super.init(initialViewState: AuthenticationStartScreenViewState()) super.init(initialViewState: AuthenticationStartScreenViewState())
if !ProcessInfo.processInfo.isiOSAppOnMac { state.isQRCodeLoginEnabled = !ProcessInfo.processInfo.isiOSAppOnMac && AppSettings.isDevelopmentBuild
if appSettings.isDevelopmentBuild {
state.isQRCodeLoginEnabled = true
} else {
appSettings.$qrCodeLoginEnabled
.weakAssign(to: \.state.isQRCodeLoginEnabled, on: self)
.store(in: &cancellables)
}
}
} }
override func process(viewAction: AuthenticationStartScreenViewAction) { override func process(viewAction: AuthenticationStartScreenViewAction) {
@@ -117,10 +117,7 @@ struct AuthenticationStartScreen: View {
// MARK: - Previews // MARK: - Previews
struct AuthenticationStartScreen_Previews: PreviewProvider, TestablePreview { struct AuthenticationStartScreen_Previews: PreviewProvider, TestablePreview {
static let viewModel = { static let viewModel = AuthenticationStartScreenViewModel()
ServiceLocator.shared.settings.qrCodeLoginEnabled = true
return AuthenticationStartScreenViewModel(appSettings: ServiceLocator.shared.settings)
}()
static var previews: some View { static var previews: some View {
AuthenticationStartScreen(context: viewModel.context) AuthenticationStartScreen(context: viewModel.context)
@@ -120,7 +120,7 @@ class RoomScreenInteractionHandler {
} }
var debugActions: [TimelineItemMenuAction] = [] var debugActions: [TimelineItemMenuAction] = []
if appSettings.isDevelopmentBuild || appSettings.viewSourceEnabled { if appSettings.viewSourceEnabled {
debugActions.append(.viewSource) debugActions.append(.viewSource)
} }
@@ -45,10 +45,8 @@ enum DeveloperOptionsScreenViewAction {
protocol DeveloperOptionsProtocol: AnyObject { protocol DeveloperOptionsProtocol: AnyObject {
var logLevel: TracingConfiguration.LogLevel { get set } var logLevel: TracingConfiguration.LogLevel { get set }
var shouldCollapseRoomStateEvents: Bool { get set }
var hideUnreadMessagesBadge: Bool { get set } var hideUnreadMessagesBadge: Bool { get set }
var elementCallBaseURL: URL { get set } var elementCallBaseURL: URL { get set }
var publicSearchEnabled: Bool { get set }
} }
extension AppSettings: DeveloperOptionsProtocol { } extension AppSettings: DeveloperOptionsProtocol { }
@@ -32,19 +32,7 @@ struct DeveloperOptionsScreen: View {
Text("Hide grey dots") Text("Hide grey dots")
} }
} }
Section("Room Directory Search") {
Toggle(isOn: $context.publicSearchEnabled) {
Text("Public rooms search")
}
}
Section("Room") {
Toggle(isOn: $context.shouldCollapseRoomStateEvents) {
Text("Collapse room state events")
}
}
Section("Element Call") { Section("Element Call") {
TextField(context.elementCallBaseURL.absoluteString, text: $elementCallBaseURLString) TextField(context.elementCallBaseURL.absoluteString, text: $elementCallBaseURLString)
.submitLabel(.done) .submitLabel(.done)
@@ -64,6 +64,7 @@ enum SettingsScreenViewAction {
case secureBackup case secureBackup
case manageAccount(url: URL) case manageAccount(url: URL)
case notifications case notifications
case enableDeveloperOptions
case developerOptions case developerOptions
case advancedSettings case advancedSettings
case logout case logout
@@ -29,7 +29,7 @@ class SettingsScreenViewModel: SettingsScreenViewModelType, SettingsScreenViewMo
init(userSession: UserSessionProtocol, appSettings: AppSettings) { init(userSession: UserSessionProtocol, appSettings: AppSettings) {
super.init(initialViewState: .init(deviceID: userSession.clientProxy.deviceID, super.init(initialViewState: .init(deviceID: userSession.clientProxy.deviceID,
userID: userSession.clientProxy.userID, userID: userSession.clientProxy.userID,
showDeveloperOptions: appSettings.isDevelopmentBuild), showDeveloperOptions: AppSettings.isDevelopmentBuild),
imageProvider: userSession.mediaProvider) imageProvider: userSession.mediaProvider)
userSession.clientProxy.userAvatarURLPublisher userSession.clientProxy.userAvatarURLPublisher
@@ -110,6 +110,8 @@ class SettingsScreenViewModel: SettingsScreenViewModelType, SettingsScreenViewMo
actionsSubject.send(.notifications) actionsSubject.send(.notifications)
case .advancedSettings: case .advancedSettings:
actionsSubject.send(.advancedSettings) actionsSubject.send(.advancedSettings)
case .enableDeveloperOptions:
state.showDeveloperOptions = true
case .developerOptions: case .developerOptions:
actionsSubject.send(.developerOptions) actionsSubject.send(.developerOptions)
} }
@@ -196,6 +196,9 @@ struct SettingsScreen: View {
.compoundListSectionFooter() .compoundListSectionFooter()
.textSelection(.enabled) .textSelection(.enabled)
.padding(.top, 24) .padding(.top, 24)
.onTapGesture(count: 7) {
context.send(viewAction: .enableDeveloperOptions)
}
} }
} }
@@ -363,10 +363,6 @@ class RoomTimelineController: RoomTimelineControllerProtocol {
} }
private func isItemCollapsible(_ item: TimelineItemProxy) -> Bool { private func isItemCollapsible(_ item: TimelineItemProxy) -> Bool {
if !appSettings.shouldCollapseRoomStateEvents {
return false
}
if case let .event(eventItem) = item { if case let .event(eventItem) = item {
switch eventItem.content.kind() { switch eventItem.content.kind() {
case .profileChange, .roomMembership, .state: case .profileChange, .roomMembership, .state:
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1 version https://git-lfs.github.com/spec/v1
oid sha256:8cd0132d6e6b1accd323b35c4f76194715ec5672e8ebadba2cea0d8b9328acd4 oid sha256:f85f8897cd79b5d4d2df216679ffcdc45da409e9fc1bce42cbb434512e7d5053
size 156339 size 156848
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1 version https://git-lfs.github.com/spec/v1
oid sha256:b952da8ab3650bd6c62f5fcb2f58f5abbc43abb59a194a67bb5e5b45c6d358c0 oid sha256:af072c34f22fa7757d3a7f48e318c20f78bfc0b6dda2ca976edea2985d8e4706
size 217756 size 218093
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1 version https://git-lfs.github.com/spec/v1
oid sha256:2cf3303ef793b9062a0971a0af37cc4fb76ac950d2ef5025330cef2e59e619db oid sha256:4c88a64b71907671ad6ba30275a58efb4c8131533d983c4ad3c341dd1d6d9a74
size 104184 size 104849
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1 version https://git-lfs.github.com/spec/v1
oid sha256:c1a257c5c1b5a762cd8454637d6fa378980b930fbeed3ec12c8ccb8cce99f2b9 oid sha256:dcdf67bedffc6d677cbb292986dfe3270ce04afeb51611fc62bc1d8d77b1c936
size 165685 size 166288