/** * SPDX-FileCopyrightText: 2020 Nextcloud GmbH and Nextcloud contributors * SPDX-License-Identifier: GPL-3.0-or-later */ #import "ChatTableViewCell.h" #import "NextcloudTalk-Swift.h" typedef void (^GetMenuUserActionsForMessageCompletionBlock)(NSArray *menuItems); @interface ChatTableViewCell () @property (nonatomic, strong) DRCellSlideGestureRecognizer *replyGestureRecognizer; @end @implementation ChatTableViewCell - (instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier { self = [super initWithStyle:style reuseIdentifier:reuseIdentifier]; if (self) { // Initialization } return self; } - (void)prepareForReuse { [super prepareForReuse]; self.messageId = -1; self.message = nil; [self removeGestureRecognizer:self.replyGestureRecognizer]; } - (void)addReplyGestureWithActionBlock:(DRCellSlideActionBlock)block { self.replyGestureRecognizer = [DRCellSlideGestureRecognizer new]; self.replyGestureRecognizer.leftActionStartPosition = 80; DRCellSlideAction *action = [DRCellSlideAction actionForFraction:0.2]; action.behavior = DRCellSlideActionPullBehavior; action.activeColor = [UIColor labelColor]; action.inactiveColor = [UIColor placeholderTextColor]; action.activeBackgroundColor = self.backgroundColor; action.inactiveBackgroundColor = self.backgroundColor; action.icon = [UIImage systemImageNamed:@"arrowshape.turn.up.left"]; [action setWillTriggerBlock:^(UITableView *tableView, NSIndexPath *indexPath) { block(tableView, indexPath); }]; [action setDidChangeStateBlock:^(DRCellSlideAction *action, BOOL active) { if (active) { // Actuate `Peek` feedback (weak boom) AudioServicesPlaySystemSound(1519); } }]; [self.replyGestureRecognizer addActions:action]; [self addGestureRecognizer:self.replyGestureRecognizer]; } - (UIMenu *)getDeferredUserMenuForMessage:(NCChatMessage *)message { TalkAccount *activeAccount = [[NCDatabaseManager sharedInstance] activeAccount]; if (![message.actorType isEqualToString:@"users"] || [message.actorId isEqualToString:activeAccount.userId]) { return nil; } UIDeferredMenuElement *deferredMenuElement; // Use an uncached provider so local time is not cached deferredMenuElement = [UIDeferredMenuElement elementWithUncachedProvider:^(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:@"talk-20"] 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:NSNotification.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 systemImageNamed:@"person"]]; } else if ([appId isEqualToString:@"email"]) { [otherAction setImage:[UIImage systemImageNamed:@"envelope"]]; } else if ([appId isEqualToString:@"timezone"]) { [otherAction setImage:[UIImage systemImageNamed:@"clock"]]; } else if ([appId isEqualToString:@"social"]) { [otherAction setImage:[UIImage systemImageNamed:@"heart"]]; } [items addObject:otherAction]; } if (block) { block(items); } }]; } @end