mirror of
https://github.com/Novaloop-AG/element-x-ios.git
synced 2026-11-02 21:33:26 +00:00
Various fixes (#437)
* Fix information leaking on RoomSummaryDetails logging * Prevent crashes when force quitting the application * Cleanup crash detected alert presentation and exposed home screen view model actions * Fixes #340 - Wait for logout confirmation before changing the app state * Add changelogs * Fix unit tests * Add missing softLogout logout handling
This commit is contained in:
@@ -85,6 +85,11 @@ class AppCoordinator: AppCoordinatorProtocol {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func start() {
|
func start() {
|
||||||
|
guard stateMachine.state == .initial else {
|
||||||
|
MXLog.error("Received a start request when already started")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
stateMachine.processEvent(userSessionStore.hasSessions ? .startWithExistingSession : .startWithAuthentication)
|
stateMachine.processEvent(userSessionStore.hasSessions ? .startWithExistingSession : .startWithAuthentication)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -255,21 +260,27 @@ class AppCoordinator: AppCoordinatorProtocol {
|
|||||||
|
|
||||||
deobserveUserSessionChanges()
|
deobserveUserSessionChanges()
|
||||||
|
|
||||||
if !isSoftLogout {
|
guard !isSoftLogout else {
|
||||||
Task {
|
stateMachine.processEvent(.completedSigningOut)
|
||||||
// first log out from the server
|
return
|
||||||
_ = await userSession.clientProxy.logout()
|
|
||||||
|
|
||||||
// regardless of the result, clear user data
|
|
||||||
userSessionStore.logout(userSession: userSession)
|
|
||||||
userSession = nil
|
|
||||||
notificationManager?.delegate = nil
|
|
||||||
notificationManager = nil
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// complete logging out
|
Task {
|
||||||
stateMachine.processEvent(.completedSigningOut)
|
showLoadingIndicator()
|
||||||
|
|
||||||
|
// first log out from the server
|
||||||
|
_ = await userSession.clientProxy.logout()
|
||||||
|
|
||||||
|
// regardless of the result, clear user data
|
||||||
|
userSessionStore.logout(userSession: userSession)
|
||||||
|
userSession = nil
|
||||||
|
notificationManager?.delegate = nil
|
||||||
|
notificationManager = nil
|
||||||
|
|
||||||
|
stateMachine.processEvent(.completedSigningOut)
|
||||||
|
|
||||||
|
hideLoadingIndicator()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private func presentSplashScreen(isSoftLogout: Bool = false) {
|
private func presentSplashScreen(isSoftLogout: Bool = false) {
|
||||||
|
|||||||
@@ -61,6 +61,10 @@ class AppCoordinatorStateMachine {
|
|||||||
|
|
||||||
private let stateMachine: StateMachine<State, Event>
|
private let stateMachine: StateMachine<State, Event>
|
||||||
|
|
||||||
|
var state: AppCoordinatorStateMachine.State {
|
||||||
|
stateMachine.state
|
||||||
|
}
|
||||||
|
|
||||||
init() {
|
init() {
|
||||||
stateMachine = StateMachine(state: .initial)
|
stateMachine = StateMachine(state: .initial)
|
||||||
configure()
|
configure()
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ struct HomeScreenCoordinatorParameters {
|
|||||||
}
|
}
|
||||||
|
|
||||||
enum HomeScreenCoordinatorAction {
|
enum HomeScreenCoordinatorAction {
|
||||||
case presentRoomScreen(roomIdentifier: String)
|
case presentRoom(roomIdentifier: String)
|
||||||
case presentSettingsScreen
|
case presentSettingsScreen
|
||||||
case presentFeedbackScreen
|
case presentFeedbackScreen
|
||||||
case presentSessionVerificationScreen
|
case presentSessionVerificationScreen
|
||||||
@@ -50,12 +50,18 @@ final class HomeScreenCoordinator: CoordinatorProtocol {
|
|||||||
guard let self else { return }
|
guard let self else { return }
|
||||||
|
|
||||||
switch action {
|
switch action {
|
||||||
case .selectRoom(let roomIdentifier):
|
case .presentRoom(let roomIdentifier):
|
||||||
self.callback?(.presentRoomScreen(roomIdentifier: roomIdentifier))
|
self.callback?(.presentRoom(roomIdentifier: roomIdentifier))
|
||||||
case .userMenu(let action):
|
case .presentFeedbackScreen:
|
||||||
self.processUserMenuAction(action)
|
self.callback?(.presentFeedbackScreen)
|
||||||
case .verifySession:
|
case .presentSettingsScreen:
|
||||||
|
self.callback?(.presentSettingsScreen)
|
||||||
|
case .presentInviteFriendsScreen:
|
||||||
|
self.presentInviteFriends()
|
||||||
|
case .presentSessionVerificationScreen:
|
||||||
self.callback?(.presentSessionVerificationScreen)
|
self.callback?(.presentSessionVerificationScreen)
|
||||||
|
case .signOut:
|
||||||
|
self.callback?(.signOut)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -63,15 +69,11 @@ final class HomeScreenCoordinator: CoordinatorProtocol {
|
|||||||
// MARK: - Public
|
// MARK: - Public
|
||||||
|
|
||||||
func start() {
|
func start() {
|
||||||
|
#if !DEBUG
|
||||||
if parameters.bugReportService.crashedLastRun {
|
if parameters.bugReportService.crashedLastRun {
|
||||||
viewModel.presentAlert(
|
viewModel.presentCrashedLastRunAlert()
|
||||||
AlertInfo(id: UUID(),
|
|
||||||
title: ElementL10n.sendBugReportAppCrashed,
|
|
||||||
primaryButton: .init(title: ElementL10n.no, action: nil),
|
|
||||||
secondaryButton: .init(title: ElementL10n.yes) { [weak self] in
|
|
||||||
self?.callback?(.presentFeedbackScreen)
|
|
||||||
}))
|
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
func toPresentable() -> AnyView {
|
func toPresentable() -> AnyView {
|
||||||
@@ -79,19 +81,6 @@ final class HomeScreenCoordinator: CoordinatorProtocol {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// MARK: - Private
|
// MARK: - Private
|
||||||
|
|
||||||
private func processUserMenuAction(_ action: HomeScreenViewUserMenuAction) {
|
|
||||||
switch action {
|
|
||||||
case .settings:
|
|
||||||
callback?(.presentSettingsScreen)
|
|
||||||
case .inviteFriends:
|
|
||||||
presentInviteFriends()
|
|
||||||
case .feedback:
|
|
||||||
callback?(.presentFeedbackScreen)
|
|
||||||
case .signOut:
|
|
||||||
callback?(.signOut)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private func presentInviteFriends() {
|
private func presentInviteFriends() {
|
||||||
parameters.navigationStackCoordinator.setSheetCoordinator(InviteFriendsCoordinator(userId: parameters.userSession.userID))
|
parameters.navigationStackCoordinator.setSheetCoordinator(InviteFriendsCoordinator(userId: parameters.userSession.userID))
|
||||||
|
|||||||
@@ -18,9 +18,12 @@ import Foundation
|
|||||||
import UIKit
|
import UIKit
|
||||||
|
|
||||||
enum HomeScreenViewModelAction {
|
enum HomeScreenViewModelAction {
|
||||||
case selectRoom(roomIdentifier: String)
|
case presentRoom(roomIdentifier: String)
|
||||||
case userMenu(action: HomeScreenViewUserMenuAction)
|
case presentSessionVerificationScreen
|
||||||
case verifySession
|
case presentSettingsScreen
|
||||||
|
case presentInviteFriendsScreen
|
||||||
|
case presentFeedbackScreen
|
||||||
|
case signOut
|
||||||
}
|
}
|
||||||
|
|
||||||
enum HomeScreenViewUserMenuAction {
|
enum HomeScreenViewUserMenuAction {
|
||||||
|
|||||||
@@ -112,6 +112,7 @@ class HomeScreenViewModel: HomeScreenViewModelType, HomeScreenViewModelProtocol
|
|||||||
|
|
||||||
// MARK: - Public
|
// MARK: - Public
|
||||||
|
|
||||||
|
// swiftlint:disable:next cyclomatic_complexity
|
||||||
override func process(viewAction: HomeScreenViewAction) async {
|
override func process(viewAction: HomeScreenViewAction) async {
|
||||||
switch viewAction {
|
switch viewAction {
|
||||||
case .loadRoomData(let roomIdentifier):
|
case .loadRoomData(let roomIdentifier):
|
||||||
@@ -119,11 +120,20 @@ class HomeScreenViewModel: HomeScreenViewModelType, HomeScreenViewModelProtocol
|
|||||||
loadDataForRoomIdentifier(roomIdentifier)
|
loadDataForRoomIdentifier(roomIdentifier)
|
||||||
}
|
}
|
||||||
case .selectRoom(let roomIdentifier):
|
case .selectRoom(let roomIdentifier):
|
||||||
callback?(.selectRoom(roomIdentifier: roomIdentifier))
|
callback?(.presentRoom(roomIdentifier: roomIdentifier))
|
||||||
case .userMenu(let action):
|
case .userMenu(let action):
|
||||||
callback?(.userMenu(action: action))
|
switch action {
|
||||||
|
case .feedback:
|
||||||
|
callback?(.presentFeedbackScreen)
|
||||||
|
case .settings:
|
||||||
|
callback?(.presentSettingsScreen)
|
||||||
|
case .inviteFriends:
|
||||||
|
callback?(.presentInviteFriendsScreen)
|
||||||
|
case .signOut:
|
||||||
|
callback?(.signOut)
|
||||||
|
}
|
||||||
case .verifySession:
|
case .verifySession:
|
||||||
callback?(.verifySession)
|
callback?(.presentSessionVerificationScreen)
|
||||||
case .skipSessionVerification:
|
case .skipSessionVerification:
|
||||||
state.showSessionVerificationBanner = false
|
state.showSessionVerificationBanner = false
|
||||||
case .updatedVisibleItemIdentifiers(let identifiers):
|
case .updatedVisibleItemIdentifiers(let identifiers):
|
||||||
@@ -131,8 +141,13 @@ class HomeScreenViewModel: HomeScreenViewModelType, HomeScreenViewModelProtocol
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func presentAlert(_ alertInfo: AlertInfo<UUID>) {
|
func presentCrashedLastRunAlert() {
|
||||||
state.bindings.alertInfo = alertInfo
|
state.bindings.alertInfo = AlertInfo(id: UUID(),
|
||||||
|
title: ElementL10n.sendBugReportAppCrashed,
|
||||||
|
primaryButton: .init(title: ElementL10n.no, action: nil),
|
||||||
|
secondaryButton: .init(title: ElementL10n.yes) { [weak self] in
|
||||||
|
self?.callback?(.presentFeedbackScreen)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// MARK: - Private
|
// MARK: - Private
|
||||||
|
|||||||
@@ -23,5 +23,5 @@ protocol HomeScreenViewModelProtocol {
|
|||||||
|
|
||||||
var context: HomeScreenViewModelType.Context { get }
|
var context: HomeScreenViewModelType.Context { get }
|
||||||
|
|
||||||
func presentAlert(_ alert: AlertInfo<UUID>)
|
func presentCrashedLastRunAlert()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -25,3 +25,9 @@ struct RoomSummaryDetails {
|
|||||||
let lastMessageTimestamp: Date?
|
let lastMessageTimestamp: Date?
|
||||||
let unreadNotificationCount: UInt
|
let unreadNotificationCount: UInt
|
||||||
}
|
}
|
||||||
|
|
||||||
|
extension RoomSummaryDetails: CustomStringConvertible {
|
||||||
|
var description: String {
|
||||||
|
"id: \"\(id)\", isDirect: \"\(isDirect)\", unreadNotificationCount: \"\(unreadNotificationCount)\""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -125,7 +125,7 @@ class UserSessionFlowCoordinator: CoordinatorProtocol {
|
|||||||
guard let self else { return }
|
guard let self else { return }
|
||||||
|
|
||||||
switch action {
|
switch action {
|
||||||
case .presentRoomScreen(let roomIdentifier):
|
case .presentRoom(let roomIdentifier):
|
||||||
self.stateMachine.processEvent(.selectRoom(roomId: roomIdentifier))
|
self.stateMachine.processEvent(.selectRoom(roomId: roomIdentifier))
|
||||||
case .presentSettingsScreen:
|
case .presentSettingsScreen:
|
||||||
self.stateMachine.processEvent(.showSettingsScreen)
|
self.stateMachine.processEvent(.showSettingsScreen)
|
||||||
|
|||||||
@@ -35,7 +35,7 @@ class HomeScreenViewModelTests: XCTestCase {
|
|||||||
var selectedRoomId = ""
|
var selectedRoomId = ""
|
||||||
viewModel.callback = { result in
|
viewModel.callback = { result in
|
||||||
switch result {
|
switch result {
|
||||||
case .selectRoom(let roomId):
|
case .presentRoom(let roomId):
|
||||||
correctResult = true
|
correctResult = true
|
||||||
selectedRoomId = roomId
|
selectedRoomId = roomId
|
||||||
default:
|
default:
|
||||||
@@ -53,8 +53,8 @@ class HomeScreenViewModelTests: XCTestCase {
|
|||||||
var correctResult = false
|
var correctResult = false
|
||||||
viewModel.callback = { result in
|
viewModel.callback = { result in
|
||||||
switch result {
|
switch result {
|
||||||
case .userMenu(let action):
|
case .presentSettingsScreen:
|
||||||
correctResult = action == .settings
|
correctResult = true
|
||||||
default:
|
default:
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1 @@
|
|||||||
|
Wait for logout confirmation before changing the app state
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
Prevent crash popups when force quitting the application
|
||||||
Reference in New Issue
Block a user