Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Separate Manage account from Manage devices. #1698

Merged
merged 1 commit into from
Sep 13, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion ElementX.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -5613,7 +5613,7 @@
repositoryURL = "https://github.com/matrix-org/matrix-rust-components-swift";
requirement = {
kind = exactVersion;
version = 1.1.12;
version = 1.1.13;
};
};
821C67C9A7F8CC3FD41B28B4 /* XCRemoteSwiftPackageReference "emojibase-bindings" */ = {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -129,8 +129,8 @@
"kind" : "remoteSourceControl",
"location" : "https://github.com/matrix-org/matrix-rust-components-swift",
"state" : {
"revision" : "8c2307180e468fc40ab72e6a5e8b31a4fbbea4d5",
"version" : "1.1.12"
"revision" : "482c8c04019e6e6ac9638ae792adae9d67b08114",
"version" : "1.1.13"
}
},
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@
"action_learn_more" = "Learn more";
"action_leave" = "Leave";
"action_leave_room" = "Leave room";
"action_manage_account" = "Manage account";
"action_manage_devices" = "Manage devices";
"action_next" = "Next";
"action_no" = "No";
"action_not_now" = "Not now";
Expand Down
4 changes: 4 additions & 0 deletions ElementX/Sources/Generated/Strings.swift
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,10 @@ public enum L10n {
public static var actionLeave: String { return L10n.tr("Localizable", "action_leave") }
/// Leave room
public static var actionLeaveRoom: String { return L10n.tr("Localizable", "action_leave_room") }
/// Manage account
public static var actionManageAccount: String { return L10n.tr("Localizable", "action_manage_account") }
/// Manage devices
public static var actionManageDevices: String { return L10n.tr("Localizable", "action_manage_devices") }
/// Next
public static var actionNext: String { return L10n.tr("Localizable", "action_next") }
/// No
Expand Down
32 changes: 20 additions & 12 deletions ElementX/Sources/Mocks/Generated/SDKGeneratedMocks.swift
Original file line number Diff line number Diff line change
Expand Up @@ -33,19 +33,27 @@ class SDKClientMock: SDKClientProtocol {
}
//MARK: - accountUrl

public var accountUrlCallsCount = 0
public var accountUrlCalled: Bool {
return accountUrlCallsCount > 0
}
public var accountUrlReturnValue: String?
public var accountUrlClosure: (() -> String?)?

public func accountUrl() -> String? {
accountUrlCallsCount += 1
if let accountUrlClosure = accountUrlClosure {
return accountUrlClosure()
public var accountUrlActionThrowableError: Error?
public var accountUrlActionCallsCount = 0
public var accountUrlActionCalled: Bool {
return accountUrlActionCallsCount > 0
}
public var accountUrlActionReceivedAction: AccountManagementAction?
public var accountUrlActionReceivedInvocations: [AccountManagementAction?] = []
public var accountUrlActionReturnValue: String?
public var accountUrlActionClosure: ((AccountManagementAction?) throws -> String?)?

public func accountUrl(action: AccountManagementAction?) throws -> String? {
if let error = accountUrlActionThrowableError {
throw error
}
accountUrlActionCallsCount += 1
accountUrlActionReceivedAction = action
accountUrlActionReceivedInvocations.append(action)
if let accountUrlActionClosure = accountUrlActionClosure {
return try accountUrlActionClosure(action)
} else {
return accountUrlReturnValue
return accountUrlActionReturnValue
}
}
//MARK: - avatarUrl
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,23 +48,25 @@ final class SettingsScreenCoordinator: CoordinatorProtocol {

switch action {
case .close:
self.callback?(.dismiss)
case .account:
self.presentAccountSettings()
callback?(.dismiss)
case .accountProfile:
presentAccountProfileURL()
case .analytics:
self.presentAnalyticsScreen()
presentAnalyticsScreen()
case .reportBug:
self.presentBugReportScreen()
presentBugReportScreen()
case .about:
self.presentLegalInformationScreen()
presentLegalInformationScreen()
case .sessionVerification:
self.verifySession()
verifySession()
case .accountSessionsList:
presentAccountSessionsListURL()
case .developerOptions:
self.presentDeveloperOptions()
presentDeveloperOptions()
case .logout:
self.callback?(.logout)
callback?(.logout)
case .notifications:
self.presentNotificationSettings()
presentNotificationSettings()
}
}
}
Expand All @@ -75,26 +77,39 @@ final class SettingsScreenCoordinator: CoordinatorProtocol {
AnyView(SettingsScreen(context: viewModel.context))
}

// MARK: - Private
// MARK: - OIDC Account Management

private var accountSettingsPresenter: OIDCAccountSettingsPresenter?
private func presentAccountSettings() {
guard let accountURL = viewModel.context.viewState.accountURL else {
private func presentAccountProfileURL() {
guard let url = viewModel.context.viewState.accountProfileURL else {
MXLog.error("Account URL is missing.")
return
}

presentAccountManagementURL(url)
}

private func presentAccountSessionsListURL() {
guard let url = viewModel.context.viewState.accountSessionsListURL else {
MXLog.error("Account URL is missing.")
return
}
presentAccountManagementURL(url)
}

private var accountSettingsPresenter: OIDCAccountSettingsPresenter?
private func presentAccountManagementURL(_ url: URL) {
guard let window = viewModel.context.viewState.window else {
MXLog.error("The window is missing.")
return
}

// Note to anyone in the future if you come back here to make this open in Safari instead of a WAS.
// As of iOS 16, there is an issue on the simulator with accessing the cookie but it works on a device. 🤷‍♂️
accountSettingsPresenter = OIDCAccountSettingsPresenter(accountURL: accountURL, presentationAnchor: window)
accountSettingsPresenter = OIDCAccountSettingsPresenter(accountURL: url, presentationAnchor: window)
accountSettingsPresenter?.start()
}

// MARK: - Private

private func presentAnalyticsScreen() {
let coordinator = AnalyticsSettingsScreenCoordinator(parameters: .init(appSettings: ServiceLocator.shared.settings,
analytics: ServiceLocator.shared.analytics))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,12 @@ import UIKit

enum SettingsScreenViewModelAction {
case close
case account
case accountProfile
case analytics
case reportBug
case about
case sessionVerification
case accountSessionsList
case developerOptions
case notifications
case logout
Expand All @@ -33,7 +34,8 @@ struct SettingsScreenViewState: BindableState {
var bindings: SettingsScreenViewStateBindings
var deviceID: String?
var userID: String
var accountURL: URL?
var accountProfileURL: URL?
var accountSessionsListURL: URL?
var userAvatarURL: URL?
var userDisplayName: String?
var showSessionVerificationSection: Bool
Expand All @@ -49,13 +51,14 @@ struct SettingsScreenViewStateBindings {

enum SettingsScreenViewAction {
case close
case account
case accountProfile
case analytics
case reportBug
case about
case sessionVerification
case logout
case changedTimelineStyle
case accountSessionsList
case developerOptions
case notifications

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,8 @@ class SettingsScreenViewModel: SettingsScreenViewModelType, SettingsScreenViewMo
super.init(initialViewState: .init(bindings: bindings,
deviceID: userSession.deviceID,
userID: userSession.userID,
accountURL: userSession.clientProxy.accountURL,
accountProfileURL: userSession.clientProxy.accountURL(action: .profile),
accountSessionsListURL: userSession.clientProxy.accountURL(action: .sessionsList),
showSessionVerificationSection: showSessionVerificationSection,
showDeveloperOptions: appSettings.canShowDeveloperOptions),
imageProvider: userSession.mediaProvider)
Expand Down Expand Up @@ -81,8 +82,8 @@ class SettingsScreenViewModel: SettingsScreenViewModelType, SettingsScreenViewMo
switch viewAction {
case .close:
callback?(.close)
case .account:
callback?(.account)
case .accountProfile:
callback?(.accountProfile)
case .analytics:
callback?(.analytics)
case .reportBug:
Expand All @@ -97,6 +98,8 @@ class SettingsScreenViewModel: SettingsScreenViewModelType, SettingsScreenViewMo
appSettings.timelineStyle = state.bindings.timelineStyle
case .notifications:
callback?(.notifications)
case .accountSessionsList:
callback?(.accountSessionsList)
case .developerOptions:
callback?(.developerOptions)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
//

import Compound
import SFSafeSymbols
import SwiftUI

struct SettingsScreen: View {
Expand All @@ -30,7 +31,11 @@ struct SettingsScreen: View {
sessionVerificationSection
}

simplifiedSection
mainSection

if context.viewState.accountSessionsListURL != nil {
manageSessionsSection
}

if context.viewState.showDeveloperOptions {
developerOptionsSection
Expand All @@ -41,20 +46,12 @@ struct SettingsScreen: View {
.compoundList()
.navigationTitle(L10n.commonSettings)
.navigationBarTitleDisplayMode(.inline)
.toolbar {
ToolbarItem(placement: .confirmationAction) {
doneButton
}
}
.toolbar { toolbar }
.introspect(.window, on: .iOS(.v16, .v17)) { window in
context.send(viewAction: .updateWindow(window))
}
}

private var versionText: Text {
Text(L10n.settingsVersionNumber(InfoPlistReader.main.bundleShortVersionString, InfoPlistReader.main.bundleVersion))
}

private var userSection: some View {
Section {
ListRow(kind: .custom {
Expand Down Expand Up @@ -90,25 +87,13 @@ struct SettingsScreen: View {
}
}

private var developerOptionsSection: some View {
Section {
ListRow(label: .default(title: L10n.commonDeveloperOptions,
systemIcon: .hammerCircle),
kind: .navigationLink {
context.send(viewAction: .developerOptions)
})
.accessibilityIdentifier(A11yIdentifiers.settingsScreen.developerOptions)
}
}

private var simplifiedSection: some View {
private var mainSection: some View {
Section {
// Account
if context.viewState.accountURL != nil {
ListRow(label: .default(title: L10n.screenSettingsOidcAccount,
systemIcon: .person),
if context.viewState.accountProfileURL != nil {
ListRow(label: .default(title: L10n.actionManageAccount, systemIcon: .person),
kind: .button {
context.send(viewAction: .account)
context.send(viewAction: .accountProfile)
})
.accessibilityIdentifier(A11yIdentifiers.settingsScreen.account)
}
Expand Down Expand Up @@ -157,6 +142,36 @@ struct SettingsScreen: View {
}
}

private var manageSessionsSection: some View {
Section {
ListRow(label: .default(title: L10n.actionManageDevices, systemIcon: deviceIcon),
kind: .button {
context.send(viewAction: .accountSessionsList)
})
}
}

private var deviceIcon: SFSymbol {
if ProcessInfo.processInfo.isiOSAppOnMac {
return .macbookAndIphone
} else if UIDevice.current.userInterfaceIdiom == .pad {
return .ipad
} else {
return .iphone
}
}

private var developerOptionsSection: some View {
Section {
ListRow(label: .default(title: L10n.commonDeveloperOptions,
systemIcon: .hammerCircle),
kind: .navigationLink {
context.send(viewAction: .developerOptions)
})
.accessibilityIdentifier(A11yIdentifiers.settingsScreen.developerOptions)
}
}

private var signOutSection: some View {
Section {
ListRow(label: .default(title: L10n.screenSignoutPreferenceItem,
Expand All @@ -166,9 +181,9 @@ struct SettingsScreen: View {
})
.accessibilityIdentifier(A11yIdentifiers.settingsScreen.logout)
.alert(L10n.screenSignoutConfirmationDialogTitle, isPresented: $showingLogoutConfirmation) {
Button(L10n.screenSignoutConfirmationDialogSubmit,
role: .destructive,
action: logout)
Button(L10n.screenSignoutConfirmationDialogSubmit, role: .destructive) {
context.send(viewAction: .logout)
}
} message: {
Text(L10n.screenSignoutConfirmationDialogContent)
}
Expand All @@ -186,18 +201,16 @@ struct SettingsScreen: View {
.padding(.top, 24)
}
}

private var doneButton: some View {
Button(L10n.actionDone, action: close)
.accessibilityIdentifier(A11yIdentifiers.settingsScreen.done)
}

private func close() {
context.send(viewAction: .close)

private var versionText: Text {
Text(L10n.settingsVersionNumber(InfoPlistReader.main.bundleShortVersionString, InfoPlistReader.main.bundleVersion))
}

private func logout() {
context.send(viewAction: .logout)

private var toolbar: some ToolbarContent {
ToolbarItem(placement: .confirmationAction) {
Button(L10n.actionDone) { context.send(viewAction: .close) }
.accessibilityIdentifier(A11yIdentifiers.settingsScreen.done)
}
}
}

Expand All @@ -220,8 +233,7 @@ struct SettingsScreen_Previews: PreviewProvider {
verificationController.isVerified = false
let userSession = MockUserSession(sessionVerificationController: verificationController,
clientProxy: MockClientProxy(userID: "@userid:example.com",
deviceID: "AAAAAAAAAAA",
accountURL: "https://matrix.org/account"),
deviceID: "AAAAAAAAAAA"),
mediaProvider: MockMediaProvider())
return SettingsScreenViewModel(userSession: userSession,
appSettings: ServiceLocator.shared.settings)
Expand Down
Loading