Reduce the number of unnecessary home page reloads

This commit is contained in:
Andy Uhnak 2022-04-04 11:38:27 +01:00
parent 53a6c29743
commit 08b48b6285
7 changed files with 99 additions and 97 deletions

View file

@ -1501,35 +1501,41 @@ NSString *const kRecentsDataSourceTapOnDirectoryServerChange = @"kRecentsDataSou
forSection:(RecentsListServiceSection)section
totalCountsChanged:(BOOL)totalCountsChanged
{
NSInteger sectionIndex = -1;
switch (section)
RecentsDataSourceSections *updatedSections = [self makeDataSourceSections];
BOOL hasChangedSections = ![self.sections isEqual:updatedSections];
if (hasChangedSections) {
// If the number or order of sections has changed, we reload all of the data
[self.delegate dataSource:self didCellChange:nil];
return;
}
RecentsDataSourceSectionType sectionType = [self sectionTypeForServiceSection:section];
NSInteger sectionIndex = [self.sections sectionIndexForSectionType:sectionType];
if (sectionIndex >= 0) {
NSIndexPath *indexPath = [NSIndexPath indexPathForRow:0 inSection:(NSUInteger)sectionIndex];
[self.delegate dataSource:self didCellChange:indexPath];
}
}
- (RecentsDataSourceSectionType)sectionTypeForServiceSection:(RecentsListServiceSection)serviceSection
{
switch (serviceSection)
{
case RecentsListServiceSectionInvited:
sectionIndex = [self.sections sectionIndexForSectionType:RecentsDataSourceSectionTypeInvites];
break;
return RecentsDataSourceSectionTypeInvites;
case RecentsListServiceSectionFavorited:
sectionIndex = [self.sections sectionIndexForSectionType:RecentsDataSourceSectionTypeFavorites];
break;
return RecentsDataSourceSectionTypeFavorites;
case RecentsListServiceSectionPeople:
sectionIndex = [self.sections sectionIndexForSectionType:RecentsDataSourceSectionTypePeople];
break;
return RecentsDataSourceSectionTypePeople;
case RecentsListServiceSectionConversation:
sectionIndex = [self.sections sectionIndexForSectionType:RecentsDataSourceSectionTypeConversation];
break;
return RecentsDataSourceSectionTypeConversation;
case RecentsListServiceSectionLowPriority:
sectionIndex = [self.sections sectionIndexForSectionType:RecentsDataSourceSectionTypeLowPriority];
break;
return RecentsDataSourceSectionTypeLowPriority;
case RecentsListServiceSectionServerNotice:
sectionIndex = [self.sections sectionIndexForSectionType:RecentsDataSourceSectionTypeServerNotice];
break;
return RecentsDataSourceSectionTypeServerNotice;
case RecentsListServiceSectionSuggested:
sectionIndex = [self.sections sectionIndexForSectionType:RecentsDataSourceSectionTypeSuggestedRooms];
break;
return RecentsDataSourceSectionTypeSuggestedRooms;
}
RecentsSectionUpdate *update = [[RecentsSectionUpdate alloc] initWithSectionIndex:sectionIndex
totalCountsChanged:totalCountsChanged];
[self.delegate dataSource:self didCellChange:update];
}
#pragma mark - Shrinkable

View file

@ -75,4 +75,11 @@ import Foundation
}
return item.key
}
override func isEqual(_ object: Any?) -> Bool {
guard let other = object as? RecentsDataSourceSections else {
return false
}
return sections == other.sections
}
}

View file

@ -1,40 +0,0 @@
//
// Copyright 2021 New Vector Ltd
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
import Foundation
/// Object to represent a recents section update. Will be used as the `changes` parameter of `-[MXKDataSourceDelegate dataSource:didCellChange:]`method.
@objcMembers
class RecentsSectionUpdate: NSObject {
/// Updated section index.
let sectionIndex: Int
/// Flag indicating the total counts on the section have changed or not.
let totalCountsChanged: Bool
init(withSectionIndex sectionIndex: Int,
totalCountsChanged: Bool) {
self.sectionIndex = sectionIndex
self.totalCountsChanged = totalCountsChanged
super.init()
}
/// Flag indicating the section update info is valid. If `true`, only the related section at `sectionIndex` can be reloaded.
var isValid: Bool {
return sectionIndex >= 0
}
}

View file

