From 807c97d076f3718b7b2f9706263e30ef0b180953 Mon Sep 17 00:00:00 2001 From: Gil Eluard Date: Wed, 23 Mar 2022 10:58:41 +0100 Subject: [PATCH] Update suggested room preview to behave the same way in all cases #5771 - Done --- .../Common/Recents/RecentsViewController.m | 34 ++++-- Riot/Modules/Home/HomeViewController.m | 3 +- .../Controllers/MXKRecentListViewController.h | 3 +- .../Controllers/MXKRecentListViewController.m | 3 +- .../SpaceChildRoomDetailBridgePresenter.swift | 113 ++++++++++++++++++ changelog.d/5771.change | 2 + 6 files changed, 145 insertions(+), 13 deletions(-) create mode 100644 Riot/Modules/Spaces/SpaceRoomList/SpaceChildRoomDetail/SpaceChildRoomDetailBridgePresenter.swift create mode 100644 changelog.d/5771.change diff --git a/Riot/Modules/Common/Recents/RecentsViewController.m b/Riot/Modules/Common/Recents/RecentsViewController.m index 0c731f723..a6a59f00c 100644 --- a/Riot/Modules/Common/Recents/RecentsViewController.m +++ b/Riot/Modules/Common/Recents/RecentsViewController.m @@ -36,7 +36,7 @@ NSString *const RecentsViewControllerDataReadyNotification = @"RecentsViewControllerDataReadyNotification"; -@interface RecentsViewController () +@interface RecentsViewController () { // Tell whether a recents refresh is pending (suspended during editing mode). BOOL isRefreshPending; @@ -83,6 +83,8 @@ NSString *const RecentsViewControllerDataReadyNotification = @"RecentsViewContro @property (nonatomic, strong) RoomNotificationSettingsCoordinatorBridgePresenter *roomNotificationSettingsCoordinatorBridgePresenter; +@property (nonatomic, strong) SpaceChildRoomDetailBridgePresenter *spaceChildPresenter; + @end @implementation RecentsViewController @@ -2171,18 +2173,13 @@ NSString *const RecentsViewControllerDataReadyNotification = @"RecentsViewContro [self showRoomWithRoomId:roomId inMatrixSession:matrixSession]; } -- (void)recentListViewController:(MXKRecentListViewController *)recentListViewController didSelectSuggestedRoom:(MXSpaceChildInfo *)childInfo +- (void)recentListViewController:(MXKRecentListViewController *)recentListViewController didSelectSuggestedRoom:(MXSpaceChildInfo *)childInfo from:(UIView* _Nullable)sourceView { Analytics.shared.joinedRoomTrigger = AnalyticsJoinedRoomTriggerSpaceHierarchy; - RoomPreviewData *previewData = [[RoomPreviewData alloc] initWithSpaceChildInfo:childInfo andSession:self.mainSession]; - [self startActivityIndicator]; - MXWeakify(self); - [previewData peekInRoom:^(BOOL succeeded) { - MXStrongifyAndReturnIfNil(self); - [self stopActivityIndicator]; - [self showRoomPreviewWithData:previewData]; - }]; + self.spaceChildPresenter = [[SpaceChildRoomDetailBridgePresenter alloc] initWithSession:self.mainSession childInfo:childInfo]; + self.spaceChildPresenter.delegate = self; + [self.spaceChildPresenter presentFrom:self sourceView:sourceView animated:YES]; } #pragma mark - UISearchBarDelegate @@ -2433,6 +2430,23 @@ NSString *const RecentsViewControllerDataReadyNotification = @"RecentsViewContro self.roomNotificationSettingsCoordinatorBridgePresenter = nil; } +#pragma mark - SpaceChildRoomDetailBridgePresenterDelegate +- (void)spaceChildRoomDetailBridgePresenterDidCancel:(SpaceChildRoomDetailBridgePresenter *)coordinator +{ + [self.spaceChildPresenter dismissWithAnimated:YES completion:^{ + self.spaceChildPresenter = nil; + }]; +} + +- (void)spaceChildRoomDetailBridgePresenter:(SpaceChildRoomDetailBridgePresenter *)coordinator didOpenRoomWith:(NSString *)roomId +{ + [self showRoomWithRoomId:roomId inMatrixSession:self.mainSession]; + + [self.spaceChildPresenter dismissWithAnimated:YES completion:^{ + self.spaceChildPresenter = nil; + }]; +} + #pragma mark - Activity Indicator - (BOOL)providesCustomActivityIndicator { diff --git a/Riot/Modules/Home/HomeViewController.m b/Riot/Modules/Home/HomeViewController.m index 77fd9f012..bf4c0d3af 100644 --- a/Riot/Modules/Home/HomeViewController.m +++ b/Riot/Modules/Home/HomeViewController.m @@ -605,7 +605,8 @@ if (renderedCellData.isSuggestedRoom) { [self.delegate recentListViewController:self - didSelectSuggestedRoom:renderedCellData.roomSummary.spaceChildInfo]; + didSelectSuggestedRoom:renderedCellData.roomSummary.spaceChildInfo + from:roomCollectionViewCell]; } else { diff --git a/Riot/Modules/MatrixKit/Controllers/MXKRecentListViewController.h b/Riot/Modules/MatrixKit/Controllers/MXKRecentListViewController.h index da8d193f3..5e064d295 100644 --- a/Riot/Modules/MatrixKit/Controllers/MXKRecentListViewController.h +++ b/Riot/Modules/MatrixKit/Controllers/MXKRecentListViewController.h @@ -41,8 +41,9 @@ limitations under the License. @param recentListViewController the `MXKRecentListViewController` instance. @param childInfo the `MXSpaceChildInfo` instance that describes the selected room. + @param sourceView the view the modal has to be presented from. */ --(void)recentListViewController:(MXKRecentListViewController *)recentListViewController didSelectSuggestedRoom:(MXSpaceChildInfo *)childInfo; +-(void)recentListViewController:(MXKRecentListViewController *)recentListViewController didSelectSuggestedRoom:(MXSpaceChildInfo *)childInfo from:(UIView* _Nullable)sourceView; @end diff --git a/Riot/Modules/MatrixKit/Controllers/MXKRecentListViewController.m b/Riot/Modules/MatrixKit/Controllers/MXKRecentListViewController.m index 7285ef564..43c112efd 100644 --- a/Riot/Modules/MatrixKit/Controllers/MXKRecentListViewController.m +++ b/Riot/Modules/MatrixKit/Controllers/MXKRecentListViewController.m @@ -442,7 +442,8 @@ if (recentCellData.isSuggestedRoom) { [_delegate recentListViewController:self - didSelectSuggestedRoom:recentCellData.roomSummary.spaceChildInfo]; + didSelectSuggestedRoom:recentCellData.roomSummary.spaceChildInfo + from:selectedCell]; } else { diff --git a/Riot/Modules/Spaces/SpaceRoomList/SpaceChildRoomDetail/SpaceChildRoomDetailBridgePresenter.swift b/Riot/Modules/Spaces/SpaceRoomList/SpaceChildRoomDetail/SpaceChildRoomDetailBridgePresenter.swift new file mode 100644 index 000000000..8691c7597 --- /dev/null +++ b/Riot/Modules/Spaces/SpaceRoomList/SpaceChildRoomDetail/SpaceChildRoomDetailBridgePresenter.swift @@ -0,0 +1,113 @@ +/* + 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 + +@objc protocol SpaceChildRoomDetailBridgePresenterDelegate { + func spaceChildRoomDetailBridgePresenter(_ coordinator: SpaceChildRoomDetailBridgePresenter, didOpenRoomWith roomId: String) + func spaceChildRoomDetailBridgePresenterDidCancel(_ coordinator: SpaceChildRoomDetailBridgePresenter) +} + +/// SpaceChildRoomDetailBridgePresenter enables to start SpaceChildRoomDetailCoordinator from a view controller. +/// This bridge is used while waiting for global usage of coordinator pattern. +/// It breaks the Coordinator abstraction and it has been introduced for Objective-C compatibility (mainly for integration in legacy view controllers). Each bridge should be removed once the underlying Coordinator has +/// been integrated by another Coordinator. +@objcMembers +final class SpaceChildRoomDetailBridgePresenter: NSObject { + + // MARK: - Properties + + // MARK: Private + + private let session: MXSession + private let childInfo: MXSpaceChildInfo + private var coordinator: SpaceChildRoomDetailCoordinator? + private lazy var slidingModalPresenter: SlidingModalPresenter = { + return SlidingModalPresenter() + }() + + // MARK: Public + + weak var delegate: SpaceChildRoomDetailBridgePresenterDelegate? + + // MARK: - Setup + + init(session: MXSession, childInfo: MXSpaceChildInfo) { + self.session = session + self.childInfo = childInfo + super.init() + } + + // MARK: - Public + + // NOTE: Default value feature is not compatible with Objective-C. + // func present(from viewController: UIViewController, animated: Bool) { + // self.present(from: viewController, animated: animated) + // } + + func present(from viewController: UIViewController, sourceView: UIView?, animated: Bool) { + let coordinator = SpaceChildRoomDetailCoordinator(parameters: SpaceChildRoomDetailCoordinatorParameters(session: session, childInfo: childInfo)) + coordinator.delegate = self + coordinator.start() + + self.coordinator = coordinator + + if UIDevice.current.isPhone || sourceView == nil { + slidingModalPresenter.present(coordinator.toSlidingPresentable(), from: viewController, animated: animated, completion: nil) + } else { + let presentable = coordinator.toPresentable() + presentable.modalPresentationStyle = .popover + if let sourceView = sourceView, let popoverPresentationController = presentable.popoverPresentationController { + popoverPresentationController.sourceView = sourceView + popoverPresentationController.sourceRect = sourceView.bounds + } + + viewController.present(presentable, animated: true) + } + } + + func dismiss(animated: Bool, completion: (() -> Void)?) { + guard let coordinator = self.coordinator else { + return + } + coordinator.toPresentable().dismiss(animated: animated) { + self.coordinator = nil + + if let completion = completion { + completion() + } + } + } +} + +// MARK: - SpaceChildRoomDetailCoordinatorDelegate +extension SpaceChildRoomDetailBridgePresenter: SpaceChildRoomDetailCoordinatorDelegate { + func spaceChildRoomDetailCoordinator(_ coordinator: SpaceChildRoomDetailCoordinatorType, didOpenRoomWith roomId: String) { + delegate?.spaceChildRoomDetailBridgePresenter(self, didOpenRoomWith: roomId) + } + + func spaceChildRoomDetailCoordinatorDidCancel(_ coordinator: SpaceChildRoomDetailCoordinatorType) { + delegate?.spaceChildRoomDetailBridgePresenterDidCancel(self) + } +} + +// MARK: - UIAdaptivePresentationControllerDelegate +extension SpaceChildRoomDetailBridgePresenter: UIAdaptivePresentationControllerDelegate { + + func presentationControllerDidDismiss(_ presentationController: UIPresentationController) { + delegate?.spaceChildRoomDetailBridgePresenterDidCancel(self) + } +} diff --git a/changelog.d/5771.change b/changelog.d/5771.change new file mode 100644 index 000000000..cef75bd46 --- /dev/null +++ b/changelog.d/5771.change @@ -0,0 +1,2 @@ +Update suggested room preview to behave the same way in all cases +