From d91a4e12d41780ddc7a1267622e99aebd6e5301f Mon Sep 17 00:00:00 2001 From: SBiOSoftWhare Date: Fri, 13 Nov 2020 09:38:42 +0100 Subject: [PATCH 01/43] Create RoomChangeMembershipStateDataSource to store and notify room membership state changes. --- .../Managers/Room/ChangeMembershipState.swift | 56 +++++++++++++ .../RoomChangeMembershipStateDataSource.swift | 84 +++++++++++++++++++ 2 files changed, 140 insertions(+) create mode 100644 Riot/Managers/Room/ChangeMembershipState.swift create mode 100644 Riot/Managers/Room/RoomChangeMembershipStateDataSource.swift diff --git a/Riot/Managers/Room/ChangeMembershipState.swift b/Riot/Managers/Room/ChangeMembershipState.swift new file mode 100644 index 000000000..a48b089bc --- /dev/null +++ b/Riot/Managers/Room/ChangeMembershipState.swift @@ -0,0 +1,56 @@ +// +// Copyright 2020 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 + +/// `ChangeMembershipState` represents room membership change states +enum ChangeMembershipState { + case unknown + case pending + case joining + case failedJoining(Error) + case joined + case leaving + case failedLeaving(Error) + case left + + func isInProgress() -> Bool { + switch self { + case .joining, .leaving: + return true + default: + return false + } + } + + func isSuccessful() -> Bool { + switch self { + case .joined, .left: + return true + default: + return false + } + } + + func isError() -> Bool { + switch self { + case .failedJoining, .failedLeaving: + return true + default: + return false + } + } +} diff --git a/Riot/Managers/Room/RoomChangeMembershipStateDataSource.swift b/Riot/Managers/Room/RoomChangeMembershipStateDataSource.swift new file mode 100644 index 000000000..65f5e8b03 --- /dev/null +++ b/Riot/Managers/Room/RoomChangeMembershipStateDataSource.swift @@ -0,0 +1,84 @@ +// +// Copyright 2020 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 + +/// `RoomChangeMembershipStateDataSource` store and notify room membership state change +@objcMembers +final class RoomChangeMembershipStateDataSource: NSObject { + + // MARK: - Notifications + + /// Posted when a membership state of a room is changed. The `Notification` contains the room id. + static let didChangeRoomMembershipStateNotification = Notification.Name(rawValue: "RoomChangeMembershipStateDataSource.didChangeRoomMembershipState") + + /// The key in notification userInfo dictionary representating the roomId. + static let notificationUserInfoRoomIdKey = "roomId" + + // MARK: - Properties + + private var changeMembershipStates: [String: ChangeMembershipState] = [:] + + // MARK: - Public + + func createOrUpdateStateIfNeeded(for roomId: String, and membership: MXMembership) -> ChangeMembershipState { + let state: ChangeMembershipState + + if let currentState = self.getState(for: roomId) { + state = currentState + } else { + state = self.changeMembershipState(for: membership) + } + + self.changeMembershipStates[roomId] = state + + return state + } + + func getState(for roomId: String) -> ChangeMembershipState? { + self.changeMembershipStates[roomId] + } + + func updateState(for roomId: String, from membership: MXMembership) { + self.updateState(for: roomId, with: self.changeMembershipState(for: membership)) + } + + func updateState(for roomId: String, with changeMembershipState: ChangeMembershipState) { + self.changeMembershipStates[roomId] = changeMembershipState + let userInfo = [RoomChangeMembershipStateDataSource.notificationUserInfoRoomIdKey: roomId] + NotificationCenter.default.post(name: RoomChangeMembershipStateDataSource.didChangeRoomMembershipStateNotification, object: self, userInfo: userInfo) + } + + // MARK: - Private + + private func changeMembershipState(for membership: MXMembership) -> ChangeMembershipState { + + let inviteState: ChangeMembershipState + + switch membership { + case .invite: + inviteState = .pending + case .join: + inviteState = .joined + case .leave: + inviteState = .left + default: + inviteState = .unknown + } + + return inviteState + } +} From 23a11019a5b469552c617f1dc73f884a893298c6 Mon Sep 17 00:00:00 2001 From: SBiOSoftWhare Date: Fri, 13 Nov 2020 09:39:38 +0100 Subject: [PATCH 02/43] Create RoomService that enables to manage Matrix room. --- Riot/Managers/Room/RoomService.swift | 191 +++++++++++++++++++ Riot/Managers/Room/RoomServiceProtocol.swift | 35 ++++ 2 files changed, 226 insertions(+) create mode 100644 Riot/Managers/Room/RoomService.swift create mode 100644 Riot/Managers/Room/RoomServiceProtocol.swift diff --git a/Riot/Managers/Room/RoomService.swift b/Riot/Managers/Room/RoomService.swift new file mode 100644 index 000000000..507a3f4db --- /dev/null +++ b/Riot/Managers/Room/RoomService.swift @@ -0,0 +1,191 @@ +// +// Copyright 2020 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 + +/// `RoomService` errors +enum RoomServiceError: Error { + case roomNotFound + case roomAlreadyJoined + case cannotJoinRoom + case roomAlreadyLeft + case cannotLeaveRoom + case changeMembershipAlreadyInProgress +} + +/// `RoomService` enables to manage room +@objcMembers +class RoomService: NSObject, RoomServiceProtocol { + + // MARK: - Constants + + // NOTE: Use shared instance as we can't inject easily this dependency at the moment. Remove when injection will be possible. + static let shared = RoomService() + + // MARK: - Properties + + private var session: MXSession! + private let roomChangeMembershipStateDataSource: RoomChangeMembershipStateDataSource + private var roomChangeMembershipOperations: [String: MXHTTPOperation] = [:] + + // MARK: - Setup + + override init() { + self.roomChangeMembershipStateDataSource = RoomChangeMembershipStateDataSource() + super.init() + } + + // MARK: - Public + + // TODO: To remove once session will be injected in constructor + func updateSession(_ session: MXSession) { + guard session != self.session else { + return + } + self.session = session + + self.roomChangeMembershipOperations = [:] + } + + @discardableResult + func join(roomWithId roomId: String, success: @escaping (() -> Void), failure: @escaping ((Error) -> Void)) -> MXHTTPOperation? { + guard let room = self.session.room(withRoomId: roomId) else { + failure(RoomServiceError.roomNotFound) + return nil + } + + let changeMembershipState = self.roomChangeMembershipStateDataSource.createOrUpdateStateIfNeeded(for: roomId, and: room.summary.membership) + + if case .failure(let error) = self.canJoinRoom(for: changeMembershipState) { + failure(error) + return nil + } + + guard self.isPendingRoomChangeMembershipOperationExists(for: roomId) == false else { + failure(RoomServiceError.changeMembershipAlreadyInProgress) + return nil + } + + let httpOperation = room.join { response in + switch response { + case .success: + self.roomChangeMembershipStateDataSource.updateState(for: roomId, with: .joined) + self.removeRoomChangeMembershipOperation(for: roomId) + success() + case .failure(let error): + self.roomChangeMembershipStateDataSource.updateState(for: roomId, with: .failedJoining(error)) + self.removeRoomChangeMembershipOperation(for: roomId) + failure(error) + } + } + + self.addChangeMembershipTask(for: roomId, changeMembershipState: .joining, httpOperation: httpOperation) + + return httpOperation + } + + @discardableResult + func leave(roomWithId roomId: String, success: @escaping (() -> Void), failure: @escaping ((Error) -> Void)) -> MXHTTPOperation? { + guard let room = self.session.room(withRoomId: roomId) else { + failure(RoomServiceError.roomNotFound) + return nil + } + + let changeMembershipState = self.roomChangeMembershipStateDataSource.createOrUpdateStateIfNeeded(for: roomId, and: room.summary.membership) + + if case .failure(let error) = self.canLeaveRoom(for: changeMembershipState) { + failure(error) + return nil + } + + guard self.isPendingRoomChangeMembershipOperationExists(for: roomId) == false else { + failure(RoomServiceError.changeMembershipAlreadyInProgress) + return nil + } + + let httpOperation = room.leave { response in + switch response { + case .success: + self.roomChangeMembershipStateDataSource.updateState(for: roomId, with: .left) + self.removeRoomChangeMembershipOperation(for: roomId) + success() + case .failure(let error): + self.roomChangeMembershipStateDataSource.updateState(for: roomId, with: .failedLeaving(error)) + self.removeRoomChangeMembershipOperation(for: roomId) + failure(error) + } + } + + self.addChangeMembershipTask(for: roomId, changeMembershipState: .leaving, httpOperation: httpOperation) + + return httpOperation + } + + /// Get the current `ChangeMembershipState` for the room + /// - Parameter roomId: The room id + func getChangeMembeshipState(for roomId: String) -> ChangeMembershipState { + return self.roomChangeMembershipStateDataSource.getState(for: roomId) ?? .unknown + } + + // MARK: - Private + + // MARK: Membership change + + private func isPendingRoomChangeMembershipOperationExists(for roomId: String) -> Bool { + return self.roomChangeMembershipOperations[roomId] != nil + } + + private func canJoinRoom(for changeMembershipState: ChangeMembershipState) -> Result { + let result: Result + + switch changeMembershipState { + case .joining, .leaving: + result = .failure(RoomServiceError.changeMembershipAlreadyInProgress) + case .joined: + result = .failure(RoomServiceError.roomAlreadyJoined) + default: + result = .success(Void()) + } + + return result + } + + private func canLeaveRoom(for changeMembershipState: ChangeMembershipState) -> Result { + let result: Result + + switch changeMembershipState { + case .joining, .leaving: + result = .failure(RoomServiceError.changeMembershipAlreadyInProgress) + case .left: + result = .failure(RoomServiceError.roomAlreadyLeft) + default: + result = .success(Void()) + } + + return result + } + + private func addChangeMembershipTask(for roomId: String, + changeMembershipState: ChangeMembershipState, + httpOperation: MXHTTPOperation) { + self.roomChangeMembershipStateDataSource.updateState(for: roomId, with: changeMembershipState) + self.roomChangeMembershipOperations[roomId] = httpOperation + } + + private func removeRoomChangeMembershipOperation(for roomId: String) { + self.roomChangeMembershipOperations[roomId] = nil + } +} diff --git a/Riot/Managers/Room/RoomServiceProtocol.swift b/Riot/Managers/Room/RoomServiceProtocol.swift new file mode 100644 index 000000000..6ba4cbc32 --- /dev/null +++ b/Riot/Managers/Room/RoomServiceProtocol.swift @@ -0,0 +1,35 @@ +// +// Copyright 2020 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 RoomServiceProtocol { + + /// Join a room + /// - Parameters: + /// - roomId: The room id + /// - success: A block object called when the operation completes. + /// - failure: A block object called when the operation fails. + @objc func join(roomWithId roomId: String, success: @escaping (() -> Void), failure: @escaping ((Error) -> Void)) -> MXHTTPOperation? + + /// Leave a room + /// - Parameters: + /// - roomId: The room id + /// - success: A block object called when the operation completes. + /// - failure: A block object called when the operation fails. + @objc func leave(roomWithId roomId: String, success: @escaping (() -> Void), failure: @escaping ((Error) -> Void)) -> MXHTTPOperation? +} From 2865f7cbdff091f5fbe2765ca470ef8129aa3a8a Mon Sep 17 00:00:00 2001 From: SBiOSoftWhare Date: Fri, 13 Nov 2020 09:47:39 +0100 Subject: [PATCH 03/43] Fix conflict. --- ...ecentTableViewCell+ButtonViewsUpdate.swift | 61 +++++++++++++++++++ .../People/Views/InviteRecentTableViewCell.h | 10 +++ .../People/Views/InviteRecentTableViewCell.m | 25 ++++++-- .../Views/InviteRecentTableViewCell.xib | 38 +++++++----- Riot/SupportingFiles/Riot-Bridging-Header.h | 1 + 5 files changed, 115 insertions(+), 20 deletions(-) create mode 100644 Riot/Modules/People/Views/InviteRecentTableViewCell+ButtonViewsUpdate.swift diff --git a/Riot/Modules/People/Views/InviteRecentTableViewCell+ButtonViewsUpdate.swift b/Riot/Modules/People/Views/InviteRecentTableViewCell+ButtonViewsUpdate.swift new file mode 100644 index 000000000..9eaed0795 --- /dev/null +++ b/Riot/Modules/People/Views/InviteRecentTableViewCell+ButtonViewsUpdate.swift @@ -0,0 +1,61 @@ +// +// Copyright 2020 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 + +extension InviteRecentTableViewCell { + + @objc func resetButtonViews() { + self.leftButton.isEnabled = true + self.rightButton.isEnabled = true + self.leftButtonActivityIndicator.stopAnimating() + self.rightButtonActivityIndicator.stopAnimating() + } + + /// Update buttons according to current ChangeMembeshipState of the room + @objc func updateButtonViews(with roomId: String) { + let changeMembershipState = RoomService.shared.getChangeMembeshipState(for: roomId) + + var joinButtonIsLoading = false + var leaveButtonIsLoading = false + + switch changeMembershipState { + case .joining: + joinButtonIsLoading = true + case .leaving: + leaveButtonIsLoading = true + default: + break + } + + let areButtonsEnabled = !(joinButtonIsLoading || leaveButtonIsLoading) + + self.leftButton.isEnabled = areButtonsEnabled + self.rightButton.isEnabled = areButtonsEnabled + + if leaveButtonIsLoading { + self.leftButtonActivityIndicator.startAnimating() + } else { + self.leftButtonActivityIndicator.stopAnimating() + } + + if joinButtonIsLoading { + self.rightButtonActivityIndicator.startAnimating() + } else { + self.rightButtonActivityIndicator.stopAnimating() + } + } +} diff --git a/Riot/Modules/People/Views/InviteRecentTableViewCell.h b/Riot/Modules/People/Views/InviteRecentTableViewCell.h index 1b4ca9d93..314f7f7e8 100644 --- a/Riot/Modules/People/Views/InviteRecentTableViewCell.h +++ b/Riot/Modules/People/Views/InviteRecentTableViewCell.h @@ -25,6 +25,13 @@ */ extern NSString *const kInviteRecentTableViewCellPreviewButtonPressed; +/** + Action identifier used when the user pressed 'accept' button displayed on room invitation. + + The `userInfo` dictionary contains an `MXRoom` object under the `kInviteRecentTableViewCellRoomKey` key, representing the room of the invitation. + */ +extern NSString *const kInviteRecentTableViewCellAcceptButtonPressed; + /** Action identifier used when the user pressed 'decline' button displayed on room invitation. @@ -45,6 +52,9 @@ extern NSString *const kInviteRecentTableViewCellRoomKey; @property (weak, nonatomic) IBOutlet UIButton *leftButton; @property (weak, nonatomic) IBOutlet UIButton *rightButton; +@property (weak, nonatomic) IBOutlet UIActivityIndicatorView *leftButtonActivityIndicator; +@property (weak, nonatomic) IBOutlet UIActivityIndicatorView *rightButtonActivityIndicator; + @property (weak, nonatomic) IBOutlet UIView *noticeBadgeView; diff --git a/Riot/Modules/People/Views/InviteRecentTableViewCell.m b/Riot/Modules/People/Views/InviteRecentTableViewCell.m index b9a7de18b..db2f7130c 100644 --- a/Riot/Modules/People/Views/InviteRecentTableViewCell.m +++ b/Riot/Modules/People/Views/InviteRecentTableViewCell.m @@ -26,6 +26,7 @@ #pragma mark - Constant definitions +NSString *const kInviteRecentTableViewCellAcceptButtonPressed = @"kInviteRecentTableViewCellAcceptButtonPressed"; NSString *const kInviteRecentTableViewCellPreviewButtonPressed = @"kInviteRecentTableViewCellPreviewButtonPressed"; NSString *const kInviteRecentTableViewCellDeclineButtonPressed = @"kInviteRecentTableViewCellDeclineButtonPressed"; @@ -42,14 +43,12 @@ NSString *const kInviteRecentTableViewCellRoomKey = @"kInviteRecentTableViewCell [self.leftButton.layer setCornerRadius:5]; self.leftButton.clipsToBounds = YES; [self.leftButton setTitle:NSLocalizedStringFromTable(@"decline", @"Vector", nil) forState:UIControlStateNormal]; - [self.leftButton setTitle:NSLocalizedStringFromTable(@"decline", @"Vector", nil) forState:UIControlStateHighlighted]; [self.leftButton addTarget:self action:@selector(onDeclinePressed:) forControlEvents:UIControlEventTouchUpInside]; [self.rightButton.layer setCornerRadius:5]; self.rightButton.clipsToBounds = YES; - [self.rightButton setTitle:NSLocalizedStringFromTable(@"preview", @"Vector", nil) forState:UIControlStateNormal]; - [self.rightButton setTitle:NSLocalizedStringFromTable(@"preview", @"Vector", nil) forState:UIControlStateHighlighted]; - [self.rightButton addTarget:self action:@selector(onPreviewPressed:) forControlEvents:UIControlEventTouchUpInside]; + [self.rightButton setTitle:NSLocalizedStringFromTable(@"accept", @"Vector", nil) forState:UIControlStateNormal]; + [self.rightButton addTarget:self action:@selector(onAcceptPressed:) forControlEvents:UIControlEventTouchUpInside]; [self.noticeBadgeView.layer setCornerRadius:10]; @@ -66,6 +65,13 @@ NSString *const kInviteRecentTableViewCellRoomKey = @"kInviteRecentTableViewCell self.noticeBadgeView.backgroundColor = ThemeService.shared.theme.noticeColor; } +- (void)prepareForReuse +{ + [super prepareForReuse]; + + [self resetButtonViews]; +} + - (void)onDeclinePressed:(id)sender { if (self.delegate) @@ -79,7 +85,7 @@ NSString *const kInviteRecentTableViewCellRoomKey = @"kInviteRecentTableViewCell } } -- (void)onPreviewPressed:(id)sender +- (void)onAcceptPressed:(id)sender { if (self.delegate) { @@ -87,7 +93,7 @@ NSString *const kInviteRecentTableViewCellRoomKey = @"kInviteRecentTableViewCell if (room) { - [self.delegate cell:self didRecognizeAction:kInviteRecentTableViewCellPreviewButtonPressed userInfo:@{kInviteRecentTableViewCellRoomKey:room}]; + [self.delegate cell:self didRecognizeAction:kInviteRecentTableViewCellAcceptButtonPressed userInfo:@{kInviteRecentTableViewCellRoomKey:room}]; } } } @@ -95,6 +101,13 @@ NSString *const kInviteRecentTableViewCellRoomKey = @"kInviteRecentTableViewCell - (void)render:(MXKCellData *)cellData { [super render:cellData]; + + MXRoom *room = roomCellData.roomSummary.room; + + if (room.roomId) + { + [self updateButtonViewsWith:room.roomId]; + } } + (CGFloat)heightForCellData:(MXKCellData *)cellData withMaximumWidth:(CGFloat)maxWidth diff --git a/Riot/Modules/People/Views/InviteRecentTableViewCell.xib b/Riot/Modules/People/Views/InviteRecentTableViewCell.xib index 5b756ca84..f1ecf7116 100644 --- a/Riot/Modules/People/Views/InviteRecentTableViewCell.xib +++ b/Riot/Modules/People/Views/InviteRecentTableViewCell.xib @@ -1,12 +1,9 @@ - - - - + + - - + @@ -16,7 +13,7 @@ - + @@ -33,7 +30,7 @@ diff --git a/Riot/SupportingFiles/Riot-Bridging-Header.h b/Riot/SupportingFiles/Riot-Bridging-Header.h index 26bf83cda..b3f520b1f 100644 --- a/Riot/SupportingFiles/Riot-Bridging-Header.h +++ b/Riot/SupportingFiles/Riot-Bridging-Header.h @@ -25,3 +25,4 @@ #import "RoomFilesViewController.h" #import "RoomSettingsViewController.h" #import "JitsiWidgetData.h" +#import "InviteRecentTableViewCell.h" From 1d29988eaf82d1067dd6a50fbf218f8d0a540b0a Mon Sep 17 00:00:00 2001 From: SBiOSoftWhare Date: Fri, 13 Nov 2020 09:45:10 +0100 Subject: [PATCH 04/43] RecentsViewController: Handle direct room invite approval. --- Riot/Modules/Application/LegacyAppDelegate.m | 2 + .../RecentsViewController+RoomInvite.swift | 45 +++++++ .../Common/Recents/RecentsViewController.m | 117 +++++++++++++++--- 3 files changed, 149 insertions(+), 15 deletions(-) create mode 100644 Riot/Modules/Common/Recents/RecentsViewController+RoomInvite.swift diff --git a/Riot/Modules/Application/LegacyAppDelegate.m b/Riot/Modules/Application/LegacyAppDelegate.m index bf303c6ef..6a28738a5 100644 --- a/Riot/Modules/Application/LegacyAppDelegate.m +++ b/Riot/Modules/Application/LegacyAppDelegate.m @@ -1753,6 +1753,8 @@ NSString *const AppDelegateUniversalLinkDidChangeNotification = @"AppDelegateUni [self configureCallManagerIfRequiredForSession:mxSession]; [self.configuration setupSettingsFor:mxSession]; + + [RoomService.shared updateSession:mxSession]; } else if (mxSession.state == MXSessionStateStoreDataReady) { diff --git a/Riot/Modules/Common/Recents/RecentsViewController+RoomInvite.swift b/Riot/Modules/Common/Recents/RecentsViewController+RoomInvite.swift new file mode 100644 index 000000000..e2b6dfebf --- /dev/null +++ b/Riot/Modules/Common/Recents/RecentsViewController+RoomInvite.swift @@ -0,0 +1,45 @@ +// +// Copyright 2020 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 + +extension RecentsViewController { + + @objc func registerRoomChangeMembershipStateDataSourceNotifications() { + NotificationCenter.default.addObserver(self, selector: #selector(roomChangeMembershipStateDataSourceDidChangeRoomMembershipState(notification:)), name: RoomChangeMembershipStateDataSource.didChangeRoomMembershipStateNotification, object: nil) + } + + @objc func unregisterRoomChangeMembershipStateDataSourceNotifications() { + NotificationCenter.default.removeObserver(self, name: RoomChangeMembershipStateDataSource.didChangeRoomMembershipStateNotification, object: nil) + } + + @objc func roomChangeMembershipStateDataSourceDidChangeRoomMembershipState(notification: Notification) { + self.recentsTableView.reloadData() + } + + @objc func canShowRoomPreview(for roomId: String) -> Bool { + let changeMembershipState = RoomService.shared.getChangeMembeshipState(for: roomId) + + // NOTE: For the moment do not offer the possibility to show room preview when invitation action is in progress + + switch changeMembershipState { + case .failedJoining, .failedLeaving: + return false + default: + return true + } + } +} diff --git a/Riot/Modules/Common/Recents/RecentsViewController.m b/Riot/Modules/Common/Recents/RecentsViewController.m index 336275581..48045d5d0 100644 --- a/Riot/Modules/Common/Recents/RecentsViewController.m +++ b/Riot/Modules/Common/Recents/RecentsViewController.m @@ -155,6 +155,9 @@ self.recentsSearchBar.autocapitalizationType = UITextAutocapitalizationTypeNone; self.recentsSearchBar.placeholder = NSLocalizedStringFromTable(@"search_default_placeholder", @"Vector", nil); + // Register room change membership state notifications + [self registerRoomChangeMembershipStateDataSourceNotifications]; + // Observe user interface theme change. kThemeServiceDidChangeThemeNotificationObserver = [[NSNotificationCenter defaultCenter] addObserverForName:kThemeServiceDidChangeThemeNotification object:nil queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification *notif) { @@ -452,6 +455,83 @@ } } +- (void)joinRoomWithId:(NSString*)roomId completion:(void(^)(BOOL succeed))completion +{ + RoomService *roomService = RoomService.shared; + + [roomService joinWithRoomWithId:roomId success:^{ + // `recentsTableView` will be reloaded `roomChangeMembershipStateDataSourceDidChangeRoomMembershipState` function + + if (completion) + { + completion(YES); + } + + } failure:^(NSError * _Nonnull error) { + NSLog(@"[RecentsViewController] Failed to join an invited room (%@)", roomId); + [self presentRoomJoinFailedAlertForError:error completion:^{ + if (completion) + { + completion(NO); + } + }]; + }]; +} + +- (void)leaveRoomWithId:(NSString*)roomId completion:(void(^)(BOOL succeed))completion +{ + RoomService *roomService = RoomService.shared; + + // Decline the invitation + [roomService leaveWithRoomWithId:roomId success:^{ + + // `recentsTableView` will be reloaded `roomChangeMembershipStateDataSourceDidChangeRoomMembershipState` function + + if (completion) + { + completion(YES); + } + } failure:^(NSError * _Nonnull error) { + NSLog(@"[RecentsViewController] Failed to reject an invited room (%@)", roomId); + [[AppDelegate theDelegate] showErrorAsAlert:error]; + + if (completion) + { + completion(NO); + } + }]; +} + +- (void)presentRoomJoinFailedAlertForError:(NSError*)error completion:(void(^)(void))completion +{ + MXWeakify(self); + NSString *msg = [error.userInfo valueForKey:NSLocalizedDescriptionKey]; + if ([msg isEqualToString:@"No known servers"]) + { + // minging kludge until https://matrix.org/jira/browse/SYN-678 is fixed + // 'Error when trying to join an empty room should be more explicit' + msg = [NSBundle mxk_localizedStringForKey:@"room_error_join_failed_empty_room"]; + } + + [self->currentAlert dismissViewControllerAnimated:NO completion:nil]; + + self->currentAlert = [UIAlertController alertControllerWithTitle:[NSBundle mxk_localizedStringForKey:@"room_error_join_failed_title"] message:msg preferredStyle:UIAlertControllerStyleAlert]; + + [self->currentAlert addAction:[UIAlertAction actionWithTitle:[NSBundle mxk_localizedStringForKey:@"ok"] + style:UIAlertActionStyleDefault + handler:^(UIAlertAction * action) { + MXStrongifyAndReturnIfNil(self); + self->currentAlert = nil; + + if (completion) + { + completion(); + } + }]]; + + [self presentViewController:self->currentAlert animated:YES completion:nil]; +} + #pragma mark - Sticky Headers - (void)setEnableStickyHeaders:(BOOL)enableStickyHeaders @@ -812,31 +892,23 @@ - (void)dataSource:(MXKDataSource *)dataSource didRecognizeAction:(NSString *)actionIdentifier inCell:(id)cell userInfo:(NSDictionary *)userInfo { // Handle here user actions on recents for Riot app - if ([actionIdentifier isEqualToString:kInviteRecentTableViewCellPreviewButtonPressed]) + if ([actionIdentifier isEqualToString:kInviteRecentTableViewCellAcceptButtonPressed]) { // Retrieve the invited room MXRoom *invitedRoom = userInfo[kInviteRecentTableViewCellRoomKey]; - // Display the room preview - [self dispayRoomWithRoomId:invitedRoom.roomId inMatrixSession:invitedRoom.mxSession]; + // Accept invitation + [self joinRoomWithId:invitedRoom.roomId completion:nil]; } else if ([actionIdentifier isEqualToString:kInviteRecentTableViewCellDeclineButtonPressed]) { // Retrieve the invited room MXRoom *invitedRoom = userInfo[kInviteRecentTableViewCellRoomKey]; - + [self cancelEditionMode:isRefreshPending]; // Decline the invitation - [invitedRoom leave:^{ - - [self.recentsTableView reloadData]; - - } failure:^(NSError *error) { - - NSLog(@"[RecentsViewController] Failed to reject an invited room (%@)", invitedRoom.roomId); - - }]; + [self leaveRoomWithId:invitedRoom.roomId completion:nil]; } else { @@ -1271,8 +1343,23 @@ if ([cell isKindOfClass:[InviteRecentTableViewCell class]]) { - // hide the selection - [tableView deselectRowAtIndexPath:indexPath animated:NO]; + id cellData = [self.dataSource cellDataAtIndexPath:indexPath]; + + // Retrieve the invited room + MXRoom* invitedRoom = cellData.roomSummary.room; + + NSString *roomId = invitedRoom.roomId; + + // Check if can show preview for the invited room + if ([self canShowRoomPreviewFor:roomId]) + { + // Display the room preview + [self dispayRoomWithRoomId:roomId inMatrixSession:invitedRoom.mxSession]; + } + else + { + [tableView deselectRowAtIndexPath:indexPath animated:NO]; + } } else if ([cell isKindOfClass:[DirectoryRecentTableViewCell class]]) { From d34595b3d047fa5c2a4bab5caf92cebfafa700c7 Mon Sep 17 00:00:00 2001 From: SBiOSoftWhare Date: Fri, 13 Nov 2020 09:48:56 +0100 Subject: [PATCH 05/43] Fix pbxproj conflict. --- Riot.xcodeproj/project.pbxproj | 34 ++++++++++++++++++++++++++++++++-- 1 file changed, 32 insertions(+), 2 deletions(-) diff --git a/Riot.xcodeproj/project.pbxproj b/Riot.xcodeproj/project.pbxproj index e8992b783..a35f89039 100644 --- a/Riot.xcodeproj/project.pbxproj +++ b/Riot.xcodeproj/project.pbxproj @@ -203,6 +203,8 @@ B110872621F098F0003554A5 /* ActivityIndicatorView.swift in Sources */ = {isa = PBXBuildFile; fileRef = B110872221F098F0003554A5 /* ActivityIndicatorView.swift */; }; B11291EA238D35590077B478 /* SlidingModalPresentable.swift in Sources */ = {isa = PBXBuildFile; fileRef = B11291E9238D35590077B478 /* SlidingModalPresentable.swift */; }; B11291EC238D704C0077B478 /* FloatingPoint.swift in Sources */ = {isa = PBXBuildFile; fileRef = B11291EB238D704C0077B478 /* FloatingPoint.swift */; }; + B113DD36255DF8AF0022942A /* RoomServiceProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = B113DD35255DF8AF0022942A /* RoomServiceProtocol.swift */; }; + B113DD38255DFA3E0022942A /* ChangeMembershipState.swift in Sources */ = {isa = PBXBuildFile; fileRef = B113DD37255DFA3E0022942A /* ChangeMembershipState.swift */; }; B120863722EF375F001F89E0 /* ReactionHistoryBridgeCoordinatorPresenter.swift in Sources */ = {isa = PBXBuildFile; fileRef = B120863622EF375F001F89E0 /* ReactionHistoryBridgeCoordinatorPresenter.swift */; }; B125FE1B231D5BF200B72806 /* SettingsDiscoveryTableViewSection.swift in Sources */ = {isa = PBXBuildFile; fileRef = B125FE1A231D5BF200B72806 /* SettingsDiscoveryTableViewSection.swift */; }; B125FE1D231D5DE400B72806 /* SettingsDiscoveryViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = B125FE1C231D5DE400B72806 /* SettingsDiscoveryViewModel.swift */; }; @@ -750,7 +752,10 @@ B1E5368921FB1E20001F3AFF /* UIButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = B1E5368821FB1E20001F3AFF /* UIButton.swift */; }; B1E5368D21FB7245001F3AFF /* KeyBackupRecoverFromPassphraseViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = B1E5368C21FB7245001F3AFF /* KeyBackupRecoverFromPassphraseViewController.swift */; }; B1E5368F21FB7258001F3AFF /* KeyBackupRecoverFromPassphraseViewController.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = B1E5368E21FB7258001F3AFF /* KeyBackupRecoverFromPassphraseViewController.storyboard */; }; - B1E5EF9D2541C06000E8A883 /* JitsiWellKnown.swift in Sources */ = {isa = PBXBuildFile; fileRef = B1E5EF9C2541C06000E8A883 /* JitsiWellKnown.swift */; }; + B1F907292559CDB000DD14E5 /* RoomChangeMembershipStateDataSource.swift in Sources */ = {isa = PBXBuildFile; fileRef = B1F907282559CDAF00DD14E5 /* RoomChangeMembershipStateDataSource.swift */; }; + B1F9072B255ADBA700DD14E5 /* RoomService.swift in Sources */ = {isa = PBXBuildFile; fileRef = B1F9072A255ADBA700DD14E5 /* RoomService.swift */; }; + B1F9072D255CDA1200DD14E5 /* RecentsViewController+RoomInvite.swift in Sources */ = {isa = PBXBuildFile; fileRef = B1F9072C255CDA1200DD14E5 /* RecentsViewController+RoomInvite.swift */; }; + B1F9072F255CE06000DD14E5 /* InviteRecentTableViewCell+ButtonViewsUpdate.swift in Sources */ = {isa = PBXBuildFile; fileRef = B1F9072E255CE06000DD14E5 /* InviteRecentTableViewCell+ButtonViewsUpdate.swift */; }; B1FDF56021F5FE5500BA3834 /* KeyBackupSetupPassphraseViewAction.swift in Sources */ = {isa = PBXBuildFile; fileRef = B1FDF55F21F5FE5500BA3834 /* KeyBackupSetupPassphraseViewAction.swift */; }; DB1392A2332C3CAF6C9962EF /* Pods_RiotPods_RiotNSE.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E4D418D054E4032F2CFA8B51 /* Pods_RiotPods_RiotNSE.framework */; }; EC1CA85F24C1DEC400DE9EBF /* EnterPinCodeViewModelType.swift in Sources */ = {isa = PBXBuildFile; fileRef = EC1CA85124C1DEC400DE9EBF /* EnterPinCodeViewModelType.swift */; }; @@ -1240,6 +1245,8 @@ B110872221F098F0003554A5 /* ActivityIndicatorView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ActivityIndicatorView.swift; sourceTree = ""; }; B11291E9238D35590077B478 /* SlidingModalPresentable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SlidingModalPresentable.swift; sourceTree = ""; }; B11291EB238D704C0077B478 /* FloatingPoint.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FloatingPoint.swift; sourceTree = ""; }; + B113DD35255DF8AF0022942A /* RoomServiceProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomServiceProtocol.swift; sourceTree = ""; }; + B113DD37255DFA3E0022942A /* ChangeMembershipState.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ChangeMembershipState.swift; sourceTree = ""; }; B120863622EF375F001F89E0 /* ReactionHistoryBridgeCoordinatorPresenter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ReactionHistoryBridgeCoordinatorPresenter.swift; sourceTree = ""; }; B125FE1A231D5BF200B72806 /* SettingsDiscoveryTableViewSection.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingsDiscoveryTableViewSection.swift; sourceTree = ""; }; B125FE1C231D5DE400B72806 /* SettingsDiscoveryViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingsDiscoveryViewModel.swift; sourceTree = ""; }; @@ -1980,6 +1987,10 @@ B1EDFDF32525E9690020EEFF /* et */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = et; path = et.lproj/Vector.strings; sourceTree = ""; }; B1EDFDF42525E9690020EEFF /* et */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = et; path = et.lproj/InfoPlist.strings; sourceTree = ""; }; B1EDFDF52525E96A0020EEFF /* et */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = et; path = et.lproj/Localizable.strings; sourceTree = ""; }; + B1F907282559CDAF00DD14E5 /* RoomChangeMembershipStateDataSource.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomChangeMembershipStateDataSource.swift; sourceTree = ""; }; + B1F9072A255ADBA700DD14E5 /* RoomService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomService.swift; sourceTree = ""; }; + B1F9072C255CDA1200DD14E5 /* RecentsViewController+RoomInvite.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "RecentsViewController+RoomInvite.swift"; sourceTree = ""; }; + B1F9072E255CE06000DD14E5 /* InviteRecentTableViewCell+ButtonViewsUpdate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "InviteRecentTableViewCell+ButtonViewsUpdate.swift"; sourceTree = ""; }; B1FDF55F21F5FE5500BA3834 /* KeyBackupSetupPassphraseViewAction.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = KeyBackupSetupPassphraseViewAction.swift; sourceTree = ""; }; B43DC75D1590BB8A4243BD4D /* Pods-RiotPods-Riot.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RiotPods-Riot.release.xcconfig"; path = "Target Support Files/Pods-RiotPods-Riot/Pods-RiotPods-Riot.release.xcconfig"; sourceTree = ""; }; BABB6681FBD79219B1213D6C /* Pods-RiotTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RiotTests.debug.xcconfig"; path = "Target Support Files/Pods-RiotTests/Pods-RiotTests.debug.xcconfig"; sourceTree = ""; }; @@ -3229,6 +3240,17 @@ path = OnBoarding; sourceTree = ""; }; + B180A645255DF59800F5E6FF /* Room */ = { + isa = PBXGroup; + children = ( + B113DD35255DF8AF0022942A /* RoomServiceProtocol.swift */, + B1F9072A255ADBA700DD14E5 /* RoomService.swift */, + B113DD37255DFA3E0022942A /* ChangeMembershipState.swift */, + B1F907282559CDAF00DD14E5 /* RoomChangeMembershipStateDataSource.swift */, + ); + path = Room; + sourceTree = ""; + }; B183226923F59F3E0035B2E8 /* Buttons */ = { isa = PBXGroup; children = ( @@ -3781,6 +3803,7 @@ B1B556DB20EE6C4C00210D55 /* RecentsViewController.h */, B1B556D920EE6C4C00210D55 /* RecentsViewController.m */, B1B556DA20EE6C4C00210D55 /* RecentsViewController.xib */, + B1F9072C255CDA1200DD14E5 /* RecentsViewController+RoomInvite.swift */, B16932F320F3C4B800746532 /* DataSources */, B16932F420F3C4C000746532 /* CellData */, B1B5594E20EF9A8600210D55 /* Views */, @@ -4496,6 +4519,7 @@ isa = PBXGroup; children = ( B1B5597420EFB02900210D55 /* InviteRecentTableViewCell.h */, + B1F9072E255CE06000DD14E5 /* InviteRecentTableViewCell+ButtonViewsUpdate.swift */, B1B5597220EFB02900210D55 /* InviteRecentTableViewCell.m */, B1B5597320EFB02900210D55 /* InviteRecentTableViewCell.xib */, ); @@ -4518,7 +4542,7 @@ B1B5598A20EFC42100210D55 /* Settings */, 32242F0B21E8FBA900725742 /* Theme */, B1B5598020EFC3DF00210D55 /* Widgets */, - B19207112550683500F5062F /* Room */, + B180A645255DF59800F5E6FF /* Room */, ); path = Managers; sourceTree = ""; @@ -6226,6 +6250,7 @@ buildActionMask = 2147483647; files = ( EC711B7B24A63B37008F830C /* SecretsSetupRecoveryKeyCoordinator.swift in Sources */, + B1F9072D255CDA1200DD14E5 /* RecentsViewController+RoomInvite.swift in Sources */, B1B557D120EF5E3500210D55 /* MediaAlbumTableCell.m in Sources */, 32607D71243E0A55006674CC /* KeyBackupRecoverFromPrivateKeyViewState.swift in Sources */, EC51E7A92514D2E100AAE7DB /* RoomInfoListViewModelType.swift in Sources */, @@ -6269,6 +6294,7 @@ B1DB4F0E22316FFF0065DBFA /* UserNameColorGenerator.swift in Sources */, B157FAA123264AE900EBFBD4 /* SettingsDiscoveryThreePidDetailsCoordinatorType.swift in Sources */, EC85D7302477DD33002C44C9 /* JitsiWidgetData.m in Sources */, + B1F907292559CDB000DD14E5 /* RoomChangeMembershipStateDataSource.swift in Sources */, 32607D6C243E0A55006674CC /* KeyBackupRecoverFromPrivateKeyViewController.swift in Sources */, B1057789221304EC00334B1E /* KeyBackupSetupSuccessFromPassphraseViewController.swift in Sources */, B1DCC61922E5E17100625807 /* EmojiPickerCoordinatorType.swift in Sources */, @@ -6362,6 +6388,7 @@ B140B4A621F89E7600E3F5FE /* KeyBackupSetupCoordinatorBridgePresenter.swift in Sources */, B1B5577420EE702900210D55 /* WidgetViewController.m in Sources */, B1DCC63122E7026F00625807 /* EmojiPickerHeaderView.swift in Sources */, + B113DD38255DFA3E0022942A /* ChangeMembershipState.swift in Sources */, ECB101302477CFDB00CF8C11 /* UITableView.swift in Sources */, B1CE83DC2422817200D07506 /* KeyVerificationVerifyByScanningViewState.swift in Sources */, B139C21B21FE5B9200BB68EC /* KeyBackupRecoverFromPassphraseViewModel.swift in Sources */, @@ -6462,6 +6489,7 @@ 3232ABA7225730E100AD6A5C /* DeviceVerificationStartCoordinator.swift in Sources */, B1D4752721EE4E630067973F /* KeyboardAvoider.swift in Sources */, B1D4752821EE4E630067973F /* KeyboardNotification.swift in Sources */, + B1F9072B255ADBA700DD14E5 /* RoomService.swift in Sources */, B1D1BDA622BBAFB500831367 /* ReactionsMenuView.swift in Sources */, EC51E7AD2514D2E100AAE7DB /* RoomInfoListCoordinator.swift in Sources */, EC711B4624A63B13008F830C /* MXRecoveryService.swift in Sources */, @@ -6696,6 +6724,7 @@ B18DEDD9243377C10075FEF7 /* KeyVerificationSelfVerifyWaitViewController.swift in Sources */, EC1CA89524C9C9A200DE9EBF /* SetupBiometricsViewController.swift in Sources */, 324A2052225FC571004FE8B0 /* DeviceVerificationIncomingViewAction.swift in Sources */, + B1F9072F255CE06000DD14E5 /* InviteRecentTableViewCell+ButtonViewsUpdate.swift in Sources */, EC85D72C2477DCF2002C44C9 /* KeyVerificationManuallyVerifyViewState.swift in Sources */, EC1CA86E24C5BA4500DE9EBF /* PinCodePreferences.swift in Sources */, B105778D2213051E00334B1E /* KeyBackupSetupSuccessFromRecoveryKeyViewController.swift in Sources */, @@ -6870,6 +6899,7 @@ B139C22521FF01C100BB68EC /* KeyBackupRecoverFromPassphraseCoordinator.swift in Sources */, B1BEE71623DF2ACF0003A4CB /* UserVerificationCoordinatorBridgePresenter.swift in Sources */, B1098BFD21ECFE65000DDA48 /* PasswordStrengthManager.swift in Sources */, + B113DD36255DF8AF0022942A /* RoomServiceProtocol.swift in Sources */, B1B558F520EF768F00210D55 /* RoomOutgoingTextMsgWithPaginationTitleBubbleCell.m in Sources */, 3232AB482256558300AD6A5C /* FlowTemplateCoordinatorType.swift in Sources */, B1B9DEF122EB396B0065E677 /* ReactionHistoryViewData.swift in Sources */, From 9b897556dbc3e8a7720017a3f38dab7296435693 Mon Sep 17 00:00:00 2001 From: SBiOSoftWhare Date: Fri, 13 Nov 2020 10:24:56 +0100 Subject: [PATCH 06/43] Fix pbxproj --- Riot.xcodeproj/project.pbxproj | 18 ++++++------------ 1 file changed, 6 insertions(+), 12 deletions(-) diff --git a/Riot.xcodeproj/project.pbxproj b/Riot.xcodeproj/project.pbxproj index a35f89039..c1047c5dc 100644 --- a/Riot.xcodeproj/project.pbxproj +++ b/Riot.xcodeproj/project.pbxproj @@ -205,6 +205,8 @@ B11291EC238D704C0077B478 /* FloatingPoint.swift in Sources */ = {isa = PBXBuildFile; fileRef = B11291EB238D704C0077B478 /* FloatingPoint.swift */; }; B113DD36255DF8AF0022942A /* RoomServiceProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = B113DD35255DF8AF0022942A /* RoomServiceProtocol.swift */; }; B113DD38255DFA3E0022942A /* ChangeMembershipState.swift in Sources */ = {isa = PBXBuildFile; fileRef = B113DD37255DFA3E0022942A /* ChangeMembershipState.swift */; }; + B113DD3C255E83C70022942A /* RoomIdComponents.swift in Sources */ = {isa = PBXBuildFile; fileRef = B113DD3B255E83C60022942A /* RoomIdComponents.swift */; }; + B113DD3D255E876A0022942A /* JitsiWellKnown.swift in Sources */ = {isa = PBXBuildFile; fileRef = B1E5EF9C2541C06000E8A883 /* JitsiWellKnown.swift */; }; B120863722EF375F001F89E0 /* ReactionHistoryBridgeCoordinatorPresenter.swift in Sources */ = {isa = PBXBuildFile; fileRef = B120863622EF375F001F89E0 /* ReactionHistoryBridgeCoordinatorPresenter.swift */; }; B125FE1B231D5BF200B72806 /* SettingsDiscoveryTableViewSection.swift in Sources */ = {isa = PBXBuildFile; fileRef = B125FE1A231D5BF200B72806 /* SettingsDiscoveryTableViewSection.swift */; }; B125FE1D231D5DE400B72806 /* SettingsDiscoveryViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = B125FE1C231D5DE400B72806 /* SettingsDiscoveryViewModel.swift */; }; @@ -333,7 +335,6 @@ B190F55922CE356800AEB493 /* EditHistoryHeaderView.swift in Sources */ = {isa = PBXBuildFile; fileRef = B190F55822CE356800AEB493 /* EditHistoryHeaderView.swift */; }; B190F55B22CE35FD00AEB493 /* EditHistoryHeaderView.xib in Resources */ = {isa = PBXBuildFile; fileRef = B190F55A22CE35FD00AEB493 /* EditHistoryHeaderView.xib */; }; B190F55D22CE5A9700AEB493 /* EditHistorySection.swift in Sources */ = {isa = PBXBuildFile; fileRef = B190F55C22CE5A9600AEB493 /* EditHistorySection.swift */; }; - B1920713255068B300F5062F /* RoomIdComponents.swift in Sources */ = {isa = PBXBuildFile; fileRef = B1920712255068B200F5062F /* RoomIdComponents.swift */; }; B1963B2B228F1C4900CBA17F /* BubbleReactionsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = B1963B25228F1C4800CBA17F /* BubbleReactionsView.swift */; }; B1963B2C228F1C4900CBA17F /* BubbleReactionViewCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = B1963B26228F1C4800CBA17F /* BubbleReactionViewCell.xib */; }; B1963B2D228F1C4900CBA17F /* BubbleReactionsViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = B1963B27228F1C4800CBA17F /* BubbleReactionsViewModel.swift */; }; @@ -1247,6 +1248,7 @@ B11291EB238D704C0077B478 /* FloatingPoint.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FloatingPoint.swift; sourceTree = ""; }; B113DD35255DF8AF0022942A /* RoomServiceProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomServiceProtocol.swift; sourceTree = ""; }; B113DD37255DFA3E0022942A /* ChangeMembershipState.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ChangeMembershipState.swift; sourceTree = ""; }; + B113DD3B255E83C60022942A /* RoomIdComponents.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RoomIdComponents.swift; sourceTree = ""; }; B120863622EF375F001F89E0 /* ReactionHistoryBridgeCoordinatorPresenter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ReactionHistoryBridgeCoordinatorPresenter.swift; sourceTree = ""; }; B125FE1A231D5BF200B72806 /* SettingsDiscoveryTableViewSection.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingsDiscoveryTableViewSection.swift; sourceTree = ""; }; B125FE1C231D5DE400B72806 /* SettingsDiscoveryViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingsDiscoveryViewModel.swift; sourceTree = ""; }; @@ -1425,7 +1427,6 @@ B190F55822CE356800AEB493 /* EditHistoryHeaderView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EditHistoryHeaderView.swift; sourceTree = ""; }; B190F55A22CE35FD00AEB493 /* EditHistoryHeaderView.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = EditHistoryHeaderView.xib; sourceTree = ""; }; B190F55C22CE5A9600AEB493 /* EditHistorySection.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EditHistorySection.swift; sourceTree = ""; }; - B1920712255068B200F5062F /* RoomIdComponents.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RoomIdComponents.swift; sourceTree = ""; }; B1963B25228F1C4800CBA17F /* BubbleReactionsView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BubbleReactionsView.swift; sourceTree = ""; }; B1963B26228F1C4800CBA17F /* BubbleReactionViewCell.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = BubbleReactionViewCell.xib; sourceTree = ""; }; B1963B27228F1C4800CBA17F /* BubbleReactionsViewModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BubbleReactionsViewModel.swift; sourceTree = ""; }; @@ -3243,6 +3244,7 @@ B180A645255DF59800F5E6FF /* Room */ = { isa = PBXGroup; children = ( + B113DD3B255E83C60022942A /* RoomIdComponents.swift */, B113DD35255DF8AF0022942A /* RoomServiceProtocol.swift */, B1F9072A255ADBA700DD14E5 /* RoomService.swift */, B113DD37255DFA3E0022942A /* ChangeMembershipState.swift */, @@ -3291,14 +3293,6 @@ path = SelfVerifyWait; sourceTree = ""; }; - B19207112550683500F5062F /* Room */ = { - isa = PBXGroup; - children = ( - B1920712255068B200F5062F /* RoomIdComponents.swift */, - ); - path = Room; - sourceTree = ""; - }; B1963B24228F1C4800CBA17F /* BubbleReactions */ = { isa = PBXGroup; children = ( @@ -6369,6 +6363,7 @@ B157FAA823264BED00EBFBD4 /* SettingsDiscoveryThreePidDetailsCoordinatorBridgePresenter.swift in Sources */, B169330B20F3CA3A00746532 /* Contact.m in Sources */, B1A5B33E227ADF2A004CBA85 /* UIImage.swift in Sources */, + B113DD3D255E876A0022942A /* JitsiWellKnown.swift in Sources */, EC51E7AC2514D2E100AAE7DB /* RoomInfoListCoordinatorType.swift in Sources */, B1D4752A21EE52B10067973F /* KeyBackupSetupIntroViewController.swift in Sources */, B10A3E9424FE8254007C380F /* AppCoordinatorType.swift in Sources */, @@ -6710,7 +6705,6 @@ EC51E7A62514D2E100AAE7DB /* RoomInfoCoordinatorBridgePresenter.swift in Sources */, EC1CA87524C8259700DE9EBF /* KeychainStore.swift in Sources */, B1B5575220EE6C4D00210D55 /* RoomKeyRequestViewController.m in Sources */, - B1920713255068B300F5062F /* RoomIdComponents.swift in Sources */, 32A6001A22C661100042C1D9 /* EditHistoryCoordinator.swift in Sources */, F083BD1E1E7009ED00A9B29C /* LegacyAppDelegate.m in Sources */, B1B558E620EF768F00210D55 /* RoomIncomingAttachmentWithoutSenderInfoBubbleCell.m in Sources */, @@ -6910,7 +6904,6 @@ B18DEDD5243377C10075FEF7 /* KeyVerificationSelfVerifyWaitViewModel.swift in Sources */, EC711B8B24A63B37008F830C /* SecretsRecoveryWithPassphraseViewState.swift in Sources */, ECAE7AE524EC0E01002FA813 /* TableViewSections.swift in Sources */, - B1E5EF9D2541C06000E8A883 /* JitsiWellKnown.swift in Sources */, B1CE83DA2422817200D07506 /* KeyVerificationVerifyByScanningViewModel.swift in Sources */, 32242F0921E8B05F00725742 /* UIColor.swift in Sources */, B16932E720F3C37100746532 /* HomeMessagesSearchDataSource.m in Sources */, @@ -6933,6 +6926,7 @@ ECAE7AE724EC15F7002FA813 /* Section.swift in Sources */, B1B5591020EF782800210D55 /* TableViewCellWithPhoneNumberTextField.m in Sources */, B1CE83E52422817200D07506 /* KeyVerificationVerifyBySASViewModel.swift in Sources */, + B113DD3C255E83C70022942A /* RoomIdComponents.swift in Sources */, ECFBD5ED250F97FC00DD5F5A /* RoomCreationCollapsedBubbleCell.m in Sources */, B1DB4F06223015080065DBFA /* Character.swift in Sources */, EC1CA87724C82D0E00DE9EBF /* MemoryStore.swift in Sources */, From e3d77ed7160585811ab3f2e1f744e2b5945c837c Mon Sep 17 00:00:00 2001 From: SBiOSoftWhare Date: Fri, 13 Nov 2020 10:34:44 +0100 Subject: [PATCH 07/43] Update changes --- CHANGES.rst | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGES.rst b/CHANGES.rst index 0bbaf0353..6c9a8df23 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -11,6 +11,7 @@ Changes to be released in next version * MXAnalyticsDelegate: Make it fully agnostic on tracked data. * KeyValueStore improvements. * Jitsi: Support authenticated Jitsi widgets (#3655). + * Room invites: Allow to accept a room invite without preview. 🐛 Bugfix * Fix analytics in order to track performance improvements. From ad85de8573262c0fb3701cd82970869c9d9ad40e Mon Sep 17 00:00:00 2001 From: SBiOSoftWhare Date: Fri, 13 Nov 2020 17:16:43 +0100 Subject: [PATCH 08/43] InviteRecentTableViewCell: Add disclosure indicator to indicate preview action. --- Riot/Categories/UITableViewCell.swift | 8 +++++++- .../People/Views/InviteRecentTableViewCell.m | 2 ++ .../People/Views/InviteRecentTableViewCell.xib | 18 +++++++++--------- 3 files changed, 18 insertions(+), 10 deletions(-) diff --git a/Riot/Categories/UITableViewCell.swift b/Riot/Categories/UITableViewCell.swift index 359b02134..e9ea1f8ba 100644 --- a/Riot/Categories/UITableViewCell.swift +++ b/Riot/Categories/UITableViewCell.swift @@ -18,6 +18,10 @@ import Foundation extension UITableViewCell { + + private enum AccessoryImageAlpha { + static let highlighted: CGFloat = 0.3 + } /// Returns safe area insetted separator inset. Should only be used when custom constraints on custom table view cells are being set according to separator insets. @objc var vc_separatorInset: UIEdgeInsets { @@ -30,8 +34,10 @@ extension UITableViewCell { } @objc func vc_setAccessoryDisclosureIndicator(withTintColor tintColor: UIColor) { - let disclosureImageView = UIImageView(image: Asset.Images.disclosureIcon.image) + let disclosureImage = Asset.Images.disclosureIcon.image.withRenderingMode(.alwaysTemplate) + let disclosureImageView = UIImageView(image: disclosureImage) disclosureImageView.tintColor = tintColor + disclosureImageView.highlightedImage = disclosureImage.vc_withAlpha(AccessoryImageAlpha.highlighted) self.accessoryView = disclosureImageView } diff --git a/Riot/Modules/People/Views/InviteRecentTableViewCell.m b/Riot/Modules/People/Views/InviteRecentTableViewCell.m index db2f7130c..3530a4385 100644 --- a/Riot/Modules/People/Views/InviteRecentTableViewCell.m +++ b/Riot/Modules/People/Views/InviteRecentTableViewCell.m @@ -63,6 +63,8 @@ NSString *const kInviteRecentTableViewCellRoomKey = @"kInviteRecentTableViewCell self.rightButton.backgroundColor = ThemeService.shared.theme.tintColor; self.noticeBadgeView.backgroundColor = ThemeService.shared.theme.noticeColor; + + [self vc_setAccessoryDisclosureIndicatorWithCurrentTheme]; } - (void)prepareForReuse diff --git a/Riot/Modules/People/Views/InviteRecentTableViewCell.xib b/Riot/Modules/People/Views/InviteRecentTableViewCell.xib index f1ecf7116..bca20828a 100644 --- a/Riot/Modules/People/Views/InviteRecentTableViewCell.xib +++ b/Riot/Modules/People/Views/InviteRecentTableViewCell.xib @@ -9,11 +9,11 @@ - + - + @@ -40,7 +40,7 @@ - + - + - + @@ -94,7 +94,7 @@ - + - + - + - + @@ -94,7 +94,7 @@ - +