@ -363,6 +363,7 @@ NSString *const RecentsViewControllerDataReadyNotification = @"RecentsViewContro
- (void)refreshRecentsTable
{
MXLogDebug(@"[RecentsViewController]: Refreshing recents table view")
// Refresh the tabBar icon badges
[[AppDelegate theDelegate].masterTabBarController refreshTabBarBadges];
@ -1031,49 +1032,44 @@ NSString *const RecentsViewControllerDataReadyNotification = @"RecentsViewContro
- (void)dataSource:(MXKDataSource *)dataSource didCellChange:(id)changes
{
BOOL cellReloaded = NO;
if ([changes isKindOfClass:RecentsSectionUpdate.class])
if ([changes isKindOfClass:NSIndexPath.class])
{
RecentsSectionUpdate *update = (RecentsSectionUpdate*)changes;
if (update.isValid && !update.totalCountsChanged)
NSIndexPath *indexPath = (NSIndexPath *)changes;
UITableViewCell *cell = [self.recentsTableView cellForRowAtIndexPath:indexPath];
if ([cell isKindOfClass:TableViewCellWithCollectionView.class])
{
NSIndexPath *indexPath = [NSIndexPath indexPathForRow:0 inSection:update.sectionIndex];
UITableViewCell *cell = [self.recentsTableView cellForRowAtIndexPath:indexPath];
if ([cell isKindOfClass:TableViewCellWithCollectionView.class])
{
TableViewCellWithCollectionView *collectionViewCell = (TableViewCellWithCollectionView *)cell;
[collectionViewCell.collectionView reloadData];
cellReloaded = YES;
MXLogDebug(@"[RecentsViewController]: Reloading nested collection view cell in section %ld", indexPath.section);
TableViewCellWithCollectionView *collectionViewCell = (TableViewCellWithCollectionView *)cell;
[collectionViewCell.collectionView reloadData];
CGRect headerFrame = [self.recentsTableView rectForHeaderInSection:update.sectionIndex];
UIView *headerView = [self.recentsTableView headerViewForSection:update.sectionIndex];
UIView *updatedHeaderView = [self.dataSource viewForHeaderInSection:update.sectionIndex withFrame:headerFrame inTableView:self.recentsTableView];
if ([headerView isKindOfClass:SectionHeaderView.class]
&& [updatedHeaderView isKindOfClass:SectionHeaderView.class])
{
SectionHeaderView *sectionHeaderView = (SectionHeaderView *)headerView;
SectionHeaderView *updatedSectionHeaderView = (SectionHeaderView *)updatedHeaderView;
sectionHeaderView.headerLabel = updatedSectionHeaderView.headerLabel;
sectionHeaderView.accessoryView = updatedSectionHeaderView.accessoryView;
sectionHeaderView.rightAccessoryView = updatedSectionHeaderView.rightAccessoryView;
}
CGRect headerFrame = [self.recentsTableView rectForHeaderInSection:indexPath.section];
UIView *headerView = [self.recentsTableView headerViewForSection:indexPath.section];
UIView *updatedHeaderView = [self.dataSource viewForHeaderInSection:indexPath.section withFrame:headerFrame inTableView:self.recentsTableView];
if ([headerView isKindOfClass:SectionHeaderView.class]
&& [updatedHeaderView isKindOfClass:SectionHeaderView.class])
{
SectionHeaderView *sectionHeaderView = (SectionHeaderView *)headerView;
SectionHeaderView *updatedSectionHeaderView = (SectionHeaderView *)updatedHeaderView;
sectionHeaderView.headerLabel = updatedSectionHeaderView.headerLabel;
sectionHeaderView.accessoryView = updatedSectionHeaderView.accessoryView;
sectionHeaderView.rightAccessoryView = updatedSectionHeaderView.rightAccessoryView;
}
} else {
MXLogDebug(@"[RecentsViewController]: Reloading table view section %ld", indexPath.section);
[self.recentsTableView reloadSections:[NSIndexSet indexSetWithIndex:indexPath.section] withRowAnimation:UITableViewRowAnimationNone];
}
} else if (!changes) {
MXLogDebug(@"[RecentsViewController]: Reloading the entire table view");
[self refreshRecentsTable];
}
if (!cellReloaded)
{
[super dataSource:dataSource didCellChange:changes];
}
else
{
// Since we've enabled room list pagination, `refreshRecentsTable` not called in this case.
// Refresh tab bar badges separately.
[[AppDelegate theDelegate].masterTabBarController refreshTabBarBadges];
}
// Since we've enabled room list pagination, `refreshRecentsTable` not called in this case.
// Refresh tab bar badges separately.
[[AppDelegate theDelegate].masterTabBarController refreshTabBarBadges];
[self showEmptyViewIfNeeded];
if (dataSource.state == MXKDataSourceStateReady)
{
[[NSNotificationCenter defaultCenter] postNotificationName:RecentsViewControllerDataReadyNotification

View file

@ -1,4 +1,4 @@
//
//
// Copyright 2021 New Vector Ltd
//
// Licensed under the Apache License, Version 2.0 (the "License");
@ -610,9 +610,10 @@ public class RecentsListService: NSObject, RecentsListServiceProtocol {
multicastDelegate.invoke { $0.recentsListServiceDidChangeData?(self,
forSection: section,
totalCountsChanged: totalCountsChanged) }
} else {
multicastDelegate.invoke { $0.recentsListServiceDidChangeData?(self,
totalCountsChanged: totalCountsChanged) }
}
multicastDelegate.invoke { $0.recentsListServiceDidChangeData?(self,
totalCountsChanged: totalCountsChanged) }
}
deinit {

View file

@ -112,4 +112,35 @@ class RecentsDataSourceSectionsTests: XCTestCase {
]
)
}
func test_equalsIfSameSectionsInSameOrder() {
let original = RecentsDataSourceSections(sectionTypes: [
.favorites,
.invites,
.lowPriority,
.searchedRoom,
])
let sameOrder = RecentsDataSourceSections(sectionTypes: [
.favorites,
.invites,
.lowPriority,
.searchedRoom,
])
let differentOrder = RecentsDataSourceSections(sectionTypes: [
.lowPriority,
.favorites,
.invites,
.searchedRoom,
])
let differentSections = RecentsDataSourceSections(sectionTypes: [
.favorites,
.serverNotice,
.lowPriority,
.searchedRoom,
])
XCTAssertEqual(original, sameOrder)
XCTAssertNotEqual(original, differentOrder)
XCTAssertNotEqual(original, differentSections)
}
}

1
changelog.d/5619.bugfix Normal file
View file

@ -0,0 +1 @@
Home: Reduce the number of unnecessary home page reloads