344 lines
9.9 KiB
Objective-C
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
|