diff --git a/NextcloudTalk/ChatMessageTableViewCell.h b/NextcloudTalk/ChatMessageTableViewCell.h index d97736df..a4da66a8 100644 --- a/NextcloudTalk/ChatMessageTableViewCell.h +++ b/NextcloudTalk/ChatMessageTableViewCell.h @@ -49,7 +49,7 @@ static NSString *AutoCompletionCellIdentifier = @"AutoCompletionCellIdentifier @property (nonatomic, strong) UILabel *dateLabel; @property (nonatomic, strong) QuotedMessageView *quotedMessageView; @property (nonatomic, strong) MessageBodyTextView *bodyTextView; -@property (nonatomic, strong) UIImageView *avatarView; +@property (nonatomic, strong) UIButton *avatarButton; @property (nonatomic, strong) UIView *statusView; @property (nonatomic, strong) UIImageView *userStatusImageView; diff --git a/NextcloudTalk/ChatMessageTableViewCell.m b/NextcloudTalk/ChatMessageTableViewCell.m index aebe6be2..67f24878 100644 --- a/NextcloudTalk/ChatMessageTableViewCell.m +++ b/NextcloudTalk/ChatMessageTableViewCell.m @@ -24,8 +24,7 @@ #import "MaterialActivityIndicator.h" #import "SLKUIConstants.h" -#import "UIImageView+AFNetworking.h" -#import "UIImageView+Letters.h" +#import "UIButton+AFNetworking.h" #import "NextcloudTalk-Swift.h" @@ -58,16 +57,15 @@ - (void)configureSubviews { - _avatarView = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, kChatCellAvatarHeight, kChatCellAvatarHeight)]; - _avatarView.translatesAutoresizingMaskIntoConstraints = NO; - _avatarView.userInteractionEnabled = YES; - _avatarView.backgroundColor = [NCAppBranding placeholderColor]; - _avatarView.layer.cornerRadius = kChatCellAvatarHeight/2.0; - _avatarView.layer.masksToBounds = YES; - _avatarView.contentMode = UIViewContentModeScaleToFill; - UITapGestureRecognizer *avatarTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(avatarTapped:)]; - [_avatarView addGestureRecognizer:avatarTap]; - [self.contentView addSubview:_avatarView]; + _avatarButton = [[UIButton alloc] initWithFrame:CGRectMake(0, 0, kChatCellAvatarHeight, kChatCellAvatarHeight)]; + _avatarButton.translatesAutoresizingMaskIntoConstraints = NO; + _avatarButton.backgroundColor = [NCAppBranding placeholderColor]; + _avatarButton.layer.cornerRadius = kChatCellAvatarHeight/2.0; + _avatarButton.layer.masksToBounds = YES; + _avatarButton.showsMenuAsPrimaryAction = YES; + _avatarButton.imageView.contentMode = UIViewContentModeScaleToFill; + + [self.contentView addSubview:_avatarButton]; _statusView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, kChatCellStatusViewHeight, kChatCellStatusViewHeight)]; _statusView.translatesAutoresizingMaskIntoConstraints = NO; @@ -95,7 +93,7 @@ [self.contentView addSubview:self.referenceView]; } - NSDictionary *views = @{@"avatarView": self.avatarView, + NSDictionary *views = @{@"avatarButton": self.avatarButton, @"userStatusImageView": self.userStatusImageView, @"statusView": self.statusView, @"titleLabel": self.titleLabel, @@ -116,22 +114,22 @@ }; if ([self.reuseIdentifier isEqualToString:ChatMessageCellIdentifier]) { - [self.contentView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-right-[avatarView(avatarSize)]-right-[titleLabel]-[dateLabel(>=dateLabelWidth)]-right-|" options:0 metrics:metrics views:views]]; - [self.contentView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-right-[avatarView(avatarSize)]-right-[bodyTextView(>=0)]-right-|" options:0 metrics:metrics views:views]]; - [self.contentView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-right-[avatarView(avatarSize)]-right-[reactionsView(>=0)]-right-|" options:0 metrics:metrics views:views]]; - [self.contentView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-right-[avatarView(avatarSize)]-right-[referenceView(>=0)]-right-|" options:0 metrics:metrics views:views]]; + [self.contentView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-right-[avatarButton(avatarSize)]-right-[titleLabel]-[dateLabel(>=dateLabelWidth)]-right-|" options:0 metrics:metrics views:views]]; + [self.contentView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-right-[avatarButton(avatarSize)]-right-[bodyTextView(>=0)]-right-|" options:0 metrics:metrics views:views]]; + [self.contentView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-right-[avatarButton(avatarSize)]-right-[reactionsView(>=0)]-right-|" options:0 metrics:metrics views:views]]; + [self.contentView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-right-[avatarButton(avatarSize)]-right-[referenceView(>=0)]-right-|" options:0 metrics:metrics views:views]]; [self.contentView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-padding-[statusView(statusSize)]-padding-[bodyTextView(>=0)]-right-|" options:0 metrics:metrics views:views]]; _vConstraintNormal = [NSLayoutConstraint constraintsWithVisualFormat:@"V:|-right-[titleLabel(avatarSize)]-left-[bodyTextView(>=0@999)]-0-[referenceView(0)]-0-[reactionsView(0)]-(>=left)-|" options:0 metrics:metrics views:views]; [self.contentView addConstraints:_vConstraintNormal]; [self.contentView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-right-[dateLabel(avatarSize)]-(>=0)-|" options:0 metrics:metrics views:views]]; [self.contentView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-right-[titleLabel(avatarSize)]-left-[statusView(statusSize)]-(>=0)-|" options:0 metrics:metrics views:views]]; } else if ([self.reuseIdentifier isEqualToString:ReplyMessageCellIdentifier]) { - [self.contentView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-right-[avatarView(avatarSize)]-right-[titleLabel]-[dateLabel(>=dateLabelWidth)]-right-|" options:0 metrics:metrics views:views]]; - [self.contentView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-right-[avatarView(avatarSize)]-right-[bodyTextView(>=0)]-right-|" options:0 metrics:metrics views:views]]; - [self.contentView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-right-[avatarView(avatarSize)]-right-[reactionsView(>=0)]-right-|" options:0 metrics:metrics views:views]]; - [self.contentView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-right-[avatarView(avatarSize)]-right-[referenceView(>=0)]-right-|" options:0 metrics:metrics views:views]]; + [self.contentView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-right-[avatarButton(avatarSize)]-right-[titleLabel]-[dateLabel(>=dateLabelWidth)]-right-|" options:0 metrics:metrics views:views]]; + [self.contentView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-right-[avatarButton(avatarSize)]-right-[bodyTextView(>=0)]-right-|" options:0 metrics:metrics views:views]]; + [self.contentView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-right-[avatarButton(avatarSize)]-right-[reactionsView(>=0)]-right-|" options:0 metrics:metrics views:views]]; + [self.contentView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-right-[avatarButton(avatarSize)]-right-[referenceView(>=0)]-right-|" options:0 metrics:metrics views:views]]; [self.contentView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-padding-[statusView(statusSize)]-padding-[bodyTextView(>=0)]-right-|" options:0 metrics:metrics views:views]]; - [self.contentView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-right-[avatarView(avatarSize)]-right-[quoteContainerView(bodyTextView)]-right-|" options:0 metrics:metrics views:views]]; + [self.contentView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-right-[avatarButton(avatarSize)]-right-[quoteContainerView(bodyTextView)]-right-|" options:0 metrics:metrics views:views]]; [self.contentView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|[quotedMessageView(quoteContainerView)]|" options:0 metrics:nil views:views]]; _vConstraintReply = [NSLayoutConstraint constraintsWithVisualFormat:@"V:|-right-[titleLabel(avatarSize)]-left-[quoteContainerView]-left-[bodyTextView(>=0@999)]-0-[referenceView(0)]-0-[reactionsView(0)]-(>=left)-|" options:0 metrics:metrics views:views]; [self.contentView addConstraints:_vConstraintReply]; @@ -139,7 +137,7 @@ [self.contentView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|[quotedMessageView(quoteContainerView)]|" options:0 metrics:nil views:views]]; [self.contentView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-right-[titleLabel(avatarSize)]-left-[quoteContainerView]-left-[statusView(statusSize)]-(>=0)-|" options:0 metrics:metrics views:views]]; } else if ([self.reuseIdentifier isEqualToString:AutoCompletionCellIdentifier]) { - [self.contentView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-right-[avatarView(avatarSize)]-right-[titleLabel]-right-|" options:0 metrics:metrics views:views]]; + [self.contentView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-right-[avatarButton(avatarSize)]-right-[titleLabel]-right-|" options:0 metrics:metrics views:views]]; [self.contentView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|[titleLabel]|" options:0 metrics:metrics views:views]]; [self.contentView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-32-[userStatusImageView(12)]-(>=0)-|" options:0 metrics:metrics views:views]]; [self.contentView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-32-[userStatusImageView(12)]-(>=0)-|" options:0 metrics:metrics views:views]]; @@ -147,7 +145,7 @@ self.titleLabel.textColor = [UIColor labelColor]; } - [self.contentView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-right-[avatarView(avatarSize)]-(>=0)-|" options:0 metrics:metrics views:views]]; + [self.contentView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-right-[avatarButton(avatarSize)]-(>=0)-|" options:0 metrics:metrics views:views]]; } - (void)prepareForReuse @@ -181,10 +179,10 @@ } [_referenceView prepareForReuse]; - - [self.avatarView cancelImageDownloadTask]; - self.avatarView.image = nil; - self.avatarView.contentMode = UIViewContentModeScaleToFill; + + [self.avatarButton cancelImageDownloadTaskForState:UIControlStateNormal]; + [self.avatarButton setImage:nil forState:UIControlStateNormal]; + self.avatarButton.imageView.contentMode = UIViewContentModeScaleToFill; self.userStatusImageView.image = nil; self.userStatusImageView.backgroundColor = [UIColor clearColor]; @@ -197,13 +195,6 @@ #pragma mark - Gesture recognizers -- (void)avatarTapped:(UIGestureRecognizer *)gestureRecognizer -{ - if (self.delegate && self.message) { - [self.delegate cellWantsToDisplayOptionsForMessageActor:self.message]; - } -} - - (void)quoteTapped:(UIGestureRecognizer *)gestureRecognizer { if (self.delegate && self.message && self.message.parent) { @@ -321,13 +312,17 @@ [self setBotAvatar]; } } else { - [self.avatarView - setImageWithURLRequest:[[NCAPIController sharedInstance] - createAvatarRequestForUser:message.actorId - withStyle:self.traitCollection.userInterfaceStyle - andSize:96 - usingAccount:activeAccount] - placeholderImage:nil success:nil failure:nil]; + [self.avatarButton setImageForState:UIControlStateNormal + withURLRequest:[[NCAPIController sharedInstance] + createAvatarRequestForUser:message.actorId + withStyle:self.traitCollection.userInterfaceStyle + andSize:96 + usingAccount:activeAccount] + placeholderImage:nil + success:nil + failure:nil]; + + _avatarButton.menu = [super getDeferredUserMenuForMessage:message]; } // This check is just a workaround to fix the issue with the deleted parents returned by the API. @@ -399,18 +394,21 @@ { UIColor *guestAvatarColor = [NCAppBranding placeholderColor]; NSString *name = ([displayName isEqualToString:@""]) ? @"?" : displayName; - [_avatarView setImageWithString:name color:guestAvatarColor circular:true]; + + UIImage *image = [NCUtils getImageWithString:name withBackgroundColor:guestAvatarColor withBounds:_avatarButton.bounds isCircular:YES]; + [_avatarButton setImage:image forState:UIControlStateNormal]; } - (void)setBotAvatar { UIColor *guestAvatarColor = [UIColor colorWithRed:0.21 green:0.21 blue:0.21 alpha:1.0]; /*#363636*/ - [_avatarView setImageWithString:@">" color:guestAvatarColor circular:true]; + UIImage *image = [NCUtils getImageWithString:@">" withBackgroundColor:guestAvatarColor withBounds:_avatarButton.bounds isCircular:YES]; + [_avatarButton setImage:image forState:UIControlStateNormal]; } - (void)setChangelogAvatar { - [_avatarView setImage:[UIImage imageNamed:@"changelog"]]; + [_avatarButton setImage:[UIImage imageNamed:@"changelog"] forState:UIControlStateNormal]; } - (void)setDeliveryState:(ChatMessageDeliveryState)state diff --git a/NextcloudTalk/ChatTableViewCell.h b/NextcloudTalk/ChatTableViewCell.h index 1bd1fd26..3b90c123 100644 --- a/NextcloudTalk/ChatTableViewCell.h +++ b/NextcloudTalk/ChatTableViewCell.h @@ -40,7 +40,6 @@ typedef enum ChatMessageDeliveryState { @protocol ChatTableViewCellDelegate -- (void)cellWantsToDisplayOptionsForMessageActor:(NCChatMessage *)message; - (void)cellDidSelectedReaction:(NCChatReaction *)reaction forMessage:(NCChatMessage *)message; @end @@ -50,4 +49,6 @@ typedef enum ChatMessageDeliveryState { @property (nonatomic, assign) NSInteger messageId; @property (nonatomic, strong) NCChatMessage *message; +- (UIMenu *)getDeferredUserMenuForMessage:(NCChatMessage *)message; + @end diff --git a/NextcloudTalk/ChatTableViewCell.m b/NextcloudTalk/ChatTableViewCell.m index 951dbd76..82a9fb81 100644 --- a/NextcloudTalk/ChatTableViewCell.m +++ b/NextcloudTalk/ChatTableViewCell.m @@ -22,6 +22,8 @@ #import "ChatTableViewCell.h" +typedef void (^GetMenuUserActionsForMessageCompletionBlock)(NSArray *menuItems); + @interface ChatTableViewCell () @end @@ -43,4 +45,107 @@ self.message = nil; } +- (UIMenu *)getDeferredUserMenuForMessage:(NCChatMessage *)message +{ + TalkAccount *activeAccount = [[NCDatabaseManager sharedInstance] activeAccount]; + if (![message.actorType isEqualToString:@"users"] || [message.actorId isEqualToString:activeAccount.userId]) { + return nil; + } + + UIDeferredMenuElement *deferredMenuElement; + + if (@available(iOS 15.0, *)) { + // When iOS 15 is available, we can use an uncached provider so local time is not cached for example + deferredMenuElement = [UIDeferredMenuElement elementWithUncachedProvider:^(void (^ _Nonnull completion)(NSArray * _Nonnull)) { + [self getMenuUserActionsForMessage:message withCompletionBlock:^(NSArray *menuItems) { + completion(menuItems); + }]; + }]; + } else { + deferredMenuElement = [UIDeferredMenuElement elementWithProvider:^(void (^ _Nonnull completion)(NSArray * _Nonnull)) { + [self getMenuUserActionsForMessage:message withCompletionBlock:^(NSArray *menuItems) { + completion(menuItems); + }]; + }]; + } + + return [UIMenu menuWithTitle:message.actorDisplayName children:@[deferredMenuElement]]; +} + +- (void)getMenuUserActionsForMessage:(NCChatMessage *)message withCompletionBlock:(GetMenuUserActionsForMessageCompletionBlock)block +{ + TalkAccount *activeAccount = [[NCDatabaseManager sharedInstance] activeAccount]; + [[NCAPIController sharedInstance] getUserActionsForUser:message.actorId usingAccount:activeAccount withCompletionBlock:^(NSDictionary *userActions, NSError *error) { + if (error) { + if (block) { + UIAction *errorAction = [UIAction actionWithTitle:NSLocalizedString(@"No actions available", nil) image:nil identifier:nil handler:^(UIAction *action) {}]; + errorAction.attributes = UIMenuElementAttributesDisabled; + block(@[errorAction]); + } + + return; + } + + NSArray *actions = [userActions objectForKey:@"actions"]; + if (![actions isKindOfClass:[NSArray class]]) { + if (block) { + UIAction *errorAction = [UIAction actionWithTitle:NSLocalizedString(@"No actions available", nil) image:nil identifier:nil handler:^(UIAction *action) {}]; + errorAction.attributes = UIMenuElementAttributesDisabled; + block(@[errorAction]); + } + + return; + } + + NSMutableArray *items = [[NSMutableArray alloc] init]; + + for (NSDictionary *action in actions) { + NSString *appId = [action objectForKey:@"appId"]; + NSString *title = [action objectForKey:@"title"]; + NSString *link = [action objectForKey:@"hyperlink"]; + + // Talk to user action + if ([appId isEqualToString:@"spreed"]) { + UIAction *talkAction = [UIAction actionWithTitle:title + image:[[UIImage imageNamed:@"navigationLogo"] imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate] + identifier:nil + handler:^(UIAction *action) { + NSMutableDictionary *userInfo = [[NSMutableDictionary alloc] init]; + NSString *userId = [userActions objectForKey:@"userId"]; + [userInfo setObject:userId forKey:@"actorId"]; + [[NSNotificationCenter defaultCenter] postNotificationName:NCChatViewControllerTalkToUserNotification + object:self + userInfo:userInfo]; + }]; + + [items addObject:talkAction]; + continue; + } + + // Other user actions + UIAction *otherAction = [UIAction actionWithTitle:title + image:nil + identifier:nil + handler:^(UIAction *action) { + NSURL *actionURL = [NSURL URLWithString:[link stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLQueryAllowedCharacterSet]]]; + [[UIApplication sharedApplication] openURL:actionURL options:@{} completionHandler:nil]; + }]; + + if ([appId isEqualToString:@"profile"]) { + [otherAction setImage:[[UIImage imageNamed:@"user-profile"] imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate]]; + } else if ([appId isEqualToString:@"email"]) { + [otherAction setImage:[[UIImage imageNamed:@"mail"] imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate]]; + } else if ([appId isEqualToString:@"timezone"]) { + [otherAction setImage:[UIImage systemImageNamed:@"clock"]]; + } + + [items addObject:otherAction]; + } + + if (block) { + block(items); + } + }]; +} + @end diff --git a/NextcloudTalk/FileMessageTableViewCell.h b/NextcloudTalk/FileMessageTableViewCell.h index 7b7b8def..d04a5e1f 100644 --- a/NextcloudTalk/FileMessageTableViewCell.h +++ b/NextcloudTalk/FileMessageTableViewCell.h @@ -58,7 +58,7 @@ static NSString *GroupedFileMessageCellIdentifier = @"GroupedFileMessageCellId @property (nonatomic, strong) FilePreviewImageView *previewImageView; @property (nonatomic, strong) UIImageView *playIconImageView; @property (nonatomic, strong) MessageBodyTextView *bodyTextView; -@property (nonatomic, strong) UIImageView *avatarView; +@property (nonatomic, strong) UIButton *avatarButton; @property (nonatomic, strong) UIView *statusView; @property (nonatomic, strong) UIView *fileStatusView; @property (nonatomic, strong) UIStackView *statusStackView; @@ -71,7 +71,6 @@ static NSString *GroupedFileMessageCellIdentifier = @"GroupedFileMessageCellId @property (nonatomic, strong) NSArray *hGroupedPreviewSize; + (CGFloat)defaultFontSize; -- (void)setGuestAvatar:(NSString *)displayName; - (void)setupForMessage:(NCChatMessage *)message withLastCommonReadMessage:(NSInteger)lastCommonRead; @end diff --git a/NextcloudTalk/FileMessageTableViewCell.m b/NextcloudTalk/FileMessageTableViewCell.m index 1027ad80..2a963756 100644 --- a/NextcloudTalk/FileMessageTableViewCell.m +++ b/NextcloudTalk/FileMessageTableViewCell.m @@ -24,8 +24,7 @@ #import "MaterialActivityIndicator.h" #import "SLKUIConstants.h" -#import "UIImageView+AFNetworking.h" -#import "UIImageView+Letters.h" +#import "UIButton+AFNetworking.h" #import "NCAPIController.h" #import "NCAppBranding.h" @@ -59,15 +58,14 @@ - (void)configureSubviews { - _avatarView = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, kChatCellAvatarHeight, kChatCellAvatarHeight)]; - _avatarView.translatesAutoresizingMaskIntoConstraints = NO; - _avatarView.userInteractionEnabled = YES; - _avatarView.backgroundColor = [NCAppBranding placeholderColor]; - _avatarView.layer.cornerRadius = kChatCellAvatarHeight/2.0; - _avatarView.layer.masksToBounds = YES; - UITapGestureRecognizer *avatarTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(avatarTapped:)]; - [_avatarView addGestureRecognizer:avatarTap]; - + _avatarButton = [[UIButton alloc] initWithFrame:CGRectMake(0, 0, kChatCellAvatarHeight, kChatCellAvatarHeight)]; + _avatarButton.translatesAutoresizingMaskIntoConstraints = NO; + _avatarButton.backgroundColor = [NCAppBranding placeholderColor]; + _avatarButton.layer.cornerRadius = kChatCellAvatarHeight/2.0; + _avatarButton.layer.masksToBounds = YES; + _avatarButton.showsMenuAsPrimaryAction = YES; + _avatarButton.imageView.contentMode = UIViewContentModeScaleToFill; + _playIconImageView = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, kFileMessageCellVideoPlayIconSize, kFileMessageCellVideoPlayIconSize)]; _playIconImageView.hidden = YES; [_playIconImageView setTintColor:[UIColor colorWithWhite:1.0 alpha:0.8]]; @@ -87,7 +85,7 @@ _previewImageView.userInteractionEnabled = YES; if ([self.reuseIdentifier isEqualToString:FileMessageCellIdentifier]) { - [self.contentView addSubview:_avatarView]; + [self.contentView addSubview:self.avatarButton]; [self.contentView addSubview:self.titleLabel]; [self.contentView addSubview:self.dateLabel]; } @@ -113,7 +111,7 @@ _previewImageView.contentMode = UIViewContentModeScaleAspectFit; - NSDictionary *views = @{@"avatarView": self.avatarView, + NSDictionary *views = @{@"avatarButton": self.avatarButton, @"statusStackView": self.statusStackView, @"titleLabel": self.titleLabel, @"dateLabel": self.dateLabel, @@ -133,15 +131,15 @@ }; if ([self.reuseIdentifier isEqualToString:FileMessageCellIdentifier]) { - [self.contentView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-right-[avatarView(avatarSize)]-right-[titleLabel]-[dateLabel(>=dateLabelWidth)]-right-|" options:0 metrics:metrics views:views]]; - self.hPreviewSize = [NSLayoutConstraint constraintsWithVisualFormat:@"H:|-right-[avatarView(avatarSize)]-right-[previewImageView(previewSize)]-(>=0)-|" options:0 metrics:metrics views:views]; + [self.contentView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-right-[avatarButton(avatarSize)]-right-[titleLabel]-[dateLabel(>=dateLabelWidth)]-right-|" options:0 metrics:metrics views:views]]; + self.hPreviewSize = [NSLayoutConstraint constraintsWithVisualFormat:@"H:|-right-[avatarButton(avatarSize)]-right-[previewImageView(previewSize)]-(>=0)-|" options:0 metrics:metrics views:views]; [self.contentView addConstraints:self.hPreviewSize]; - [self.contentView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-right-[avatarView(avatarSize)]-right-[bodyTextView(>=0)]-right-|" options:0 metrics:metrics views:views]]; - [self.contentView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-right-[avatarView(avatarSize)]-right-[reactionsView(>=0)]-right-|" options:0 metrics:metrics views:views]]; + [self.contentView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-right-[avatarButton(avatarSize)]-right-[bodyTextView(>=0)]-right-|" options:0 metrics:metrics views:views]]; + [self.contentView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-right-[avatarButton(avatarSize)]-right-[reactionsView(>=0)]-right-|" options:0 metrics:metrics views:views]]; [self.contentView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-right-[dateLabel(avatarSize)]-(>=0)-|" options:0 metrics:metrics views:views]]; self.vPreviewSize = [NSLayoutConstraint constraintsWithVisualFormat:@"V:|-right-[titleLabel(avatarSize)]-left-[previewImageView(previewSize)]-right-[bodyTextView(>=0@999)]-0-[reactionsView(0)]-left-|" options:0 metrics:metrics views:views]; [self.contentView addConstraints:self.vPreviewSize]; - [self.contentView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-right-[avatarView(avatarSize)]-(>=0)-|" options:0 metrics:metrics views:views]]; + [self.contentView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-right-[avatarButton(avatarSize)]-(>=0)-|" options:0 metrics:metrics views:views]]; [self.contentView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-right-[titleLabel(avatarSize)]-left-[statusStackView(statusStackHeight)]-(>=0)-|" options:0 metrics:metrics views:views]]; } else if ([self.reuseIdentifier isEqualToString:GroupedFileMessageCellIdentifier]) { self.hGroupedPreviewSize = [NSLayoutConstraint constraintsWithVisualFormat:@"H:|-avatarGap-[previewImageView(previewSize)]-(>=0)-|" options:0 metrics:metrics views:views]; @@ -172,8 +170,9 @@ self.bodyTextView.text = @""; self.dateLabel.text = @""; - [self.avatarView cancelImageDownloadTask]; - self.avatarView.image = nil; + [self.avatarButton cancelImageDownloadTaskForState:UIControlStateNormal]; + [self.avatarButton setImage:nil forState:UIControlStateNormal]; + self.avatarButton.imageView.contentMode = UIViewContentModeScaleToFill; [self.previewImageView cancelImageDownloadTask]; self.previewImageView.layer.borderWidth = 0.0f; @@ -203,9 +202,17 @@ self.dateLabel.text = [NCUtils getTimeFromDate:date]; TalkAccount *activeAccount = [[NCDatabaseManager sharedInstance] activeAccount]; - [self.avatarView setImageWithURLRequest:[[NCAPIController sharedInstance] createAvatarRequestForUser:message.actorId withStyle:self.traitCollection.userInterfaceStyle andSize:96 usingAccount:activeAccount] - placeholderImage:nil success:nil failure:nil]; + [self.avatarButton setImageForState:UIControlStateNormal + withURLRequest:[[NCAPIController sharedInstance] + createAvatarRequestForUser:message.actorId + withStyle:self.traitCollection.userInterfaceStyle + andSize:96 + usingAccount:activeAccount] + placeholderImage:nil + success:nil + failure:nil]; + _avatarButton.menu = [super getDeferredUserMenuForMessage:message]; [self requestPreviewForMessage:message withAccount:activeAccount]; @@ -406,13 +413,6 @@ #pragma mark - Gesture recognizers -- (void)avatarTapped:(UIGestureRecognizer *)gestureRecognizer -{ - if (self.delegate && self.message) { - [self.delegate cellWantsToDisplayOptionsForMessageActor:self.message]; - } -} - - (void)previewTapped:(UITapGestureRecognizer *)recognizer { if (!self.fileParameter || !self.fileParameter.path || !self.fileParameter.link) { @@ -484,13 +484,6 @@ return _bodyTextView; } -- (void)setGuestAvatar:(NSString *)displayName -{ - UIColor *guestAvatarColor = [NCAppBranding placeholderColor]; - NSString *name = ([displayName isEqualToString:@""]) ? @"?" : displayName; - [_avatarView setImageWithString:name color:guestAvatarColor circular:true]; -} - - (void)clearFileStatusView { if (_activityIndicator) { [_activityIndicator stopAnimating]; diff --git a/NextcloudTalk/GroupedChatMessageTableViewCell.m b/NextcloudTalk/GroupedChatMessageTableViewCell.m index 71e13f05..1b50f25e 100644 --- a/NextcloudTalk/GroupedChatMessageTableViewCell.m +++ b/NextcloudTalk/GroupedChatMessageTableViewCell.m @@ -25,7 +25,6 @@ #import "MaterialActivityIndicator.h" #import "SLKUIConstants.h" #import "AFImageDownloader.h" -#import "UIImageView+AFNetworking.h" #import "NCAppBranding.h" #import "NCDatabaseManager.h" diff --git a/NextcloudTalk/LocationMessageTableViewCell.h b/NextcloudTalk/LocationMessageTableViewCell.h index 09536127..fd668a88 100644 --- a/NextcloudTalk/LocationMessageTableViewCell.h +++ b/NextcloudTalk/LocationMessageTableViewCell.h @@ -50,7 +50,7 @@ static NSString *GroupedLocationMessageCellIdentifier = @"GroupedLocationMessa @property (nonatomic, strong) UILabel *dateLabel; @property (nonatomic, strong) UIImageView *previewImageView; @property (nonatomic, strong) MessageBodyTextView *bodyTextView; -@property (nonatomic, strong) UIImageView *avatarView; +@property (nonatomic, strong) UIButton *avatarButton; @property (nonatomic, strong) UIView *statusView; @property (nonatomic, strong) GeoLocationRichObject *geoLocationRichObject; @property (nonatomic, strong) ReactionsView *reactionsView; @@ -58,7 +58,6 @@ static NSString *GroupedLocationMessageCellIdentifier = @"GroupedLocationMessa @property (nonatomic, strong) NSArray *vGroupedConstraints; + (CGFloat)defaultFontSize; -- (void)setGuestAvatar:(NSString *)displayName; - (void)setupForMessage:(NCChatMessage *)message withLastCommonReadMessage:(NSInteger)lastCommonRead; @end diff --git a/NextcloudTalk/LocationMessageTableViewCell.m b/NextcloudTalk/LocationMessageTableViewCell.m index ba5c09bb..b5bfd8c4 100644 --- a/NextcloudTalk/LocationMessageTableViewCell.m +++ b/NextcloudTalk/LocationMessageTableViewCell.m @@ -24,8 +24,7 @@ #import "MaterialActivityIndicator.h" #import "SLKUIConstants.h" -#import "UIImageView+AFNetworking.h" -#import "UIImageView+Letters.h" +#import "UIButton+AFNetworking.h" #import "NCAPIController.h" #import "NCAppBranding.h" @@ -55,15 +54,14 @@ - (void)configureSubviews { - _avatarView = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, kChatCellAvatarHeight, kChatCellAvatarHeight)]; - _avatarView.translatesAutoresizingMaskIntoConstraints = NO; - _avatarView.userInteractionEnabled = YES; - _avatarView.backgroundColor = [NCAppBranding placeholderColor]; - _avatarView.layer.cornerRadius = kChatCellAvatarHeight/2.0; - _avatarView.layer.masksToBounds = YES; - UITapGestureRecognizer *avatarTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(avatarTapped:)]; - [_avatarView addGestureRecognizer:avatarTap]; - + _avatarButton = [[UIButton alloc] initWithFrame:CGRectMake(0, 0, kChatCellAvatarHeight, kChatCellAvatarHeight)]; + _avatarButton.translatesAutoresizingMaskIntoConstraints = NO; + _avatarButton.backgroundColor = [NCAppBranding placeholderColor]; + _avatarButton.layer.cornerRadius = kChatCellAvatarHeight/2.0; + _avatarButton.layer.masksToBounds = YES; + _avatarButton.showsMenuAsPrimaryAction = YES; + _avatarButton.imageView.contentMode = UIViewContentModeScaleToFill; + _previewImageView = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, kLocationMessageCellPreviewWidth, kLocationMessageCellPreviewHeight)]; _previewImageView.translatesAutoresizingMaskIntoConstraints = NO; _previewImageView.userInteractionEnabled = NO; @@ -75,7 +73,7 @@ _previewImageView.userInteractionEnabled = YES; if ([self.reuseIdentifier isEqualToString:LocationMessageCellIdentifier]) { - [self.contentView addSubview:_avatarView]; + [self.contentView addSubview:self.avatarButton]; [self.contentView addSubview:self.titleLabel]; [self.contentView addSubview:self.dateLabel]; } @@ -88,7 +86,7 @@ [self.contentView addSubview:self.reactionsView]; - NSDictionary *views = @{@"avatarView": self.avatarView, + NSDictionary *views = @{@"avatarButton": self.avatarButton, @"statusView": self.statusView, @"titleLabel": self.titleLabel, @"dateLabel": self.dateLabel, @@ -109,15 +107,15 @@ }; if ([self.reuseIdentifier isEqualToString:LocationMessageCellIdentifier]) { - [self.contentView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-right-[avatarView(avatarSize)]-right-[titleLabel]-[dateLabel(>=dateLabelWidth)]-right-|" options:0 metrics:metrics views:views]]; - [self.contentView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-right-[avatarView(avatarSize)]-right-[previewImageView(previewWidth)]-(>=0)-|" options:0 metrics:metrics views:views]]; - [self.contentView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-right-[avatarView(avatarSize)]-right-[bodyTextView(>=0)]-right-|" options:0 metrics:metrics views:views]]; - [self.contentView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-right-[avatarView(avatarSize)]-right-[reactionsView(>=0)]-right-|" options:0 metrics:metrics views:views]]; + [self.contentView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-right-[avatarButton(avatarSize)]-right-[titleLabel]-[dateLabel(>=dateLabelWidth)]-right-|" options:0 metrics:metrics views:views]]; + [self.contentView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-right-[avatarButton(avatarSize)]-right-[previewImageView(previewWidth)]-(>=0)-|" options:0 metrics:metrics views:views]]; + [self.contentView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-right-[avatarButton(avatarSize)]-right-[bodyTextView(>=0)]-right-|" options:0 metrics:metrics views:views]]; + [self.contentView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-right-[avatarButton(avatarSize)]-right-[reactionsView(>=0)]-right-|" options:0 metrics:metrics views:views]]; [self.contentView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-padding-[statusView(statusSize)]-padding-[bodyTextView(>=0)]-right-|" options:0 metrics:metrics views:views]]; self.vConstraints = [NSLayoutConstraint constraintsWithVisualFormat:@"V:|-right-[titleLabel(avatarSize)]-left-[previewImageView(previewHeight)]-right-[bodyTextView(>=0@999)]-0-[reactionsView(0)]-left-|" options:0 metrics:metrics views:views]; [self.contentView addConstraints:self.vConstraints]; [self.contentView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-right-[dateLabel(avatarSize)]-(>=0)-|" options:0 metrics:metrics views:views]]; - [self.contentView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-right-[avatarView(avatarSize)]-(>=0)-|" options:0 metrics:metrics views:views]]; + [self.contentView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-right-[avatarButton(avatarSize)]-(>=0)-|" options:0 metrics:metrics views:views]]; [self.contentView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-right-[titleLabel(avatarSize)]-left-[previewImageView(previewHeight)]-right-[statusView(statusSize)]-(>=0)-|" options:0 metrics:metrics views:views]]; } else if ([self.reuseIdentifier isEqualToString:GroupedLocationMessageCellIdentifier]) { [self.contentView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-avatarGap-[previewImageView(previewWidth)]-(>=0)-|" options:0 metrics:metrics views:views]]; @@ -143,8 +141,9 @@ self.bodyTextView.text = @""; self.dateLabel.text = @""; - [self.avatarView cancelImageDownloadTask]; - self.avatarView.image = nil; + [self.avatarButton cancelImageDownloadTaskForState:UIControlStateNormal]; + [self.avatarButton setImage:nil forState:UIControlStateNormal]; + self.avatarButton.imageView.contentMode = UIViewContentModeScaleToFill; self.previewImageView.image = nil; @@ -169,8 +168,18 @@ self.dateLabel.text = [NCUtils getTimeFromDate:date]; TalkAccount *activeAccount = [[NCDatabaseManager sharedInstance] activeAccount]; - [self.avatarView setImageWithURLRequest:[[NCAPIController sharedInstance] createAvatarRequestForUser:message.actorId withStyle:self.traitCollection.userInterfaceStyle andSize:96 usingAccount:activeAccount] - placeholderImage:nil success:nil failure:nil]; + + [self.avatarButton setImageForState:UIControlStateNormal + withURLRequest:[[NCAPIController sharedInstance] + createAvatarRequestForUser:message.actorId + withStyle:self.traitCollection.userInterfaceStyle + andSize:96 + usingAccount:activeAccount] + placeholderImage:nil + success:nil + failure:nil]; + + _avatarButton.menu = [super getDeferredUserMenuForMessage:message]; if (message.sendingFailed) { @@ -257,13 +266,6 @@ #pragma mark - Gesture recognizers -- (void)avatarTapped:(UIGestureRecognizer *)gestureRecognizer -{ - if (self.delegate && self.message) { - [self.delegate cellWantsToDisplayOptionsForMessageActor:self.message]; - } -} - - (void)previewTapped:(UITapGestureRecognizer *)recognizer { if (!self.geoLocationRichObject) { @@ -335,13 +337,6 @@ return _bodyTextView; } -- (void)setGuestAvatar:(NSString *)displayName -{ - UIColor *guestAvatarColor = [NCAppBranding placeholderColor]; - NSString *name = ([displayName isEqualToString:@""]) ? @"?" : displayName; - [_avatarView setImageWithString:name color:guestAvatarColor circular:true]; -} - + (CGFloat)defaultFontSize { CGFloat pointSize = 16.0; diff --git a/NextcloudTalk/ObjectShareMessageTableViewCell.h b/NextcloudTalk/ObjectShareMessageTableViewCell.h index 525d93ae..be974c91 100644 --- a/NextcloudTalk/ObjectShareMessageTableViewCell.h +++ b/NextcloudTalk/ObjectShareMessageTableViewCell.h @@ -47,7 +47,7 @@ static NSString *GroupedObjectShareMessageCellIdentifier = @"GroupedObjectSha @property (nonatomic, strong) UIView *objectContainerView; @property (nonatomic, strong) UIImageView *objectTypeImageView; @property (nonatomic, strong) UITextView *objectTitle; -@property (nonatomic, strong) UIImageView *avatarView; +@property (nonatomic, strong) UIButton *avatarButton; @property (nonatomic, strong) UIView *statusView; @property (nonatomic, strong) NCMessageParameter *objectParameter; @property (nonatomic, strong) ReactionsView *reactionsView; @@ -55,7 +55,6 @@ static NSString *GroupedObjectShareMessageCellIdentifier = @"GroupedObjectSha @property (nonatomic, strong) NSArray *vGroupedConstraints; + (CGFloat)defaultFontSize; -- (void)setGuestAvatar:(NSString *)displayName; - (void)setupForMessage:(NCChatMessage *)message withLastCommonReadMessage:(NSInteger)lastCommonRead; @end diff --git a/NextcloudTalk/ObjectShareMessageTableViewCell.m b/NextcloudTalk/ObjectShareMessageTableViewCell.m index 1c6a1e4b..fa869b02 100644 --- a/NextcloudTalk/ObjectShareMessageTableViewCell.m +++ b/NextcloudTalk/ObjectShareMessageTableViewCell.m @@ -24,8 +24,7 @@ #import "MaterialActivityIndicator.h" #import "SLKUIConstants.h" -#import "UIImageView+AFNetworking.h" -#import "UIImageView+Letters.h" +#import "UIButton+AFNetworking.h" #import "NCAPIController.h" #import "NCAppBranding.h" @@ -46,15 +45,14 @@ - (void)configureSubviews { - _avatarView = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, kChatCellAvatarHeight, kChatCellAvatarHeight)]; - _avatarView.translatesAutoresizingMaskIntoConstraints = NO; - _avatarView.userInteractionEnabled = YES; - _avatarView.backgroundColor = [NCAppBranding placeholderColor]; - _avatarView.layer.cornerRadius = kChatCellAvatarHeight/2.0; - _avatarView.layer.masksToBounds = YES; - UITapGestureRecognizer *avatarTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(avatarTapped:)]; - [_avatarView addGestureRecognizer:avatarTap]; - + _avatarButton = [[UIButton alloc] initWithFrame:CGRectMake(0, 0, kChatCellAvatarHeight, kChatCellAvatarHeight)]; + _avatarButton.translatesAutoresizingMaskIntoConstraints = NO; + _avatarButton.backgroundColor = [NCAppBranding placeholderColor]; + _avatarButton.layer.cornerRadius = kChatCellAvatarHeight/2.0; + _avatarButton.layer.masksToBounds = YES; + _avatarButton.showsMenuAsPrimaryAction = YES; + _avatarButton.imageView.contentMode = UIViewContentModeScaleToFill; + _objectContainerView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 200, 44)]; _objectContainerView.translatesAutoresizingMaskIntoConstraints = NO; _objectContainerView.layer.cornerRadius = 8.0; @@ -85,7 +83,7 @@ _objectContainerView.userInteractionEnabled = YES; if ([self.reuseIdentifier isEqualToString:ObjectShareMessageCellIdentifier]) { - [self.contentView addSubview:_avatarView]; + [self.contentView addSubview:self.avatarButton]; [self.contentView addSubview:self.titleLabel]; [self.contentView addSubview:self.dateLabel]; } @@ -97,7 +95,7 @@ [self.contentView addSubview:self.reactionsView]; - NSDictionary *views = @{@"avatarView": self.avatarView, + NSDictionary *views = @{@"avatarButton": self.avatarButton, @"statusView": self.statusView, @"objectContainerView": self.objectContainerView, @"objectTypeImageView": self.objectTypeImageView, @@ -120,12 +118,12 @@ }; if ([self.reuseIdentifier isEqualToString:ObjectShareMessageCellIdentifier]) { - [self.contentView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-right-[avatarView(avatarSize)]-right-[titleLabel]-[dateLabel(>=dateLabelWidth)]-right-|" options:0 metrics:metrics views:views]]; + [self.contentView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-right-[avatarButton(avatarSize)]-right-[titleLabel]-[dateLabel(>=dateLabelWidth)]-right-|" options:0 metrics:metrics views:views]]; self.vConstraints = [NSLayoutConstraint constraintsWithVisualFormat:@"V:|-right-[titleLabel(avatarSize)]-left-[objectContainerView(>=0@999)]-0-[reactionsView(0)]-left-|" options:0 metrics:metrics views:views]; [self.contentView addConstraints:self.vConstraints]; [self.contentView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-right-[dateLabel(avatarSize)]-(>=0)-|" options:0 metrics:metrics views:views]]; [self.contentView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-right-[titleLabel(avatarSize)]-statusTopPadding-[statusView(statusSize)]-(>=0)-|" options:0 metrics:metrics views:views]]; - [self.contentView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-right-[avatarView(avatarSize)]-(>=0)-|" options:0 metrics:metrics views:views]]; + [self.contentView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-right-[avatarButton(avatarSize)]-(>=0)-|" options:0 metrics:metrics views:views]]; } else if ([self.reuseIdentifier isEqualToString:GroupedObjectShareMessageCellIdentifier]) { self.vGroupedConstraints = [NSLayoutConstraint constraintsWithVisualFormat:@"V:|-left-[objectContainerView(>=0@999)]-0-[reactionsView(0)]-left-|" options:0 metrics:metrics views:views]; [self.contentView addConstraints:self.vGroupedConstraints]; @@ -151,8 +149,9 @@ self.titleLabel.text = @""; self.dateLabel.text = @""; - [self.avatarView cancelImageDownloadTask]; - self.avatarView.image = nil; + [self.avatarButton cancelImageDownloadTaskForState:UIControlStateNormal]; + [self.avatarButton setImage:nil forState:UIControlStateNormal]; + self.avatarButton.imageView.contentMode = UIViewContentModeScaleToFill; self.objectTypeImageView.image = nil; self.objectTitle.text = @""; @@ -173,8 +172,18 @@ self.dateLabel.text = [NCUtils getTimeFromDate:date]; TalkAccount *activeAccount = [[NCDatabaseManager sharedInstance] activeAccount]; - [self.avatarView setImageWithURLRequest:[[NCAPIController sharedInstance] createAvatarRequestForUser:message.actorId withStyle:self.traitCollection.userInterfaceStyle andSize:96 usingAccount:activeAccount] - placeholderImage:nil success:nil failure:nil]; + + [self.avatarButton setImageForState:UIControlStateNormal + withURLRequest:[[NCAPIController sharedInstance] + createAvatarRequestForUser:message.actorId + withStyle:self.traitCollection.userInterfaceStyle + andSize:96 + usingAccount:activeAccount] + placeholderImage:nil + success:nil + failure:nil]; + + _avatarButton.menu = [super getDeferredUserMenuForMessage:message]; if (message.sendingFailed) { @@ -233,7 +242,7 @@ - (void)avatarTapped:(UIGestureRecognizer *)gestureRecognizer { if (self.delegate && self.message) { - [self.delegate cellWantsToDisplayOptionsForMessageActor:self.message]; + //[self.delegate cellWantsToDisplayOptionsForMessageActor:self.message]; } } @@ -298,13 +307,6 @@ return _reactionsView; } -- (void)setGuestAvatar:(NSString *)displayName -{ - UIColor *guestAvatarColor = [NCAppBranding placeholderColor]; - NSString *name = ([displayName isEqualToString:@""]) ? @"?" : displayName; - [_avatarView setImageWithString:name color:guestAvatarColor circular:true]; -} - + (CGFloat)defaultFontSize { CGFloat pointSize = 16.0; diff --git a/NextcloudTalk/VoiceMessageTableViewCell.h b/NextcloudTalk/VoiceMessageTableViewCell.h index e40fec6f..cdc0aad6 100644 --- a/NextcloudTalk/VoiceMessageTableViewCell.h +++ b/NextcloudTalk/VoiceMessageTableViewCell.h @@ -47,7 +47,7 @@ static NSString *GroupedVoiceMessageCellIdentifier = @"GroupedVoiceMessageCell @property (nonatomic, strong) UILabel *titleLabel; @property (nonatomic, strong) UILabel *dateLabel; @property (nonatomic, strong) MessageBodyTextView *bodyTextView; -@property (nonatomic, strong) UIImageView *avatarView; +@property (nonatomic, strong) UIButton *avatarButton; @property (nonatomic, strong) UIView *statusView; @property (nonatomic, strong) UIView *fileStatusView; @property (nonatomic, strong) NCMessageFileParameter *fileParameter; @@ -59,7 +59,6 @@ static NSString *GroupedVoiceMessageCellIdentifier = @"GroupedVoiceMessageCell @property (nonatomic, strong) NSArray *vGroupedConstraints; + (CGFloat)defaultFontSize; -- (void)setGuestAvatar:(NSString *)displayName; - (void)setupForMessage:(NCChatMessage *)message withLastCommonReadMessage:(NSInteger)lastCommonRead; - (void)setPlayerProgress:(CGFloat)progress isPlaying:(BOOL)playing maximumValue:(CGFloat)maxValue; - (void)resetPlayer; diff --git a/NextcloudTalk/VoiceMessageTableViewCell.m b/NextcloudTalk/VoiceMessageTableViewCell.m index c0d1afe3..751c20f2 100644 --- a/NextcloudTalk/VoiceMessageTableViewCell.m +++ b/NextcloudTalk/VoiceMessageTableViewCell.m @@ -24,8 +24,7 @@ #import "MaterialActivityIndicator.h" #import "SLKUIConstants.h" -#import "UIImageView+AFNetworking.h" -#import "UIImageView+Letters.h" +#import "UIButton+AFNetworking.h" #import "NCAPIController.h" #import "NCAppBranding.h" @@ -58,21 +57,20 @@ - (void)configureSubviews { - _avatarView = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, kChatCellAvatarHeight, kChatCellAvatarHeight)]; - _avatarView.translatesAutoresizingMaskIntoConstraints = NO; - _avatarView.userInteractionEnabled = YES; - _avatarView.backgroundColor = [NCAppBranding placeholderColor]; - _avatarView.layer.cornerRadius = kChatCellAvatarHeight/2.0; - _avatarView.layer.masksToBounds = YES; - UITapGestureRecognizer *avatarTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(avatarTapped:)]; - [_avatarView addGestureRecognizer:avatarTap]; - + _avatarButton = [[UIButton alloc] initWithFrame:CGRectMake(0, 0, kChatCellAvatarHeight, kChatCellAvatarHeight)]; + _avatarButton.translatesAutoresizingMaskIntoConstraints = NO; + _avatarButton.backgroundColor = [NCAppBranding placeholderColor]; + _avatarButton.layer.cornerRadius = kChatCellAvatarHeight/2.0; + _avatarButton.layer.masksToBounds = YES; + _avatarButton.showsMenuAsPrimaryAction = YES; + _avatarButton.imageView.contentMode = UIViewContentModeScaleToFill; + _audioPlayerView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 200, 44)]; _audioPlayerView.translatesAutoresizingMaskIntoConstraints = NO; [_audioPlayerView setSemanticContentAttribute:UISemanticContentAttributeForceLeftToRight]; if ([self.reuseIdentifier isEqualToString:VoiceMessageCellIdentifier]) { - [self.contentView addSubview:_avatarView]; + [self.contentView addSubview:self.avatarButton]; [self.contentView addSubview:self.titleLabel]; [self.contentView addSubview:self.dateLabel]; } @@ -111,7 +109,7 @@ [self.contentView addSubview:self.reactionsView]; - NSDictionary *views = @{@"avatarView": self.avatarView, + NSDictionary *views = @{@"avatarButton": self.avatarButton, @"statusView": self.statusView, @"fileStatusView": self.fileStatusView, @"durationLabel": self.durationLabel, @@ -140,12 +138,12 @@ }; if ([self.reuseIdentifier isEqualToString:VoiceMessageCellIdentifier]) { - [self.contentView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-right-[avatarView(avatarSize)]-right-[titleLabel]-[dateLabel(>=dateLabelWidth)]-right-|" options:0 metrics:metrics views:views]]; + [self.contentView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-right-[avatarButton(avatarSize)]-right-[titleLabel]-[dateLabel(>=dateLabelWidth)]-right-|" options:0 metrics:metrics views:views]]; self.vConstraints = [NSLayoutConstraint constraintsWithVisualFormat:@"V:|-right-[titleLabel(avatarSize)]-left-[audioPlayerView(buttonHeight)]-right-[bodyTextView(>=0@999)]-0-[reactionsView(0)]-left-|" options:0 metrics:metrics views:views]; [self.contentView addConstraints:self.vConstraints]; [self.contentView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-right-[dateLabel(avatarSize)]-(>=0)-|" options:0 metrics:metrics views:views]]; [self.contentView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-right-[titleLabel(avatarSize)]-statusTopPadding-[statusView(statusSize)]-(>=0)-|" options:0 metrics:metrics views:views]]; - [self.contentView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-right-[avatarView(avatarSize)]-(>=0)-|" options:0 metrics:metrics views:views]]; + [self.contentView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-right-[avatarButton(avatarSize)]-(>=0)-|" options:0 metrics:metrics views:views]]; } else if ([self.reuseIdentifier isEqualToString:GroupedVoiceMessageCellIdentifier]) { self.vGroupedConstraints = [NSLayoutConstraint constraintsWithVisualFormat:@"V:|-left-[audioPlayerView(buttonHeight)]-right-[bodyTextView(>=0@999)]-0-[reactionsView(0)]-left-|" options:0 metrics:metrics views:views]; [self.contentView addConstraints:self.vGroupedConstraints]; @@ -179,8 +177,9 @@ self.bodyTextView.text = @""; self.dateLabel.text = @""; - [self.avatarView cancelImageDownloadTask]; - self.avatarView.image = nil; + [self.avatarButton cancelImageDownloadTaskForState:UIControlStateNormal]; + [self.avatarButton setImage:nil forState:UIControlStateNormal]; + self.avatarButton.imageView.contentMode = UIViewContentModeScaleToFill; self.vConstraints[7].constant = 0; self.vGroupedConstraints[5].constant = 0; @@ -201,8 +200,18 @@ self.dateLabel.text = [NCUtils getTimeFromDate:date]; TalkAccount *activeAccount = [[NCDatabaseManager sharedInstance] activeAccount]; - [self.avatarView setImageWithURLRequest:[[NCAPIController sharedInstance] createAvatarRequestForUser:message.actorId withStyle:self.traitCollection.userInterfaceStyle andSize:96 usingAccount:activeAccount] - placeholderImage:nil success:nil failure:nil]; + + [self.avatarButton setImageForState:UIControlStateNormal + withURLRequest:[[NCAPIController sharedInstance] + createAvatarRequestForUser:message.actorId + withStyle:self.traitCollection.userInterfaceStyle + andSize:96 + usingAccount:activeAccount] + placeholderImage:nil + success:nil + failure:nil]; + + _avatarButton.menu = [super getDeferredUserMenuForMessage:message]; if (message.sendingFailed) { UIImageView *errorView = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, 20, 20)]; @@ -378,15 +387,6 @@ [self.fileStatusView addSubview:_activityIndicator]; } -#pragma mark - Gesture recognizers - -- (void)avatarTapped:(UIGestureRecognizer *)gestureRecognizer -{ - if (self.delegate && self.message) { - [self.delegate cellWantsToDisplayOptionsForMessageActor:self.message]; - } -} - #pragma mark - ReactionsView delegate - (void)didSelectReactionWithReaction:(NCChatReaction *)reaction @@ -463,13 +463,6 @@ } } -- (void)setGuestAvatar:(NSString *)displayName -{ - UIColor *guestAvatarColor = [NCAppBranding placeholderColor]; - NSString *name = ([displayName isEqualToString:@""]) ? @"?" : displayName; - [_avatarView setImageWithString:name color:guestAvatarColor circular:true]; -} - - (void)clearFileStatusView { if (_activityIndicator) { [_activityIndicator stopAnimating];