mirror of
https://github.com/Novaloop-AG/element-x-ios.git
synced 2026-11-04 19:44:05 +00:00
feat(healthchat): advertise the account status in settings
Pending approval and an incomplete profile were only visible in the members tab, which a new user has no reason to open.
This commit is contained in:
@@ -11,6 +11,8 @@ import SwiftUI
|
||||
|
||||
struct SettingsScreenCoordinatorParameters {
|
||||
let userSession: UserSessionProtocol
|
||||
let appSettings: AppSettings
|
||||
let appHooks: AppHooks
|
||||
let isBugReportServiceEnabled: Bool
|
||||
let isInSecondaryWindow: Bool
|
||||
let userIndicatorController: UserIndicatorControllerProtocol
|
||||
@@ -18,30 +20,22 @@ struct SettingsScreenCoordinatorParameters {
|
||||
|
||||
enum SettingsScreenCoordinatorAction {
|
||||
case dismiss
|
||||
|
||||
case logout
|
||||
case secureBackup
|
||||
case userDetails
|
||||
case userStatusEmojiPicker(EmojiPickerScreenContinuation)
|
||||
|
||||
case addAccount
|
||||
|
||||
case manageAccount(url: URL)
|
||||
case linkNewDevice
|
||||
case notifications
|
||||
case secureBackup
|
||||
case moderationAndSafety
|
||||
case bugReport
|
||||
|
||||
case logout
|
||||
case deactivateAccount
|
||||
|
||||
case mediaUploadQuality
|
||||
case appLock
|
||||
case locationSharing
|
||||
case analytics
|
||||
case labs
|
||||
case appLock
|
||||
case bugReport
|
||||
case about
|
||||
|
||||
case blockedUsers
|
||||
case linkNewDevice
|
||||
case manageAccount(url: URL)
|
||||
case notifications
|
||||
case advancedSettings
|
||||
case labs
|
||||
case developerOptions
|
||||
case deactivateAccount
|
||||
}
|
||||
|
||||
final class SettingsScreenCoordinator: CoordinatorProtocol {
|
||||
@@ -58,6 +52,8 @@ final class SettingsScreenCoordinator: CoordinatorProtocol {
|
||||
|
||||
init(parameters: SettingsScreenCoordinatorParameters) {
|
||||
viewModel = SettingsScreenViewModel(userSession: parameters.userSession,
|
||||
appSettings: parameters.appSettings,
|
||||
appHooks: parameters.appHooks,
|
||||
isBugReportServiceEnabled: parameters.isBugReportServiceEnabled,
|
||||
isInSecondaryWindow: parameters.isInSecondaryWindow,
|
||||
userIndicatorController: parameters.userIndicatorController)
|
||||
@@ -69,48 +65,38 @@ final class SettingsScreenCoordinator: CoordinatorProtocol {
|
||||
switch action {
|
||||
case .close:
|
||||
actionsSubject.send(.dismiss)
|
||||
|
||||
case .userDetails:
|
||||
actionsSubject.send(.userDetails)
|
||||
case let .userStatusEmojiPicker(continuation):
|
||||
actionsSubject.send(.userStatusEmojiPicker(continuation))
|
||||
|
||||
case .addAccount:
|
||||
actionsSubject.send(.addAccount)
|
||||
|
||||
case let .manageAccount(url):
|
||||
actionsSubject.send(.manageAccount(url: url))
|
||||
case .linkNewDevice:
|
||||
actionsSubject.send(.linkNewDevice)
|
||||
case .notifications:
|
||||
actionsSubject.send(.notifications)
|
||||
case .secureBackup:
|
||||
actionsSubject.send(.secureBackup)
|
||||
case .moderationAndSafety:
|
||||
actionsSubject.send(.moderationAndSafety)
|
||||
case let .manageAccount(url):
|
||||
actionsSubject.send(.manageAccount(url: url))
|
||||
case .analytics:
|
||||
actionsSubject.send(.analytics)
|
||||
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:
|
||||
actionsSubject.send(.notifications)
|
||||
case .advancedSettings:
|
||||
actionsSubject.send(.advancedSettings)
|
||||
case .labs:
|
||||
actionsSubject.send(.labs)
|
||||
case .developerOptions:
|
||||
actionsSubject.send(.developerOptions)
|
||||
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:
|
||||
actionsSubject.send(.labs)
|
||||
case .about:
|
||||
actionsSubject.send(.about)
|
||||
|
||||
case .developerOptions:
|
||||
actionsSubject.send(.developerOptions)
|
||||
}
|
||||
}
|
||||
.store(in: &cancellables)
|
||||
|
||||
@@ -10,30 +10,22 @@ import SwiftUI
|
||||
|
||||
enum SettingsScreenViewModelAction {
|
||||
case close
|
||||
|
||||
case userDetails
|
||||
case userStatusEmojiPicker(EmojiPickerScreenContinuation)
|
||||
|
||||
case addAccount
|
||||
|
||||
case manageAccount(url: URL)
|
||||
case linkNewDevice
|
||||
case notifications
|
||||
case secureBackup
|
||||
case moderationAndSafety
|
||||
case manageAccount(url: URL)
|
||||
case analytics
|
||||
case appLock
|
||||
case reportBug
|
||||
|
||||
case about
|
||||
case blockedUsers
|
||||
case secureBackup
|
||||
case notifications
|
||||
case advancedSettings
|
||||
case labs
|
||||
case developerOptions
|
||||
case logout
|
||||
case deactivateAccount
|
||||
|
||||
case mediaUploadQuality
|
||||
case appLock
|
||||
case locationSharing
|
||||
case analytics
|
||||
case labs
|
||||
case about
|
||||
|
||||
case developerOptions
|
||||
}
|
||||
|
||||
enum SettingsScreenSecuritySectionMode {
|
||||
@@ -46,7 +38,6 @@ struct SettingsScreenViewState: BindableState {
|
||||
var userProfile: UserProfile
|
||||
var showUserStatusInput = false
|
||||
var showLinkNewDeviceButton: Bool
|
||||
var showAddAccountButton: Bool
|
||||
var accountProfileURL: URL?
|
||||
var showAccountDeactivation: Bool
|
||||
var showDeveloperOptions: Bool
|
||||
@@ -54,13 +45,16 @@ struct SettingsScreenViewState: BindableState {
|
||||
var securitySectionMode = SettingsScreenSecuritySectionMode.none
|
||||
var showSecuritySectionBadge = false
|
||||
|
||||
var showBlockedUsers = false
|
||||
let showAnalyticsSettings: Bool
|
||||
|
||||
let isBugReportServiceEnabled: Bool
|
||||
|
||||
let navigationBarVisibility: Visibility
|
||||
|
||||
var bindings: SettingsScreenViewStateBindings
|
||||
let appHooks: AppHooks
|
||||
|
||||
var bindings = SettingsScreenViewStateBindings()
|
||||
|
||||
var userStatusRowMode: SettingsScreenUserStatusRow.Mode {
|
||||
if bindings.isShowingCustomStatusField {
|
||||
@@ -74,8 +68,6 @@ struct SettingsScreenViewState: BindableState {
|
||||
}
|
||||
|
||||
struct SettingsScreenViewStateBindings {
|
||||
private let userSettings: UserSettings
|
||||
|
||||
var isPresentingStatusPicker = false
|
||||
var customStatusEmoji: Character = "😄"
|
||||
var isShowingCustomStatusField = false {
|
||||
@@ -87,44 +79,27 @@ struct SettingsScreenViewStateBindings {
|
||||
}
|
||||
|
||||
var isPresentingAccountDeactivationConfirmation = false
|
||||
|
||||
var appAppearance: AppAppearance {
|
||||
get { userSettings.app.appAppearance }
|
||||
set { userSettings.app.appAppearance = newValue }
|
||||
}
|
||||
|
||||
init(userSettings: UserSettings) {
|
||||
self.userSettings = userSettings
|
||||
}
|
||||
}
|
||||
|
||||
enum SettingsScreenViewAction {
|
||||
case close
|
||||
|
||||
case userDetails
|
||||
case userStatus(UserStatusAction)
|
||||
|
||||
case addAccount
|
||||
|
||||
case manageAccount(url: URL)
|
||||
case linkNewDevice
|
||||
case notifications
|
||||
case secureBackup
|
||||
case moderationAndSafety
|
||||
case reportBug
|
||||
|
||||
case logout
|
||||
case deactivateAccount
|
||||
|
||||
case mediaUploadQuality
|
||||
case appLock
|
||||
case locationSharing
|
||||
case analytics
|
||||
case labs
|
||||
case appLock
|
||||
case reportBug
|
||||
case about
|
||||
|
||||
case blockedUsers
|
||||
case secureBackup
|
||||
case linkNewDevice
|
||||
case manageAccount(url: URL)
|
||||
case notifications
|
||||
case enableDeveloperOptions
|
||||
case developerOptions
|
||||
case advancedSettings
|
||||
case labs
|
||||
case logout
|
||||
case deactivateAccount
|
||||
|
||||
enum UserStatusAction {
|
||||
/// Show status picker sheet to select a preset status.
|
||||
|
||||
@@ -12,7 +12,7 @@ import SwiftUI
|
||||
typealias SettingsScreenViewModelType = StateStoreViewModelV2<SettingsScreenViewState, SettingsScreenViewAction>
|
||||
|
||||
class SettingsScreenViewModel: SettingsScreenViewModelType, SettingsScreenViewModelProtocol {
|
||||
private let userSettings: UserSettings
|
||||
private let appSettings: AppSettings
|
||||
private let clientProxy: ClientProxyProtocol
|
||||
private let userIndicatorController: UserIndicatorControllerProtocol
|
||||
|
||||
@@ -22,35 +22,30 @@ class SettingsScreenViewModel: SettingsScreenViewModelType, SettingsScreenViewMo
|
||||
actionsSubject.eraseToAnyPublisher()
|
||||
}
|
||||
|
||||
init(userSession: UserSessionProtocol, isBugReportServiceEnabled: Bool, isInSecondaryWindow: Bool, userIndicatorController: UserIndicatorControllerProtocol) {
|
||||
userSettings = userSession.userSettings
|
||||
init(userSession: UserSessionProtocol, appSettings: AppSettings, appHooks: AppHooks, isBugReportServiceEnabled: Bool, isInSecondaryWindow: Bool, userIndicatorController: UserIndicatorControllerProtocol) {
|
||||
self.appSettings = appSettings
|
||||
clientProxy = userSession.clientProxy
|
||||
self.userIndicatorController = userIndicatorController
|
||||
|
||||
super.init(initialViewState: .init(deviceID: userSession.clientProxy.deviceID,
|
||||
userProfile: userSession.clientProxy.userProfilePublisher.value,
|
||||
showLinkNewDeviceButton: userSettings.app.linkNewDeviceEnabled,
|
||||
showAddAccountButton: userSettings.app.multiAccountEnabled,
|
||||
showLinkNewDeviceButton: appSettings.linkNewDeviceEnabled,
|
||||
showAccountDeactivation: userSession.clientProxy.canDeactivateAccount,
|
||||
showDeveloperOptions: userSettings.app.developerOptionsEnabled,
|
||||
showAnalyticsSettings: userSettings.app.canPromptForAnalytics,
|
||||
showDeveloperOptions: appSettings.developerOptionsEnabled,
|
||||
showAnalyticsSettings: appSettings.canPromptForAnalytics,
|
||||
isBugReportServiceEnabled: isBugReportServiceEnabled,
|
||||
navigationBarVisibility: isInSecondaryWindow ? .hidden : .automatic,
|
||||
bindings: .init(userSettings: userSettings)),
|
||||
appHooks: appHooks),
|
||||
mediaProvider: userSession.mediaProvider)
|
||||
|
||||
userSettings.app.developerOptionsEnabledPublisher
|
||||
appSettings.developerOptionsEnabledPublisher
|
||||
.weakAssign(to: \.state.showDeveloperOptions, on: self)
|
||||
.store(in: &cancellables)
|
||||
|
||||
userSettings.app.linkNewDeviceEnabledPublisher
|
||||
appSettings.linkNewDeviceEnabledPublisher
|
||||
.weakAssign(to: \.state.showLinkNewDeviceButton, on: self)
|
||||
.store(in: &cancellables)
|
||||
|
||||
userSettings.app.multiAccountEnabledPublisher
|
||||
.weakAssign(to: \.state.showAddAccountButton, on: self)
|
||||
.store(in: &cancellables)
|
||||
|
||||
userSession.clientProxy.userProfilePublisher
|
||||
.receive(on: DispatchQueue.main)
|
||||
.weakAssign(to: \.state.userProfile, on: self)
|
||||
@@ -78,6 +73,18 @@ class SettingsScreenViewModel: SettingsScreenViewModelType, SettingsScreenViewMo
|
||||
}
|
||||
.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 {
|
||||
if case .success(true) = await userSession.clientProxy.isUserStatusSupported() {
|
||||
state.showUserStatusInput = true
|
||||
@@ -91,7 +98,6 @@ class SettingsScreenViewModel: SettingsScreenViewModelType, SettingsScreenViewMo
|
||||
switch viewAction {
|
||||
case .close:
|
||||
actionsSubject.send(.close)
|
||||
|
||||
case .userDetails:
|
||||
actionsSubject.send(.userDetails)
|
||||
case .userStatus(.pickStatus):
|
||||
@@ -108,45 +114,36 @@ class SettingsScreenViewModel: SettingsScreenViewModelType, SettingsScreenViewMo
|
||||
case .userStatus(.cancel):
|
||||
state.bindings.isPresentingStatusPicker = false
|
||||
state.bindings.isShowingCustomStatusField = false
|
||||
|
||||
case .addAccount:
|
||||
actionsSubject.send(.addAccount)
|
||||
|
||||
case let .manageAccount(url):
|
||||
actionsSubject.send(.manageAccount(url: url))
|
||||
case .linkNewDevice:
|
||||
actionsSubject.send(.linkNewDevice)
|
||||
case .notifications:
|
||||
actionsSubject.send(.notifications)
|
||||
case .secureBackup:
|
||||
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 let .manageAccount(url):
|
||||
actionsSubject.send(.manageAccount(url: url))
|
||||
case .analytics:
|
||||
actionsSubject.send(.analytics)
|
||||
case .labs:
|
||||
actionsSubject.send(.labs)
|
||||
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:
|
||||
actionsSubject.send(.notifications)
|
||||
case .advancedSettings:
|
||||
actionsSubject.send(.advancedSettings)
|
||||
case .labs:
|
||||
actionsSubject.send(.labs)
|
||||
case .enableDeveloperOptions:
|
||||
userSettings.app.developerOptionsEnabled.toggle()
|
||||
appSettings.developerOptionsEnabled.toggle()
|
||||
case .developerOptions:
|
||||
actionsSubject.send(.developerOptions)
|
||||
case .deactivateAccount:
|
||||
actionsSubject.send(.deactivateAccount)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -13,19 +13,37 @@ import SwiftUI
|
||||
struct SettingsScreen: View {
|
||||
@Bindable var context: SettingsScreenViewModel.Context
|
||||
|
||||
private var shouldHideManageAccountSection: Bool {
|
||||
context.viewState.accountProfileURL == nil &&
|
||||
!context.viewState.showBlockedUsers &&
|
||||
!context.viewState.showLinkNewDeviceButton
|
||||
}
|
||||
|
||||
var body: some View {
|
||||
Form {
|
||||
userSection
|
||||
|
||||
if context.viewState.showAddAccountButton {
|
||||
addAccountSection
|
||||
if context.viewState.showUserStatusInput {
|
||||
userStatusSection
|
||||
}
|
||||
|
||||
accountSettingsSection
|
||||
context.viewState.appHooks.settingsScreenHook.accountStatusSection {
|
||||
context.send(viewAction: .userDetails)
|
||||
}
|
||||
|
||||
if !shouldHideManageAccountSection {
|
||||
manageAccountSection
|
||||
}
|
||||
|
||||
manageMyAppSection
|
||||
|
||||
generalSection
|
||||
|
||||
signOutSection
|
||||
|
||||
appSettingsSection
|
||||
if context.viewState.showDeveloperOptions {
|
||||
developerOptionsSection
|
||||
}
|
||||
}
|
||||
.compoundList()
|
||||
.navigationTitle(L10n.commonSettings)
|
||||
@@ -56,9 +74,15 @@ struct SettingsScreen: View {
|
||||
.accessibilityHidden(true)
|
||||
|
||||
VStack(alignment: .leading, spacing: 2) {
|
||||
Text(context.viewState.userProfile.displayName ?? "")
|
||||
.font(.compound.headingMD)
|
||||
.foregroundColor(.compound.textPrimary)
|
||||
HStack(spacing: 6) {
|
||||
Text(context.viewState.userProfile.displayName ?? "")
|
||||
|
||||
if let statusEmoji = context.viewState.userProfile.status.displayed?.emoji {
|
||||
Text(String(statusEmoji))
|
||||
}
|
||||
}
|
||||
.font(.compound.headingMD)
|
||||
.foregroundColor(.compound.textPrimary)
|
||||
|
||||
Text(context.viewState.userProfile.id)
|
||||
.font(.compound.bodySM)
|
||||
@@ -73,27 +97,47 @@ struct SettingsScreen: View {
|
||||
.padding(.vertical, 8)
|
||||
}
|
||||
})
|
||||
|
||||
if context.viewState.showUserStatusInput {
|
||||
SettingsScreenUserStatusRow(mode: context.viewState.userStatusRowMode) { action in
|
||||
context.send(viewAction: .userStatus(action))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private var userStatusSection: some View {
|
||||
Section {
|
||||
SettingsScreenUserStatusRow(mode: context.viewState.userStatusRowMode) { action in
|
||||
context.send(viewAction: .userStatus(action))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private var addAccountSection: some View {
|
||||
private var manageMyAppSection: some View {
|
||||
Section {
|
||||
ListRow(label: .default(title: L10n.screenSettingsAddAccount,
|
||||
icon: \.plus),
|
||||
ListRow(label: .default(title: L10n.screenNotificationSettingsTitle,
|
||||
icon: \.notifications),
|
||||
kind: .navigationLink {
|
||||
context.send(viewAction: .addAccount)
|
||||
context.send(viewAction: .notifications)
|
||||
})
|
||||
.accessibilityIdentifier(A11yIdentifiers.settingsScreen.addAccount)
|
||||
.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 accountSettingsSection: some View {
|
||||
private var manageAccountSection: some View {
|
||||
Section {
|
||||
if let url = context.viewState.accountProfileURL {
|
||||
ListRow(label: .default(title: L10n.actionManageAccountAndDevices,
|
||||
@@ -112,29 +156,38 @@ struct SettingsScreen: View {
|
||||
})
|
||||
}
|
||||
|
||||
ListRow(label: .default(title: L10n.screenNotificationSettingsTitle,
|
||||
icon: \.notifications),
|
||||
kind: .navigationLink {
|
||||
context.send(viewAction: .notifications)
|
||||
})
|
||||
.accessibilityIdentifier(A11yIdentifiers.settingsScreen.notifications)
|
||||
|
||||
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()
|
||||
if context.viewState.showBlockedUsers {
|
||||
ListRow(label: .default(title: L10n.commonBlockedUsers,
|
||||
icon: \.block),
|
||||
kind: .navigationLink {
|
||||
context.send(viewAction: .blockedUsers)
|
||||
})
|
||||
.accessibilityIdentifier(A11yIdentifiers.settingsScreen.blockedUsers)
|
||||
}
|
||||
|
||||
ListRow(label: .default(title: L10n.commonModerationAndSafety,
|
||||
icon: \.admin),
|
||||
}
|
||||
}
|
||||
|
||||
private var generalSection: some View {
|
||||
Section {
|
||||
ListRow(label: .default(title: L10n.commonAdvancedSettings,
|
||||
icon: \.settings),
|
||||
kind: .navigationLink {
|
||||
context.send(viewAction: .moderationAndSafety)
|
||||
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 {
|
||||
context.send(viewAction: .about)
|
||||
})
|
||||
.accessibilityIdentifier(A11yIdentifiers.settingsScreen.about)
|
||||
|
||||
if context.viewState.isBugReportServiceEnabled {
|
||||
ListRow(label: .default(title: L10n.commonReportAProblem,
|
||||
@@ -144,9 +197,15 @@ struct SettingsScreen: View {
|
||||
})
|
||||
.accessibilityIdentifier(A11yIdentifiers.settingsScreen.reportBug)
|
||||
}
|
||||
} header: {
|
||||
Text(L10n.commonAccountSettings)
|
||||
.compoundListSectionHeader()
|
||||
|
||||
if context.viewState.showAnalyticsSettings {
|
||||
ListRow(label: .default(title: L10n.commonAnalytics,
|
||||
icon: \.chart),
|
||||
kind: .navigationLink {
|
||||
context.send(viewAction: .analytics)
|
||||
})
|
||||
.accessibilityIdentifier(A11yIdentifiers.settingsScreen.analytics)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -168,68 +227,21 @@ struct SettingsScreen: View {
|
||||
context.send(viewAction: .deactivateAccount)
|
||||
})
|
||||
}
|
||||
} footer: {
|
||||
if !context.viewState.showDeveloperOptions {
|
||||
versionSection
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private var appSettingsSection: some View {
|
||||
private var developerOptionsSection: some View {
|
||||
Section {
|
||||
ListRow(label: .default(title: L10n.commonAppearance,
|
||||
icon: \.darkMode),
|
||||
kind: .picker(selection: $context.appAppearance,
|
||||
items: AppAppearance.allCases.map { (title: $0.name, tag: $0) }))
|
||||
|
||||
ListRow(label: .default(title: L10n.commonMediaUploadQuality,
|
||||
icon: \.image),
|
||||
ListRow(label: .default(title: L10n.commonDeveloperOptions,
|
||||
icon: \.code),
|
||||
kind: .navigationLink {
|
||||
context.send(viewAction: .mediaUploadQuality)
|
||||
context.send(viewAction: .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()
|
||||
.accessibilityIdentifier(A11yIdentifiers.settingsScreen.developerOptions)
|
||||
} footer: {
|
||||
versionSection
|
||||
}
|
||||
@@ -274,19 +286,6 @@ 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
|
||||
|
||||
@available(iOS 26.0, *)
|
||||
@@ -299,7 +298,7 @@ struct SettingsScreen_Previews: PreviewProvider, TestablePreview {
|
||||
SettingsScreen(context: viewModel.context)
|
||||
}
|
||||
.snapshotPreferences(expect: viewModel.context.observe(\.viewState.accountProfileURL).map { $0 != nil })
|
||||
.frame(height: 1300)
|
||||
.frame(height: 1100)
|
||||
.previewLayout(.sizeThatFits)
|
||||
.previewDisplayName("Default")
|
||||
|
||||
@@ -307,21 +306,19 @@ struct SettingsScreen_Previews: PreviewProvider, TestablePreview {
|
||||
SettingsScreen(context: bugReportDisabledViewModel.context)
|
||||
}
|
||||
.snapshotPreferences(expect: bugReportDisabledViewModel.context.observe(\.viewState.accountProfileURL).map { $0 != nil })
|
||||
.frame(height: 1250)
|
||||
.frame(height: 1050)
|
||||
.previewLayout(.sizeThatFits)
|
||||
.previewDisplayName("Bug report disabled")
|
||||
}
|
||||
|
||||
static func makeViewModel(isBugReportServiceEnabled: Bool = true) -> SettingsScreenViewModel {
|
||||
let userSettings = UserSettings.mock()
|
||||
userSettings.app.multiAccountEnabled = true
|
||||
userSettings.app.linkNewDeviceEnabled = true
|
||||
let userSession = UserSessionMock(.init(clientProxy: ClientProxyMock(.init(userID: "@alice:example.com",
|
||||
deviceID: "AAAAAAAAAAA",
|
||||
displayName: "Alice Liddell",
|
||||
status: .mockFocussing)),
|
||||
userSettings: userSettings))
|
||||
status: .mockFocussing))))
|
||||
return SettingsScreenViewModel(userSession: userSession,
|
||||
appSettings: .volatile(),
|
||||
appHooks: AppHooks(),
|
||||
isBugReportServiceEnabled: isBugReportServiceEnabled,
|
||||
isInSecondaryWindow: false,
|
||||
userIndicatorController: UserIndicatorControllerMock())
|
||||
|
||||
Reference in New Issue
Block a user