mirror of
https://gitlab.opencode.de/bwi/bundesmessenger/clients/bundesmessenger-ios.git
synced 2026-04-25 02:52:45 +02:00
Merge pull request #5946 from vector-im/andy/5606_create_indicators
New loading indicators when creating a room
This commit is contained in:
@@ -1,56 +0,0 @@
|
||||
//
|
||||
// Copyright 2021 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 Foundation
|
||||
import CommonKit
|
||||
|
||||
/// A convenience objc-compatible wrapper around `UserIndicatorTypePresenterProtocol`.
|
||||
///
|
||||
/// This class wraps swift-only protocol by exposing multiple methods instead of accepting struct types
|
||||
/// and it keeps a track of `UserIndicator`s instead of returning them to the caller.
|
||||
@objc final class UserIndicatorPresenterWrapper: NSObject {
|
||||
private let presenter: UserIndicatorTypePresenterProtocol
|
||||
private var loadingIndicator: UserIndicator?
|
||||
private var otherIndicators = [UserIndicator]()
|
||||
|
||||
init(presenter: UserIndicatorTypePresenterProtocol) {
|
||||
self.presenter = presenter
|
||||
}
|
||||
|
||||
@objc func presentLoadingIndicator() {
|
||||
presentLoadingIndicator(label: VectorL10n.homeSyncing)
|
||||
}
|
||||
|
||||
@objc func presentLoadingIndicator(label: String) {
|
||||
guard loadingIndicator == nil else {
|
||||
// The app is very liberal with calling `presentLoadingIndicator` (often not matched by corresponding `dismissLoadingIndicator`),
|
||||
// so there is no reason to keep adding new indiciators if there is one already showing.
|
||||
return
|
||||
}
|
||||
|
||||
MXLog.debug("[UserIndicatorPresenterWrapper] Present loading indicator")
|
||||
loadingIndicator = presenter.present(.loading(label: label, isInteractionBlocking: false))
|
||||
}
|
||||
|
||||
@objc func dismissLoadingIndicator() {
|
||||
MXLog.debug("[UserIndicatorPresenterWrapper] Dismiss loading indicator")
|
||||
loadingIndicator = nil
|
||||
}
|
||||
|
||||
@objc func presentSuccess(label: String) {
|
||||
presenter.present(.success(label: label)).store(in: &otherIndicators)
|
||||
}
|
||||
}
|
||||
@@ -19,7 +19,7 @@
|
||||
|
||||
@class RootTabEmptyView;
|
||||
@class AnalyticsScreenTracker;
|
||||
@class UserIndicatorPresenterWrapper;
|
||||
@class UserIndicatorStore;
|
||||
|
||||
/**
|
||||
Notification to be posted when recents data is ready. Notification object will be the RecentsViewController instance.
|
||||
@@ -98,9 +98,10 @@ FOUNDATION_EXPORT NSString *const RecentsViewControllerDataReadyNotification;
|
||||
@property (nonatomic) AnalyticsScreenTracker *screenTracker;
|
||||
|
||||
/**
|
||||
Presenter for displaying app-wide user indicators. If not set, the view controller will use legacy activity indicators
|
||||
A store of user indicators that lets the room present and dismiss indicators without
|
||||
worrying about the presentation context or memory management.
|
||||
*/
|
||||
@property (nonatomic, strong) UserIndicatorPresenterWrapper *indicatorPresenter;
|
||||
@property (nonatomic, strong) UserIndicatorStore *userIndicatorStore;
|
||||
|
||||
/**
|
||||
Return the sticky header for the specified section of the table view
|
||||
|
||||
@@ -69,6 +69,9 @@ NSString *const RecentsViewControllerDataReadyNotification = @"RecentsViewContro
|
||||
|
||||
// Observe kThemeServiceDidChangeThemeNotification to handle user interface theme change.
|
||||
__weak id kThemeServiceDidChangeThemeNotificationObserver;
|
||||
|
||||
// Cancel handler of any ongoing loading indicator
|
||||
UserIndicatorCancel loadingIndicatorCancel;
|
||||
}
|
||||
|
||||
@property (nonatomic, strong) CreateRoomCoordinatorBridgePresenter *createRoomCoordinatorBridgePresenter;
|
||||
@@ -1305,7 +1308,7 @@ NSString *const RecentsViewControllerDataReadyNotification = @"RecentsViewContro
|
||||
{
|
||||
typeof(self) self = weakSelf;
|
||||
[self stopActivityIndicator];
|
||||
[self.indicatorPresenter presentSuccessWithLabel:[VectorL10n roomParticipantsLeaveSuccess]];
|
||||
[self.userIndicatorStore presentSuccessWithLabel:[VectorL10n roomParticipantsLeaveSuccess]];
|
||||
// Force table refresh
|
||||
[self cancelEditionMode:YES];
|
||||
}
|
||||
@@ -2450,28 +2453,35 @@ NSString *const RecentsViewControllerDataReadyNotification = @"RecentsViewContro
|
||||
#pragma mark - Activity Indicator
|
||||
|
||||
- (BOOL)providesCustomActivityIndicator {
|
||||
return self.indicatorPresenter != nil;
|
||||
return self.userIndicatorStore != nil;
|
||||
}
|
||||
|
||||
- (void)startActivityIndicatorWithLabel:(NSString *)label {
|
||||
if (self.indicatorPresenter && isViewVisible) {
|
||||
[self.indicatorPresenter presentLoadingIndicatorWithLabel:label];
|
||||
if (self.userIndicatorStore && isViewVisible) {
|
||||
// The app is very liberal with calling `startActivityIndicator` (often not matched by corresponding `stopActivityIndicator`),
|
||||
// so there is no reason to keep adding new indicators if there is one already showing.
|
||||
if (loadingIndicatorCancel) {
|
||||
return;
|
||||
}
|
||||
|
||||
MXLogDebug(@"[RecentsViewController] Present loading indicator")
|
||||
loadingIndicatorCancel = [self.userIndicatorStore presentLoadingWithLabel:label isInteractionBlocking:NO];
|
||||
} else {
|
||||
[super startActivityIndicator];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)startActivityIndicator {
|
||||
if (self.indicatorPresenter && isViewVisible) {
|
||||
[self.indicatorPresenter presentLoadingIndicator];
|
||||
} else {
|
||||
[super startActivityIndicator];
|
||||
}
|
||||
[self startActivityIndicatorWithLabel:[VectorL10n homeSyncing]];
|
||||
}
|
||||
|
||||
- (void)stopActivityIndicator {
|
||||
if (self.indicatorPresenter) {
|
||||
[self.indicatorPresenter dismissLoadingIndicator];
|
||||
if (self.userIndicatorStore) {
|
||||
if (loadingIndicatorCancel) {
|
||||
MXLogDebug(@"[RecentsViewController] Present loading indicator")
|
||||
loadingIndicatorCancel();
|
||||
loadingIndicatorCancel = nil;
|
||||
}
|
||||
} else {
|
||||
[super stopActivityIndicator];
|
||||
}
|
||||
|
||||
@@ -39,8 +39,8 @@ import CommonKit
|
||||
}
|
||||
}
|
||||
|
||||
/// Present a new type of user indicator, such as loading spinner or success message.
|
||||
/// To remove an indicator, call the returned `UserIndicatorCancel` function
|
||||
/// Present a loading indicator.
|
||||
/// To remove the indicator call the returned `UserIndicatorCancel` function
|
||||
///
|
||||
/// Note: This is a convenience function callable by objective-c code
|
||||
@objc func presentLoading(label: String, isInteractionBlocking: Bool) -> UserIndicatorCancel {
|
||||
@@ -51,4 +51,12 @@ import CommonKit
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
/// Present a success message that will be automatically dismissed after a few seconds.
|
||||
///
|
||||
/// Note: This is a convenience function callable by objective-c code
|
||||
@objc func presentSuccess(label: String) {
|
||||
let indicator = presenter.present(.success(label: label))
|
||||
indicators.append(indicator)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
*/
|
||||
|
||||
import UIKit
|
||||
import CommonKit
|
||||
|
||||
final class EnterNewRoomDetailsViewController: UIViewController {
|
||||
|
||||
@@ -47,7 +48,9 @@ final class EnterNewRoomDetailsViewController: UIViewController {
|
||||
private var theme: Theme!
|
||||
private var keyboardAvoider: KeyboardAvoider?
|
||||
private var errorPresenter: MXKErrorPresentation!
|
||||
private var activityPresenter: ActivityIndicatorPresenter!
|
||||
private var userIndicatorPresenter: UserIndicatorTypePresenterProtocol!
|
||||
private var loadingIndicator: UserIndicator?
|
||||
|
||||
private lazy var createBarButtonItem: MXKBarButtonItem = {
|
||||
let title: String
|
||||
switch viewModel.actionType {
|
||||
@@ -262,7 +265,7 @@ final class EnterNewRoomDetailsViewController: UIViewController {
|
||||
|
||||
self.setupViews()
|
||||
self.keyboardAvoider = KeyboardAvoider(scrollViewContainerView: self.view, scrollView: self.mainTableView)
|
||||
self.activityPresenter = ActivityIndicatorPresenter()
|
||||
self.userIndicatorPresenter = UserIndicatorTypePresenter(presentingViewController: self)
|
||||
self.errorPresenter = MXKErrorAlertPresentation()
|
||||
|
||||
self.registerThemeServiceDidChangeThemeNotification()
|
||||
@@ -352,11 +355,11 @@ final class EnterNewRoomDetailsViewController: UIViewController {
|
||||
}
|
||||
|
||||
private func renderLoading() {
|
||||
self.activityPresenter.presentActivityIndicator(on: self.view, animated: true)
|
||||
loadingIndicator = userIndicatorPresenter.present(.loading(label: VectorL10n.createRoomProcessing, isInteractionBlocking: true))
|
||||
}
|
||||
|
||||
private func render(error: Error) {
|
||||
self.activityPresenter.removeCurrentActivityIndicator(animated: true)
|
||||
loadingIndicator = nil
|
||||
self.errorPresenter.presentError(from: self, forError: error, animated: true, handler: nil)
|
||||
}
|
||||
|
||||
|
||||
@@ -115,6 +115,7 @@ final class EnterNewRoomDetailsViewModel: EnterNewRoomDetailsViewModelType {
|
||||
fatalError("[EnterNewRoomDetailsViewModel] createRoom: room name cannot be nil.")
|
||||
}
|
||||
|
||||
viewState = .loading
|
||||
currentOperation = session.createRoom(
|
||||
withName: roomName,
|
||||
joinRule: roomCreationParameters.joinRule,
|
||||
@@ -125,6 +126,8 @@ final class EnterNewRoomDetailsViewModel: EnterNewRoomDetailsViewModelType {
|
||||
completion: { response in
|
||||
switch response {
|
||||
case .success(let room):
|
||||
self.viewState = .loaded
|
||||
|
||||
if let parentSpace = self.parentSpace {
|
||||
self.add(room, to: parentSpace)
|
||||
} else {
|
||||
|
||||
@@ -239,7 +239,7 @@ final class TabBarCoordinator: NSObject, TabBarCoordinatorType {
|
||||
homeViewController.tabBarItem.tag = Int(TABBAR_HOME_INDEX)
|
||||
homeViewController.tabBarItem.image = homeViewController.tabBarItem.image
|
||||
homeViewController.accessibilityLabel = VectorL10n.titleHome
|
||||
homeViewController.indicatorPresenter = UserIndicatorPresenterWrapper(presenter: indicatorPresenter)
|
||||
homeViewController.userIndicatorStore = UserIndicatorStore(presenter: indicatorPresenter)
|
||||
|
||||
let wrapperViewController = HomeViewControllerWithBannerWrapperViewController(viewController: homeViewController)
|
||||
return wrapperViewController
|
||||
@@ -249,7 +249,7 @@ final class TabBarCoordinator: NSObject, TabBarCoordinatorType {
|
||||
let favouritesViewController: FavouritesViewController = FavouritesViewController.instantiate()
|
||||
favouritesViewController.tabBarItem.tag = Int(TABBAR_FAVOURITES_INDEX)
|
||||
favouritesViewController.accessibilityLabel = VectorL10n.titleFavourites
|
||||
favouritesViewController.indicatorPresenter = UserIndicatorPresenterWrapper(presenter: indicatorPresenter)
|
||||
favouritesViewController.userIndicatorStore = UserIndicatorStore(presenter: indicatorPresenter)
|
||||
return favouritesViewController
|
||||
}
|
||||
|
||||
@@ -257,7 +257,7 @@ final class TabBarCoordinator: NSObject, TabBarCoordinatorType {
|
||||
let peopleViewController: PeopleViewController = PeopleViewController.instantiate()
|
||||
peopleViewController.tabBarItem.tag = Int(TABBAR_PEOPLE_INDEX)
|
||||
peopleViewController.accessibilityLabel = VectorL10n.titlePeople
|
||||
peopleViewController.indicatorPresenter = UserIndicatorPresenterWrapper(presenter: indicatorPresenter)
|
||||
peopleViewController.userIndicatorStore = UserIndicatorStore(presenter: indicatorPresenter)
|
||||
return peopleViewController
|
||||
}
|
||||
|
||||
@@ -265,7 +265,7 @@ final class TabBarCoordinator: NSObject, TabBarCoordinatorType {
|
||||
let roomsViewController: RoomsViewController = RoomsViewController.instantiate()
|
||||
roomsViewController.tabBarItem.tag = Int(TABBAR_ROOMS_INDEX)
|
||||
roomsViewController.accessibilityLabel = VectorL10n.titleRooms
|
||||
roomsViewController.indicatorPresenter = UserIndicatorPresenterWrapper(presenter: indicatorPresenter)
|
||||
roomsViewController.userIndicatorStore = UserIndicatorStore(presenter: indicatorPresenter)
|
||||
return roomsViewController
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user