From e3383bc393c836fdd8ae7c5c4bc35ae0d01de37a Mon Sep 17 00:00:00 2001 From: Mauro <34335419+Velin92@users.noreply.github.com> Date: Wed, 14 Jun 2023 16:24:10 +0200 Subject: [PATCH] Refactored alert info to not use the soon to be deprecated API (#1084) * refactored alert info to not use the soon to be deprecated API * missing files and changelog * updated some tests * Update ElementX/Sources/Screens/RoomMemberDetailsScreen/View/RoomMemberDetailsScreen.swift Co-authored-by: Doug <6060466+pixlwave@users.noreply.github.com> --------- Co-authored-by: Doug <6060466+pixlwave@users.noreply.github.com> --- ElementX.xcodeproj/project.pbxproj | 12 -- .../xcshareddata/swiftpm/Package.resolved | 9 ++ ElementX/Sources/Other/Extensions/Alert.swift | 76 +++++++++--- .../SwiftUI/ErrorHandling/AlertInfo.swift | 108 ------------------ .../UserIndicatorPresenter.swift | 4 +- .../LoginScreen/View/LoginScreen.swift | 2 +- .../View/ServerSelectionScreen.swift | 2 +- .../View/SoftLogoutScreen.swift | 2 +- .../CreateRoom/View/CreateRoomScreen.swift | 2 +- .../Screens/HomeScreen/View/HomeScreen.swift | 2 +- .../View/InviteUsersScreen.swift | 2 +- .../InvitesScreen/View/InvitesScreen.swift | 2 +- .../LocationSharingScreenModels.swift | 11 +- .../View/StaticLocationScreen.swift | 2 +- .../RoomDetailsScreenModels.swift | 4 +- .../View/RoomDetailsScreen.swift | 2 +- .../RoomMemberDetailsScreenModels.swift | 9 +- .../RoomMemberDetailsScreenViewModel.swift | 8 +- .../View/RoomMemberDetailsScreen.swift | 2 +- .../View/RoomMembersListScreen.swift | 2 +- .../Screens/RoomScreen/View/RoomScreen.swift | 2 +- .../View/StartChatScreen.swift | 2 +- .../RoomMemberDetailsViewModelTests.swift | 10 +- changelog.d/1067.change | 1 + 24 files changed, 107 insertions(+), 171 deletions(-) delete mode 100644 ElementX/Sources/Other/SwiftUI/ErrorHandling/AlertInfo.swift create mode 100644 changelog.d/1067.change diff --git a/ElementX.xcodeproj/project.pbxproj b/ElementX.xcodeproj/project.pbxproj index 22093dd61..b2cdcbb21 100644 --- a/ElementX.xcodeproj/project.pbxproj +++ b/ElementX.xcodeproj/project.pbxproj @@ -430,7 +430,6 @@ A440D4BC02088482EC633A88 /* KeychainControllerProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = E5E94DCFEE803E5ABAE8ACCE /* KeychainControllerProtocol.swift */; }; A494741843F087881299ACF0 /* RestorationToken.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3558A15CFB934F9229301527 /* RestorationToken.swift */; }; A4E885358D7DD5A072A06824 /* PostHog in Frameworks */ = {isa = PBXBuildFile; productRef = CCE5BF78B125320CBF3BB834 /* PostHog */; }; - A50849766F056FD1DB942DEA /* AlertInfo.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2EEB64CC6F3DF5B68736A6B4 /* AlertInfo.swift */; }; A5B9EF45C7B8ACEB4954AE36 /* LoginScreenViewModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9780389F8A53E4D26E23DD03 /* LoginScreenViewModelProtocol.swift */; }; A5D551E5691749066E0E0C44 /* RoomDetailsScreenViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 837B440C4705E4B899BCB899 /* RoomDetailsScreenViewModel.swift */; }; A680F54935A6ADEA4ED6C38F /* TimelineItemStatusView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6A4C9547BBFEEF30AA11329B /* TimelineItemStatusView.swift */; }; @@ -837,7 +836,6 @@ 2D0946F77B696176E062D037 /* RoomMembersListScreenModels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomMembersListScreenModels.swift; sourceTree = ""; }; 2D256FEE2F1AF1E51D39B622 /* LoginTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LoginTests.swift; sourceTree = ""; }; 2D505843AB66822EB91F0DF0 /* TimelineItemProxy.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TimelineItemProxy.swift; sourceTree = ""; }; - 2EEB64CC6F3DF5B68736A6B4 /* AlertInfo.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AlertInfo.swift; sourceTree = ""; }; 2EFE1922F39398ABFB36DF3F /* RoomDetailsViewModelTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomDetailsViewModelTests.swift; sourceTree = ""; }; 2F36C5D9B37E50915ECBD3EE /* RoomMemberProxy.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomMemberProxy.swift; sourceTree = ""; }; 303FCADE77DF1F3670C086ED /* BugReportScreenViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BugReportScreenViewModel.swift; sourceTree = ""; }; @@ -1434,7 +1432,6 @@ children = ( 693E16574C6F7F9FA1015A8C /* Search.swift */, E2DA161C142B7AB8CC40F752 /* Animation */, - 595B8797ED6A7489ABDCE384 /* ErrorHandling */, 1BC3028DDD0C27AE5318FEDC /* Form Styles */, CE2FBFD64A89F5DBE4EB30DB /* Layout */, 10578D9852BA78D309A1CBDF /* ViewModel */, @@ -2064,14 +2061,6 @@ path = FlowCoordinators; sourceTree = ""; }; - 595B8797ED6A7489ABDCE384 /* ErrorHandling */ = { - isa = PBXGroup; - children = ( - 2EEB64CC6F3DF5B68736A6B4 /* AlertInfo.swift */, - ); - path = ErrorHandling; - sourceTree = ""; - }; 5970F275D6014548DCED6106 /* ReportContentScreen */ = { isa = PBXGroup; children = ( @@ -3843,7 +3832,6 @@ 70394ECD2DCC70741538620D /* AccessibilityIdentifiers.swift in Sources */, 4219391CD2351E410554B3E8 /* AggregratedReaction.swift in Sources */, 64D05250CEDE8B604119F6E6 /* Alert.swift in Sources */, - A50849766F056FD1DB942DEA /* AlertInfo.swift in Sources */, 39929D29B265C3F6606047DE /* AlignedScrollView.swift in Sources */, A371629728E597C5FCA3C2B2 /* Analytics.swift in Sources */, F7567DD6635434E8C563BF85 /* AnalyticsClientProtocol.swift in Sources */, diff --git a/ElementX.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved b/ElementX.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved index a596c5b7c..092fc4784 100644 --- a/ElementX.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved +++ b/ElementX.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved @@ -88,6 +88,15 @@ "revision" : "d27a9557427d261adccdf4b566acc9d9c0fec6f4" } }, + { + "identity" : "maplibre-gl-native-distribution", + "kind" : "remoteSourceControl", + "location" : "https://github.com/maplibre/maplibre-gl-native-distribution", + "state" : { + "revision" : "ffda61e298c1490d4860d5184e80d618aaadc089", + "version" : "5.13.0" + } + }, { "identity" : "matrix-analytics-events", "kind" : "remoteSourceControl", diff --git a/ElementX/Sources/Other/Extensions/Alert.swift b/ElementX/Sources/Other/Extensions/Alert.swift index f48f7b79c..7f1fcc4a5 100644 --- a/ElementX/Sources/Other/Extensions/Alert.swift +++ b/ElementX/Sources/Other/Extensions/Alert.swift @@ -16,12 +16,12 @@ import SwiftUI -protocol AlertItem { +protocol AlertProtocol { var title: String { get } } extension View { - func alert(item: Binding, @ViewBuilder actions: (Item) -> Actions, @ViewBuilder message: (Item) -> Message) -> some View where Item: AlertItem, Actions: View, Message: View { + func alert(item: Binding, @ViewBuilder actions: (Item) -> Actions, @ViewBuilder message: (Item) -> Message) -> some View where Item: AlertProtocol, Actions: View, Message: View { let binding = Binding(get: { item.wrappedValue != nil }, set: { newValue in @@ -32,7 +32,7 @@ extension View { return alert(item.wrappedValue?.title ?? "", isPresented: binding, presenting: item.wrappedValue, actions: actions, message: message) } - func alert(item: Binding, @ViewBuilder actions: (Item) -> Actions) -> some View where Item: AlertItem, Actions: View { + func alert(item: Binding, @ViewBuilder actions: (Item) -> Actions) -> some View where Item: AlertProtocol, Actions: View { let binding = Binding(get: { item.wrappedValue != nil }, set: { newValue in @@ -44,29 +44,69 @@ extension View { } } -// Only for Alerts that display a simple error message with a message and one or two buttons -struct ErrorAlertItem: AlertItem { - struct Action { - var title: String - var action: () -> Void +/// A type that describes an alert to be shown to the user. +/// +/// The alert info can be added to the view state bindings and used as an alert's `item`: +/// ``` +/// view +/// .alert(item: $context.alertInfo) +/// ``` +struct AlertInfo: Identifiable, AlertProtocol { + struct AlertButton { + let title: String + var role: ButtonRole? + let action: (() -> Void)? } - var error: Error - var title = L10n.commonError - var message = L10n.errorUnknown - var cancelAction = Action(title: L10n.actionOk, action: { }) - var primaryAction: Action? + /// An identifier that can be used to distinguish one error from another. + let id: T + /// The alert's title. + let title: String + /// The alert's message (optional). + var message: String? + /// The alert's primary button title and action. Defaults to an Ok button with no action. + var primaryButton = AlertButton(title: L10n.actionOk, action: nil) + /// The alert's secondary button title and action. + var secondaryButton: AlertButton? +} + +extension AlertInfo { + /// Initialises the type with a generic title and message for an unknown error along with the default Ok button. + /// - Parameters: + /// - id: An ID that identifies the error. + /// - error: The Error that occurred. + init(id: T) { + self.id = id + title = L10n.commonError + message = L10n.errorUnknown + } + + /// Initialises the type with the title from an `Error`'s localised description along with the default Ok button. + /// + /// Currently this initialiser creates an alert for every error, however in the future it may be updated to filter + /// out some specific errors such as cancellation and networking issues that create too much noise or are + /// indicated to the user using other mechanisms. + init(error: Error) where T == String { + self.init(id: error.localizedDescription, + title: error.localizedDescription) + } } extension View { - func errorAlert(item: Binding) -> some View { + func alert(item: Binding?>) -> some View { alert(item: item) { item in - Button(item.cancelAction.title) { item.cancelAction.action() } - if let primaryAction = item.primaryAction { - Button(primaryAction.title) { primaryAction.action() } + Button(item.primaryButton.title, role: item.primaryButton.role) { + item.primaryButton.action?() + } + if let secondaryButton = item.secondaryButton { + Button(secondaryButton.title, role: secondaryButton.role) { + secondaryButton.action?() + } } } message: { item in - Text(item.message) + if let message = item.message { + Text(message) + } } } } diff --git a/ElementX/Sources/Other/SwiftUI/ErrorHandling/AlertInfo.swift b/ElementX/Sources/Other/SwiftUI/ErrorHandling/AlertInfo.swift deleted file mode 100644 index 233444138..000000000 --- a/ElementX/Sources/Other/SwiftUI/ErrorHandling/AlertInfo.swift +++ /dev/null @@ -1,108 +0,0 @@ -// -// Copyright 2022 New Vector Ltd -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// - -import SwiftUI - -/// A type that describes an alert to be shown to the user. -/// -/// The alert info can be added to the view state bindings and used as an alert's `item`: -/// ``` -/// MyView -/// .alert(item: $viewModel.alertInfo) { $0.alert } -/// ``` -struct AlertInfo: Identifiable { - /// An identifier that can be used to distinguish one error from another. - let id: T - /// The alert's title. - let title: String - /// The alert's message (optional). - var message: String? - /// The alert's primary button title and action. Defaults to an Ok button with no action. - var primaryButton = AlertButton(title: L10n.actionOk, action: nil) - /// The alert's secondary button title and action. - var secondaryButton: AlertButton? -} - -struct AlertButton { - let title: String - var role: Role = .default - let action: (() -> Void)? - - enum Role { - case `default`, cancel, destructive - } -} - -extension AlertInfo { - /// Initialises the type with the title from an `Error`'s localised description along with the default Ok button. - /// - /// Currently this initialiser creates an alert for every error, however in the future it may be updated to filter - /// out some specific errors such as cancellation and networking issues that create too much noise or are - /// indicated to the user using other mechanisms. - init(error: Error) where T == String { - self.init(id: error.localizedDescription, - title: error.localizedDescription) - } - - /// Initialises the type with a generic title and message for an unknown error along with the default Ok button. - /// - Parameters: - /// - id: An ID that identifies the error. - /// - error: The Error that occurred. - init(id: T) { - self.id = id - title = L10n.commonError - message = L10n.errorUnknown - } -} - -extension AlertInfo { - private var messageText: Text? { - guard let message else { return nil } - return Text(message) - } - - /// Returns a SwiftUI `Alert` created from this alert info, using default button - /// styles for both primary and (if set) secondary buttons. - var alert: Alert { - if let secondaryButton { - return Alert(title: Text(title), - message: messageText, - primaryButton: alertButton(for: primaryButton), - secondaryButton: alertButton(for: secondaryButton)) - } else { - return Alert(title: Text(title), - message: messageText, - dismissButton: alertButton(for: primaryButton)) - } - } - - private func alertButton(for buttonParameters: AlertButton) -> Alert.Button { - switch (buttonParameters.role, buttonParameters.action) { - case (.default, nil): - return .default(Text(buttonParameters.title)) - case (.default, let action): - return .default(Text(buttonParameters.title), action: action) - case (.cancel, nil): - return .cancel(Text(buttonParameters.title)) - case (.cancel, let action): - return .cancel(Text(buttonParameters.title), action: action) - case (.destructive, nil): - return .destructive(Text(buttonParameters.title)) - case (.destructive, let action): - return .destructive(Text(buttonParameters.title), action: action) - } - } -} diff --git a/ElementX/Sources/Other/UserIndicator/UserIndicatorPresenter.swift b/ElementX/Sources/Other/UserIndicator/UserIndicatorPresenter.swift index 215bf8643..1a754ebd6 100644 --- a/ElementX/Sources/Other/UserIndicator/UserIndicatorPresenter.swift +++ b/ElementX/Sources/Other/UserIndicator/UserIndicatorPresenter.swift @@ -40,8 +40,6 @@ struct UserIndicatorPresenter: View { } } } - .alert(item: $userIndicatorController.alertInfo) { - $0.alert - } + .alert(item: $userIndicatorController.alertInfo) } } diff --git a/ElementX/Sources/Screens/Authentication/LoginScreen/View/LoginScreen.swift b/ElementX/Sources/Screens/Authentication/LoginScreen/View/LoginScreen.swift index 2eb5859b5..5e5dad8ab 100644 --- a/ElementX/Sources/Screens/Authentication/LoginScreen/View/LoginScreen.swift +++ b/ElementX/Sources/Screens/Authentication/LoginScreen/View/LoginScreen.swift @@ -46,7 +46,7 @@ struct LoginScreen: View { .padding(.bottom, 16) } .background(Color.element.background.ignoresSafeArea()) - .alert(item: $context.alertInfo) { $0.alert } + .alert(item: $context.alertInfo) } /// The header containing the title and icon. diff --git a/ElementX/Sources/Screens/Authentication/ServerSelectionScreen/View/ServerSelectionScreen.swift b/ElementX/Sources/Screens/Authentication/ServerSelectionScreen/View/ServerSelectionScreen.swift index 8a497679e..b5603971a 100644 --- a/ElementX/Sources/Screens/Authentication/ServerSelectionScreen/View/ServerSelectionScreen.swift +++ b/ElementX/Sources/Screens/Authentication/ServerSelectionScreen/View/ServerSelectionScreen.swift @@ -33,7 +33,7 @@ struct ServerSelectionScreen: View { } .background(Color.element.background.ignoresSafeArea()) .toolbar { toolbar } - .alert(item: $context.alertInfo) { $0.alert } + .alert(item: $context.alertInfo) .interactiveDismissDisabled() } diff --git a/ElementX/Sources/Screens/Authentication/SoftLogoutScreen/View/SoftLogoutScreen.swift b/ElementX/Sources/Screens/Authentication/SoftLogoutScreen/View/SoftLogoutScreen.swift index a149a8ba9..7db73abaa 100644 --- a/ElementX/Sources/Screens/Authentication/SoftLogoutScreen/View/SoftLogoutScreen.swift +++ b/ElementX/Sources/Screens/Authentication/SoftLogoutScreen/View/SoftLogoutScreen.swift @@ -48,7 +48,7 @@ struct SoftLogoutScreen: View { .padding(.bottom, 16) } .background(Color.element.background.ignoresSafeArea()) - .alert(item: $context.alertInfo) { $0.alert } + .alert(item: $context.alertInfo) .introspectViewController { viewController in guard let window = viewController.view.window else { return } context.send(viewAction: .updateWindow(window)) diff --git a/ElementX/Sources/Screens/CreateRoom/View/CreateRoomScreen.swift b/ElementX/Sources/Screens/CreateRoom/View/CreateRoomScreen.swift index f7796986e..c55bc0cc0 100644 --- a/ElementX/Sources/Screens/CreateRoom/View/CreateRoomScreen.swift +++ b/ElementX/Sources/Screens/CreateRoom/View/CreateRoomScreen.swift @@ -41,7 +41,7 @@ struct CreateRoomScreen: View { } } .background(ViewFrameReader(frame: $frame)) - .alert(item: $context.alertInfo) { $0.alert } + .alert(item: $context.alertInfo) } @ScaledMetric private var roomIconSize: CGFloat = 70 diff --git a/ElementX/Sources/Screens/HomeScreen/View/HomeScreen.swift b/ElementX/Sources/Screens/HomeScreen/View/HomeScreen.swift index 5ff845836..70cb29ccc 100644 --- a/ElementX/Sources/Screens/HomeScreen/View/HomeScreen.swift +++ b/ElementX/Sources/Screens/HomeScreen/View/HomeScreen.swift @@ -116,7 +116,7 @@ struct HomeScreen: View { .animation(.elementDefault, value: context.viewState.showSessionVerificationBanner) .animation(.elementDefault, value: context.viewState.roomListMode) .animation(.none, value: context.viewState.visibleRooms) - .alert(item: $context.alertInfo) { $0.alert } + .alert(item: $context.alertInfo) .alert(item: $context.leaveRoomAlertItem, actions: leaveRoomAlertActions, message: leaveRoomAlertMessage) diff --git a/ElementX/Sources/Screens/InviteUsersScreen/View/InviteUsersScreen.swift b/ElementX/Sources/Screens/InviteUsersScreen/View/InviteUsersScreen.swift index 71229b039..fe4bf329d 100644 --- a/ElementX/Sources/Screens/InviteUsersScreen/View/InviteUsersScreen.swift +++ b/ElementX/Sources/Screens/InviteUsersScreen/View/InviteUsersScreen.swift @@ -38,7 +38,7 @@ struct InviteUsersScreen: View { searchViewController.hidesNavigationBarDuringPresentation = false } .compoundSearchField() - .alert(item: $context.alertInfo) { $0.alert } + .alert(item: $context.alertInfo) .background(ViewFrameReader(frame: $frame)) } diff --git a/ElementX/Sources/Screens/InvitesScreen/View/InvitesScreen.swift b/ElementX/Sources/Screens/InvitesScreen/View/InvitesScreen.swift index cda933b26..7fbabdf40 100644 --- a/ElementX/Sources/Screens/InvitesScreen/View/InvitesScreen.swift +++ b/ElementX/Sources/Screens/InvitesScreen/View/InvitesScreen.swift @@ -36,7 +36,7 @@ struct InvitesScreen: View { } .background(Color.element.background.ignoresSafeArea()) .navigationTitle(L10n.actionInvitesList) - .alert(item: $context.alertInfo) { $0.alert } + .alert(item: $context.alertInfo) } // MARK: - Private diff --git a/ElementX/Sources/Screens/LocationSharing/LocationSharingScreenModels.swift b/ElementX/Sources/Screens/LocationSharing/LocationSharingScreenModels.swift index d67319f87..c58b1dca6 100644 --- a/ElementX/Sources/Screens/LocationSharing/LocationSharingScreenModels.swift +++ b/ElementX/Sources/Screens/LocationSharing/LocationSharingScreenModels.swift @@ -16,7 +16,7 @@ import Foundation -enum LocationSharingViewError: Error { +enum LocationSharingViewError: Error, Hashable { case failedSharingLocation case mapError(MapLibreError) } @@ -31,15 +31,18 @@ struct StaticLocationScreenBindings { /// Information describing the currently displayed alert. var mapError: MapLibreError? { get { - errorAlert?.error as? MapLibreError + if case let .mapError(error) = alertInfo?.id { + return error + } + return nil } set { - errorAlert = newValue.map { ErrorAlertItem(error: $0) } + alertInfo = newValue.map { AlertInfo(id: .mapError($0)) } } } /// Information describing the currently displayed alert. - var errorAlert: ErrorAlertItem? + var alertInfo: AlertInfo? } enum StaticLocationScreenViewAction { } diff --git a/ElementX/Sources/Screens/LocationSharing/View/StaticLocationScreen.swift b/ElementX/Sources/Screens/LocationSharing/View/StaticLocationScreen.swift index 16482cb6e..d13d74082 100644 --- a/ElementX/Sources/Screens/LocationSharing/View/StaticLocationScreen.swift +++ b/ElementX/Sources/Screens/LocationSharing/View/StaticLocationScreen.swift @@ -26,7 +26,7 @@ struct StaticLocationScreen: View { mapView .ignoresSafeArea(.all, edges: [.bottom]) .navigationBarTitleDisplayMode(.inline) - .errorAlert(item: $context.errorAlert) + .alert(item: $context.alertInfo) } } diff --git a/ElementX/Sources/Screens/RoomDetailsScreen/RoomDetailsScreenModels.swift b/ElementX/Sources/Screens/RoomDetailsScreen/RoomDetailsScreenModels.swift index 34e1b5813..9f4d60a0b 100644 --- a/ElementX/Sources/Screens/RoomDetailsScreen/RoomDetailsScreenModels.swift +++ b/ElementX/Sources/Screens/RoomDetailsScreen/RoomDetailsScreenModels.swift @@ -61,7 +61,7 @@ struct RoomDetailsScreenViewState: BindableState { } struct RoomDetailsScreenViewStateBindings { - struct IgnoreUserAlertItem: AlertItem, Equatable { + struct IgnoreUserAlertItem: AlertProtocol, Equatable { enum Action { case ignore case unignore @@ -105,7 +105,7 @@ struct RoomDetailsScreenViewStateBindings { var ignoreUserRoomAlertItem: IgnoreUserAlertItem? } -struct LeaveRoomAlertItem: AlertItem { +struct LeaveRoomAlertItem: AlertProtocol { enum RoomState { case empty case `public` diff --git a/ElementX/Sources/Screens/RoomDetailsScreen/View/RoomDetailsScreen.swift b/ElementX/Sources/Screens/RoomDetailsScreen/View/RoomDetailsScreen.swift index fa1b5dee0..e34bd9c38 100644 --- a/ElementX/Sources/Screens/RoomDetailsScreen/View/RoomDetailsScreen.swift +++ b/ElementX/Sources/Screens/RoomDetailsScreen/View/RoomDetailsScreen.swift @@ -42,7 +42,7 @@ struct RoomDetailsScreen: View { } } .elementFormStyle() - .alert(item: $context.alertInfo) { $0.alert } + .alert(item: $context.alertInfo) .alert(item: $context.leaveRoomAlertItem, actions: leaveRoomAlertActions, message: leaveRoomAlertMessage) diff --git a/ElementX/Sources/Screens/RoomMemberDetailsScreen/RoomMemberDetailsScreenModels.swift b/ElementX/Sources/Screens/RoomMemberDetailsScreen/RoomMemberDetailsScreenModels.swift index ef07ac2dd..8232f98a2 100644 --- a/ElementX/Sources/Screens/RoomMemberDetailsScreen/RoomMemberDetailsScreenModels.swift +++ b/ElementX/Sources/Screens/RoomMemberDetailsScreen/RoomMemberDetailsScreenModels.swift @@ -26,7 +26,7 @@ struct RoomMemberDetailsScreenViewState: BindableState { } struct RoomMemberDetailsScreenViewStateBindings { - struct IgnoreUserAlertItem: AlertItem, Equatable { + struct IgnoreUserAlertItem: AlertProtocol, Equatable { enum Action { case ignore case unignore @@ -65,7 +65,7 @@ struct RoomMemberDetailsScreenViewStateBindings { } var ignoreUserAlert: IgnoreUserAlertItem? - var errorAlert: ErrorAlertItem? + var alertInfo: AlertInfo? } enum RoomMemberDetailsScreenViewAction { @@ -74,3 +74,8 @@ enum RoomMemberDetailsScreenViewAction { case ignoreConfirmed case unignoreConfirmed } + +enum RoomMemberDetailsScreenError: Hashable { + case alert(String) + case unknown +} diff --git a/ElementX/Sources/Screens/RoomMemberDetailsScreen/RoomMemberDetailsScreenViewModel.swift b/ElementX/Sources/Screens/RoomMemberDetailsScreen/RoomMemberDetailsScreenViewModel.swift index f89f6ad71..6b825cd71 100644 --- a/ElementX/Sources/Screens/RoomMemberDetailsScreen/RoomMemberDetailsScreenViewModel.swift +++ b/ElementX/Sources/Screens/RoomMemberDetailsScreen/RoomMemberDetailsScreenViewModel.swift @@ -55,8 +55,8 @@ class RoomMemberDetailsScreenViewModel: RoomMemberDetailsScreenViewModelType, Ro switch result { case .success: state.details.isIgnored = true - case .failure(let error): - state.bindings.errorAlert = .init(error: error) + case .failure: + state.bindings.alertInfo = .init(id: .unknown) } } @@ -68,8 +68,8 @@ class RoomMemberDetailsScreenViewModel: RoomMemberDetailsScreenViewModelType, Ro switch result { case .success: state.details.isIgnored = false - case .failure(let error): - state.bindings.errorAlert = .init(error: error) + case .failure: + state.bindings.alertInfo = .init(id: .unknown) } } } diff --git a/ElementX/Sources/Screens/RoomMemberDetailsScreen/View/RoomMemberDetailsScreen.swift b/ElementX/Sources/Screens/RoomMemberDetailsScreen/View/RoomMemberDetailsScreen.swift index 4a3f46c2d..4cbb7e5af 100644 --- a/ElementX/Sources/Screens/RoomMemberDetailsScreen/View/RoomMemberDetailsScreen.swift +++ b/ElementX/Sources/Screens/RoomMemberDetailsScreen/View/RoomMemberDetailsScreen.swift @@ -29,7 +29,7 @@ struct RoomMemberDetailsScreen: View { } .elementFormStyle() .alert(item: $context.ignoreUserAlert, actions: blockUserAlertActions, message: blockUserAlertMessage) - .errorAlert(item: $context.errorAlert) + .alert(item: $context.alertInfo) } // MARK: - Private diff --git a/ElementX/Sources/Screens/RoomMemberListScreen/View/RoomMembersListScreen.swift b/ElementX/Sources/Screens/RoomMemberListScreen/View/RoomMembersListScreen.swift index a4cdd47e2..e93b547d5 100644 --- a/ElementX/Sources/Screens/RoomMemberListScreen/View/RoomMembersListScreen.swift +++ b/ElementX/Sources/Screens/RoomMemberListScreen/View/RoomMembersListScreen.swift @@ -33,7 +33,7 @@ struct RoomMembersListScreen: View { .compoundSearchField() .background(Color.element.background.ignoresSafeArea()) .navigationTitle(L10n.commonPeople) - .alert(item: $context.alertInfo) { $0.alert } + .alert(item: $context.alertInfo) .toolbar { ToolbarItem(placement: .confirmationAction) { inviteButton diff --git a/ElementX/Sources/Screens/RoomScreen/View/RoomScreen.swift b/ElementX/Sources/Screens/RoomScreen/View/RoomScreen.swift index f347f80e1..ddc548de0 100644 --- a/ElementX/Sources/Screens/RoomScreen/View/RoomScreen.swift +++ b/ElementX/Sources/Screens/RoomScreen/View/RoomScreen.swift @@ -37,7 +37,7 @@ struct RoomScreen: View { .toolbar { toolbar } .toolbarBackground(.visible, for: .navigationBar) // Fix the toolbar's background. .overlay { loadingIndicator } - .alert(item: $context.alertInfo) { $0.alert } + .alert(item: $context.alertInfo) .sheet(item: $context.debugInfo) { TimelineItemDebugView(info: $0) } .sheet(item: $context.actionMenuInfo) { info in context.viewState.timelineItemMenuActionProvider?(info.item.id).map { actions in diff --git a/ElementX/Sources/Screens/StartChatScreen/View/StartChatScreen.swift b/ElementX/Sources/Screens/StartChatScreen/View/StartChatScreen.swift index 261a4e821..fa6018456 100644 --- a/ElementX/Sources/Screens/StartChatScreen/View/StartChatScreen.swift +++ b/ElementX/Sources/Screens/StartChatScreen/View/StartChatScreen.swift @@ -41,7 +41,7 @@ struct StartChatScreen: View { .dismissSearchOnDisappear() .searchable(text: $context.searchQuery, placement: .navigationBarDrawer(displayMode: .always), prompt: L10n.commonSearchForSomeone) .compoundSearchField() - .alert(item: $context.alertInfo) { $0.alert } + .alert(item: $context.alertInfo) } // MARK: - Private diff --git a/UnitTests/Sources/RoomMemberDetailsViewModelTests.swift b/UnitTests/Sources/RoomMemberDetailsViewModelTests.swift index b73b6be5e..25cc44fff 100644 --- a/UnitTests/Sources/RoomMemberDetailsViewModelTests.swift +++ b/UnitTests/Sources/RoomMemberDetailsViewModelTests.swift @@ -30,7 +30,7 @@ class RoomMemberDetailsViewModelTests: XCTestCase { XCTAssertEqual(context.viewState.details, RoomMemberDetails(withProxy: roomMemberProxyMock)) XCTAssertNil(context.ignoreUserAlert) - XCTAssertNil(context.errorAlert) + XCTAssertNil(context.alertInfo) } func testIgnoreSuccess() async throws { @@ -73,7 +73,7 @@ class RoomMemberDetailsViewModelTests: XCTestCase { _ = await context.$viewState.values.first { $0.isProcessingIgnoreRequest == false } XCTAssertFalse(context.viewState.isProcessingIgnoreRequest) - XCTAssertNotNil(context.errorAlert) + XCTAssertNotNil(context.alertInfo) XCTAssertFalse(context.viewState.details.isIgnored) } @@ -119,7 +119,7 @@ class RoomMemberDetailsViewModelTests: XCTestCase { _ = await context.$viewState.values.first { $0.isProcessingIgnoreRequest == false } XCTAssertFalse(context.viewState.isProcessingIgnoreRequest) XCTAssertTrue(context.viewState.details.isIgnored) - XCTAssertNotNil(context.errorAlert) + XCTAssertNotNil(context.alertInfo) } func testInitialStateAccountOwner() async { @@ -128,7 +128,7 @@ class RoomMemberDetailsViewModelTests: XCTestCase { XCTAssertEqual(context.viewState.details, RoomMemberDetails(withProxy: roomMemberProxyMock)) XCTAssertNil(context.ignoreUserAlert) - XCTAssertNil(context.errorAlert) + XCTAssertNil(context.alertInfo) } func testInitialStateIgnoredUser() async { @@ -137,6 +137,6 @@ class RoomMemberDetailsViewModelTests: XCTestCase { XCTAssertEqual(context.viewState.details, RoomMemberDetails(withProxy: roomMemberProxyMock)) XCTAssertNil(context.ignoreUserAlert) - XCTAssertNil(context.errorAlert) + XCTAssertNil(context.alertInfo) } } diff --git a/changelog.d/1067.change b/changelog.d/1067.change new file mode 100644 index 000000000..1b3e24d4f --- /dev/null +++ b/changelog.d/1067.change @@ -0,0 +1 @@ +Refactored AlertInfo to not use the soon to be deprecated API for alerts anymore. \ No newline at end of file