зеркало из https://github.com/nextcloud/talk-ios.git
Show chat messages reactions.
Signed-off-by: Ivan Sein <ivan@nextcloud.com>
This commit is contained in:
Родитель
b1671e9a6a
Коммит
894b87355c
|
@ -246,6 +246,12 @@
|
|||
2CC007CA20E125C20096D91F /* NewRoomTableViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 2CC007C820E125C20096D91F /* NewRoomTableViewController.m */; };
|
||||
2CC007CB20E125C20096D91F /* NewRoomTableViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 2CC007C920E125C20096D91F /* NewRoomTableViewController.xib */; };
|
||||
2CC007CE20E50B0A0096D91F /* MessageBodyTextView.m in Sources */ = {isa = PBXBuildFile; fileRef = 2CC007CD20E50B0A0096D91F /* MessageBodyTextView.m */; };
|
||||
2CC32E8D27F4540E00BB8C39 /* ReactionsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2CC32E8C27F4540E00BB8C39 /* ReactionsView.swift */; };
|
||||
2CC32E9227F45AE000BB8C39 /* ReactionsViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2CC32E9027F45AE000BB8C39 /* ReactionsViewCell.swift */; };
|
||||
2CC32E9327F45AE000BB8C39 /* ReactionsViewCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = 2CC32E9127F45AE000BB8C39 /* ReactionsViewCell.xib */; };
|
||||
2CC32E9827F5D9BD00BB8C39 /* NCChatReaction.m in Sources */ = {isa = PBXBuildFile; fileRef = 2CC32E9727F5D9BD00BB8C39 /* NCChatReaction.m */; };
|
||||
2CC32E9927F5DADA00BB8C39 /* NCChatReaction.m in Sources */ = {isa = PBXBuildFile; fileRef = 2CC32E9727F5D9BD00BB8C39 /* NCChatReaction.m */; };
|
||||
2CC32E9A27F5DADB00BB8C39 /* NCChatReaction.m in Sources */ = {isa = PBXBuildFile; fileRef = 2CC32E9727F5D9BD00BB8C39 /* NCChatReaction.m */; };
|
||||
2CC5F0982716FF1900DE1775 /* NCCommunication in Frameworks */ = {isa = PBXBuildFile; productRef = 2CC5F0972716FF1900DE1775 /* NCCommunication */; };
|
||||
2CC5F09A2717028B00DE1775 /* NCCommunication in Frameworks */ = {isa = PBXBuildFile; productRef = 2CC5F0992717028B00DE1775 /* NCCommunication */; };
|
||||
2CC5F09C2717198500DE1775 /* NCCommunication in Frameworks */ = {isa = PBXBuildFile; productRef = 2CC5F09B2717198500DE1775 /* NCCommunication */; };
|
||||
|
@ -714,6 +720,11 @@
|
|||
2CC007C920E125C20096D91F /* NewRoomTableViewController.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = NewRoomTableViewController.xib; sourceTree = "<group>"; };
|
||||
2CC007CC20E50B0A0096D91F /* MessageBodyTextView.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MessageBodyTextView.h; sourceTree = "<group>"; };
|
||||
2CC007CD20E50B0A0096D91F /* MessageBodyTextView.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MessageBodyTextView.m; sourceTree = "<group>"; };
|
||||
2CC32E8C27F4540E00BB8C39 /* ReactionsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ReactionsView.swift; sourceTree = "<group>"; };
|
||||
2CC32E9027F45AE000BB8C39 /* ReactionsViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ReactionsViewCell.swift; sourceTree = "<group>"; };
|
||||
2CC32E9127F45AE000BB8C39 /* ReactionsViewCell.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = ReactionsViewCell.xib; sourceTree = "<group>"; };
|
||||
2CC32E9627F5D9BD00BB8C39 /* NCChatReaction.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = NCChatReaction.h; sourceTree = "<group>"; };
|
||||
2CC32E9727F5D9BD00BB8C39 /* NCChatReaction.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = NCChatReaction.m; sourceTree = "<group>"; };
|
||||
2CC7158820B837140045C789 /* PlaceholderView.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = PlaceholderView.xib; sourceTree = "<group>"; };
|
||||
2CC7158A20B8394A0045C789 /* PlaceholderView.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = PlaceholderView.h; sourceTree = "<group>"; };
|
||||
2CC7158B20B8394A0045C789 /* PlaceholderView.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = PlaceholderView.m; sourceTree = "<group>"; };
|
||||
|
@ -1177,6 +1188,9 @@
|
|||
2CA52AC92670D02800619610 /* VoiceMessageRecordingView.h */,
|
||||
2CA52ACA2670D02800619610 /* VoiceMessageRecordingView.m */,
|
||||
2CA52ACC2670D07900619610 /* VoiceMessageRecordingView.xib */,
|
||||
2CC32E8C27F4540E00BB8C39 /* ReactionsView.swift */,
|
||||
2CC32E9027F45AE000BB8C39 /* ReactionsViewCell.swift */,
|
||||
2CC32E9127F45AE000BB8C39 /* ReactionsViewCell.xib */,
|
||||
);
|
||||
name = "Chat views";
|
||||
sourceTree = "<group>";
|
||||
|
@ -1413,6 +1427,8 @@
|
|||
2C6DEAB3243CCCCA00AE8437 /* Chat views */,
|
||||
2CA1553F208E350300CE8EF0 /* NCChatMessage.h */,
|
||||
2CA15540208E350300CE8EF0 /* NCChatMessage.m */,
|
||||
2CC32E9627F5D9BD00BB8C39 /* NCChatReaction.h */,
|
||||
2CC32E9727F5D9BD00BB8C39 /* NCChatReaction.m */,
|
||||
2C42ADB220B58E6300296DEA /* NCChatController.h */,
|
||||
2C42ADB320B58E6300296DEA /* NCChatController.m */,
|
||||
1FEDE3C5257D439500853F79 /* NCChatFileController.h */,
|
||||
|
@ -1610,6 +1626,7 @@
|
|||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
2CC007BE20D8F24B0096D91F /* RoomCreation2TableViewController.xib in Resources */,
|
||||
2CC32E9327F45AE000BB8C39 /* ReactionsViewCell.xib in Resources */,
|
||||
2C330372255E6EBC00BDB4E4 /* InfoPlist.strings in Resources */,
|
||||
2C78EFA11F828C41008AFA74 /* CallViewController.xib in Resources */,
|
||||
2C3780C5210F4A26003F9AE8 /* HeaderWithButton.xib in Resources */,
|
||||
|
@ -1838,6 +1855,7 @@
|
|||
2C78EF9C1F826B22008AFA74 /* NCCallController.m in Sources */,
|
||||
2C4D7D761F30F7B600FF4A0D /* ARDUtilities.m in Sources */,
|
||||
2CB6ACE92641954700D3D641 /* MapViewController.m in Sources */,
|
||||
2CC32E9227F45AE000BB8C39 /* ReactionsViewCell.swift in Sources */,
|
||||
2CBF82AE1FC888FC00636459 /* NCPushNotification.m in Sources */,
|
||||
2CC7159420C54D080045C789 /* ChatTableViewCell.m in Sources */,
|
||||
2CA1CCAA1F02D1A4002FE6A2 /* NCAPIController.m in Sources */,
|
||||
|
@ -1867,6 +1885,7 @@
|
|||
2C4446F0265D454200DF1DBC /* NotificationCenterNotifications.m in Sources */,
|
||||
1F3D3B22255F109E00230DAE /* BarButtonItemWithActivity.m in Sources */,
|
||||
2C0574821EDD9E8E00D9E7F2 /* main.m in Sources */,
|
||||
2CC32E9827F5D9BD00BB8C39 /* NCChatReaction.m in Sources */,
|
||||
2C40281522832EED0000DDFC /* NCDatabaseManager.m in Sources */,
|
||||
2CC007B820D8139D0096D91F /* RoomCreationTableViewController.m in Sources */,
|
||||
DA7558132790D65700A48A1B /* AccountTableViewCell.swift in Sources */,
|
||||
|
@ -1924,6 +1943,7 @@
|
|||
2C1ABDCE257E939600AEDFB6 /* NCContact.m in Sources */,
|
||||
2C7A12422017872600864818 /* AddParticipantsTableViewController.m in Sources */,
|
||||
2C43BA7621309A1000B3068A /* NCMessageParameter.m in Sources */,
|
||||
2CC32E8D27F4540E00BB8C39 /* ReactionsView.swift in Sources */,
|
||||
2C4DE9F221F732B40096940D /* NCAudioController.m in Sources */,
|
||||
2C8A2BC9221F094F00DE6D2C /* DirectoryTableViewController.m in Sources */,
|
||||
2C42ADB420B58E6300296DEA /* NCChatController.m in Sources */,
|
||||
|
@ -1986,6 +2006,7 @@
|
|||
2C62AFB924C1A4E6007E460A /* ShareViewController.m in Sources */,
|
||||
2C4446DF2658158000DF1DBC /* NCChatBlock.m in Sources */,
|
||||
2C62B00924C1BDBD007E460A /* NCAPISessionManager.m in Sources */,
|
||||
2CC32E9A27F5DADB00BB8C39 /* NCChatReaction.m in Sources */,
|
||||
2C62AFBB24C1B7B1007E460A /* NCDatabaseManager.m in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
|
@ -2024,6 +2045,7 @@
|
|||
2C444704265D641300DF1DBC /* NCUserDefaults.m in Sources */,
|
||||
2CC001B724A37A9A00A20167 /* NCUser.m in Sources */,
|
||||
2CC0016124A25B5500A20167 /* NCAPIController.m in Sources */,
|
||||
2CC32E9927F5DADA00BB8C39 /* NCChatReaction.m in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
|
|
|
@ -27,14 +27,20 @@
|
|||
#import "UIImageView+AFNetworking.h"
|
||||
#import "UIImageView+Letters.h"
|
||||
|
||||
#import "NextcloudTalk-Swift.h"
|
||||
|
||||
#import "NCAPIController.h"
|
||||
#import "NCAppBranding.h"
|
||||
#import "NCChatMessage.h"
|
||||
#import "NCDatabaseManager.h"
|
||||
#import "NCUtils.h"
|
||||
#import "QuotedMessageView.h"
|
||||
|
||||
@interface ChatMessageTableViewCell ()
|
||||
@property (nonatomic, strong) UIView *quoteContainerView;
|
||||
@property (nonatomic, strong) ReactionsView *reactionsView;
|
||||
@property (nonatomic, strong) NSArray<NSLayoutConstraint *> *vConstraint1;
|
||||
@property (nonatomic, strong) NSArray<NSLayoutConstraint *> *vConstraint2;
|
||||
@end
|
||||
|
||||
@implementation ChatMessageTableViewCell
|
||||
|
@ -83,6 +89,8 @@
|
|||
[self.quoteContainerView addGestureRecognizer:quoteTap];
|
||||
}
|
||||
|
||||
[self.contentView addSubview:self.reactionsView];
|
||||
|
||||
NSDictionary *views = @{@"avatarView": self.avatarView,
|
||||
@"userStatusImageView": self.userStatusImageView,
|
||||
@"statusView": self.statusView,
|
||||
|
@ -90,7 +98,8 @@
|
|||
@"dateLabel": self.dateLabel,
|
||||
@"bodyTextView": self.bodyTextView,
|
||||
@"quoteContainerView": self.quoteContainerView,
|
||||
@"quotedMessageView": self.quotedMessageView
|
||||
@"quotedMessageView": self.quotedMessageView,
|
||||
@"reactionsView": self.reactionsView
|
||||
};
|
||||
|
||||
NSDictionary *metrics = @{@"avatarSize": @(kChatCellAvatarHeight),
|
||||
|
@ -104,9 +113,12 @@
|
|||
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:|-padding-[statusView(statusSize)]-padding-[bodyTextView(>=0)]-right-|" options:0 metrics:metrics views:views]];
|
||||
[self.contentView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-right-[titleLabel(avatarSize)]-left-[bodyTextView(>=0@999)]-left-|" options:0 metrics:metrics views:views]];
|
||||
[self.contentView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-right-[dateLabel(avatarSize)]-left-[bodyTextView(>=0@999)]-left-|" options:0 metrics:metrics views:views]];
|
||||
_vConstraint1 = [NSLayoutConstraint constraintsWithVisualFormat:@"V:|-right-[titleLabel(avatarSize)]-left-[bodyTextView(>=0@999)]-0-[reactionsView(0)]-left-|" options:0 metrics:metrics views:views];
|
||||
[self.contentView addConstraints:_vConstraint1];
|
||||
_vConstraint2 = [NSLayoutConstraint constraintsWithVisualFormat:@"V:|-right-[dateLabel(avatarSize)]-left-[bodyTextView(>=0@999)]-0-[reactionsView(0)]-left-|" options:0 metrics:metrics views:views];
|
||||
[self.contentView addConstraints:_vConstraint2];
|
||||
[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]];
|
||||
|
@ -151,6 +163,10 @@
|
|||
self.quotedMessageView.actorLabel.text = @"";
|
||||
self.quotedMessageView.messageLabel.text = @"";
|
||||
|
||||
self.reactionsView.reactions = @[];
|
||||
_vConstraint1[5].constant = 0;
|
||||
_vConstraint2[5].constant = 0;
|
||||
|
||||
[self.avatarView cancelImageDownloadTask];
|
||||
self.avatarView.image = nil;
|
||||
self.avatarView.contentMode = UIViewContentModeScaleToFill;
|
||||
|
@ -219,6 +235,17 @@
|
|||
return _dateLabel;
|
||||
}
|
||||
|
||||
- (ReactionsView *)reactionsView
|
||||
{
|
||||
if (!_reactionsView) {
|
||||
UICollectionViewFlowLayout *flowLayout = [[UICollectionViewFlowLayout alloc] init];
|
||||
flowLayout.scrollDirection = UICollectionViewScrollDirectionHorizontal;
|
||||
_reactionsView = [[ReactionsView alloc] initWithFrame:CGRectMake(0, 0, 50, 50) collectionViewLayout:flowLayout];
|
||||
_reactionsView.translatesAutoresizingMaskIntoConstraints = NO;
|
||||
}
|
||||
return _reactionsView;
|
||||
}
|
||||
|
||||
- (UIView *)quoteContainerView
|
||||
{
|
||||
if (!_quoteContainerView) {
|
||||
|
@ -270,10 +297,12 @@
|
|||
[self setBotAvatar];
|
||||
}
|
||||
} else {
|
||||
[self.avatarView setImageWithURLRequest:[[NCAPIController sharedInstance] createAvatarRequestForUser:message.actorId
|
||||
andSize:96
|
||||
usingAccount:activeAccount]
|
||||
placeholderImage:nil success:nil failure:nil];
|
||||
[self.avatarView
|
||||
setImageWithURLRequest:[[NCAPIController sharedInstance]
|
||||
createAvatarRequestForUser:message.actorId
|
||||
andSize:96
|
||||
usingAccount:activeAccount]
|
||||
placeholderImage:nil success:nil failure:nil];
|
||||
}
|
||||
|
||||
// This check is just a workaround to fix the issue with the deleted parents returned by the API.
|
||||
|
@ -305,6 +334,13 @@
|
|||
self.bodyTextView.textColor = [UIColor tertiaryLabelColor];
|
||||
}
|
||||
}
|
||||
|
||||
const NSArray *reactions = message.reactionsArray;
|
||||
[self.reactionsView updateReactionsWithReactions:reactions];
|
||||
if (reactions.count > 0) {
|
||||
_vConstraint1[5].constant = 40;
|
||||
_vConstraint2[5].constant = 40;
|
||||
}
|
||||
}
|
||||
|
||||
- (void)setGuestAvatar:(NSString *)displayName
|
||||
|
|
|
@ -21,6 +21,9 @@
|
|||
*/
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
|
||||
#import "NextcloudTalk-Swift.h"
|
||||
|
||||
#import "ChatTableViewCell.h"
|
||||
#import "NCChatMessage.h"
|
||||
#import "MessageBodyTextView.h"
|
||||
|
@ -32,6 +35,8 @@ static NSString *GroupedChatMessageCellIdentifier = @"GroupedChatMessageCellIden
|
|||
|
||||
@property (nonatomic, strong) MessageBodyTextView *bodyTextView;
|
||||
@property (nonatomic, strong) UIView *statusView;
|
||||
@property (nonatomic, strong) ReactionsView *reactionsView;
|
||||
@property (nonatomic, strong) NSArray<NSLayoutConstraint *> *vConstraint;
|
||||
|
||||
+ (CGFloat)defaultFontSize;
|
||||
- (void)setupForMessage:(NCChatMessage *)message withLastCommonReadMessage:(NSInteger)lastCommonRead;
|
||||
|
|
|
@ -47,9 +47,11 @@
|
|||
_statusView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, kChatCellStatusViewHeight, kChatCellStatusViewHeight)];
|
||||
_statusView.translatesAutoresizingMaskIntoConstraints = NO;
|
||||
[self.contentView addSubview:_statusView];
|
||||
[self.contentView addSubview:self.reactionsView];
|
||||
|
||||
NSDictionary *views = @{@"bodyTextView": self.bodyTextView,
|
||||
@"statusView": self.statusView
|
||||
@"statusView": self.statusView,
|
||||
@"reactionsView": self.reactionsView
|
||||
};
|
||||
|
||||
NSDictionary *metrics = @{@"avatar": @50,
|
||||
|
@ -61,7 +63,9 @@
|
|||
|
||||
[self.contentView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-avatar-[bodyTextView(>=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:@"V:|-left-[bodyTextView(>=0@999)]-left-|" options:0 metrics:metrics views:views]];
|
||||
[self.contentView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-padding-[statusView(statusSize)]-padding-[reactionsView(>=0)]-right-|" options:0 metrics:metrics views:views]];
|
||||
_vConstraint = [NSLayoutConstraint constraintsWithVisualFormat:@"V:|-left-[bodyTextView(>=0@999)]-0-[reactionsView(0)]-left-|" options:0 metrics:metrics views:views];
|
||||
[self.contentView addConstraints:_vConstraint];
|
||||
[self.contentView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-left-[statusView(statusSize)]-(>=0)-|" options:0 metrics:metrics views:views]];
|
||||
}
|
||||
|
||||
|
@ -75,6 +79,9 @@
|
|||
|
||||
self.bodyTextView.text = @"";
|
||||
|
||||
self.reactionsView.reactions = @[];
|
||||
_vConstraint[3].constant = 0;
|
||||
|
||||
self.statusView.hidden = NO;
|
||||
[self.statusView.subviews makeObjectsPerformSelector: @selector(removeFromSuperview)];
|
||||
}
|
||||
|
@ -111,6 +118,11 @@
|
|||
self.bodyTextView.textColor = [UIColor tertiaryLabelColor];
|
||||
}
|
||||
}
|
||||
const NSArray *reactions = message.reactionsArray;
|
||||
[self.reactionsView updateReactionsWithReactions:reactions];
|
||||
if (reactions.count > 0) {
|
||||
_vConstraint[3].constant = 40;
|
||||
}
|
||||
}
|
||||
|
||||
- (void)setDeliveryState:(ChatMessageDeliveryState)state
|
||||
|
@ -153,6 +165,17 @@
|
|||
return _bodyTextView;
|
||||
}
|
||||
|
||||
- (ReactionsView *)reactionsView
|
||||
{
|
||||
if (!_reactionsView) {
|
||||
UICollectionViewFlowLayout *flowLayout = [[UICollectionViewFlowLayout alloc] init];
|
||||
flowLayout.scrollDirection = UICollectionViewScrollDirectionHorizontal;
|
||||
_reactionsView = [[ReactionsView alloc] initWithFrame:CGRectMake(0, 0, 50, 50) collectionViewLayout:flowLayout];
|
||||
_reactionsView.translatesAutoresizingMaskIntoConstraints = NO;
|
||||
}
|
||||
return _reactionsView;
|
||||
}
|
||||
|
||||
+ (CGFloat)defaultFontSize
|
||||
{
|
||||
CGFloat pointSize = 16.0;
|
||||
|
|
|
@ -376,7 +376,7 @@ NSString * const NCChatControllerDidReceiveCallEndedMessageNotification
|
|||
userInfo:userInfo];
|
||||
}
|
||||
// Notify if "deleted messages" have been received
|
||||
if ([message.systemMessage isEqualToString:@"message_deleted"] || [message.systemMessage isEqualToString:@"reaction"]) {
|
||||
if ([message.systemMessage isEqualToString:@"message_deleted"] || [message.systemMessage isEqualToString:@"reaction"] || [message.systemMessage isEqualToString:@"reaction_revoked"]) {
|
||||
[userInfo setObject:message forKey:@"updateMessage"];
|
||||
[[NSNotificationCenter defaultCenter] postNotificationName:NCChatControllerDidReceiveUpdateMessageNotification
|
||||
object:self
|
||||
|
@ -624,8 +624,10 @@ NSString * const NCChatControllerDidReceiveCallEndedMessageNotification
|
|||
object:self
|
||||
userInfo:userInfo];
|
||||
}
|
||||
// Notify if "deleted messages" have been received
|
||||
if ([message.systemMessage isEqualToString:@"message_deleted"] || [message.systemMessage isEqualToString:@"reaction"]) {
|
||||
// Notify if an "update messages" have been received
|
||||
if ([message.systemMessage isEqualToString:@"message_deleted"] ||
|
||||
[message.systemMessage isEqualToString:@"reaction"] ||
|
||||
[message.systemMessage isEqualToString:@"reaction_revoked"]) {
|
||||
[userInfo setObject:message forKey:@"updateMessage"];
|
||||
[[NSNotificationCenter defaultCenter] postNotificationName:NCChatControllerDidReceiveUpdateMessageNotification
|
||||
object:self
|
||||
|
|
|
@ -23,6 +23,7 @@
|
|||
#import <Foundation/Foundation.h>
|
||||
#import <UIKit/UIKit.h>
|
||||
#import <Realm/Realm.h>
|
||||
#import "NCChatReaction.h"
|
||||
#import "NCDatabaseManager.h"
|
||||
#import "NCMessageParameter.h"
|
||||
#import "NCMessageFileParameter.h"
|
||||
|
@ -37,11 +38,6 @@ extern NSString * const kMessageTypeSystem;
|
|||
extern NSString * const kMessageTypeCommand;
|
||||
extern NSString * const kMessageTypeVoiceMessage;
|
||||
|
||||
@interface NCChatReaction : RLMObject
|
||||
@property (nonatomic, strong) NSString *reaction;
|
||||
@property (nonatomic, assign) NSInteger count;
|
||||
@end
|
||||
|
||||
RLM_ARRAY_TYPE(NCChatReaction)
|
||||
|
||||
@interface NCChatMessage : RLMObject <NSCopying>
|
||||
|
@ -81,5 +77,6 @@ RLM_ARRAY_TYPE(NCChatReaction)
|
|||
- (NSMutableAttributedString *)parsedMessage;
|
||||
- (NSMutableAttributedString *)systemMessageFormat;
|
||||
- (NCChatMessage *)parent;
|
||||
- (NSArray *)reactionsArray;
|
||||
|
||||
@end
|
||||
|
|
|
@ -41,9 +41,6 @@ NSString * const kMessageTypeVoiceMessage = @"voice-message";
|
|||
|
||||
@end
|
||||
|
||||
@implementation NCChatReaction
|
||||
@end
|
||||
|
||||
@implementation NCChatMessage
|
||||
|
||||
+ (instancetype)messageWithDictionary:(NSDictionary *)messageDict
|
||||
|
@ -93,9 +90,7 @@ NSString * const kMessageTypeVoiceMessage = @"voice-message";
|
|||
NSDictionary *reactionsDict = reactions;
|
||||
NSMutableArray *reactionsArray = [NSMutableArray new];
|
||||
for (NSString *reactionKey in reactionsDict.allKeys) {
|
||||
NCChatReaction *reaction = [[NCChatReaction alloc] init];
|
||||
reaction.reaction = reactionKey;
|
||||
reaction.count = [[reactionsDict objectForKey:reactionKey] integerValue];
|
||||
NCChatReaction *reaction = [NCChatReaction initWithReaction:reactionKey andCount:[[reactionsDict objectForKey:reactionKey] integerValue]];
|
||||
[reactionsArray addObject:reaction];
|
||||
}
|
||||
message.reactions = (RLMArray<NCChatReaction *><NCChatReaction> *)reactionsArray;
|
||||
|
@ -374,4 +369,13 @@ NSString * const kMessageTypeVoiceMessage = @"voice-message";
|
|||
return nil;
|
||||
}
|
||||
|
||||
- (NSArray *)reactionsArray
|
||||
{
|
||||
NSMutableArray *reactions = [NSMutableArray new];
|
||||
for (NCChatReaction *reaction in _reactions) {
|
||||
[reactions addObject:reaction];
|
||||
}
|
||||
return reactions;
|
||||
}
|
||||
|
||||
@end
|
||||
|
|
|
@ -0,0 +1,34 @@
|
|||
/**
|
||||
* @copyright Copyright (c) 2022 Ivan Sein <ivan@nextcloud.com>
|
||||
*
|
||||
* @author Ivan Sein <ivan@nextcloud.com>
|
||||
*
|
||||
* @license GNU GPL version 3 or any later version
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#import <Realm/Realm.h>
|
||||
|
||||
|
||||
@interface NCChatReaction : RLMObject
|
||||
|
||||
@property (nonatomic, strong) NSString *reaction;
|
||||
@property (nonatomic, assign) NSInteger count;
|
||||
|
||||
+ (instancetype)initWithReaction:(NSString *)reaction andCount:(NSInteger)count;
|
||||
|
||||
@end
|
||||
|
|
@ -0,0 +1,35 @@
|
|||
/**
|
||||
* @copyright Copyright (c) 2022 Ivan Sein <ivan@nextcloud.com>
|
||||
*
|
||||
* @author Ivan Sein <ivan@nextcloud.com>
|
||||
*
|
||||
* @license GNU GPL version 3 or any later version
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#import "NCChatReaction.h"
|
||||
|
||||
@implementation NCChatReaction
|
||||
|
||||
+ (instancetype)initWithReaction:(NSString *)reaction andCount:(NSInteger)count
|
||||
{
|
||||
NCChatReaction *reactionObject = [[NCChatReaction alloc] init];
|
||||
reactionObject.reaction = reaction;
|
||||
reactionObject.count = count;
|
||||
return reactionObject;
|
||||
}
|
||||
|
||||
@end
|
|
@ -3041,7 +3041,9 @@ NSString * const NCChatViewControllerTalkToUserNotification = @"NCChatViewContro
|
|||
return separatorCell;
|
||||
}
|
||||
if (message.isSystemMessage) {
|
||||
if ([message.systemMessage isEqualToString:@"message_deleted"] || [message.systemMessage isEqualToString:@"reaction"]) {
|
||||
if ([message.systemMessage isEqualToString:@"message_deleted"] ||
|
||||
[message.systemMessage isEqualToString:@"reaction"] ||
|
||||
[message.systemMessage isEqualToString:@"reaction_revoked"]) {
|
||||
return (SystemMessageTableViewCell *)[self.tableView dequeueReusableCellWithIdentifier:InvisibleSystemMessageCellIdentifier];
|
||||
}
|
||||
SystemMessageTableViewCell *systemCell = (SystemMessageTableViewCell *)[self.tableView dequeueReusableCellWithIdentifier:SystemMessageCellIdentifier];
|
||||
|
@ -3129,8 +3131,11 @@ NSString * const NCChatViewControllerTalkToUserNotification = @"NCChatViewContro
|
|||
return kMessageSeparatorCellHeight;
|
||||
}
|
||||
|
||||
// Message deleted (the ones that notify about a deleted message, they should not be displayed)
|
||||
if (message.message.length == 0 || [message.systemMessage isEqualToString:@"message_deleted"] || [message.systemMessage isEqualToString:@"reaction"]) {
|
||||
// Update messages (the ones that notify about an update in one message, they should not be displayed)
|
||||
if (message.message.length == 0 ||
|
||||
[message.systemMessage isEqualToString:@"message_deleted"] ||
|
||||
[message.systemMessage isEqualToString:@"reaction"] ||
|
||||
[message.systemMessage isEqualToString:@"reaction_revoked"]) {
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
|
@ -3146,6 +3151,10 @@ NSString * const NCChatViewControllerTalkToUserNotification = @"NCChatViewContro
|
|||
height = kChatMessageCellMinimumHeight;
|
||||
}
|
||||
|
||||
if (message.reactionsArray.count > 0) {
|
||||
height += 40; // reactionsView(40)
|
||||
}
|
||||
|
||||
if (message.parent) {
|
||||
height += 55; // left(5) + quoteView(50)
|
||||
return height;
|
||||
|
@ -3157,6 +3166,10 @@ NSString * const NCChatViewControllerTalkToUserNotification = @"NCChatViewContro
|
|||
if (height < kGroupedChatMessageCellMinimumHeight) {
|
||||
height = kGroupedChatMessageCellMinimumHeight;
|
||||
}
|
||||
|
||||
if (message.reactionsArray.count > 0) {
|
||||
height += 40; // reactionsView(40)
|
||||
}
|
||||
}
|
||||
|
||||
// Voice message should be before message.file check since it contains a file
|
||||
|
|
|
@ -0,0 +1,81 @@
|
|||
/**
|
||||
* @copyright Copyright (c) 2022 Ivan Sein <ivan@nextcloud.com>
|
||||
*
|
||||
* @author Ivan Sein <ivan@nextcloud.com>
|
||||
*
|
||||
* @license GNU GPL version 3 or any later version
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
import UIKit
|
||||
|
||||
@objcMembers class ReactionsView: UICollectionView, UICollectionViewDataSource, UICollectionViewDelegateFlowLayout {
|
||||
|
||||
var reactions: [NCChatReaction] = []
|
||||
|
||||
required init?(coder aDecoder: NSCoder) {
|
||||
super.init(coder: aDecoder)
|
||||
self.dataSource = self
|
||||
self.delegate = self
|
||||
}
|
||||
|
||||
required override init(frame: CGRect, collectionViewLayout layout: UICollectionViewLayout) {
|
||||
super.init(frame: frame, collectionViewLayout: layout)
|
||||
self.dataSource = self
|
||||
self.delegate = self
|
||||
self.register(UINib(nibName: "ReactionsViewCell", bundle: .main), forCellWithReuseIdentifier: "ReactionCellIdentifier")
|
||||
self.backgroundColor = .clear
|
||||
self.showsHorizontalScrollIndicator = false
|
||||
}
|
||||
|
||||
func updateReactions(reactions: [NCChatReaction]) {
|
||||
self.reactions = reactions
|
||||
self.reloadData()
|
||||
}
|
||||
|
||||
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
|
||||
return reactions.count
|
||||
}
|
||||
|
||||
func collectionView(_ collectionView: UICollectionView, numberOfSections section: Int) -> Int {
|
||||
return 1
|
||||
}
|
||||
|
||||
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumInteritemSpacingForSectionAt section: Int) -> CGFloat {
|
||||
return 2
|
||||
}
|
||||
|
||||
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
|
||||
return CGSize(width: 50, height: 30)
|
||||
}
|
||||
|
||||
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
|
||||
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "ReactionCellIdentifier", for: indexPath) as? ReactionsViewCell
|
||||
if indexPath.row < reactions.count {
|
||||
cell?.setReaction(reaction: reactions[indexPath.row])
|
||||
}
|
||||
return cell ?? UICollectionViewCell()
|
||||
}
|
||||
|
||||
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
|
||||
// TODO: Set reaction
|
||||
}
|
||||
|
||||
func neededHeight() -> CGFloat {
|
||||
return self.collectionViewLayout.collectionViewContentSize.height
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,47 @@
|
|||
/**
|
||||
* @copyright Copyright (c) 2022 Ivan Sein <ivan@nextcloud.com>
|
||||
*
|
||||
* @author Ivan Sein <ivan@nextcloud.com>
|
||||
*
|
||||
* @license GNU GPL version 3 or any later version
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
import UIKit
|
||||
|
||||
@objcMembers class ReactionsViewCell: UICollectionViewCell {
|
||||
|
||||
@IBOutlet weak var label: UILabel!
|
||||
|
||||
override func awakeFromNib() {
|
||||
super.awakeFromNib()
|
||||
label.layer.borderWidth = 1.0
|
||||
label.layer.borderColor = NCAppBranding.elementColor().cgColor
|
||||
label.layer.cornerRadius = 15.0
|
||||
label.clipsToBounds = true
|
||||
label.backgroundColor = NCAppBranding.backgroundColor()
|
||||
}
|
||||
|
||||
override func prepareForReuse() {
|
||||
super.prepareForReuse()
|
||||
label.text = ""
|
||||
}
|
||||
|
||||
func setReaction(reaction: NCChatReaction) {
|
||||
label.text = reaction.reaction + " " + String(reaction.count)
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,37 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="19529" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES">
|
||||
<device id="retina6_1" orientation="portrait" appearance="light"/>
|
||||
<dependencies>
|
||||
<deployment identifier="iOS"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="19519"/>
|
||||
<capability name="Safe area layout guides" minToolsVersion="9.0"/>
|
||||
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
|
||||
</dependencies>
|
||||
<objects>
|
||||
<placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner"/>
|
||||
<placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/>
|
||||
<collectionViewCell opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" id="gTV-IL-0wX" customClass="ReactionsViewCell" customModule="NextcloudTalk" customModuleProvider="target">
|
||||
<rect key="frame" x="0.0" y="0.0" width="50" height="30"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<view key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center">
|
||||
<rect key="frame" x="0.0" y="0.0" width="50" height="30"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
||||
<subviews>
|
||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" fixedFrame="YES" text="👍999" textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="1w7-iO-0oY">
|
||||
<rect key="frame" x="0.0" y="0.0" width="50" height="30"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
||||
<fontDescription key="fontDescription" type="system" pointSize="13"/>
|
||||
<nil key="textColor"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
</subviews>
|
||||
</view>
|
||||
<viewLayoutGuide key="safeArea" id="ZTg-uK-7eu"/>
|
||||
<size key="customSize" width="66" height="50"/>
|
||||
<connections>
|
||||
<outlet property="label" destination="1w7-iO-0oY" id="QBG-3F-rJ4"/>
|
||||
</connections>
|
||||
<point key="canvasLocation" x="149.27536231884059" y="71.651785714285708"/>
|
||||
</collectionViewCell>
|
||||
</objects>
|
||||
</document>
|
Загрузка…
Ссылка в новой задаче