Feature/2865 participant sorting

This commit is contained in:
Frank Rotermund
2022-06-01 13:53:23 +00:00
parent 30a0d78d5f
commit df14eedff6
10 changed files with 385 additions and 187 deletions
@@ -39,6 +39,8 @@
NSString *currentSearchText;
NSMutableArray<Contact*> *filteredActualParticipants;
NSMutableArray<Contact*> *filteredInvitedParticipants;
NSMutableArray<Contact*> *filteredAdminParticipants;
NSMutableArray<Contact*> *filteredModParticipants;
// Mask view while processing a request
UIActivityIndicatorView *pendingMaskSpinnerView;
@@ -247,10 +249,14 @@
filteredActualParticipants = nil;
filteredInvitedParticipants = nil;
filteredAdminParticipants = nil;
filteredModParticipants = nil;
actualParticipants = nil;
invitedParticipants = nil;
userParticipant = nil;
adminParticipants = nil;
modParticipants = nil;
[self removePendingActionMask];
@@ -580,6 +586,8 @@
{
actualParticipants = [NSMutableArray array];
invitedParticipants = [NSMutableArray array];
adminParticipants = [NSMutableArray array];
modParticipants = [NSMutableArray array];
userParticipant = nil;
if (self.mxRoom)
@@ -596,21 +604,7 @@
for (MXRoomMember *mxMember in members)
{
// Update the current participants list
if ([mxMember.userId isEqualToString:userId])
{
if (mxMember.membership == MXMembershipJoin || mxMember.membership == MXMembershipInvite)
{
// The user is in this room
NSString *displayName = [VectorL10n you];
self->userParticipant = [[Contact alloc] initMatrixContactWithDisplayName:displayName andMatrixID:userId];
self->userParticipant.mxMember = [roomState.members memberWithUserId:userId];
}
}
else
{
[self handleRoomMember:mxMember];
}
[self handleRoomMember:mxMember];
}
for (MXRoomThirdPartyInvite *roomThirdPartyInvite in roomThirdPartyInvites)
@@ -648,10 +642,24 @@
Contact *contact = [[Contact alloc] initMatrixContactWithDisplayName:displayName andMatrixID:mxMember.userId];
contact.mxMember = mxMember;
MXRoomState* roomState = self.mxRoom.dangerousSyncState;
// Update member power level
MXRoomPowerLevels *powerLevels = [roomState powerLevels];
NSInteger powerLevel = [powerLevels powerLevelOfUserWithUserID:mxMember.userId];
RoomPowerLevel roomPowerLevel = [RoomPowerLevelHelper roomPowerLevelFrom:powerLevel];
if (mxMember.membership == MXMembershipInvite)
{
[invitedParticipants addObject:contact];
}
else if (roomPowerLevel == RoomPowerLevelAdmin) {
[adminParticipants addObject:contact];
}
else if (roomPowerLevel == RoomPowerLevelModerator) {
[modParticipants addObject:contact];
}
else
{
[actualParticipants addObject:contact];
@@ -704,6 +712,34 @@
}
}
if (adminParticipants.count)
{
for (index = 0; index < adminParticipants.count; index++)
{
Contact *contact = adminParticipants[index];
if (contact.mxMember && [contact.mxMember.userId isEqualToString:key])
{
[adminParticipants removeObjectAtIndex:index];
return;
}
}
}
if (modParticipants.count)
{
for (index = 0; index < modParticipants.count; index++)
{
Contact *contact = modParticipants[index];
if (contact.mxMember && [contact.mxMember.userId isEqualToString:key])
{
[modParticipants removeObjectAtIndex:index];
return;
}
}
}
if (invitedParticipants.count)
{
for (index = 0; index < invitedParticipants.count; index++)
@@ -732,6 +768,9 @@
// ...and then alphabetically.
// We could tiebreak instead by "last recently spoken in this room" if we wanted to.
NSComparator comparator = ^NSComparisonResult(Contact *contactA, Contact *contactB) {
if (BwiBuildSettings.bwiUserLabelParticipantSorting == true) {
return [self bwiParticipantsCompareLeft:contactA right:contactB];
}
MXUser *userA = [self.mxRoom.mxSession userWithUserId:contactA.mxMember.userId];
MXUser *userB = [self.mxRoom.mxSession userWithUserId:contactB.mxMember.userId];
@@ -748,7 +787,7 @@
{
return NSOrderedDescending;
}
if (userA.currentlyActive && userB.currentlyActive)
{
// Order first by power levels (admins then moderators then others)
@@ -806,6 +845,8 @@
// Sort each participants list in alphabetical order
[actualParticipants sortUsingComparator:comparator];
[invitedParticipants sortUsingComparator:comparator];
[adminParticipants sortUsingComparator:comparator];
[modParticipants sortUsingComparator:comparator];
// Reload search result if any
[self reloadSearchResult];
@@ -916,10 +957,20 @@
{
NSInteger count = 0;
participantsSection = invitedSection = -1;
participantsSection = invitedSection = adminSection = modSection = -1;
if (currentSearchText.length)
{
if (filteredAdminParticipants.count)
{
adminSection = count++;
}
if (filteredModParticipants.count)
{
modSection = count++;
}
if (filteredActualParticipants.count)
{
participantsSection = count++;
@@ -932,6 +983,14 @@
}
else
{
if (adminParticipants.count) {
adminSection = count++;
}
if (modParticipants.count) {
modSection = count++;
}
if (userParticipant || actualParticipants.count)
{
participantsSection = count++;
@@ -965,6 +1024,28 @@
}
}
}
else if (section == adminSection)
{
if (currentSearchText.length)
{
count = filteredAdminParticipants.count;
}
else
{
count = adminParticipants.count;
}
}
else if (section == modSection)
{
if (currentSearchText.length)
{
count = filteredModParticipants.count;
}
else
{
count = modParticipants.count;
}
}
else if (section == invitedSection)
{
if (currentSearchText.length)
@@ -983,107 +1064,57 @@
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell;
ContactTableViewCell* participantCell = [tableView dequeueReusableCellWithIdentifier:@"ParticipantTableViewCellId" forIndexPath:indexPath];
participantCell.selectionStyle = UITableViewCellSelectionStyleNone;
participantCell.showCustomAccessoryView = self.showParticipantCustomAccessoryView;
if (indexPath.section == participantsSection || indexPath.section == invitedSection)
participantCell.mxRoom = self.mxRoom;
Contact *contact = [self contactAtIndexPath:indexPath];
if (contact)
{
ContactTableViewCell* participantCell = [tableView dequeueReusableCellWithIdentifier:@"ParticipantTableViewCellId" forIndexPath:indexPath];
participantCell.selectionStyle = UITableViewCellSelectionStyleNone;
participantCell.showCustomAccessoryView = self.showParticipantCustomAccessoryView;
[participantCell render:contact];
participantCell.mxRoom = self.mxRoom;
Contact *contact;
if ((indexPath.section == participantsSection && userParticipant && indexPath.row == 0) && !currentSearchText.length)
if (contact.mxMember)
{
// oneself dedicated cell
contact = userParticipant;
}
else
{
NSInteger index = indexPath.row;
NSArray *participants;
MXRoomState *roomState = self.mxRoom.dangerousSyncState;
if (indexPath.section == participantsSection)
{
if (currentSearchText.length)
{
participants = filteredActualParticipants;
}
else
{
participants = actualParticipants;
if (userParticipant)
{
index --;
}
}
}
else
{
if (currentSearchText.length)
{
participants = filteredInvitedParticipants;
}
else
{
participants = invitedParticipants;
}
// Update member power level
MXRoomPowerLevels *powerLevels = [roomState powerLevels];
NSInteger powerLevel = [powerLevels powerLevelOfUserWithUserID:contact.mxMember.userId];
RoomPowerLevel roomPowerLevel = [RoomPowerLevelHelper roomPowerLevelFrom:powerLevel];
NSString *powerLevelText;
switch (roomPowerLevel) {
case RoomPowerLevelAdmin:
powerLevelText = [VectorL10n roomMemberPowerLevelShortAdmin];
break;
case RoomPowerLevelModerator:
powerLevelText = [VectorL10n roomMemberPowerLevelShortModerator];
break;
default:
powerLevelText = nil;
break;
}
if (index < participants.count)
{
contact = participants[index];
}
}
if (contact)
{
[participantCell render:contact];
participantCell.powerLevelLabel.text = powerLevelText;
if (contact.mxMember)
// Update the contact display name by considering the current room state.
if (contact.mxMember.userId)
{
MXRoomState *roomState = self.mxRoom.dangerousSyncState;
participantCell.contactDisplayNameLabel.text = [roomState.members memberName:contact.mxMember.userId];
}
if (BwiBuildSettings.bwiUserLabelsParticipantsVisible) {
contact.bwiUserLabel = [self.bwiUserLabelService getUserLabelWithUser:contact.mxMember.userId];
// Update member power level
MXRoomPowerLevels *powerLevels = [roomState powerLevels];
NSInteger powerLevel = [powerLevels powerLevelOfUserWithUserID:contact.mxMember.userId];
RoomPowerLevel roomPowerLevel = [RoomPowerLevelHelper roomPowerLevelFrom:powerLevel];
NSString *powerLevelText;
switch (roomPowerLevel) {
case RoomPowerLevelAdmin:
powerLevelText = [VectorL10n roomMemberPowerLevelShortAdmin];
break;
case RoomPowerLevelModerator:
powerLevelText = [VectorL10n roomMemberPowerLevelShortModerator];
break;
default:
powerLevelText = nil;
break;
}
participantCell.powerLevelLabel.text = powerLevelText;
// Update the contact display name by considering the current room state.
if (contact.mxMember.userId)
{
participantCell.contactDisplayNameLabel.text = [roomState.members memberName:contact.mxMember.userId];
}
if (BwiBuildSettings.bwiUserLabelsParticipantsVisible) {
contact.bwiUserLabel = [self.bwiUserLabelService getUserLabelWithUser:contact.mxMember.userId];
if (!participantCell.powerLevelLabel.text) {
participantCell.powerLevelLabel.text = contact.bwiUserLabel;
}
}
participantCell.powerLevelLabel.text = contact.bwiUserLabel;
}
}
cell = participantCell;
}
else
@@ -1136,40 +1167,40 @@
- (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section
{
CGFloat height = 0.0;
if (section == invitedSection)
{
height = 30.0;
}
return height;
return 30.0;
}
- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section
{
UIView* sectionHeader;
UIView* sectionHeader = [[UIView alloc] initWithFrame:CGRectMake(0, 0, tableView.frame.size.width, 30)];
sectionHeader.backgroundColor = ThemeService.shared.theme.headerBackgroundColor;
CGRect frame = sectionHeader.frame;
frame.origin.x = 20;
frame.origin.y = 5;
frame.size.width = sectionHeader.frame.size.width - 10;
frame.size.height -= 10;
UILabel *headerLabel = [[UILabel alloc] initWithFrame:frame];
headerLabel.textColor = ThemeService.shared.theme.textPrimaryColor;
headerLabel.font = [UIFont boldSystemFontOfSize:15.0];
headerLabel.backgroundColor = [UIColor clearColor];;
if (section == invitedSection)
{
sectionHeader = [[UIView alloc] initWithFrame:CGRectMake(0, 0, tableView.frame.size.width, 30)];
sectionHeader.backgroundColor = ThemeService.shared.theme.headerBackgroundColor;
CGRect frame = sectionHeader.frame;
frame.origin.x = 20;
frame.origin.y = 5;
frame.size.width = sectionHeader.frame.size.width - 10;
frame.size.height -= 10;
UILabel *headerLabel = [[UILabel alloc] initWithFrame:frame];
headerLabel.textColor = ThemeService.shared.theme.textPrimaryColor;
headerLabel.font = [UIFont boldSystemFontOfSize:15.0];
headerLabel.backgroundColor = [UIColor clearColor];
headerLabel.text = [VectorL10n roomParticipantsInvitedSection];
[sectionHeader addSubview:headerLabel];
} else if (section == adminSection)
{
headerLabel.text = @"Admin";
} else if (section == modSection)
{
headerLabel.text = @"Moderator";
} else if (section == participantsSection)
{
headerLabel.text = @"Nutzer";
}
[sectionHeader addSubview:headerLabel];
return sectionHeader;
}
@@ -1186,51 +1217,7 @@
return;
}
Contact *contact;
// oneself dedicated cell
if ((indexPath.section == participantsSection && userParticipant && indexPath.row == 0) && !currentSearchText.length)
{
contact = userParticipant;
}
else
{
NSInteger index = indexPath.row;
NSArray *participants;
if (indexPath.section == participantsSection)
{
if (currentSearchText.length)
{
participants = filteredActualParticipants;
}
else
{
participants = actualParticipants;
if (userParticipant)
{
index --;
}
}
}
else
{
if (currentSearchText.length)
{
participants = filteredInvitedParticipants;
}
else
{
participants = invitedParticipants;
}
}
if (index < participants.count)
{
contact = participants[index];
}
}
Contact *contact = [self contactAtIndexPath:indexPath];
if (contact.mxMember)
{
@@ -1552,6 +1539,8 @@
// Copy participants and invited participants
filteredActualParticipants = [NSMutableArray arrayWithArray:actualParticipants];
filteredInvitedParticipants = [NSMutableArray arrayWithArray:invitedParticipants];
filteredModParticipants = [NSMutableArray arrayWithArray:modParticipants];
filteredAdminParticipants = [NSMutableArray arrayWithArray:adminParticipants];
// Add the current user if he belongs to the room members.
if (userParticipant)
@@ -1565,6 +1554,31 @@
// Filter room participants
if (currentSearchText.length)
{
for (index = 0; index < filteredModParticipants.count;)
{
contact = filteredModParticipants[index];
if (![contact matchedWithPatterns:@[currentSearchText]])
{
[filteredModParticipants removeObjectAtIndex:index];
}
else
{
index++;
}
}
for (index = 0; index < filteredAdminParticipants.count;)
{
contact = filteredAdminParticipants[index];
if (![contact matchedWithPatterns:@[currentSearchText]])
{
[filteredAdminParticipants removeObjectAtIndex:index];
}
else
{
index++;
}
}
for (index = 0; index < filteredActualParticipants.count;)
{
contact = filteredActualParticipants[index];
@@ -1595,6 +1609,8 @@
{
filteredActualParticipants = nil;
filteredInvitedParticipants = nil;
filteredModParticipants = nil;
filteredAdminParticipants = nil;
}
// Refresh display
@@ -1656,4 +1672,102 @@
[self removePendingActionMask];
}
#pragma mark - bwi helper for admin and mod sections
- (Contact*)contactAtIndexPath:(NSIndexPath*)indexPath {
Contact* contact;
if (indexPath.section == adminSection) {
if (currentSearchText.length && indexPath.row < filteredAdminParticipants.count)
{
contact = filteredAdminParticipants[indexPath.row];
} else if (indexPath.row < adminParticipants.count) {
contact = adminParticipants[indexPath.row];
}
}
if (indexPath.section == modSection) {
if (currentSearchText.length && indexPath.row < filteredModParticipants.count)
{
contact = filteredModParticipants[indexPath.row];
} else if (indexPath.row < modParticipants.count) {
contact = modParticipants[indexPath.row];
}
}
if (indexPath.section == participantsSection || indexPath.section == invitedSection)
{
if ((indexPath.section == participantsSection && userParticipant && indexPath.row == 0) && !currentSearchText.length)
{
// oneself dedicated cell
contact = userParticipant;
}
else
{
NSInteger index = indexPath.row;
NSArray *participants;
if (indexPath.section == participantsSection)
{
if (currentSearchText.length)
{
participants = filteredActualParticipants;
}
else
{
participants = actualParticipants;
if (userParticipant)
{
index --;
}
}
}
else
{
if (currentSearchText.length)
{
participants = filteredInvitedParticipants;
}
else
{
participants = invitedParticipants;
}
}
if (index < participants.count)
{
contact = participants[index];
}
}
}
return contact;
}
- (NSComparisonResult)bwiParticipantsCompareLeft:(Contact*)contactA right:(Contact*)contactB {
MXUser *userA = [self.mxRoom.mxSession userWithUserId:contactA.mxMember.userId];
MXUser *userB = [self.mxRoom.mxSession userWithUserId:contactB.mxMember.userId];
if (!userA && !userB)
{
return [contactA.sortingDisplayName compare:contactB.sortingDisplayName options:NSCaseInsensitiveSearch];
} else if (userA && !userB)
{
return NSOrderedAscending;
} else if (!userA && userB)
{
return NSOrderedDescending;
} else {
NSString* userLabelA = [self.bwiUserLabelService getUserLabelWithUser:contactA.mxMember.userId];
NSString* userLabelB = [self.bwiUserLabelService getUserLabelWithUser:contactB.mxMember.userId];
if (userLabelA && !userLabelB) {
return NSOrderedAscending;
} else if (!userLabelA && userLabelB) {
return NSOrderedDescending;
} else {
return [contactA.sortingDisplayName compare:contactB.sortingDisplayName options:NSCaseInsensitiveSearch];
}
}
}
@end