element-ios/Riot/Modules/MatrixKit/Models/Contact/MXKContactField.m

227 lines
7.9 KiB
Objective-C

/*
Copyright 2018-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 "MXKContactField.h"
@import MatrixSDK.MXMediaManager;
#import "MXKContactManager.h"
@interface MXKContactField()
{
// Tell whether we already check the contact avatar definition.
BOOL shouldCheckAvatarURL;
// The media manager of the session used to retrieve the contect avatar url
// This manager is used to download this avatar if need
MXMediaManager *mediaManager;
// The current download id
NSString *downloadId;
}
@end
@implementation MXKContactField
- (void)initFields
{
// init members
_contactID = nil;
_matrixID = nil;
[self resetMatrixAvatar];
}
- (id)initWithContactID:(NSString*)contactID matrixID:(NSString*)matrixID
{
self = [super init];
if (self)
{
[self initFields];
_contactID = contactID;
_matrixID = matrixID;
}
return self;
}
- (void)resetMatrixAvatar
{
_avatarImage = nil;
_matrixAvatarURL = nil;
shouldCheckAvatarURL = YES;
mediaManager = nil;
downloadId = nil;
}
- (void)loadAvatarWithSize:(CGSize)avatarSize
{
// Check whether the avatar image is already set
if (_avatarImage)
{
return;
}
// Sanity check
if (_matrixID)
{
if (shouldCheckAvatarURL)
{
// Consider here all sessions reported into contact manager
NSArray* mxSessions = [MXKContactManager sharedManager].mxSessions;
if (mxSessions.count)
{
// Check whether a matrix user is already known
MXUser* user;
MXSession *mxSession;
for (mxSession in mxSessions)
{
user = [mxSession userWithUserId:_matrixID];
if (user)
{
_matrixAvatarURL = user.avatarUrl;
if (_matrixAvatarURL)
{
shouldCheckAvatarURL = NO;
mediaManager = mxSession.mediaManager;
[self downloadAvatarImage:avatarSize];
}
break;
}
}
// Trigger a server request if this url has not been found.
if (shouldCheckAvatarURL)
{
MXWeakify(self);
[mxSession.matrixRestClient avatarUrlForUser:_matrixID
success:^(NSString *mxAvatarUrl) {
MXStrongifyAndReturnIfNil(self);
self.matrixAvatarURL = mxAvatarUrl;
self->shouldCheckAvatarURL = NO;
self->mediaManager = mxSession.mediaManager;
[self downloadAvatarImage:avatarSize];
} failure:nil];
}
}
}
else if (_matrixAvatarURL)
{
[self downloadAvatarImage:avatarSize];
}
// Do nothing if the avatar url has been checked, and it is null.
}
}
- (void)downloadAvatarImage:(CGSize)avatarSize
{
// the avatar image is already done
if (_avatarImage)
{
return;
}
if (_matrixAvatarURL)
{
NSString *cacheFilePath = [MXMediaManager thumbnailCachePathForMatrixContentURI:_matrixAvatarURL
andType:nil
inFolder:kMXMediaManagerAvatarThumbnailFolder
toFitViewSize:avatarSize
withMethod:MXThumbnailingMethodCrop];
_avatarImage = [MXMediaManager loadPictureFromFilePath:cacheFilePath];
// the image is already in the cache
if (_avatarImage)
{
MXWeakify(self);
dispatch_async(dispatch_get_main_queue(), ^{
MXStrongifyAndReturnIfNil(self);
[[NSNotificationCenter defaultCenter] postNotificationName:kMXKContactThumbnailUpdateNotification object:self.contactID userInfo:nil];
});
}
else
{
NSString *downloadId = [MXMediaManager thumbnailDownloadIdForMatrixContentURI:_matrixAvatarURL inFolder:kMXMediaManagerAvatarThumbnailFolder toFitViewSize:avatarSize withMethod:MXThumbnailingMethodCrop];
MXMediaLoader* loader = [MXMediaManager existingDownloaderWithIdentifier:downloadId];
[[NSNotificationCenter defaultCenter] removeObserver:self name:kMXMediaLoaderStateDidChangeNotification object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(onMediaDownloadEnd:) name:kMXMediaLoaderStateDidChangeNotification object:loader];
if (!loader && mediaManager)
{
[mediaManager downloadThumbnailFromMatrixContentURI:_matrixAvatarURL
withType:nil
inFolder:kMXMediaManagerAvatarThumbnailFolder
toFitViewSize:avatarSize
withMethod:MXThumbnailingMethodCrop
success:nil
failure:nil];
}
}
}
}
- (void)onMediaDownloadEnd:(NSNotification *)notif
{
MXMediaLoader *loader = (MXMediaLoader*)notif.object;
if ([loader.downloadId isEqualToString:downloadId])
{
// update the image
switch (loader.state) {
case MXMediaLoaderStateDownloadCompleted:
{
UIImage *image = [MXMediaManager loadPictureFromFilePath:loader.downloadOutputFilePath];
if (image)
{
_avatarImage = image;
MXWeakify(self);
dispatch_async(dispatch_get_main_queue(), ^{
MXStrongifyAndReturnIfNil(self);
[[NSNotificationCenter defaultCenter] postNotificationName:kMXKContactThumbnailUpdateNotification object:self.contactID userInfo:nil];
});
}
[[NSNotificationCenter defaultCenter] removeObserver:self name:kMXMediaLoaderStateDidChangeNotification object:nil];
downloadId = nil;
break;
}
case MXMediaLoaderStateDownloadFailed:
case MXMediaLoaderStateCancelled:
[[NSNotificationCenter defaultCenter] removeObserver:self name:kMXMediaLoaderStateDidChangeNotification object:nil];
downloadId = nil;
break;
default:
break;
}
}
}
#pragma mark NSCoding
- (id)initWithCoder:(NSCoder *)coder
{
if (self)
{
[self initFields];
_contactID = [coder decodeObjectForKey:@"contactID"];
_matrixID = [coder decodeObjectForKey:@"matrixID"];
}
return self;
}
- (void)encodeWithCoder:(NSCoder *)coder
{
[coder encodeObject:_contactID forKey:@"contactID"];
[coder encodeObject:_matrixID forKey:@"matrixID"];
}
@end