mirror of
https://github.com/Novaloop-AG/element-x-ios.git
synced 2026-11-06 04:18:31 +00:00
Fixes #3146 - Remove the account migration screen
This commit is contained in:
committed by
Stefan Ceriu
parent
cce42a7126
commit
6759a66533
@@ -356,20 +356,6 @@ class AppCoordinator: AppCoordinatorProtocol, AuthenticationFlowCoordinatorDeleg
|
|||||||
|
|
||||||
MXLog.info("The app was upgraded from \(oldVersion) to \(newVersion)")
|
MXLog.info("The app was upgraded from \(oldVersion) to \(newVersion)")
|
||||||
|
|
||||||
if oldVersion < Version(1, 1, 0) {
|
|
||||||
MXLog.info("Migrating to v1.1.0, signing out the user.")
|
|
||||||
// Version 1.1.0 switched the Rust crypto store to SQLite
|
|
||||||
// There are no migrations in place so we need to sign the user out
|
|
||||||
wipeUserData()
|
|
||||||
}
|
|
||||||
|
|
||||||
if oldVersion < Version(1, 1, 7) {
|
|
||||||
MXLog.info("Migrating to v1.1.7, marking accounts as migrated.")
|
|
||||||
for userID in userSessionStore.userIDs {
|
|
||||||
appSettings.migratedAccounts[userID] = true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if oldVersion < Version(1, 6, 0) {
|
if oldVersion < Version(1, 6, 0) {
|
||||||
MXLog.info("Migrating to v1.6.0, marking identity confirmation onboarding as ran.")
|
MXLog.info("Migrating to v1.6.0, marking identity confirmation onboarding as ran.")
|
||||||
if !userSessionStore.userIDs.isEmpty {
|
if !userSessionStore.userIDs.isEmpty {
|
||||||
|
|||||||
@@ -14,7 +14,6 @@ final class AppSettings {
|
|||||||
case lastVersionLaunched
|
case lastVersionLaunched
|
||||||
case appLockNumberOfPINAttempts
|
case appLockNumberOfPINAttempts
|
||||||
case appLockNumberOfBiometricAttempts
|
case appLockNumberOfBiometricAttempts
|
||||||
case migratedAccounts
|
|
||||||
case timelineStyle
|
case timelineStyle
|
||||||
|
|
||||||
case analyticsConsentState
|
case analyticsConsentState
|
||||||
@@ -159,14 +158,7 @@ final class AppSettings {
|
|||||||
contacts: [supportEmailAddress],
|
contacts: [supportEmailAddress],
|
||||||
staticRegistrations: oidcStaticRegistrations.mapKeys { $0.absoluteString },
|
staticRegistrations: oidcStaticRegistrations.mapKeys { $0.absoluteString },
|
||||||
dynamicRegistrationsFile: .sessionsBaseDirectory.appending(path: "oidc/registrations.json"))
|
dynamicRegistrationsFile: .sessionsBaseDirectory.appending(path: "oidc/registrations.json"))
|
||||||
|
|
||||||
/// A dictionary of accounts that have performed an initial sync through their proxy.
|
|
||||||
///
|
|
||||||
/// This is a temporary workaround. In the future we should be able to receive a signal from the
|
|
||||||
/// proxy that it is the first sync (or that an upgrade on the backend will involve a slower sync).
|
|
||||||
@UserPreference(key: UserDefaultsKeys.migratedAccounts, defaultValue: [:], storageType: .userDefaults(store))
|
|
||||||
var migratedAccounts: [String: Bool]
|
|
||||||
|
|
||||||
// MARK: - Notifications
|
// MARK: - Notifications
|
||||||
|
|
||||||
var pusherAppId: String {
|
var pusherAppId: String {
|
||||||
|
|||||||
@@ -32,7 +32,6 @@ enum A11yIdentifiers {
|
|||||||
static let roomMemberDetailsScreen = RoomMemberDetailsScreen()
|
static let roomMemberDetailsScreen = RoomMemberDetailsScreen()
|
||||||
static let createRoomScreen = CreateRoomScreen()
|
static let createRoomScreen = CreateRoomScreen()
|
||||||
static let inviteUsersScreen = InviteUsersScreen()
|
static let inviteUsersScreen = InviteUsersScreen()
|
||||||
static let migrationScreen = MigrationScreen()
|
|
||||||
static let notificationSettingsScreen = NotificationSettingsScreen()
|
static let notificationSettingsScreen = NotificationSettingsScreen()
|
||||||
static let notificationSettingsEditScreen = NotificationSettingsEditScreen()
|
static let notificationSettingsEditScreen = NotificationSettingsEditScreen()
|
||||||
static let pollFormScreen = PollFormScreen()
|
static let pollFormScreen = PollFormScreen()
|
||||||
@@ -239,10 +238,6 @@ enum A11yIdentifiers {
|
|||||||
"\(optionPrefix)-\(index)"
|
"\(optionPrefix)-\(index)"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct MigrationScreen {
|
|
||||||
let message = "migration_screen-message"
|
|
||||||
}
|
|
||||||
|
|
||||||
struct NotificationSettingsScreen {
|
struct NotificationSettingsScreen {
|
||||||
let fixMismatchConfiguration = "notification_settings_screen-fix_mismatch_configuration"
|
let fixMismatchConfiguration = "notification_settings_screen-fix_mismatch_configuration"
|
||||||
|
|||||||
@@ -43,15 +43,12 @@ enum HomeScreenViewAction {
|
|||||||
}
|
}
|
||||||
|
|
||||||
enum HomeScreenRoomListMode: CustomStringConvertible {
|
enum HomeScreenRoomListMode: CustomStringConvertible {
|
||||||
case migration
|
|
||||||
case skeletons
|
case skeletons
|
||||||
case empty
|
case empty
|
||||||
case rooms
|
case rooms
|
||||||
|
|
||||||
var description: String {
|
var description: String {
|
||||||
switch self {
|
switch self {
|
||||||
case .migration:
|
|
||||||
return "Showing account migration"
|
|
||||||
case .skeletons:
|
case .skeletons:
|
||||||
return "Showing placeholders"
|
return "Showing placeholders"
|
||||||
case .empty:
|
case .empty:
|
||||||
|
|||||||
@@ -19,8 +19,6 @@ class HomeScreenViewModel: HomeScreenViewModelType, HomeScreenViewModelProtocol
|
|||||||
|
|
||||||
private let roomSummaryProvider: RoomSummaryProviderProtocol?
|
private let roomSummaryProvider: RoomSummaryProviderProtocol?
|
||||||
|
|
||||||
private var migrationCancellable: AnyCancellable?
|
|
||||||
|
|
||||||
private var actionsSubject: PassthroughSubject<HomeScreenViewModelAction, Never> = .init()
|
private var actionsSubject: PassthroughSubject<HomeScreenViewModelAction, Never> = .init()
|
||||||
var actions: AnyPublisher<HomeScreenViewModelAction, Never> {
|
var actions: AnyPublisher<HomeScreenViewModelAction, Never> {
|
||||||
actionsSubject.eraseToAnyPublisher()
|
actionsSubject.eraseToAnyPublisher()
|
||||||
@@ -223,27 +221,7 @@ class HomeScreenViewModel: HomeScreenViewModelType, HomeScreenViewModelProtocol
|
|||||||
}
|
}
|
||||||
|
|
||||||
analyticsService.signpost.beginFirstRooms()
|
analyticsService.signpost.beginFirstRooms()
|
||||||
|
|
||||||
let hasUserBeenMigrated = appSettings.migratedAccounts[userSession.clientProxy.userID] == true
|
|
||||||
|
|
||||||
if !hasUserBeenMigrated {
|
|
||||||
state.roomListMode = .migration
|
|
||||||
|
|
||||||
MXLog.info("Account not migrated, setting view room list mode to \"\(state.roomListMode)\"")
|
|
||||||
|
|
||||||
migrationCancellable = userSession.clientProxy.actionsPublisher
|
|
||||||
.receive(on: DispatchQueue.main)
|
|
||||||
.sink { [weak self] callback in
|
|
||||||
guard let self, case .receivedSyncUpdate = callback else { return }
|
|
||||||
migrationCancellable = nil
|
|
||||||
appSettings.migratedAccounts[userSession.clientProxy.userID] = true
|
|
||||||
|
|
||||||
MXLog.info("Received first sync response, updating room list mode")
|
|
||||||
|
|
||||||
updateRoomListMode(with: roomSummaryProvider.statePublisher.value)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
roomSummaryProvider.statePublisher
|
roomSummaryProvider.statePublisher
|
||||||
.receive(on: DispatchQueue.main)
|
.receive(on: DispatchQueue.main)
|
||||||
.sink { [weak self] state in
|
.sink { [weak self] state in
|
||||||
@@ -262,11 +240,6 @@ class HomeScreenViewModel: HomeScreenViewModelType, HomeScreenViewModelProtocol
|
|||||||
}
|
}
|
||||||
|
|
||||||
private func updateRoomListMode(with roomSummaryProviderState: RoomSummaryProviderState) {
|
private func updateRoomListMode(with roomSummaryProviderState: RoomSummaryProviderState) {
|
||||||
guard appSettings.migratedAccounts[userSession.clientProxy.userID] == true else {
|
|
||||||
// Ignore room summary provider updates while "migrating"
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
let isLoadingData = !roomSummaryProviderState.isLoaded
|
let isLoadingData = !roomSummaryProviderState.isLoaded
|
||||||
let hasNoRooms = roomSummaryProviderState.isLoaded && roomSummaryProviderState.totalNumberOfRooms == 0
|
let hasNoRooms = roomSummaryProviderState.isLoaded && roomSummaryProviderState.totalNumberOfRooms == 0
|
||||||
|
|
||||||
|
|||||||
@@ -188,17 +188,11 @@ struct HomeScreen: View {
|
|||||||
// MARK: - Previews
|
// MARK: - Previews
|
||||||
|
|
||||||
struct HomeScreen_Previews: PreviewProvider, TestablePreview {
|
struct HomeScreen_Previews: PreviewProvider, TestablePreview {
|
||||||
static let migratingViewModel = viewModel(.migration)
|
|
||||||
static let loadingViewModel = viewModel(.skeletons)
|
static let loadingViewModel = viewModel(.skeletons)
|
||||||
static let emptyViewModel = viewModel(.empty)
|
static let emptyViewModel = viewModel(.empty)
|
||||||
static let loadedViewModel = viewModel(.rooms)
|
static let loadedViewModel = viewModel(.rooms)
|
||||||
|
|
||||||
static var previews: some View {
|
static var previews: some View {
|
||||||
NavigationStack {
|
|
||||||
HomeScreen(context: migratingViewModel.context)
|
|
||||||
}
|
|
||||||
.previewDisplayName("Migrating")
|
|
||||||
|
|
||||||
NavigationStack {
|
NavigationStack {
|
||||||
HomeScreen(context: loadingViewModel.context)
|
HomeScreen(context: loadingViewModel.context)
|
||||||
}
|
}
|
||||||
@@ -218,14 +212,9 @@ struct HomeScreen_Previews: PreviewProvider, TestablePreview {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static func viewModel(_ mode: HomeScreenRoomListMode) -> HomeScreenViewModel {
|
static func viewModel(_ mode: HomeScreenRoomListMode) -> HomeScreenViewModel {
|
||||||
let userID = mode == .migration ? "@unmigrated_alice:example.com" : "@alice:example.com"
|
let userID = "@alice:example.com"
|
||||||
|
|
||||||
let appSettings = AppSettings() // This uses shared storage under the hood
|
|
||||||
appSettings.migratedAccounts[userID] = mode != .migration
|
|
||||||
|
|
||||||
let roomSummaryProviderState: RoomSummaryProviderMockConfigurationState = switch mode {
|
let roomSummaryProviderState: RoomSummaryProviderMockConfigurationState = switch mode {
|
||||||
case .migration:
|
|
||||||
.loading
|
|
||||||
case .skeletons:
|
case .skeletons:
|
||||||
.loading
|
.loading
|
||||||
case .empty:
|
case .empty:
|
||||||
@@ -241,7 +230,7 @@ struct HomeScreen_Previews: PreviewProvider, TestablePreview {
|
|||||||
|
|
||||||
return HomeScreenViewModel(userSession: userSession,
|
return HomeScreenViewModel(userSession: userSession,
|
||||||
analyticsService: ServiceLocator.shared.analytics,
|
analyticsService: ServiceLocator.shared.analytics,
|
||||||
appSettings: appSettings,
|
appSettings: ServiceLocator.shared.settings,
|
||||||
selectedRoomPublisher: CurrentValueSubject<String?, Never>(nil).asCurrentValuePublisher(),
|
selectedRoomPublisher: CurrentValueSubject<String?, Never>(nil).asCurrentValuePublisher(),
|
||||||
userIndicatorController: ServiceLocator.shared.userIndicatorController)
|
userIndicatorController: ServiceLocator.shared.userIndicatorController)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,13 +16,8 @@ struct HomeScreenContent: View {
|
|||||||
let scrollViewAdapter: ScrollViewAdapter
|
let scrollViewAdapter: ScrollViewAdapter
|
||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
switch context.viewState.roomListMode {
|
roomList
|
||||||
case .migration:
|
.sentryTrace("\(Self.self)")
|
||||||
migrationView
|
|
||||||
default:
|
|
||||||
roomList
|
|
||||||
.sentryTrace("\(Self.self)")
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private var roomList: some View {
|
private var roomList: some View {
|
||||||
@@ -59,8 +54,6 @@ struct HomeScreenContent: View {
|
|||||||
.searchable(text: $context.searchQuery, placement: .navigationBarDrawer(displayMode: .always))
|
.searchable(text: $context.searchQuery, placement: .navigationBarDrawer(displayMode: .always))
|
||||||
.compoundSearchField()
|
.compoundSearchField()
|
||||||
.disableAutocorrection(true)
|
.disableAutocorrection(true)
|
||||||
case .migration:
|
|
||||||
EmptyView()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.introspect(.scrollView, on: .supportedVersions) { scrollView in
|
.introspect(.scrollView, on: .supportedVersions) { scrollView in
|
||||||
@@ -141,47 +134,6 @@ struct HomeScreenContent: View {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ViewBuilder
|
|
||||||
private var migrationView: some View {
|
|
||||||
if UIDevice.current.isPhone {
|
|
||||||
if verticalSizeClass == .compact {
|
|
||||||
migrationViewContent
|
|
||||||
.frame(maxWidth: .infinity, maxHeight: .infinity)
|
|
||||||
} else {
|
|
||||||
WaitingDialog {
|
|
||||||
migrationViewContent
|
|
||||||
} bottomContent: {
|
|
||||||
EmptyView()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
migrationViewContent
|
|
||||||
.frame(maxWidth: .infinity, maxHeight: .infinity)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private var migrationViewContent: some View {
|
|
||||||
VStack(spacing: 16) {
|
|
||||||
ProgressView()
|
|
||||||
.tint(.compound.iconPrimary)
|
|
||||||
.padding(.bottom, 4)
|
|
||||||
|
|
||||||
Text(L10n.screenMigrationTitle.tinting(".", color: Asset.Colors.brandColor.swiftUIColor))
|
|
||||||
.minimumScaleFactor(0.01)
|
|
||||||
.font(.compound.headingXLBold)
|
|
||||||
.multilineTextAlignment(.center)
|
|
||||||
.foregroundColor(.compound.textPrimary)
|
|
||||||
|
|
||||||
Text(L10n.screenMigrationMessage)
|
|
||||||
.minimumScaleFactor(0.01)
|
|
||||||
.font(.compound.bodyLG)
|
|
||||||
.multilineTextAlignment(.center)
|
|
||||||
.foregroundColor(.compound.textPrimary)
|
|
||||||
.accessibilityIdentifier(A11yIdentifiers.migrationScreen.message)
|
|
||||||
}
|
|
||||||
.padding(.horizontal)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Often times the scroll view's content size isn't correct yet when this method is called e.g. when cancelling a search
|
/// Often times the scroll view's content size isn't correct yet when this method is called e.g. when cancelling a search
|
||||||
/// Dispatch it with a delay to allow the UI to update and the computations to be correct
|
/// Dispatch it with a delay to allow the UI to update and the computations to be correct
|
||||||
/// Once we move to iOS 17 we should remove all of this and use scroll anchors instead
|
/// Once we move to iOS 17 we should remove all of this and use scroll anchors instead
|
||||||
|
|||||||
@@ -522,7 +522,6 @@ class MockScreen: Identifiable {
|
|||||||
let navigationSplitCoordinator = NavigationSplitCoordinator(placeholderCoordinator: PlaceholderScreenCoordinator())
|
let navigationSplitCoordinator = NavigationSplitCoordinator(placeholderCoordinator: PlaceholderScreenCoordinator())
|
||||||
|
|
||||||
let clientProxy = ClientProxyMock(.init(userID: "@mock:client.com", deviceID: "MOCKCLIENT", roomSummaryProvider: RoomSummaryProviderMock(.init(state: .loaded(.mockRooms)))))
|
let clientProxy = ClientProxyMock(.init(userID: "@mock:client.com", deviceID: "MOCKCLIENT", roomSummaryProvider: RoomSummaryProviderMock(.init(state: .loaded(.mockRooms)))))
|
||||||
ServiceLocator.shared.settings.migratedAccounts[clientProxy.userID] = true
|
|
||||||
|
|
||||||
let appMediator = AppMediatorMock.default
|
let appMediator = AppMediatorMock.default
|
||||||
appMediator.underlyingWindowManager = windowManager
|
appMediator.underlyingWindowManager = windowManager
|
||||||
@@ -635,8 +634,6 @@ class MockScreen: Identifiable {
|
|||||||
|
|
||||||
clientProxy.roomForIdentifierReturnValue = .joined(roomProxy)
|
clientProxy.roomForIdentifierReturnValue = .joined(roomProxy)
|
||||||
|
|
||||||
ServiceLocator.shared.settings.migratedAccounts[clientProxy.userID] = true
|
|
||||||
|
|
||||||
let timelineController = RoomTimelineController(roomProxy: roomProxy,
|
let timelineController = RoomTimelineController(roomProxy: roomProxy,
|
||||||
timelineProxy: roomProxy.timeline,
|
timelineProxy: roomProxy.timeline,
|
||||||
initialFocussedEventID: nil,
|
initialFocussedEventID: nil,
|
||||||
|
|||||||
@@ -65,15 +65,6 @@ extension XCUIApplication {
|
|||||||
|
|
||||||
savePasswordButton.tap()
|
savePasswordButton.tap()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Migration screen may be shown as an overlay.
|
|
||||||
// if that pops up soon enough, we just let that happen and wait
|
|
||||||
let message = staticTexts[A11yIdentifiers.migrationScreen.message]
|
|
||||||
|
|
||||||
if message.waitForExistence(timeout: 10.0) {
|
|
||||||
currentTestCase.expectation(for: doesNotExistPredicate, evaluatedWith: message)
|
|
||||||
currentTestCase.waitForExpectations(timeout: 300.0)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Wait for the home screen to become visible.
|
// Wait for the home screen to become visible.
|
||||||
let profileButton = buttons[A11yIdentifiers.homeScreen.userAvatar]
|
let profileButton = buttons[A11yIdentifiers.homeScreen.userAvatar]
|
||||||
|
|||||||
@@ -1,3 +0,0 @@
|
|||||||
version https://git-lfs.github.com/spec/v1
|
|
||||||
oid sha256:82f915f692c622ca6486a0f7a0b8bab6df7959078add40a16ded37593716af57
|
|
||||||
size 893292
|
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
version https://git-lfs.github.com/spec/v1
|
|
||||||
oid sha256:9cbb28cd9f361a81b96057ee8738d154a9add7de7a4ca9cdcd1600d499f6bf8d
|
|
||||||
size 909428
|
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
version https://git-lfs.github.com/spec/v1
|
|
||||||
oid sha256:32dde9b6437682f702c13359337b3f21479d138a0cbcf20e47a3ff1b6ecbe2d7
|
|
||||||
size 274869
|
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
version https://git-lfs.github.com/spec/v1
|
|
||||||
oid sha256:487cf66a31c068c0bfc33ff95b4a69c9e5a9f77c4f2f958ac266349587e1b098
|
|
||||||
size 293724
|
|
||||||
Reference in New Issue
Block a user