element-ios/Riot/Modules/MatrixKit/Views/Contact/MXKContactTableCell.m

344 lines
9.9 KiB
Objective-C

/*
Copyright 2024 New Vector Ltd.
Copyright 2017 Vector Creations Ltd
Copyright 2015 OpenMarket Ltd
SPDX-License-Identifier: AGPL-3.0-only
Please see LICENSE in the repository root for full details.
*/
#import "MXKContactTableCell.h"
@import MatrixSDK.MXTools;
#import "MXKContactManager.h"
#import "MXKAppSettings.h"
#import "NSBundle+MatrixKit.h"
#pragma mark - Constant definitions
NSString *const kMXKContactCellTapOnThumbnailView = @"kMXKContactCellTapOnThumbnailView";
NSString *const kMXKContactCellContactIdKey = @"kMXKContactCellContactIdKey";
@interface MXKContactTableCell()
{
/**
The current displayed contact.
*/
MXKContact *contact;
/**
The observer of the presence for matrix user.
*/
id mxPresenceObserver;
}
@end
@implementation MXKContactTableCell
@synthesize delegate;
- (void)awakeFromNib
{
[super awakeFromNib];
self.thumbnailDisplayBoxType = MXKTableViewCellDisplayBoxTypeDefault;
// No accessory view by default
self.contactAccessoryViewType = MXKContactTableCellAccessoryCustom;
self.hideMatrixPresence = NO;
}
- (void)customizeTableViewCellRendering
{
[super customizeTableViewCellRendering];
self.thumbnailView.defaultBackgroundColor = [UIColor clearColor];
}
- (void)layoutSubviews
{
[super layoutSubviews];
if (self.thumbnailDisplayBoxType == MXKTableViewCellDisplayBoxTypeCircle)
{
// Round image view for thumbnail
self.thumbnailView.layer.cornerRadius = self.thumbnailView.frame.size.width / 2;
self.thumbnailView.clipsToBounds = YES;
}
else if (self.thumbnailDisplayBoxType == MXKTableViewCellDisplayBoxTypeRoundedCorner)
{
self.thumbnailView.layer.cornerRadius = 5;
self.thumbnailView.clipsToBounds = YES;
}
else
{
self.thumbnailView.layer.cornerRadius = 0;
self.thumbnailView.clipsToBounds = NO;
}
}
- (UIImage*)picturePlaceholder
{
return [NSBundle mxk_imageFromMXKAssetsBundleWithName:@"default-profile"];
}
- (void)setContactAccessoryViewType:(MXKContactTableCellAccessoryType)contactAccessoryViewType
{
_contactAccessoryViewType = contactAccessoryViewType;
if (contactAccessoryViewType == MXKContactTableCellAccessoryMatrixIcon)
{
// Load default matrix icon
self.contactAccessoryImageView.image = [NSBundle mxk_imageFromMXKAssetsBundleWithName:@"matrixUser"];
self.contactAccessoryImageView.hidden = NO;
self.contactAccessoryButton.hidden = YES;
// Update accessory view visibility
[self refreshMatrixIdentifiers];
}
else
{
// Hide accessory view by default
self.contactAccessoryView.hidden = YES;
self.contactAccessoryImageView.hidden = YES;
self.contactAccessoryButton.hidden = YES;
}
}
#pragma mark - MXKCellRendering
- (void)render:(MXKCellData *)cellData
{
// Sanity check: accept only object of MXKContact classes or sub-classes
NSParameterAssert([cellData isKindOfClass:[MXKContact class]]);
contact = (MXKContact*)cellData;
// remove any pending observers
[[NSNotificationCenter defaultCenter] removeObserver:self];
if (mxPresenceObserver)
{
[[NSNotificationCenter defaultCenter] removeObserver:mxPresenceObserver];
mxPresenceObserver = nil;
}
self.thumbnailView.layer.borderWidth = 0;
if (contact)
{
// Be warned when the thumbnail is updated
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(onThumbnailUpdate:) name:kMXKContactThumbnailUpdateNotification object:nil];
if (! self.hideMatrixPresence)
{
// Observe contact presence change
MXWeakify(self);
mxPresenceObserver = [[NSNotificationCenter defaultCenter] addObserverForName:kMXKContactManagerMatrixUserPresenceChangeNotification object:nil queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification *notif) {
MXStrongifyAndReturnIfNil(self);
// get the matrix identifiers
NSArray* matrixIdentifiers = self->contact.matrixIdentifiers;
if (matrixIdentifiers.count > 0)
{
// Consider only the first id
NSString *matrixUserID = matrixIdentifiers.firstObject;
if ([matrixUserID isEqualToString:notif.object])
{
[self refreshPresenceUserRing:[MXTools presence:[notif.userInfo objectForKey:kMXKContactManagerMatrixPresenceKey]]];
}
}
}];
}
if (!contact.isMatrixContact)
{
// Be warned when the linked matrix IDs are updated
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(onMatrixIdUpdate:) name:kMXKContactManagerDidUpdateLocalContactMatrixIDsNotification object:nil];
}
NSArray* matrixIDs = contact.matrixIdentifiers;
if (matrixIDs.count)
{
self.contactDisplayNameLabel.hidden = YES;
self.matrixDisplayNameLabel.hidden = NO;
self.matrixDisplayNameLabel.text = contact.displayName;
self.matrixIDLabel.hidden = NO;
self.matrixIDLabel.text = [matrixIDs firstObject];
}
else
{
self.contactDisplayNameLabel.hidden = NO;
self.contactDisplayNameLabel.text = contact.displayName;
self.matrixDisplayNameLabel.hidden = YES;
self.matrixIDLabel.hidden = YES;
}
UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(onContactThumbnailTap:)];
[tap setNumberOfTouchesRequired:1];
[tap setNumberOfTapsRequired:1];
[tap setDelegate:self];
[self.thumbnailView addGestureRecognizer:tap];
}
[self refreshContactThumbnail];
[self manageMatrixIcon];
}
+ (CGFloat)heightForCellData:(MXKCellData*)cellData withMaximumWidth:(CGFloat)maxWidth
{
// The height is fixed
return 50;
}
- (void)didEndDisplay
{
// remove any pending observers
[[NSNotificationCenter defaultCenter] removeObserver:self];
if (mxPresenceObserver) {
[[NSNotificationCenter defaultCenter] removeObserver:mxPresenceObserver];
mxPresenceObserver = nil;
}
// Remove all gesture recognizer
while (self.thumbnailView.gestureRecognizers.count)
{
[self.thumbnailView removeGestureRecognizer:self.thumbnailView.gestureRecognizers[0]];
}
self.delegate = nil;
contact = nil;
}
#pragma mark -
- (void)refreshMatrixIdentifiers
{
// Look for a potential matrix user linked with this contact
NSArray* matrixIdentifiers = contact.matrixIdentifiers;
if ((matrixIdentifiers.count > 0) && (! self.hideMatrixPresence))
{
// Consider only the first matrix identifier
NSString* matrixUserID = matrixIdentifiers.firstObject;
// Consider here all sessions reported into contact manager
NSArray* mxSessions = [MXKContactManager sharedManager].mxSessions;
for (MXSession *mxSession in mxSessions)
{
MXUser *mxUser = [mxSession userWithUserId:matrixUserID];
if (mxUser)
{
[self refreshPresenceUserRing:mxUser.presence];
break;
}
}
}
// Update accessory view visibility
if (self.contactAccessoryViewType == MXKContactTableCellAccessoryMatrixIcon)
{
self.contactAccessoryView.hidden = (!matrixIdentifiers.count);
}
}
- (void)refreshContactThumbnail
{
self.thumbnailView.image = [contact thumbnailWithPreferedSize:self.thumbnailView.frame.size];
if (!self.thumbnailView.image)
{
self.thumbnailView.image = self.picturePlaceholder;
}
}
- (void)refreshPresenceUserRing:(MXPresence)presenceStatus
{
UIColor* ringColor;
switch (presenceStatus)
{
case MXPresenceOnline:
ringColor = [[MXKAppSettings standardAppSettings] presenceColorForOnlineUser];
break;
case MXPresenceUnavailable:
ringColor = [[MXKAppSettings standardAppSettings] presenceColorForUnavailableUser];
break;
case MXPresenceOffline:
ringColor = [[MXKAppSettings standardAppSettings] presenceColorForOfflineUser];
break;
default:
ringColor = nil;
}
// if the thumbnail is defined
if (ringColor && (! self.hideMatrixPresence))
{
self.thumbnailView.layer.borderWidth = 2;
self.thumbnailView.layer.borderColor = ringColor.CGColor;
}
else
{
// remove the border
// else it draws black border
self.thumbnailView.layer.borderWidth = 0;
}
}
- (void)manageMatrixIcon
{
// try to update the thumbnail with the matrix thumbnail
if (contact.matrixIdentifiers)
{
[self refreshContactThumbnail];
}
[self refreshMatrixIdentifiers];
}
- (void)onMatrixIdUpdate:(NSNotification *)notif
{
// sanity check
if ([notif.object isKindOfClass:[NSString class]])
{
NSString* contactID = notif.object;
if ([contactID isEqualToString:contact.contactID])
{
[self manageMatrixIcon];
}
}
}
- (void)onThumbnailUpdate:(NSNotification *)notif
{
// sanity check
if ([notif.object isKindOfClass:[NSString class]])
{
NSString* contactID = notif.object;
if ([contactID isEqualToString:contact.contactID])
{
[self refreshContactThumbnail];
[self refreshMatrixIdentifiers];
}
}
}
#pragma mark - Action
- (IBAction)onContactThumbnailTap:(id)sender
{
if (self.delegate)
{
[self.delegate cell:self didRecognizeAction:kMXKContactCellTapOnThumbnailView userInfo:@{kMXKContactCellContactIdKey: contact.contactID}];
}
}
@end