Skip to content

Commit

Permalink
New loading indicators when creating a room
Browse files Browse the repository at this point in the history
  • Loading branch information
Anderas committed Mar 29, 2022
1 parent 92b31a0 commit 8aa0191
Show file tree
Hide file tree
Showing 10 changed files with 55 additions and 80 deletions.
1 change: 1 addition & 0 deletions Riot/Assets/en.lproj/Vector.strings
Original file line number Diff line number Diff line change
Expand Up @@ -1767,6 +1767,7 @@ Tap the + to start adding people.";
"create_room_placeholder_address" = "#testroom:matrix.org";
"create_room_suggest_room" = "Suggest to space members";
"create_room_suggest_room_footer" = "Suggested rooms are promoted to space members as good to join.";
"create_room_processing" = "Creating room";

// MARK: - Room Info

Expand Down
4 changes: 4 additions & 0 deletions Riot/Generated/Strings.swift
Original file line number Diff line number Diff line change
Expand Up @@ -935,6 +935,10 @@ public class VectorL10n: NSObject {
public static var createRoomPlaceholderTopic: String {
return VectorL10n.tr("Vector", "create_room_placeholder_topic")
}
/// Creating room
public static var createRoomProcessing: String {
return VectorL10n.tr("Vector", "create_room_processing")
}
/// PROMOTION
public static var createRoomPromotionHeader: String {
return VectorL10n.tr("Vector", "create_room_promotion_header")
Expand Down

This file was deleted.

7 changes: 4 additions & 3 deletions Riot/Modules/Common/Recents/RecentsViewController.h
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -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
Expand Down
32 changes: 21 additions & 11 deletions Riot/Modules/Common/Recents/RecentsViewController.m
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,9 @@ @interface RecentsViewController () <CreateRoomCoordinatorBridgePresenterDelegat

// 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;
Expand Down Expand Up @@ -1305,7 +1308,7 @@ - (void)leaveEditedRoom
{
typeof(self) self = weakSelf;
[self stopActivityIndicator];
[self.indicatorPresenter presentSuccessWithLabel:[VectorL10n roomParticipantsLeaveSuccess]];
[self.userIndicatorStore presentSuccessWithLabel:[VectorL10n roomParticipantsLeaveSuccess]];
// Force table refresh
[self cancelEditionMode:YES];
}
Expand Down Expand Up @@ -2450,28 +2453,35 @@ - (void)spaceChildRoomDetailBridgePresenter:(SpaceChildRoomDetailBridgePresenter
#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 indiciators 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];
}
Expand Down
12 changes: 10 additions & 2 deletions Riot/Modules/Common/UserIndicators/UserIndicatorStore.swift
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand All @@ -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)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
*/

import UIKit
import CommonKit

final class EnterNewRoomDetailsViewController: UIViewController {

Expand Down Expand Up @@ -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 {
Expand Down Expand Up @@ -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()
Expand Down Expand Up @@ -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)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -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 {
Expand Down
8 changes: 4 additions & 4 deletions Riot/Modules/TabBar/TabBarCoordinator.swift
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -249,23 +249,23 @@ 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
}

private func createPeopleViewController() -> PeopleViewController {
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
}

private func createRoomsViewController() -> RoomsViewController {
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
}

Expand Down
1 change: 1 addition & 0 deletions changelog.d/5606.change
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Room: New loading indicators when creating a room

0 comments on commit 8aa0191

Please sign in to comment.