mirror of
https://github.com/Novaloop-AG/element-x-ios.git
synced 2026-11-04 19:44:05 +00:00
#106: Add Analytics UI
This commit is contained in:
@@ -18,6 +18,7 @@ import SwiftUI
|
||||
|
||||
struct SettingsCoordinatorParameters {
|
||||
let navigationRouter: NavigationRouterType
|
||||
let userSession: UserSessionProtocol
|
||||
let bugReportService: BugReportServiceProtocol
|
||||
}
|
||||
|
||||
@@ -60,6 +61,8 @@ final class SettingsCoordinator: Coordinator, Presentable {
|
||||
guard let self = self else { return }
|
||||
MXLog.debug("SettingsViewModel did complete with result: \(result).")
|
||||
switch result {
|
||||
case .toggleAnalytics:
|
||||
self.toggleAnalytics()
|
||||
case .reportBug:
|
||||
self.presentBugReportScreen()
|
||||
case .crash:
|
||||
@@ -82,17 +85,12 @@ final class SettingsCoordinator: Coordinator, Presentable {
|
||||
|
||||
// MARK: - Private
|
||||
|
||||
/// Show an activity indicator whilst loading.
|
||||
/// - Parameters:
|
||||
/// - label: The label to show on the indicator.
|
||||
/// - isInteractionBlocking: Whether the indicator should block any user interaction.
|
||||
private func startLoading(label: String = ElementL10n.loading, isInteractionBlocking: Bool = true) {
|
||||
loadingIndicator = indicatorPresenter.present(.loading(label: label, isInteractionBlocking: isInteractionBlocking))
|
||||
}
|
||||
|
||||
/// Hide the currently displayed activity indicator.
|
||||
private func stopLoading() {
|
||||
loadingIndicator = nil
|
||||
private func toggleAnalytics() {
|
||||
if ElementSettings.shared.enableAnalytics {
|
||||
Analytics.shared.optOut()
|
||||
} else {
|
||||
Analytics.shared.optIn(with: parameters.userSession)
|
||||
}
|
||||
}
|
||||
|
||||
private func presentBugReportScreen() {
|
||||
@@ -114,6 +112,19 @@ final class SettingsCoordinator: Coordinator, Presentable {
|
||||
self.remove(childCoordinator: coordinator)
|
||||
}
|
||||
}
|
||||
|
||||
/// Show an activity indicator whilst loading.
|
||||
/// - Parameters:
|
||||
/// - label: The label to show on the indicator.
|
||||
/// - isInteractionBlocking: Whether the indicator should block any user interaction.
|
||||
private func startLoading(label: String = ElementL10n.loading, isInteractionBlocking: Bool = true) {
|
||||
loadingIndicator = indicatorPresenter.present(.loading(label: label, isInteractionBlocking: isInteractionBlocking))
|
||||
}
|
||||
|
||||
/// Hide the currently displayed activity indicator.
|
||||
private func stopLoading() {
|
||||
loadingIndicator = nil
|
||||
}
|
||||
|
||||
/// Show success indicator
|
||||
private func showSuccess(label: String) {
|
||||
|
||||
@@ -21,6 +21,7 @@ import Foundation
|
||||
// MARK: View model
|
||||
|
||||
enum SettingsViewModelAction {
|
||||
case toggleAnalytics
|
||||
case reportBug
|
||||
case crash
|
||||
case logout
|
||||
@@ -32,9 +33,12 @@ struct SettingsViewState: BindableState {
|
||||
var bindings: SettingsViewStateBindings
|
||||
}
|
||||
|
||||
struct SettingsViewStateBindings { }
|
||||
struct SettingsViewStateBindings {
|
||||
var enableAnalytics = ElementSettings.shared.enableAnalytics
|
||||
}
|
||||
|
||||
enum SettingsViewAction {
|
||||
case toggleAnalytics
|
||||
case reportBug
|
||||
case crash
|
||||
case logout
|
||||
|
||||
@@ -40,6 +40,8 @@ class SettingsViewModel: SettingsViewModelType, SettingsViewModelProtocol {
|
||||
|
||||
override func process(viewAction: SettingsViewAction) async {
|
||||
switch viewAction {
|
||||
case .toggleAnalytics:
|
||||
callback?(.toggleAnalytics)
|
||||
case .reportBug:
|
||||
callback?(.reportBug)
|
||||
case .crash:
|
||||
|
||||
@@ -31,43 +31,14 @@ struct SettingsScreen: View {
|
||||
|
||||
var body: some View {
|
||||
Form {
|
||||
Section {
|
||||
Button { context.send(viewAction: .reportBug) } label: {
|
||||
Text(ElementL10n.sendBugReport)
|
||||
}
|
||||
.foregroundColor(Color.element.primaryContent)
|
||||
.accessibilityIdentifier("reportBugButton")
|
||||
|
||||
if BuildSettings.settingsCrashButtonVisible {
|
||||
Button("Crash the app",
|
||||
role: .destructive) { context.send(viewAction: .crash)
|
||||
}
|
||||
|
||||
.accessibilityIdentifier("crashButton")
|
||||
}
|
||||
}
|
||||
.listRowBackground(rowBackgroundColor)
|
||||
analyticsSection
|
||||
.listRowBackground(rowBackgroundColor)
|
||||
|
||||
userInterfaceSection
|
||||
.listRowBackground(rowBackgroundColor)
|
||||
|
||||
Section {
|
||||
Button { showingLogoutConfirmation = true } label: {
|
||||
Text(ElementL10n.actionSignOut)
|
||||
}
|
||||
.frame(maxWidth: .infinity)
|
||||
.foregroundColor(Color.element.primaryContent)
|
||||
.accessibilityIdentifier("logoutButton")
|
||||
.confirmationDialog(ElementL10n.actionSignOutConfirmationSimple,
|
||||
isPresented: $showingLogoutConfirmation,
|
||||
titleVisibility: .visible) {
|
||||
Button(ElementL10n.actionSignOut,
|
||||
role: .destructive) { context.send(viewAction: .logout)
|
||||
}
|
||||
}
|
||||
} footer: {
|
||||
versionText
|
||||
}
|
||||
.listRowBackground(rowBackgroundColor)
|
||||
logoutSection
|
||||
.listRowBackground(rowBackgroundColor)
|
||||
}
|
||||
.introspectTableView { tableView in
|
||||
tableView.backgroundColor = .clear
|
||||
@@ -87,11 +58,28 @@ struct SettingsScreen: View {
|
||||
private var rowBackgroundColor: Color {
|
||||
colorScheme == .light ? .element.background : .element.system
|
||||
}
|
||||
|
||||
private var analyticsSection: some View {
|
||||
Section(ElementL10n.settingsAnalytics) {
|
||||
Button { context.send(viewAction: .reportBug) } label: {
|
||||
Text(ElementL10n.sendBugReport)
|
||||
}
|
||||
.foregroundColor(.element.primaryContent)
|
||||
.accessibilityIdentifier("reportBugButton")
|
||||
|
||||
if BuildSettings.settingsCrashButtonVisible {
|
||||
Button("Crash the app",
|
||||
role: .destructive) { context.send(viewAction: .crash)
|
||||
}
|
||||
.accessibilityIdentifier("crashButton")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ViewBuilder
|
||||
private var userInterfaceSection: some View {
|
||||
if BuildSettings.settingsShowTimelineStyle {
|
||||
Section(header: Text(ElementL10n.settingsUserInterface)) {
|
||||
Section(ElementL10n.settingsUserInterface) {
|
||||
Picker(ElementL10n.settingsTimelineStyle, selection: $settings.timelineStyle) {
|
||||
ForEach(TimelineStyle.allCases, id: \.self) { style in
|
||||
Text(style.description)
|
||||
@@ -100,7 +88,26 @@ struct SettingsScreen: View {
|
||||
}
|
||||
.accessibilityIdentifier("timelineStylePicker")
|
||||
}
|
||||
.listRowBackground(rowBackgroundColor)
|
||||
}
|
||||
}
|
||||
|
||||
private var logoutSection: some View {
|
||||
Section {
|
||||
Button { showingLogoutConfirmation = true } label: {
|
||||
Text(ElementL10n.actionSignOut)
|
||||
}
|
||||
.frame(maxWidth: .infinity)
|
||||
.foregroundColor(.element.primaryContent)
|
||||
.accessibilityIdentifier("logoutButton")
|
||||
.confirmationDialog(ElementL10n.actionSignOutConfirmationSimple,
|
||||
isPresented: $showingLogoutConfirmation,
|
||||
titleVisibility: .visible) {
|
||||
Button(ElementL10n.actionSignOut,
|
||||
role: .destructive) { context.send(viewAction: .logout)
|
||||
}
|
||||
}
|
||||
} footer: {
|
||||
versionText
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user