mirror of
https://github.com/Novaloop-AG/element-x-ios.git
synced 2026-11-03 06:02:10 +00:00
430 - Design review for first public TestFlight Part2 (#496)
* 430 - Design review for first public TestFlight Part2 --------- Co-authored-by: Doug <douglase@element.io>
This commit is contained in:
@@ -50,6 +50,8 @@ final class SettingsScreenCoordinator: CoordinatorProtocol {
|
||||
self.toggleAnalytics()
|
||||
case .reportBug:
|
||||
self.presentBugReportScreen()
|
||||
case .sessionVerification:
|
||||
self.verifySession()
|
||||
case .logout:
|
||||
self.callback?(.logout)
|
||||
}
|
||||
@@ -91,6 +93,23 @@ final class SettingsScreenCoordinator: CoordinatorProtocol {
|
||||
|
||||
parameters.navigationStackCoordinator.push(coordinator)
|
||||
}
|
||||
|
||||
private func verifySession() {
|
||||
guard let sessionVerificationController = parameters.userSession.sessionVerificationController else {
|
||||
fatalError("The sessionVerificationController should aways be valid at this point")
|
||||
}
|
||||
|
||||
let verificationParameters = SessionVerificationCoordinatorParameters(sessionVerificationControllerProxy: sessionVerificationController)
|
||||
let coordinator = SessionVerificationCoordinator(parameters: verificationParameters)
|
||||
|
||||
coordinator.callback = { [weak self] in
|
||||
self?.parameters.navigationStackCoordinator.setSheetCoordinator(nil)
|
||||
}
|
||||
|
||||
parameters.navigationStackCoordinator.setSheetCoordinator(coordinator) { [weak self] in
|
||||
self?.parameters.navigationStackCoordinator.setSheetCoordinator(nil)
|
||||
}
|
||||
}
|
||||
|
||||
private func showSuccess(label: String) {
|
||||
parameters.userNotificationController.submitNotification(UserNotification(title: label))
|
||||
|
||||
@@ -21,6 +21,7 @@ enum SettingsScreenViewModelAction {
|
||||
case close
|
||||
case toggleAnalytics
|
||||
case reportBug
|
||||
case sessionVerification
|
||||
case logout
|
||||
}
|
||||
|
||||
@@ -30,6 +31,7 @@ struct SettingsScreenViewState: BindableState {
|
||||
var userID: String
|
||||
var userAvatarURL: URL?
|
||||
var userDisplayName: String?
|
||||
var showSessionVerificationSection: Bool
|
||||
}
|
||||
|
||||
struct SettingsScreenViewStateBindings {
|
||||
@@ -40,5 +42,6 @@ enum SettingsScreenViewAction {
|
||||
case close
|
||||
case toggleAnalytics
|
||||
case reportBug
|
||||
case sessionVerification
|
||||
case logout
|
||||
}
|
||||
|
||||
@@ -26,7 +26,10 @@ class SettingsScreenViewModel: SettingsScreenViewModelType, SettingsScreenViewMo
|
||||
init(withUserSession userSession: UserSessionProtocol) {
|
||||
self.userSession = userSession
|
||||
let bindings = SettingsScreenViewStateBindings()
|
||||
super.init(initialViewState: .init(bindings: bindings, deviceID: userSession.deviceId, userID: userSession.userID),
|
||||
super.init(initialViewState: .init(bindings: bindings,
|
||||
deviceID: userSession.deviceId,
|
||||
userID: userSession.userID,
|
||||
showSessionVerificationSection: !(userSession.sessionVerificationController?.isVerified ?? false)),
|
||||
imageProvider: userSession.mediaProvider)
|
||||
|
||||
Task {
|
||||
@@ -40,6 +43,20 @@ class SettingsScreenViewModel: SettingsScreenViewModelType, SettingsScreenViewMo
|
||||
state.userDisplayName = userDisplayName
|
||||
}
|
||||
}
|
||||
|
||||
userSession.callbacks
|
||||
.receive(on: DispatchQueue.main)
|
||||
.sink { [weak self] callback in
|
||||
switch callback {
|
||||
case .sessionVerificationNeeded:
|
||||
self?.state.showSessionVerificationSection = true
|
||||
case .didVerifySession:
|
||||
self?.state.showSessionVerificationSection = false
|
||||
default:
|
||||
break
|
||||
}
|
||||
}
|
||||
.store(in: &cancellables)
|
||||
}
|
||||
|
||||
override func process(viewAction: SettingsScreenViewAction) async {
|
||||
@@ -52,6 +69,8 @@ class SettingsScreenViewModel: SettingsScreenViewModelType, SettingsScreenViewMo
|
||||
callback?(.reportBug)
|
||||
case .logout:
|
||||
callback?(.logout)
|
||||
case .sessionVerification:
|
||||
callback?(.sessionVerification)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -32,17 +32,16 @@ struct SettingsScreen: View {
|
||||
userSection
|
||||
.listRowBackground(rowBackgroundColor)
|
||||
|
||||
if context.viewState.showSessionVerificationSection {
|
||||
sessionVerificationSection
|
||||
.listRowBackground(rowBackgroundColor)
|
||||
}
|
||||
|
||||
simplifiedSection
|
||||
.listRowBackground(rowBackgroundColor)
|
||||
|
||||
// analyticsSection
|
||||
// .listRowBackground(rowBackgroundColor)
|
||||
|
||||
// userInterfaceSection
|
||||
// .listRowBackground(rowBackgroundColor)
|
||||
|
||||
// logoutSection
|
||||
// .listRowBackground(rowBackgroundColor)
|
||||
|
||||
signOutSection
|
||||
.listRowBackground(rowBackgroundColor)
|
||||
}
|
||||
.introspectTableView { tableView in
|
||||
tableView.backgroundColor = .clear
|
||||
@@ -80,10 +79,10 @@ struct SettingsScreen: View {
|
||||
|
||||
VStack(alignment: .leading, spacing: 4) {
|
||||
Text(context.viewState.userDisplayName ?? "")
|
||||
.font(.title3)
|
||||
.font(.element.title3)
|
||||
.foregroundColor(.element.primaryContent)
|
||||
Text(context.viewState.userID)
|
||||
.font(.subheadline)
|
||||
.font(.element.subheadline)
|
||||
.foregroundColor(.element.primaryContent)
|
||||
}
|
||||
}
|
||||
@@ -91,14 +90,38 @@ struct SettingsScreen: View {
|
||||
}
|
||||
}
|
||||
|
||||
private var sessionVerificationSection: some View {
|
||||
Section {
|
||||
SettingsDefaultRow(title: ElementL10n.settingsSessionVerification,
|
||||
image: Image(systemName: "checkmark.shield")) {
|
||||
context.send(viewAction: .sessionVerification)
|
||||
}
|
||||
.accessibilityIdentifier("sessionVerificationButton")
|
||||
}
|
||||
}
|
||||
|
||||
private var simplifiedSection: some View {
|
||||
Section {
|
||||
SettingsPickerRow(title: ElementL10n.settingsTimelineStyle,
|
||||
image: Image(systemName: "rectangle.grid.1x2"),
|
||||
selection: $settings.timelineStyle) {
|
||||
ForEach(TimelineStyle.allCases, id: \.self) { style in
|
||||
Text(style.description)
|
||||
.tag(style)
|
||||
}
|
||||
}
|
||||
.accessibilityIdentifier("timelineStylePicker")
|
||||
|
||||
SettingsDefaultRow(title: ElementL10n.sendBugReport,
|
||||
image: Image(systemName: "questionmark.circle")) {
|
||||
context.send(viewAction: .reportBug)
|
||||
}
|
||||
.accessibilityIdentifier("reportBugButton")
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
private var signOutSection: some View {
|
||||
Section {
|
||||
SettingsDefaultRow(title: ElementL10n.actionSignOut,
|
||||
image: Image(systemName: "rectangle.portrait.and.arrow.right")) {
|
||||
showingLogoutConfirmation = true
|
||||
@@ -112,76 +135,20 @@ struct SettingsScreen: View {
|
||||
} message: {
|
||||
Text(ElementL10n.actionSignOutConfirmationSimple)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private var analyticsSection: some View {
|
||||
Section {
|
||||
Button { context.send(viewAction: .reportBug) } label: {
|
||||
HStack {
|
||||
Text(ElementL10n.sendBugReport)
|
||||
Spacer()
|
||||
Image(systemName: "chevron.forward")
|
||||
.foregroundColor(.element.tertiaryContent)
|
||||
}
|
||||
}
|
||||
.listRowInsets(listRowInsets)
|
||||
.listRowSeparator(.hidden)
|
||||
.foregroundColor(.element.primaryContent)
|
||||
.accessibilityIdentifier("reportBugButton")
|
||||
}
|
||||
}
|
||||
|
||||
@ViewBuilder
|
||||
private var userInterfaceSection: some View {
|
||||
Section {
|
||||
Picker(ElementL10n.settingsTimelineStyle, selection: $settings.timelineStyle) {
|
||||
ForEach(TimelineStyle.allCases, id: \.self) { style in
|
||||
Text(style.description)
|
||||
.tag(style)
|
||||
}
|
||||
}
|
||||
.listRowInsets(listRowInsets)
|
||||
.accessibilityIdentifier("timelineStylePicker")
|
||||
}
|
||||
}
|
||||
|
||||
private var logoutSection: some View {
|
||||
Section {
|
||||
Button { showingLogoutConfirmation = true } label: {
|
||||
HStack {
|
||||
Image(systemName: "rectangle.portrait.and.arrow.right")
|
||||
.foregroundColor(.element.systemGray)
|
||||
.padding(4)
|
||||
.background(Color.element.systemGray6)
|
||||
.clipShape(Circle())
|
||||
.frame(width: menuIconSize, height: menuIconSize)
|
||||
Text(ElementL10n.actionSignOut)
|
||||
Spacer()
|
||||
Image(systemName: "chevron.forward")
|
||||
.foregroundColor(.element.tertiaryContent)
|
||||
}
|
||||
}
|
||||
.listRowInsets(listRowInsets)
|
||||
.foregroundColor(.element.primaryContent)
|
||||
.accessibilityIdentifier("logoutButton")
|
||||
.alert(ElementL10n.actionSignOut,
|
||||
isPresented: $showingLogoutConfirmation) {
|
||||
Button(ElementL10n.actionSignOut,
|
||||
role: .destructive,
|
||||
action: logout)
|
||||
} message: {
|
||||
Text(ElementL10n.actionSignOutConfirmationSimple)
|
||||
}
|
||||
} footer: {
|
||||
VStack {
|
||||
versionText
|
||||
.font(.element.caption1)
|
||||
.foregroundColor(.element.tertiaryContent)
|
||||
.frame(maxWidth: .infinity)
|
||||
|
||||
if let deviceId = context.viewState.deviceID {
|
||||
Text(deviceId)
|
||||
.font(.element.caption1)
|
||||
.foregroundColor(.element.tertiaryContent)
|
||||
}
|
||||
}
|
||||
.padding(.top, 24)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user