diff --git a/CHANGES.rst b/CHANGES.rst index 6f976ca2e..bf9209684 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -5,13 +5,47 @@ Changes to be released in next version * 🙌 Improvements - * Room: Added support for Voice Messages (#4090, #4091, #4092, #4094, #4095, #4096) - * Remove the directory section from the Rooms tab. - * Notifications: Show decrypted content is enabled by default (#4519). * Tools: Add a script to initialize quickly and easily the project. +🐛 Bugfix + * + +⚠️ API Changes + * + +🗣 Translations + * + +🧱 Build + * + +Others + * + +Changes in 1.4.8 (2021-07-29) +================================================= + +✨ Features + * + +🙌 Improvements + * Room: Added support for Voice Messages (#4090, #4091, #4092, #4094, #4095, #4096) + * Rooms Tab: Remove the directory section (#4521). + * Notifications: Show decrypted content is enabled by default (#4519). + * People Tab: Remove the local contacts section (#4523). + * Contacts: Delay access to local contacts until they're needed for display (#4616). + * RecentsDataSource: Factorize section reset in one place (target #4591). + * Voice Messages: Tap/hold to send voice messages isn't intuitive (#4601). + * Voice Messages: copy could be improved (#4604). + * Slide to lock should be more generous (#4602). + 🐛 Bugfix * Room: Fixed mentioning users from room info member details (#4583) + * Settings: Disabled autocorrection when entering an identity server (#4593). + * Room Notification Settings: Fix Crash when opening the new Room Notification Settings Screen (Not yet released) (#4599). + * AuthenticationViewController: Fix crash on authentication if an intermediate view was presented (#4606). + * Room: Fixed crash when opening a read-only room (#4620). + * Voice Messages: Tapping on waveform in composer glitches UI (#4603). ⚠️ API Changes * @@ -26,6 +60,9 @@ Others * Separated CI jobs into individual actions * Update Gemfile.lock +Improvements: + * Upgrade MatrixKit version ([v0.15.6](https://github.com/matrix-org/matrix-ios-kit/releases/tag/v0.15.6)). + Changes in 1.4.7 (2021-07-22) ================================================= diff --git a/Config/AppIdentifiers.xcconfig b/Config/AppIdentifiers.xcconfig index 1628e83d8..c21273565 100644 --- a/Config/AppIdentifiers.xcconfig +++ b/Config/AppIdentifiers.xcconfig @@ -22,8 +22,8 @@ APPLICATION_GROUP_IDENTIFIER = group.im.vector APPLICATION_SCHEME = element // Version -MARKETING_VERSION = 1.4.8 -CURRENT_PROJECT_VERSION = 1.4.8 +MARKETING_VERSION = 1.4.9 +CURRENT_PROJECT_VERSION = 1.4.9 // Team diff --git a/Podfile b/Podfile index aa6b4d8f5..53b05e0e6 100644 --- a/Podfile +++ b/Podfile @@ -11,7 +11,7 @@ use_frameworks! # - `{ {kit spec hash} => {sdk spec hash}` to depend on specific pod options (:git => …, :podspec => …) for each repo. Used by Fastfile during CI # # Warning: our internal tooling depends on the name of this variable name, so be sure not to change it -$matrixKitVersion = '= 0.15.5' +$matrixKitVersion = '= 0.15.6' # $matrixKitVersion = :local # $matrixKitVersion = {'develop' => 'develop'} diff --git a/Podfile.lock b/Podfile.lock index 8a8b129b9..0024fd9b1 100644 --- a/Podfile.lock +++ b/Podfile.lock @@ -58,29 +58,29 @@ PODS: - MatomoTracker (7.4.1): - MatomoTracker/Core (= 7.4.1) - MatomoTracker/Core (7.4.1) - - MatrixKit (0.15.5): + - MatrixKit (0.15.6): - Down (~> 0.11.0) - DTCoreText (~> 1.6.25) - HPGrowingTextView (~> 1.1) - libPhoneNumber-iOS (~> 0.9.13) - - MatrixKit/Core (= 0.15.5) - - MatrixSDK (= 0.19.5) - - MatrixKit/Core (0.15.5): + - MatrixKit/Core (= 0.15.6) + - MatrixSDK (= 0.19.6) + - MatrixKit/Core (0.15.6): - Down (~> 0.11.0) - DTCoreText (~> 1.6.25) - HPGrowingTextView (~> 1.1) - libPhoneNumber-iOS (~> 0.9.13) - - MatrixSDK (= 0.19.5) - - MatrixSDK (0.19.5): - - MatrixSDK/Core (= 0.19.5) - - MatrixSDK/Core (0.19.5): + - MatrixSDK (= 0.19.6) + - MatrixSDK (0.19.6): + - MatrixSDK/Core (= 0.19.6) + - MatrixSDK/Core (0.19.6): - AFNetworking (~> 4.0.0) - GZIP (~> 1.3.0) - libbase58 (~> 0.1.4) - OLMKit (~> 3.2.4) - Realm (= 10.7.6) - SwiftyBeaver (= 1.9.5) - - MatrixSDK/JingleCallStack (0.19.5): + - MatrixSDK/JingleCallStack (0.19.6): - JitsiMeetSDK (= 3.5.0) - MatrixSDK/Core - OLMKit (3.2.4): @@ -124,7 +124,7 @@ DEPENDENCIES: - KeychainAccess (~> 4.2.2) - KTCenterFlowLayout (~> 1.3.1) - MatomoTracker (~> 7.4.1) - - MatrixKit (= 0.15.5) + - MatrixKit (= 0.15.6) - MatrixSDK - MatrixSDK/JingleCallStack - OLMKit @@ -204,8 +204,8 @@ SPEC CHECKSUMS: LoggerAPI: ad9c4a6f1e32f518fdb43a1347ac14d765ab5e3d Logging: beeb016c9c80cf77042d62e83495816847ef108b MatomoTracker: 24a846c9d3aa76933183fe9d47fd62c9efa863fb - MatrixKit: 7606227237cf58c1a1a2235547222c5d75b464c4 - MatrixSDK: 9fa30f9ca2504c4251b99212dcf4ff569bbf45b1 + MatrixKit: 740fee40187fe84099678c56b2f080d877dd7a65 + MatrixSDK: 04a7f15b03b3def5af644444f3364b8272fb8efc OLMKit: 2d73cd67d149b5c3e3a8eb8ecae93d0b429d8a02 ReadMoreTextView: 19147adf93abce6d7271e14031a00303fe28720d Realm: ed860452717c8db8f4bf832b6807f7f2ce708839 @@ -219,6 +219,6 @@ SPEC CHECKSUMS: zxcvbn-ios: fef98b7c80f1512ff0eec47ac1fa399fc00f7e3c ZXingObjC: fdbb269f25dd2032da343e06f10224d62f537bdb -PODFILE CHECKSUM: c7386ecfb38fc4302613c915aef79eebdb98a53d +PODFILE CHECKSUM: c1f1d1137ebacb6c74706cb28d5c10f26d6fe655 COCOAPODS: 1.10.1 diff --git a/Riot.xcodeproj/xcshareddata/xcschemes/Riot.xcscheme b/Riot.xcodeproj/xcshareddata/xcschemes/Riot.xcscheme index a9bea1d96..84ecb908a 100644 --- a/Riot.xcodeproj/xcshareddata/xcschemes/Riot.xcscheme +++ b/Riot.xcodeproj/xcshareddata/xcschemes/Riot.xcscheme @@ -4,8 +4,7 @@ version = "1.3"> + buildImplicitDependencies = "YES"> String { return VectorL10n.tr("Vector", "voice_message_remaining_recording_time", p1) } - /// Tap on the wavelength to stop and playback + /// Tap on your recording to stop or listen internal static var voiceMessageStopLockedModeRecording: String { return VectorL10n.tr("Vector", "voice_message_stop_locked_mode_recording") } diff --git a/Riot/Modules/Application/LegacyAppDelegate.m b/Riot/Modules/Application/LegacyAppDelegate.m index ae55cf538..a6df6cb48 100644 --- a/Riot/Modules/Application/LegacyAppDelegate.m +++ b/Riot/Modules/Application/LegacyAppDelegate.m @@ -1854,16 +1854,6 @@ NSString *const AppDelegateUniversalLinkDidChangeNotification = @"AppDelegateUni [account addObserver:self forKeyPath:@"enableInAppNotifications" options:0 context:nil]; } - // Load the local contacts on first account creation. - if ([MXKAccountManager sharedManager].accounts.count == 1) - { - dispatch_async(dispatch_get_main_queue(), ^{ - - [self refreshLocalContacts]; - - }); - } - [self.delegate legacyAppDelegate:self didAddAccount:account]; }]; @@ -1976,14 +1966,6 @@ NSString *const AppDelegateUniversalLinkDidChangeNotification = @"AppDelegateUni // during this blocking task. dispatch_after(dispatch_walltime(DISPATCH_TIME_NOW, 0.3 * NSEC_PER_SEC), dispatch_get_main_queue(), ^{ [[MXKContactManager sharedManager] addMatrixSession:mxSession]; - - // Load the local contacts on first account - if ([MXKAccountManager sharedManager].accounts.count == 1) - { - dispatch_async(dispatch_get_main_queue(), ^{ - [self refreshLocalContacts]; - }); - } }); // Register the session to the widgets manager @@ -2939,54 +2921,6 @@ NSString *const AppDelegateUniversalLinkDidChangeNotification = @"AppDelegateUni }]; } -- (void)refreshLocalContacts -{ - if (!BuildSettings.allowLocalContactsAccess) - { - return; - } - - // Do not scan local contacts in background if the user has not decided yet about using - // an identity server - BOOL doRefreshLocalContacts = NO; - for (MXSession *session in mxSessionArray) - { - if (session.hasAccountDataIdentityServerValue) - { - doRefreshLocalContacts = YES; - break; - } - } - - // Check whether the application is allowed to access the local contacts. - if (doRefreshLocalContacts - && [CNContactStore authorizationStatusForEntityType:CNEntityTypeContacts] == CNAuthorizationStatusAuthorized) - { - // Check the user permission for syncing local contacts. This permission was handled independently on previous application version. - if (![MXKAppSettings standardAppSettings].syncLocalContacts) - { - // Check whether it was not requested yet. - if (![MXKAppSettings standardAppSettings].syncLocalContactsPermissionRequested) - { - [MXKAppSettings standardAppSettings].syncLocalContactsPermissionRequested = YES; - - [MXKContactManager requestUserConfirmationForLocalContactsSyncInViewController:self.presentedViewController completionHandler:^(BOOL granted) { - - if (granted) - { - // Allow local contacts sync in order to discover matrix users. - [MXKAppSettings standardAppSettings].syncLocalContacts = YES; - } - - }]; - } - } - - // Refresh the local contacts list. - [[MXKContactManager sharedManager] refreshLocalContacts]; - } -} - #pragma mark - Matrix Groups handling - (void)showGroup:(MXGroup*)group withMatrixSession:(MXSession*)mxSession diff --git a/Riot/Modules/Authentication/AuthenticationViewController.m b/Riot/Modules/Authentication/AuthenticationViewController.m index 4d7e65964..ad064f196 100644 --- a/Riot/Modules/Authentication/AuthenticationViewController.m +++ b/Riot/Modules/Authentication/AuthenticationViewController.m @@ -354,8 +354,6 @@ static const CGFloat kAuthInputContainerViewMinHeightConstraintConstant = 150.0; { [_keyboardAvoider stopAvoiding]; - [self.authenticationActivityIndicator removeObserver:self forKeyPath:@"hidden"]; - [super viewDidDisappear:animated]; } @@ -384,6 +382,8 @@ static const CGFloat kAuthInputContainerViewMinHeightConstraintConstant = 150.0; [[NSNotificationCenter defaultCenter] removeObserver:universalLinkDidChangeNotificationObserver]; universalLinkDidChangeNotificationObserver = nil; } + + [self.authenticationActivityIndicator removeObserver:self forKeyPath:@"hidden"]; autoDiscovery = nil; _keyVerificationCoordinatorBridgePresenter = nil; diff --git a/Riot/Modules/Common/Recents/DataSources/RecentsDataSource.m b/Riot/Modules/Common/Recents/DataSources/RecentsDataSource.m index 0e2f14ea3..123d9da69 100644 --- a/Riot/Modules/Common/Recents/DataSources/RecentsDataSource.m +++ b/Riot/Modules/Common/Recents/DataSources/RecentsDataSource.m @@ -71,17 +71,9 @@ NSString *const kRecentsDataSourceTapOnDirectoryServerChange = @"kRecentsDataSou processingQueue = dispatch_queue_create("RecentsDataSource", DISPATCH_QUEUE_SERIAL); _crossSigningBannerDisplay = CrossSigningBannerDisplayNone; - crossSigningBannerSection = -1; - _secureBackupBannerDisplay = SecureBackupBannerDisplayNone; - secureBackupBannerSection = -1; - directorySection = -1; - invitesSection = -1; - favoritesSection = -1; - peopleSection = -1; - conversationSection = -1; - lowPrioritySection = -1; - serverNoticeSection = -1; + + [self resetSectionIndexes]; _areSectionsShrinkable = NO; shrinkedSectionsBitMask = 0; @@ -96,6 +88,19 @@ NSString *const kRecentsDataSourceTapOnDirectoryServerChange = @"kRecentsDataSou return self; } +- (void)resetSectionIndexes +{ + crossSigningBannerSection = -1; + secureBackupBannerSection = -1; + directorySection = -1; + invitesSection = -1; + favoritesSection = -1; + peopleSection = -1; + conversationSection = -1; + lowPrioritySection = -1; + serverNoticeSection = -1; +} + #pragma mark - Properties @@ -445,7 +450,7 @@ NSString *const kRecentsDataSourceTapOnDirectoryServerChange = @"kRecentsDataSou // Check whether all data sources are ready before rendering recents if (self.state == MXKDataSourceStateReady) { - crossSigningBannerSection = secureBackupBannerSection = directorySection = favoritesSection = peopleSection = conversationSection = lowPrioritySection = invitesSection = serverNoticeSection = -1; + [self resetSectionIndexes]; if (self.crossSigningBannerDisplay != CrossSigningBannerDisplayNone) { @@ -1119,10 +1124,8 @@ NSString *const kRecentsDataSourceTapOnDirectoryServerChange = @"kRecentsDataSou #pragma mark - MXKDataSourceDelegate -- (void)refreshRoomsSection:(void (^)(void))onComplete; +- (void)refreshRoomsSection:(void (^)(void))onComplete { - secureBackupBannerSection = directorySection = favoritesSection = peopleSection = conversationSection = lowPrioritySection = serverNoticeSection = invitesSection = -1; - if (displayedRecentsDataSourceArray.count > 0) { // FIXME manage multi accounts diff --git a/Riot/Modules/Contacts/ContactsTableViewController.m b/Riot/Modules/Contacts/ContactsTableViewController.m index 5437cd149..c9af2e4c5 100644 --- a/Riot/Modules/Contacts/ContactsTableViewController.m +++ b/Riot/Modules/Contacts/ContactsTableViewController.m @@ -174,6 +174,15 @@ [self refreshContactsTable]; } +- (void)viewDidAppear:(BOOL)animated +{ + [super viewDidAppear:animated]; + + // Load the local contacts for display. + // In viewDidAppear as it may trigger a request for contacts access. + [self refreshLocalContacts]; +} + - (void)viewWillDisappear:(BOOL)animated { [super viewWillDisappear:animated]; @@ -212,6 +221,54 @@ } } +- (void)refreshLocalContacts +{ + if (!BuildSettings.allowLocalContactsAccess) + { + return; + } + + // Do not scan local contacts in background if the user has not decided yet about using + // an identity server + BOOL doRefreshLocalContacts = NO; + for (MXSession *session in self.mxSessions) + { + if (session.hasAccountDataIdentityServerValue) + { + doRefreshLocalContacts = YES; + break; + } + } + + // Check whether the application is allowed to access the local contacts. + if (doRefreshLocalContacts + && [CNContactStore authorizationStatusForEntityType:CNEntityTypeContacts] == CNAuthorizationStatusAuthorized) + { + // Check the user permission for syncing local contacts. This permission was handled independently on previous application version. + if (![MXKAppSettings standardAppSettings].syncLocalContacts) + { + // Check whether it was not requested yet. + if (![MXKAppSettings standardAppSettings].syncLocalContactsPermissionRequested) + { + [MXKAppSettings standardAppSettings].syncLocalContactsPermissionRequested = YES; + + [MXKContactManager requestUserConfirmationForLocalContactsSyncInViewController:self completionHandler:^(BOOL granted) { + + if (granted) + { + // Allow local contacts sync in order to discover matrix users. + [MXKAppSettings standardAppSettings].syncLocalContacts = YES; + } + + }]; + } + } + + // Refresh the local contacts list. + [[MXKContactManager sharedManager] refreshLocalContacts]; + } +} + - (void)refreshContactsTable { [self.contactsTableView reloadData]; diff --git a/Riot/Modules/People/PeopleViewController.h b/Riot/Modules/People/PeopleViewController.h index 8cc3607a4..696ebbb5b 100644 --- a/Riot/Modules/People/PeopleViewController.h +++ b/Riot/Modules/People/PeopleViewController.h @@ -20,7 +20,7 @@ /** 'PeopleViewController' instance is used to display/filter the direct rooms and a list of contacts. */ -@interface PeopleViewController : RecentsViewController +@interface PeopleViewController : RecentsViewController + (instancetype)instantiate; diff --git a/Riot/Modules/People/PeopleViewController.m b/Riot/Modules/People/PeopleViewController.m index 5985ce346..26b0ca3f0 100644 --- a/Riot/Modules/People/PeopleViewController.m +++ b/Riot/Modules/People/PeopleViewController.m @@ -14,7 +14,6 @@ limitations under the License. */ -#import #import "PeopleViewController.h" #import "UIViewController+RiotSearch.h" @@ -25,17 +24,11 @@ #import "RecentTableViewCell.h" #import "InviteRecentTableViewCell.h" -#import "ContactTableViewCell.h" - #import "Riot-Swift.h" @interface PeopleViewController () { NSInteger directRoomsSectionNumber; - - ContactsDataSource *contactsDataSource; - NSInteger contactsSectionNumber; - RecentsDataSource *recentsDataSource; } @@ -55,7 +48,6 @@ [super finalizeInit]; directRoomsSectionNumber = 0; - contactsSectionNumber = 0; self.screenName = @"People"; } @@ -76,14 +68,6 @@ plusButtonImageView = [self vc_addFABWithImage:[UIImage imageNamed:@"people_floating_action"] target:self action:@selector(onPlusButtonPressed)]; - - // Register table view cell for contacts. - [self.recentsTableView registerClass:ContactTableViewCell.class forCellReuseIdentifier:ContactTableViewCell.defaultReuseIdentifier]; - - // Change the table data source. It must be the people view controller itself. - self.recentsTableView.dataSource = self; - - self.enableStickyHeaders = YES; } - (void)didReceiveMemoryWarning @@ -92,302 +76,36 @@ // Dispose of any resources that can be recreated. } -- (void)destroy -{ - contactsDataSource.delegate = nil; - [contactsDataSource destroy]; - contactsDataSource = nil; - - [super destroy]; -} - - (void)viewWillAppear:(BOOL)animated { [super viewWillAppear:animated]; - - if (BuildSettings.allowLocalContactsAccess) - { - // Check whether the access to the local contacts has not been already asked - // and check that the user has decided to use or not to use an identity server - if ([CNContactStore authorizationStatusForEntityType:CNEntityTypeContacts] == CNAuthorizationStatusNotDetermined - || !contactsDataSource.mxSession.hasAccountDataIdentityServerValue) - { - // Allow by default the local contacts sync in order to discover matrix users. - // This setting change will trigger the loading of the local contacts, which will automatically - // ask user permission to access their local contacts. - [MXKAppSettings standardAppSettings].syncLocalContacts = YES; - } - - // Refresh the local contacts list. - [[MXKContactManager sharedManager] refreshLocalContacts]; - } [AppDelegate theDelegate].masterTabBarController.navigationItem.title = NSLocalizedStringFromTable(@"title_people", @"Vector", nil); [AppDelegate theDelegate].masterTabBarController.tabBar.tintColor = ThemeService.shared.theme.tintColor; - if (recentsDataSource) + if ([self.dataSource isKindOfClass:RecentsDataSource.class]) { // Take the lead on the shared data source. + recentsDataSource = (RecentsDataSource*)self.dataSource; recentsDataSource.areSectionsShrinkable = NO; [recentsDataSource setDelegate:self andRecentsDataSourceMode:RecentsDataSourceModePeople]; } } -#pragma mark - - -- (void)displayList:(MXKRecentsDataSource *)listDataSource -{ - [super displayList:listDataSource]; - - // Change the table data source. It must be the people view controller itself. - self.recentsTableView.dataSource = self; - - // Keep a ref on the recents data source - if ([listDataSource isKindOfClass:RecentsDataSource.class]) - { - recentsDataSource = (RecentsDataSource*)listDataSource; - } - - if (BuildSettings.allowLocalContactsAccess) - { - if (!contactsDataSource) - { - // Prepare its contacts data source - contactsDataSource = [[ContactsDataSource alloc] initWithMatrixSession:listDataSource.mxSession]; - contactsDataSource.contactCellAccessoryImage = [[UIImage imageNamed: @"disclosure_icon"] vc_tintedImageUsingColor:ThemeService.shared.theme.textSecondaryColor]; - contactsDataSource.delegate = self; - } - } -} - -#pragma mark - MXKDataSourceDelegate - -- (Class)cellViewClassForCellData:(MXKCellData*)cellData -{ - if ([cellData isKindOfClass:MXKContact.class]) - { - return ContactTableViewCell.class; - } - - return [super cellViewClassForCellData:cellData]; -} - -#pragma mark - UITableView data source - -- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView -{ - // Retrieve the current number of sections related to the direct rooms. - // Sanity check: check whether the recents data source is correctly configured. - directRoomsSectionNumber = 0; - - if (recentsDataSource.recentsDataSourceMode == RecentsDataSourceModePeople) - { - directRoomsSectionNumber = [self.dataSource numberOfSectionsInTableView:self.recentsTableView]; - } - - // Retrieve the current number of sections related to the contacts - contactsSectionNumber = [contactsDataSource numberOfSectionsInTableView:self.recentsTableView]; - - return (directRoomsSectionNumber + contactsSectionNumber); -} - -- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section -{ - NSInteger count = 0; - - if (section < directRoomsSectionNumber) - { - count = [self.dataSource tableView:tableView numberOfRowsInSection:section]; - } - else - { - section -= directRoomsSectionNumber; - if (section < contactsSectionNumber) - { - count = [contactsDataSource tableView:tableView numberOfRowsInSection:section]; - } - } - - return count; -} - -- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath -{ - NSInteger section = indexPath.section; - - if (section < directRoomsSectionNumber) - { - return [self.dataSource tableView:tableView cellForRowAtIndexPath:indexPath]; - } - else - { - section -= directRoomsSectionNumber; - if (section < contactsSectionNumber) - { - return [contactsDataSource tableView:tableView cellForRowAtIndexPath:[NSIndexPath indexPathForRow:indexPath.row inSection:section]]; - } - } - - // Return a fake cell to prevent app from crashing. - return [[UITableViewCell alloc] init]; -} - -- (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath -{ - NSInteger section = indexPath.section; - - if (section < directRoomsSectionNumber) - { - return [self.dataSource tableView:tableView canEditRowAtIndexPath:indexPath]; - } - else - { - section -= directRoomsSectionNumber; - if (section < contactsSectionNumber) - { - return [contactsDataSource tableView:tableView canEditRowAtIndexPath:[NSIndexPath indexPathForRow:indexPath.row inSection:section]]; - } - } - - return NO; -} - #pragma mark - UITableView delegate - (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section { - if (section >= directRoomsSectionNumber) - { - // Let the contact dataSource provide the height of the section header. - section -= directRoomsSectionNumber; - if (section < contactsSectionNumber) - { - return [contactsDataSource heightForHeaderInSection:section]; - } - else - { - return 0.0; - } - } - - return [super tableView:tableView heightForHeaderInSection:section]; + return 0.0; } - (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section { - if (section >= directRoomsSectionNumber) - { - // Let the contact dataSource provide the section header. - CGRect frame = [tableView rectForHeaderInSection:section]; - section -= directRoomsSectionNumber; - if (section < contactsSectionNumber) - { - UIView *sectionHeader = [contactsDataSource viewForHeaderInSection:section withFrame:frame]; - sectionHeader.tag = section + directRoomsSectionNumber; - - if (self.enableStickyHeaders) - { - while (sectionHeader.gestureRecognizers.count) - { - UIGestureRecognizer *gestureRecognizer = sectionHeader.gestureRecognizers.lastObject; - [sectionHeader removeGestureRecognizer:gestureRecognizer]; - } - - // Handle tap gesture - UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(didTapOnSectionHeader:)]; - [tap setNumberOfTouchesRequired:1]; - [tap setNumberOfTapsRequired:1]; - [sectionHeader addGestureRecognizer:tap]; - } - - return sectionHeader; - } - else - { - return nil; - } - } - - return [super tableView:tableView viewForHeaderInSection:section]; -} - -- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath -{ - NSInteger section = indexPath.section; - if (section >= directRoomsSectionNumber) - { - section -= directRoomsSectionNumber; - if (section < contactsSectionNumber) - { - if ([contactsDataSource contactAtIndexPath:[NSIndexPath indexPathForRow:indexPath.row inSection:section]]) - { - // Return the default height of the contact cell - return 74.0; - } - - return 50; - } - else - { - return 0.0; - } - } - - return [super tableView:tableView heightForRowAtIndexPath:indexPath]; -} - -- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath -{ - NSInteger section = indexPath.section; - if (section >= directRoomsSectionNumber) - { - section -= directRoomsSectionNumber; - if (section < contactsSectionNumber) - { - MXKContact *mxkContact = [contactsDataSource contactAtIndexPath:[NSIndexPath indexPathForRow:indexPath.row inSection:section]]; - - if (mxkContact) - { - [[AppDelegate theDelegate].masterTabBarController selectContact:mxkContact]; - - // Keep selected the cell by default. - return; - } - } - else - { - [tableView deselectRowAtIndexPath:indexPath animated:NO]; - return; - } - } - - return [super tableView:tableView didSelectRowAtIndexPath:indexPath]; + return nil; } #pragma mark - Override RecentsViewController -- (UIView *)tableView:(UITableView *)tableView viewForStickyHeaderInSection:(NSInteger)section -{ - CGRect frame = [tableView rectForHeaderInSection:section]; - frame.size.height = self.stickyHeaderHeight; - - if (section >= directRoomsSectionNumber) - { - // Let the contact dataSource provide this header. - section -= directRoomsSectionNumber; - if (section < contactsSectionNumber) - { - return [contactsDataSource viewForStickyHeaderInSection:section withFrame:frame]; - } - } - else if (recentsDataSource) - { - return [recentsDataSource viewForStickyHeaderInSection:section withFrame:frame]; - } - - return nil; -} - - (void)refreshCurrentSelectedCell:(BOOL)forceVisible { // Check whether the recents data source is correctly configured. @@ -396,41 +114,7 @@ return; } - // Update here the index of the current selected cell (if any) - Useful in landscape mode with split view controller. - NSIndexPath *currentSelectedCellIndexPath = nil; - MasterTabBarController *masterTabBarController = [AppDelegate theDelegate].masterTabBarController; - if (masterTabBarController.currentContactDetailViewController) - { - // Look for the rank of this selected contact - currentSelectedCellIndexPath = [contactsDataSource cellIndexPathWithContact:masterTabBarController.selectedContact]; - - if (currentSelectedCellIndexPath) - { - // Select the right row - currentSelectedCellIndexPath = [NSIndexPath indexPathForRow:currentSelectedCellIndexPath.row inSection:(directRoomsSectionNumber + currentSelectedCellIndexPath.section)]; - [self.recentsTableView selectRowAtIndexPath:currentSelectedCellIndexPath animated:YES scrollPosition:UITableViewScrollPositionNone]; - - if (forceVisible) - { - // Scroll table view to make the selected row appear at second position - NSInteger topCellIndexPathRow = currentSelectedCellIndexPath.row ? currentSelectedCellIndexPath.row - 1: currentSelectedCellIndexPath.row; - NSIndexPath* indexPath = [NSIndexPath indexPathForRow:topCellIndexPathRow inSection:currentSelectedCellIndexPath.section]; - [self.recentsTableView scrollToRowAtIndexPath:indexPath atScrollPosition:UITableViewScrollPositionTop animated:NO]; - } - } - else - { - NSIndexPath *indexPath = [self.recentsTableView indexPathForSelectedRow]; - if (indexPath) - { - [self.recentsTableView deselectRowAtIndexPath:indexPath animated:NO]; - } - } - } - else - { - [super refreshCurrentSelectedCell:forceVisible]; - } + [super refreshCurrentSelectedCell:forceVisible]; } - (void)onPlusButtonPressed @@ -449,24 +133,6 @@ } } -#pragma mark - UISearchBarDelegate - -- (void)searchBar:(UISearchBar *)searchBar textDidChange:(NSString *)searchText -{ - // Apply filter on contact source - [contactsDataSource searchWithPattern:searchText forceReset:NO]; - - [super searchBar:searchBar textDidChange:searchText]; -} - -- (void)searchBarCancelButtonClicked:(UISearchBar *)searchBar -{ - // Reset filtering - [contactsDataSource searchWithPattern:nil forceReset:NO]; - - [super searchBarCancelButtonClicked:searchBar]; -} - #pragma mark - Empty view management - (void)updateEmptyView @@ -503,35 +169,7 @@ - (NSUInteger)totalItemCounts { return recentsDataSource.invitesCellDataArray.count - + recentsDataSource.conversationCellDataArray.count - + recentsDataSource.peopleCellDataArray.count - + [self numberOfContactsInContactsDataSource]; -} - -- (NSUInteger)numberOfContactsInContactsDataSource -{ - BOOL areLocalContactsAccessAuthorized = [CNContactStore authorizationStatusForEntityType:CNEntityTypeContacts] == CNAuthorizationStatusAuthorized; - - NSInteger nbOfItemsInContactDataSource = 0; - - for (NSInteger i = 0; i < contactsSectionNumber; i++) - { - nbOfItemsInContactDataSource += [contactsDataSource tableView:self.recentsTableView numberOfRowsInSection:i]; - } - - NSInteger numberOfContactsInContactsDataSource; - - // No local contacts to show and no search in directory - if (!areLocalContactsAccessAuthorized && contactsSectionNumber == 1 && nbOfItemsInContactDataSource <= 1) - { - numberOfContactsInContactsDataSource = 0; - } - else - { - numberOfContactsInContactsDataSource = nbOfItemsInContactDataSource; - } - - return numberOfContactsInContactsDataSource; + + recentsDataSource.conversationCellDataArray.count; } @end diff --git a/Riot/Modules/Room/NotificationSettings/RoomNotificationsSettingsService.swift b/Riot/Modules/Room/NotificationSettings/RoomNotificationsSettingsService.swift index 1bd0e4b6b..b62c7ea60 100644 --- a/Riot/Modules/Room/NotificationSettings/RoomNotificationsSettingsService.swift +++ b/Riot/Modules/Room/NotificationSettings/RoomNotificationsSettingsService.swift @@ -264,11 +264,17 @@ fileprivate extension MXRoom { } var overridePushRule: MXPushRule? { - getRoomRule(from: mxSession.notificationCenter.rules.global.override) + guard let overrideRules = mxSession.notificationCenter.rules.global.override else { + return nil + } + return getRoomRule(from: overrideRules) } var roomPushRule: MXPushRule? { - getRoomRule(from: mxSession.notificationCenter.rules.global.room) + guard let roomRules = mxSession.notificationCenter.rules.global.room else { + return nil + } + return getRoomRule(from: roomRules) } var notificationState: RoomNotificationState { diff --git a/Riot/Modules/Room/RoomViewController.m b/Riot/Modules/Room/RoomViewController.m index 8d32e11e8..56542e5cc 100644 --- a/Riot/Modules/Room/RoomViewController.m +++ b/Riot/Modules/Room/RoomViewController.m @@ -1126,7 +1126,11 @@ const NSTimeInterval kResizeComposerAnimationDuration = .05; { [super setRoomInputToolbarViewClass:roomInputToolbarViewClass]; - [(RoomInputToolbarView *)self.inputToolbarView setVoiceMessageToolbarView:self.voiceMessageController.voiceMessageToolbarView]; + // The voice message toolbar cannot be set on DisabledInputToolbarView. + if ([self.inputToolbarView isKindOfClass:RoomInputToolbarView.class]) + { + [(RoomInputToolbarView *)self.inputToolbarView setVoiceMessageToolbarView:self.voiceMessageController.voiceMessageToolbarView]; + } [self updateInputToolBarViewHeight]; } diff --git a/Riot/Modules/Room/VoiceMessages/VoiceMessageToolbarView.swift b/Riot/Modules/Room/VoiceMessages/VoiceMessageToolbarView.swift index 4650d6fae..f0b27fd46 100644 --- a/Riot/Modules/Room/VoiceMessages/VoiceMessageToolbarView.swift +++ b/Riot/Modules/Room/VoiceMessages/VoiceMessageToolbarView.swift @@ -45,7 +45,7 @@ struct VoiceMessageToolbarViewDetails { class VoiceMessageToolbarView: PassthroughView, NibLoadable, Themable, UIGestureRecognizerDelegate, VoiceMessagePlaybackViewDelegate { private enum Constants { - static let longPressMinimumDuration: TimeInterval = 1.0 + static let longPressMinimumDuration: TimeInterval = 0.0 static let animationDuration: TimeInterval = 0.25 static let lockModeTransitionAnimationDuration: TimeInterval = 0.5 static let panDirectionChangeThreshold: CGFloat = 20.0 @@ -145,7 +145,7 @@ class VoiceMessageToolbarView: PassthroughView, NibLoadable, Themable, UIGesture convertedFrame = self.convert(lockChevron.frame, from: lockContainerView) lockChevronToRecordButtonDistance = recordButtonsContainerView.frame.midY + convertedFrame.maxY - lockChevronToLockButtonDistance = lockChevron.frame.minY - lockButtonsContainerView.frame.midY + lockChevronToLockButtonDistance = (lockChevron.frame.minY - lockButtonsContainerView.frame.midY) / 2 startAnimatingRecordingIndicator() default: @@ -393,6 +393,10 @@ class VoiceMessageToolbarView: PassthroughView, NibLoadable, Themable, UIGesture } @objc private func handleWaveformTap(_ gestureRecognizer: UITapGestureRecognizer) { + guard self.lastUIState == .lockedModeRecord else { + return + } + delegate?.voiceMessageToolbarViewDidRequestRecordingFinish(self) } } diff --git a/Riot/Modules/Settings/IdentityServer/SettingsIdentityServerViewController.storyboard b/Riot/Modules/Settings/IdentityServer/SettingsIdentityServerViewController.storyboard index ab35e9993..b33325642 100644 --- a/Riot/Modules/Settings/IdentityServer/SettingsIdentityServerViewController.storyboard +++ b/Riot/Modules/Settings/IdentityServer/SettingsIdentityServerViewController.storyboard @@ -1,11 +1,9 @@ - - - - + + - + @@ -19,7 +17,7 @@ - + @@ -38,9 +36,8 @@ - - + @@ -63,7 +60,7 @@ -