diff --git a/iOS/TUIKit/TIMCommon/BaseCell/TUIMessageCell.m b/iOS/TUIKit/TIMCommon/BaseCell/TUIMessageCell.m index bf5044a35..96e2bf4cd 100644 --- a/iOS/TUIKit/TIMCommon/BaseCell/TUIMessageCell.m +++ b/iOS/TUIKit/TIMCommon/BaseCell/TUIMessageCell.m @@ -108,41 +108,86 @@ self.selectionStyle = UITableViewCellSelectionStyleNone; self.backgroundColor = UIColor.clearColor; self.contentView.backgroundColor = UIColor.clearColor; + + [self makeConstraints]; } -- (void)layoutSubviews { - [super layoutSubviews]; +- (void)makeConstraints { + + [self.nameLabel mas_makeConstraints:^(MASConstraintMaker *make) { + make.leading.mas_equalTo(_container.mas_leading).mas_offset(7); + make.top.mas_equalTo(self.avatarView.mas_top); + make.width.mas_equalTo(1); + make.height.mas_equalTo(20); + }]; + + [self.selectedIcon mas_makeConstraints:^(MASConstraintMaker *make) { + make.leading.mas_equalTo(self.contentView.mas_leading).mas_offset(3); + make.top.mas_equalTo(self.avatarView.mas_centerY).mas_offset(-10); + make.width.mas_equalTo(20); + make.height.mas_equalTo(20); + }]; - if (self.messageData.showName) { - _nameLabel.mm_sizeToFitThan(1, 20); - _nameLabel.hidden = NO; - } else { - _nameLabel.hidden = YES; - _nameLabel.mm_height(0); - } + [self.timeLabel mas_makeConstraints:^(MASConstraintMaker *make) { + make.trailing.mas_equalTo(self.contentView.mas_trailing).mas_offset(-10); + make.top.mas_equalTo(self.avatarView); + make.width.mas_greaterThanOrEqualTo(10); + make.height.mas_equalTo(10); + }]; + + [self.selectedView mas_makeConstraints:^(MASConstraintMaker *make) { + make.edges.mas_equalTo(self.contentView); + }]; - if (self.messageData.showCheckBox) { - _selectedIcon.frame = CGRectMake(10, _avatarView.mm_centerY - 10, 20, 20); - _selectedIcon.hidden = NO; - _selectedView.hidden = NO; - } else { - _selectedIcon.frame = CGRectZero; - _selectedIcon.hidden = YES; - _selectedView.hidden = YES; - } +} - if (self.messageData.showMessageTime) { - _timeLabel.mm_y = self.avatarView.mm_y; - _timeLabel.mm_x = self.contentView.bounds.size.width - 10 - _timeLabel.mm_w; - } else { - _timeLabel.mm_y = 0; - _timeLabel.mm_r = 0; - } ++ (BOOL)requiresConstraintBasedLayout { + return YES; +} + +// this is Apple's recommended place for adding/updating constraints +- (void)updateConstraints { + TUIMessageCellLayout *cellLayout = self.messageData.cellLayout; + BOOL isInComing = (self.messageData.direction == MsgDirectionIncoming); + + [self.nameLabel mas_remakeConstraints:^(MASConstraintMaker *make) { + if (isInComing) { + make.leading.mas_equalTo(_container.mas_leading).mas_offset(7); + make.trailing.mas_equalTo(self.contentView).mas_offset(-7); + } else { + make.leading.mas_equalTo(self.contentView).mas_offset(7); + make.trailing.mas_equalTo(self.container.mas_trailing); + } + if (self.messageData.showName) { + make.width.mas_greaterThanOrEqualTo(20); + make.height.mas_greaterThanOrEqualTo(20); + } else { + make.height.mas_equalTo(0); + } + make.top.mas_equalTo(self.avatarView.mas_top); + }]; + + [self.selectedIcon mas_updateConstraints:^(MASConstraintMaker *make) { + if (self.messageData.showCheckBox) { + make.width.mas_equalTo(20); + make.height.mas_equalTo(20); + } else { + make.size.mas_equalTo(CGSizeZero); + } + }]; + + [self.timeLabel sizeToFit]; + [self.timeLabel mas_updateConstraints:^(MASConstraintMaker *make) { + if (self.messageData.showMessageTime) { + make.width.mas_equalTo(self.timeLabel.frame.size.width); + make.height.mas_equalTo(self.timeLabel.frame.size.height); + } else { + make.width.mas_equalTo(0); + make.height.mas_equalTo(0); + } + }]; CGSize csize = [self.class getContentSize:self.messageData]; - - _selectedView.frame = self.contentView.bounds; - CGFloat contentWidth = csize.width; CGFloat contentHeight = csize.height; @@ -159,73 +204,97 @@ contentWidth = MIN(contentWidth, Screen_Width * 0.25 * 3); contentHeight = csize.height + self.messageData.messageModifyReactsSize.height; } - - TUIMessageCellLayout *cellLayout = self.messageData.cellLayout; if (self.messageData.direction == MsgDirectionIncoming) { self.avatarView.hidden = !self.messageData.showAvatar; - self.avatarView.frame = CGRectMake(_selectedIcon.mm_maxX + cellLayout.avatarInsets.left, cellLayout.avatarInsets.top, cellLayout.avatarSize.width, - cellLayout.avatarSize.height); + [self.avatarView mas_remakeConstraints:^(MASConstraintMaker *make) { + if (self.messageData.showCheckBox) { + make.leading.mas_equalTo(self.selectedIcon.mas_trailing).mas_offset(cellLayout.avatarInsets.left); + } else { + make.leading.mas_equalTo(self.contentView.mas_leading).mas_offset(cellLayout.avatarInsets.left); + } + make.top.mas_equalTo(cellLayout.avatarInsets.top); + make.size.mas_equalTo(cellLayout.avatarSize); + }]; - CGFloat ctop = cellLayout.messageInsets.top + _nameLabel.mm_h; - self.container.frame = CGRectMake(cellLayout.messageInsets.left + self.avatarView.mm_maxX, ctop, contentWidth, contentHeight); - - CGRect nameLabelFrame = self.nameLabel.frame; - nameLabelFrame.origin = CGPointMake(_container.mm_x + 7, self.avatarView.mm_y); - self.nameLabel.frame = nameLabelFrame; + [self.container mas_remakeConstraints:^(MASConstraintMaker *make) { + make.leading.mas_equalTo(self.avatarView.mas_trailing).mas_offset(cellLayout.messageInsets.left); + make.top.mas_equalTo(self.nameLabel.mas_bottom).mas_offset(cellLayout.messageInsets.top); + make.width.mas_equalTo(contentWidth); + make.height.mas_equalTo(contentHeight); + }]; CGRect indicatorFrame = self.indicator.frame; - indicatorFrame.origin = CGPointMake(_container.mm_maxX + 8, _container.mm_centerY - 0.5 * self.indicator.mm_h); - self.indicator.frame = indicatorFrame; - if (!self.retryView.isHidden) { - self.retryView.frame = indicatorFrame; - } - + [self.indicator mas_remakeConstraints:^(MASConstraintMaker *make) { + make.leading.mas_equalTo(self.container.mas_trailing).mas_offset(8); + make.centerY.mas_equalTo(self.container.mas_centerY); + make.size.mas_equalTo(indicatorFrame.size); + }]; + self.retryView.frame = self.indicator.frame; self.readReceiptLabel.hidden = YES; - } else { if (self.messageData.showAvatar) { cellLayout.avatarSize = CGSizeMake(40, 40); } else { cellLayout.avatarSize = CGSizeZero; } - self.avatarView.mm_w = cellLayout.avatarSize.width; - self.avatarView.mm_h = cellLayout.avatarSize.height; - self.avatarView.mm_top(cellLayout.avatarInsets.top).mm_right(cellLayout.avatarInsets.right); + [self.avatarView mas_remakeConstraints:^(MASConstraintMaker *make) { + make.trailing.mas_equalTo(self.contentView.mas_trailing).mas_offset(-cellLayout.avatarInsets.right); + make.top.mas_equalTo(cellLayout.avatarInsets.top); + make.size.mas_equalTo(cellLayout.avatarSize); + }]; + [self.container mas_remakeConstraints:^(MASConstraintMaker *make) { + make.trailing.mas_equalTo(self.avatarView.mas_leading).mas_offset(-cellLayout.messageInsets.right); + make.top.mas_equalTo(self.nameLabel.mas_bottom).mas_offset(cellLayout.messageInsets.top); + make.width.mas_equalTo(contentWidth); + make.height.mas_equalTo(contentHeight); + }]; - self.nameLabel.mm_top(self.avatarView.mm_y); + CGRect indicatorFrame = self.indicator.frame; + [self.indicator mas_remakeConstraints:^(MASConstraintMaker *make) { + make.trailing.mas_equalTo(self.container.mas_leading).mas_offset(-8); + make.centerY.mas_equalTo(self.container.mas_centerY); + make.size.mas_equalTo(indicatorFrame.size); + }]; - CGFloat ctop = cellLayout.messageInsets.top + _nameLabel.mm_h; - - self.container.mm_width(contentWidth) - .mm_height(contentHeight) - .mm_right(cellLayout.messageInsets.right + self.contentView.mm_w - self.avatarView.mm_x) - .mm_top(ctop); - - self.nameLabel.mm_right(_container.mm_r); - self.indicator.mm_sizeToFit().mm__centerY(_container.mm_centerY).mm_left(_container.mm_x - 8 - _indicator.mm_w); self.retryView.frame = self.indicator.frame; - self.readReceiptLabel.mm_sizeToFit().mm_bottom(self.container.mm_b).mm_left(_container.mm_x - 8 - _readReceiptLabel.mm_w); + [self.readReceiptLabel sizeToFit]; + [self.readReceiptLabel mas_remakeConstraints:^(MASConstraintMaker *make) { + make.bottom.mas_equalTo(self.container.mas_bottom); + make.trailing.mas_equalTo(self.container.mas_leading).mas_offset(-8); + make.size.mas_equalTo(self.readReceiptLabel.frame.size); + }]; } if (!self.messageModifyRepliesButton.isHidden) { self.messageModifyRepliesButton.mm_sizeToFit(); - CGFloat repliesBtnX = 0; CGFloat repliesBtnTextWidth = self.messageModifyRepliesButton.frame.size.width; - CGFloat repliesBtnPadding = 10; - CGFloat repliesBtnWidth = repliesBtnTextWidth + repliesBtnPadding; - if (self.messageData.direction == MsgDirectionIncoming) { - repliesBtnX = _container.mm_x; - } else { - repliesBtnX = CGRectGetMaxX(_container.frame) - repliesBtnWidth; - } - self.messageModifyRepliesButton.frame = CGRectMake(repliesBtnX, CGRectGetMaxY(_container.frame), repliesBtnWidth, 30); + [self.messageModifyRepliesButton mas_remakeConstraints:^(MASConstraintMaker *make) { + if (isInComing) { + make.leading.mas_equalTo(self.container.mas_leading); + } else { + make.trailing.mas_equalTo(self.container.mas_trailing); + } + make.top.mas_equalTo(self.container.mas_bottom); + make.size.mas_equalTo(CGSizeMake(repliesBtnTextWidth + 10, 30)); + }]; } if (self.tagView) { + [self.tagView updateView]; self.tagView.frame = CGRectMake(0, _container.frame.size.height - self.messageData.messageModifyReactsSize.height, contentWidth, self.messageData.messageModifyReactsSize.height); + if (isRTL() && self.tagView.frame.size.width>0 ) { + [self.tagView updateRTLView]; + } } + + // according to apple super should be called at end of method + [super updateConstraints]; +} + +- (void)layoutSubviews { + [super layoutSubviews]; } - (void)setupRAC { @@ -262,6 +331,20 @@ [self loadAvatar:data]; + if (self.messageData.showName) { + _nameLabel.hidden = NO; + } else { + _nameLabel.hidden = YES; + } + + if (self.messageData.showCheckBox) { + _selectedIcon.hidden = NO; + _selectedView.hidden = NO; + } else { + _selectedIcon.hidden = YES; + _selectedView.hidden = YES; + } + if ([TUIConfig defaultConfig].avatarType == TAvatarTypeRounded) { self.avatarView.layer.masksToBounds = YES; self.avatarView.layer.cornerRadius = data.cellLayout.avatarSize.height / 2; @@ -339,6 +422,15 @@ dispatch_async(dispatch_get_main_queue(), ^{ [weakSelf highlightWhenMatchKeyword:data.highlightKeyword]; }); + + // tell constraints they need updating + [self setNeedsUpdateConstraints]; + + // update constraints now so we can animate the change + [self updateConstraintsIfNeeded]; + + [self layoutIfNeeded]; + } - (void)loadAvatar:(TUIMessageCellData *)data { @@ -357,7 +449,7 @@ userId = V2TIMManager.sharedInstance.getLoginUser; } - [V2TIMManager.sharedInstance getUsersInfo:@[ userId ] + [V2TIMManager.sharedInstance getUsersInfo:@[ userId?:@"" ] succ:^(NSArray *infoList) { @strongify(self); V2TIMUserFullInfo *info = infoList.firstObject; @@ -419,7 +511,13 @@ NSString *text = isPeerRead ? TIMCommonLocalizableString(TUIKitMessageReadC2CRead) : TIMCommonLocalizableString(TUIKitMessageReadC2CUnRead); self.readReceiptLabel.text = text; } - self.readReceiptLabel.mm_sizeToFit().mm_bottom(self.container.mm_b).mm_left(_container.mm_x - 8 - _readReceiptLabel.mm_w); + + [self.readReceiptLabel sizeToFit]; + [self.readReceiptLabel mas_remakeConstraints:^(MASConstraintMaker *make) { + make.bottom.mas_equalTo(self.container.mas_bottom); + make.trailing.mas_equalTo(self.container.mas_leading).mas_offset(-8); + make.size.mas_equalTo(self.readReceiptLabel.frame.size); + }]; self.readReceiptLabel.textColor = [self shouldHighlightReadReceiptLabel] ? TIMCommonDynamicColor(@"chat_message_read_status_text_color", @"#147AFF") : TIMCommonDynamicColor(@"chat_message_read_status_text_gray_color", @"#BBBBBB"); } @@ -533,7 +631,6 @@ - (void)prepareReactTagUI:(UIView *)containerView { TUITagsView *tagView = [[TUITagsView alloc] init]; - tagView.backgroundColor = [UIColor clearColor]; [containerView addSubview:tagView]; self.tagView = tagView; __weak typeof(self) weakSelf = self; diff --git a/iOS/TUIKit/TIMCommon/BaseCell/TUISystemMessageCell.m b/iOS/TUIKit/TIMCommon/BaseCell/TUISystemMessageCell.m index 0bb68d4a2..26ec152a8 100644 --- a/iOS/TUIKit/TIMCommon/BaseCell/TUISystemMessageCell.m +++ b/iOS/TUIKit/TIMCommon/BaseCell/TUISystemMessageCell.m @@ -24,7 +24,7 @@ _messageLabel.font = [UIFont systemFontOfSize:13]; _messageLabel.textColor = [UIColor d_systemGrayColor]; _messageLabel.textAlignment = NSTextAlignmentCenter; - _messageLabel.numberOfLines = 0; + _messageLabel.numberOfLines = 1; _messageLabel.backgroundColor = [UIColor clearColor]; _messageLabel.layer.cornerRadius = 3; [_messageLabel.layer setMasksToBounds:YES]; @@ -35,6 +35,27 @@ return self; } ++ (BOOL)requiresConstraintBasedLayout { + return YES; +} + +// this is Apple's recommended place for adding/updating constraints +- (void)updateConstraints { + [super updateConstraints]; + + [self.container mas_remakeConstraints:^(MASConstraintMaker *make) { + make.center.mas_equalTo(self.contentView); + make.size.mas_equalTo(self.contentView); + }]; + [self.messageLabel sizeToFit]; + if(self.messageLabel.superview) { + [self.messageLabel mas_remakeConstraints:^(MASConstraintMaker *make) { + make.center.mas_equalTo(self.container); + make.size.mas_equalTo(self.messageLabel.frame.size); + }]; + } +} + - (void)fillWithData:(TUISystemMessageCellData *)data; { [super fillWithData:data]; @@ -44,12 +65,17 @@ self.avatarView.hidden = YES; self.retryView.hidden = YES; [self.indicator stopAnimating]; + // tell constraints they need updating + [self setNeedsUpdateConstraints]; + + // update constraints now so we can animate the change + [self updateConstraintsIfNeeded]; + + [self layoutIfNeeded]; } - (void)layoutSubviews { [super layoutSubviews]; - self.container.center = self.contentView.center; - self.messageLabel.frame = self.container.bounds; } diff --git a/iOS/TUIKit/TIMCommon/BaseCell/TUITagsCell.m b/iOS/TUIKit/TIMCommon/BaseCell/TUITagsCell.m index 6cc78de48..ff9b43dc2 100644 --- a/iOS/TUIKit/TIMCommon/BaseCell/TUITagsCell.m +++ b/iOS/TUIKit/TIMCommon/BaseCell/TUITagsCell.m @@ -100,6 +100,15 @@ allWidth += rightMargin; allWidth += 8; self.ItemWidth = allWidth; + +} +- (void)layoutSubviews { + [super layoutSubviews]; + + for (UIView *subView in self.subviews) { + [subView resetFrameToFitRTL]; + } + } - (void)emojiBtnClick { diff --git a/iOS/TUIKit/TIMCommon/BaseCell/TUITagsView.h b/iOS/TUIKit/TIMCommon/BaseCell/TUITagsView.h index 2005652d8..1cb04e490 100644 --- a/iOS/TUIKit/TIMCommon/BaseCell/TUITagsView.h +++ b/iOS/TUIKit/TIMCommon/BaseCell/TUITagsView.h @@ -13,8 +13,6 @@ NS_ASSUME_NONNULL_BEGIN @interface TUITagsView : UIView -/// collectionView -@property(nonatomic, strong) UIView *containerView; /// datasource @property(nonatomic, strong) NSMutableArray *listArrM; @@ -30,5 +28,6 @@ NS_ASSUME_NONNULL_BEGIN - (void)updateView; +- (void)updateRTLView; @end NS_ASSUME_NONNULL_END diff --git a/iOS/TUIKit/TIMCommon/BaseCell/TUITagsView.m b/iOS/TUIKit/TIMCommon/BaseCell/TUITagsView.m index 1893f00c8..cc47eb88f 100644 --- a/iOS/TUIKit/TIMCommon/BaseCell/TUITagsView.m +++ b/iOS/TUIKit/TIMCommon/BaseCell/TUITagsView.m @@ -134,4 +134,12 @@ self.frame = CGRectMake(self.frame.origin.x, self.frame.origin.y, tagViewWidth, tagViewHeight); } +- (void)updateRTLView { + for (UIView *subView in self.subviews) { + if (subView) { + [subView resetFrameToFitRTL]; + } + } +} + @end diff --git a/iOS/TUIKit/TIMCommon/BaseCellData/NSString+TUIEmoji.m b/iOS/TUIKit/TIMCommon/BaseCellData/NSString+TUIEmoji.m index 1be81b086..4dcedbb5a 100644 --- a/iOS/TUIKit/TIMCommon/BaseCellData/NSString+TUIEmoji.m +++ b/iOS/TUIKit/TIMCommon/BaseCellData/NSString+TUIEmoji.m @@ -11,9 +11,15 @@ @implementation NSString (TUIEmoji) ++ (NSString *)getRegex_emoji { + + NSString *regex_emoji = @"\\[[a-zA-Z0-9\\/\\u4e00-\\u9fa5]+\\]"; // match emoji + + return regex_emoji; +} - (NSString *)getLocalizableStringWithFaceContent { NSString *content = self; - NSString *regex_emoji = @"\\[[a-zA-Z0-9\\/\\u4e00-\\u9fa5]+\\]"; // match emoji + NSString *regex_emoji = [self.class getRegex_emoji]; // match emoji NSError *error = nil; NSRegularExpression *re = [NSRegularExpression regularExpressionWithPattern:regex_emoji options:NSRegularExpressionCaseInsensitive error:&error]; if (re) { @@ -49,7 +55,7 @@ - (NSString *)getInternationalStringWithfaceContent { NSString *content = self; - NSString *regex_emoji = @"\\[[a-z\\s*A-Z\\s*0-9!-@\\/\\u4e00-\\u9fa5]+\\]"; // match emoji + NSString *regex_emoji = [self.class getRegex_emoji]; NSError *error = nil; NSRegularExpression *re = [NSRegularExpression regularExpressionWithPattern:regex_emoji options:NSRegularExpressionCaseInsensitive error:&error]; if (re) { @@ -111,7 +117,7 @@ NSError *error = nil; static NSRegularExpression *re = nil; if (re == nil) { - NSString *regex_emoji = @"\\[[a-zA-Z0-9\\/\\u4e00-\\u9fa5]+\\]"; // match emoji + NSString *regex_emoji = [self.class getRegex_emoji]; re = [NSRegularExpression regularExpressionWithPattern:regex_emoji options:NSRegularExpressionCaseInsensitive error:&error]; } if (!re) { @@ -270,7 +276,7 @@ return attributeString; } - NSString *regex_emoji = @"\\[[a-zA-Z0-9\\/\\u4e00-\\u9fa5]+\\]"; // match emoji + NSString *regex_emoji = [self.class getRegex_emoji]; NSError *error = nil; NSRegularExpression *re = [NSRegularExpression regularExpressionWithPattern:regex_emoji options:NSRegularExpressionCaseInsensitive error:&error]; @@ -295,10 +301,8 @@ TUIEmojiTextAttachment *emojiTextAttachment = [[TUIEmojiTextAttachment alloc] init]; emojiTextAttachment.faceCellData = face; - NSString *localizableFaceName = face.localizableName.length ? face.localizableName : face.name; - // Set tag and image - emojiTextAttachment.emojiTag = localizableFaceName; + emojiTextAttachment.emojiTag = face.name; emojiTextAttachment.image = [[TUIImageCache sharedInstance] getFaceFromCache:face.path]; // Set emoji size @@ -505,7 +509,7 @@ NSMutableArray *result = [NSMutableArray new]; /// TUIKit qq emoji. - NSString *regexOfCustomEmoji = @"\\[[a-zA-Z0-9\\/\\u4e00-\\u9fa5]+\\]"; + NSString *regexOfCustomEmoji = [self.class getRegex_emoji]; NSError *error = nil; NSRegularExpression *re = [NSRegularExpression regularExpressionWithPattern:regexOfCustomEmoji options:NSRegularExpressionCaseInsensitive error:&error]; if (error) { diff --git a/iOS/TUIKit/TIMCommon/CommonModel/TIMCommonModel.m b/iOS/TUIKit/TIMCommon/CommonModel/TIMCommonModel.m index 720700f57..b1a3c2f3e 100644 --- a/iOS/TUIKit/TIMCommon/CommonModel/TIMCommonModel.m +++ b/iOS/TUIKit/TIMCommon/CommonModel/TIMCommonModel.m @@ -173,6 +173,11 @@ self.title.frame = CGRectMake(_image.frame.origin.x + _image.frame.size.width + TUIPopCell_Margin, TUIPopCell_Padding, titleWidth, self.contentView.bounds.size.height); self.title.center = CGPointMake(self.title.center.x, self.contentView.center.y); + + if (isRTL()) { + [self.image resetFrameToFitRTL]; + [self.title resetFrameToFitRTL]; + } } - (void)setData:(TUIPopCellData *)data { @@ -253,6 +258,7 @@ CGFloat contentY = CGRectGetMaxY(_hLine.frame) + 17; CGFloat contentheight = 40; _content = [[UITextField alloc] initWithFrame:CGRectMake(contentMargin, contentY, contentWidth, contentheight)]; + _content.textAlignment = isRTL()?NSTextAlignmentRight:NSTextAlignmentLeft; _content.delegate = self; _content.backgroundColor = TUIGroupDynamicColor(@"group_modify_input_bg_color", @"#F5F5F5"); _content.textColor = TUIGroupDynamicColor(@"group_modify_input_text_color", @"#000000"); @@ -579,39 +585,22 @@ self.backgroundColor = TIMCommonDynamicColor(@"form_bg_color", @"#FFFFFF"); self.contentView.backgroundColor = TIMCommonDynamicColor(@"form_bg_color", @"#FFFFFF"); - _keyLabel = self.textLabel; + _keyLabel = [[UILabel alloc] init]; _keyLabel.textColor = TIMCommonDynamicColor(@"form_key_text_color", @"#444444"); _keyLabel.font = [UIFont systemFontOfSize:16.0]; - - _valueLabel = self.detailTextLabel; + [self.contentView addSubview:_keyLabel]; + [_keyLabel setRtlAlignment:TUITextRTLAlignmentTrailing]; + + _valueLabel = [[UILabel alloc] init]; + [self.contentView addSubview:_valueLabel]; _valueLabel.textColor = TIMCommonDynamicColor(@"form_value_text_color", @"#000000"); _valueLabel.font = [UIFont systemFontOfSize:16.0]; - + [_valueLabel setRtlAlignment:TUITextRTLAlignmentTrailing]; self.selectionStyle = UITableViewCellSelectionStyleNone; } return self; } -- (void)layoutSubviews { - [super layoutSubviews]; - - if (self.textData.keyEdgeInsets.left) { - self.keyLabel.mm_left(self.textData.keyEdgeInsets.left); - } - - if (self.textData.keyEdgeInsets.top) { - self.keyLabel.mm_top(self.textData.keyEdgeInsets.top); - } - - if (self.textData.keyEdgeInsets.bottom) { - self.keyLabel.mm_bottom(self.textData.keyEdgeInsets.bottom); - } - - if (self.textData.keyEdgeInsets.right) { - self.keyLabel.mm_right(self.textData.keyEdgeInsets.right); - } -} - - (void)fillWithData:(TUICommonTextCellData *)textData { [super fillWithData:textData]; @@ -638,6 +627,41 @@ } else { self.valueLabel.numberOfLines = 1; } + // tell constraints they need updating + [self setNeedsUpdateConstraints]; + + // update constraints now so we can animate the change + [self updateConstraintsIfNeeded]; + + [self layoutIfNeeded]; +} + ++ (BOOL)requiresConstraintBasedLayout { + return YES; +} + +// this is Apple's recommended place for adding/updating constraints +- (void)updateConstraints { + [super updateConstraints]; + + [self.keyLabel sizeToFit]; + [self.keyLabel mas_remakeConstraints:^(MASConstraintMaker *make) { + make.size.mas_equalTo(self.keyLabel.frame.size); + make.leading.mas_equalTo(self.contentView).mas_offset(self.textData.keyEdgeInsets.left); + make.centerY.mas_equalTo(self.contentView); + }]; + + [self.valueLabel sizeToFit]; + [self.valueLabel mas_remakeConstraints:^(MASConstraintMaker *make) { + make.leading.mas_equalTo(self.keyLabel.mas_trailing).mas_offset(10); + if (self.textData.showAccessory) { + make.trailing.mas_equalTo(self.contentView.mas_trailing).mas_offset(-10); + } + else { + make.trailing.mas_equalTo(self.contentView.mas_trailing).mas_offset(-20); + } + make.centerY.mas_equalTo(self.contentView); + }]; } @end @@ -685,14 +709,14 @@ _titleLabel = [[UILabel alloc] init]; _titleLabel.textColor = TIMCommonDynamicColor(@"form_key_text_color", @"#444444"); _titleLabel.font = [UIFont systemFontOfSize:16]; - _titleLabel.textAlignment = NSTextAlignmentLeft; + [_titleLabel setRtlAlignment:TUITextRTLAlignmentLeading]; [self.contentView addSubview:_titleLabel]; _descLabel = [[UILabel alloc] init]; _descLabel.textColor = TIMCommonDynamicColor(@"group_modify_desc_color", @"#888888"); _descLabel.font = [UIFont systemFontOfSize:12]; _descLabel.numberOfLines = 0; - _descLabel.textAlignment = NSTextAlignmentLeft; + [_descLabel setRtlAlignment:TUITextRTLAlignmentLeading]; _descLabel.hidden = YES; [self.contentView addSubview:_descLabel]; @@ -713,7 +737,35 @@ - (void)layoutSubviews { [super layoutSubviews]; +} +- (void)fillWithData:(TUICommonSwitchCellData *)switchData { + [super fillWithData:switchData]; + + self.switchData = switchData; + _titleLabel.text = switchData.title; + [_switcher setOn:switchData.isOn]; + _descLabel.text = switchData.desc; + + // tell constraints they need updating + [self setNeedsUpdateConstraints]; + + // update constraints now so we can animate the change + [self updateConstraintsIfNeeded]; + + [self layoutIfNeeded]; + +} + ++ (BOOL)requiresConstraintBasedLayout { + return YES; +} + +// this is Apple's recommended place for adding/updating constraints +- (void)updateConstraints { + + [super updateConstraints]; + if (self.switchData.disableChecked) { _titleLabel.textColor = [UIColor grayColor]; _titleLabel.alpha = 0.4; @@ -747,23 +799,29 @@ attributes:attribute context:nil] .size; - _titleLabel.mm_width(size.width).mm_height(24).mm_left(leftMargin).mm_top(12); - _descLabel.mm_width(size.width).mm_height(size.height).mm_left(_titleLabel.mm_x).mm_top(self.titleLabel.mm_maxY + 2); + + [self.titleLabel mas_remakeConstraints:^(MASConstraintMaker *make) { + make.width.mas_equalTo(size.width); + make.height.mas_equalTo(24); + make.leading.mas_equalTo(leftMargin); + make.top.mas_equalTo(12); + }]; + [self.descLabel mas_remakeConstraints:^(MASConstraintMaker *make) { + make.width.mas_equalTo(size.width); + make.height.mas_equalTo(size.height); + make.leading.mas_equalTo(self.titleLabel.mas_leading); + make.top.mas_equalTo(self.titleLabel.mas_bottom).mas_offset(2); + }]; } else { _descLabel.text = @""; - _titleLabel.mm_sizeToFit().mm_left(leftMargin).mm__centerY(self.contentView.mm_h / 2); + [self.titleLabel sizeToFit]; + [self.titleLabel mas_remakeConstraints:^(MASConstraintMaker *make) { + make.size.mas_equalTo(self.titleLabel.frame.size); + make.leading.mas_equalTo(self.switchData.margin); + make.centerY.mas_equalTo(self.contentView); + }]; } } - -- (void)fillWithData:(TUICommonSwitchCellData *)switchData { - [super fillWithData:switchData]; - - self.switchData = switchData; - _titleLabel.text = switchData.title; - [_switcher setOn:switchData.isOn]; - _descLabel.text = switchData.desc; -} - - (void)switchClick { if (self.switchData.cswitchSelector) { UIViewController *vc = self.mm_viewController; @@ -1449,6 +1507,10 @@ NSString *kTopConversationListChangedNotification = @"kTopConversationListChange self.accessoryBtn.mm_sizeToFit().mm_height(30).mm_right(15).mm_top(13); self.collectionView.mm_left(15).mm_height(40).mm_width(self.accessoryBtn.mm_x - 30).mm__centerY(self.accessoryBtn.mm_centerY); + if (isRTL()) { + [self.accessoryBtn resetFrameToFitRTL]; + [self.collectionView resetFrameToFitRTL]; + } } @end @@ -1544,7 +1606,7 @@ NSString *kTopConversationListChangedNotification = @"kTopConversationListChange RAC(_signature, text) = [RACObserve(data, signature) takeUntil:self.rac_prepareForReuseSignal]; [[[RACObserve(data, identifier) takeUntil:self.rac_prepareForReuseSignal] distinctUntilChanged] subscribeNext:^(NSString *x) { @strongify(self); - self.identifier.text = [@"ID: " stringByAppendingString:data.identifier]; + self.identifier.text = [NSString stringWithFormat:@"%@:%@",TIMCommonLocalizableString(TUIKitIdentity),data.identifier]; }]; [[[RACObserve(data, name) takeUntil:self.rac_prepareForReuseSignal] distinctUntilChanged] subscribeNext:^(NSString *x) { @@ -1573,33 +1635,91 @@ NSString *kTopConversationListChangedNotification = @"kTopConversationListChange } else { self.accessoryType = UITableViewCellAccessoryNone; } + // tell constraints they need updating + [self setNeedsUpdateConstraints]; + + // update constraints now so we can animate the change + [self updateConstraintsIfNeeded]; + + [self layoutIfNeeded]; } - (void)layoutSubviews { [super layoutSubviews]; - CGFloat maxLabelWidth = self.contentView.mm_w - CGRectGetMaxX(_avatar.frame) - 30; - _name.mm_sizeToFitThan(0, _avatar.mm_h / 3).mm_top(_avatar.mm_y).mm_left(_avatar.mm_maxX + TPersonalCommonCell_Margin); - if (CGRectGetMaxX(_name.frame) >= self.contentView.mm_w) { - _name.mm_w = maxLabelWidth; +} + ++ (BOOL)requiresConstraintBasedLayout { + return YES; +} + +// this is Apple's recommended place for adding/updating constraints +- (void)updateConstraints { + [super updateConstraints]; + CGSize headSize = CGSizeMake(kScale390(66), kScale390(66)); + + [self.avatar mas_remakeConstraints:^(MASConstraintMaker *make) { + make.size.mas_equalTo(headSize); + make.top.mas_equalTo(kScale390(10)); + make.leading.mas_equalTo(kScale390(16)); + }]; + + if ([TUIConfig defaultConfig].avatarType == TAvatarTypeRounded) { + self.avatar.layer.masksToBounds = YES; + self.avatar.layer.cornerRadius = headSize.height / 2; + } else if ([TUIConfig defaultConfig].avatarType == TAvatarTypeRadiusCorner) { + self.avatar.layer.masksToBounds = YES; + self.avatar.layer.cornerRadius = [TUIConfig defaultConfig].avatarCornerRadius; } - _identifier.mm_sizeToFitThan(80, _avatar.mm_h / 3).mm_left(_name.mm_x); + [self.name sizeToFit]; + [self.name mas_remakeConstraints:^(MASConstraintMaker *make) { + make.top.mas_equalTo(TPersonalCommonCell_Margin); + make.leading.mas_equalTo(self.avatar.mas_trailing).mas_offset(15); + make.width.mas_lessThanOrEqualTo(self.name.frame.size.width); + make.height.mas_greaterThanOrEqualTo(self.name.frame.size.height); + make.trailing.mas_lessThanOrEqualTo(self.genderIcon.mas_leading).mas_offset(- 1); + }]; + + [self.genderIcon mas_remakeConstraints:^(MASConstraintMaker *make) { + make.width.height.mas_equalTo(self.name.font.pointSize *0.9); + make.centerY.mas_equalTo(self.name); + make.leading.mas_equalTo(self.name.mas_trailing).mas_offset(1); + make.trailing.mas_lessThanOrEqualTo(self.contentView.mas_trailing).mas_offset(- 10); + }]; + + [self.identifier sizeToFit]; + [self.identifier mas_remakeConstraints:^(MASConstraintMaker *make) { + make.leading.mas_equalTo(self.name); + make.top.mas_equalTo(self.name.mas_bottom).mas_offset(5); + if(self.identifier.frame.size.width > 80) { + make.width.mas_greaterThanOrEqualTo(self.identifier.frame.size.width); + } + else { + make.width.mas_greaterThanOrEqualTo(@80); + } + make.height.mas_greaterThanOrEqualTo(self.identifier.frame.size.height); + make.trailing.mas_lessThanOrEqualTo(self.contentView.mas_trailing).mas_offset(-1); + }]; if (self.cardData.showSignature) { - _identifier.mm_y = _name.mm_y + _name.mm_h + 5; + [self.signature sizeToFit]; + [self.signature mas_remakeConstraints:^(MASConstraintMaker *make) { + make.leading.mas_equalTo(self.name); + make.top.mas_equalTo(self.identifier.mas_bottom).mas_offset(5); + if(self.signature.frame.size.width > 80) { + make.width.mas_greaterThanOrEqualTo(self.signature.frame.size.width); + } + else { + make.width.mas_greaterThanOrEqualTo(@80); + } + make.height.mas_greaterThanOrEqualTo(self.signature.frame.size.height); + make.trailing.mas_lessThanOrEqualTo(self.contentView.mas_trailing).mas_offset(-1); + }]; + } else { - _identifier.mm_bottom(_avatar.mm_b); + self.signature.frame = CGRectZero; } - _signature.mm_sizeToFitThan(80, _avatar.mm_h / 3).mm_left(_name.mm_x); - _signature.mm_y = CGRectGetMaxY(_identifier.frame) + 5; - if (CGRectGetMaxX(_signature.frame) >= self.contentView.mm_w) { - _signature.mm_w = maxLabelWidth; - } - - _genderIcon.mm_sizeToFitThan(_name.font.pointSize * 0.9, _name.font.pointSize * 0.9) - .mm__centerY(_name.mm_centerY) - .mm_left(_name.mm_x + _name.mm_w + TPersonalCommonCell_Margin); } - (void)onTapAvatar { @@ -2164,21 +2284,21 @@ static NSString *const reuseIdentifier = @"TUISelectAvatarCollectionCell"; } else { self.accessoryType = UITableViewCellAccessoryNone; } + + // tell constraints they need updating + [self setNeedsUpdateConstraints]; + + // update constraints now so we can animate the change + [self updateConstraintsIfNeeded]; + + [self layoutIfNeeded]; + } - (void)setupViews { - CGSize headSize = TPersonalCommonCell_Image_Size; - _avatar = [[UIImageView alloc] initWithFrame:CGRectMake(TPersonalCommonCell_Margin, TPersonalCommonCell_Margin, headSize.width, headSize.height)]; + _avatar = [[UIImageView alloc] initWithFrame:CGRectZero]; _avatar.contentMode = UIViewContentModeScaleAspectFit; - if ([TUIConfig defaultConfig].avatarType == TAvatarTypeRounded) { - self.avatar.layer.masksToBounds = YES; - self.avatar.layer.cornerRadius = headSize.height / 2; - } else if ([TUIConfig defaultConfig].avatarType == TAvatarTypeRadiusCorner) { - self.avatar.layer.masksToBounds = YES; - self.avatar.layer.cornerRadius = [TUIConfig defaultConfig].avatarCornerRadius; - } - [self addSubview:_avatar]; _keyLabel = self.textLabel; @@ -2193,12 +2313,37 @@ static NSString *const reuseIdentifier = @"TUISelectAvatarCollectionCell"; self.selectionStyle = UITableViewCellSelectionStyleNone; } ++ (BOOL)requiresConstraintBasedLayout { + return YES; +} + +// this is Apple's recommended place for adding/updating constraints +- (void)updateConstraints { + [super updateConstraints]; + CGSize headSize = TPersonalCommonCell_Image_Size; + [self.avatar mas_remakeConstraints:^(MASConstraintMaker *make) { + make.size.mas_equalTo(headSize); + if (self.avatarData.showAccessory) { + make.trailing.mas_equalTo(self.contentView.mas_trailing).mas_offset(-10); + } + else { + make.trailing.mas_equalTo(self.contentView.mas_trailing).mas_offset(-20); + } + make.centerY.mas_equalTo(self); + }]; + + if ([TUIConfig defaultConfig].avatarType == TAvatarTypeRounded) { + self.avatar.layer.masksToBounds = YES; + self.avatar.layer.cornerRadius = headSize.height / 2; + } else if ([TUIConfig defaultConfig].avatarType == TAvatarTypeRadiusCorner) { + self.avatar.layer.masksToBounds = YES; + self.avatar.layer.cornerRadius = [TUIConfig defaultConfig].avatarCornerRadius; + } +} - (void)layoutSubviews { [super layoutSubviews]; - //_avatar.mm_top(self.mm_maxY - TPersonalCommonCell_Margin).mm_left(self.mm_maxX - 100); - CGFloat margin = self.avatarData.showAccessory ? 20 : 0; - _avatar.mm_left(self.mm_maxX - 16 - TPersonalCommonCell_Image_Size.width - margin); + } @end diff --git a/iOS/TUIKit/TIMCommon/CommonModel/TIMDefine.h b/iOS/TUIKit/TIMCommon/CommonModel/TIMDefine.h index 4f632bb65..0604cbb2f 100644 --- a/iOS/TUIKit/TIMCommon/CommonModel/TIMDefine.h +++ b/iOS/TUIKit/TIMCommon/CommonModel/TIMDefine.h @@ -11,8 +11,10 @@ #import #import +#import #import "TIMConfig.h" #import "TIMCommonModel.h" +#import "TIMRTLUtil.h" #define kEnableAllRotationOrientationNotification @"kEnableAllRotationOrientationNotification" #define kDisableAllRotationOrientationNotification @"kDisableAllRotationOrientationNotification" diff --git a/iOS/TUIKit/TIMCommon/CommonModel/TIMRTLUtil.h b/iOS/TUIKit/TIMCommon/CommonModel/TIMRTLUtil.h new file mode 100644 index 000000000..790fc2de5 --- /dev/null +++ b/iOS/TUIKit/TIMCommon/CommonModel/TIMRTLUtil.h @@ -0,0 +1,51 @@ +// +// TIMRTLUtil.h +// TIMCommon +// +// Created by cologne on 2023/7/21. +// Copyright © 2023 Tencent. All rights reserved +// + +#import + +NS_ASSUME_NONNULL_BEGIN + + +@interface TIMRTLUtil : NSObject + +@end + +@interface UIView (TUIRTL) +- (void)resetFrameToFitRTL; + +@end + +@interface UIImage (TUIRTL) + +- (UIImage *_Nonnull)checkOverturn; +- (UIImage *)rtl_imageFlippedForRightToLeftLayoutDirection; +@end + +typedef NS_ENUM(NSUInteger, TUITextRTLAlignment) { + TUITextRTLAlignmentUndefine, + TUITextRTLAlignmentLeading, + TUITextRTLAlignmentTrailing, + TUITextRTLAlignmentCenter, +}; +@interface UILabel (TUIRTL) +@property (nonatomic, assign) TUITextRTLAlignment rtlAlignment; +@end + +@interface NSMutableAttributedString (TUIRTL) +@property (nonatomic, assign) TUITextRTLAlignment rtlAlignment; +@end + +BOOL isRTLString(NSString *string); +NSString * rtlString(NSString *string); +NSAttributedString *rtlAttributeString(NSAttributedString *attributeString ,NSTextAlignment textAlignment ); +UIEdgeInsets rtlEdgeInsetsWithInsets(UIEdgeInsets insets); + +@interface TUICollectionRTLFitFlowLayout : UICollectionViewFlowLayout + +@end +NS_ASSUME_NONNULL_END diff --git a/iOS/TUIKit/TIMCommon/CommonModel/TIMRTLUtil.m b/iOS/TUIKit/TIMCommon/CommonModel/TIMRTLUtil.m new file mode 100644 index 000000000..d7dea0a8b --- /dev/null +++ b/iOS/TUIKit/TIMCommon/CommonModel/TIMRTLUtil.m @@ -0,0 +1,291 @@ +// +// TIMRTLUtil.m +// TIMCommon +// +// Created by cologne on 2023/7/21. +// Copyright © 2023 Tencent. All rights reserved +// + +#import "TIMRTLUtil.h" +#import +#import + +@implementation TIMRTLUtil + +@end + + +@interface UIView (TUIRTL) + +@end +@implementation UIView (TUIRTL) +- (void)setRTLFrame:(CGRect)frame width:(CGFloat)width { + if (isRTL()) { + if (self.superview == nil) { + NSAssert(0, @"must invoke after have superView"); + } + CGFloat x = width - frame.origin.x - frame.size.width; + frame.origin.x = x; + } + self.frame = frame; +} + +- (void)setRTLFrame:(CGRect)frame { + [self setRTLFrame:frame width:self.superview.frame.size.width]; +} + +- (void)resetFrameToFitRTL { + [self setRTLFrame:self.frame]; +} + +@end + +@interface UIImage (TUIRTL) + +@end +@implementation UIImage (TUIRTL) +- (UIImage *_Nonnull)checkOverturn{ + if (isRTL()) { + UIGraphicsBeginImageContextWithOptions(self.size, false, self.scale); + CGContextRef bitmap = UIGraphicsGetCurrentContext(); + CGContextTranslateCTM(bitmap, self.size.width / 2, self.size.height / 2); + CGContextScaleCTM(bitmap, -1.0, -1.0); + CGContextTranslateCTM(bitmap, -self.size.width / 2, -self.size.height / 2); + CGContextDrawImage(bitmap, CGRectMake(0, 0, self.size.width, self.size.height), self.CGImage); + UIImage *image = UIGraphicsGetImageFromCurrentImageContext(); + return image; + } + return self; +} +- (UIImage *)_imageFlippedForRightToLeftLayoutDirection { + if (isRTL()) { + return [UIImage imageWithCGImage:self.CGImage + scale:self.scale + orientation:UIImageOrientationUpMirrored]; + } + + return self; +} + +- (UIImage *)rtl_imageFlippedForRightToLeftLayoutDirection { + if (isRTL()) { + if (@available(iOS 13.0, *)) { + UITraitCollection *const scaleTraitCollection = [UITraitCollection currentTraitCollection]; + UITraitCollection *const darkUnscaledTraitCollection = [UITraitCollection traitCollectionWithUserInterfaceStyle:UIUserInterfaceStyleDark]; + UITraitCollection *const darkScaledTraitCollection = + [UITraitCollection traitCollectionWithTraitsFromCollections:@[ scaleTraitCollection, darkUnscaledTraitCollection ]]; + + UIImage *lightImg = [[self.imageAsset imageWithTraitCollection:[UITraitCollection traitCollectionWithUserInterfaceStyle:UIUserInterfaceStyleLight]] + _imageFlippedForRightToLeftLayoutDirection]; + + UIImage *darkImage = [[self.imageAsset imageWithTraitCollection:[UITraitCollection traitCollectionWithUserInterfaceStyle:UIUserInterfaceStyleDark]] + _imageFlippedForRightToLeftLayoutDirection]; + + UIImage *image = + [lightImg imageWithConfiguration:[self.configuration + configurationWithTraitCollection:[UITraitCollection + traitCollectionWithUserInterfaceStyle:UIUserInterfaceStyleLight]]]; + [image.imageAsset registerImage:darkImage withTraitCollection:darkScaledTraitCollection]; + return image; + } else { + return [UIImage imageWithCGImage:self.CGImage scale:self.scale orientation:UIImageOrientationUpMirrored]; + } + } + return self; +} + +@end +@interface UINavigationController (TUIRTL) +@end +@implementation UINavigationController (TUIRTL) ++ (void)load { + Method oldMethod = class_getInstanceMethod(self, @selector(initWithRootViewController:)); + Method newMethod = class_getInstanceMethod(self, @selector(rtl_initWithRootViewController:)); + method_exchangeImplementations(oldMethod, newMethod); +} + +- (instancetype)rtl_initWithRootViewController:(UIViewController *)rootViewController { + if ([self rtl_initWithRootViewController:rootViewController]) { + if (@available(iOS 9.0, *)) { + if (isRTL()) { + self.navigationBar.semanticContentAttribute = [UIView appearance].semanticContentAttribute; + self.view.semanticContentAttribute = [UIView appearance].semanticContentAttribute; + } + } + } + return self; +} +@end + + +UIEdgeInsets rtlEdgeInsetsWithInsets(UIEdgeInsets insets) { + if (insets.left != insets.right && isRTL()) { + CGFloat temp = insets.left; + insets.left = insets.right; + insets.right = temp; + } + return insets; + +} + +@implementation UIButton (TUIRTL) + +void swizzleInstanceMethod(Class cls, SEL originSelector, SEL swizzleSelector){ + if (!cls) { + return; + } + /* if current class not exist selector, then get super*/ + Method originalMethod = class_getInstanceMethod(cls, originSelector); + Method swizzledMethod = class_getInstanceMethod(cls, swizzleSelector); + + /* add selector if not exist, implement append with method */ + if (class_addMethod(cls, + originSelector, + method_getImplementation(swizzledMethod), + method_getTypeEncoding(swizzledMethod)) ) { + /* replace class instance method, added if selector not exist */ + /* for class cluster , it always add new selector here */ + class_replaceMethod(cls, + swizzleSelector, + method_getImplementation(originalMethod), + method_getTypeEncoding(originalMethod)); + + } else { + /* swizzleMethod maybe belong to super */ + class_replaceMethod(cls, + swizzleSelector, + class_replaceMethod(cls, + originSelector, + method_getImplementation(swizzledMethod), + method_getTypeEncoding(swizzledMethod)), + method_getTypeEncoding(originalMethod)); + } +} ++ (void)load +{ + swizzleInstanceMethod(self, @selector(setContentEdgeInsets:), @selector(rtl_setContentEdgeInsets:)); + swizzleInstanceMethod(self, @selector(setImageEdgeInsets:), @selector(rtl_setImageEdgeInsets:)); + swizzleInstanceMethod(self, @selector(setTitleEdgeInsets:), @selector(rtl_setTitleEdgeInsets:)); +} + +- (void)rtl_setContentEdgeInsets:(UIEdgeInsets)contentEdgeInsets { + [self rtl_setContentEdgeInsets:rtlEdgeInsetsWithInsets(contentEdgeInsets)]; +} + +- (void)rtl_setImageEdgeInsets:(UIEdgeInsets)imageEdgeInsets { + [self rtl_setImageEdgeInsets:rtlEdgeInsetsWithInsets(imageEdgeInsets)]; +} + +- (void)rtl_setTitleEdgeInsets:(UIEdgeInsets)titleEdgeInsets { + [self rtl_setTitleEdgeInsets:rtlEdgeInsetsWithInsets(titleEdgeInsets)]; +} + + +@end + + +@implementation UILabel (TUIRTL) + +- (void)setRtlAlignment:(TUITextRTLAlignment)rtlAlignment { + objc_setAssociatedObject(self, @selector(rtlAlignment), @(rtlAlignment), OBJC_ASSOCIATION_ASSIGN); + switch (rtlAlignment) { + case TUITextRTLAlignmentLeading: + self.textAlignment = (isRTL() ? NSTextAlignmentRight : NSTextAlignmentLeft); + break; + case TUITextRTLAlignmentTrailing: + self.textAlignment = (isRTL() ? NSTextAlignmentLeft : NSTextAlignmentRight); + break; + case TUITextRTLAlignmentCenter: + self.textAlignment = NSTextAlignmentCenter; + case TUITextRTLAlignmentUndefine: + break; + default: + break; + } +} + +- (TUITextRTLAlignment)rtlAlignment { + NSNumber *identifier = objc_getAssociatedObject(self, @selector(rtlAlignment)); + if (identifier) { + return identifier.integerValue; + } + return TUITextRTLAlignmentUndefine; +} +@end + +@implementation NSMutableAttributedString (TUIRTL) +- (void)setRtlAlignment:(TUITextRTLAlignment)rtlAlignment { + switch (rtlAlignment) { + case TUITextRTLAlignmentLeading: + self.rtlAlignment = (isRTL() ? NSTextAlignmentRight : NSTextAlignmentLeft); + break; + case TUITextRTLAlignmentTrailing: + self.rtlAlignment = (isRTL() ? NSTextAlignmentLeft : NSTextAlignmentRight); + break; + case TUITextRTLAlignmentCenter: + self.rtlAlignment = NSTextAlignmentCenter; + case TUITextRTLAlignmentUndefine: + break; + default: + break; + } +} +@end + +BOOL isRTLString(NSString *string) { + if ([string hasPrefix:@"\u202B"] || [string hasPrefix:@"\u202A"]) { + return YES; + } + return NO; +} + +NSString * rtlString(NSString *string) { + if (string.length == 0 || isRTLString(string)) { + return string; + } + if (isRTL()) { + string = [@"\u202B" stringByAppendingString:string]; + } else { + string = [@"\u202A" stringByAppendingString:string]; + } + return string; +} + +NSAttributedString *rtlAttributeString(NSAttributedString *attributeString ,NSTextAlignment textAlignment ){ + if (attributeString.length == 0) { + return attributeString; + } + NSRange range; + NSDictionary *originAttributes = [attributeString attributesAtIndex:0 effectiveRange:&range]; + NSParagraphStyle *style = [originAttributes objectForKey:NSParagraphStyleAttributeName]; + + if (style && isRTLString(attributeString.string)) { + return attributeString; + } + + NSMutableDictionary *attributes = originAttributes ? [originAttributes mutableCopy] : [NSMutableDictionary new]; + if (!style) { + NSMutableParagraphStyle *mutableParagraphStyle = [[NSMutableParagraphStyle alloc] init]; + UILabel *test = [UILabel new]; + test.textAlignment = textAlignment; + mutableParagraphStyle.alignment = test.textAlignment; + style = mutableParagraphStyle; + [attributes setValue:mutableParagraphStyle forKey:NSParagraphStyleAttributeName]; + } + NSString *string = rtlString(attributeString.string); + return [[NSAttributedString alloc] initWithString:string attributes:attributes]; +} + +@implementation TUICollectionRTLFitFlowLayout +- (UIUserInterfaceLayoutDirection)effectiveUserInterfaceLayoutDirection { + if (isRTL()) { + return UIUserInterfaceLayoutDirectionRightToLeft; + } + return UIUserInterfaceLayoutDirectionLeftToRight; +} + +- (BOOL)flipsHorizontallyInOppositeLayoutDirection{ + + return isRTL()? YES:NO; +} +@end diff --git a/iOS/TUIKit/TIMCommon/CommonModel/TUIFloatViewController.m b/iOS/TUIKit/TIMCommon/CommonModel/TUIFloatViewController.m index 5ef9952dc..e71be880f 100644 --- a/iOS/TUIKit/TIMCommon/CommonModel/TUIFloatViewController.m +++ b/iOS/TUIKit/TIMCommon/CommonModel/TUIFloatViewController.m @@ -79,6 +79,10 @@ typedef enum : NSUInteger { [self.rightButton sizeToFit]; self.rightButton.frame = CGRectMake(self.frame.size.width - self.rightButton.frame.size.width - kScale390(14), kScale390(23.5), self.rightButton.frame.size.width, self.rightButton.frame.size.height); + if (isRTL()){ + [self.leftButton resetFrameToFitRTL]; + [self.rightButton resetFrameToFitRTL]; + } } - (void)leftButtonClick { if (self.leftButtonClickCallback) { diff --git a/iOS/TUIKit/TIMCommon/Resources/TIMCommon.bundle/default_c2c_head@2x.png b/iOS/TUIKit/TIMCommon/Resources/TIMCommon.bundle/default_c2c_head@2x.png index aca00ca22..09188487e 100644 Binary files a/iOS/TUIKit/TIMCommon/Resources/TIMCommon.bundle/default_c2c_head@2x.png and b/iOS/TUIKit/TIMCommon/Resources/TIMCommon.bundle/default_c2c_head@2x.png differ diff --git a/iOS/TUIKit/TIMCommon/Resources/TIMCommon.bundle/default_choose@3x.png b/iOS/TUIKit/TIMCommon/Resources/TIMCommon.bundle/default_choose@3x.png index 3bd50617d..e408b1dee 100644 Binary files a/iOS/TUIKit/TIMCommon/Resources/TIMCommon.bundle/default_choose@3x.png and b/iOS/TUIKit/TIMCommon/Resources/TIMCommon.bundle/default_choose@3x.png differ diff --git a/iOS/TUIKit/TIMCommon/Resources/TIMCommon.bundle/default_fold_group@2x.png b/iOS/TUIKit/TIMCommon/Resources/TIMCommon.bundle/default_fold_group@2x.png index 1e3c90570..0cce45aae 100644 Binary files a/iOS/TUIKit/TIMCommon/Resources/TIMCommon.bundle/default_fold_group@2x.png and b/iOS/TUIKit/TIMCommon/Resources/TIMCommon.bundle/default_fold_group@2x.png differ diff --git a/iOS/TUIKit/TIMCommon/Resources/TIMCommon.bundle/default_group_head@2x.png b/iOS/TUIKit/TIMCommon/Resources/TIMCommon.bundle/default_group_head@2x.png index 30d1732fb..1a9dbda07 100644 Binary files a/iOS/TUIKit/TIMCommon/Resources/TIMCommon.bundle/default_group_head@2x.png and b/iOS/TUIKit/TIMCommon/Resources/TIMCommon.bundle/default_group_head@2x.png differ diff --git a/iOS/TUIKit/TIMCommon/Resources/TIMCommon.bundle/default_group_head_avchatroom@2x.png b/iOS/TUIKit/TIMCommon/Resources/TIMCommon.bundle/default_group_head_avchatroom@2x.png index 015ce7aaf..e821e64bb 100644 Binary files a/iOS/TUIKit/TIMCommon/Resources/TIMCommon.bundle/default_group_head_avchatroom@2x.png and b/iOS/TUIKit/TIMCommon/Resources/TIMCommon.bundle/default_group_head_avchatroom@2x.png differ diff --git a/iOS/TUIKit/TIMCommon/Resources/TIMCommon.bundle/default_group_head_community@2x.png b/iOS/TUIKit/TIMCommon/Resources/TIMCommon.bundle/default_group_head_community@2x.png index ca5814336..92aceceeb 100644 Binary files a/iOS/TUIKit/TIMCommon/Resources/TIMCommon.bundle/default_group_head_community@2x.png and b/iOS/TUIKit/TIMCommon/Resources/TIMCommon.bundle/default_group_head_community@2x.png differ diff --git a/iOS/TUIKit/TIMCommon/Resources/TIMCommon.bundle/default_group_head_meeting@2x.png b/iOS/TUIKit/TIMCommon/Resources/TIMCommon.bundle/default_group_head_meeting@2x.png index e363ed6ef..dffcd1413 100644 Binary files a/iOS/TUIKit/TIMCommon/Resources/TIMCommon.bundle/default_group_head_meeting@2x.png and b/iOS/TUIKit/TIMCommon/Resources/TIMCommon.bundle/default_group_head_meeting@2x.png differ diff --git a/iOS/TUIKit/TIMCommon/Resources/TIMCommon.bundle/default_group_head_public@2x.png b/iOS/TUIKit/TIMCommon/Resources/TIMCommon.bundle/default_group_head_public@2x.png index 5484cddcb..2a275ca75 100644 Binary files a/iOS/TUIKit/TIMCommon/Resources/TIMCommon.bundle/default_group_head_public@2x.png and b/iOS/TUIKit/TIMCommon/Resources/TIMCommon.bundle/default_group_head_public@2x.png differ diff --git a/iOS/TUIKit/TIMCommon/Resources/TIMCommon.bundle/icon_avatar_selected@2x.png b/iOS/TUIKit/TIMCommon/Resources/TIMCommon.bundle/icon_avatar_selected@2x.png index 05c99cb27..54a862ffc 100644 Binary files a/iOS/TUIKit/TIMCommon/Resources/TIMCommon.bundle/icon_avatar_selected@2x.png and b/iOS/TUIKit/TIMCommon/Resources/TIMCommon.bundle/icon_avatar_selected@2x.png differ diff --git a/iOS/TUIKit/TIMCommon/Resources/TIMCommon.bundle/icon_cell_blue_normal@2x.png b/iOS/TUIKit/TIMCommon/Resources/TIMCommon.bundle/icon_cell_blue_normal@2x.png index 7c87c8ee5..28f3ed993 100644 Binary files a/iOS/TUIKit/TIMCommon/Resources/TIMCommon.bundle/icon_cell_blue_normal@2x.png and b/iOS/TUIKit/TIMCommon/Resources/TIMCommon.bundle/icon_cell_blue_normal@2x.png differ diff --git a/iOS/TUIKit/TIMCommon/Resources/TIMCommon.bundle/icon_cell_blue_normal@3x.png b/iOS/TUIKit/TIMCommon/Resources/TIMCommon.bundle/icon_cell_blue_normal@3x.png index 34eee2cb6..6495f1c9a 100644 Binary files a/iOS/TUIKit/TIMCommon/Resources/TIMCommon.bundle/icon_cell_blue_normal@3x.png and b/iOS/TUIKit/TIMCommon/Resources/TIMCommon.bundle/icon_cell_blue_normal@3x.png differ diff --git a/iOS/TUIKit/TIMCommon/Resources/TIMCommon.bundle/icon_flex_arrow@3x.png b/iOS/TUIKit/TIMCommon/Resources/TIMCommon.bundle/icon_flex_arrow@3x.png index c92575a1a..d4f63158c 100644 Binary files a/iOS/TUIKit/TIMCommon/Resources/TIMCommon.bundle/icon_flex_arrow@3x.png and b/iOS/TUIKit/TIMCommon/Resources/TIMCommon.bundle/icon_flex_arrow@3x.png differ diff --git a/iOS/TUIKit/TIMCommon/Resources/TIMCommon.bundle/icon_offline_status@2x.png b/iOS/TUIKit/TIMCommon/Resources/TIMCommon.bundle/icon_offline_status@2x.png index a99167c98..73c21091e 100644 Binary files a/iOS/TUIKit/TIMCommon/Resources/TIMCommon.bundle/icon_offline_status@2x.png and b/iOS/TUIKit/TIMCommon/Resources/TIMCommon.bundle/icon_offline_status@2x.png differ diff --git a/iOS/TUIKit/TIMCommon/Resources/TIMCommon.bundle/icon_offline_status@3x.png b/iOS/TUIKit/TIMCommon/Resources/TIMCommon.bundle/icon_offline_status@3x.png index 93f4010f8..f326e14ea 100644 Binary files a/iOS/TUIKit/TIMCommon/Resources/TIMCommon.bundle/icon_offline_status@3x.png and b/iOS/TUIKit/TIMCommon/Resources/TIMCommon.bundle/icon_offline_status@3x.png differ diff --git a/iOS/TUIKit/TIMCommon/Resources/TIMCommon.bundle/icon_online_status@2x.png b/iOS/TUIKit/TIMCommon/Resources/TIMCommon.bundle/icon_online_status@2x.png index 71e71c74b..a04b9f80f 100644 Binary files a/iOS/TUIKit/TIMCommon/Resources/TIMCommon.bundle/icon_online_status@2x.png and b/iOS/TUIKit/TIMCommon/Resources/TIMCommon.bundle/icon_online_status@2x.png differ diff --git a/iOS/TUIKit/TIMCommon/Resources/TIMCommon.bundle/icon_online_status@3x.png b/iOS/TUIKit/TIMCommon/Resources/TIMCommon.bundle/icon_online_status@3x.png index cf07e72e3..925ec9b4e 100644 Binary files a/iOS/TUIKit/TIMCommon/Resources/TIMCommon.bundle/icon_online_status@3x.png and b/iOS/TUIKit/TIMCommon/Resources/TIMCommon.bundle/icon_online_status@3x.png differ diff --git a/iOS/TUIKit/TIMCommon/Resources/TIMCommon.bundle/icon_select_normal@2x.png b/iOS/TUIKit/TIMCommon/Resources/TIMCommon.bundle/icon_select_normal@2x.png index c061a1641..47ce633b9 100644 Binary files a/iOS/TUIKit/TIMCommon/Resources/TIMCommon.bundle/icon_select_normal@2x.png and b/iOS/TUIKit/TIMCommon/Resources/TIMCommon.bundle/icon_select_normal@2x.png differ diff --git a/iOS/TUIKit/TIMCommon/Resources/TIMCommon.bundle/icon_select_normal@3x.png b/iOS/TUIKit/TIMCommon/Resources/TIMCommon.bundle/icon_select_normal@3x.png index 394c16d83..3241b9289 100644 Binary files a/iOS/TUIKit/TIMCommon/Resources/TIMCommon.bundle/icon_select_normal@3x.png and b/iOS/TUIKit/TIMCommon/Resources/TIMCommon.bundle/icon_select_normal@3x.png differ diff --git a/iOS/TUIKit/TIMCommon/Resources/TIMCommon.bundle/icon_select_pressed@2x.png b/iOS/TUIKit/TIMCommon/Resources/TIMCommon.bundle/icon_select_pressed@2x.png index c3bb6e0a3..8e4df358a 100644 Binary files a/iOS/TUIKit/TIMCommon/Resources/TIMCommon.bundle/icon_select_pressed@2x.png and b/iOS/TUIKit/TIMCommon/Resources/TIMCommon.bundle/icon_select_pressed@2x.png differ diff --git a/iOS/TUIKit/TIMCommon/Resources/TIMCommon.bundle/icon_select_pressed@3x.png b/iOS/TUIKit/TIMCommon/Resources/TIMCommon.bundle/icon_select_pressed@3x.png index c1a94329e..7f203456b 100644 Binary files a/iOS/TUIKit/TIMCommon/Resources/TIMCommon.bundle/icon_select_pressed@3x.png and b/iOS/TUIKit/TIMCommon/Resources/TIMCommon.bundle/icon_select_pressed@3x.png differ diff --git a/iOS/TUIKit/TIMCommon/Resources/TIMCommon.bundle/icon_select_selected@2x.png b/iOS/TUIKit/TIMCommon/Resources/TIMCommon.bundle/icon_select_selected@2x.png index 2b7c1ca62..892a9a71c 100644 Binary files a/iOS/TUIKit/TIMCommon/Resources/TIMCommon.bundle/icon_select_selected@2x.png and b/iOS/TUIKit/TIMCommon/Resources/TIMCommon.bundle/icon_select_selected@2x.png differ diff --git a/iOS/TUIKit/TIMCommon/Resources/TIMCommon.bundle/icon_select_selected@3x.png b/iOS/TUIKit/TIMCommon/Resources/TIMCommon.bundle/icon_select_selected@3x.png index ca0f6c3c7..f491e70ed 100644 Binary files a/iOS/TUIKit/TIMCommon/Resources/TIMCommon.bundle/icon_select_selected@3x.png and b/iOS/TUIKit/TIMCommon/Resources/TIMCommon.bundle/icon_select_selected@3x.png differ diff --git a/iOS/TUIKit/TIMCommon/Resources/TIMCommon.bundle/icon_select_selected_disable@2x.png b/iOS/TUIKit/TIMCommon/Resources/TIMCommon.bundle/icon_select_selected_disable@2x.png index 4cf89bf1f..b939184a6 100644 Binary files a/iOS/TUIKit/TIMCommon/Resources/TIMCommon.bundle/icon_select_selected_disable@2x.png and b/iOS/TUIKit/TIMCommon/Resources/TIMCommon.bundle/icon_select_selected_disable@2x.png differ diff --git a/iOS/TUIKit/TIMCommon/Resources/TIMCommon.bundle/icon_select_selected_disable@3x.png b/iOS/TUIKit/TIMCommon/Resources/TIMCommon.bundle/icon_select_selected_disable@3x.png index 0b310eec2..035a990c7 100644 Binary files a/iOS/TUIKit/TIMCommon/Resources/TIMCommon.bundle/icon_select_selected_disable@3x.png and b/iOS/TUIKit/TIMCommon/Resources/TIMCommon.bundle/icon_select_selected_disable@3x.png differ diff --git a/iOS/TUIKit/TIMCommon/Resources/TIMCommon.bundle/icon_translate@2x.png b/iOS/TUIKit/TIMCommon/Resources/TIMCommon.bundle/icon_translate@2x.png index 0ddaef6d9..2fc93ba53 100644 Binary files a/iOS/TUIKit/TIMCommon/Resources/TIMCommon.bundle/icon_translate@2x.png and b/iOS/TUIKit/TIMCommon/Resources/TIMCommon.bundle/icon_translate@2x.png differ diff --git a/iOS/TUIKit/TIMCommon/Resources/TIMCommon.bundle/icon_translate@3x.png b/iOS/TUIKit/TIMCommon/Resources/TIMCommon.bundle/icon_translate@3x.png index 2ae4e9ba8..72bede4bf 100644 Binary files a/iOS/TUIKit/TIMCommon/Resources/TIMCommon.bundle/icon_translate@3x.png and b/iOS/TUIKit/TIMCommon/Resources/TIMCommon.bundle/icon_translate@3x.png differ diff --git a/iOS/TUIKit/TIMCommon/Resources/TIMCommon.bundle/messageReplyIcon@2x.png b/iOS/TUIKit/TIMCommon/Resources/TIMCommon.bundle/messageReplyIcon@2x.png index 19e4b81e0..b2ca55155 100644 Binary files a/iOS/TUIKit/TIMCommon/Resources/TIMCommon.bundle/messageReplyIcon@2x.png and b/iOS/TUIKit/TIMCommon/Resources/TIMCommon.bundle/messageReplyIcon@2x.png differ diff --git a/iOS/TUIKit/TIMCommon/Resources/TIMCommon.bundle/message_translation_loading@2x.png b/iOS/TUIKit/TIMCommon/Resources/TIMCommon.bundle/message_translation_loading@2x.png index 9dac0f968..0c1d67584 100644 Binary files a/iOS/TUIKit/TIMCommon/Resources/TIMCommon.bundle/message_translation_loading@2x.png and b/iOS/TUIKit/TIMCommon/Resources/TIMCommon.bundle/message_translation_loading@2x.png differ diff --git a/iOS/TUIKit/TIMCommon/Resources/TIMCommon.bundle/message_translation_loading@3x.png b/iOS/TUIKit/TIMCommon/Resources/TIMCommon.bundle/message_translation_loading@3x.png index 761f43419..832c00cf2 100644 Binary files a/iOS/TUIKit/TIMCommon/Resources/TIMCommon.bundle/message_translation_loading@3x.png and b/iOS/TUIKit/TIMCommon/Resources/TIMCommon.bundle/message_translation_loading@3x.png differ diff --git a/iOS/TUIKit/TIMCommon/Resources/TIMCommon.bundle/message_translation_tips@2x.png b/iOS/TUIKit/TIMCommon/Resources/TIMCommon.bundle/message_translation_tips@2x.png index d83cc83ff..e84c6c505 100644 Binary files a/iOS/TUIKit/TIMCommon/Resources/TIMCommon.bundle/message_translation_tips@2x.png and b/iOS/TUIKit/TIMCommon/Resources/TIMCommon.bundle/message_translation_tips@2x.png differ diff --git a/iOS/TUIKit/TIMCommon/Resources/TIMCommon.bundle/message_translation_tips@3x.png b/iOS/TUIKit/TIMCommon/Resources/TIMCommon.bundle/message_translation_tips@3x.png index 3d6af40fa..9520ab53d 100644 Binary files a/iOS/TUIKit/TIMCommon/Resources/TIMCommon.bundle/message_translation_tips@3x.png and b/iOS/TUIKit/TIMCommon/Resources/TIMCommon.bundle/message_translation_tips@3x.png differ diff --git a/iOS/TUIKit/TIMCommon/Resources/TIMCommon.bundle/more@2x.png b/iOS/TUIKit/TIMCommon/Resources/TIMCommon.bundle/more@2x.png index b2890f402..134a61308 100644 Binary files a/iOS/TUIKit/TIMCommon/Resources/TIMCommon.bundle/more@2x.png and b/iOS/TUIKit/TIMCommon/Resources/TIMCommon.bundle/more@2x.png differ diff --git a/iOS/TUIKit/TIMCommon/Resources/TIMCommon.bundle/more_group_note@2x.png b/iOS/TUIKit/TIMCommon/Resources/TIMCommon.bundle/more_group_note@2x.png index 6e09e1e02..a8774392a 100644 Binary files a/iOS/TUIKit/TIMCommon/Resources/TIMCommon.bundle/more_group_note@2x.png and b/iOS/TUIKit/TIMCommon/Resources/TIMCommon.bundle/more_group_note@2x.png differ diff --git a/iOS/TUIKit/TIMCommon/Resources/TIMCommon.bundle/more_group_note@3x.png b/iOS/TUIKit/TIMCommon/Resources/TIMCommon.bundle/more_group_note@3x.png index acc41a783..8fb611a9e 100644 Binary files a/iOS/TUIKit/TIMCommon/Resources/TIMCommon.bundle/more_group_note@3x.png and b/iOS/TUIKit/TIMCommon/Resources/TIMCommon.bundle/more_group_note@3x.png differ diff --git a/iOS/TUIKit/TIMCommon/Resources/TIMCommon.bundle/more_poll@2x.png b/iOS/TUIKit/TIMCommon/Resources/TIMCommon.bundle/more_poll@2x.png index c90a74d45..cbe92506a 100644 Binary files a/iOS/TUIKit/TIMCommon/Resources/TIMCommon.bundle/more_poll@2x.png and b/iOS/TUIKit/TIMCommon/Resources/TIMCommon.bundle/more_poll@2x.png differ diff --git a/iOS/TUIKit/TIMCommon/Resources/TIMCommon.bundle/more_poll@3x.png b/iOS/TUIKit/TIMCommon/Resources/TIMCommon.bundle/more_poll@3x.png index be52e9a1b..addad7591 100644 Binary files a/iOS/TUIKit/TIMCommon/Resources/TIMCommon.bundle/more_poll@3x.png and b/iOS/TUIKit/TIMCommon/Resources/TIMCommon.bundle/more_poll@3x.png differ diff --git a/iOS/TUIKit/TIMCommon/Resources/TIMCommon.bundle/more_video_call@2x.png b/iOS/TUIKit/TIMCommon/Resources/TIMCommon.bundle/more_video_call@2x.png index f153cd288..6665734da 100644 Binary files a/iOS/TUIKit/TIMCommon/Resources/TIMCommon.bundle/more_video_call@2x.png and b/iOS/TUIKit/TIMCommon/Resources/TIMCommon.bundle/more_video_call@2x.png differ diff --git a/iOS/TUIKit/TIMCommon/Resources/TIMCommon.bundle/more_video_call@3x.png b/iOS/TUIKit/TIMCommon/Resources/TIMCommon.bundle/more_video_call@3x.png index 4d41ed8b2..f9714116a 100644 Binary files a/iOS/TUIKit/TIMCommon/Resources/TIMCommon.bundle/more_video_call@3x.png and b/iOS/TUIKit/TIMCommon/Resources/TIMCommon.bundle/more_video_call@3x.png differ diff --git a/iOS/TUIKit/TIMCommon/Resources/TIMCommon.bundle/more_voice_call@2x.png b/iOS/TUIKit/TIMCommon/Resources/TIMCommon.bundle/more_voice_call@2x.png index 0c9e81498..d847912eb 100644 Binary files a/iOS/TUIKit/TIMCommon/Resources/TIMCommon.bundle/more_voice_call@2x.png and b/iOS/TUIKit/TIMCommon/Resources/TIMCommon.bundle/more_voice_call@2x.png differ diff --git a/iOS/TUIKit/TIMCommon/Resources/TIMCommon.bundle/more_voice_call@3x.png b/iOS/TUIKit/TIMCommon/Resources/TIMCommon.bundle/more_voice_call@3x.png index 4c0455089..f333fe9ed 100644 Binary files a/iOS/TUIKit/TIMCommon/Resources/TIMCommon.bundle/more_voice_call@3x.png and b/iOS/TUIKit/TIMCommon/Resources/TIMCommon.bundle/more_voice_call@3x.png differ diff --git a/iOS/TUIKit/TIMCommon/Resources/TIMCommon.bundle/nav_back@3x.png b/iOS/TUIKit/TIMCommon/Resources/TIMCommon.bundle/nav_back@3x.png new file mode 100644 index 000000000..bd86caa65 Binary files /dev/null and b/iOS/TUIKit/TIMCommon/Resources/TIMCommon.bundle/nav_back@3x.png differ diff --git a/iOS/TUIKit/TIMCommon/Resources/TIMCommonLocalizable.bundle/Localizable/ar.lproj/Localizable.strings b/iOS/TUIKit/TIMCommon/Resources/TIMCommonLocalizable.bundle/Localizable/ar.lproj/Localizable.strings new file mode 100644 index 000000000..1cef35b53 --- /dev/null +++ b/iOS/TUIKit/TIMCommon/Resources/TIMCommonLocalizable.bundle/Localizable/ar.lproj/Localizable.strings @@ -0,0 +1,728 @@ +/* + Localizable.strings + Chinese Simplized + + Created by harvy on 2020/10/9. + +*/ + +/***************************** 日期格式化 Start *************************/ +"YesterdayDateFormat" = "aHH:mm"; +/***************************** 日期格式化 End *************************/ + +"TUIKitTipsMostSelectTextFormat" = "يمكن اختيار حد أقصى %ld"; + +"Confirm" = "تأكيد"; +"Cancel" = "إلغاء"; +"Send" = "إرسال"; +"Save" = "حفظ"; +"You" = "أنت"; +"you" = "أنت"; +"Male" = "ذكر"; +"Female" = "أنثى"; +"File" = "ملف"; +"Download" = "تحميل"; +"Unsetted" = "غير محدد"; +"Show" = "عرض"; + +"Monday" = "الاثنين"; +"Tuesday" = "الثلاثاء"; +"Wednesday" = "الأربعاء"; +"Thursday" = "الخميس"; +"Friday" = "الجمعة"; +"Saturday" = "السبت"; +"Sunday" = "الأحد"; +"Yesterday" = "أمس"; +"am" = "صباحًا"; +"pm" = "مساءً"; + +"Read" = "تمت القراءة"; +"Unread" = "غير مقروء"; + +"Copy" = "نسخ"; +"Delete" = "حذف"; +"Revoke" = "إلغاء"; +"Retry" = "إعادة المحاولة"; +"Re_send" = "إعادة الإرسال"; +"Make_a_call" = "إجراء مكالمة"; +"Done" = "تم"; +"All" = "الكل"; +"Agreed" = "تم الموافقة"; +"Disclined" = "تم الرفض"; +"Agree" = "موافقة"; +"Have_been_sent" = "تم الإرسال"; + +"OK" = "موافق"; +"None" = "لا شيء"; +"Send" = "إرسال"; +"Cancel" = "إلغاء"; +"Alia" = "ملاحظة"; +"Group" = "مجموعة"; +"Accept" = "قبول"; +"Decline" = "رفض"; +"send_success" = "تم الإرسال بنجاح"; +"add_success" = "تمت الإضافة بنجاح"; +"delete_success" = "تم الحذف بنجاح"; +"my_friend" = "أصدقائي"; +"no_personal_signature" = "لا توجد توقيع شخصي"; +"SignatureFormat" = "التوقيع الشخصي: %@"; +"choose_avatar_for_you" = "تم تعيين صورة رمزية لك تلقائيًا من التطبيق"; +"SearchGroupPlaceholder" = "معرف المستخدم"; +"please_fill_in_verification_information" = "يرجى ملء معلومات التحقق"; +"please_fill_in_remarks_group_info" = "يرجى ملء معلومات الملاحظات والمجموعة"; + +"no_set" = "غير محدد"; +"no_personal_signature" = "لا توجد توقيع شخصي"; +"logout" = "تسجيل الخروج"; +"login" = "تسجيل الدخول"; +"ReadAll" = "قراءة الكل"; +"Hide" = "إخفاء"; +"Delete" = "حذف"; + +"ContactsJoinGroup" = "إضافة محادثة جماعية"; +"ContactsAddFriends" = "إضافة صديق"; + +"ChatsNewChatText" = "بدء محادثة"; +"ChatsNewGroupText" = "إنشاء محادثة جماعية"; +"ChatsSelectContact" = "اختيار جهة الاتصال"; + +"GroupJoin" = "إضافة مجموعة"; +"GroupRequestJoinGroupFormat" = "%@ يطلب الانضمام إلى المحادثة الجماعية"; +"GroupDeleteFriend" = "حذف جهة الاتصال"; +"GroupAddFirend" = "إضافة جهة الاتصال"; +"GroupMember" = "أعضاء المجموعة"; + +"ProfileAlia" = "اسم الملاحظة"; +"ProfileMessageDoNotDisturb" = "عدم الإزعاج"; +"ProfileStickyonTop" = "تثبيت المحادثة في الأعلى"; +"ProfileBlocked" = "إضافة إلى القائمة السوداء"; +"ProfileSendMessages" = "إرسال رسالة"; +"ProfileDeleteFirend" = "حذف الصديق"; +"ProfileEditAlia" = "تعديل الملاحظة"; +"ProfileDetails" = "تفاصيل الملف الشخصي"; +"ProfileSetBackgroundImage" = "تعيين صورة خلفية للمحادثة الحالية"; +"ProfilePhoto" = "الصورة الرمزية"; +"ProfileName" = "الاسم"; +"ProfileAccount" = "الحساب"; +"ProfileSignature" = "التوقيع الشخصي"; +"ProfileGender" = "الجنس"; +"ProfileEditName" = "تعديل الاسم"; +"ProfileEditNameDesc" = "يسمح فقط بالأحرف الصينية والحروف والأرقام والشرطة السفلية"; +"ProfileEditSignture" = "تعديل التوقيع الشخصي"; +"ProfileEditGender" = "تعديل الجنس"; +"ProfileEditAlia" = "تعديل الملاحظة"; +"ProfileEdit" = "تعديل"; +"ProfileAlia" = "اسم الملاحظة"; +"ProfileBlocked" = "إضافة إلى القائمة السوداء"; +"ProfileMessageDoNotDisturb" = "عدم الإزعاج"; +"ProfileStickyonTop" = "تثبيت المحادثة في الأعلى"; +"ProfileSendMessages" = "إرسال رسالة"; +"ProfileDeleteFirend" = "حذف الصديق"; +"ProfileBirthday" = "تاريخ الميلاد"; +"SignatureFormat" = "التوقيع الشخصي: %@"; + +"FriendRequestFormat" = "أنا %@"; +"FriendRequestFillInfo" = "إضافة صديق"; +"FriendOneWay" = "صديق في اتجاه واحد"; +"FriendAddTitle" = "إضافة صديق"; +"FriendAddVerificationMessage" = "رسالة التحقق"; +"FriendAddResultSuccessWait" = "تم الإرسال بنجاح، في انتظار الموافقة"; +"FriendAddResultForbid" = "الطرف الآخر ممنوع إضافته"; +"FriendAddResultSuccess" = "تمت الإضافة إلى قائمة الأصدقاء"; +"FriendAddResultExists" = "الطرف الآخر هو بالفعل صديق لك"; +"MeFriendRequest" = "عندما يرغب شخص ما في إضافتي كصديق"; +"MeFriendRequestMethodAgreeAll" = "الموافقة على أي شخص يرغب في إضافتي كصديق"; +"MeFriendRequestMethodNeedConfirm" = "يحتاج التحقق"; +"MeFriendRequestMethodDenyAll" = "رفض أي شخص يرغب في إضافتي كصديق"; +"MeMessageReadStatus" = "حالة قراءة الرسائل"; +"MeMessageReadStatusOpenDesc" = "عند الإغلاق، لن تظهر حالة قراءة الرسائل في الرسائل التي تستلمها أو ترسلها، ولن تتمكن من معرفة ما إذا قرأ الطرف الآخر الرسالة أم لا، وبالمثل، الطرف الآخر لن يتمكن من معرفة ما إذا قرأت الرسالة أم لا."; +"MeMessageReadStatusCloseDesc" = "عند الفتح، ستظهر حالة قراءة الرسائل في الرسائل التي تستلمها أو ترسلها في المحادثات الجماعية، ويمكنك رؤية ما إذا قرأ الطرف الآخر الرسالة أم لا. إذا قام أصدقاؤك في المحادثات الفردية بتفعيل حالة قراءة الرسائل، ستظهر حالة قراءة الرسائل في المحادثات الفردية التي تتبادلها معهم."; + +"ShowOnlineStatus" = "عرض حالة الاتصال"; +"ShowOnlineStatusOpenDesc" = "عند الإغلاق، لن ترى حالة الاتصال (متصل/غير متصل) لأصدقائك في قائمة المحادثات وقائمة الأصدقاء."; +"ShowOnlineStatusCloseDesc" = "عند الفتح، سترى حالة الاتصال (متصل/غير متصل) لأصدقائك في قائمة المحادثات وقائمة الأصدقاء."; +"ShowPackageToast" = "هذه الميزة متاحة في الإصدار الفاخر"; + +"ShowCallsRecord" = "عرض سجل المكالمات"; + +"TUIKitClassic" = "التصميم الكلاسيكي"; +"TUIKitMinimalist" = "التصميم البسيط"; +"TUIKitThemeNameSystemFollowTitle" = "متابعة نظام الجهاز"; +"TUIKitThemeNameSystemFollowSubTitle" = "عند الفتح، سيتم عرض التصميم الافتراضي (الخفيف/الداكن) فقط، ولا يمكن تغيير تصميم التطبيق إلى أي تصميم آخر."; +"TUIKitThemeNameSerious" = "جدي"; +"TUIKitThemeNameLight" = "خفيف"; +"TUIKitThemeNameLivey" = "حيوي"; +"TUIKitThemeNameDark" = "داكن"; +"TUIKitThemeNameSystem" = "متابعة نظام الجهاز"; + +"TUIKitDone" = "تم"; +"TUIKitWelcome" = "مرحبًا بك في عائلة Tencent Cloud IM!"; +"TUIKitMicCamerAuthTips" = "يرجى تمكين إذن الوصول إلى الميكروفون والكاميرا"; +"TUIKitMicAuth" = "يرجى تمكين إذن الوصول إلى الميكروفون"; +"TUIKitTipsConfirmResendMessage" = "هل ترغب في إعادة إرسال هذه الرسالة؟"; +"TUIKitTipsSystemError" = "خطأ في النظام"; +"TUIKitTipsEnterRoomErrorFormat" = "فشل الانضمام إلى الغرفة: %d"; +"TUIKitWhoRequestForJoinGroupFormat" = "%@ يطلب الانضمام إلى المجموعة"; +"TUIKitInviteJoinGroupFormat" = "دعوة %@ للانضمام إلى المجموعة"; +"TUIKitAgreedByAdministor" = "تمت الموافقة من قبل المسؤول"; +"TUIkitDiscliedByAdministor" = "تم الرفض من قبل المسؤول"; +"TUIKitDownloadProgressFormat" = "جارٍ تنزيل %d٪"; +"TUIKitOpenWithOtherApp" = "فتح باستخدام تطبيق آخر"; +"TUIKitTipsContactListNil" = "قائمة جهات الاتصال فارغة، يرجى إضافة أصدقاء أولاً"; + +"TUIKitUserStatusUnknown" = "غير معروف"; +"TUIKitUserStatusOnline" = "متصل"; +"TUIKitUserStatusOffline" = "غير متصل"; +"TUIKitUserStatusUnlogined" = "غير مسجل الدخول"; + +"TUIKitInputHoldToTalk" = "استمر في الضغط للتحدث"; +"TUIKitInputReleaseToSend" = "رفع الإصبع لإرسال"; +"TUIKitInputReleaseToCancel" = "رفع الإصبع للإلغاء"; +"TUIKitInputBlankMessageTitle" = "لا يمكن إرسال رسالة فارغة"; +"TUIKitInputWillFinishRecordInSeconds" = "سيتم إنهاء التسجيل في %ld ثانية"; +"TUIKitInputRecordSlideToCancel" = "اسحب الإصبع للأعلى للإلغاء"; +"TUIKitInputRecordReleaseToCancel" = "رفع الإصبع للإلغاء"; +"TUIKitInputRecordTimeshort" = "مدة التسجيل قصيرة جدًا"; +"TUIKitInputRecordTimeLong" = "مدة التسجيل طويلة جدًا"; + +"TUIKitGroupProfileDetails" = "تفاصيل الملف الشخصي"; +"TUIKitGroupProfileMember" = "أعضاء المجموعة"; +"TUIKitGroupProfileMemberCount" = "%d أشخاص"; +"TUIKitGroupProfileMemberCountlu" = "%lu شخص"; +"TUIKitGroupProfileType" = "نوع المجموعة"; +"TUIKitGroupProfileJoinType" = "طريقة الانضمام النشطة"; +"TUIKitGroupProfileInviteType" = "طريقة الدعوة للانضمام"; +"TUIKitGroupProfileInviteJoin" = "دعوة للانضمام"; +"TUIKitGroupProfileAutoApproval" = "الموافقة التلقائية"; +"TUIKitGroupProfileAlias" = "اسم المجموعة الخاص بي"; +"TUIKitGroupProfileMessageDoNotDisturb" = "عدم الإزعاج للرسائل"; +"TUIKitGroupProfileStickyOnTop" = "تثبيت في الأعلى"; +"TUIKitGroupProfileDeleteAndExit" = "حذف والخروج"; +"TUIKitGroupProfileDissolve" = "حل المجموعة"; +"TUIKitGroupProfileJoinDisable" = "تعطيل الانضمام"; +"TUIKitGroupProfileInviteDisable" = "تعطيل الدعوة"; +"TUIKitGroupProfileAdminApprove" = "موافقة المشرف"; +"TUIKitGroupProfileEditAlias" = "تعديل اسم المجموعة الخاص بي"; +"TUIKitGroupProfileEditAliasDesc" = "مسموح فقط بالأحرف الصينية والأحرف اللاتينية والأرقام والشرطة السفلية"; +"TUIKitGroupProfileEditGroupName" = "تعديل اسم المجموعة"; +"TUIKitGroupProfileEditAnnouncement" = "تعديل إعلان المجموعة"; +"TUIKitGroupProfileEditAvatar" = "تعديل صورة المجموعة"; +"TUIKitGroupProfileDeleteGroupTips" = "بمجرد الخروج، لن تتلقى رسائل المجموعة"; +"TUIKitGroupProfileGroupCountFormat" = "أعضاء المجموعة (%ld أشخاص)"; +"TUIKitGroupProfileManage" = "الإدارة"; +"TUIKitGroupProfileManageAdd" = "إضافة عضو"; +"TUIKitGroupProfileManageDelete" = "حذف عضو"; +"TUIKitGroupProfileAdmainAdd" = "تعيين كمشرف"; +"TUIKitGroupProfileAdmainDelete" = "إلغاء تعيين كمشرف"; +"TUIKitGroupTransferOwner" = "نقل ملكية المجموعة"; +"TUIKitGroupTransferOwnerSuccess" = "تم نقل ملكية المجموعة بنجاح"; + +"TUIKitGroupApplicant" = "طلبات الانضمام للمجموعة"; +"TUIKitGroupDismssTipsFormat" = "تم حل مجموعة %@"; +"TUIKitGroupRecycledTipsFormat" = "تم إعادة تدوير مجموعة %@"; +"TUIKitGroupKickOffTipsFormat" = "تم طردك من مجموعة %@"; +"TUIKitGroupDropoutTipsFormat" = "لقد قمت بالخروج من مجموعة %@"; + +"TUIKitMessageTipsYouRecallMessage" = "لقد قمت بسحب رسالة"; +"TUIKitMessageTipsReEditMessage" = "إعادة التحرير"; +"TUIKitMessageTipsRecallMessageFormat" = "\"%@\" قام بسحب رسالة"; +"TUIKitMessageTipsOthersRecallMessage" = "قام الطرف الآخر بسحب رسالة"; +"TUIKitMessageTipsJoinGroupFormat" = "\"%@\" انضم إلى المجموعة"; +"TUIKitMessageTipsInviteJoinGroupFormat" = "\"%@\" يدعو \"%@\" للانضمام إلى المجموعة"; +"TUIKitMessageTipsLeaveGroupFormat" = "\"%@\" غادر المجموعة"; +"TUIKitMessageTipsKickoffGroupFormat" = "\"%@\" يطرد \"%@\" من المجموعة"; +"TUIKitMessageTipsSettAdminFormat" = "\"%@\" تم تعيينه مديرًا للمجموعة"; +"TUIKitMessageTipsCancelAdminFormat" = "\"%@\" تم إزالة صلاحياته كمدير للمجموعة"; +"TUIkitMessageTipsEditGroupNameFormat" = "%@قام بتغيير اسم المجموعة إلى %@、"; +"TUIKitMessageTipsEditGroupIntroFormat" = "\"%@\" قام بتغيير وصف المجموعة إلى \"%@\"、"; +"TUIKitMessageTipsEditGroupAnnounceFormat" = "\"%@\" قام بتغيير إعلان المجموعة إلى \"%@\"、"; +"TUIKitMessageTipsDeleteGroupAnnounceFormat" = "\"%@\" قام بحذف إعلان المجموعة、"; +"TUIKitMessageTipsEditGroupAvatarFormat" = "\"%@\" قام بتغيير صورة المجموعة、"; +"TUIKitMessageTipsEditGroupOwnerFormat" = "\"%@\" قام بنقل ملكية المجموعة إلى \"%@\"、"; +"TUIKitMessageTipsCreateGroupFormat" = "\"%@\" قام بإنشاء مجموعة"; +"TUIKitMessageTipsUnsupportCustomMessage" = "[رسالة مخصصة غير مدعومة]"; + +"TUIKitMessageTipsMute" = "تم حظر الصوت"; +"TUIKitMessageTipsUnmute" = "تم إلغاء حظر الصوت"; + +"TUIKitSignalingFinishGroupChat" = "إنهاء المحادثة الجماعية"; +"TUIKitSignalingFinishConversationAndTimeFormat" = "مدة المكالمة"; +"TUIKitSignalingNewCall" = "بدء مكالمة"; +"TUIKitSignalingNewGroupCallFormat" = "%@ يبدأ مكالمة جماعية"; +"TUIkitSignalingCancelCall" = "إلغاء المكالمة"; +"TUIkitSignalingCancelGroupCallFormat" = "%@ يلغي المكالمة الجماعية"; +"TUIkitSignalingHangonCall" = "تم الرد"; +"TUIKitSignalingHangonCallFormat" = "%@ تم الرد عليه"; +"TUIKitSignalingBusyFormat" = "%@ مشغول"; +"TUIKitSignalingDeclineFormat" = "%@ يرفض المكالمة"; +"TUIKitSignalingCallBusy" = "الطرف الآخر مشغول"; +"TUIkitSignalingDecline" = "رفض المكالمة"; +"TUIKitSignalingNoResponse" = "لا يوجد رد"; +"TUIkitSignalingUnrecognlize" = "أمر المكالمة غير معروف"; +"TUIkitMessageTypeImage" = "[صورة]"; +"TUIKitMessageTypeVoice" = "[تسجيل صوتي]"; +"TUIkitMessageTypeVideo" = "[فيديو]"; +"TUIkitMessageTypeFile" = "[ملف]"; +"TUIKitMessageTypeAnimateEmoji" = "[رمز تعبيري متحرك]"; +"TUIKitMessageTypeDraftFormat" = "[مسودة] "; +"TUIKitMessageTypeLastMsgCountFormat" = "رسالة"; + +"TUIKitMessageReadPartRead" = "شخص قرأ"; +"TUIKitMessageReadPartUnread" = "غير مقروء"; +"TUIKitMessageReadPartDisable" = "بدون حالة"; +"TUIKitMessageReadAllRead" = "تمت القراءة بالكامل"; +"TUIKitMessageReadC2CRead" = "تمت القراءة"; +"TUIKitMessageReadC2CUnRead" = "لم يتم القراءة"; +"TUIKitMessageReadC2CUnReadDetail" = "لم يتم القراءة بعد"; +"TUIKitMessageReadDetail" = "تفاصيل الرسالة"; +"TUIKitMessageReadNoMoreData" = "لا توجد مزيد من البيانات"; +"TUIKitMessageReadGetReadMembersFail" = "فشل في الحصول على قائمة المستخدمين الذين قرأوا الرسالة"; +"TUIKitMessageReadGetUnreadMembersFail" = "فشل في الحصول على قائمة المستخدمين الذين لم يقروا الرسالة"; + +"TUIKitMoreCamera" = "التقاط صورة"; +"TUIKitMorePhoto" = "صورة"; +"TUIKitMoreVideo" = "تسجيل فيديو"; +"TUIKitMoreVideoCaptureDurationTip" = "مدة التسجيل قصيرة جدًا"; +"TUIKitMoreFile" = "ملف"; +"TUIKitMoreVideoCall" = "مكالمة فيديو"; +"TUIKitMoreVoiceCall" = "مكالمة صوتية"; +"TUIKitMoreLink" = "مخصص"; +"TUIKitMoreLinkDetails" = "عرض التفاصيل >>"; +"TUIKitMorePoll" = "استطلاع"; +"TUIKitMoreGroupNote" = "ملاحظة المجموعة"; + +"TUIKitCallInviteYouVideoCall" = "يدعوك لمكالمة فيديو"; +"TUIKitCallTurningOnMute" = "تشغيل الصوت"; +"TUIKitCallTurningOffMute" = "إيقاف الصوت"; +"TUIKitCallUsingSpeaker" = "استخدام مكبر الصوت"; +"TUIKitCallUsingHeadphone" = "استخدام سماعة الأذن"; +"TUIKitCallCancelCallingFormat" = "%@ قام بإلغاء المكالمة"; + +"TUIKitAtSelectMemberTitle" = "اختيار أعضاء المجموعة"; + +"TUIKitConversationTipsAtMe" = "[شخص ما @ لي]"; +"TUIKitConversationTipsAtAll" = "[@ الجميع]"; +"TUIKitConversationTipsAtMeAndAll" = "[شخص ما @ لي][@ الجميع]"; +"TUIKitConversationTipsDelete" = "سيتم حذف هذه المحادثة وجميع سجلات الدردشة المرتبطة بها"; + +"TUIKitPublicGroup" = "مجموعة عامة"; +"TUIKitWorkGroup" = "مجموعة عمل"; +"TUIKitChatRoom" = "غرفة دردشة"; +"TUIKitCommunity" = "مجتمع"; + +"TUIKitContactsNewFriends" = "جهات اتصال جديدة"; +"TUIKitContactsGroupChats" = "الدردشات الجماعية"; +"TUIKitContactsBlackList" = "القائمة السوداء"; +"TUIKitAddFriendSourceFormat" = "المصدر: %@"; +"TUIKitFriendApplicationApproved" = "تمت الموافقة على طلب الصداقة"; +"TUIKitFirendRequestRejected" = "تم رفض طلب الصداقة"; + +"TUIKitOfflinePushCallTips" = "لديك طلب مكالمة"; + +"TUIKitChatTap2Remove" = "انقر للحذف"; +"TUIKitChatPendencyTitle" = "انقر للمعالجة"; +"TUIKitChatPendencyRequestToJoinGroupFormat" = "%@ طلبات الانضمام إلى المجموعة"; +"TUIKitChatTipsAtMe" = "شخص ما @ لي"; +"TUIKitChatBackToLatestLocation" = "العودة إلى الموقع الأحدث"; +"TUIKitChatNewMessages" = "%@ رسالة جديدة"; + +"TUIKitAllowTypeAcceptOne" = "السماح لأي مستخدم بإضافة صديق"; +"TUIKitAllowTypeNeedConfirm" = "يتطلب التحقق"; +"TUIKitAllowTypeDeclineAll" = "رفض جميع طلبات الصداقة"; + +/***************************** 消息转发 & 消息搜索 *************************/ +// 补充 +"Multiple" = "متعدد"; +"Forward" = "إعادة توجيه"; +"Delete" = "حذف"; +"Copy" = "نسخ"; +"Revoke" = "إلغاء"; +"Resend" = "إعادة إرسال"; +"Search" = "بحث"; +"Recall" = "إلغاء"; +"MultiSelect" = "تحديد متعدد"; +"Quote" = "اقتباس"; + +"TUIKitCallMicCamAuthTips" = "يرجى تمكين إذن الوصول إلى الميكروفون والكاميرا"; +"TUIKitCallMicAuthTips" = "يرجى تمكين إذن الوصول إلى الميكروفون"; +"TUIKitMessageTipsSureToResend" = "هل أنت متأكد من إعادة إرسال الرسالة؟"; + +// 消息转发 +"TUIKitRelayNoMessageTips" = "يرجى تحديد الرسالة"; +"TUIKitRelayRecentMessages" = "الرسائل الأخيرة"; +"TUIKitRelayChatHistory" = "سجل الدردشة"; +"TUIKitRelaySepcialForbid" = "لا يمكن إعادة توجيه رسائل الصوت وغيرها من الرسائل الخاصة المحددة."; +"TUIKitRelayConfirmForward" = "هل أنت متأكد من إعادة التوجيه؟"; +"TUIKitRelayOneByOneForward" = "إعادة التوجيه بشكل فردي"; +"TUIKitRelayCombineForwad" = "دمج إعادة التوجيه"; +"TUIKitRelayGroupChatHistory" = "سجل الدردشة الجماعية"; +"TUIKitRelayChatHistoryForSomebodyFormat" = "سجل الدردشة لـ %@ و %@"; +"TUIKitRelayErrorForwardFormat" = "@فشل إعادة التوجيه، code:%d, desc:%@"; +"TUIKitRelayTargetCreateNewChat" = "إنشاء دردشة جديدة"; +"TUIKitRelayTargetCreateNewGroup" = "إنشاء مجموعة جديدة"; +"TUIKitRelayTargetSelectFromContacts" = "اختيار من جهات الاتصال"; +"TUIKitRelayTargetCrateGroupError" = "فشل إنشاء المجموعة"; +"TUIKitRelayTargetNoneTips" = "يرجى تحديد جهة اتصال أو محادثة"; +"TUIKitRelayLayerLimitTips" = "عذرًا، تجاوزت الحد المسموح به للتداخل الطبقي الحالي"; +"TUIKitRelayCompatibleText" = "لا يدعم إعادة توجيه الرسائل المدمجة، يرجى الترقية إلى أحدث إصدار."; +"TUIKitRelayUnsupportForward" = "لا يدعم إعادة توجيه الرسائل التي فشلت في الإرسال"; +"TUIKitRelayOneByOnyOverLimit" = "تم تجاوز الحد الأقصى لعدد رسائل إعادة التوجيه، لا يدعم حاليًا إعادة التوجيه بشكل فردي"; +"TUIKitRelayPluginNotAllowed" = "لا يدعم إعادة توجيه رسائل التصويت/التسلسل الزمني"; +// 消息搜索 +"TUIKitSearchItemHeaderTitleContact" = "جهات الاتصال"; +"TUIKitSearchItemFooterTitleContact" = "عرض المزيد من جهات الاتصال"; +"TUIKitSearchItemHeaderTitleGroup" = "الدردشات الجماعية"; +"TUIKitSearchItemFooterTitleGroup" = "عرض المزيد من الدردشات الجماعية"; +"TUIkitSearchItemHeaderTitleChatHistory" = "سجل الدردشة"; +"TUIKitSearchItemFooterTitleChatHistory" = "عرض المزيد من سجل الدردشة"; +"TUIKitSearchResultMatchFormat" = "يحتوي على: %@"; +"TUIKitSearchResultMatchGroupIDFormat" = "يحتوي على معرف المجموعة: %@"; +"TUIKitSearchResultMatchGroupMember" = "يحتوي على أعضاء المجموعة:"; +"TUIKitSearchResultDisplayChatHistoryCountFormat" = "%zd سجل دردشة"; +/***************************** 消息转发 & 消息搜索 *************************/ + + +/***************************** 消息回复 & 换肤 *************************/ +"Reply" = "الرد"; +"TUIKitReplyMessageNotFoundOriginMessage" = "تعذر تحديد الرسالة الأصلية"; +"TUIKitClearAllChatHistory" = "مسح سجل الدردشة بالكامل"; +"TUIKitClearAllChatHistoryTips" = "هل أنت متأكد من مسح سجل الدردشة بالكامل؟"; +"Discline" = "رفض"; +"Copied" = "تم النسخ"; +"ConfirmDeleteMessage" = "هل أنت متأكد من حذف الرسائل المحددة؟"; +"TUIKitAddFriend" = "إضافة صديق"; +"TUIKitAddGroup" = "إضافة مجموعة"; +"TUIKitSearchUserID" = "البحث عن معرف المستخدم"; +"TUIKitSearchGroupID" = "البحث عن معرف المجموعة"; +"TUIKitNoSelfSignature" = "لا يوجد توقيع شخصي حاليًا"; +"TUIKitSelfSignatureFormat" = "توقيع شخصي: %@";//fix me +"TUIKitGroupProfileManage" = "إدارة المجموعة"; +"TUIKitGroupManageShutupAllTips" = "عند تمكين الحظر الكلي للمستخدمين، سيتم السماح فقط للمالك والمشرفين بالتحدث."; +"TUIKitGroupManageAdminSetting" = "تعيين المشرفين"; +"TUIKitGroupManageShutAll" = "حظر الكل"; +"TUIKitGroupAddShutupMember" = "إضافة أعضاء المجموعة الذين يجب حظرهم"; +"TUIKitGroupOwner" = "مالك المجموعة"; +"TUIKitGroupManagerFormat" = "المشرفون (%zd/%zd)"; +"TUIKitSetShutupAllFormat" = "%@ تم تمكين الحظر الكلي للمستخدمين،"; +"TUIKitCancelShutupAllFormat" = "%@ تم إلغاء الحظر الكلي للمستخدمين،"; +"TUIKitGroupNotice" = "إعلان المجموعة"; +"TUIKitGroupNoticeNull" = "لا يوجد إعلان حاليًا"; +"Edit" = "تحرير"; +"Done" = "تم"; +"TUIKitAddContactMyUserIDFormat" = "معرف المستخدم الخاص بي: %@"; +"TUIKitAddUserNoDataTips" = "هذا المستخدم غير موجود"; +"TUIKitAddGroupNoDataTips" = "هذه الدردشة الجماعية غير موجودة"; +/***************************** 消息回复 & 换肤 *************************/ + + +/***************************** 视频、图片加载 & 保存 *************************/ +"TUIKitVideoTranscoding" = "جاري تحويل الفيديو..."; +"TUIKitVideoDownloading" = "جاري تحميل الفيديو..."; +"TUIKitVideoSavedSuccess" = "تم حفظ الفيديو بنجاح"; +"TUIKitVideoSavedFailed" = "فشل حفظ الفيديو"; +"TUIKitPictureSavedSuccess" = "تم حفظ الصورة بنجاح"; +"TUIKitPictureSavedFailed" = "فشل حفظ الصورة"; +/***************************** 视频、图片加载 & 保存 *************************/ + +"TUIKitGroupSetAdminsForbidden" = "لا يدعم الدردشة الجماعية الحالية إعداد المشرفين"; +"TUIKitGroupAddAdmins" = "إضافة مشرفين"; +"TUIKitGroupAddMemberOfBlockedForbidden" = "لا يدعم الدردشة الجماعية الحالية حظر أعضاء محددين"; + +"TUIKitNotDownload"= "لم يتم التنزيل بعد"; + +"TUIKitInputNoCameraTitle" = "لم يتم تمكين إذن الكاميرا"; +"TUIKitInputNoCameraTips" = "لا يمكن استخدام ميزات التقاط الصور والفيديو والمكالمات الفيديو، انقر على (الذهاب للتمكين) لفتح إذن الكاميرا"; +"TUIKitInputNoCameraOperateLater" = "لاحقًا"; +"TUIKitInputNoCameraOperateEnable" = "الذهاب للتمكين"; + +"TUIKitInputNoMicTitle" = "لم يتم تمكين إذن الميكروفون"; +"TUIKitInputNoMicTips" = "لا يمكن استخدام ميزات إرسال رسائل الصوت والتقاط الفيديو والمكالمات الصوتية والفيديو، انقر على (الذهاب للتمكين) لفتح إذن الميكروفون"; +"TUIKitInputNoMicOperateLater" = "لاحقًا"; +"TUIKitInputNoMicOperateEnable" = "الذهاب للتمكين"; + +"TUIKitInputNoPhotoTitle" = "لم يتم تمكين إذن الصور"; +"TUIKitInputNoPhotoTips" = "لا يمكن استخدام ميزات عرض الصور واختيارها في ميزات الدردشة، انقر على (الذهاب للتمكين) لفتح إذن الصور"; +"TUIKitInputNoPhotoOperateLater" = "لاحقًا"; +"TUIKitInputNoPhotoerateEnable" = "الذهاب للتمكين"; + +"TUIKitInputRecordTipsTitle" = "قم بتحرير الإصدار لإرساله، اسحب لليسار للإلغاء"; +"TUIKitInputRecordCancelTipsTitle" = "تم إلغاء الإصدار"; +"TUIKitInputRecordRejectedInCall" = "جاري المكالمة الصوتية أو الفيديو، يرجى المحاولة لاحقًا"; +"TUIKitInputRecordRejectedIsRecording" = "جاري التسجيل الصوتي، يرجى الانتظار حتى ينتهي"; + +"StickyonTop" = "تثبيت في الأعلى"; +"CancelStickonTop" = "إلغاء التثبيت في الأعلى"; +"ClearHistoryChatMessage" = "مسح الرسائل"; +"MarkAsRead" = "وضع علامة كمقروءة"; +"MarkAsUnRead" = "وضع علامة كغير مقروءة"; +"MarkHide" = "إخفاء"; +"MinimizeGroup" = "طي الدردشة"; +"More" = "المزيد"; +"Info" = "معلومات"; + +"TUIKitConversationMarkHide" = "إخفاء الدردشة"; +"TUIKitConversationMarkHideDescriptionOn" = "عند التمكين، لن تظهر هذه الدردشة في قائمة الدردشات، وسيتم الاحتفاظ بسجل الدردشة."; +"TUIKitConversationMarkHideDescriptionOff" = "عند التعطيل، ستظهر هذه الدردشة في قائمة الدردشات، وسيتم الاحتفاظ بسجل الدردشة."; + +"TUIKitConversationMarkFoldGroups" = "مجموعات الدردشة المطوية"; +"TUIKitConversationMarkFold" = "طي هذه المجموعة"; + +"TUIKitRepliesDetailTitle" = "تفاصيل الرد"; +"TUIKitRepliesNum" = "ردود"; +"TUIKitReference" = "المرجع"; +"TUIKitNotSupportThisMessage" = "[لا يتم دعم عرض هذه الرسالة مؤقتًا]"; + +"TUIKitAudioPlaybackStyleLoudspeaker" = "مكبر الصوت"; +"TUIKitAudioPlaybackStyleHandset" = "سماعة الهاتف"; +"TUIKitAudioPlaybackStyleChange2Loudspeaker" = "التبديل إلى تشغيل الصوت عبر مكبر الصوت"; +"TUIKitAudioPlaybackStyleChange2Handset" = "التبديل إلى تشغيل الصوت عبر سماعة الهاتف"; + +"TUIKitTranslate" = "ترجمة"; +"TUIKitTranslateDefaultTips" = "تقدم خدمة الترجمة بواسطة Tencent Cloud IM"; +"TUIKitTranslateFailed" = "فشل الترجمة"; +"Hide" = "إخفاء"; +"TranslateMessage" = "ترجمة الرسالة إلى"; +"TranslateLanguageNotSupport" = "اللغة المستهدفة غير مدعومة، يرجى تغيير اللغة"; + +"TUIKitConvertToText" = "تحويل النص"; +"TUIKitConvertToTextFailed" = "فشل تحويل"; + +"TUIKitSignalingSwitchToAudio" = "تحويل الفيديو إلى صوت"; +"TUIKitSignalingUnsupportedCalling" = "دعوة غير معروفة"; +"TUIKitSignalingComfirmSwitchToAudio" = "تأكيد التحويل إلى صوت"; + +"TUIKitErrorEnableUserStatusOnConsole" = "لم تقم بتمكين ميزة حالة المستخدم، يرجى تسجيل الدخول إلى لوحة التحكم وتمكينها"; + +"TUIKitChooseAvatar" = "اختيار الصورة الرمزية"; +"TUIKitChooseCover" = "اختيار الغلاف"; +"TUIKitChooseBackground" = "تغيير الخلفية"; +"TUIKitDefaultBackground" = "الخلفية الافتراضية"; +"TUIKitIdentity" = "المعرف"; + +"TUIKitChooseBackgroundSuccess" = "تم التعيين بنجاح!"; +"TUIKitChooseBackgroundFailed" = "فشل التعيين!"; + +"TUIKitContactNoNewApplicationRequest" = "لا توجد طلبات صداقة جديدة حاليًا"; +"TUIKitContactNoGroupChats" = "لا توجد محادثات جماعية حاليًا"; +"TUIKitContactNoBlockList" = "لا توجد أشخاص في قائمة الحظر حاليًا"; +"TUIKitSearchNoResultLists" = "لا توجد نتائج متعلقة بالمحادثات أو جهات الاتصال أو سجل الرسائل"; +"TUIKitTyping" = "الشخص الآخر يكتب حاليًا"; + +"TUIKitMessageTipsEditGroupAddOptFormat" = "\"%@\" قام بتعديل طريقة الانضمام إلى المجموعة إلى \"%@\"、"; +"TUIKitMessageTipsEditGroupInviteOptFormat" = "\"%@\" قام بتعديل طريقة الدعوة إلى المجموعة إلى \"%@\"、"; + +"TUIKitCreatGroupNamed" = "اسم المجموعة"; +"TUIKitCreatGroupID" = "معرف المجموعة (اختياري)"; +"TUIKitCreatGroupNamed_Placeholder" = "أدخل اسم المجموعة"; +"TUIKitCreatGroupID_Placeholder" = "أدخل معرف المجموعة"; +"TUIKitCreatGroupAvatar" = "صورة المجموعة"; +"TUIKitCreatGroupType" = "نوع المجموعة"; +"TUIKitCreatGroupType_Work" = "مجموعة عمل للأصدقاء (Work)"; +"TUIKitCreatGroupType_Public" = "مجموعة تواصل مع غرباء (Public)"; +"TUIKitCreatGroupType_Meeting" = "مجموعة اجتماع مؤقتة (Meeting)"; +"TUIKitCreatGroupType_Community" = "مجموعة مجتمع (Community)"; +"TUIKitCreatGroupType_Work_Desc" = "مجموعة عمل للأصدقاء (Work): تشبه مجموعات الدردشة العادية في تطبيق WeChat، بعد الإنشاء، يمكن للأصدقاء الموجودين في المجموعة دعوة أصدقاء آخرين للانضمام دون الحاجة لموافقة المدعو أو موافقة صاحب المجموعة."; +"TUIKitCreatGroupType_Public_Desc" = "مجموعة تواصل مع غرباء (Public): تشبه مجموعات QQ، بعد الإنشاء، يمكن لصاحب المجموعة تعيين مشرفين للمجموعة، عندما يقوم المستخدم بالبحث عن معرف المجموعة ويقدم طلب الانضمام، يحتاج إلى موافقة صاحب المجموعة أو المشرفين قبل الانضمام إلى المجموعة."; +"TUIKitCreatGroupType_Meeting_Desc" = "مجموعة اجتماع مؤقتة (Meeting): بعد الإنشاء، يمكن للمستخدمين الانضمام والخروج بحرية، ويدعم عرض الرسائل قبل الانضمام؛ مناسبة لسيناريوهات المؤتمرات الصوتية والمرئية وسيناريوهات التعليم عبر الإنترنت وغيرها من السيناريوهات التي تجمع بين منتجات الصوت والفيديو الفورية."; +"TUIKitCreatGroupType_Community_Desc" = "مجموعة مجتمع (Community): بعد الإنشاء، يمكن للمستخدمين الانضمام والخروج بحرية، وتدعم ما يصل إلى 100000 شخص، وتدعم تخزين الرسائل التاريخية، عندما يقوم المستخدم بالبحث عن معرف المجموعة ويقدم طلب الانضمام، لا يحتاج إلى موافقة المشرفين للانضمام إلى المجموعة."; +"TUIKitCreatGroupType_See_Doc" = "انظر الوثائق المنتج"; +"TUIKitCreatGroupType_Desc_Highlight" = "وثائق المنتج"; +"TUIKitCreatGroupType_See_Doc_Simple" = "عرض وثائق المنتج"; +"TUIKitSearchItemCancel" = "إلغاء"; + +//----mini--- +"Pin" = "تثبيت"; +"UnPin" = "إلغاء التثبيت"; +"TUIKitSelected" = "تم تحديدها"; +"TUIKitThreadQuote" = "ردود"; +"MessageInfo" = "تفاصيل الرسالة"; +"C2CReadBy" = "تمت القراءة"; +"C2CDeliveredTo" = "لم يتم القراءة"; +"GroupReadBy" = "قائمة المقروءة"; +"GroupDeliveredTo" = "قائمة الغير مقروءة"; +"TUIKitMessage" = "إرسال رسالة"; +"TUIKitAudio" = "مكالمة صوتية"; +"TUIKitVideo" = "مكالمة فيديو"; +"TUIKitAddMembers" = "+ إضافة أعضاء"; +"TUIKitMembersRoleMember" = "عضو"; +"TUIKitMembersRoleAdmin" = "مشرف"; +"TUIKitMembersRoleSuper" = "مالك المجموعة"; +"TUIKitCreateCancel" = "إلغاء"; +"TUIKitCreateNext" = "التالي"; +"TUIKitCreateFinish" = "إنشاء"; +"TUIKitCreateMemebers" = "الأعضاء المحددين"; +"TUIKitDateToday" = "اليوم"; +//----mini--- + +"TUIPollCreateNew" = "إنشاء استطلاع"; +"TUIPollCreateSucceed" = "تم الإنشاء بنجاح"; +"TUIPollCreateFail" = "فشل الإنشاء"; +"TUIPollEnterTitle" = "أدخل عنوان الاستطلاع"; +"TUIPollEnterOption" = "أدخل الخيار"; +"TUIPollAddOption" = "إضافة خيار"; +"TUIPollEnableMultiSelect" = "السماح بالتحديد المتعدد"; +"TUIPollSingleSelect" = "اختيار واحد"; +"TUIPollMultiSelect" = "اختيار متعدد"; +"TUIPollAnonymousVote" = "التصويت المجهول"; +"TUIPollPublic" = "نتائج عامة"; +"TUIPollNonPublic" = "نتائج غير عامة"; +"TUIPollNonAnonymous" = "غير مجهول"; +"TUIPollAnonymous" = "مجهول"; +"TUIPollEnableNotification" = "إرسال إشعار عند تقديم جديد في المجموعة"; +"TUIPolllPublish" = "نشر"; +"TUIPollOneCount" = "صوت"; +"TUIPollMoreCount" = "أصوات"; +"TUIPollInvitedParticipants" = "عدد المشاركين المطلوبين: %d"; +"TUIPollRespondedParticipants" = "عدد المشاركين الفعليين: %d"; +"TUIPollResend" = "إعادة الإرسال"; +"TUIPollResendFail" = "فشل إعادة الإرسال، رمز الخطأ: %d"; +"TUIPollEnd" = "إنهاء الاستطلاع"; +"TUIPollEndFail" = "فشل إنهاء الاستطلاع، رمز الخطأ: %d"; +"TUIPollVoteNow" = "التصويت الآن"; +"TUIPollConfirmVote" = "تأكيد"; +"TUIPollCancelVote" = "إلغاء"; +"TUIPollPercent" = "تم التصويت بـ %d صوت، يشكل %.0f";//fix me +"TUIPollEnded" = "انتهت الاستطلاع"; +"TUIPollVoteSucceed" = "تم التصويت بنجاح"; +"TUIPollVoteFail" = "فشل التصويت"; +"TUIPollPublicResult" = "نتائج عامة"; +"TUIPollViewAllOptions" = "عرض جميع الخيارات"; +"TUIPollDisplayString" = "[استطلاع]"; +"TUIPollTextFieldExceedLimit" = "تجاوز الحد الأقصى لعدد الأحرف (50)"; +"TUIPollVoted" = "تم التصويت"; +"TUIPoll" = "استطلاع"; +"TUIGroupNote" = "التوالي"; +"TUIGroupNoteTitle" = "التوالي الجماعي"; +"TUIGroupNoteSettings" = "الإعدادات"; +"TUIGroupNoteDeadline" = "الموعد النهائي %@"; +"TUIGroupNoteTitleHint" = "إضافة عنوان التوالي"; +"TUIGroupNoteDescriptionHint" = "إضافة وصف التوالي"; +"TUIGroupNoteFormatExample" = "مثال"; +"TUIGroupNoteFormatHint" = "يمكنك ملء تنسيق التوالي"; +"TUIGroupNoteFillIn" = "يرجى ملء"; +"TUIGroupNoteMultipleSettings" = "السماح بتقديم عدة نسخ لكل شخص"; +"TUIGroupNoteDeadlineSettings" = "تعيين الموعد النهائي"; +"TUIGroupNoteDeadlineNotSet" = "غير محدد"; +"TUIGroupNoteNotifySettings" = "إرسال إشعار في المجموعة عند تقديم جديد"; +"TUIGroupNoteSend" = "إرسال"; +"TUIGroupNoteNow" = "التوالي الفوري"; +"TUIGroupNoteMessageTitle" = "التوالي الجماعي"; +"TUIGroupNoteMessageTitleInfo" = "تم إطلاقها بواسطة %@، وقد انضم %d شخصًا"; +"TUIGroupNoteTipsMessagePrefix" = "انضم %@ إلى التوالي الجماعي"; +"TUIGroupNoteHasStopped" = "تم إيقاف التوالي"; +"TUIGroupNoteDeadlineMustBeLater" = "يجب أن يكون الموعد النهائي لاحقًا من الوقت الحالي"; +"TUIGroupNoteDisplayString" = "[التوالي الجماعي]"; +"TUIGroupNoteSendSucceed" = "تم الإرسال بنجاح"; +"TUIGroupNoteSendFail" = "فشل الإرسال"; +"TUIGroupNoteSubmitExceedLimit" = "تجاوز الحد الأقصى لعدد التواليات"; +"TUIGroupNoteTextFieldExceedLimit" = "تجاوز الحد الأقصى لعدد الأحرف 50"; +"TUIGroupNoteSubmitOnce" = "يُسمح بتقديم مرة واحدة فقط"; +"TUIGroupNoteSubmitNotAllowed" = "غير مسموح بالتقديم"; +"TUIGroupNoteExceedDeadline" = "تجاوز الموعد النهائي، تم إيقاف التوالي"; +"TUIGroupNoteNotChanged" = "لم يتغير معلومات التوالي"; +"TUIGroupNoteExpand" = "...عرض المزيد..."; +"TUIGroupNoteNotDatePickerConfirm" = "تأكيد"; +"TUIGroupNoteNotDatePickerCancel" = "إلغاء"; +"TUIGroupNoteNotDatePickerDone" = "تم"; +"TUIGroupNoteNotDatePickerYear" = " سنة"; +"TUIGroupNoteNotDatePickerMonth" = " شهر"; +"TUIGroupNoteNotDatePickerDay" = " يوم"; +"TUIGroupNoteNotDatePickerHour" = " ساعة"; +"TUIGroupNoteNotDatePickerMinute" = " دقيقة"; +"TUIGroupNoteNotDatePickerSecond" = " ثانية"; +"TUIGroupNoteNotDatePickerAM" = "صباحًا"; +"TUIGroupNoteNotDatePickerPM" = "مساءً"; +"TUIGroupNoteNotDatePickerNow" = " حتى الآن"; +"TUIGroupNoteNotDatePickerToday" = " اليوم"; +"TUIGroupNoteNotDatePickerMon" = " الاثنين"; +"TUIGroupNoteNotDatePickerTue" = " الثلاثاء"; +"TUIGroupNoteNotDatePickerWed" = " الأربعاء"; +"TUIGroupNoteNotDatePickerTHR" = " الخميس"; +"TUIGroupNoteNotDatePickerFRI" = " الجمعة"; +"TUIGroupNoteNotDatePickerSAT" = " السبت"; +"TUIGroupNoteNotDatePickerSUN" = " الأحد"; +"TUIConversationGroupAll" = "الكل"; +"TUIConversationGroupUnread" = "غير مقروءة"; +"TUIConversationGroupAtMe" = "@ لي"; +"TUIConversationGroupGroup" = "مجموعة"; +"TUIConversationGroupC2C" = "دردشة فردية"; +"TUIConversationGroupInputGroupName" = "يرجى إدخال اسم المجموعة"; +"TUIConversationGroupCreateGroup" = "إنشاء مجموعة المحادثة"; +"TUIConversationGroupNewGroup" = "مجموعة جديدة"; +"TUIConversationGroupAddGroup" = "إضافة مجموعة"; +"TUIConversationGroupMoveGroup" = "نقل المجموعة"; +"TUIConversationGroupRemoveGroup" = "إزالة المجموعة"; +"TUIConversationGroupShowGroup" = "عرض مجموعة المحادثة"; +"TUIConversationGroupHideGroup" = "إخفاء مجموعة المحادثة"; +"TUIConversationGroupEditGroup" = "إعدادات مجموعة المحادثة"; +"TUIConversationGroupEdit" = "تعديل"; +"TUIConversationGroupSave" = "حفظ"; +"TUIConversationGroupSaveSucc" = "تم حفظ المجموعة بنجاح"; +"TUIConversationGroupCreate" = "إنشاء"; +"TUIConversationGroupNameIsNull" = "اسم المجموعة لا يمكن أن يكون فارغًا!"; +"TUIConversationGroupNameIsInvalid" = "اسم المجموعة لا يمكن أن يكون اسمًا محددًا مسبقًا"; +"TUIConversationGroupConversationIsNull" = "المحادثة لا يمكن أن تكون فارغة!"; +"TUIConversationGroupCreateSucc" = "تم إنشاء المجموعة بنجاح"; +"TUIConversationGroupModifySucc" = "تم تعديل المجموعة بنجاح"; +"TUIConversationGroupName" = "اسم المجموعة"; +"TUIConversationGroupIncludeConversation" = "تضمين المحادثة"; +"TUIConversationGroupAddConversation" = "إضافة محادثة"; +"TUIConversationGroup" = "مجموعة المحادثة"; +"TUIConversationGroupManager" = "المدير"; +"TUIConversationGroupSelectGroup" = "اختر مجموعة المحادثة"; +"TUIConversationGroupUnlogined" = "غير مسجل الدخول، فشل الحفظ!"; +"TUIConversationMark" = "وضع علامة"; +"TUIConversationMarkCancel" = "إلغاء العلامة"; + +"TUIConversationNone" = "لا يوجد أي محادثات لـ %@"; + +//----timApp--- +"TIMAppMainTitle" = "تينسنت كلاود · IM"; +"TIMAppMainConnectingTitle" = "جاري الاتصال..."; +"TIMAppMainDisconnectTitle" = "تينسنت كلاود · IM (غير متصل)"; +"TIMAppTabBarItemMessageText" = "الرسائل"; +"TIMAppTabBarItemContactText" = "جهات الاتصال"; +"TIMAppTabBarItemMeText" = "أنا"; +"TIMAppTabBarItemMessageText_mini" = "الدردشة"; +"TIMAppTabBarItemContactText_mini" = "جهات الاتصال"; +"TIMAppTabBarItemSettingText_mini" = "الإعدادات"; +"TIMAppTabBarItemCallsRecordText_mini" = "سجل المكالمات"; +"TIMAppChat" = "الدردشة"; +"TIMAppChatDisconnectTitle" = "الدردشة (غير متصل)"; +"TIMAppChatSecurityWarning" = "【تحذير أمان】تستخدم هذه التطبيقات فقط لتجربة وظائف منتج تينسنت كلاود للاتصال الفوري. يجب عدم استخدامها للتفاوض التجاري والتوسع. يرجى عدم الوثوق بمعلومات تتعلق بالمدفوعات والفوز بجوائز وغيرها من المعلومات المتعلقة بالمال. يرجى عدم الاتصال بأرقام الهواتف الغريبة بسهولة وتوخي الحذر لتجنب الوقوع في الاحتيال."; +"TIMAppChatSecurityWarningReport" = "النقر هنا للإبلاغ"; +"TIMAppTencentCloudIM" = "الاتصال الفوري"; +"TIMAppWelcomeToChat" = "مرحبًا بك في استخدام هذا التطبيق لتجربة خدمة الاتصال الفوري من تينسنت كلاود IM"; + +"TIMAppWelcomeToChatDetails" = "مرحبًا بك في استخدام هذا التطبيق لتجربة خدمة الاتصال الفوري من تينسنت كلاود IM. يمكنك استخدامه لإرسال الرسائل النصية والرموز التعبيرية والرسائل الغنية بالوسائط والرد على الرسائل والردود بالرموز التعبيرية وحالة قراءة الرسائل وعلاقات الأصدقاء وغيرها من الوظائف. في الوقت نفسه، قمنا بتوفير 3 أصدقاء آليين لك لا يمكنهم الرد، يمكنك بدء محادثة فردية أو محادثة جماعية معهم وتجربة إدارة المجموعات وغيرها من الوظائف."; +"TIMAppSelectStyle" = "اختيار النمط"; +"TIMAppChatStyles" = "تبديل نمط IM الحصري"; +"TIMAppChangeTheme" = "اختيار السمة"; +"TIMAppChatThemes" = "تبديل سمة IM الحصرية"; +"TIMAppEnterChat" = "دخول IM"; + +"TIMAppRunDemo" = "تشغيل العرض التوضيحي في دقيقة واحدة بتغيير سطرين من الشفرة"; +"TIMAppCustomers" = "أكثر من 10000 عميل يخدمون شهريًا"; +"TIMAppMessagingSuccess" = "معدل نجاح إرسال واستلام الرسائل وموثوقية الخدمة أعلى من 99.99٪"; +"TIMAppActiveUsers" = "أكثر من مليار مستخدم نشط شهريًا"; +"TIMAppOK" = "موافق"; +"TIMApp1Billion+" = "أكثر من مليار"; +"TIMApp10000+" = "أكثر من 10000"; +"TIMApp1Minute" = "دقيقة واحدة"; +"TIMAppMeAbout" = "حول تينسنت كلاود · IM"; +"TIMAppConfirmLogout" = "هل أنت متأكد من تسجيل الخروج؟"; +"TIMAppConfirm" = "تأكيد"; +"TIMAppCancel" = "إلغاء"; +"TIMChangeLanguage" = "تغيير اللغة"; +//----timApp--- +"TUIKitTickledMe" = "أنا"; +"TUIKitTickledActionVaule" = "طبقة"; +"TUIKitTickledMyself" = "نفسي"; +"TUIKitImageViewOrigin" = "عرض الصورة الأصلية"; +"TUIGroupCreateTipsMessage" = "إنشاء مجموعة"; +"TUICommunityCreateTipsMessage" = "إنشاء مجتمع"; + +"zh-Hans" = "الصينية المبسطة"; +"en" = "إنجليزي"; +"ar" = "عربي"; + diff --git a/iOS/TUIKit/TIMCommon/Resources/TIMCommonLocalizable.bundle/Localizable/en.lproj/Localizable.strings b/iOS/TUIKit/TIMCommon/Resources/TIMCommonLocalizable.bundle/Localizable/en.lproj/Localizable.strings index 96d389a64..bc82bbe83 100644 --- a/iOS/TUIKit/TIMCommon/Resources/TIMCommonLocalizable.bundle/Localizable/en.lproj/Localizable.strings +++ b/iOS/TUIKit/TIMCommon/Resources/TIMCommonLocalizable.bundle/Localizable/en.lproj/Localizable.strings @@ -240,7 +240,7 @@ "TUIKitMessageTipsUnmute" = "unblocked"; "TUIKitSignalingFinishGroupChat" = "End Group Chat"; -"TUIKitSignalingFinishConversationAndTimeFormat" = "Duration: %.2d:%.2d."; +"TUIKitSignalingFinishConversationAndTimeFormat" = "Duration"; "TUIKitSignalingNewCall" = "Start Call"; "TUIKitSignalingNewGroupCallFormat" = "\"%@\" initiated a group call."; "TUIkitSignalingCancelCall" = "Cancel Call"; @@ -476,6 +476,11 @@ "TUIKitReference" = "reference"; "TUIKitNotSupportThisMessage" = "[This message display is not currently supported]"; +"TUIKitAudioPlaybackStyleLoudspeaker" = "Loudspeaker"; +"TUIKitAudioPlaybackStyleHandset" = "Handset"; +"TUIKitAudioPlaybackStyleChange2Loudspeaker" = "Switch To Loudspeaker"; +"TUIKitAudioPlaybackStyleChange2Handset" = "Switch To Handset"; + "TUIKitTranslate" = "Translate"; "TUIKitTranslateDefaultTips" = "Translated by IM"; "TUIKitTranslateFailed" = "Unable to translate"; @@ -483,6 +488,9 @@ "TranslateMessage" = "Translate message to language"; "TranslateLanguageNotSupport" = "Translation is not supported between current languages, please switch to another language."; +"TUIKitConvertToText" = "Convert\nto Text"; +"TUIKitConvertToTextFailed" = "Unable to convert"; + "TUIKitSignalingSwitchToAudio" = "Switch to voice call"; "TUIKitSignalingUnsupportedCalling" = "Unknown invitation"; "TUIKitSignalingComfirmSwitchToAudio" = "Comfirm video to voice"; @@ -493,6 +501,7 @@ "TUIKitChooseCover" = "Choose a cover"; "TUIKitChooseBackground" = "Choose a Wallpaper"; "TUIKitDefaultBackground" = "Default background"; +"TUIKitIdentity" = "ID"; "TUIKitChooseBackgroundSuccess" = "Setup Success!"; "TUIKitChooseBackgroundFailed" = "Setup failed!"; @@ -710,7 +719,10 @@ "TIMAppConfirmLogout" = "Leave now?"; "TIMAppConfirm" = "OK"; "TIMAppCancel" = "Cancel"; +"TIMAppMarkAllMessageAsReadSucc" = "Success to mark all as read"; +"TIMAppMarkAllMessageAsReadErrFormat" = "Error, %d, %@"; "TIMChangeLanguage" = "Language"; + //----timApp--- "TUIKitTickledMe" = "I"; "TUIKitTickledActionVaule" = " tickled "; @@ -718,3 +730,6 @@ "TUIKitImageViewOrigin" = "Original image"; "TUIGroupCreateTipsMessage" = "Create Group"; "TUICommunityCreateTipsMessage" = "Create Community"; +"zh-Hans" = "Simple Chinese"; +"en" = "English"; +"ar" = "Arabic"; diff --git a/iOS/TUIKit/TIMCommon/Resources/TIMCommonLocalizable.bundle/Localizable/zh-Hans.lproj/Localizable.strings b/iOS/TUIKit/TIMCommon/Resources/TIMCommonLocalizable.bundle/Localizable/zh-Hans.lproj/Localizable.strings index cdc668d5b..8b81c9993 100644 --- a/iOS/TUIKit/TIMCommon/Resources/TIMCommonLocalizable.bundle/Localizable/zh-Hans.lproj/Localizable.strings +++ b/iOS/TUIKit/TIMCommon/Resources/TIMCommonLocalizable.bundle/Localizable/zh-Hans.lproj/Localizable.strings @@ -245,7 +245,7 @@ "TUIKitMessageTipsUnmute" = "被解除禁言"; "TUIKitSignalingFinishGroupChat" = "结束群聊"; -"TUIKitSignalingFinishConversationAndTimeFormat" = "通话时长:%.2d:%.2d"; +"TUIKitSignalingFinishConversationAndTimeFormat" = "通话时长"; "TUIKitSignalingNewCall" = "发起通话"; "TUIKitSignalingNewGroupCallFormat" = "\"%@\" 发起群通话"; "TUIkitSignalingCancelCall" = "取消通话"; @@ -473,6 +473,11 @@ "TUIKitReference" = "引用"; "TUIKitNotSupportThisMessage" = "[暂时不支持该消息展示]"; +"TUIKitAudioPlaybackStyleLoudspeaker" = "扬声器"; +"TUIKitAudioPlaybackStyleHandset" = "听筒"; +"TUIKitAudioPlaybackStyleChange2Loudspeaker" = "切换至扬声器播放"; +"TUIKitAudioPlaybackStyleChange2Handset" = "切换至听筒播放"; + "TUIKitTranslate" = "翻译"; "TUIKitTranslateDefaultTips" = "由腾讯云 IM 提供翻译支持"; "TUIKitTranslateFailed" = "翻译失败"; @@ -480,6 +485,9 @@ "TranslateMessage" = "将消息翻译为"; "TranslateLanguageNotSupport" = "当前翻译语言不支持,请切换至其他语言"; +"TUIKitConvertToText" = "转文字"; +"TUIKitConvertToTextFailed" = "转换失败"; + "TUIKitSignalingSwitchToAudio" = "视频转语音"; "TUIKitSignalingUnsupportedCalling" = "未知邀请"; "TUIKitSignalingComfirmSwitchToAudio" = "确认转语音"; @@ -490,6 +498,7 @@ "TUIKitChooseCover" = "选择封面"; "TUIKitChooseBackground" = "更换背景"; "TUIKitDefaultBackground" = "默认背景"; +"TUIKitIdentity" = "ID"; "TUIKitChooseBackgroundSuccess" = "设置成功!"; "TUIKitChooseBackgroundFailed" = "设置失败!"; @@ -706,7 +715,10 @@ "TIMAppConfirmLogout" = "确定退出吗"; "TIMAppConfirm" = "确定"; "TIMAppCancel" = "取消"; +"TIMAppMarkAllMessageAsReadSucc" = "清空未读成功"; +"TIMAppMarkAllMessageAsReadErrFormat" = "清空未读失败, %d, %@"; "TIMChangeLanguage" = "切换语言"; + //----timApp--- "TUIKitTickledMe" = "我"; "TUIKitTickledActionVaule" = "拍了拍"; @@ -714,3 +726,7 @@ "TUIKitImageViewOrigin" = "查看原图"; "TUIGroupCreateTipsMessage" = "创建群组"; "TUICommunityCreateTipsMessage" = "创建社群"; + +"zh-Hans" = "简体中文"; +"en" = "英语"; +"ar" = "阿拉伯语"; diff --git a/iOS/TUIKit/TIMCommon/Resources/TIMCommonTheme.bundle/dark/resource/bg.png b/iOS/TUIKit/TIMCommon/Resources/TIMCommonTheme.bundle/dark/resource/bg.png index 7077009d5..a4d07d07a 100644 Binary files a/iOS/TUIKit/TIMCommon/Resources/TIMCommonTheme.bundle/dark/resource/bg.png and b/iOS/TUIKit/TIMCommon/Resources/TIMCommonTheme.bundle/dark/resource/bg.png differ diff --git a/iOS/TUIKit/TIMCommon/Resources/TIMCommonTheme.bundle/dark/resource/default_group_head@2x.png b/iOS/TUIKit/TIMCommon/Resources/TIMCommonTheme.bundle/dark/resource/default_group_head@2x.png index 3af28307b..dfadf82bd 100644 Binary files a/iOS/TUIKit/TIMCommon/Resources/TIMCommonTheme.bundle/dark/resource/default_group_head@2x.png and b/iOS/TUIKit/TIMCommon/Resources/TIMCommonTheme.bundle/dark/resource/default_group_head@2x.png differ diff --git a/iOS/TUIKit/TIMCommon/Resources/TIMCommonTheme.bundle/dark/resource/default_group_head_avchatroom@2x.png b/iOS/TUIKit/TIMCommon/Resources/TIMCommonTheme.bundle/dark/resource/default_group_head_avchatroom@2x.png index 89c9f977e..b2f614ac6 100644 Binary files a/iOS/TUIKit/TIMCommon/Resources/TIMCommonTheme.bundle/dark/resource/default_group_head_avchatroom@2x.png and b/iOS/TUIKit/TIMCommon/Resources/TIMCommonTheme.bundle/dark/resource/default_group_head_avchatroom@2x.png differ diff --git a/iOS/TUIKit/TIMCommon/Resources/TIMCommonTheme.bundle/dark/resource/default_group_head_community@2x.png b/iOS/TUIKit/TIMCommon/Resources/TIMCommonTheme.bundle/dark/resource/default_group_head_community@2x.png index dc0277ffe..7f3c9bfd5 100644 Binary files a/iOS/TUIKit/TIMCommon/Resources/TIMCommonTheme.bundle/dark/resource/default_group_head_community@2x.png and b/iOS/TUIKit/TIMCommon/Resources/TIMCommonTheme.bundle/dark/resource/default_group_head_community@2x.png differ diff --git a/iOS/TUIKit/TIMCommon/Resources/TIMCommonTheme.bundle/dark/resource/default_group_head_meeting@2x.png b/iOS/TUIKit/TIMCommon/Resources/TIMCommonTheme.bundle/dark/resource/default_group_head_meeting@2x.png index 79c65c94b..b7b14c61a 100644 Binary files a/iOS/TUIKit/TIMCommon/Resources/TIMCommonTheme.bundle/dark/resource/default_group_head_meeting@2x.png and b/iOS/TUIKit/TIMCommon/Resources/TIMCommonTheme.bundle/dark/resource/default_group_head_meeting@2x.png differ diff --git a/iOS/TUIKit/TIMCommon/Resources/TIMCommonTheme.bundle/dark/resource/default_group_head_public@2x.png b/iOS/TUIKit/TIMCommon/Resources/TIMCommonTheme.bundle/dark/resource/default_group_head_public@2x.png index 631ad4923..309f128e9 100644 Binary files a/iOS/TUIKit/TIMCommon/Resources/TIMCommonTheme.bundle/dark/resource/default_group_head_public@2x.png and b/iOS/TUIKit/TIMCommon/Resources/TIMCommonTheme.bundle/dark/resource/default_group_head_public@2x.png differ diff --git a/iOS/TUIKit/TIMCommon/Resources/TIMCommonTheme.bundle/dark/resource/icon_offline_status@2x.png b/iOS/TUIKit/TIMCommon/Resources/TIMCommonTheme.bundle/dark/resource/icon_offline_status@2x.png index e5f4fbf12..77b382afd 100644 Binary files a/iOS/TUIKit/TIMCommon/Resources/TIMCommonTheme.bundle/dark/resource/icon_offline_status@2x.png and b/iOS/TUIKit/TIMCommon/Resources/TIMCommonTheme.bundle/dark/resource/icon_offline_status@2x.png differ diff --git a/iOS/TUIKit/TIMCommon/Resources/TIMCommonTheme.bundle/dark/resource/icon_offline_status@3x.png b/iOS/TUIKit/TIMCommon/Resources/TIMCommonTheme.bundle/dark/resource/icon_offline_status@3x.png index 85e2b9d4b..2a2dec003 100644 Binary files a/iOS/TUIKit/TIMCommon/Resources/TIMCommonTheme.bundle/dark/resource/icon_offline_status@3x.png and b/iOS/TUIKit/TIMCommon/Resources/TIMCommonTheme.bundle/dark/resource/icon_offline_status@3x.png differ diff --git a/iOS/TUIKit/TIMCommon/Resources/TIMCommonTheme.bundle/dark/resource/icon_online_status@2x.png b/iOS/TUIKit/TIMCommon/Resources/TIMCommonTheme.bundle/dark/resource/icon_online_status@2x.png index 11a5d2c02..d3e5b574b 100644 Binary files a/iOS/TUIKit/TIMCommon/Resources/TIMCommonTheme.bundle/dark/resource/icon_online_status@2x.png and b/iOS/TUIKit/TIMCommon/Resources/TIMCommonTheme.bundle/dark/resource/icon_online_status@2x.png differ diff --git a/iOS/TUIKit/TIMCommon/Resources/TIMCommonTheme.bundle/dark/resource/icon_online_status@3x.png b/iOS/TUIKit/TIMCommon/Resources/TIMCommonTheme.bundle/dark/resource/icon_online_status@3x.png index 77a837aa3..f4ec3fdcc 100644 Binary files a/iOS/TUIKit/TIMCommon/Resources/TIMCommonTheme.bundle/dark/resource/icon_online_status@3x.png and b/iOS/TUIKit/TIMCommon/Resources/TIMCommonTheme.bundle/dark/resource/icon_online_status@3x.png differ diff --git a/iOS/TUIKit/TIMCommon/Resources/TIMCommonTheme.bundle/dark/resource/icon_translate@2x.png b/iOS/TUIKit/TIMCommon/Resources/TIMCommonTheme.bundle/dark/resource/icon_translate@2x.png index 39a060963..31f852d65 100644 Binary files a/iOS/TUIKit/TIMCommon/Resources/TIMCommonTheme.bundle/dark/resource/icon_translate@2x.png and b/iOS/TUIKit/TIMCommon/Resources/TIMCommonTheme.bundle/dark/resource/icon_translate@2x.png differ diff --git a/iOS/TUIKit/TIMCommon/Resources/TIMCommonTheme.bundle/dark/resource/icon_translate@3x.png b/iOS/TUIKit/TIMCommon/Resources/TIMCommonTheme.bundle/dark/resource/icon_translate@3x.png index c5dd5382c..0a685a756 100644 Binary files a/iOS/TUIKit/TIMCommon/Resources/TIMCommonTheme.bundle/dark/resource/icon_translate@3x.png and b/iOS/TUIKit/TIMCommon/Resources/TIMCommonTheme.bundle/dark/resource/icon_translate@3x.png differ diff --git a/iOS/TUIKit/TIMCommon/Resources/TIMCommonTheme.bundle/dark/resource/messageReplyIcon@2x.png b/iOS/TUIKit/TIMCommon/Resources/TIMCommonTheme.bundle/dark/resource/messageReplyIcon@2x.png index 5a516d98a..28347f268 100644 Binary files a/iOS/TUIKit/TIMCommon/Resources/TIMCommonTheme.bundle/dark/resource/messageReplyIcon@2x.png and b/iOS/TUIKit/TIMCommon/Resources/TIMCommonTheme.bundle/dark/resource/messageReplyIcon@2x.png differ diff --git a/iOS/TUIKit/TIMCommon/Resources/TIMCommonTheme.bundle/dark/resource/message_translation_tips@2x.png b/iOS/TUIKit/TIMCommon/Resources/TIMCommonTheme.bundle/dark/resource/message_translation_tips@2x.png index 34b2d452d..116173f58 100644 Binary files a/iOS/TUIKit/TIMCommon/Resources/TIMCommonTheme.bundle/dark/resource/message_translation_tips@2x.png and b/iOS/TUIKit/TIMCommon/Resources/TIMCommonTheme.bundle/dark/resource/message_translation_tips@2x.png differ diff --git a/iOS/TUIKit/TIMCommon/Resources/TIMCommonTheme.bundle/dark/resource/message_translation_tips@3x.png b/iOS/TUIKit/TIMCommon/Resources/TIMCommonTheme.bundle/dark/resource/message_translation_tips@3x.png index f488f313c..5df98ee9c 100644 Binary files a/iOS/TUIKit/TIMCommon/Resources/TIMCommonTheme.bundle/dark/resource/message_translation_tips@3x.png and b/iOS/TUIKit/TIMCommon/Resources/TIMCommonTheme.bundle/dark/resource/message_translation_tips@3x.png differ diff --git a/iOS/TUIKit/TIMCommon/Resources/TIMCommonTheme.bundle/dark/resource/nav_back@3x.png b/iOS/TUIKit/TIMCommon/Resources/TIMCommonTheme.bundle/dark/resource/nav_back@3x.png index 20726344a..f0967a6e0 100644 Binary files a/iOS/TUIKit/TIMCommon/Resources/TIMCommonTheme.bundle/dark/resource/nav_back@3x.png and b/iOS/TUIKit/TIMCommon/Resources/TIMCommonTheme.bundle/dark/resource/nav_back@3x.png differ diff --git a/iOS/TUIKit/TIMCommon/Resources/TIMCommonTheme.bundle/dark/resource/nav_more@3x.png b/iOS/TUIKit/TIMCommon/Resources/TIMCommonTheme.bundle/dark/resource/nav_more@3x.png index 62557b2dc..42efcc5db 100644 Binary files a/iOS/TUIKit/TIMCommon/Resources/TIMCommonTheme.bundle/dark/resource/nav_more@3x.png and b/iOS/TUIKit/TIMCommon/Resources/TIMCommonTheme.bundle/dark/resource/nav_more@3x.png differ diff --git a/iOS/TUIKit/TIMCommon/Resources/TIMCommonTheme.bundle/dark/resource/service_more_group_note_img@3x.png b/iOS/TUIKit/TIMCommon/Resources/TIMCommonTheme.bundle/dark/resource/service_more_group_note_img@3x.png index 5c63b05f8..2622c2e15 100644 Binary files a/iOS/TUIKit/TIMCommon/Resources/TIMCommonTheme.bundle/dark/resource/service_more_group_note_img@3x.png and b/iOS/TUIKit/TIMCommon/Resources/TIMCommonTheme.bundle/dark/resource/service_more_group_note_img@3x.png differ diff --git a/iOS/TUIKit/TIMCommon/Resources/TIMCommonTheme.bundle/dark/resource/service_more_poll_img@3x.png b/iOS/TUIKit/TIMCommon/Resources/TIMCommonTheme.bundle/dark/resource/service_more_poll_img@3x.png index fbcbfa124..0226679b3 100644 Binary files a/iOS/TUIKit/TIMCommon/Resources/TIMCommonTheme.bundle/dark/resource/service_more_poll_img@3x.png and b/iOS/TUIKit/TIMCommon/Resources/TIMCommonTheme.bundle/dark/resource/service_more_poll_img@3x.png differ diff --git a/iOS/TUIKit/TIMCommon/Resources/TIMCommonTheme.bundle/dark/resource/service_more_video_call@3x.png b/iOS/TUIKit/TIMCommon/Resources/TIMCommonTheme.bundle/dark/resource/service_more_video_call@3x.png index 7e8124d3b..757c99e27 100644 Binary files a/iOS/TUIKit/TIMCommon/Resources/TIMCommonTheme.bundle/dark/resource/service_more_video_call@3x.png and b/iOS/TUIKit/TIMCommon/Resources/TIMCommonTheme.bundle/dark/resource/service_more_video_call@3x.png differ diff --git a/iOS/TUIKit/TIMCommon/Resources/TIMCommonTheme.bundle/dark/resource/service_more_voice_call@3x.png b/iOS/TUIKit/TIMCommon/Resources/TIMCommonTheme.bundle/dark/resource/service_more_voice_call@3x.png index 2277b5e78..10aed5f8e 100644 Binary files a/iOS/TUIKit/TIMCommon/Resources/TIMCommonTheme.bundle/dark/resource/service_more_voice_call@3x.png and b/iOS/TUIKit/TIMCommon/Resources/TIMCommonTheme.bundle/dark/resource/service_more_voice_call@3x.png differ diff --git a/iOS/TUIKit/TIMCommon/Resources/TIMCommonTheme.bundle/light/resource/bg.png b/iOS/TUIKit/TIMCommon/Resources/TIMCommonTheme.bundle/light/resource/bg.png index 87d7c51a0..292267063 100644 Binary files a/iOS/TUIKit/TIMCommon/Resources/TIMCommonTheme.bundle/light/resource/bg.png and b/iOS/TUIKit/TIMCommon/Resources/TIMCommonTheme.bundle/light/resource/bg.png differ diff --git a/iOS/TUIKit/TIMCommon/Resources/TIMCommonTheme.bundle/light/resource/default_group_head@2x.png b/iOS/TUIKit/TIMCommon/Resources/TIMCommonTheme.bundle/light/resource/default_group_head@2x.png index 314f5c98b..d31242fc9 100644 Binary files a/iOS/TUIKit/TIMCommon/Resources/TIMCommonTheme.bundle/light/resource/default_group_head@2x.png and b/iOS/TUIKit/TIMCommon/Resources/TIMCommonTheme.bundle/light/resource/default_group_head@2x.png differ diff --git a/iOS/TUIKit/TIMCommon/Resources/TIMCommonTheme.bundle/light/resource/default_group_head_avchatroom@2x.png b/iOS/TUIKit/TIMCommon/Resources/TIMCommonTheme.bundle/light/resource/default_group_head_avchatroom@2x.png index 015ce7aaf..e821e64bb 100644 Binary files a/iOS/TUIKit/TIMCommon/Resources/TIMCommonTheme.bundle/light/resource/default_group_head_avchatroom@2x.png and b/iOS/TUIKit/TIMCommon/Resources/TIMCommonTheme.bundle/light/resource/default_group_head_avchatroom@2x.png differ diff --git a/iOS/TUIKit/TIMCommon/Resources/TIMCommonTheme.bundle/light/resource/default_group_head_community@2x.png b/iOS/TUIKit/TIMCommon/Resources/TIMCommonTheme.bundle/light/resource/default_group_head_community@2x.png index ca5814336..92aceceeb 100644 Binary files a/iOS/TUIKit/TIMCommon/Resources/TIMCommonTheme.bundle/light/resource/default_group_head_community@2x.png and b/iOS/TUIKit/TIMCommon/Resources/TIMCommonTheme.bundle/light/resource/default_group_head_community@2x.png differ diff --git a/iOS/TUIKit/TIMCommon/Resources/TIMCommonTheme.bundle/light/resource/default_group_head_meeting@2x.png b/iOS/TUIKit/TIMCommon/Resources/TIMCommonTheme.bundle/light/resource/default_group_head_meeting@2x.png index e363ed6ef..dffcd1413 100644 Binary files a/iOS/TUIKit/TIMCommon/Resources/TIMCommonTheme.bundle/light/resource/default_group_head_meeting@2x.png and b/iOS/TUIKit/TIMCommon/Resources/TIMCommonTheme.bundle/light/resource/default_group_head_meeting@2x.png differ diff --git a/iOS/TUIKit/TIMCommon/Resources/TIMCommonTheme.bundle/light/resource/default_group_head_public@2x.png b/iOS/TUIKit/TIMCommon/Resources/TIMCommonTheme.bundle/light/resource/default_group_head_public@2x.png index 5484cddcb..2a275ca75 100644 Binary files a/iOS/TUIKit/TIMCommon/Resources/TIMCommonTheme.bundle/light/resource/default_group_head_public@2x.png and b/iOS/TUIKit/TIMCommon/Resources/TIMCommonTheme.bundle/light/resource/default_group_head_public@2x.png differ diff --git a/iOS/TUIKit/TIMCommon/Resources/TIMCommonTheme.bundle/light/resource/icon_offline_status@2x.png b/iOS/TUIKit/TIMCommon/Resources/TIMCommonTheme.bundle/light/resource/icon_offline_status@2x.png index a99167c98..73c21091e 100644 Binary files a/iOS/TUIKit/TIMCommon/Resources/TIMCommonTheme.bundle/light/resource/icon_offline_status@2x.png and b/iOS/TUIKit/TIMCommon/Resources/TIMCommonTheme.bundle/light/resource/icon_offline_status@2x.png differ diff --git a/iOS/TUIKit/TIMCommon/Resources/TIMCommonTheme.bundle/light/resource/icon_offline_status@3x.png b/iOS/TUIKit/TIMCommon/Resources/TIMCommonTheme.bundle/light/resource/icon_offline_status@3x.png index 93f4010f8..f326e14ea 100644 Binary files a/iOS/TUIKit/TIMCommon/Resources/TIMCommonTheme.bundle/light/resource/icon_offline_status@3x.png and b/iOS/TUIKit/TIMCommon/Resources/TIMCommonTheme.bundle/light/resource/icon_offline_status@3x.png differ diff --git a/iOS/TUIKit/TIMCommon/Resources/TIMCommonTheme.bundle/light/resource/icon_online_status@2x.png b/iOS/TUIKit/TIMCommon/Resources/TIMCommonTheme.bundle/light/resource/icon_online_status@2x.png index 71e71c74b..a04b9f80f 100644 Binary files a/iOS/TUIKit/TIMCommon/Resources/TIMCommonTheme.bundle/light/resource/icon_online_status@2x.png and b/iOS/TUIKit/TIMCommon/Resources/TIMCommonTheme.bundle/light/resource/icon_online_status@2x.png differ diff --git a/iOS/TUIKit/TIMCommon/Resources/TIMCommonTheme.bundle/light/resource/icon_online_status@3x.png b/iOS/TUIKit/TIMCommon/Resources/TIMCommonTheme.bundle/light/resource/icon_online_status@3x.png index cf07e72e3..7a46b0d3b 100644 Binary files a/iOS/TUIKit/TIMCommon/Resources/TIMCommonTheme.bundle/light/resource/icon_online_status@3x.png and b/iOS/TUIKit/TIMCommon/Resources/TIMCommonTheme.bundle/light/resource/icon_online_status@3x.png differ diff --git a/iOS/TUIKit/TIMCommon/Resources/TIMCommonTheme.bundle/light/resource/messageReplyIcon@2x.png b/iOS/TUIKit/TIMCommon/Resources/TIMCommonTheme.bundle/light/resource/messageReplyIcon@2x.png index 19e4b81e0..b2ca55155 100644 Binary files a/iOS/TUIKit/TIMCommon/Resources/TIMCommonTheme.bundle/light/resource/messageReplyIcon@2x.png and b/iOS/TUIKit/TIMCommon/Resources/TIMCommonTheme.bundle/light/resource/messageReplyIcon@2x.png differ diff --git a/iOS/TUIKit/TIMCommon/Resources/TIMCommonTheme.bundle/light/resource/nav_back@3x.png b/iOS/TUIKit/TIMCommon/Resources/TIMCommonTheme.bundle/light/resource/nav_back@3x.png index 3d8c99915..9d18b0b69 100644 Binary files a/iOS/TUIKit/TIMCommon/Resources/TIMCommonTheme.bundle/light/resource/nav_back@3x.png and b/iOS/TUIKit/TIMCommon/Resources/TIMCommonTheme.bundle/light/resource/nav_back@3x.png differ diff --git a/iOS/TUIKit/TIMCommon/Resources/TIMCommonTheme.bundle/light/resource/nav_more@2x.png b/iOS/TUIKit/TIMCommon/Resources/TIMCommonTheme.bundle/light/resource/nav_more@2x.png index b2890f402..134a61308 100644 Binary files a/iOS/TUIKit/TIMCommon/Resources/TIMCommonTheme.bundle/light/resource/nav_more@2x.png and b/iOS/TUIKit/TIMCommon/Resources/TIMCommonTheme.bundle/light/resource/nav_more@2x.png differ diff --git a/iOS/TUIKit/TIMCommon/Resources/TIMCommonTheme.bundle/light/resource/service_more_group_note_img@3x.png b/iOS/TUIKit/TIMCommon/Resources/TIMCommonTheme.bundle/light/resource/service_more_group_note_img@3x.png index acc41a783..8fb611a9e 100644 Binary files a/iOS/TUIKit/TIMCommon/Resources/TIMCommonTheme.bundle/light/resource/service_more_group_note_img@3x.png and b/iOS/TUIKit/TIMCommon/Resources/TIMCommonTheme.bundle/light/resource/service_more_group_note_img@3x.png differ diff --git a/iOS/TUIKit/TIMCommon/Resources/TIMCommonTheme.bundle/light/resource/service_more_poll_img@3x.png b/iOS/TUIKit/TIMCommon/Resources/TIMCommonTheme.bundle/light/resource/service_more_poll_img@3x.png index be52e9a1b..addad7591 100644 Binary files a/iOS/TUIKit/TIMCommon/Resources/TIMCommonTheme.bundle/light/resource/service_more_poll_img@3x.png and b/iOS/TUIKit/TIMCommon/Resources/TIMCommonTheme.bundle/light/resource/service_more_poll_img@3x.png differ diff --git a/iOS/TUIKit/TIMCommon/Resources/TIMCommonTheme.bundle/light/resource/service_more_video_call@3x.png b/iOS/TUIKit/TIMCommon/Resources/TIMCommonTheme.bundle/light/resource/service_more_video_call@3x.png index cc3776137..7d89281fb 100644 Binary files a/iOS/TUIKit/TIMCommon/Resources/TIMCommonTheme.bundle/light/resource/service_more_video_call@3x.png and b/iOS/TUIKit/TIMCommon/Resources/TIMCommonTheme.bundle/light/resource/service_more_video_call@3x.png differ diff --git a/iOS/TUIKit/TIMCommon/Resources/TIMCommonTheme.bundle/light/resource/service_more_voice_call@3x.png b/iOS/TUIKit/TIMCommon/Resources/TIMCommonTheme.bundle/light/resource/service_more_voice_call@3x.png index 4c0455089..f333fe9ed 100644 Binary files a/iOS/TUIKit/TIMCommon/Resources/TIMCommonTheme.bundle/light/resource/service_more_voice_call@3x.png and b/iOS/TUIKit/TIMCommon/Resources/TIMCommonTheme.bundle/light/resource/service_more_voice_call@3x.png differ diff --git a/iOS/TUIKit/TIMCommon/Resources/TIMCommonTheme.bundle/lively/resource/bg.png b/iOS/TUIKit/TIMCommon/Resources/TIMCommonTheme.bundle/lively/resource/bg.png index 62c1d746f..acfbbf52c 100644 Binary files a/iOS/TUIKit/TIMCommon/Resources/TIMCommonTheme.bundle/lively/resource/bg.png and b/iOS/TUIKit/TIMCommon/Resources/TIMCommonTheme.bundle/lively/resource/bg.png differ diff --git a/iOS/TUIKit/TIMCommon/Resources/TIMCommonTheme.bundle/lively/resource/default_group_head@2x.png b/iOS/TUIKit/TIMCommon/Resources/TIMCommonTheme.bundle/lively/resource/default_group_head@2x.png index d94772e46..97f17ecb7 100644 Binary files a/iOS/TUIKit/TIMCommon/Resources/TIMCommonTheme.bundle/lively/resource/default_group_head@2x.png and b/iOS/TUIKit/TIMCommon/Resources/TIMCommonTheme.bundle/lively/resource/default_group_head@2x.png differ diff --git a/iOS/TUIKit/TIMCommon/Resources/TIMCommonTheme.bundle/lively/resource/default_group_head_avchatroom@2x.png b/iOS/TUIKit/TIMCommon/Resources/TIMCommonTheme.bundle/lively/resource/default_group_head_avchatroom@2x.png index 21b0cafab..2f7fd80d8 100644 Binary files a/iOS/TUIKit/TIMCommon/Resources/TIMCommonTheme.bundle/lively/resource/default_group_head_avchatroom@2x.png and b/iOS/TUIKit/TIMCommon/Resources/TIMCommonTheme.bundle/lively/resource/default_group_head_avchatroom@2x.png differ diff --git a/iOS/TUIKit/TIMCommon/Resources/TIMCommonTheme.bundle/lively/resource/default_group_head_community@2x.png b/iOS/TUIKit/TIMCommon/Resources/TIMCommonTheme.bundle/lively/resource/default_group_head_community@2x.png index d7dc620ff..f332607ec 100644 Binary files a/iOS/TUIKit/TIMCommon/Resources/TIMCommonTheme.bundle/lively/resource/default_group_head_community@2x.png and b/iOS/TUIKit/TIMCommon/Resources/TIMCommonTheme.bundle/lively/resource/default_group_head_community@2x.png differ diff --git a/iOS/TUIKit/TIMCommon/Resources/TIMCommonTheme.bundle/lively/resource/default_group_head_meeting@2x.png b/iOS/TUIKit/TIMCommon/Resources/TIMCommonTheme.bundle/lively/resource/default_group_head_meeting@2x.png index 85630caa7..0e1f87924 100644 Binary files a/iOS/TUIKit/TIMCommon/Resources/TIMCommonTheme.bundle/lively/resource/default_group_head_meeting@2x.png and b/iOS/TUIKit/TIMCommon/Resources/TIMCommonTheme.bundle/lively/resource/default_group_head_meeting@2x.png differ diff --git a/iOS/TUIKit/TIMCommon/Resources/TIMCommonTheme.bundle/lively/resource/default_group_head_public@2x.png b/iOS/TUIKit/TIMCommon/Resources/TIMCommonTheme.bundle/lively/resource/default_group_head_public@2x.png index f53088b7f..193bb68d8 100644 Binary files a/iOS/TUIKit/TIMCommon/Resources/TIMCommonTheme.bundle/lively/resource/default_group_head_public@2x.png and b/iOS/TUIKit/TIMCommon/Resources/TIMCommonTheme.bundle/lively/resource/default_group_head_public@2x.png differ diff --git a/iOS/TUIKit/TIMCommon/Resources/TIMCommonTheme.bundle/lively/resource/icon_offline_status@2x.png b/iOS/TUIKit/TIMCommon/Resources/TIMCommonTheme.bundle/lively/resource/icon_offline_status@2x.png index a99167c98..73c21091e 100644 Binary files a/iOS/TUIKit/TIMCommon/Resources/TIMCommonTheme.bundle/lively/resource/icon_offline_status@2x.png and b/iOS/TUIKit/TIMCommon/Resources/TIMCommonTheme.bundle/lively/resource/icon_offline_status@2x.png differ diff --git a/iOS/TUIKit/TIMCommon/Resources/TIMCommonTheme.bundle/lively/resource/icon_offline_status@3x.png b/iOS/TUIKit/TIMCommon/Resources/TIMCommonTheme.bundle/lively/resource/icon_offline_status@3x.png index 93f4010f8..f326e14ea 100644 Binary files a/iOS/TUIKit/TIMCommon/Resources/TIMCommonTheme.bundle/lively/resource/icon_offline_status@3x.png and b/iOS/TUIKit/TIMCommon/Resources/TIMCommonTheme.bundle/lively/resource/icon_offline_status@3x.png differ diff --git a/iOS/TUIKit/TIMCommon/Resources/TIMCommonTheme.bundle/lively/resource/icon_online_status@2x.png b/iOS/TUIKit/TIMCommon/Resources/TIMCommonTheme.bundle/lively/resource/icon_online_status@2x.png index 753ea61bb..625fd34ae 100644 Binary files a/iOS/TUIKit/TIMCommon/Resources/TIMCommonTheme.bundle/lively/resource/icon_online_status@2x.png and b/iOS/TUIKit/TIMCommon/Resources/TIMCommonTheme.bundle/lively/resource/icon_online_status@2x.png differ diff --git a/iOS/TUIKit/TIMCommon/Resources/TIMCommonTheme.bundle/lively/resource/icon_online_status@3x.png b/iOS/TUIKit/TIMCommon/Resources/TIMCommonTheme.bundle/lively/resource/icon_online_status@3x.png index 69b05d8af..5f8388755 100644 Binary files a/iOS/TUIKit/TIMCommon/Resources/TIMCommonTheme.bundle/lively/resource/icon_online_status@3x.png and b/iOS/TUIKit/TIMCommon/Resources/TIMCommonTheme.bundle/lively/resource/icon_online_status@3x.png differ diff --git a/iOS/TUIKit/TIMCommon/Resources/TIMCommonTheme.bundle/lively/resource/messageReplyIcon@2x.png b/iOS/TUIKit/TIMCommon/Resources/TIMCommonTheme.bundle/lively/resource/messageReplyIcon@2x.png index 5e9158c43..77bc8dcc0 100644 Binary files a/iOS/TUIKit/TIMCommon/Resources/TIMCommonTheme.bundle/lively/resource/messageReplyIcon@2x.png and b/iOS/TUIKit/TIMCommon/Resources/TIMCommonTheme.bundle/lively/resource/messageReplyIcon@2x.png differ diff --git a/iOS/TUIKit/TIMCommon/Resources/TIMCommonTheme.bundle/lively/resource/nav_back@3x.png b/iOS/TUIKit/TIMCommon/Resources/TIMCommonTheme.bundle/lively/resource/nav_back@3x.png index 20726344a..d8461bba2 100644 Binary files a/iOS/TUIKit/TIMCommon/Resources/TIMCommonTheme.bundle/lively/resource/nav_back@3x.png and b/iOS/TUIKit/TIMCommon/Resources/TIMCommonTheme.bundle/lively/resource/nav_back@3x.png differ diff --git a/iOS/TUIKit/TIMCommon/Resources/TIMCommonTheme.bundle/lively/resource/nav_more@3x.png b/iOS/TUIKit/TIMCommon/Resources/TIMCommonTheme.bundle/lively/resource/nav_more@3x.png index e44975b2c..b69d31e2f 100644 Binary files a/iOS/TUIKit/TIMCommon/Resources/TIMCommonTheme.bundle/lively/resource/nav_more@3x.png and b/iOS/TUIKit/TIMCommon/Resources/TIMCommonTheme.bundle/lively/resource/nav_more@3x.png differ diff --git a/iOS/TUIKit/TIMCommon/Resources/TIMCommonTheme.bundle/lively/resource/service_more_group_note_img@3x.png b/iOS/TUIKit/TIMCommon/Resources/TIMCommonTheme.bundle/lively/resource/service_more_group_note_img@3x.png index acc41a783..8fb611a9e 100644 Binary files a/iOS/TUIKit/TIMCommon/Resources/TIMCommonTheme.bundle/lively/resource/service_more_group_note_img@3x.png and b/iOS/TUIKit/TIMCommon/Resources/TIMCommonTheme.bundle/lively/resource/service_more_group_note_img@3x.png differ diff --git a/iOS/TUIKit/TIMCommon/Resources/TIMCommonTheme.bundle/lively/resource/service_more_poll_img@3x.png b/iOS/TUIKit/TIMCommon/Resources/TIMCommonTheme.bundle/lively/resource/service_more_poll_img@3x.png index be52e9a1b..addad7591 100644 Binary files a/iOS/TUIKit/TIMCommon/Resources/TIMCommonTheme.bundle/lively/resource/service_more_poll_img@3x.png and b/iOS/TUIKit/TIMCommon/Resources/TIMCommonTheme.bundle/lively/resource/service_more_poll_img@3x.png differ diff --git a/iOS/TUIKit/TIMCommon/Resources/TIMCommonTheme.bundle/lively/resource/service_more_video_call@3x.png b/iOS/TUIKit/TIMCommon/Resources/TIMCommonTheme.bundle/lively/resource/service_more_video_call@3x.png index cc3776137..7d89281fb 100644 Binary files a/iOS/TUIKit/TIMCommon/Resources/TIMCommonTheme.bundle/lively/resource/service_more_video_call@3x.png and b/iOS/TUIKit/TIMCommon/Resources/TIMCommonTheme.bundle/lively/resource/service_more_video_call@3x.png differ diff --git a/iOS/TUIKit/TIMCommon/Resources/TIMCommonTheme.bundle/lively/resource/service_more_voice_call@3x.png b/iOS/TUIKit/TIMCommon/Resources/TIMCommonTheme.bundle/lively/resource/service_more_voice_call@3x.png index 4c0455089..f333fe9ed 100644 Binary files a/iOS/TUIKit/TIMCommon/Resources/TIMCommonTheme.bundle/lively/resource/service_more_voice_call@3x.png and b/iOS/TUIKit/TIMCommon/Resources/TIMCommonTheme.bundle/lively/resource/service_more_voice_call@3x.png differ diff --git a/iOS/TUIKit/TIMCommon/Resources/TIMCommonTheme.bundle/serious/resource/bg.png b/iOS/TUIKit/TIMCommon/Resources/TIMCommonTheme.bundle/serious/resource/bg.png index ccaf89e4a..0ad7159f3 100644 Binary files a/iOS/TUIKit/TIMCommon/Resources/TIMCommonTheme.bundle/serious/resource/bg.png and b/iOS/TUIKit/TIMCommon/Resources/TIMCommonTheme.bundle/serious/resource/bg.png differ diff --git a/iOS/TUIKit/TIMCommon/Resources/TIMCommonTheme.bundle/serious/resource/default_group_head@2x.png b/iOS/TUIKit/TIMCommon/Resources/TIMCommonTheme.bundle/serious/resource/default_group_head@2x.png index 64f95e26d..9178c8144 100644 Binary files a/iOS/TUIKit/TIMCommon/Resources/TIMCommonTheme.bundle/serious/resource/default_group_head@2x.png and b/iOS/TUIKit/TIMCommon/Resources/TIMCommonTheme.bundle/serious/resource/default_group_head@2x.png differ diff --git a/iOS/TUIKit/TIMCommon/Resources/TIMCommonTheme.bundle/serious/resource/default_group_head_avchatroom@2x.png b/iOS/TUIKit/TIMCommon/Resources/TIMCommonTheme.bundle/serious/resource/default_group_head_avchatroom@2x.png index a26280314..19d2cfcf8 100644 Binary files a/iOS/TUIKit/TIMCommon/Resources/TIMCommonTheme.bundle/serious/resource/default_group_head_avchatroom@2x.png and b/iOS/TUIKit/TIMCommon/Resources/TIMCommonTheme.bundle/serious/resource/default_group_head_avchatroom@2x.png differ diff --git a/iOS/TUIKit/TIMCommon/Resources/TIMCommonTheme.bundle/serious/resource/default_group_head_community@2x.png b/iOS/TUIKit/TIMCommon/Resources/TIMCommonTheme.bundle/serious/resource/default_group_head_community@2x.png index ca5814336..92aceceeb 100644 Binary files a/iOS/TUIKit/TIMCommon/Resources/TIMCommonTheme.bundle/serious/resource/default_group_head_community@2x.png and b/iOS/TUIKit/TIMCommon/Resources/TIMCommonTheme.bundle/serious/resource/default_group_head_community@2x.png differ diff --git a/iOS/TUIKit/TIMCommon/Resources/TIMCommonTheme.bundle/serious/resource/default_group_head_meeting@2x.png b/iOS/TUIKit/TIMCommon/Resources/TIMCommonTheme.bundle/serious/resource/default_group_head_meeting@2x.png index b4830e003..428541d3e 100644 Binary files a/iOS/TUIKit/TIMCommon/Resources/TIMCommonTheme.bundle/serious/resource/default_group_head_meeting@2x.png and b/iOS/TUIKit/TIMCommon/Resources/TIMCommonTheme.bundle/serious/resource/default_group_head_meeting@2x.png differ diff --git a/iOS/TUIKit/TIMCommon/Resources/TIMCommonTheme.bundle/serious/resource/default_group_head_public@2x.png b/iOS/TUIKit/TIMCommon/Resources/TIMCommonTheme.bundle/serious/resource/default_group_head_public@2x.png index 47e24ed90..dcd64e15c 100644 Binary files a/iOS/TUIKit/TIMCommon/Resources/TIMCommonTheme.bundle/serious/resource/default_group_head_public@2x.png and b/iOS/TUIKit/TIMCommon/Resources/TIMCommonTheme.bundle/serious/resource/default_group_head_public@2x.png differ diff --git a/iOS/TUIKit/TIMCommon/Resources/TIMCommonTheme.bundle/serious/resource/icon_offline_status@2x.png b/iOS/TUIKit/TIMCommon/Resources/TIMCommonTheme.bundle/serious/resource/icon_offline_status@2x.png index a99167c98..73c21091e 100644 Binary files a/iOS/TUIKit/TIMCommon/Resources/TIMCommonTheme.bundle/serious/resource/icon_offline_status@2x.png and b/iOS/TUIKit/TIMCommon/Resources/TIMCommonTheme.bundle/serious/resource/icon_offline_status@2x.png differ diff --git a/iOS/TUIKit/TIMCommon/Resources/TIMCommonTheme.bundle/serious/resource/icon_offline_status@3x.png b/iOS/TUIKit/TIMCommon/Resources/TIMCommonTheme.bundle/serious/resource/icon_offline_status@3x.png index 93f4010f8..f326e14ea 100644 Binary files a/iOS/TUIKit/TIMCommon/Resources/TIMCommonTheme.bundle/serious/resource/icon_offline_status@3x.png and b/iOS/TUIKit/TIMCommon/Resources/TIMCommonTheme.bundle/serious/resource/icon_offline_status@3x.png differ diff --git a/iOS/TUIKit/TIMCommon/Resources/TIMCommonTheme.bundle/serious/resource/icon_online_status@2x.png b/iOS/TUIKit/TIMCommon/Resources/TIMCommonTheme.bundle/serious/resource/icon_online_status@2x.png index fd50172d0..1ebee1c5b 100644 Binary files a/iOS/TUIKit/TIMCommon/Resources/TIMCommonTheme.bundle/serious/resource/icon_online_status@2x.png and b/iOS/TUIKit/TIMCommon/Resources/TIMCommonTheme.bundle/serious/resource/icon_online_status@2x.png differ diff --git a/iOS/TUIKit/TIMCommon/Resources/TIMCommonTheme.bundle/serious/resource/icon_online_status@3x.png b/iOS/TUIKit/TIMCommon/Resources/TIMCommonTheme.bundle/serious/resource/icon_online_status@3x.png index ec31c4a34..54fc878ec 100644 Binary files a/iOS/TUIKit/TIMCommon/Resources/TIMCommonTheme.bundle/serious/resource/icon_online_status@3x.png and b/iOS/TUIKit/TIMCommon/Resources/TIMCommonTheme.bundle/serious/resource/icon_online_status@3x.png differ diff --git a/iOS/TUIKit/TIMCommon/Resources/TIMCommonTheme.bundle/serious/resource/messageReplyIcon@2x.png b/iOS/TUIKit/TIMCommon/Resources/TIMCommonTheme.bundle/serious/resource/messageReplyIcon@2x.png index 19e4b81e0..b2ca55155 100644 Binary files a/iOS/TUIKit/TIMCommon/Resources/TIMCommonTheme.bundle/serious/resource/messageReplyIcon@2x.png and b/iOS/TUIKit/TIMCommon/Resources/TIMCommonTheme.bundle/serious/resource/messageReplyIcon@2x.png differ diff --git a/iOS/TUIKit/TIMCommon/Resources/TIMCommonTheme.bundle/serious/resource/nav_back@3x.png b/iOS/TUIKit/TIMCommon/Resources/TIMCommonTheme.bundle/serious/resource/nav_back@3x.png index 20726344a..1410968a0 100644 Binary files a/iOS/TUIKit/TIMCommon/Resources/TIMCommonTheme.bundle/serious/resource/nav_back@3x.png and b/iOS/TUIKit/TIMCommon/Resources/TIMCommonTheme.bundle/serious/resource/nav_back@3x.png differ diff --git a/iOS/TUIKit/TIMCommon/Resources/TIMCommonTheme.bundle/serious/resource/nav_more@3x.png b/iOS/TUIKit/TIMCommon/Resources/TIMCommonTheme.bundle/serious/resource/nav_more@3x.png index e44975b2c..b69d31e2f 100644 Binary files a/iOS/TUIKit/TIMCommon/Resources/TIMCommonTheme.bundle/serious/resource/nav_more@3x.png and b/iOS/TUIKit/TIMCommon/Resources/TIMCommonTheme.bundle/serious/resource/nav_more@3x.png differ diff --git a/iOS/TUIKit/TIMCommon/Resources/TIMCommonTheme.bundle/serious/resource/service_more_group_note_img@3x.png b/iOS/TUIKit/TIMCommon/Resources/TIMCommonTheme.bundle/serious/resource/service_more_group_note_img@3x.png index acc41a783..8fb611a9e 100644 Binary files a/iOS/TUIKit/TIMCommon/Resources/TIMCommonTheme.bundle/serious/resource/service_more_group_note_img@3x.png and b/iOS/TUIKit/TIMCommon/Resources/TIMCommonTheme.bundle/serious/resource/service_more_group_note_img@3x.png differ diff --git a/iOS/TUIKit/TIMCommon/Resources/TIMCommonTheme.bundle/serious/resource/service_more_poll_img@3x.png b/iOS/TUIKit/TIMCommon/Resources/TIMCommonTheme.bundle/serious/resource/service_more_poll_img@3x.png index be52e9a1b..addad7591 100644 Binary files a/iOS/TUIKit/TIMCommon/Resources/TIMCommonTheme.bundle/serious/resource/service_more_poll_img@3x.png and b/iOS/TUIKit/TIMCommon/Resources/TIMCommonTheme.bundle/serious/resource/service_more_poll_img@3x.png differ diff --git a/iOS/TUIKit/TIMCommon/Resources/TIMCommonTheme.bundle/serious/resource/service_more_video_call@3x.png b/iOS/TUIKit/TIMCommon/Resources/TIMCommonTheme.bundle/serious/resource/service_more_video_call@3x.png index cc3776137..7d89281fb 100644 Binary files a/iOS/TUIKit/TIMCommon/Resources/TIMCommonTheme.bundle/serious/resource/service_more_video_call@3x.png and b/iOS/TUIKit/TIMCommon/Resources/TIMCommonTheme.bundle/serious/resource/service_more_video_call@3x.png differ diff --git a/iOS/TUIKit/TIMCommon/Resources/TIMCommonTheme.bundle/serious/resource/service_more_voice_call@3x.png b/iOS/TUIKit/TIMCommon/Resources/TIMCommonTheme.bundle/serious/resource/service_more_voice_call@3x.png index 4c0455089..f333fe9ed 100644 Binary files a/iOS/TUIKit/TIMCommon/Resources/TIMCommonTheme.bundle/serious/resource/service_more_voice_call@3x.png and b/iOS/TUIKit/TIMCommon/Resources/TIMCommonTheme.bundle/serious/resource/service_more_voice_call@3x.png differ diff --git a/iOS/TUIKit/TIMCommon/TIMCommon.podspec b/iOS/TUIKit/TIMCommon/TIMCommon.podspec index 8591218c6..3d4937611 100644 --- a/iOS/TUIKit/TIMCommon/TIMCommon.podspec +++ b/iOS/TUIKit/TIMCommon/TIMCommon.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |spec| spec.name = 'TIMCommon' - spec.version = '7.4.4643' + spec.version = '7.5.4852' spec.platform = :ios spec.ios.deployment_target = '9.0' spec.license = { :type => 'Proprietary', diff --git a/iOS/TUIKit/TIMCommon/UI_Classic/TUIBubbleMessageCell.m b/iOS/TUIKit/TIMCommon/UI_Classic/TUIBubbleMessageCell.m index 6beb0b8ab..57a1307b1 100644 --- a/iOS/TUIKit/TIMCommon/UI_Classic/TUIBubbleMessageCell.m +++ b/iOS/TUIKit/TIMCommon/UI_Classic/TUIBubbleMessageCell.m @@ -28,18 +28,38 @@ self.bubbleData = data; self.bubbleView.image = self.getBubble; self.bubbleView.highlightedImage = self.getHighlightBubble; + // tell constraints they need updating + [self setNeedsUpdateConstraints]; + + // update constraints now so we can animate the change + [self updateConstraintsIfNeeded]; + + [self layoutIfNeeded]; + +} + ++ (BOOL)requiresConstraintBasedLayout { + return YES; +} + +// this is Apple's recommended place for adding/updating constraints +- (void)updateConstraints { + + [super updateConstraints]; + [self.bubbleView mas_remakeConstraints:^(MASConstraintMaker *make) { + make.leading.mas_equalTo(self.getBubbleTop); + make.size.mas_equalTo(self.container); + make.top.mas_equalTo(self.container); + }]; + + CGPoint center = self.retryView.center; + center.y = self.bubbleView.center.y; + self.retryView.center = center; + } - (void)layoutSubviews { [super layoutSubviews]; - - CGRect frame = self.bubbleView.frame; - frame.origin.x = self.getBubbleTop; - self.bubbleView.frame = frame; - - CGPoint center = self.retryView.center; - center.y = self.bubbleView.center.y; - self.retryView.center = center; } - (void)highlightWhenMatchKeyword:(NSString *)keyword { @@ -134,8 +154,11 @@ static UIImage *gOutgoingBubble; + (UIImage *)outgoingBubble { if (!gOutgoingBubble) { UIImage *defaultImage = [[TUIImageCache sharedInstance] getResourceFromCache:TUIChatImagePath(@"SenderTextNodeBkg")]; - gOutgoingBubble = [TUIChatDynamicImage(@"chat_bubble_send_img", defaultImage) resizableImageWithCapInsets:UIEdgeInsetsFromString(@"{12,12,12,12}") - resizingMode:UIImageResizingModeStretch]; + UIImage *formatImage = TUIChatDynamicImage(@"chat_bubble_send_img", defaultImage); + formatImage = [formatImage rtl_imageFlippedForRightToLeftLayoutDirection]; + UIEdgeInsets ei = UIEdgeInsetsFromString(@"{12,12,12,12}"); + ei = rtlEdgeInsetsWithInsets(ei); + gOutgoingBubble = [formatImage resizableImageWithCapInsets:ei resizingMode:UIImageResizingModeStretch]; } return gOutgoingBubble; } @@ -148,9 +171,11 @@ static UIImage *gOutgoingHighlightedBubble; + (UIImage *)outgoingHighlightedBubble { if (!gOutgoingHighlightedBubble) { UIImage *defaultImage = [[TUIImageCache sharedInstance] getResourceFromCache:TUIChatImagePath(@"SenderTextNodeBkgHL")]; - gOutgoingHighlightedBubble = - [TUIChatDynamicImage(@"chat_bubble_send_img", defaultImage) resizableImageWithCapInsets:UIEdgeInsetsFromString(@"{12,12,12,12}") - resizingMode:UIImageResizingModeStretch]; + UIImage *formatImage = TUIChatDynamicImage(@"chat_bubble_send_img", defaultImage); + formatImage = [formatImage rtl_imageFlippedForRightToLeftLayoutDirection]; + UIEdgeInsets ei = UIEdgeInsetsFromString(@"{12,12,12,12}"); + ei = rtlEdgeInsetsWithInsets(ei); + gOutgoingHighlightedBubble = [formatImage resizableImageWithCapInsets:ei resizingMode:UIImageResizingModeStretch]; } return gOutgoingHighlightedBubble; } @@ -163,8 +188,11 @@ static UIImage *gIncommingBubble; + (UIImage *)incommingBubble { if (!gIncommingBubble) { UIImage *defaultImage = [[TUIImageCache sharedInstance] getResourceFromCache:TUIChatImagePath(@"ReceiverTextNodeBkg")]; - gIncommingBubble = [TUIChatDynamicImage(@"chat_bubble_receive_img", defaultImage) resizableImageWithCapInsets:UIEdgeInsetsFromString(@"{12,12,12,12}") - resizingMode:UIImageResizingModeStretch]; + UIImage *formatImage = TUIChatDynamicImage(@"chat_bubble_receive_img", defaultImage); + formatImage = [formatImage rtl_imageFlippedForRightToLeftLayoutDirection]; + UIEdgeInsets ei = UIEdgeInsetsFromString(@"{12,12,12,12}"); + ei = rtlEdgeInsetsWithInsets(ei); + gIncommingBubble = [formatImage resizableImageWithCapInsets:ei resizingMode:UIImageResizingModeStretch]; } return gIncommingBubble; } @@ -177,9 +205,11 @@ static UIImage *gIncommingHighlightedBubble; + (UIImage *)incommingHighlightedBubble { if (!gIncommingHighlightedBubble) { UIImage *defaultImage = [[TUIImageCache sharedInstance] getResourceFromCache:TUIChatImagePath(@"ReceiverTextNodeBkgHL")]; - gIncommingHighlightedBubble = - [TUIChatDynamicImage(@"chat_bubble_receive_img", defaultImage) resizableImageWithCapInsets:UIEdgeInsetsFromString(@"{12,12,12,12}") - resizingMode:UIImageResizingModeStretch]; + UIImage *formatImage = TUIChatDynamicImage(@"chat_bubble_receive_img", defaultImage); + formatImage = [formatImage rtl_imageFlippedForRightToLeftLayoutDirection]; + UIEdgeInsets ei = UIEdgeInsetsFromString(@"{12,12,12,12}"); + ei = rtlEdgeInsetsWithInsets(ei); + gIncommingHighlightedBubble = [formatImage resizableImageWithCapInsets:ei resizingMode:UIImageResizingModeStretch]; } return gIncommingHighlightedBubble; } @@ -214,9 +244,11 @@ static UIImage *gOutgoingAnimatedHighlightedAlpha50; + (UIImage *)outgoingAnimatedHighlightedAlpha50 { if (!gOutgoingAnimatedHighlightedAlpha50) { UIImage *alpha50 = [[TUIImageCache sharedInstance] getResourceFromCache:TUIChatImagePath(@"SenderTextNodeBkg_alpha50")]; - gOutgoingAnimatedHighlightedAlpha50 = - [TUIChatDynamicImage(@"chat_bubble_send_alpha50_img", alpha50) resizableImageWithCapInsets:UIEdgeInsetsFromString(@"{12,12,12,12}") - resizingMode:UIImageResizingModeStretch]; + UIImage *formatImage = TUIChatDynamicImage(@"chat_bubble_send_alpha50_img", alpha50); + formatImage = [formatImage rtl_imageFlippedForRightToLeftLayoutDirection]; + UIEdgeInsets ei = UIEdgeInsetsFromString(@"{12,12,12,12}"); + ei = rtlEdgeInsetsWithInsets(ei); + gOutgoingAnimatedHighlightedAlpha50 = [formatImage resizableImageWithCapInsets:ei resizingMode:UIImageResizingModeStretch]; } return gOutgoingAnimatedHighlightedAlpha50; } @@ -230,9 +262,11 @@ static UIImage *gOutgoingAnimatedHighlightedAlpha20; + (UIImage *)outgoingAnimatedHighlightedAlpha20 { if (!gOutgoingAnimatedHighlightedAlpha20) { UIImage *alpha20 = [[TUIImageCache sharedInstance] getResourceFromCache:TUIChatImagePath(@"SenderTextNodeBkg_alpha20")]; - gOutgoingAnimatedHighlightedAlpha20 = - [TUIChatDynamicImage(@"chat_bubble_send_alpha20_img", alpha20) resizableImageWithCapInsets:UIEdgeInsetsFromString(@"{12,12,12,12}") - resizingMode:UIImageResizingModeStretch]; + UIImage *formatImage = TUIChatDynamicImage(@"chat_bubble_send_alpha20_img", alpha20); + formatImage = [formatImage rtl_imageFlippedForRightToLeftLayoutDirection]; + UIEdgeInsets ei = UIEdgeInsetsFromString(@"{12,12,12,12}"); + ei = rtlEdgeInsetsWithInsets(ei); + gOutgoingAnimatedHighlightedAlpha20 = [formatImage resizableImageWithCapInsets:ei resizingMode:UIImageResizingModeStretch]; } return gOutgoingAnimatedHighlightedAlpha20; } @@ -245,9 +279,11 @@ static UIImage *gIncommingAnimatedHighlightedAlpha50; + (UIImage *)incommingAnimatedHighlightedAlpha50 { if (!gIncommingAnimatedHighlightedAlpha50) { UIImage *alpha50 = [[TUIImageCache sharedInstance] getResourceFromCache:TUIChatImagePath(@"ReceiverTextNodeBkg_alpha50")]; - gIncommingAnimatedHighlightedAlpha50 = - [TUIChatDynamicImage(@"chat_bubble_receive_alpha50_img", alpha50) resizableImageWithCapInsets:UIEdgeInsetsFromString(@"{12,12,12,12}") - resizingMode:UIImageResizingModeStretch]; + UIImage *formatImage = TUIChatDynamicImage(@"chat_bubble_receive_alpha50_img", alpha50); + formatImage = [formatImage rtl_imageFlippedForRightToLeftLayoutDirection]; + UIEdgeInsets ei = UIEdgeInsetsFromString(@"{12,12,12,12}"); + ei = rtlEdgeInsetsWithInsets(ei); + gIncommingAnimatedHighlightedAlpha50 = [formatImage resizableImageWithCapInsets:ei resizingMode:UIImageResizingModeStretch]; } return gIncommingAnimatedHighlightedAlpha50; } @@ -260,9 +296,11 @@ static UIImage *gIncommingAnimatedHighlightedAlpha20; + (UIImage *)incommingAnimatedHighlightedAlpha20 { if (!gIncommingAnimatedHighlightedAlpha20) { UIImage *alpha20 = [[TUIImageCache sharedInstance] getResourceFromCache:TUIChatImagePath(@"ReceiverTextNodeBkg_alpha20")]; - gIncommingAnimatedHighlightedAlpha20 = - [TUIChatDynamicImage(@"chat_bubble_receive_alpha20_img", alpha20) resizableImageWithCapInsets:UIEdgeInsetsFromString(@"{12,12,12,12}") - resizingMode:UIImageResizingModeStretch]; + UIImage *formatImage = TUIChatDynamicImage(@"chat_bubble_receive_alpha20_img", alpha20); + formatImage = [formatImage rtl_imageFlippedForRightToLeftLayoutDirection]; + UIEdgeInsets ei = UIEdgeInsetsFromString(@"{12,12,12,12}"); + ei = rtlEdgeInsetsWithInsets(ei); + gIncommingAnimatedHighlightedAlpha20 = [formatImage resizableImageWithCapInsets:ei resizingMode:UIImageResizingModeStretch]; } return gIncommingAnimatedHighlightedAlpha20; } diff --git a/iOS/TUIKit/TIMCommon/UI_Minimalist/TUIBubbleMessageCell_Minimalist.m b/iOS/TUIKit/TIMCommon/UI_Minimalist/TUIBubbleMessageCell_Minimalist.m index 9cf626991..2790577aa 100644 --- a/iOS/TUIKit/TIMCommon/UI_Minimalist/TUIBubbleMessageCell_Minimalist.m +++ b/iOS/TUIKit/TIMCommon/UI_Minimalist/TUIBubbleMessageCell_Minimalist.m @@ -33,11 +33,37 @@ self.bubbleView.image = self.getBubble; self.bubbleView.highlightedImage = self.getHighlightBubble; } + // tell constraints they need updating + [self setNeedsUpdateConstraints]; + + // update constraints now so we can animate the change + [self updateConstraintsIfNeeded]; + + [self layoutIfNeeded]; +} + ++ (BOOL)requiresConstraintBasedLayout { + return YES; +} + +// this is Apple's recommended place for adding/updating constraints +- (void)updateConstraints { + + [super updateConstraints]; + [self.bubbleView mas_remakeConstraints:^(MASConstraintMaker *make) { + make.leading.mas_equalTo(self.getBubbleTop); + make.size.mas_equalTo(self.container); + make.top.mas_equalTo(self.container); + }]; + + CGPoint center = self.retryView.center; + center.y = self.bubbleView.center.y; + self.retryView.center = center; + } - (void)layoutSubviews { [super layoutSubviews]; - self.bubbleView.mm_top(self.getBubbleTop); } - (void)highlightWhenMatchKeyword:(NSString *)keyword { @@ -121,12 +147,16 @@ - (UIImage *)getSameMessageBubble { UIImage *bubble_SameMsg = nil; + UIEdgeInsets ei = UIEdgeInsetsFromString(@"{12,12,12,12}"); + ei = rtlEdgeInsetsWithInsets(ei); if (self.bubbleData.direction == MsgDirectionIncoming) { UIImage *defaultImage = [[TUIImageCache sharedInstance] getResourceFromCache:TUIChatImagePath_Minimalist(@"ReceiverTextNodeBkg_Same")]; - bubble_SameMsg = [defaultImage resizableImageWithCapInsets:UIEdgeInsetsFromString(@"{12,12,12,12}") resizingMode:UIImageResizingModeStretch]; + defaultImage = [defaultImage rtl_imageFlippedForRightToLeftLayoutDirection]; + bubble_SameMsg = [defaultImage resizableImageWithCapInsets:ei resizingMode:UIImageResizingModeStretch]; } else { UIImage *defaultImage = [[TUIImageCache sharedInstance] getResourceFromCache:TUIChatImagePath_Minimalist(@"SenderTextNodeBkg_Same")]; - bubble_SameMsg = [defaultImage resizableImageWithCapInsets:UIEdgeInsetsFromString(@"{12,12,12,12}") resizingMode:UIImageResizingModeStretch]; + defaultImage = [defaultImage rtl_imageFlippedForRightToLeftLayoutDirection]; + bubble_SameMsg = [defaultImage resizableImageWithCapInsets:ei resizingMode:UIImageResizingModeStretch]; } return bubble_SameMsg; } @@ -156,7 +186,10 @@ static UIImage *gOutgoingBubble; + (UIImage *)outgoingBubble { if (!gOutgoingBubble) { UIImage *defaultImage = [[TUIImageCache sharedInstance] getResourceFromCache:TUIChatImagePath_Minimalist(@"SenderTextNodeBkg")]; - gOutgoingBubble = [defaultImage resizableImageWithCapInsets:UIEdgeInsetsFromString(@"{12,12,12,12}") resizingMode:UIImageResizingModeStretch]; + defaultImage = [defaultImage rtl_imageFlippedForRightToLeftLayoutDirection]; + UIEdgeInsets ei = UIEdgeInsetsFromString(@"{12,12,12,12}"); + ei = rtlEdgeInsetsWithInsets(ei); + gOutgoingBubble = [defaultImage resizableImageWithCapInsets:ei resizingMode:UIImageResizingModeStretch]; } return gOutgoingBubble; } @@ -169,7 +202,10 @@ static UIImage *gOutgoingHighlightedBubble; + (UIImage *)outgoingHighlightedBubble { if (!gOutgoingHighlightedBubble) { UIImage *defaultImage = [[TUIImageCache sharedInstance] getResourceFromCache:TUIChatImagePath_Minimalist(@"SenderTextNodeBkg")]; - gOutgoingHighlightedBubble = [defaultImage resizableImageWithCapInsets:UIEdgeInsetsFromString(@"{12,12,12,12}") + defaultImage = [defaultImage rtl_imageFlippedForRightToLeftLayoutDirection]; + UIEdgeInsets ei = UIEdgeInsetsFromString(@"{12,12,12,12}"); + ei = rtlEdgeInsetsWithInsets(ei); + gOutgoingHighlightedBubble = [defaultImage resizableImageWithCapInsets:ei resizingMode:UIImageResizingModeStretch]; } return gOutgoingHighlightedBubble; @@ -183,7 +219,10 @@ static UIImage *gIncommingBubble; + (UIImage *)incommingBubble { if (!gIncommingBubble) { UIImage *defaultImage = [[TUIImageCache sharedInstance] getResourceFromCache:TUIChatImagePath_Minimalist(@"ReceiverTextNodeBkg")]; - gIncommingBubble = [defaultImage resizableImageWithCapInsets:UIEdgeInsetsFromString(@"{12,12,12,12}") resizingMode:UIImageResizingModeStretch]; + defaultImage = [defaultImage rtl_imageFlippedForRightToLeftLayoutDirection]; + UIEdgeInsets ei = UIEdgeInsetsFromString(@"{12,12,12,12}"); + ei = rtlEdgeInsetsWithInsets(ei); + gIncommingBubble = [defaultImage resizableImageWithCapInsets:ei resizingMode:UIImageResizingModeStretch]; } return gIncommingBubble; } @@ -196,7 +235,10 @@ static UIImage *gIncommingHighlightedBubble; + (UIImage *)incommingHighlightedBubble { if (!gIncommingHighlightedBubble) { UIImage *defaultImage = [[TUIImageCache sharedInstance] getResourceFromCache:TUIChatImagePath_Minimalist(@"ReceiverTextNodeBkg")]; - gIncommingHighlightedBubble = [defaultImage resizableImageWithCapInsets:UIEdgeInsetsFromString(@"{12,12,12,12}") + defaultImage = [defaultImage rtl_imageFlippedForRightToLeftLayoutDirection]; + UIEdgeInsets ei = UIEdgeInsetsFromString(@"{12,12,12,12}"); + ei = rtlEdgeInsetsWithInsets(ei); + gIncommingHighlightedBubble = [defaultImage resizableImageWithCapInsets:ei resizingMode:UIImageResizingModeStretch]; } return gIncommingHighlightedBubble; @@ -211,9 +253,11 @@ static UIImage *gOutgoingAnimatedHighlightedAlpha50; + (UIImage *)outgoingAnimatedHighlightedAlpha50 { if (!gOutgoingAnimatedHighlightedAlpha50) { UIImage *alpha50 = [[TUIImageCache sharedInstance] getResourceFromCache:TUIChatImagePath(@"SenderTextNodeBkg_alpha50")]; + alpha50 = [alpha50 rtl_imageFlippedForRightToLeftLayoutDirection]; + UIEdgeInsets ei = UIEdgeInsetsFromString(@"{12,12,12,12}"); + ei = rtlEdgeInsetsWithInsets(ei); gOutgoingAnimatedHighlightedAlpha50 = - [TUIChatDynamicImage(@"chat_bubble_send_alpha50_img", alpha50) resizableImageWithCapInsets:UIEdgeInsetsFromString(@"{12,12,12,12}") - resizingMode:UIImageResizingModeStretch]; + [TUIChatDynamicImage(@"chat_bubble_send_alpha50_img", alpha50) resizableImageWithCapInsets:ei resizingMode:UIImageResizingModeStretch]; } return gOutgoingAnimatedHighlightedAlpha50; } @@ -227,9 +271,11 @@ static UIImage *gOutgoingAnimatedHighlightedAlpha20; + (UIImage *)outgoingAnimatedHighlightedAlpha20 { if (!gOutgoingAnimatedHighlightedAlpha20) { UIImage *alpha20 = [[TUIImageCache sharedInstance] getResourceFromCache:TUIChatImagePath(@"SenderTextNodeBkg_alpha20")]; + alpha20 = [alpha20 rtl_imageFlippedForRightToLeftLayoutDirection]; + UIEdgeInsets ei = UIEdgeInsetsFromString(@"{12,12,12,12}"); + ei = rtlEdgeInsetsWithInsets(ei); gOutgoingAnimatedHighlightedAlpha20 = - [TUIChatDynamicImage(@"chat_bubble_send_alpha20_img", alpha20) resizableImageWithCapInsets:UIEdgeInsetsFromString(@"{12,12,12,12}") - resizingMode:UIImageResizingModeStretch]; + [TUIChatDynamicImage(@"chat_bubble_send_alpha20_img", alpha20) resizableImageWithCapInsets:ei resizingMode:UIImageResizingModeStretch]; } return gOutgoingAnimatedHighlightedAlpha20; } @@ -242,8 +288,11 @@ static UIImage *gIncommingAnimatedHighlightedAlpha50; + (UIImage *)incommingAnimatedHighlightedAlpha50 { if (!gIncommingAnimatedHighlightedAlpha50) { UIImage *alpha50 = [[TUIImageCache sharedInstance] getResourceFromCache:TUIChatImagePath(@"ReceiverTextNodeBkg_alpha50")]; + alpha50 = [alpha50 rtl_imageFlippedForRightToLeftLayoutDirection]; + UIEdgeInsets ei = UIEdgeInsetsFromString(@"{12,12,12,12}"); + ei = rtlEdgeInsetsWithInsets(ei); gIncommingAnimatedHighlightedAlpha50 = - [TUIChatDynamicImage(@"chat_bubble_receive_alpha50_img", alpha50) resizableImageWithCapInsets:UIEdgeInsetsFromString(@"{12,12,12,12}") + [TUIChatDynamicImage(@"chat_bubble_receive_alpha50_img", alpha50) resizableImageWithCapInsets:ei resizingMode:UIImageResizingModeStretch]; } return gIncommingAnimatedHighlightedAlpha50; @@ -257,9 +306,11 @@ static UIImage *gIncommingAnimatedHighlightedAlpha20; + (UIImage *)incommingAnimatedHighlightedAlpha20 { if (!gIncommingAnimatedHighlightedAlpha20) { UIImage *alpha20 = [[TUIImageCache sharedInstance] getResourceFromCache:TUIChatImagePath(@"ReceiverTextNodeBkg_alpha20")]; + alpha20 = [alpha20 rtl_imageFlippedForRightToLeftLayoutDirection]; + UIEdgeInsets ei = UIEdgeInsetsFromString(@"{12,12,12,12}"); + ei = rtlEdgeInsetsWithInsets(ei); gIncommingAnimatedHighlightedAlpha20 = - [TUIChatDynamicImage(@"chat_bubble_receive_alpha20_img", alpha20) resizableImageWithCapInsets:UIEdgeInsetsFromString(@"{12,12,12,12}") - resizingMode:UIImageResizingModeStretch]; + [TUIChatDynamicImage(@"chat_bubble_receive_alpha20_img", alpha20) resizableImageWithCapInsets:ei resizingMode:UIImageResizingModeStretch]; } return gIncommingAnimatedHighlightedAlpha20; } diff --git a/iOS/TUIKit/TIMCommon/UI_Minimalist/TUIMessageCell_Minimalist.m b/iOS/TUIKit/TIMCommon/UI_Minimalist/TUIMessageCell_Minimalist.m index 0848c8c24..58612e53f 100644 --- a/iOS/TUIKit/TIMCommon/UI_Minimalist/TUIMessageCell_Minimalist.m +++ b/iOS/TUIKit/TIMCommon/UI_Minimalist/TUIMessageCell_Minimalist.m @@ -38,12 +38,17 @@ _replyEmojiCount = [[UILabel alloc] init]; [_replyEmojiCount setTextColor:RGBA(153, 153, 153, 1)]; - [_replyEmojiCount setTextAlignment:NSTextAlignmentLeft]; + _replyEmojiCount.rtlAlignment = TUITextRTLAlignmentLeading; [_replyEmojiCount setFont:[UIFont systemFontOfSize:12]]; [_replyEmojiView addSubview:_replyEmojiCount]; [self.messageModifyRepliesButton.titleLabel setFont:[UIFont systemFontOfSize:12]]; - [self.messageModifyRepliesButton setContentHorizontalAlignment:UIControlContentHorizontalAlignmentLeft]; + if(isRTL()) { + self.messageModifyRepliesButton.contentHorizontalAlignment = UIControlContentHorizontalAlignmentRight; + } + else { + self.messageModifyRepliesButton.contentHorizontalAlignment = UIControlContentHorizontalAlignmentLeft; + } [self.messageModifyRepliesButton setTitleColor:RGBA(0, 95, 255, 1) forState:UIControlStateNormal]; _msgStatusView = [[UIImageView alloc] initWithFrame:CGRectZero]; @@ -57,7 +62,7 @@ _msgTimeLabel = [[UILabel alloc] initWithFrame:CGRectZero]; _msgTimeLabel.textColor = RGB(102, 102, 102); _msgTimeLabel.font = [UIFont systemFontOfSize:12]; - _msgTimeLabel.textAlignment = NSTextAlignmentRight; + _msgTimeLabel.rtlAlignment = TUITextRTLAlignmentTrailing; _msgTimeLabel.layer.zPosition = CGFLOAT_MAX; [self.container addSubview:_msgTimeLabel]; @@ -87,6 +92,289 @@ } } ++ (BOOL)requiresConstraintBasedLayout { + return YES; +} + +// this is Apple's recommended place for adding/updating constraints +- (void)updateConstraints { + + [super updateConstraints]; + TUIMessageCellLayout *cellLayout = self.messageData.cellLayout; + BOOL isInComing = (self.messageData.direction == MsgDirectionIncoming); + + [self.nameLabel mas_remakeConstraints:^(MASConstraintMaker *make) { + if (isInComing) { + make.leading.mas_equalTo(self.container.mas_leading).mas_offset(7); + } else { + make.trailing.mas_equalTo(self.container.mas_trailing); + } + if (self.messageData.showName) { + make.width.mas_greaterThanOrEqualTo(20); + make.height.mas_greaterThanOrEqualTo(20); + } else { + make.height.mas_equalTo(0); + } + make.top.mas_equalTo(self.avatarView.mas_top); + }]; + + [self.selectedIcon mas_remakeConstraints:^(MASConstraintMaker *make) { + make.leading.mas_equalTo(self.contentView.mas_leading).mas_offset(3); + make.centerY.mas_equalTo(self.container.mas_centerY); + if (self.messageData.showCheckBox) { + make.width.mas_equalTo(20); + make.height.mas_equalTo(20); + } else { + make.size.mas_equalTo(CGSizeZero); + } + }]; + + [self.timeLabel sizeToFit]; + [self.timeLabel mas_updateConstraints:^(MASConstraintMaker *make) { + if (self.messageData.showMessageTime) { + make.width.mas_equalTo(self.timeLabel.frame.size.width); + make.height.mas_equalTo(self.timeLabel.frame.size.height); + } else { + make.width.mas_equalTo(0); + make.height.mas_equalTo(0); + } + }]; + + CGSize csize = [self.class getContentSize:self.messageData]; + CGFloat contentWidth = csize.width; + CGFloat contentHeight = csize.height; + + if (self.messageData.direction == MsgDirectionIncoming) { + self.avatarView.hidden = !self.messageData.showAvatar; + [self.avatarView mas_remakeConstraints:^(MASConstraintMaker *make) { + if (self.messageData.showCheckBox) { + make.leading.mas_equalTo(self.selectedIcon.mas_trailing).mas_offset(cellLayout.avatarInsets.left); + } else { + make.leading.mas_equalTo(self.contentView.mas_leading).mas_offset(cellLayout.avatarInsets.left); + } + make.top.mas_equalTo(cellLayout.avatarInsets.top); + make.size.mas_equalTo(cellLayout.avatarSize); + }]; + + [self.container mas_remakeConstraints:^(MASConstraintMaker *make) { + make.leading.mas_equalTo(self.avatarView.mas_trailing).mas_offset(cellLayout.messageInsets.left); + make.top.mas_equalTo(self.nameLabel.mas_bottom).mas_offset(cellLayout.messageInsets.top); + make.width.mas_equalTo(contentWidth); + make.height.mas_equalTo(contentHeight); + }]; + + CGRect indicatorFrame = self.indicator.frame; + [self.indicator mas_remakeConstraints:^(MASConstraintMaker *make) { + make.leading.mas_equalTo(self.container.mas_trailing).mas_offset(8); + make.centerY.mas_equalTo(self.container.mas_centerY); + make.size.mas_equalTo(indicatorFrame.size); + }]; + self.retryView.frame = self.indicator.frame; + self.readReceiptLabel.hidden = YES; + } else { + if (self.messageData.showAvatar) { + cellLayout.avatarSize = CGSizeMake(40, 40); + } else { + cellLayout.avatarSize = CGSizeZero; + } + [self.avatarView mas_remakeConstraints:^(MASConstraintMaker *make) { + make.trailing.mas_equalTo(self.contentView.mas_trailing).mas_offset(-cellLayout.avatarInsets.right); + make.top.mas_equalTo(cellLayout.avatarInsets.top); + make.size.mas_equalTo(cellLayout.avatarSize); + }]; + [self.container mas_remakeConstraints:^(MASConstraintMaker *make) { + make.trailing.mas_equalTo(self.avatarView.mas_leading).mas_offset(-cellLayout.messageInsets.right); + make.top.mas_equalTo(self.nameLabel.mas_bottom).mas_offset(cellLayout.messageInsets.top); + make.width.mas_equalTo(contentWidth); + make.height.mas_equalTo(contentHeight); + }]; + + CGRect indicatorFrame = self.indicator.frame; + [self.indicator mas_remakeConstraints:^(MASConstraintMaker *make) { + make.trailing.mas_equalTo(self.container.mas_leading).mas_offset(-8); + make.centerY.mas_equalTo(self.container.mas_centerY); + make.size.mas_equalTo(indicatorFrame.size); + }]; + + self.retryView.frame = self.indicator.frame; + + [self.readReceiptLabel sizeToFit]; + [self.readReceiptLabel mas_remakeConstraints:^(MASConstraintMaker *make) { + make.bottom.mas_equalTo(self.container.mas_bottom); + make.trailing.mas_equalTo(self.container.mas_leading).mas_offset(-8); + make.size.mas_equalTo(self.readReceiptLabel.frame.size); + }]; + } + + if (!self.messageModifyRepliesButton.isHidden) { + self.messageModifyRepliesButton.mm_sizeToFit(); + CGFloat repliesBtnTextWidth = self.messageModifyRepliesButton.frame.size.width; + [self.messageModifyRepliesButton mas_remakeConstraints:^(MASConstraintMaker *make) { + if (isInComing) { + make.leading.mas_equalTo(self.container.mas_leading); + } else { + make.trailing.mas_equalTo(self.container.mas_trailing); + } + make.top.mas_equalTo(self.container.mas_bottom); + make.size.mas_equalTo(CGSizeMake(repliesBtnTextWidth + 10, 30)); + }]; + } + + if (self.tagView) { + [self.tagView mas_remakeConstraints:^(MASConstraintMaker *make) { + make.trailing.mas_equalTo(self.container.mas_trailing); + make.bottom.mas_equalTo(self.container.mas_bottom); + make.size.mas_equalTo(CGSizeZero); + }]; + } + + CGSize contentSize = [self.class getContentSize:self.messageData]; + + if ((self.messageData.messageModifyReacts.count > 0) &&_replyEmojiImageViews.count > 0) { + CGFloat emojiSize = 12; + CGFloat emojiSpace = kScale390(4); + __block UIImageView * preEmojiView = nil; + for (int i = 0; i < _replyEmojiImageViews.count; ++i) { + UIImageView *emojiView = _replyEmojiImageViews[i]; + if (i == 0) { + preEmojiView = nil; + } + else { + preEmojiView = _replyEmojiImageViews[i-1]; + } + [emojiView mas_remakeConstraints:^(MASConstraintMaker *make) { + if (i == 0){ + make.leading.mas_equalTo(_replyEmojiView.mas_leading).mas_offset(kScale390(8)); + } + else { + make.leading.mas_equalTo(preEmojiView.mas_trailing).mas_offset(emojiSpace); + } + make.width.height.mas_equalTo(emojiSize); + make.centerY.mas_equalTo(_replyEmojiView.mas_centerY); + }]; + emojiView.layer.masksToBounds = YES; + emojiView.layer.cornerRadius = emojiSize / 2.0; + } + UIImageView * lastEmojiView = _replyEmojiImageViews.lastObject; + [_replyEmojiCount mas_remakeConstraints:^(MASConstraintMaker *make) { + make.leading.mas_equalTo(lastEmojiView.mas_trailing).mas_offset(kScale390(8)); + make.trailing.mas_equalTo(_replyEmojiView.mas_trailing); + make.width.mas_equalTo(emojiSize + 10); + make.height.mas_equalTo(emojiSize); + make.centerY.mas_equalTo(_replyEmojiView.mas_centerY); + }]; + + [_replyEmojiView mas_remakeConstraints:^(MASConstraintMaker *make) { + if (self.messageData.direction == MsgDirectionIncoming) { + make.leading.mas_greaterThanOrEqualTo(self.container).mas_offset(kScale390(16)); + } else { + make.trailing.mas_lessThanOrEqualTo(self.container).mas_offset(-kScale390(16)); + } + make.top.mas_equalTo(self.container.mas_bottom).mas_offset(-4); + make.height.mas_equalTo(20); + }]; + } else { + _replyEmojiCount.frame = CGRectZero; + _replyEmojiView.frame = CGRectZero; + } + + if (self.messageData.showMessageModifyReplies && _replyAvatarImageViews.count > 0) { + CGFloat lineViewW = 17; + CGFloat avatarSize = 16; + CGFloat repliesBtnW = kScale390(50); + CGFloat avatarY = self.contentView.mm_h - (self.messageData.sameToNextMsgSender ? avatarSize : avatarSize * 2); + if (self.messageData.direction == MsgDirectionIncoming) { + UIImageView *preAvatarImageView = nil; + for (int i = 0; i < _replyAvatarImageViews.count; ++i) { + UIImageView *avatarView = _replyAvatarImageViews[i]; + if (i == 0) { + preAvatarImageView = nil; + } + else { + preAvatarImageView = _replyAvatarImageViews[i-1]; + } + [avatarView mas_remakeConstraints:^(MASConstraintMaker *make) { + if (i == 0) { + make.leading.mas_equalTo(_replyLineView.mas_trailing); + } + else { + make.leading.mas_equalTo(preAvatarImageView.mas_centerX); + } + make.top.mas_equalTo(avatarY); + make.width.height.mas_equalTo(avatarSize); + + }]; + avatarView.layer.masksToBounds = YES; + avatarView.layer.cornerRadius = avatarSize / 2.0; + } + } + else { + __block UIImageView *preAvatarImageView = nil; + NSInteger count = _replyAvatarImageViews.count; + for (NSInteger i = (count - 1); i >=0; i--) { + UIImageView *avatarView = _replyAvatarImageViews[i]; + [avatarView mas_remakeConstraints:^(MASConstraintMaker *make) { + if (!preAvatarImageView) { + make.trailing.mas_equalTo(self.messageModifyRepliesButton.mas_leading); + } + else { + make.trailing.mas_equalTo(preAvatarImageView.mas_centerX); + } + make.top.mas_equalTo(avatarY); + make.width.height.mas_equalTo(avatarSize); + }]; + avatarView.layer.masksToBounds = YES; + avatarView.layer.cornerRadius = avatarSize / 2.0; + preAvatarImageView = avatarView; + } + } + + UIImageView *lastAvatarImageView = _replyAvatarImageViews.lastObject; + + [self.messageModifyRepliesButton mas_remakeConstraints:^(MASConstraintMaker *make) { + if (self.messageData.direction == MsgDirectionIncoming) { + make.leading.mas_equalTo(lastAvatarImageView.mas_trailing); + } + else { + make.trailing.mas_equalTo(_replyLineView.mas_leading); + } + + make.top.mas_equalTo(avatarY); + make.width.mas_equalTo(repliesBtnW); + make.height.mas_equalTo(avatarSize); + }]; + + [_replyLineView mas_remakeConstraints:^(MASConstraintMaker *make) { + if (self.messageData.direction == MsgDirectionIncoming) { + make.leading.mas_equalTo(self.container.mas_leading).mas_offset(- 1); + } + else { + make.trailing.mas_equalTo(self.container.mas_trailing); + } + make.top.mas_equalTo(CGRectGetMaxY(self.container.frame) - 14); + make.width.mas_equalTo(lineViewW); + make.bottom.mas_equalTo(self.messageModifyRepliesButton.mas_centerY); + }]; + } else { + _replyLineView.frame = CGRectZero; + self.messageModifyRepliesButton.frame = CGRectZero; + } + + [_msgTimeLabel mas_makeConstraints:^(MASConstraintMaker *make) { + make.width.mas_equalTo(38); + make.height.mas_equalTo(self.messageData.msgStatusSize.height); + make.bottom.mas_equalTo(self.container).mas_offset(-kScale390(9)); + make.trailing.mas_equalTo(self.container).mas_offset(-kScale390(16)); + }]; + [_msgStatusView mas_makeConstraints:^(MASConstraintMaker *make) { + make.width.mas_equalTo(16); + make.height.mas_equalTo(self.messageData.msgStatusSize.height); + make.bottom.mas_equalTo(self.msgTimeLabel); + make.trailing.mas_equalTo(_msgTimeLabel.mas_leading); + }]; + +} + - (void)fillWithData:(TUIMessageCellData *)data { [super fillWithData:data]; self.readReceiptLabel.hidden = YES; @@ -154,7 +442,10 @@ } else { lineImage = [[TUIImageCache sharedInstance] getResourceFromCache:TUIChatImagePath_Minimalist(@"msg_reply_line_outcome")]; } - _replyLineView.image = [lineImage resizableImageWithCapInsets:UIEdgeInsetsFromString(@"{10,0,20,0}") resizingMode:UIImageResizingModeStretch]; + lineImage = [lineImage rtl_imageFlippedForRightToLeftLayoutDirection]; + UIEdgeInsets ei = UIEdgeInsetsFromString(@"{10,0,20,0}"); + ei = rtlEdgeInsetsWithInsets(ei); + _replyLineView.image = [lineImage resizableImageWithCapInsets:ei resizingMode:UIImageResizingModeStretch]; // avtar NSInteger avatarCount = 0; @@ -191,6 +482,7 @@ self.indicator.hidden = YES; _msgStatusView.hidden = YES; + self.readReceiptLabel.hidden = YES; if (self.messageData.direction == MsgDirectionOutgoing) { self.status = TUIMessageStatus_Unkown; if (self.messageData.status == Msg_Status_Sending || self.messageData.status == Msg_Status_Sending_2) { @@ -200,6 +492,14 @@ } [self updateReadLabelText]; } + // tell constraints they need updating + [self setNeedsUpdateConstraints]; + + // update constraints now so we can animate the change + [self updateConstraintsIfNeeded]; + + [self layoutIfNeeded]; + } - (void)updateReadLabelText { @@ -260,75 +560,6 @@ - (void)layoutSubviews { [super layoutSubviews]; - - CGSize contentSize = [self.class getContentSize:self.messageData]; - - self.tagView.frame = CGRectZero; - if (!self.retryView.hidden) { - self.retryView.mm__centerY(contentSize.height / 2); - } - self.avatarView.mm_y = contentSize.height - self.avatarView.mm_h + 4; - - if (self.messageData.messageModifyReacts.count > 0) { - CGFloat emojiSize = 12; - CGFloat emojiY = kScale390(4); - CGFloat emojiSpace = kScale390(4); - CGFloat replyEmojiCountX = 0; - for (int i = 0; i < _replyEmojiImageViews.count; ++i) { - UIImageView *emojiView = _replyEmojiImageViews[i]; - emojiView.frame = CGRectMake(kScale390(8) + (emojiSpace + emojiSize) * i, emojiY, emojiSize, emojiSize); - emojiView.layer.masksToBounds = true; - emojiView.layer.cornerRadius = emojiSize / 2.0; - replyEmojiCountX = emojiView.mm_maxX + kScale390(8); - } - _replyEmojiCount.frame = CGRectMake(replyEmojiCountX, emojiY, emojiSize + 10, emojiSize); - - CGFloat emojiViewW = _replyEmojiCount.mm_x + _replyEmojiCount.mm_w; - CGFloat emojiViewX = (self.messageData.direction == MsgDirectionIncoming ? self.container.mm_x + kScale390(16) - : self.container.mm_x + self.container.mm_w - kScale390(16) - emojiViewW); - _replyEmojiView.frame = CGRectMake(emojiViewX, self.container.mm_maxY - 4, emojiViewW, 20); - } else { - _replyEmojiCount.frame = CGRectZero; - _replyEmojiView.frame = CGRectZero; - } - - if (self.messageData.showMessageModifyReplies) { - CGFloat lineViewW = 17; - CGFloat lineViewH = 0; - CGFloat lineViewX = (self.messageData.direction == MsgDirectionIncoming ? self.container.mm_x - 1 : self.container.mm_maxX - lineViewW); - _replyLineView.mm_left(lineViewX).mm_width(lineViewW).mm_height(lineViewH).mm_top(self.container.mm_maxY - 14); - - CGFloat avatarSize = 16; - CGFloat repliesBtnW = kScale390(50); - CGFloat avatarStartX = 0; - if (self.messageData.direction == MsgDirectionIncoming) { - avatarStartX = _replyLineView.mm_maxX; - } else { - CGFloat avatarTotalW = (_replyAvatarImageViews.count + 1) * avatarSize / 2; - avatarStartX = self.container.mm_maxX - repliesBtnW - avatarTotalW - 12; - } - CGFloat avatarY = self.contentView.mm_h - (self.messageData.sameToNextMsgSender ? avatarSize : avatarSize * 2); - CGFloat repliesBtnX = 0; - for (int i = 0; i < _replyAvatarImageViews.count; ++i) { - UIImageView *avatarView = _replyAvatarImageViews[i]; - avatarView.frame = CGRectMake(avatarStartX + i * avatarSize / 2.0, avatarY, avatarSize, avatarSize); - avatarView.layer.masksToBounds = true; - avatarView.layer.cornerRadius = avatarSize / 2.0; - repliesBtnX = avatarView.mm_maxX; - } - self.messageModifyRepliesButton.frame = CGRectMake(repliesBtnX, avatarY, repliesBtnW, avatarSize); - _replyLineView.mm_h = self.messageModifyRepliesButton.mm_centerY - _replyLineView.mm_y; - } else { - _replyLineView.frame = CGRectZero; - self.messageModifyRepliesButton.frame = CGRectZero; - } - - _msgTimeLabel.mm_width(38).mm_height(self.messageData.msgStatusSize.height).mm_bottom(9).mm_right(kScale390(16)); - _msgStatusView.mm_width(16).mm_height(self.messageData.msgStatusSize.height).mm_bottom(9).mm_left(_msgTimeLabel.mm_x - 16); - - if (self.messageData.showCheckBox) { - self.selectedIcon.mm_centerY = self.container.mm_centerY; - } } #pragma mark - TUIMessageCellProtocol diff --git a/iOS/TUIKit/TUICallKit/Resources/Localized/ar.lproj/CallingLocalized.strings b/iOS/TUIKit/TUICallKit/Resources/Localized/ar.lproj/CallingLocalized.strings new file mode 100644 index 000000000..cf96db7ed --- /dev/null +++ b/iOS/TUIKit/TUICallKit/Resources/Localized/ar.lproj/CallingLocalized.strings @@ -0,0 +1,86 @@ +/* + CallingLocalized.strings + TRTCCalling + + Created by noah on 2023/8/3. + */ + +"LoginNetwork.ProfileManager.sendfailed" = "فشل الإرسال، يرجى المحاولة مرة أخرى لاحقا"; +"V2.Live.LoginMock.sendtheverificatcode" = "يرجى إرسال رمز التحقق"; +"LoginNetwork.ProfileManager.loginfailed" = "فشل تسجيل الدخول، يرجى المحاولة مرة أخرى لاحقا"; +"LoginNetwork.ProfileManager.queryfailed" = "فشل الاستعلام، يرجى المحاولة مرة أخرى لاحقا"; +"LoginNetwork.ProfileManager.registerfailed" = "فشل التسجيل، يرجى المحاولة مرة أخرى لاحقا"; +"Demo.TRTC.calling.callingrequest" = "لديك طلب مكالمة"; +"Demo.TRTC.calling.syserror"= "خطأ في النظام"; +"Demo.TRTC.calling.yourphonenumber" = "رقم هاتفك "; +"Demo.TRTC.calling.searchphonenumber" = "البحث عن رقم الهاتف"; +"Demo.TRTC.calling.searching" = "جار البحث"; +"Demo.TRTC.calling.searchandcall" = "البحث وإضافة مستخدم مسجل\nلبدء المكالمة"; +"Demo.TRTC.calling.callingbegan" = "بدء المكالمة"; +"Demo.TRTC.calling.callingcancel" = "إلغاء المكالمة"; +"Demo.TRTC.calling.callingtimeout" = "انتهاء مهلة المكالمة"; +"Demo.TRTC.calling.callingrefuse" = "رفض المكالمة"; +"Demo.TRTC.calling.callingleave" = "مغادرة المكالمة"; +"Demo.TRTC.calling.callingnoresponse" = "لا يوجد استجابة"; +"Demo.TRTC.calling.callingbusy" = "خط مشغول"; +"Demo.TRTC.calling.searchingfailed" = "فشل الاستعلام"; +"Demo.TRTC.calling.cantinviteself" = "لا يمكن دعوة نفسك"; +"Demo.TRTC.calling.muteon" = "تشغيل الكتم"; +"Demo.TRTC.calling.muteoff" = "إيقاف الكتم"; +"Demo.TRTC.calling.handsfreeon" = "تشغيل الاستخدام بدون اليدين"; +"Demo.TRTC.calling.handsfreeoff" = "إيقاف الاستخدام بدون اليدين"; +"LoginNetwork.AppUtils.warmprompt" = "تلميح دافئ"; +"LoginNetwork.AppUtils.tomeettheregulatory" = "للتوافق مع متطلبات الإشراف الحكومي، يتم تسجيل جميع المكالمات الصوتية والمرئية في هذا التطبيق، ويحظر الإباحية والإهانات والعنف والمحتوى السياسي المخالف."; +"LoginNetwork.AppUtils.determine" = "تأكيد"; +"Demo.TRTC.calling.invitetovideocall" = "يدعوك لمكالمة فيديو"; +"Demo.TRTC.calling.invitetoaudiocall" = "يدعوك لمكالمة صوتية"; +"Demo.TRTC.Streaming.call" = "مكالمة"; + +"TUICallKit.Audio.call" = "مكالمة صوتية"; +"TUICallKit.Video.call" = "مكالمة فيديو"; + +"Demo.TRTC.Calling.waitaccept" = "انتظار قبول الطرف الآخر"; +"Demo.TRTC.Calling.hangup" = "إنهاء المكالمة"; +"Demo.TRTC.Calling.decline" = "رفض"; +"Demo.TRTC.Calling.mic" = "ميكروفون"; +"Demo.TRTC.Calling.speaker" = "مكبر الصوت"; +"Demo.TRTC.Calling.camera" = "كاميرا"; +"Demo.TRTC.Calling.switchtoaudio" = "التبديل إلى المكالمة الصوتية"; +"Demo.TRTC.Calling.answer" = "الرد"; +"Demo.TRTC.Calling.othernetworkpoor" = "شبكة الطرف الآخر ضعيفة"; +"Demo.TRTC.Calling.yournetworkpoor" = "شبكتك ضعيفة"; +"Demo.TRTC.Salon.invitelimited" = "الطلب قيد المعالجة ، يرجى المحاولة مرة أخرى لاحقًا"; +"Demo.TRTC.Login.countrycode" = "رمز الهاتف الدولي"; +"Demo.TRTC.Calling.calleeTip" = "هم أيضا هنا"; +"Demo.TRTC.Calling.FloatingWindow.waitaccept" = "في انتظار الرد"; +"Demo.TRTC.Calling.FloatingWindow.dailing" = "الاتصال ..."; + +"Demo.TRTC.Calling.User.Exceed.Limit" = "يدعم مكالمات مؤقتة لما يصل إلى 9 أشخاص. لاستخدام المؤتمرات متعددة الأطراف ، يرجى استخدام TUIRoom"; +"Demo.TRTC.Calling.UnableToRestartTheCall" = "لا يمكن إعادة بدء المكالمة أثناء المكالمة"; +"Demo.TRTC.Calling.ErrorInPeerBlacklist" = "المعرف في القائمة السوداء. فشل في إرسال هذه الرسالة!"; + +"TUICallKit.failedtogetcamerapermission.Title" = "لم يتم تمكين إذن الكاميرا"; +"TUICallKit.failedtogetcamerapermission.Tips" = "لا يمكن استخدام وظيفة المكالمة المرئية ، انقر فوق \"فتح\" لفتح إذن الكاميرا"; +"TUICallKit.failedtogetcamerapermission.Later" = "قل ذلك لاحقًا"; +"TUICallKit.failedtogetcamerapermission.Enable" = "فتح"; + +"TUICallKit.failedtogetmicrophonepermission.Title" = "لم يتم تمكين إذن الميكروفون"; +"TUICallKit.failedtogetmicrophonepermission.Tips" = "لا يمكن استخدام وظيفة إرسال المكالمات الصوتية والمرئية ، انقر فوق \"فتح\" لفتح إذن الميكروفون"; +"TUICallKit.failedtogetmicrophonepermission.Later" = "قل ذلك لاحقًا"; +"TUICallKit.failedtogetmicrophonepermission.Enable" = "فتح"; + +"TUICallKit.package.not.purchased" = "لم تشترِ حزمة قدرات المكالمات الصوتية والمرئية ، يرجى الانتقال إلى لوحة تحكم IM لتجربة مجانية أو شراء الإصدار الرسمي"; +"TUICallKit.package.not.support" = "لا يدعم حزمة قدرات المكالمات الصوتية والمرئية التي اشتريتها حاليًا هذه الميزة ، نوصي بترقية نوع الحزمة"; +"TUICallKit.have.new.invitation" = "لديك مكالمة جديدة"; + +"TUICallKit.Recents.all" = "جميع المكالمات"; +"TUICallKit.Recents.missed" = "المكالمات الفائتة"; +"TUICallKit.Recents.calls" = "سجل المكالمات"; +"TUICallKit.Recents.clear" = "مسح"; +"TUICallKit.Recents.done" = "تم"; +"TUICallKit.Recents.delete" = "حذف"; +"TUICallKit.Recents.addUser" = "إضافة عضو"; +"TUICallKit.Recents.clear.all" = "مسح جميع السجلات"; +"TUICallKit.Recents.clear.cancel" = "إلغاء"; +"TUICallKit.Recents.incoming" = "وارد"; +"TUICallKit.Recents.outgoing" = "صادر"; diff --git a/iOS/TUIKit/TUICallKit/Resources/Localized/en.lproj/CallingLocalized.strings b/iOS/TUIKit/TUICallKit/Resources/Localized/en.lproj/CallingLocalized.strings index 8b688d06e..199c053e2 100644 --- a/iOS/TUIKit/TUICallKit/Resources/Localized/en.lproj/CallingLocalized.strings +++ b/iOS/TUIKit/TUICallKit/Resources/Localized/en.lproj/CallingLocalized.strings @@ -3,7 +3,6 @@ TRTCCalling Created by adams on 2021/5/13. - */ "LoginNetwork.ProfileManager.sendfailed" = "Send failed. Please try again later."; @@ -58,6 +57,7 @@ "Demo.TRTC.Calling.User.Exceed.Limit" = "TUICalling currently supports call with up to 9 people.For larger conference calls,try using TUIRoom"; "Demo.TRTC.Calling.UnableToRestartTheCall" = "Unable to restart the call"; +"Demo.TRTC.Calling.ErrorInPeerBlacklist" = "The identifier is in blacklist. Failed to send this message!"; "TUICallKit.failedtogetcamerapermission.Title" = "No access to camera"; "TUICallKit.failedtogetcamerapermission.Tips" = "Unable to use the video call function, click \"Authorize Now\" to open the camera permission."; @@ -82,3 +82,5 @@ "TUICallKit.Recents.addUser"= "Add User"; "TUICallKit.Recents.clear.all" = "Clear All Call History"; "TUICallKit.Recents.clear.cancel" = "Cancel"; +"TUICallKit.Recents.incoming" = "Incoming"; +"TUICallKit.Recents.outgoing" = "Outgoing"; diff --git a/iOS/TUIKit/TUICallKit/Resources/Localized/zh-Hans.lproj/CallingLocalized.strings b/iOS/TUIKit/TUICallKit/Resources/Localized/zh-Hans.lproj/CallingLocalized.strings index 440f63924..f98a388b4 100644 --- a/iOS/TUIKit/TUICallKit/Resources/Localized/zh-Hans.lproj/CallingLocalized.strings +++ b/iOS/TUIKit/TUICallKit/Resources/Localized/zh-Hans.lproj/CallingLocalized.strings @@ -3,7 +3,6 @@ TRTCCalling Created by adams on 2021/5/13. - */ "LoginNetwork.ProfileManager.sendfailed" = "发送失败,请稍后重试"; @@ -58,6 +57,7 @@ "Demo.TRTC.Calling.User.Exceed.Limit" = "暂支持最多9人通话。如需多人会议,请使用TUIRoom"; "Demo.TRTC.Calling.UnableToRestartTheCall" = "正在通话中,无法再次发起"; +"Demo.TRTC.Calling.ErrorInPeerBlacklist" = "发起通话失败,用户在黑名单中,禁止发起!"; "TUICallKit.failedtogetcamerapermission.Title" = "相机权限未开启"; "TUICallKit.failedtogetcamerapermission.Tips" = "无法使用视频通话功能,点击\"去开启\"打开相机权限"; @@ -82,3 +82,5 @@ "TUICallKit.Recents.addUser" = "添加成员"; "TUICallKit.Recents.clear.all" = "清除所有记录"; "TUICallKit.Recents.clear.cancel" = "取消"; +"TUICallKit.Recents.incoming" = "来电"; +"TUICallKit.Recents.outgoing" = "去电"; diff --git a/iOS/TUIKit/TUICallKit/TUICallKit-Swift/Data/Constants.swift b/iOS/TUIKit/TUICallKit/TUICallKit-Swift/Data/Constants.swift index 72f026c73..53895acba 100644 --- a/iOS/TUIKit/TUICallKit/TUICallKit-Swift/Data/Constants.swift +++ b/iOS/TUIKit/TUICallKit/TUICallKit-Swift/Data/Constants.swift @@ -7,31 +7,54 @@ // 默认头像 let TUI_CALL_DEFAULT_AVATAR: String = "https://imgcache.qq.com/qcloud/public/static//avatar1_100.20191230.png" -// TODO: 引用TUICore中的宏定义出错,现将出错的宏定义在此 +// MARK: 屏幕尺寸相关 let ScreenSize = UIScreen.main.bounds.size let Screen_Width = UIScreen.main.bounds.size.width let Screen_Height = UIScreen.main.bounds.size.height -let Is_Iphone = (UI_USER_INTERFACE_IDIOM() == .phone) -let Is_IPhoneX = (Screen_Width >= 375.0 && Screen_Height >= 812.0 && Is_Iphone) -let StatusBar_Height = Is_IPhoneX ? 44.0 : 20.0 -let Bottom_SafeHeight = Is_IPhoneX ? 34.0 : 0 +let StatusBar_Height: CGFloat = { + var statusBarHeight: CGFloat = 0 + if #available(iOS 13.0, *) { + statusBarHeight = UIApplication.shared.windows.first?.windowScene?.statusBarManager?.statusBarFrame.height ?? 0 + } else { + statusBarHeight = UIApplication.shared.statusBarFrame.height + } + return statusBarHeight +}() +let Bottom_SafeHeight = {var bottomSafeHeight: CGFloat = 0 + if #available(iOS 11.0, *) { + let window = UIApplication.shared.windows.first + bottomSafeHeight = window?.safeAreaInsets.bottom ?? 0 + } + return bottomSafeHeight +}() -// MARK: FloatWindow Param -public let kMicroAudioViewWidth = 80.0 -public let kMicroAudioViewHeight = 80.0 -public let kMicroVideoViewWidth = 100.0 -public let kMicroVideoViewHeight = (100.0 * 16) / 9.0 -public let kMicroAudioViewRect = CGRectMake(Screen_Width - kMicroAudioViewWidth, 150, kMicroAudioViewWidth, kMicroAudioViewHeight) -public let kMicroVideoViewRect = CGRectMake(Screen_Width - kMicroVideoViewWidth, 150, kMicroVideoViewWidth, kMicroVideoViewHeight) -public let kMicroVideoDisAvailableViewRect = CGRectMake(Screen_Width - kMicroVideoViewWidth, 150, kMicroVideoViewWidth, kMicroVideoViewHeight - 10) +// MARK: FloatWindow UI Param +let kMicroAudioViewWidth = 80.0 +let kMicroAudioViewHeight = 80.0 +let kMicroVideoViewWidth = 100.0 +let kMicroVideoViewHeight = (100.0 * 16) / 9.0 +let kMicroAudioViewRect = CGRect(x: Screen_Width - kMicroAudioViewWidth, y: 150, width: kMicroAudioViewWidth, height: kMicroAudioViewHeight) +let kMicroVideoViewRect = CGRect(x: Screen_Width - kMicroVideoViewWidth, y: 150, width: kMicroVideoViewWidth, height: kMicroVideoViewHeight) +let kMicroVideoDisAvailableViewRect = CGRect(x: Screen_Width - kMicroVideoViewWidth, + y: 150, + width: kMicroVideoViewWidth, + height: kMicroVideoViewHeight - 10) -// MARK: IM -let TMoreCell_Image_Size = CGSizeMake(65, 65) +// MARK: UI Size Param +let kFloatWindowButtonSize = CGSize(width: 30, height: 30) +let kInviteUserButtonSize = CGSize(width: 30, height: 30) +// MARK: TUICore & IM +let TMoreCell_Image_Size = CGSize(width: 65, height: 65) let TUI_CALLING_BELL_KEY = "CallingBell" let MAX_USER = 9 let ENABLE_MUTEMODE_USERDEFAULT = "ENABLE_MUTEMODE_USERDEFAULT" +let TUI_CALLKIT_SIGNALING_MAX_TIME : Int32 = 30 + +let kControlBtnSize = CGSize(width: 100, height: 92) +let kBtnLargeSize = CGSize(width: 64, height: 64) +let kBtnSmallSize = CGSize(width: 52, height: 52) class Constants { static let EVENT_SHOW_TUICALLKIT_VIEWCONTROLLER = "eventShowTUICallKitViewController" diff --git a/iOS/TUIKit/TUICallKit/TUICallKit-Swift/Data/OfflinePushInfoConfig.swift b/iOS/TUIKit/TUICallKit/TUICallKit-Swift/Data/OfflinePushInfoConfig.swift index 6a6924b37..727b0bec3 100644 --- a/iOS/TUIKit/TUICallKit/TUICallKit-Swift/Data/OfflinePushInfoConfig.swift +++ b/iOS/TUIKit/TUICallKit/TUICallKit-Swift/Data/OfflinePushInfoConfig.swift @@ -9,7 +9,6 @@ import Foundation import TUICallEngine class OfflinePushInfoConfig { - static func createOfflinePushInfo() -> TUIOfflinePushInfo { let pushInfo: TUIOfflinePushInfo = TUIOfflinePushInfo() pushInfo.title = "" @@ -19,11 +18,6 @@ class OfflinePushInfoConfig { pushInfo.ignoreIOSBadge = false pushInfo.iOSSound = "phone_ringing.mp3" pushInfo.androidSound = "phone_ringing" - // OPPO必须设置ChannelID才可以收到推送消息,这个channelID需要和控制台一致 - // OPPO must set a ChannelID to receive push messages. This channelID needs to be the same as the console. - pushInfo.androidOPPOChannelID = "tuikit" - // FCM channel ID, you need change PrivateConstants.java and set "fcmPushChannelId" - pushInfo.androidFCMChannelID = "fcm_push_channel" // VIVO message type: 0-push message, 1-System message(have a higher delivery rate) pushInfo.androidVIVOClassification = 1 // HuaWei message type: https://developer.huawei.com/consumer/cn/doc/development/HMSCore-Guides/message-classification-0000001149358835 diff --git a/iOS/TUIKit/TUICallKit/TUICallKit-Swift/Manager/CallEngineManager.swift b/iOS/TUIKit/TUICallKit/TUICallKit-Swift/Manager/CallEngineManager.swift index 5e23a0742..27a0afd80 100644 --- a/iOS/TUIKit/TUICallKit/TUICallKit-Swift/Manager/CallEngineManager.swift +++ b/iOS/TUIKit/TUICallKit/TUICallKit-Swift/Manager/CallEngineManager.swift @@ -16,12 +16,10 @@ import TXLiteAVSDK_Professional #endif class CallEngineManager { - static let instance = CallEngineManager() let engine = TUICallEngine.createInstance() func setSelfInfo(nickname: String, avatar: String, succ: @escaping TUICallSucc, fail: @escaping TUICallFail) { - engine.setSelfInfo(nickname: nickname, avatar: avatar) { TUICallState.instance.selfUser.value.avatar.value = avatar TUICallState.instance.selfUser.value.nickname.value = nickname @@ -30,15 +28,9 @@ class CallEngineManager { fail(code, message) } } - + func call(userId: String, callMediaType: TUICallMediaType, params: TUICallParams, succ: @escaping TUICallSucc, fail: @escaping TUICallFail) { - - let roomId = TUIRoomId() - roomId.intRoomId = TUICallKitCommon.createRoomId() - engine.call(roomId: roomId, userId: userId, callMediaType: callMediaType, params: params) { - - TUICallState.instance.roomId.value = roomId - + engine.call(userId: userId, callMediaType: callMediaType, params: params) { User.getUserInfosFromIM(userIDs: [userId]) { mInviteeList in TUICallState.instance.remoteUserList.value = mInviteeList @@ -47,14 +39,13 @@ class CallEngineManager { TUICallState.instance.remoteUserList.value[index].callRole.value = TUICallRole.called } } + TUICallState.instance.mediaType.value = callMediaType TUICallState.instance.scene.value = TUICallScene.single - TUICallState.instance.selfUser.value.callRole.value = TUICallRole.call TUICallState.instance.selfUser.value.callStatus.value = TUICallStatus.waiting let _ = CallingBellFeature.instance.playCallingBell(type: .CallingBellTypeDial) - succ() } fail: { code, message in fail(code,message) @@ -67,16 +58,10 @@ class CallEngineManager { params: TUICallParams, succ: @escaping TUICallSucc, fail: @escaping TUICallFail) { - let roomId = TUIRoomId() - roomId.intRoomId = TUICallKitCommon.createRoomId() - - engine.groupCall(roomId: roomId, - groupId: groupId, - userIdList: userIdList, - callMediaType: callMediaType, - params: params) { - - TUICallState.instance.roomId.value = roomId + engine.groupCall(groupId: groupId, + userIdList: userIdList, + callMediaType: callMediaType, + params: params) { TUICallState.instance.groupId.value = groupId User.getUserInfosFromIM(userIDs: userIdList) { mInviteeList in @@ -89,12 +74,11 @@ class CallEngineManager { TUICallState.instance.mediaType.value = callMediaType TUICallState.instance.scene.value = TUICallScene.group - + TUICallState.instance.selfUser.value.callRole.value = TUICallRole.call TUICallState.instance.selfUser.value.callStatus.value = TUICallStatus.waiting let _ = CallingBellFeature.instance.playCallingBell(type: .CallingBellTypeDial) - succ() } fail: { code, message in fail(code, message) @@ -103,43 +87,33 @@ class CallEngineManager { func joinInGroupCall(roomId: TUIRoomId, groupId: String, callMediaType: TUICallMediaType) { engine.joinInGroupCall(roomId: roomId, groupId: groupId, callMediaType: callMediaType) { - - TUICallState.instance.roomId.value = roomId - TUICallState.instance.mediaType.value = callMediaType TUICallState.instance.scene.value = TUICallScene.group TUICallState.instance.groupId.value = groupId - + TUICallState.instance.selfUser.value.callRole.value = TUICallRole.called TUICallState.instance.selfUser.value.callStatus.value = TUICallStatus.accept - + NotificationCenter.default.post(name: NSNotification.Name(rawValue: Constants.EVENT_SHOW_TUICALLKIT_VIEWCONTROLLER), object: nil) } fail: { code, message in - } } func hangup() { engine.hangup { - } fail: { code, message in - } } func accept() { engine.accept { - } fail: { code, message in - } } func reject() { engine.reject { - } fail: { code, message in - } } @@ -148,7 +122,6 @@ class CallEngineManager { engine.openMicrophone { TUICallState.instance.isMicMute.value = false } fail: { code , message in - } } else { engine.closeMicrophone() @@ -167,7 +140,7 @@ class CallEngineManager { } func switchCamera() { - if TUICallState.instance.isFrontCamera.value == .front { + if TUICallState.instance.isFrontCamera.value == .front { engine.switchCamera(.back) TUICallState.instance.isFrontCamera.value = .back } else { @@ -185,24 +158,20 @@ class CallEngineManager { engine.openCamera(TUICallState.instance.isFrontCamera.value == .front ? .front : .back, videoView: videoView) { TUICallState.instance.isCameraOpen.value = true } fail: { code, message in - } } func startRemoteView(user: User, videoView: TUIVideoView){ engine.startRemoteView(userId: user.id.value, videoView: videoView) { userId in - } onLoading: { userId in - } onError: { userId, code, message in - } } func stopRemoteView(user: User) { engine.stopRemoteView(userId: user.id.value) } - + func setAudioPlaybackDevice(device: TUIAudioPlaybackDevice) { engine.selectAudioPlaybackDevice(device) } @@ -212,11 +181,12 @@ class CallEngineManager { } func inviteUser(userIds: [String]) { - let params = TUICallParams() - params.offlinePushInfo = TUIOfflinePushInfo() - engine.inviteUser(userIdList: userIds, params: params) { userIds in + let callParams = TUICallParams() + callParams.offlinePushInfo = OfflinePushInfoConfig.createOfflinePushInfo() + callParams.timeout = TUI_CALLKIT_SIGNALING_MAX_TIME + + engine.inviteUser(userIdList: userIds, params: callParams) { userIds in User.getUserInfosFromIM(userIDs: userIds) { newRemoteUsers in - for newUser in newRemoteUsers { newUser.callStatus.value = TUICallStatus.waiting newUser.callRole.value = TUICallRole.called @@ -267,17 +237,40 @@ class CallEngineManager { var jsonParams: [String: Any] if TUICore.getService(TUICore_TUIChatService) == nil { jsonParams = ["api": "setFramework", - "params": ["component": 14, - "language": 3,],] + "params": ["component": 14, + "language": 3,],] } else { jsonParams = ["api": "setFramework", - "params": ["component": 15, - "language": 3,],] + "params": ["component": 15, + "language": 3,],] } + guard let data = try? JSONSerialization.data(withJSONObject: jsonParams, - options: JSONSerialization.WritingOptions(rawValue: 0)) else { return } - guard let paramsString = NSString(data: data, encoding: String.Encoding.utf8.rawValue) as? String else { return } + options: JSONSerialization.WritingOptions(rawValue: 0)) else { + return + } + guard let paramsString = NSString(data: data, encoding: String.Encoding.utf8.rawValue) as? String else { + return + } + + engine.callExperimentalAPI(jsonObject: paramsString) + } + + func setExcludeFromHistoryMessage() { + if TUICore.getService(TUICore_TUIChatService) == nil { + return + } + + let jsonParams: [String: Any] = ["api": "setExcludeFromHistoryMessage", + "params": ["excludeFromHistoryMessage": false,],] + guard let data = try? JSONSerialization.data(withJSONObject: jsonParams, + options: JSONSerialization.WritingOptions(rawValue: 0)) else { + return + } + guard let paramsString = NSString(data: data, encoding: String.Encoding.utf8.rawValue) as? String else { + return + } + engine.callExperimentalAPI(jsonObject: paramsString) } } - diff --git a/iOS/TUIKit/TUICallKit/TUICallKit-Swift/Service/Extension.swift b/iOS/TUIKit/TUICallKit/TUICallKit-Swift/Service/Extension.swift deleted file mode 100644 index c0ed1d2a1..000000000 --- a/iOS/TUIKit/TUICallKit/TUICallKit-Swift/Service/Extension.swift +++ /dev/null @@ -1,23 +0,0 @@ -// -// TUIExtension.swift -// TUIVideoSeat -// -// Created by WesleyLei on 2022/9/23. -// Copyright © 2022 Tencent. All rights reserved. -// - -import Foundation -import TUICore - -extension NSObject { - @objc class func swiftLoad() { - TUICore.registerService(TUICore_TUICallingService, object: TUICallKitService.instance) - - TUICore.registerExtension(TUICore_TUIChatExtension_NavigationMoreItem_MinimalistExtensionID, object: TUICallKitService.instance) - TUICore.registerExtension(TUICore_TUIChatExtension_InputViewMoreItem_ClassicExtensionID, object: TUICallKitService.instance) - TUICore.registerExtension(TUICore_TUIContactExtension_FriendProfileActionMenu_ClassicExtensionID, object: TUICallKitService.instance) - TUICore.registerExtension(TUICore_TUIContactExtension_FriendProfileActionMenu_MinimalistExtensionID, object: TUICallKitService.instance) - TUICore.registerExtension(TUICore_TUIGroupExtension_GroupInfoCardActionMenu_MinimalistExtensionID, object: TUICallKitService.instance) - - } -} diff --git a/iOS/TUIKit/TUICallKit/TUICallKit-Swift/Service/SwiftLoad.swift b/iOS/TUIKit/TUICallKit/TUICallKit-Swift/Service/SwiftLoad.swift new file mode 100644 index 000000000..145c463bb --- /dev/null +++ b/iOS/TUIKit/TUICallKit/TUICallKit-Swift/Service/SwiftLoad.swift @@ -0,0 +1,34 @@ +// +// SwiftLoad.swift +// TUIVideoSeat +// +// Created by WesleyLei on 2022/9/23. +// Copyright © 2022 Tencent. All rights reserved. +// + +import Foundation +import TUICore + +extension NSObject { + @objc class func swiftLoad() { + let _ = TUICallKit.createInstance() + + TUICore.registerService(TUICore_TUICallingService, object: TUICallKitService.instance) + + TUICore.registerService(TUICore_TUIAudioMessageRecordService, object: TUIAudioMessageRecordService.instance) + + TUICore.registerExtension(TUICore_TUIChatExtension_NavigationMoreItem_MinimalistExtensionID, + object: TUICallKitExtension.instance) + TUICore.registerExtension(TUICore_TUIChatExtension_InputViewMoreItem_ClassicExtensionID, + object: TUICallKitExtension.instance) + TUICore.registerExtension(TUICore_TUIContactExtension_FriendProfileActionMenu_ClassicExtensionID, + object: TUICallKitExtension.instance) + TUICore.registerExtension(TUICore_TUIContactExtension_FriendProfileActionMenu_MinimalistExtensionID, + object: TUICallKitExtension.instance) + TUICore.registerExtension(TUICore_TUIGroupExtension_GroupInfoCardActionMenu_MinimalistExtensionID, + object: TUICallKitExtension.instance) + + TUICore.registerObjectFactory(TUICore_TUICallingObjectFactory, objectFactory: TUICallKitObjectFactory.instance) + + } +} diff --git a/iOS/TUIKit/TUICallKit/TUICallKit-Swift/Service/TUIAudioMessageRecordService.swift b/iOS/TUIKit/TUICallKit/TUICallKit-Swift/Service/TUIAudioMessageRecordService.swift new file mode 100644 index 000000000..cd5bebf1e --- /dev/null +++ b/iOS/TUIKit/TUICallKit/TUICallKit-Swift/Service/TUIAudioMessageRecordService.swift @@ -0,0 +1,292 @@ +// +// TUIAudioMessageRecordService.swift +// TUICallKit-Swift +// +// Created by vincepzhang on 2023/8/16. +// + +import Foundation +import AVFAudio +import TUICore +import TUICallEngine + +#if USE_TRTC +import TXLiteAVSDK_TRTC +#else +import TXLiteAVSDK_Professional +#endif + +class TUIAudioRecordInfo { + var path: String = "" + var sdkAppId: Int = 0 + var signature: String = "" +} + +class TUIAudioMessageRecordService: NSObject, TUIServiceProtocol, TUINotificationProtocol, TRTCCloudDelegate, TUICallObserver { + + static let instance = TUIAudioMessageRecordService() + + var audioRecordInfo: TUIAudioRecordInfo? + var category: AVAudioSession.Category? + var categoryOptions: AVAudioSession.CategoryOptions? + + var callback: TUICallServiceResultCallback? + + override init() { + super.init() + + NotificationCenter.default.addObserver(self, selector: #selector(audioSessionInterruptionNotification), + name: AVAudioSession.interruptionNotification, object: nil) + NotificationCenter.default.addObserver(self, selector: #selector(loginSuccessNotification), + name: NSNotification.Name.TUILoginSuccess, object: nil) + } + + deinit { + NotificationCenter.default.removeObserver(self) + } + + @objc + func loginSuccessNotification() { + TUICallEngine.createInstance().addObserver(self) + } + + // MARK: AVAudioSessionInterruptionNotification + @objc + func audioSessionInterruptionNotification(_ notification: Notification) { + guard let typeValue = notification.userInfo?[AVAudioSessionInterruptionTypeKey] as? NSNumber else { return } + let type = AVAudioSession.InterruptionType(rawValue: typeValue.uintValue) + if type == .began { + stopRecordAudioMessage() + } + } +} + +// MARK: TUIServiceProtocol +extension TUIAudioMessageRecordService { + func onCall(_ method: String, param: [AnyHashable : Any]?) -> Any? { + return nil + } + + func onCall(_ method: String, param: [AnyHashable : Any]?, resultCallback: @escaping TUICallServiceResultCallback) -> Any? { + callback = resultCallback + + if method == TUICore_TUIAudioMessageRecordService_StartRecordAudioMessageMethod { + guard let param = param else { + notifyAudioMessageRecordEvent(method: TUICore_RecordAudioMessageNotify_StartRecordAudioMessageSubKey, + errorCode: Int(TUICore_RecordAudioMessageNotifyError_InvalidParam), path: "") + return nil + } + + /// 如果当前在通话中,不支持录音 + if TUICallState.instance.selfUser.value.callStatus.value != TUICallStatus.none { + notifyAudioMessageRecordEvent(method: TUICore_RecordAudioMessageNotify_StartRecordAudioMessageSubKey, + errorCode: Int(TUICore_RecordAudioMessageNotifyError_StatusInCall), path: "") + return nil + } + + /// 当前已经在录音中 + if audioRecordInfo != nil { + notifyAudioMessageRecordEvent(method: TUICore_RecordAudioMessageNotify_StartRecordAudioMessageSubKey, + errorCode: Int(TUICore_RecordAudioMessageNotifyError_StatusIsAudioRecording), path: "") + return nil + } + + requestRecordAuthorization { [weak self] granted in + guard let self = self else { return } + if granted { + /// 获取音频焦点 + if !self.requestAudioFocus() { + self.notifyAudioMessageRecordEvent(method: TUICore_RecordAudioMessageNotify_StartRecordAudioMessageSubKey, + errorCode: Int(TUICore_RecordAudioMessageNotifyError_RequestAudioFocusFailed), path: "") + } else { + self.audioRecordInfo = TUIAudioRecordInfo() + let pathKey = TUICore_TUIAudioMessageRecordService_StartRecordAudioMessageMethod_PathKey + self.audioRecordInfo?.path = param[pathKey] as? String ?? "" + let sdkAppId = param[TUICore_TUIAudioMessageRecordService_StartRecordAudioMessageMethod_SdkappidKey] as? NSNumber + if let sdkAppId = sdkAppId { + self.audioRecordInfo?.sdkAppId = sdkAppId.intValue + } + let signatureKey = TUICore_TUIAudioMessageRecordService_StartRecordAudioMessageMethod_SignatureKey + self.audioRecordInfo?.signature = param[signatureKey] as? String ?? "" + + /// 抢占TRTC delegate + TRTCCloud.sharedInstance().delegate = self + /// 启用音量大小 + let audioVolumeEvaluateParams = TRTCAudioVolumeEvaluateParams() + audioVolumeEvaluateParams.interval = 500 + TRTCCloud.sharedInstance().enableAudioVolumeEvaluation(true, with: audioVolumeEvaluateParams) + self.startRecordAudioMessage() + } + } else { + /// 获取麦克风权限失败 + self.notifyAudioMessageRecordEvent(method: TUICore_RecordAudioMessageNotify_StartRecordAudioMessageSubKey, + errorCode: Int(TUICore_RecordAudioMessageNotifyError_MicPermissionRefused), path: "") + } + } + + return nil + + } else if method == TUICore_TUIAudioMessageRecordService_StopRecordAudioMessageMethod { + stopRecordAudioMessage() + } + + return nil + } + + func requestRecordAuthorization(response: @escaping (_ granted: Bool) -> Void) { + let session = AVAudioSession.sharedInstance() + let permission = session.recordPermission + + if permission == .undetermined { + session.requestRecordPermission(response) + } else if permission == .granted { + response(true) + } else if permission == .denied { + response(false) + } + } + + func startRecordAudioMessage() { + guard let audioRecordInfo = audioRecordInfo else { return } + + let sdkAppIdKey = TUICore_TUIAudioMessageRecordService_StartRecordAudioMessageMethod_SdkappidKey + let pathKey = TUICore_TUIAudioMessageRecordService_StartRecordAudioMessageMethod_PathKey + + let jsonParams: [String: Any] = ["api": "startRecordAudioMessage", + "params": ["key": audioRecordInfo.signature, + sdkAppIdKey: audioRecordInfo.sdkAppId, + pathKey: audioRecordInfo.path,] as [String : Any],] + + guard let data = try? JSONSerialization.data(withJSONObject: jsonParams, + options: JSONSerialization.WritingOptions(rawValue: 0)) else { return } + guard let paramsString = NSString(data: data, encoding: String.Encoding.utf8.rawValue) as? String else { return } + + TRTCCloud.sharedInstance().callExperimentalAPI(paramsString) + } + + func stopRecordAudioMessage() { + let jsonParams: [String: Any] = ["api": "stopRecordAudioMessage", + "params": [:] as [String : Any],] + + guard let data = try? JSONSerialization.data(withJSONObject: jsonParams, + options: JSONSerialization.WritingOptions(rawValue: 0)) else { return } + guard let paramsString = NSString(data: data, encoding: String.Encoding.utf8.rawValue) as? String else { return } + TRTCCloud.sharedInstance().callExperimentalAPI(paramsString) + TRTCCloud.sharedInstance().enableAudioVolumeEvaluation(false, with: TRTCAudioVolumeEvaluateParams()) + TRTCCloud.sharedInstance().stopLocalAudio() + + audioRecordInfo = nil + + let _ = abandonAudioFocus() + } +} + +//MARK: TUICallObserver +extension TUIAudioMessageRecordService { + func onCallReceived(callerId: String, calleeIdList: [String], groupId: String?, callMediaType: TUICallMediaType, userData: String?) { + stopRecordAudioMessage() + } +} + +//MARK: TRTCCloudDelegate +extension TUIAudioMessageRecordService { + func onError(_ errCode: TXLiteAVError, errMsg: String?, extInfo: [AnyHashable : Any]?) { + if errCode.rawValue == TUICore_RecordAudioMessageNotifyError_MicStartFail || + errCode.rawValue == TUICore_RecordAudioMessageNotifyError_MicNotAuthorized || + errCode.rawValue == TUICore_RecordAudioMessageNotifyError_MicSetParamFail || + errCode.rawValue == TUICore_RecordAudioMessageNotifyError_MicOccupy { + notifyAudioMessageRecordEvent(method: TUICore_RecordAudioMessageNotify_StartRecordAudioMessageSubKey, + errorCode: Int(errCode.rawValue) , path: "") + } + } + + func onLocalRecordBegin(_ errCode: Int, storagePath: String) { + if errCode == TUICore_RecordAudioMessageNotifyError_None { + TRTCCloud.sharedInstance().startLocalAudio(TRTCAudioQuality.speech) + } + let tempCode = convertErrorCode("onLocalRecordBegin", errorCode: errCode) + notifyAudioMessageRecordEvent(method: TUICore_RecordAudioMessageNotify_StartRecordAudioMessageSubKey, + errorCode: Int(tempCode), path: storagePath) + } + + func onLocalRecordComplete(_ errCode: Int, storagePath: String) { + let tempCode = convertErrorCode("onLocalRecordComplete", errorCode: errCode) + notifyAudioMessageRecordEvent(method: TUICore_RecordAudioMessageNotify_StopRecordAudioMessageSubKey, + errorCode: Int(tempCode), path: storagePath) + } + + func onUserVoiceVolume(_ userVolumes: [TRTCVolumeInfo], totalVolume: Int) { + for volumeInfo in userVolumes { + if volumeInfo.userId == nil || volumeInfo.userId?.isEmpty == true { + let param = [TUICore_RecordAudioMessageNotify_RecordAudioVoiceVolumeSubKey_VolumeKey: volumeInfo.volume,] + TUICore.notifyEvent(TUICore_RecordAudioMessageNotify, + subKey: TUICore_RecordAudioMessageNotify_RecordAudioVoiceVolumeSubKey, + object: nil, param: param) + break + } + } + } +} + +//MARK: Private +extension TUIAudioMessageRecordService { + + func requestAudioFocus() -> Bool { + let session = AVAudioSession.sharedInstance() + category = session.category + categoryOptions = session.categoryOptions + do { + try session.setCategory(.playAndRecord, options: .allowBluetooth) + try session.setActive(true) + return true + } catch { + return false + } + } + + func abandonAudioFocus() -> Bool { + guard let category = category else { return false } + guard let categoryOptions = categoryOptions else { return false } + + let session = AVAudioSession.sharedInstance() + do { + try session.setCategory(category, options: categoryOptions) + try session.setActive(false, options: .notifyOthersOnDeactivation) + return true + } catch { + return false + } + } + + func notifyAudioMessageRecordEvent(method: String, errorCode: Int, path: String) { + let params: [String: Any] = ["method": method, + "errorCode": errorCode, + "path": path,] + + guard let callback = callback else { return } + callback(errorCode, "", params) + } + + func convertErrorCode(_ method: String?, errorCode: Int) -> Int32 { + var targetCode: Int32 + switch errorCode { + case -1: + if let method = method, method == "onLocalRecordBegin" { + targetCode = TUICore_RecordAudioMessageNotifyError_RecordInitFailed + } else { + targetCode = TUICore_RecordAudioMessageNotifyError_RecordFailed + } + case -2: + targetCode = TUICore_RecordAudioMessageNotifyError_PathFormatNotSupport + case -3: + targetCode = TUICore_RecordAudioMessageNotifyError_NoMessageToRecord + case -4: + targetCode = TUICore_RecordAudioMessageNotifyError_SignatureError + case -5: + targetCode = TUICore_RecordAudioMessageNotifyError_SignatureExpired + default: + targetCode = TUICore_RecordAudioMessageNotifyError_None + } + return targetCode + } +} diff --git a/iOS/TUIKit/TUICallKit/TUICallKit-Swift/Service/TUICallKitExtension.swift b/iOS/TUIKit/TUICallKit/TUICallKit-Swift/Service/TUICallKitExtension.swift new file mode 100644 index 000000000..05642e1ac --- /dev/null +++ b/iOS/TUIKit/TUICallKit/TUICallKit-Swift/Service/TUICallKitExtension.swift @@ -0,0 +1,279 @@ +// +// TUICallKitExtension.swift +// TUICallKit-Swift +// +// Created by vincepzhang on 2023/8/14. +// + +import Foundation +import TUICore +import TUICallEngine + +class TUICallKitExtension: NSObject, TUIExtensionProtocol { + + static let instance = TUICallKitExtension() + + func launchCall(type: TUICallMediaType, groupID: String, pushVC: UINavigationController, isClassic: Bool) { + if !groupID.isEmpty { + var requestParam: [String: Any] = [:] + requestParam[TUICore_TUIGroupObjectFactory_SelectGroupMemberVC_GroupID] = groupID + requestParam[TUICore_TUIGroupObjectFactory_SelectGroupMemberVC_Name] = + TUIGlobalization.getLocalizedString(forKey: "Make-a-call", bundle: TIMCommonLocalizableBundle) + let viewControllerKey = isClassic ? TUICore_TUIGroupObjectFactory_SelectGroupMemberVC_Classic : + TUICore_TUIGroupObjectFactory_SelectGroupMemberVC_Minimalist + pushVC.push(viewControllerKey, param: requestParam) { [weak self] responseData in + guard let self = self else { return } + guard let modelList = responseData[TUICore_TUIGroupObjectFactory_SelectGroupMemberVC_ResultUserList] + as? [TUIUserModel] else { return } + let userIDs: [String] = modelList.map { $0.userId } + self.startCall(groupID: groupID, userIDs: userIDs, callingType: type) + } + } + } + + func startCall(groupID: String, userIDs: [String], callingType: TUICallMediaType) { + let selector = NSSelectorFromString("setOnlineUserOnly") + if TUICallEngine.createInstance().responds(to: selector) { + TUICallEngine.createInstance().perform(selector, with: 0) + } + + if groupID.isEmpty { + guard let userID = userIDs.first else { return } + TUICallKit.createInstance().call(userId: userID, callMediaType: callingType) + } else { + TUICallKit.createInstance().groupCall(groupId: groupID, userIdList: userIDs, callMediaType: callingType) + } + } + + func doResponseInputViewExtension(param: [String: Any], type: TUICallMediaType, isClassic: Bool) { + let userID = param[TUICore_TUIChatExtension_InputViewMoreItem_UserID] as? String ?? "" + let groupId = param[TUICore_TUIChatExtension_InputViewMoreItem_GroupID] as? String ?? "" + let pushVC = param[TUICore_TUIChatExtension_InputViewMoreItem_PushVC] as? UINavigationController + + if !userID.isEmpty { + startCall(groupID: "", userIDs: [userID], callingType: type) + } else if !groupId.isEmpty { + guard let pushVC = pushVC else { return } + launchCall(type: type, groupID: groupId, pushVC: pushVC, isClassic: isClassic) + } + } + + //MARK: TUIExtensionProtocol + func onGetExtension(_ extensionID: String, param: [AnyHashable : Any]?) -> [TUIExtensionInfo]? { + if extensionID.isEmpty { + return nil + } + + if extensionID == TUICore_TUIChatExtension_NavigationMoreItem_MinimalistExtensionID { + return getNavigationMoreItemExtensionForMinimalistChat(param: param) + } else if extensionID == TUICore_TUIChatExtension_InputViewMoreItem_ClassicExtensionID { + return getInputViewMoreItemExtensionForClassicChat(param: param) + } else if extensionID == TUICore_TUIContactExtension_FriendProfileActionMenu_ClassicExtensionID { + return getFriendProfileActionMenuExtensionForClassicContact(param: param) + } else if extensionID == TUICore_TUIContactExtension_FriendProfileActionMenu_MinimalistExtensionID { + return getFriendProfileActionMenuExtensionForMinimalistContact(param: param) + } else if extensionID == TUICore_TUIGroupExtension_GroupInfoCardActionMenu_MinimalistExtensionID { + return getGroupInfoCardActionMenuExtensionForMinimalistGroup(param: param) + } else { + return nil + } + } + + func getNavigationMoreItemExtensionForMinimalistChat(param: [AnyHashable : Any]?) -> [TUIExtensionInfo]? { + guard let param = param else { return nil } + + let onClick: ([AnyHashable : Any]?, TUICallMediaType) -> Void = { [weak self] param, type in + guard let self = self else { return } + guard let param = param else { return } + let userID = param[TUICore_TUIChatExtension_NavigationMoreItem_UserID] as? String ?? "" + let groupID = param[TUICore_TUIChatExtension_NavigationMoreItem_GroupID] as? String ?? "" + let pushVC = param[TUICore_TUIChatExtension_NavigationMoreItem_PushVC] as? UINavigationController + + if !userID.isEmpty { + self.startCall(groupID: "", userIDs: [userID], callingType: type) + } else if !groupID.isEmpty { + guard let pushVC = pushVC else { return } + self.launchCall(type: type, groupID: groupID, pushVC: pushVC, isClassic: false) + } + } + + var result: [TUIExtensionInfo] = [] + guard let filterVideoCall = param[TUICore_TUIChatExtension_NavigationMoreItem_FilterVideoCall] as? Bool else { return nil } + + if !filterVideoCall { + let videoInfo = TUIExtensionInfo() + videoInfo.weight = 200 + videoInfo.icon = TUICallKitCommon.getBundleImage(name: "video_call") ?? UIImage() + videoInfo.onClicked = { param in + onClick(param, .video) + } + result.append(videoInfo) + } + + guard let filterAudioCall = param[TUICore_TUIChatExtension_NavigationMoreItem_FilterAudioCall] as? Bool else { return nil } + if !filterAudioCall { + let audioInfo = TUIExtensionInfo() + audioInfo.weight = 100 + audioInfo.icon = TUICallKitCommon.getBundleImage(name: "audio_call") ?? UIImage() + audioInfo.onClicked = { param in + onClick(param, .audio) + } + result.append(audioInfo) + } + return result + } + + func getInputViewMoreItemExtensionForClassicChat(param: [AnyHashable : Any]?) -> [TUIExtensionInfo]? { + guard let param = param else { return nil } + + var result: [TUIExtensionInfo] = [] + guard let filterVideoCall = param[TUICore_TUIChatExtension_InputViewMoreItem_FilterVideoCall] as? Bool else { return nil } + + if !filterVideoCall { + let videoInfo = TUIExtensionInfo() + videoInfo.weight = 600 + videoInfo.text = TUICoreDefineConvert.getTUIKitLocalizableString(key: "TUIKitMoreVideoCall") + videoInfo.icon = TUICoreDefineConvert.getTUICoreBundleThemeImage(imageKey: "service_more_video_call_img", + defaultImageName: "more_video_call") + videoInfo.onClicked = { param in + guard let param = param as? [String: Any] else { return } + self.doResponseInputViewExtension(param: param, type: .video, isClassic: true) + } + result.append(videoInfo) + } + + guard let filterAudioCall = param[TUICore_TUIChatExtension_InputViewMoreItem_FilterAudioCall] as? Bool else { return nil } + if !filterAudioCall { + let audioInfo = TUIExtensionInfo() + audioInfo.weight = 500 + audioInfo.text = TUICoreDefineConvert.getTUIKitLocalizableString(key: "TUIKitMoreVoiceCall") + audioInfo.icon = TUICoreDefineConvert.getTUICoreBundleThemeImage(imageKey: "service_more_voice_call_img", + defaultImageName: "more_voice_call") + audioInfo.onClicked = { param in + guard let param = param as? [String: Any] else { return } + self.doResponseInputViewExtension(param: param, type: .audio, isClassic: true) + } + result.append(audioInfo) + } + return result + } + + func getFriendProfileActionMenuExtensionForClassicContact(param: [AnyHashable : Any]?) -> [TUIExtensionInfo]? { + guard let param = param else { return nil } + + var result: [TUIExtensionInfo] = [] + guard let filterVideoCall = param[TUICore_TUIContactExtension_FriendProfileActionMenu_FilterVideoCall] as? Bool else { return nil } + if !filterVideoCall { + let videoInfo = TUIExtensionInfo() + videoInfo.weight = 200 + videoInfo.text = TUICoreDefineConvert.getTUIKitLocalizableString(key: "TUIKitMoreVideoCall") + videoInfo.onClicked = {[weak self] param in + guard let self = self else { return } + guard let userID = param[TUICore_TUIContactExtension_FriendProfileActionMenu_UserID] as? String else { return } + if !userID.isEmpty { + self.startCall(groupID: "", userIDs: [userID], callingType: .video) + } + } + result.append(videoInfo) + } + + guard let filterAudioCall = param[TUICore_TUIContactExtension_FriendProfileActionMenu_FilterAudioCall] as? Bool else { return nil } + if !filterAudioCall { + let audioInfo = TUIExtensionInfo() + audioInfo.weight = 100 + audioInfo.text = TUICoreDefineConvert.getTUIKitLocalizableString(key: "TUIKitMoreVoiceCall") + audioInfo.onClicked = {[weak self] param in + guard let self = self else { return } + guard let userID = param[TUICore_TUIContactExtension_FriendProfileActionMenu_UserID] as? String else { return } + if !userID.isEmpty { + self.startCall(groupID: "", userIDs: [userID], callingType: .audio) + } + } + result.append(audioInfo) + } + return result + } + + func getFriendProfileActionMenuExtensionForMinimalistContact(param: [AnyHashable : Any]?) -> [TUIExtensionInfo]? { + guard let param = param else { return nil } + + var result: [TUIExtensionInfo] = [] + guard let filterVideoCall = param[TUICore_TUIContactExtension_FriendProfileActionMenu_FilterVideoCall] as? Bool else { return nil } + if !filterVideoCall { + let videoInfo = TUIExtensionInfo() + videoInfo.weight = 100 + videoInfo.icon = TUICoreDefineConvert.getTUIDynamicImage(imageKey: "", module: TUIThemeModule.contact_Minimalist, + defaultImage: UIImage(named: TUICoreDefineConvert.getTUIContactImagePathMinimalist(imageName: "contact_info_video")) ?? UIImage()) + videoInfo.text = TUICoreDefineConvert.getTIMCommonLocalizableString(key: "TUIKitVideo") + videoInfo.onClicked = {[weak self] param in + guard let self = self else { return } + guard let userID = param[TUICore_TUIContactExtension_FriendProfileActionMenu_UserID] as? String else { return } + if !userID.isEmpty { + self.startCall(groupID: "", userIDs: [userID], callingType: .video) + } + } + result.append(videoInfo) + } + + guard let filterAudioCall = param[TUICore_TUIContactExtension_FriendProfileActionMenu_FilterAudioCall] as? Bool else { return nil } + if !filterAudioCall { + let audioInfo = TUIExtensionInfo() + audioInfo.weight = 200 + audioInfo.icon = TUICoreDefineConvert.getTUIDynamicImage(imageKey: "", module: TUIThemeModule.contact_Minimalist, + defaultImage: UIImage(named: TUICoreDefineConvert.getTUIContactImagePathMinimalist(imageName: "contact_info_audio")) ?? UIImage()) + audioInfo.text = TUICoreDefineConvert.getTIMCommonLocalizableString(key: "TUIKitAudio") + audioInfo.onClicked = {[weak self] param in + guard let self = self else { return } + guard let userID = param[TUICore_TUIContactExtension_FriendProfileActionMenu_UserID] as? String else { return } + if !userID.isEmpty { + self.startCall(groupID: "", userIDs: [userID], callingType: .audio) + } + } + result.append(audioInfo) + } + return result + } + + func getGroupInfoCardActionMenuExtensionForMinimalistGroup(param: [AnyHashable : Any]?) -> [TUIExtensionInfo]? { + guard let param = param else { return nil } + + var result: [TUIExtensionInfo] = [] + guard let filterVideoCall = param[TUICore_TUIGroupExtension_GroupInfoCardActionMenu_FilterVideoCall] as? Bool else { return nil } + if !filterVideoCall { + let videoInfo = TUIExtensionInfo() + videoInfo.weight = 100 + videoInfo.icon = TUICoreDefineConvert.getTUIDynamicImage(imageKey: "", module: TUIThemeModule.contact_Minimalist, + defaultImage: UIImage(named: TUICoreDefineConvert.getTUIContactImagePathMinimalist(imageName: "contact_info_video")) ?? UIImage()) + videoInfo.text = TUICoreDefineConvert.getTIMCommonLocalizableString(key: "TUIKitVideo") + videoInfo.onClicked = {[weak self] param in + guard let self = self else { return } + guard let pushVC = param[TUICore_TUIGroupExtension_GroupInfoCardActionMenu_PushVC] as? UINavigationController else { return } + guard let groupID = param[TUICore_TUIGroupExtension_GroupInfoCardActionMenu_GroupID] as? String else { return } + if !groupID.isEmpty { + self.launchCall(type: .video, groupID: groupID, pushVC: pushVC, isClassic: false) + } + } + result.append(videoInfo) + } + + guard let filterAudioCall = param[TUICore_TUIGroupExtension_GroupInfoCardActionMenu_FilterAudioCall] as? Bool else { return nil } + if !filterAudioCall { + let audioInfo = TUIExtensionInfo() + audioInfo.weight = 200 + audioInfo.icon = TUICoreDefineConvert.getTUIDynamicImage(imageKey: "", module: TUIThemeModule.contact_Minimalist, + defaultImage: UIImage(named: TUICoreDefineConvert.getTUIContactImagePathMinimalist(imageName: "contact_info_audio")) ?? UIImage()) + audioInfo.text = TUICoreDefineConvert.getTIMCommonLocalizableString(key: "TUIKitAudio") + audioInfo.onClicked = {[weak self] param in + guard let self = self else { return } + guard let pushVC = param[TUICore_TUIGroupExtension_GroupInfoCardActionMenu_PushVC] as? UINavigationController else { return } + guard let groupID = param[TUICore_TUIGroupExtension_GroupInfoCardActionMenu_GroupID] as? String else { return } + if !groupID.isEmpty { + self.launchCall(type: .audio, groupID: groupID, pushVC: pushVC, isClassic: false) + } + } + result.append(audioInfo) + } + return result + } + +} diff --git a/iOS/TUIKit/TUICallKit/TUICallKit-Swift/Service/TUICallKitObjectFactory.swift b/iOS/TUIKit/TUICallKit/TUICallKit-Swift/Service/TUICallKitObjectFactory.swift new file mode 100644 index 000000000..869dd061d --- /dev/null +++ b/iOS/TUIKit/TUICallKit/TUICallKit-Swift/Service/TUICallKitObjectFactory.swift @@ -0,0 +1,35 @@ +// +// TUICallKitObjectFactory.swift +// TUICallKit-Swift +// +// Created by vincepzhang on 2023/8/15. +// + +import Foundation +import TUICore + +class TUICallKitObjectFactory: NSObject, TUIObjectProtocol { + + static let instance = TUICallKitObjectFactory() + + func createRecordCallsVC(uiStyle: String) -> UIViewController { + + var recordCallsUIStyle: TUICallKitRecordCallsUIStyle = .minimalist + + if uiStyle == TUICore_TUICallingObjectFactory_RecordCallsVC_UIStyle_Classic { + recordCallsUIStyle = .classic + } + + let vc = TUICallRecordCallsViewController(recordCallsUIStyle: recordCallsUIStyle) + return vc + } + + // MARK: TUIObjectProtocol + func onCreateObject(_ method: String, param: [AnyHashable : Any]?) -> Any? { + if method == TUICore_TUICallingObjectFactory_RecordCallsVC { + guard let uiStyle = param?[TUICore_TUICallingObjectFactory_RecordCallsVC_UIStyle] as? String else { return nil } + return createRecordCallsVC(uiStyle: uiStyle) + } + return nil + } +} diff --git a/iOS/TUIKit/TUICallKit/TUICallKit-Swift/Service/TUICallKitService.swift b/iOS/TUIKit/TUICallKit/TUICallKit-Swift/Service/TUICallKitService.swift index 8fce25dcb..6b6f0df12 100644 --- a/iOS/TUIKit/TUICallKit/TUICallKit-Swift/Service/TUICallKitService.swift +++ b/iOS/TUIKit/TUICallKit/TUICallKit-Swift/Service/TUICallKitService.swift @@ -10,31 +10,9 @@ import TUICore import TUICallEngine import UIKit -class TUICallKitService: NSObject, TUIServiceProtocol, TUIExtensionProtocol { +class TUICallKitService: NSObject, TUIServiceProtocol { static let instance = TUICallKitService() - - override init() { - let _ = TUICallKit.createInstance() - } - - func launchCall(type: TUICallMediaType, groupID: String, pushVC: UINavigationController, isClassic: Bool) { - if !groupID.isEmpty { - var requestParam: [String: Any] = [:] - requestParam[TUICore_TUIGroupObjectFactory_SelectGroupMemberVC_GroupID] = groupID - requestParam[TUICore_TUIGroupObjectFactory_SelectGroupMemberVC_Name] = - TUIGlobalization.getLocalizedString(forKey: "Make-a-call", bundle: TIMCommonLocalizableBundle) - let viewControllerKey = isClassic ? TUICore_TUIGroupObjectFactory_SelectGroupMemberVC_Classic : - TUICore_TUIGroupObjectFactory_SelectGroupMemberVC_Minimalist - pushVC.push(viewControllerKey, param: requestParam) { [weak self] responseData in - guard let self = self else { return } - guard let modelList = responseData[TUICore_TUIGroupObjectFactory_SelectGroupMemberVC_ResultUserList] - as? [TUIUserModel] else { return } - let userIDs: [String] = modelList.map { $0.userId } - self.startCall(groupID: groupID, userIDs: userIDs, callingType: type) - } - } - } - + func startCall(groupID: String, userIDs: [String], callingType: TUICallMediaType) { let selector = NSSelectorFromString("setOnlineUserOnly") if TUICallEngine.createInstance().responds(to: selector) { @@ -48,235 +26,10 @@ class TUICallKitService: NSObject, TUIServiceProtocol, TUIExtensionProtocol { TUICallKit.createInstance().groupCall(groupId: groupID, userIdList: userIDs, callMediaType: callingType) } } - - func doResponseInputViewExtension(param: [String: Any], type: TUICallMediaType, isClassic: Bool) { - let userID = param[TUICore_TUIChatExtension_InputViewMoreItem_UserID] as? String ?? "" - let groupId = param[TUICore_TUIChatExtension_InputViewMoreItem_GroupID] as? String ?? "" - let pushVC = param[TUICore_TUIChatExtension_InputViewMoreItem_PushVC] as? UINavigationController - - if !userID.isEmpty { - startCall(groupID: "", userIDs: [userID], callingType: type) - } else if !groupId.isEmpty { - guard let pushVC = pushVC else { return } - launchCall(type: type, groupID: groupId, pushVC: pushVC, isClassic: isClassic) - } - } } +// MARK: TUIServiceProtocol extension TUICallKitService { - //MARK: TUIExtensionProtocol - func onGetExtension(_ extensionID: String, param: [AnyHashable : Any]?) -> [TUIExtensionInfo]? { - if extensionID.isEmpty { - return nil - } - - if extensionID == TUICore_TUIChatExtension_NavigationMoreItem_MinimalistExtensionID { - return getNavigationMoreItemExtensionForMinimalistChat(param: param) - } else if extensionID == TUICore_TUIChatExtension_InputViewMoreItem_ClassicExtensionID { - return getInputViewMoreItemExtensionForClassicChat(param: param) - } else if extensionID == TUICore_TUIContactExtension_FriendProfileActionMenu_ClassicExtensionID { - return getFriendProfileActionMenuExtensionForClassicContact(param: param) - } else if extensionID == TUICore_TUIContactExtension_FriendProfileActionMenu_MinimalistExtensionID { - return getFriendProfileActionMenuExtensionForMinimalistContact(param: param) - } else if extensionID == TUICore_TUIGroupExtension_GroupInfoCardActionMenu_MinimalistExtensionID { - return getGroupInfoCardActionMenuExtensionForMinimalistGroup(param: param) - } else { - return nil - } - } - - func getNavigationMoreItemExtensionForMinimalistChat(param: [AnyHashable : Any]?) -> [TUIExtensionInfo]? { - guard let param = param else { return nil } - - let onClick: ([AnyHashable : Any]?, TUICallMediaType) -> Void = { [weak self] param, type in - guard let self = self else { return } - guard let param = param else { return } - let userID = param[TUICore_TUIChatExtension_NavigationMoreItem_UserID] as? String ?? "" - let groupID = param[TUICore_TUIChatExtension_NavigationMoreItem_GroupID] as? String ?? "" - let pushVC = param[TUICore_TUIChatExtension_NavigationMoreItem_PushVC] as? UINavigationController - - if !userID.isEmpty { - self.startCall(groupID: "", userIDs: [userID], callingType: type) - } else if !groupID.isEmpty { - guard let pushVC = pushVC else { return } - self.launchCall(type: type, groupID: groupID, pushVC: pushVC, isClassic: false) - } - } - - var result: [TUIExtensionInfo] = [] - guard let filterVideoCall = param[TUICore_TUIChatExtension_NavigationMoreItem_FilterVideoCall] as? Bool else { return nil } - if !filterVideoCall { - let videoInfo = TUIExtensionInfo() - videoInfo.weight = 200 - videoInfo.icon = TUICallKitCommon.getBundleImage(name: "video_call") ?? UIImage() - videoInfo.onClicked = { param in - onClick(param, .video) - } - result.append(videoInfo) - } - - guard let filterAudioCall = param[TUICore_TUIChatExtension_NavigationMoreItem_FilterAudioCall] as? Bool else { return nil } - if !filterAudioCall { - let audioInfo = TUIExtensionInfo() - audioInfo.weight = 100 - audioInfo.icon = TUICallKitCommon.getBundleImage(name: "audio_call") ?? UIImage() - audioInfo.onClicked = { param in - onClick(param, .audio) - } - result.append(audioInfo) - } - return result - } - - func getInputViewMoreItemExtensionForClassicChat(param: [AnyHashable : Any]?) -> [TUIExtensionInfo]? { - guard let param = param else { return nil } - - var result: [TUIExtensionInfo] = [] - guard let filterVideoCall = param[TUICore_TUIChatExtension_InputViewMoreItem_FilterVideoCall] as? Bool else { return nil } - if !filterVideoCall { - let videoInfo = TUIExtensionInfo() - videoInfo.weight = 400 - videoInfo.text = TUIGlobalization.getLocalizedString(forKey: "TUIKitMoreVideoCall", bundle: TUIKitLocalizableBundle) - - videoInfo.icon = TUICallKitCommon.getBundleImage(name: "service_video_call") ?? UIImage() - - videoInfo.onClicked = { param in - guard let param = param as? [String: Any] else { return } - self.doResponseInputViewExtension(param: param, type: .video, isClassic: true) - } - result.append(videoInfo) - } - - guard let filterAudioCall = param[TUICore_TUIChatExtension_InputViewMoreItem_FilterAudioCall] as? Bool else { return nil } - if !filterAudioCall { - let audioInfo = TUIExtensionInfo() - audioInfo.weight = 300 - audioInfo.text = TUIGlobalization.getLocalizedString(forKey: "TUIKitMoreVoiceCall", bundle: TUIKitLocalizableBundle) - audioInfo.icon = TUICallKitCommon.getBundleImage(name: "service_audio_call") ?? UIImage() - audioInfo.onClicked = { param in - guard let param = param as? [String: Any] else { return } - self.doResponseInputViewExtension(param: param, type: .audio, isClassic: true) - } - result.append(audioInfo) - } - return result - } - - func getFriendProfileActionMenuExtensionForClassicContact(param: [AnyHashable : Any]?) -> [TUIExtensionInfo]? { - guard let param = param else { return nil } - - var result: [TUIExtensionInfo] = [] - guard let filterVideoCall = param[TUICore_TUIContactExtension_FriendProfileActionMenu_FilterVideoCall] as? Bool else { return nil } - if !filterVideoCall { - let videoInfo = TUIExtensionInfo() - videoInfo.weight = 200 - videoInfo.text = TUIGlobalization.getLocalizedString(forKey: "TUIKitMoreVideoCall", bundle: TUIKitLocalizableBundle) - videoInfo.onClicked = {[weak self] param in - guard let self = self else { return } - guard let userID = param[TUICore_TUIContactExtension_FriendProfileActionMenu_UserID] as? String else { return } - if !userID.isEmpty { - self.startCall(groupID: "", userIDs: [userID], callingType: .video) - } - } - result.append(videoInfo) - } - - guard let filterAudioCall = param[TUICore_TUIContactExtension_FriendProfileActionMenu_FilterAudioCall] as? Bool else { return nil } - if !filterAudioCall { - let audioInfo = TUIExtensionInfo() - audioInfo.weight = 100 - audioInfo.text = TUIGlobalization.getLocalizedString(forKey: "TUIKitMoreVoiceCall", bundle: TUIKitLocalizableBundle) - audioInfo.onClicked = {[weak self] param in - guard let self = self else { return } - guard let userID = param[TUICore_TUIContactExtension_FriendProfileActionMenu_UserID] as? String else { return } - if !userID.isEmpty { - self.startCall(groupID: "", userIDs: [userID], callingType: .audio) - } - } - result.append(audioInfo) - } - return result - } - - func getFriendProfileActionMenuExtensionForMinimalistContact(param: [AnyHashable : Any]?) -> [TUIExtensionInfo]? { - guard let param = param else { return nil } - - var result: [TUIExtensionInfo] = [] - guard let filterVideoCall = param[TUICore_TUIContactExtension_FriendProfileActionMenu_FilterVideoCall] as? Bool else { return nil } - if !filterVideoCall { - let videoInfo = TUIExtensionInfo() - videoInfo.weight = 100 - videoInfo.icon = TUICallKitCommon.getBundleImage(name: "video_call") ?? UIImage() - videoInfo.text = TUIGlobalization.getLocalizedString(forKey: "TUIKitVideo", bundle: TIMCommonLocalizableBundle) - videoInfo.onClicked = {[weak self] param in - guard let self = self else { return } - guard let userID = param[TUICore_TUIContactExtension_FriendProfileActionMenu_UserID] as? String else { return } - if !userID.isEmpty { - self.startCall(groupID: "", userIDs: [userID], callingType: .video) - } - } - result.append(videoInfo) - } - - guard let filterAudioCall = param[TUICore_TUIContactExtension_FriendProfileActionMenu_FilterAudioCall] as? Bool else { return nil } - if !filterAudioCall { - let audioInfo = TUIExtensionInfo() - audioInfo.weight = 200 - audioInfo.icon = TUICallKitCommon.getBundleImage(name: "audio_call") ?? UIImage() - audioInfo.text = TUIGlobalization.getLocalizedString(forKey: "TUIKitAudio", bundle: TIMCommonLocalizableBundle) - audioInfo.onClicked = {[weak self] param in - guard let self = self else { return } - guard let userID = param[TUICore_TUIContactExtension_FriendProfileActionMenu_UserID] as? String else { return } - if !userID.isEmpty { - self.startCall(groupID: "", userIDs: [userID], callingType: .audio) - } - } - result.append(audioInfo) - } - return result - } - - func getGroupInfoCardActionMenuExtensionForMinimalistGroup(param: [AnyHashable : Any]?) -> [TUIExtensionInfo]? { - guard let param = param else { return nil } - - var result: [TUIExtensionInfo] = [] - guard let filterVideoCall = param[TUICore_TUIGroupExtension_GroupInfoCardActionMenu_FilterVideoCall] as? Bool else { return nil } - if !filterVideoCall { - let videoInfo = TUIExtensionInfo() - videoInfo.weight = 100 - videoInfo.icon = TUICallKitCommon.getBundleImage(name: "video_call") ?? UIImage() - videoInfo.text = TUIGlobalization.getLocalizedString(forKey: "TUIKitVideo", bundle: TIMCommonLocalizableBundle) - videoInfo.onClicked = {[weak self] param in - guard let self = self else { return } - guard let pushVC = param[TUICore_TUIGroupExtension_GroupInfoCardActionMenu_PushVC] as? UINavigationController else { return } - guard let groupID = param[TUICore_TUIGroupExtension_GroupInfoCardActionMenu_GroupID] as? String else { return } - if !groupID.isEmpty { - self.launchCall(type: .video, groupID: groupID, pushVC: pushVC, isClassic: false) - } - } - result.append(videoInfo) - } - - guard let filterAudioCall = param[TUICore_TUIGroupExtension_GroupInfoCardActionMenu_FilterAudioCall] as? Bool else { return nil } - if !filterAudioCall { - let audioInfo = TUIExtensionInfo() - audioInfo.weight = 200 - audioInfo.icon = TUICallKitCommon.getBundleImage(name: "audio_call") ?? UIImage() - audioInfo.text = TUIGlobalization.getLocalizedString(forKey: "TUIKitAudio", bundle: TIMCommonLocalizableBundle) - audioInfo.onClicked = {[weak self] param in - guard let self = self else { return } - guard let pushVC = param[TUICore_TUIGroupExtension_GroupInfoCardActionMenu_PushVC] as? UINavigationController else { return } - guard let groupID = param[TUICore_TUIGroupExtension_GroupInfoCardActionMenu_GroupID] as? String else { return } - if !groupID.isEmpty { - self.launchCall(type: .audio, groupID: groupID, pushVC: pushVC, isClassic: false) - } - } - result.append(audioInfo) - } - return result - } - - //MARK: TUIServiceProtocol func onCall(_ method: String, param: [AnyHashable : Any]?) -> Any? { guard let param = param else { return nil } if param.isEmpty { diff --git a/iOS/TUIKit/TUICallKit/TUICallKit-Swift/State/TUICallState.swift b/iOS/TUIKit/TUICallKit/TUICallKit-Swift/State/TUICallState.swift index fb3affcc5..a1375b777 100644 --- a/iOS/TUIKit/TUICallKit/TUICallKit-Swift/State/TUICallState.swift +++ b/iOS/TUIKit/TUICallKit/TUICallKit-Swift/State/TUICallState.swift @@ -7,9 +7,9 @@ import Foundation import TUICore import TUICallEngine +import AVFoundation class TUICallState: NSObject { - static let instance = TUICallState() let remoteUserList: Observable<[User]> = Observable(Array()) @@ -18,10 +18,9 @@ class TUICallState: NSObject { let scene: Observable = Observable(TUICallScene.single) let mediaType: Observable = Observable(TUICallMediaType.unknown) let timeCount: Observable = Observable(0) - let roomId: Observable = Observable(TUIRoomId()) let groupId: Observable = Observable("") let event: Observable = Observable(TUICallEvent(eventType: .UNKNOWN, event: .UNKNOWN, param: Dictionary())) - + let isCameraOpen: Observable = Observable(false) let isMicMute: Observable = Observable(false) let isFrontCamera: Observable = Observable(TUICamera.front) @@ -45,34 +44,50 @@ extension TUICallState: TUICallObserver { param[EVENT_KEY_MESSAGE] = message let callEvent = TUICallEvent(eventType: .ERROR, event: .ERROR_COMMON, param: param) TUICallState.instance.event.value = callEvent - + } func onCallReceived(callerId: String, calleeIdList: [String], groupId: String?, callMediaType: TUICallMediaType) { - if (callMediaType == .unknown || calleeIdList.isEmpty) { return } - + if (calleeIdList.count >= MAX_USER) { let callEvent = TUICallEvent(eventType: .TIP, event: .USER_EXCEED_LIMIT, param: [:]) TUICallState.instance.event.value = callEvent return } - let remoteUsersId: [String] = [callerId] + calleeIdList - User.getUserInfosFromIM(userIDs: remoteUsersId) { inviteeList in + if TUICallKitCommon.checkAuthorizationStatusIsDenied(mediaType: callMediaType) { + showAuthorizationAlert(mediaType: callMediaType) + return + } + + let remoteUserIds: [String] = [callerId] + calleeIdList + User.getUserInfosFromIM(userIDs: remoteUserIds) { remoteUserLists in var remoteUsers: [User] = Array() - for invitee in inviteeList { - invitee.callRole.value = TUICallRole.called - invitee.callStatus.value = .waiting - if invitee.id.value != TUICallState.instance.selfUser.value.id.value { - remoteUsers.append(invitee) + for user in remoteUserLists { + + if user.id.value == callerId { + user.callRole.value = TUICallRole.call + + } else { + user.callRole.value = TUICallRole.called + } + + user.callStatus.value = .waiting + + if user.id.value != TUICallState.instance.selfUser.value.id.value { + if user.id.value == callerId { + remoteUsers.insert(user, at: 0) + } else { + remoteUsers.append(user) + } } } TUICallState.instance.remoteUserList.value = remoteUsers } - + if calleeIdList.count == 1 { TUICallState.instance.scene.value = .single } else { @@ -82,9 +97,9 @@ extension TUICallState: TUICallObserver { if groupId != nil { TUICallState.instance.scene.value = .group TUICallState.instance.groupId.value = groupId ?? "" - } + } TUICallState.instance.mediaType.value = callMediaType - + TUICallState.instance.selfUser.value.callRole.value = TUICallRole.called TUICallState.instance.selfUser.value.callStatus.value = TUICallStatus.waiting @@ -116,7 +131,7 @@ extension TUICallState: TUICallObserver { remoteUser.id.value = userId remoteUser.callStatus.value = TUICallStatus.accept TUICallState.instance.remoteUserList.value.append(remoteUser) - + User.getUserInfosFromIM(userIDs: [userId]) { users in guard let user = users.first else { return } for remote in TUICallState.instance.remoteUserList.value where user.id.value == remote.id.value { @@ -133,7 +148,11 @@ extension TUICallState: TUICallObserver { TUICallState.instance.remoteUserList.value.remove(at: index) break } - + + if TUICallState.instance.remoteUserList.value.isEmpty { + cleanState() + } + let callEvent = TUICallEvent(eventType: .TIP, event: .USER_LEAVE, param: [EVENT_KEY_USER_ID: userId]) TUICallState.instance.event.value = callEvent } @@ -144,11 +163,11 @@ extension TUICallState: TUICallObserver { TUICallState.instance.remoteUserList.value.remove(at: index) break } - + if TUICallState.instance.remoteUserList.value.isEmpty { cleanState() } - + let callEvent = TUICallEvent(eventType: .TIP, event: .USER_REJECT, param: [EVENT_KEY_USER_ID: userId]) TUICallState.instance.event.value = callEvent } @@ -159,7 +178,7 @@ extension TUICallState: TUICallObserver { TUICallState.instance.remoteUserList.value.remove(at: index) break } - + if TUICallState.instance.remoteUserList.value.isEmpty { cleanState() } @@ -174,7 +193,7 @@ extension TUICallState: TUICallObserver { TUICallState.instance.remoteUserList.value.remove(at: index) break } - + let callEvent = TUICallEvent(eventType: .TIP, event: .USER_NO_RESPONSE, param: [EVENT_KEY_USER_ID: userId]) TUICallState.instance.event.value = callEvent } @@ -192,7 +211,7 @@ extension TUICallState: TUICallObserver { } func onUserNetworkQualityChanged(networkQualityList: [TUINetworkQualityInfo]) { - + } func onUserAudioAvailable(userId: String, isAudioAvailable: Bool) { @@ -208,7 +227,6 @@ extension TUICallState: TUICallObserver { } func onCallBegin(roomId: TUIRoomId, callMediaType: TUICallMediaType, callRole: TUICallRole) { - TUICallState.instance.roomId.value = roomId TUICallState.instance.mediaType.value = callMediaType TUICallState.instance.selfUser.value.callRole.value = callRole TUICallState.instance.selfUser.value.callStatus.value = TUICallStatus.accept @@ -237,7 +255,6 @@ extension TUICallState { TUICallState.instance.mediaType.value = .unknown TUICallState.instance.timeCount.value = 0 - TUICallState.instance.roomId.value = TUIRoomId() TUICallState.instance.groupId.value = "" TUICallState.instance.selfUser.value.callRole.value = TUICallRole.none @@ -248,7 +265,7 @@ extension TUICallState { TUICallState.instance.isMicMute.value = false TUICallState.instance.isFrontCamera.value = .front TUICallState.instance.audioDevice.value = .earpiece - + GCDTimer.cancel(timerName: timerName) { return } VideoFactory.instance.viewMap.removeAll() @@ -261,4 +278,19 @@ extension TUICallState { } return userIdList } + + func showAuthorizationAlert(mediaType: TUICallMediaType) { + let statusVideo: AVAuthorizationStatus = AVCaptureDevice.authorizationStatus(for: .video) + var deniedType: AuthorizationDeniedType = AuthorizationDeniedType.audio + + if mediaType == .video && statusVideo == .denied { + deniedType = .video + } + + TUICallKitCommon.showAuthorizationAlert(deniedType: deniedType) { + CallEngineManager.instance.hangup() + } cancelHandler: { + CallEngineManager.instance.hangup() + } + } } diff --git a/iOS/TUIKit/TUICallKit/TUICallKit-Swift/TUICallKit.swift b/iOS/TUIKit/TUICallKit/TUICallKit-Swift/TUICallKit.swift index e4a6c4957..8ae778ee7 100644 --- a/iOS/TUIKit/TUICallKit/TUICallKit-Swift/TUICallKit.swift +++ b/iOS/TUIKit/TUICallKit/TUICallKit-Swift/TUICallKit.swift @@ -8,11 +8,13 @@ import Foundation import TUICallEngine -public class TUICallKit { +@objc +public class TUICallKit: NSObject { /** * Create a TUICallKit instance */ + @objc public static func createInstance() -> TUICallKit { return TUICallKitImpl.instance } @@ -25,6 +27,7 @@ public class TUICallKit { * For example: https://liteav.sdk.qcloud.com/app/res/picture/voiceroom/avatar/user_avatar1.png * */ + @objc public func setSelfInfo(nickname: String, avatar: String, succ:@escaping TUICallSucc, fail: @escaping TUICallFail) { return TUICallKitImpl.instance.setSelfInfo(nickname: nickname, avatar: avatar, succ: succ, fail: fail) } @@ -35,6 +38,7 @@ public class TUICallKit { * @param userId callees * @param callMediaType Call type */ + @objc public func call(userId: String, callMediaType: TUICallMediaType) { return TUICallKitImpl.instance.call(userId: userId, callMediaType: callMediaType) } @@ -46,6 +50,7 @@ public class TUICallKit { * @param callMediaType Call type * @param params Extension param: eg: offlinePushInfo */ + @objc public func call(userId: String, callMediaType: TUICallMediaType, params: TUICallParams, succ: @escaping TUICallSucc, fail: @escaping TUICallFail) { return TUICallKitImpl.instance.call(userId: userId, callMediaType: callMediaType, params: params, succ: succ, fail: fail) @@ -58,6 +63,7 @@ public class TUICallKit { * @param userIdList List of userId * @param callMediaType Call type */ + @objc public func groupCall(groupId: String, userIdList: [String], callMediaType: TUICallMediaType) { return TUICallKitImpl.instance.groupCall(groupId: groupId, userIdList: userIdList, callMediaType: callMediaType) } @@ -70,6 +76,7 @@ public class TUICallKit { * @param callMediaType Call type * @param params Extension param: eg: offlinePushInfo */ + @objc public func groupCall(groupId: String, userIdList: [String], callMediaType: TUICallMediaType, params: TUICallParams, succ: @escaping TUICallSucc, fail: @escaping TUICallFail) { return TUICallKitImpl.instance.groupCall(groupId: groupId, userIdList: userIdList, callMediaType: callMediaType, params: params, @@ -82,6 +89,7 @@ public class TUICallKit { * @param roomId current call room ID * @param callMediaType call type */ + @objc public func joinInGroupCall(roomId: TUIRoomId, groupId: String, callMediaType: TUICallMediaType) { return TUICallKitImpl.instance.joinInGroupCall(roomId: roomId, groupId: groupId, callMediaType: callMediaType) } @@ -91,6 +99,7 @@ public class TUICallKit { * * @param filePath Callee ringtone path */ + @objc public func setCallingBell(filePath: String) { return TUICallKitImpl.instance.setCallingBell(filePath: filePath) } @@ -98,13 +107,14 @@ public class TUICallKit { /** * Enable the mute mode (the callee doesn't ring) */ - public func enableMuteMode(enable: Bool) { + @objc public func enableMuteMode(enable: Bool) { return TUICallKitImpl.instance.enableMuteMode(enable: enable) } /** * Enable the floating window */ + @objc public func enableFloatWindow(enable: Bool) { return TUICallKitImpl.instance.enableFloatWindow(enable: enable) } @@ -112,6 +122,7 @@ public class TUICallKit { /** * Support custom View */ + @objc public func enableCustomViewRoute(enable: Bool) { return TUICallKitImpl.instance.enableCustomViewRoute(enable: enable) } @@ -119,6 +130,7 @@ public class TUICallKit { /** * Get TUICallKit ViewController */ + @objc public func getCallViewController() -> UIViewController { return TUICallKitImpl.instance.getCallViewController() } diff --git a/iOS/TUIKit/TUICallKit/TUICallKit-Swift/TUICallKitImpl.swift b/iOS/TUIKit/TUICallKit/TUICallKit-Swift/TUICallKitImpl.swift index 6e77ca9b6..2a47c4b20 100644 --- a/iOS/TUIKit/TUICallKit/TUICallKit-Swift/TUICallKitImpl.swift +++ b/iOS/TUIKit/TUICallKit/TUICallKit-Swift/TUICallKitImpl.swift @@ -17,7 +17,6 @@ import TXLiteAVSDK_Professional #endif class TUICallKitImpl: TUICallKit { - static let instance = TUICallKitImpl() let selfUserCallStatusObserver = Observer() @@ -33,7 +32,7 @@ class TUICallKitImpl: TUICallKit { NotificationCenter.default.removeObserver(self) TUICallState.instance.selfUser.value.callStatus.removeObserver(selfUserCallStatusObserver) } - + // MARK: TUICallKit对外接口实现 override func setSelfInfo(nickname: String, avatar: String, succ: @escaping TUICallSucc, fail: @escaping TUICallFail) { CallEngineManager.instance.setSelfInfo(nickname: nickname, avatar: avatar) { @@ -44,47 +43,54 @@ class TUICallKitImpl: TUICallKit { } override func call(userId: String, callMediaType: TUICallMediaType) { - call(userId: userId, callMediaType: callMediaType, params:TUICallParams()) { + call(userId: userId, callMediaType: callMediaType, params: getCallParams()) { } fail: { errCode, errMessage in } } - + override func call(userId: String, callMediaType: TUICallMediaType, params: TUICallParams, succ: @escaping TUICallSucc, fail: @escaping TUICallFail) { - if userId.count <= 0 { - fail(ERROR_PARAM_INVALID, "call failed, invalid params 'userId'") - return - } + fail(ERROR_PARAM_INVALID, "call failed, invalid params 'userId'") + return + } if TUILogin.getUserID() == nil { fail(ERROR_INIT_FAIL, "call failed, please login") return - } + } - if WindowManager.instance.isFloating { - fail(ERROR_PARAM_INVALID, "call failed, Unable to restart the call") - TUITool.makeToast(TUICallKitLocalize(key: "Demo.TRTC.Calling.UnableToRestartTheCall")) - return - } + if WindowManager.instance.isFloating { + fail(ERROR_PARAM_INVALID, "call failed, Unable to restart the call") + TUITool.makeToast(TUICallKitLocalize(key: "Demo.TRTC.Calling.UnableToRestartTheCall")) + return + } if callMediaType == .unknown { - fail(ERROR_PARAM_INVALID, "call failed, callMediaType is Unknown") - return - } - + fail(ERROR_PARAM_INVALID, "call failed, callMediaType is Unknown") + return + } + + if TUICallKitCommon.checkAuthorizationStatusIsDenied(mediaType: callMediaType) { + showAuthorizationAlert(mediaType: callMediaType) + fail(ERROR_PARAM_INVALID, "call failed, authorization status is denied") + return + } + CallEngineManager.instance.call(userId: userId, callMediaType: callMediaType, params: params) { succ() - } fail: { code, message in + } fail: { [weak self] code, message in + guard let self = self else { return } + self.handleAbilityFailErrorMessage(code: code, message: message) fail(code, message) } } - - override func groupCall(groupId: String, userIdList: [String], callMediaType: TUICallMediaType) { - groupCall(groupId: groupId, userIdList: userIdList, callMediaType: callMediaType, params: TUICallParams()) { + override func groupCall(groupId: String, userIdList: [String], callMediaType: TUICallMediaType) { + groupCall(groupId: groupId, userIdList: userIdList, callMediaType: callMediaType, params: getCallParams()) { + } fail: { code, message in } @@ -92,14 +98,55 @@ class TUICallKitImpl: TUICallKit { override func groupCall(groupId: String, userIdList: [String], callMediaType: TUICallMediaType, params: TUICallParams, succ: @escaping TUICallSucc, fail: @escaping TUICallFail) { + if userIdList.isEmpty { + fail(ERROR_PARAM_INVALID, "call failed, invalid params 'userIdList'") + return + } + + if userIdList.count >= MAX_USER { + fail(ERROR_PARAM_INVALID, "groupCall failed, currently supports call with up to 9 people") + TUITool.makeToast(TUICallKitLocalize(key: "Demo.TRTC.Calling.User.Exceed.Limit")) + return + } + + if TUILogin.getUserID() == nil { + fail(ERROR_INIT_FAIL, "call failed, please login") + return + } + + if WindowManager.instance.isFloating { + fail(ERROR_PARAM_INVALID, "call failed, Unable to restart the call") + TUITool.makeToast(TUICallKitLocalize(key: "Demo.TRTC.Calling.UnableToRestartTheCall")) + return + } + + if callMediaType == .unknown { + fail(ERROR_PARAM_INVALID, "call failed, callMediaType is Unknown") + return + } + + + if TUICallKitCommon.checkAuthorizationStatusIsDenied(mediaType: callMediaType) { + showAuthorizationAlert(mediaType: callMediaType) + fail(ERROR_PARAM_INVALID, "call failed, authorization status is denied") + return + } + CallEngineManager.instance.groupCall(groupId: groupId, userIdList: userIdList, callMediaType: callMediaType, params: params) { succ() - } fail: { code, message in + } fail: { [weak self] code, message in + guard let self = self else { return } + self.handleAbilityFailErrorMessage(code: code, message: message) fail(code,message) } } override func joinInGroupCall(roomId: TUIRoomId, groupId: String, callMediaType: TUICallMediaType) { + if TUICallKitCommon.checkAuthorizationStatusIsDenied(mediaType: callMediaType) { + showAuthorizationAlert(mediaType: callMediaType) + return + } + CallEngineManager.instance.joinInGroupCall(roomId: roomId, groupId: groupId, callMediaType: callMediaType) } @@ -153,7 +200,6 @@ class TUICallKitImpl: TUICallKit { } override func getCallViewController() -> UIViewController { - if let callWindowVC = WindowManager.instance.callWindow.rootViewController { return callWindowVC } @@ -164,13 +210,10 @@ class TUICallKitImpl: TUICallKit { return UIViewController() } - } - // MARK: TUICallKit内部接口 private extension TUICallKitImpl { - func registerNotifications() { NotificationCenter.default.addObserver(self, selector: #selector(loginSuccessNotification), @@ -191,6 +234,7 @@ private extension TUICallKitImpl { initState() CallEngineManager.instance.addObserver(TUICallState.instance) CallEngineManager.instance.setFramework() + CallEngineManager.instance.setExcludeFromHistoryMessage() } @objc func logoutSuccessNotification(noti: Notification) { @@ -205,8 +249,8 @@ private extension TUICallKitImpl { func initEngine() { CallEngineManager.instance.initEigine(sdkAppId:TUILogin.getSdkAppID(), - userId: TUILogin.getUserID() ?? "", - userSig: TUILogin.getUserSig() ?? "") {} fail: { Int32errCode, errMessage in } + userId: TUILogin.getUserID() ?? "", + userSig: TUILogin.getUserSig() ?? "") {} fail: { Int32errCode, errMessage in } let videoEncoderParams = TUIVideoEncoderParams() videoEncoderParams.resolution = ._640_360 @@ -217,15 +261,14 @@ private extension TUICallKitImpl { videoRenderParams.fillMode = .fill videoRenderParams.rotation = ._0 CallEngineManager.instance.setVideoRenderParams(userId: TUILogin.getUserID() ?? "", - params: videoRenderParams) {} fail: { Int32errCode, errMessage in } - + params: videoRenderParams) {} fail: { Int32errCode, errMessage in } + let beauty = CallEngineManager.instance.getTRTCCloudInstance().getBeautyManager() beauty.setBeautyStyle(.nature) beauty.setBeautyLevel(6.0) } func initState() { - CallEngineManager.instance.addObserver(TUICallState.instance) User.getSelfUserInfo(response: { selfUser in TUICallState.instance.selfUser.value.id.value = selfUser.id.value @@ -242,7 +285,7 @@ private extension TUICallKitImpl { CallEngineManager.instance.setAudioPlaybackDevice(device: TUIAudioPlaybackDevice.earpiece) WindowManager.instance.showCallWindow() } - + if TUICallState.instance.selfUser.value.callRole.value == TUICallRole.none && TUICallState.instance.selfUser.value.callStatus.value == TUICallStatus.none { WindowManager.instance.closeCallWindow() @@ -250,4 +293,40 @@ private extension TUICallKitImpl { } }) } + + func showAuthorizationAlert(mediaType: TUICallMediaType) { + let statusVideo: AVAuthorizationStatus = AVCaptureDevice.authorizationStatus(for: .video) + var deniedType: AuthorizationDeniedType = AuthorizationDeniedType.audio + + if mediaType == .video && statusVideo == .denied { + deniedType = .video + } + + TUICallKitCommon.showAuthorizationAlert(deniedType: deniedType) { + CallEngineManager.instance.hangup() + } cancelHandler: { + CallEngineManager.instance.hangup() + } + } + + func getCallParams() -> TUICallParams { + let offlinePushInfo = OfflinePushInfoConfig.createOfflinePushInfo() + let callParams = TUICallParams() + callParams.offlinePushInfo = offlinePushInfo + callParams.timeout = TUI_CALLKIT_SIGNALING_MAX_TIME + return callParams + } + + func handleAbilityFailErrorMessage(code: Int32, message: String?) { + var errorMessage: String? = message + if code == ERROR_PACKAGE_NOT_PURCHASED { + errorMessage = TUICallKitLocalize(key: "Demo.TRTC.Calling.purchased") + } else if code == ERROR_PACKAGE_NOT_SUPPORTED { + errorMessage = TUICallKitLocalize(key: "Demo.TRTC.Calling.support") + } else if code == ERR_SVR_MSG_IN_PEER_BLACKLIST.rawValue { + errorMessage = TUICallKitLocalize(key: "Demo.TRTC.Calling.ErrorInPeerBlacklist") + } + TUITool.makeToast(errorMessage ?? "", duration: 4) + } + } diff --git a/iOS/TUIKit/TUICallKit/TUICallKit-Swift/Utils/Localized.swift b/iOS/TUIKit/TUICallKit/TUICallKit-Swift/Utils/Localized.swift index 5be8b47bd..f257fbd62 100644 --- a/iOS/TUIKit/TUICallKit/TUICallKit-Swift/Utils/Localized.swift +++ b/iOS/TUIKit/TUICallKit/TUICallKit-Swift/Utils/Localized.swift @@ -21,10 +21,6 @@ func TUICallKitLocalizerFromTableAndCommon(key: String, common: String, table: S return TUICallKitLocalizeFromTable(key: key, table: table) } -//MARK: Replace String - - - // MARK: CallKit let TUICallKit_Localize_TableName = "CallingLocalized" func TUICallKitLocalize(key: String) -> String? { diff --git a/iOS/TUIKit/TUICallKit/TUICallKit-Swift/Utils/TUICallKitCommon.swift b/iOS/TUIKit/TUICallKit/TUICallKit-Swift/Utils/TUICallKitCommon.swift new file mode 100644 index 000000000..7f9a96d62 --- /dev/null +++ b/iOS/TUIKit/TUICallKit/TUICallKit-Swift/Utils/TUICallKitCommon.swift @@ -0,0 +1,104 @@ +// +// TUICallKitCommon.swift +// TUICallKit-Swift +// +// Created by vincepzhang on 2023/8/14. +// + +import Foundation +import TUICallEngine +import AVFoundation + +enum AuthorizationDeniedType { + case audio + case video +} + +class TUICallKitCommon { + + static func createRoomId() -> UInt32 { + return 1 + arc4random() % (UINT32_MAX / 2 - 1) + } + + static func getTUICallKitBundle() -> Bundle? { + guard let url: URL = Bundle.main.url(forResource: "TUICallingKitBundle", withExtension: "bundle") else { return nil } + return Bundle(url: url) + } + + static func getBundleImage(name: String) -> UIImage? { + return UIImage(named: name, in: self.getTUICallKitBundle(), compatibleWith: nil) + } + + static func getUrlImage(url: String) -> UIImage? { + guard let url = URL(string: url) else { return nil } + var data = Data() + do { + data = try Data(contentsOf: url) + } catch _ as NSError {} + return UIImage(data: data) + } + + static func getKeyWindow() -> UIWindow? { + if #available(iOS 13.0, *) { + return UIApplication.shared.windows.filter({ $0.isKeyWindow }).last + } else { + return UIApplication.shared.keyWindow + } + } + + static func checkAuthorizationStatusIsDenied(mediaType: TUICallMediaType) -> Bool { + let statusAudio: AVAuthorizationStatus = AVCaptureDevice.authorizationStatus(for: .audio) + let statusVideo: AVAuthorizationStatus = AVCaptureDevice.authorizationStatus(for: .video) + + if mediaType == TUICallMediaType.video && statusVideo == .denied { + return true + } + + if mediaType == TUICallMediaType.audio && statusAudio == .denied { + return true + } + + return false + } + + static func showAuthorizationAlert(deniedType: AuthorizationDeniedType, + openSettingHandler: @escaping () -> Void, + cancelHandler: @escaping () -> Void) { + var title: String + var message: String + var laterMessage: String + var openSettingMessage: String + + switch deniedType { + case .audio: + title = TUICallKitLocalize(key: "TUICallKit.failedtogetmicrophonepermission.Title") ?? "" + message = TUICallKitLocalize(key: "TUICallKit.failedtogetmicrophonepermission.Tips") ?? "" + laterMessage = TUICallKitLocalize(key: "TUICallKit.failedtogetmicrophonepermission.Later") ?? "" + openSettingMessage = TUICallKitLocalize(key: "TUICallKit.failedtogetmicrophonepermission.Enable") ?? "" + case .video: + title = TUICallKitLocalize(key: "TUICallKit.failedtogetcamerapermission.Title") ?? "" + message = TUICallKitLocalize(key: "TUICallKit.failedtogetcamerapermission.Tips") ?? "" + laterMessage = TUICallKitLocalize(key: "TUICallKit.failedtogetcamerapermission.Later") ?? "" + openSettingMessage = TUICallKitLocalize(key: "TUICallKit.failedtogetcamerapermission.Enable") ?? "" + } + + let alertController = UIAlertController(title: title, message: message, preferredStyle: .alert ) + + alertController.addAction(UIAlertAction(title: laterMessage, style: .cancel, handler: { action in + cancelHandler() + })) + + alertController.addAction(UIAlertAction(title: openSettingMessage, style: .default, handler: { action in + openSettingHandler() + let app = UIApplication.shared + guard let url = URL(string: UIApplication.openSettingsURLString) else { return } + if app.canOpenURL(url) { + app.openURL(url) + } + })) + + DispatchQueue.main.async { + UIApplication.shared.keyWindow?.rootViewController?.present(alertController, animated: true) + } + } +} diff --git a/iOS/TUIKit/TUICallKit/TUICallKit-Swift/Utils/TUICoreDefineConvert.swift b/iOS/TUIKit/TUICallKit/TUICallKit-Swift/Utils/TUICoreDefineConvert.swift new file mode 100644 index 000000000..ed3099780 --- /dev/null +++ b/iOS/TUIKit/TUICallKit/TUICallKit-Swift/Utils/TUICoreDefineConvert.swift @@ -0,0 +1,59 @@ +// +// TUICoreDefineConvert.swift +// TUICallKit-Swift +// +// Created by vincepzhang on 2023/8/14. +// + +import Foundation +import TUICore + + +class TUICoreDefineConvert { + + static func getTUIKitLocalizableString(key: String) -> String { + return TUIGlobalization.getLocalizedString(forKey: key, bundle: TUIKitLocalizableBundle) + } + + static func getTIMCommonLocalizableString(key: String) -> String? { + return TUIGlobalization.getLocalizedString(forKey: key, bundle: TIMCommonLocalizableBundle) + } + + static func getTUICoreBundleThemeImage(imageKey: String, defaultImageName: String) -> UIImage? { + let tuiCoreCommonBundleImage = UIImage(contentsOfFile: getTUIGetBundlePath(TUICoreBundle, TUICoreBundle_Key_Class) + "/" + defaultImageName) + return TUITheme.dynamicImage(imageKey, module: TUIThemeModule.core, defaultImage: tuiCoreCommonBundleImage ?? UIImage()) + } + + static func getTUIDynamicImage(imageKey: String, module: TUIThemeModule, defaultImage: UIImage) -> UIImage? { + return TUITheme.dynamicImage(imageKey, module: module, defaultImage: defaultImage) + } + + static func getTUIContactImagePathMinimalist(imageName: String) -> String { + return getTUIGetBundlePath(TUIContactBundle_Minimalist, TUIContactBundle_Key_Class) + "/" + imageName + } + + static func getTUICallKitDynamicColor(colorKey: String, defaultHex: String) -> UIColor? { + return TUITheme.dynamicColor(colorKey, module: TUIThemeModule.calling, defaultColor: defaultHex) + } + + static func getTUICoreDynamicColor(colorKey: String, defaultHex: String) -> UIColor? { + return TUITheme.dynamicColor(colorKey, module: TUIThemeModule.core, defaultColor: defaultHex) + } + + static func setTUIRegisterThemeResourcePath(path: String, modlue: TUIThemeModule) { + TUIThemeManager.share().registerThemeResourcePath(path, for: modlue) + } + + static func getDefaultAvatarImage() -> UIImage { + return TUIConfig.default().defaultAvatarImage + } + + static func getDefaultGroupAvatarImage() -> UIImage { + return TUIConfig.default().defaultAvatarImage + } + + static func getIsRTL() -> Bool { + return TUIGlobalization.getRTLOption() + } + +} diff --git a/iOS/TUIKit/TUICallKit/TUICallKit-Swift/Utils/Utils.swift b/iOS/TUIKit/TUICallKit/TUICallKit-Swift/Utils/Utils.swift index 318e8dac6..3b8ac2d1e 100644 --- a/iOS/TUIKit/TUICallKit/TUICallKit-Swift/Utils/Utils.swift +++ b/iOS/TUIKit/TUICallKit/TUICallKit-Swift/Utils/Utils.swift @@ -6,8 +6,6 @@ // import Foundation -import ImSDK_Plus -import TUICore func DispatchCallKitMainAsyncSafe(closure: @escaping () -> Void) { if Thread.current.isMainThread { @@ -16,81 +14,3 @@ func DispatchCallKitMainAsyncSafe(closure: @escaping () -> Void) { DispatchQueue.main.async(execute: closure) } } - -let kControlBtnSize = CGSizeMake(100, 92) -let kBtnLargeSize = CGSizeMake(64, 64) -let kBtnSmallSize = CGSizeMake(52, 52) - -class TUICallKitCommon { - - enum AuthorizationDeniedType { - case AuthorizationDeniedTypeAudio - case AuthorizationDeniedTypeVideo - } - - static func createRoomId() -> UInt32 { - return 1 + arc4random() % (UINT32_MAX / 2 - 1) - } - - static func getTUICallKitBundle() -> Bundle? { - guard let url: URL = Bundle.main.url(forResource: "TUICallingKitBundle", withExtension: "bundle") else { return nil } - return Bundle(url: url) - } - - static func getBundleImage(name: String) -> UIImage? { - return UIImage(named: name, in: self.getTUICallKitBundle(), compatibleWith: nil) - } - - static func getUrlImage(url: String) -> UIImage? { - guard let url = URL(string: url) else { return nil } - var data = Data() - do { - data = try Data(contentsOf: url) - } catch _ as NSError {} - return UIImage(data: data) - } - - static func getKeyWindow() -> UIWindow? { - if #available(iOS 13.0, *) { - return UIApplication.shared.windows.filter({ $0.isKeyWindow }).last - } else { - return UIApplication.shared.keyWindow - } - } - - static func showAuthorizationAlert(deniedType: AuthorizationDeniedType) { - var title: String - var message: String - var laterMessage: String - var openSettingMessage: String - - switch deniedType { - case .AuthorizationDeniedTypeAudio: - title = TUICallKitLocalize(key: "TUICallKit.failedtogetmicrophonepermission.Title") ?? "" - message = TUICallKitLocalize(key: "TUICallKit.failedtogetmicrophonepermission.Tips") ?? "" - laterMessage = TUICallKitLocalize(key: "TUICallKit.failedtogetmicrophonepermission.Later") ?? "" - openSettingMessage = TUICallKitLocalize(key: "TUICallKit.failedtogetmicrophonepermission.Enable") ?? "" - case .AuthorizationDeniedTypeVideo: - title = TUICallKitLocalize(key: "TUICallKit.failedtogetcamerapermission.Title") ?? "" - message = TUICallKitLocalize(key: "TUICallKit.failedtogetcamerapermission.Tips") ?? "" - laterMessage = TUICallKitLocalize(key: "TUICallKit.failedtogetcamerapermission.Later") ?? "" - openSettingMessage = TUICallKitLocalize(key: "TUICallKit.failedtogetcamerapermission.Enable") ?? "" - } - - let alertController = UIAlertController(title: title, message: message, preferredStyle: .alert ) - alertController.addAction(UIAlertAction(title: laterMessage, style: .cancel)) - alertController.addAction(UIAlertAction(title: openSettingMessage, style: .default, handler: { action in - let app = UIApplication.shared - guard let url = URL(string: UIApplication.openSettingsURLString) else { return } - if app.canOpenURL(url) { - app.openURL(url) - } - })) - - DispatchQueue.main.async { - UIApplication.shared.keyWindow?.rootViewController?.present(alertController, animated: true) - } - } - -} - diff --git a/iOS/TUIKit/TUICallKit/TUICallKit-Swift/View/CallKitViewController.swift b/iOS/TUIKit/TUICallKit/TUICallKit-Swift/View/CallKitViewController.swift index 8cc3a1e09..77a0288e9 100644 --- a/iOS/TUIKit/TUICallKit/TUICallKit-Swift/View/CallKitViewController.swift +++ b/iOS/TUIKit/TUICallKit/TUICallKit-Swift/View/CallKitViewController.swift @@ -20,7 +20,7 @@ class CallKitViewController: UIViewController { override func viewDidLoad(){ super.viewDidLoad() if TUICallState.instance.scene.value == .single { - let callView: SingleCallView? = SingleCallView(frame: CGRectZero) + let callView: SingleCallView? = SingleCallView(frame: CGRect.zero) view.addSubview(callView ?? UIView()) } else if TUICallState.instance.scene.value == .group { let groupCallView = GroupCallView() diff --git a/iOS/TUIKit/TUICallKit/TUICallKit-Swift/View/Component/CallWaitingHintView.swift b/iOS/TUIKit/TUICallKit/TUICallKit-Swift/View/Component/CallWaitingHintView.swift index dce8c497b..53730a4af 100644 --- a/iOS/TUIKit/TUICallKit/TUICallKit-Swift/View/Component/CallWaitingHintView.swift +++ b/iOS/TUIKit/TUICallKit/TUICallKit-Swift/View/Component/CallWaitingHintView.swift @@ -11,7 +11,7 @@ class CallWaitingHintView: UIView { let label: UILabel = { - let waitingInviteLabel = UILabel(frame: CGRectZero) + let waitingInviteLabel = UILabel(frame: CGRect.zero) waitingInviteLabel.textColor = UIColor.t_colorWithHexString(color: "#999999") waitingInviteLabel.font = UIFont.boldSystemFont(ofSize: 14.0) waitingInviteLabel.backgroundColor = UIColor.clear diff --git a/iOS/TUIKit/TUICallKit/TUICallKit-Swift/View/Component/Common/BaseControlButton.swift b/iOS/TUIKit/TUICallKit/TUICallKit-Swift/View/Component/Common/BaseControlButton.swift index eec4b7ce4..fb486157f 100644 --- a/iOS/TUIKit/TUICallKit/TUICallKit-Swift/View/Component/Common/BaseControlButton.swift +++ b/iOS/TUIKit/TUICallKit/TUICallKit-Swift/View/Component/Common/BaseControlButton.swift @@ -12,12 +12,12 @@ import SnapKit typealias ButtonActionBlock = (_ sender: UIButton) -> Void class BaseControlButton: UIView { - + var buttonActionBlock: ButtonActionBlock? var imageSize: CGSize let titleLabel: UILabel = { - let titleLable = UILabel(frame: CGRectZero) + let titleLable = UILabel(frame: CGRect.zero) titleLable.font = UIFont.systemFont(ofSize: 12.0) titleLable.textAlignment = .center return titleLable @@ -55,7 +55,7 @@ class BaseControlButton: UIView { bindInteraction() isViewReady = true } - + func constructViewHierarchy() { addSubview(button) addSubview(titleLabel) @@ -64,7 +64,7 @@ class BaseControlButton: UIView { func activateConstraints() { titleLabel.snp.makeConstraints { make in - make.left.right.centerX.bottom.equalTo(self) + make.leading.trailing.centerX.bottom.equalTo(self) } button.snp.makeConstraints { make in @@ -77,7 +77,7 @@ class BaseControlButton: UIView { func bindInteraction() { button.addTarget(self, action: #selector(buttonActionEvent(sender: )), for: .touchUpInside) } - + // MARK: Update Info func updateImage(image: UIImage) { button.setBackgroundImage(image, for: .normal) diff --git a/iOS/TUIKit/TUICallKit/TUICallKit-Swift/View/Component/FloatView/FloatWindowViewController.swift b/iOS/TUIKit/TUICallKit/TUICallKit-Swift/View/Component/FloatView/FloatWindowViewController.swift index b650c9f84..3d5e2a9cf 100644 --- a/iOS/TUIKit/TUICallKit/TUICallKit-Swift/View/Component/FloatView/FloatWindowViewController.swift +++ b/iOS/TUIKit/TUICallKit/TUICallKit-Swift/View/Component/FloatView/FloatWindowViewController.swift @@ -11,7 +11,7 @@ import TUICore class FloatWindowViewController: UIViewController, FloatingWindowViewDelegate { let callEventObserver = Observer() - let floatView = FloatingWindowView(frame: CGRectZero) + let floatView = FloatingWindowView(frame: CGRect.zero) weak var delegate: FloatingWindowViewDelegate? override func viewDidLoad() { diff --git a/iOS/TUIKit/TUICallKit/TUICallKit-Swift/View/Component/FloatView/FloatingWindowButton.swift b/iOS/TUIKit/TUICallKit/TUICallKit-Swift/View/Component/FloatView/FloatingWindowButton.swift index 73ca5a631..1e6947cae 100644 --- a/iOS/TUIKit/TUICallKit/TUICallKit-Swift/View/Component/FloatView/FloatingWindowButton.swift +++ b/iOS/TUIKit/TUICallKit/TUICallKit-Swift/View/Component/FloatView/FloatingWindowButton.swift @@ -49,7 +49,7 @@ class FloatingWindowButton: UIView { func activateConstraints() { floatButton.snp.makeConstraints { make in make.center.equalTo(self) - make.size.equalTo(CGSize(width: 40, height: 40)) + make.size.equalTo(kFloatWindowButtonSize) } } diff --git a/iOS/TUIKit/TUICallKit/TUICallKit-Swift/View/Component/FloatView/FloatingWindowView.swift b/iOS/TUIKit/TUICallKit/TUICallKit-Swift/View/Component/FloatView/FloatingWindowView.swift index d75d14ea6..eb913f27a 100644 --- a/iOS/TUIKit/TUICallKit/TUICallKit-Swift/View/Component/FloatView/FloatingWindowView.swift +++ b/iOS/TUIKit/TUICallKit/TUICallKit-Swift/View/Component/FloatView/FloatingWindowView.swift @@ -13,8 +13,8 @@ private let kMicroWindowCornerRatio = 15.0 private let kMicroContainerViewOffset = 8.0 private let kCallKitSingleSmallVideoViewWidth = 100.0 -private let kCallKitSingleSmallVideoViewFrame = CGRectMake(5, 5, kCallKitSingleSmallVideoViewWidth - 10, - (kCallKitSingleSmallVideoViewWidth / 9.0 * 16.0) - 10 ) +private let kCallKitSingleSmallVideoViewFrame = CGRect(x: 5, y: 5, width: kCallKitSingleSmallVideoViewWidth - 10, + height: (kCallKitSingleSmallVideoViewWidth / 9.0 * 16.0) - 10 ) protocol FloatingWindowViewDelegate: NSObject { func tapGestureAction(tapGesture: UITapGestureRecognizer) @@ -31,19 +31,19 @@ class FloatingWindowView: UIView { var localPreView: VideoView { if VideoFactory.instance.viewMap[viewModel.selfUser.value.id.value] == nil { - let _ = VideoFactory.instance.createVideoView(userId: viewModel.selfUser.value.id.value, frame: CGRectZero) + let _ = VideoFactory.instance.createVideoView(userId: viewModel.selfUser.value.id.value, frame: CGRect.zero) } VideoFactory.instance.viewMap[viewModel.selfUser.value.id.value]?.videoView.isUserInteractionEnabled = false - return VideoFactory.instance.viewMap[viewModel.selfUser.value.id.value]?.videoView ?? VideoView(frame: CGRectZero) + return VideoFactory.instance.viewMap[viewModel.selfUser.value.id.value]?.videoView ?? VideoView(frame: CGRect.zero) } var remotePreView: VideoView { - guard let remoteUser = self.viewModel.remoteUserList.value.first else { return VideoView(frame: CGRectZero) } + guard let remoteUser = self.viewModel.remoteUserList.value.first else { return VideoView(frame: CGRect.zero) } if VideoFactory.instance.viewMap[remoteUser.id.value] == nil { - let _ = VideoFactory.instance.createVideoView(userId: remoteUser.id.value, frame: CGRectZero) + let _ = VideoFactory.instance.createVideoView(userId: remoteUser.id.value, frame: CGRect.zero) } VideoFactory.instance.viewMap[remoteUser.id.value]?.videoView.isUserInteractionEnabled = false - return VideoFactory.instance.viewMap[remoteUser.id.value]?.videoView ?? VideoView(frame: CGRectZero) + return VideoFactory.instance.viewMap[remoteUser.id.value]?.videoView ?? VideoView(frame: CGRect.zero) } let avatarImageView: UIImageView = { diff --git a/iOS/TUIKit/TUICallKit/TUICallKit-Swift/View/Component/Function/AudioAndVideoCalleeWaitingView.swift b/iOS/TUIKit/TUICallKit/TUICallKit-Swift/View/Component/Function/AudioAndVideoCalleeWaitingView.swift index 80a8832fd..ef38ed234 100644 --- a/iOS/TUIKit/TUICallKit/TUICallKit-Swift/View/Component/Function/AudioAndVideoCalleeWaitingView.swift +++ b/iOS/TUIKit/TUICallKit/TUICallKit-Swift/View/Component/Function/AudioAndVideoCalleeWaitingView.swift @@ -15,9 +15,9 @@ class AudioAndVideoCalleeWaitingView: UIView { lazy var acceptBtn: BaseControlButton = { weak var weakSelf = self - let acceptBtn = BaseControlButton.create(frame: CGRectZero, + let acceptBtn = BaseControlButton.create(frame: CGRect.zero, title: TUICallKitLocalize(key: "Demo.TRTC.Calling.answer") ?? "", - imageSize: CGSizeMake(64, 64)) { sender in + imageSize: CGSize(width: 64, height: 64)) { sender in weakSelf?.acceptTouchEvent(sender: sender) } if let image = TUICallKitCommon.getBundleImage(name: "trtccalling_ic_dialing") { @@ -30,12 +30,12 @@ class AudioAndVideoCalleeWaitingView: UIView { } return acceptBtn }() - + lazy var rejectBtn: BaseControlButton = { weak var weakSelf = self - let rejectBtn = BaseControlButton.create(frame: CGRectZero, + let rejectBtn = BaseControlButton.create(frame: CGRect.zero, title: TUICallKitLocalize(key: "Demo.TRTC.Calling.decline") ?? "", - imageSize: CGSizeMake(64, 64)) { sender in + imageSize: CGSize(width: 64, height: 64)) { sender in weakSelf?.rejectTouchEvent(sender: sender) } if let image = TUICallKitCommon.getBundleImage(name: "ic_hangup") { @@ -48,7 +48,7 @@ class AudioAndVideoCalleeWaitingView: UIView { } return rejectBtn }() - + override init(frame: CGRect) { super.init(frame: frame) registerObserveState() @@ -71,42 +71,42 @@ class AudioAndVideoCalleeWaitingView: UIView { activateConstraints() isViewReady = true } - + func constructViewHierarchy() { addSubview(rejectBtn) addSubview(acceptBtn) } - + func activateConstraints() { rejectBtn.snp.makeConstraints { make in - make.centerX.equalTo(self).offset(-80) + make.centerX.equalTo(self).offset(TUICoreDefineConvert.getIsRTL() ? 80 : -80) make.bottom.equalTo(self) make.width.equalTo(100) make.height.equalTo(94) } acceptBtn.snp.makeConstraints { make in - make.centerX.equalTo(self).offset(80) + make.centerX.equalTo(self).offset(TUICoreDefineConvert.getIsRTL() ? -80 : 80) make.bottom.equalTo(self) make.width.equalTo(100) make.height.equalTo(94) } } - + //MARK: Event Action func rejectTouchEvent(sender: UIButton) { viewModel.reject() } - + func acceptTouchEvent(sender: UIButton) { viewModel.accept() } - + // MARK: Register TUICallState Observer && Update UI func registerObserveState() { mediaTypeChange() } - + func mediaTypeChange() { viewModel.mediaType.addObserver(mediaTypeObserver) { [weak self] newValue, _ in guard let self = self else { return } diff --git a/iOS/TUIKit/TUICallKit/TUICallKit-Swift/View/Component/Function/AudioCallerWaitingAndAcceptedView.swift b/iOS/TUIKit/TUICallKit/TUICallKit-Swift/View/Component/Function/AudioCallerWaitingAndAcceptedView.swift index 03a2e3cef..cec49fbc6 100644 --- a/iOS/TUIKit/TUICallKit/TUICallKit-Swift/View/Component/Function/AudioCallerWaitingAndAcceptedView.swift +++ b/iOS/TUIKit/TUICallKit/TUICallKit-Swift/View/Component/Function/AudioCallerWaitingAndAcceptedView.swift @@ -16,7 +16,7 @@ class AudioCallerWaitingAndAcceptedView : UIView { lazy var muteMicBtn: BaseControlButton = { weak var weakSelf = self - let muteAudioBtn = BaseControlButton.create(frame: CGRectZero, + let muteAudioBtn = BaseControlButton.create(frame: CGRect.zero, title: TUICallKitLocalize(key: "Demo.TRTC.Calling.mic") ?? "" , imageSize: kBtnSmallSize, buttonAction: { sender in weakSelf?.muteMicEvent(sender: sender) @@ -30,7 +30,7 @@ class AudioCallerWaitingAndAcceptedView : UIView { lazy var hangupBtn: BaseControlButton = { weak var weakSelf = self - let hangupBtn = BaseControlButton.create(frame: CGRectZero, + let hangupBtn = BaseControlButton.create(frame: CGRect.zero, title: TUICallKitLocalize(key: "Demo.TRTC.Calling.hangup") ?? "" , imageSize: kBtnLargeSize, buttonAction: { sender in weakSelf?.hanguphEvent(sender: sender) @@ -44,7 +44,7 @@ class AudioCallerWaitingAndAcceptedView : UIView { lazy var changeSpeakerBtn: BaseControlButton = { weak var weakSelf = self - let changeSpeakerBtn = BaseControlButton.create(frame: CGRectZero, + let changeSpeakerBtn = BaseControlButton.create(frame: CGRect.zero, title: TUICallKitLocalize(key: "Demo.TRTC.Calling.speaker") ?? "" , imageSize: kBtnSmallSize, buttonAction: { sender in weakSelf?.changeSpeakerEvent(sender: sender) @@ -89,7 +89,7 @@ class AudioCallerWaitingAndAcceptedView : UIView { func activateConstraints() { muteMicBtn.snp.makeConstraints { make in - make.right.equalTo(hangupBtn.snp.left).offset(-5) + make.trailing.equalTo(hangupBtn.snp.leading).offset(-5) make.centerY.equalTo(hangupBtn) make.size.equalTo(kControlBtnSize) } @@ -101,7 +101,7 @@ class AudioCallerWaitingAndAcceptedView : UIView { } changeSpeakerBtn.snp.makeConstraints { make in - make.left.equalTo(self.hangupBtn.snp.right).offset(5) + make.leading.equalTo(self.hangupBtn.snp.trailing).offset(5) make.centerY.equalTo(self.hangupBtn) make.size.equalTo(kControlBtnSize) } diff --git a/iOS/TUIKit/TUICallKit/TUICallKit-Swift/View/Component/Function/VideoCallerAndCalleeAcceptedView.swift b/iOS/TUIKit/TUICallKit/TUICallKit-Swift/View/Component/Function/VideoCallerAndCalleeAcceptedView.swift index 0f65fae3a..1c5f904a4 100644 --- a/iOS/TUIKit/TUICallKit/TUICallKit-Swift/View/Component/Function/VideoCallerAndCalleeAcceptedView.swift +++ b/iOS/TUIKit/TUICallKit/TUICallKit-Swift/View/Component/Function/VideoCallerAndCalleeAcceptedView.swift @@ -13,7 +13,7 @@ class VideoCallerAndCalleeAcceptedView: UIView { let viewModel = FunctionViewModel() lazy var muteMicBtn: BaseControlButton = { weak var weakSelf = self - let btn = BaseControlButton.create(frame: CGRectZero, + let btn = BaseControlButton.create(frame: CGRect.zero, title: TUICallKitLocalize(key: "Demo.TRTC.Calling.mic") ?? "", imageSize: kBtnSmallSize) { sender in weakSelf?.muteMicEvent(sender: sender) @@ -27,7 +27,7 @@ class VideoCallerAndCalleeAcceptedView: UIView { lazy var closeCameraBtn: BaseControlButton = { weak var weakSelf = self - let btn = BaseControlButton.create(frame: CGRectZero, + let btn = BaseControlButton.create(frame: CGRect.zero, title: TUICallKitLocalize(key: "Demo.TRTC.Calling.camera") ?? "", imageSize: kBtnSmallSize) { sender in weakSelf?.closeCameraTouchEvent(sender: sender) @@ -41,7 +41,7 @@ class VideoCallerAndCalleeAcceptedView: UIView { lazy var changeSpeakerBtn: BaseControlButton = { weak var weakSelf = self - let btn = BaseControlButton.create(frame: CGRectZero, + let btn = BaseControlButton.create(frame: CGRect.zero, title: TUICallKitLocalize(key: "Demo.TRTC.Calling.speaker") ?? "", imageSize: kBtnSmallSize) { sender in weakSelf?.changeSpeakerEvent(sender: sender) @@ -55,7 +55,7 @@ class VideoCallerAndCalleeAcceptedView: UIView { lazy var hangupBtn: BaseControlButton = { weak var weakSelf = self - let btn = BaseControlButton.create(frame: CGRectZero, + let btn = BaseControlButton.create(frame: CGRect.zero, title: TUICallKitLocalize(key: "Demo.TRTC.Calling.hangup") ?? "", imageSize: kBtnLargeSize) { sender in weakSelf?.hangupTouchEvent(sender: sender) @@ -104,7 +104,7 @@ class VideoCallerAndCalleeAcceptedView: UIView { func activateConstraints() { muteMicBtn.snp.makeConstraints { make in - make.right.equalTo(changeSpeakerBtn.snp.left) + make.trailing.equalTo(changeSpeakerBtn.snp.leading) make.centerY.equalTo(changeSpeakerBtn) make.size.equalTo(kControlBtnSize) } @@ -116,7 +116,7 @@ class VideoCallerAndCalleeAcceptedView: UIView { } closeCameraBtn.snp.makeConstraints { make in - make.left.equalTo(changeSpeakerBtn.snp.right) + make.leading.equalTo(changeSpeakerBtn.snp.trailing) make.centerY.equalTo(changeSpeakerBtn) make.size.equalTo(kControlBtnSize) } @@ -129,7 +129,7 @@ class VideoCallerAndCalleeAcceptedView: UIView { switchCameraBtn.snp.makeConstraints { make in make.centerY.equalTo(hangupBtn) - make.left.equalTo(hangupBtn.snp.right).offset(20) + make.leading.equalTo(hangupBtn.snp.trailing).offset(20) make.size.equalTo(CGSize(width: 36, height: 36)) } } diff --git a/iOS/TUIKit/TUICallKit/TUICallKit-Swift/View/Component/Function/VideoCallerWaitingView.swift b/iOS/TUIKit/TUICallKit/TUICallKit-Swift/View/Component/Function/VideoCallerWaitingView.swift index e7a3011c7..7b1281ef2 100644 --- a/iOS/TUIKit/TUICallKit/TUICallKit-Swift/View/Component/Function/VideoCallerWaitingView.swift +++ b/iOS/TUIKit/TUICallKit/TUICallKit-Swift/View/Component/Function/VideoCallerWaitingView.swift @@ -12,7 +12,7 @@ class VideoCallerWaitingView: UIView { let viewModel = FunctionViewModel() lazy var hangupBtn: BaseControlButton = { weak var weakSelf = self - let btn = BaseControlButton.create(frame: CGRectZero, + let btn = BaseControlButton.create(frame: CGRect.zero, title: TUICallKitLocalize(key: "Demo.TRTC.Calling.hangup") ?? "", imageSize: kBtnLargeSize) { sender in weakSelf?.hangupTouchEvent(sender: sender) @@ -23,7 +23,7 @@ class VideoCallerWaitingView: UIView { btn.updateTitleColor(titleColor: UIColor.t_colorWithHexString(color: "#F2F2F2")) return btn }() - + let switchCameraBtn: UIButton = { let btn = UIButton(type: .system) if let image = TUICallKitCommon.getBundleImage(name: "switch_camera") { @@ -50,12 +50,12 @@ class VideoCallerWaitingView: UIView { bindInteraction() isViewReady = true } - + func constructViewHierarchy() { addSubview(hangupBtn) addSubview(switchCameraBtn) } - + func activateConstraints() { hangupBtn.snp.makeConstraints { make in make.center.equalTo(self) @@ -64,11 +64,11 @@ class VideoCallerWaitingView: UIView { switchCameraBtn.snp.makeConstraints { make in make.centerY.equalTo(hangupBtn) - make.left.equalTo(hangupBtn.snp.right).offset(20) + make.leading.equalTo(hangupBtn.snp.trailing).offset(20) make.size.equalTo(CGSize(width: 36, height: 36)) } } - + func bindInteraction() { switchCameraBtn.addTarget(self, action: #selector(switchCameraTouchEvent(sender: )), for: .touchUpInside) } @@ -77,9 +77,9 @@ class VideoCallerWaitingView: UIView { func hangupTouchEvent(sender: UIButton) { viewModel.hangup() } - + @objc func switchCameraTouchEvent(sender: UIButton ) { viewModel.switchCamera() } - + } diff --git a/iOS/TUIKit/TUICallKit/TUICallKit-Swift/View/Component/InviteUser/SelectGroupMeberCell.swift b/iOS/TUIKit/TUICallKit/TUICallKit-Swift/View/Component/InviteUser/SelectGroupMemberCell.swift similarity index 90% rename from iOS/TUIKit/TUICallKit/TUICallKit-Swift/View/Component/InviteUser/SelectGroupMeberCell.swift rename to iOS/TUIKit/TUICallKit/TUICallKit-Swift/View/Component/InviteUser/SelectGroupMemberCell.swift index a5f6d49fa..d793767f4 100644 --- a/iOS/TUIKit/TUICallKit/TUICallKit-Swift/View/Component/InviteUser/SelectGroupMeberCell.swift +++ b/iOS/TUIKit/TUICallKit/TUICallKit-Swift/View/Component/InviteUser/SelectGroupMemberCell.swift @@ -1,5 +1,5 @@ // -// SelectGroupMeberCell.swift +// SelectGroupMemberCell.swift // Alamofire // // Created by vincepzhang on 2023/5/12. @@ -7,22 +7,22 @@ import Foundation -class SelectGroupMeberCell: UITableViewCell { +class SelectGroupMemberCell: UITableViewCell { let userImageView = { - let view = UIImageView(frame: CGRectZero) + let view = UIImageView(frame: CGRect.zero) view.layer.cornerRadius = 10 view.layer.masksToBounds = true return view }() let nameLabel = { - let view = UILabel(frame: CGRectZero) + let view = UILabel(frame: CGRect.zero) view.textColor = UIColor.t_colorWithHexString(color: "#242424") return view }() let selectImageView = { - let view = UIImageView(frame: CGRectZero) + let view = UIImageView(frame: CGRect.zero) return view }() diff --git a/iOS/TUIKit/TUICallKit/TUICallKit-Swift/View/Component/InviteUser/SelectGroupMeberViewController.swift b/iOS/TUIKit/TUICallKit/TUICallKit-Swift/View/Component/InviteUser/SelectGroupMemberViewController.swift similarity index 70% rename from iOS/TUIKit/TUICallKit/TUICallKit-Swift/View/Component/InviteUser/SelectGroupMeberViewController.swift rename to iOS/TUIKit/TUICallKit/TUICallKit-Swift/View/Component/InviteUser/SelectGroupMemberViewController.swift index e776bd8ab..4e92c4202 100644 --- a/iOS/TUIKit/TUICallKit/TUICallKit-Swift/View/Component/InviteUser/SelectGroupMeberViewController.swift +++ b/iOS/TUIKit/TUICallKit/TUICallKit-Swift/View/Component/InviteUser/SelectGroupMemberViewController.swift @@ -1,19 +1,20 @@ // -// SelectGroupMeberViewController.swift +// SelectGroupMemberViewController.swift // Alamofire // // Created by vincepzhang on 2023/5/12. // import Foundation +import TUICore -class SelectGroupMeberViewController: UIViewController, UITableViewDelegate, UITableViewDataSource { +class SelectGroupMemberViewController: UIViewController, UITableViewDelegate, UITableViewDataSource { - let viewModel = SelectGroupMeberViewModel() + let viewModel = SelectGroupMemberViewModel() let groupMemberObserver = Observer() - + let selectTableView: UITableView = { - let selectTableView = UITableView(frame: CGRectZero) + let selectTableView = UITableView(frame: CGRect.zero) selectTableView.backgroundColor = UIColor.t_colorWithHexString(color: "#F2F2F2") return selectTableView }() @@ -41,52 +42,57 @@ class SelectGroupMeberViewController: UIViewController, UITableViewDelegate, UIT title = TUICallKitLocalize(key: "TUICallKit.Recents.addUser") navigationController?.navigationBar.titleTextAttributes = [NSAttributedString.Key.foregroundColor: UIColor.t_colorWithHexString(color: "#242424")] - + constructViewHierarchy() activateConstraints() bindInteraction() - registerObserve() + registerObserve() } func constructViewHierarchy() { view.addSubview(selectTableView) } - + func activateConstraints() { selectTableView.snp.makeConstraints({ make in make.edges.equalToSuperview() }) } - + func bindInteraction() { navigationItem.rightBarButtonItem = rightBtn navigationItem.leftBarButtonItem = leftBtn selectTableView.dataSource = self selectTableView.delegate = self - selectTableView.register(SelectGroupMeberCell.self, forCellReuseIdentifier: "SelectCell") + selectTableView.register(SelectGroupMemberCell.self, forCellReuseIdentifier: "SelectCell") } func registerObserve() { - viewModel.groupMerberList.addObserver(groupMemberObserver) {[weak self] _, _ in + viewModel.groupMemberList.addObserver(groupMemberObserver) {[weak self] _, _ in guard let self = self else { return } self.selectTableView.reloadData() } } - + //MARK: Action @objc func addUser() { var userIds: [String] = [] - for state in viewModel.groupMerberStateOrigin { + for state in viewModel.groupMemberStateOrigin { if state.value { continue } - if let isSelect = viewModel.groupMerberState[state.key] { + if let isSelect = viewModel.groupMemberState[state.key] { if isSelect { userIds.append(state.key) } } } + if userIds.count + TUICallState.instance.remoteUserList.value.count >= MAX_USER { + TUITool.makeToast(TUICallKitLocalize(key: "Demo.TRTC.Calling.User.Exceed.Limit")) + return + } + CallEngineManager.instance.inviteUser(userIds: userIds) dismiss(animated: true) } @@ -96,18 +102,18 @@ class SelectGroupMeberViewController: UIViewController, UITableViewDelegate, UIT } } -extension SelectGroupMeberViewController { +extension SelectGroupMemberViewController { func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { - return viewModel.groupMerberList.value.count + 1 + return viewModel.groupMemberList.value.count + 1 } - + func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { - let cell = tableView.dequeueReusableCell(withIdentifier: "SelectCell", for: indexPath) as? SelectGroupMeberCell + let cell = tableView.dequeueReusableCell(withIdentifier: "SelectCell", for: indexPath) as? SelectGroupMemberCell if indexPath.row == 0 { cell?.configCell(user: viewModel.selfUser.value, isSelect: true) } else { - let user = viewModel.groupMerberList.value[indexPath.row - 1] - let isSelect = viewModel.groupMerberState[user.id.value] + let user = viewModel.groupMemberList.value[indexPath.row - 1] + let isSelect = viewModel.groupMemberState[user.id.value] cell?.configCell(user: user, isSelect: isSelect ?? false) } return cell ?? UITableViewCell() @@ -123,15 +129,15 @@ extension SelectGroupMeberViewController { return } - let user = viewModel.groupMerberList.value[indexPath.row - 1] - if viewModel.groupMerberStateOrigin[user.id.value] ?? false { + let user = viewModel.groupMemberList.value[indexPath.row - 1] + if viewModel.groupMemberStateOrigin[user.id.value] ?? false { return } - if viewModel.groupMerberState[user.id.value] ?? false { - viewModel.groupMerberState[user.id.value] = false + if viewModel.groupMemberState[user.id.value] ?? false { + viewModel.groupMemberState[user.id.value] = false } else { - viewModel.groupMerberState[user.id.value] = true + viewModel.groupMemberState[user.id.value] = true } selectTableView.reloadData() diff --git a/iOS/TUIKit/TUICallKit/TUICallKit-Swift/View/Component/InviteUserButton.swift b/iOS/TUIKit/TUICallKit/TUICallKit-Swift/View/Component/InviteUserButton.swift index f11d207e6..6975f14b6 100644 --- a/iOS/TUIKit/TUICallKit/TUICallKit-Swift/View/Component/InviteUserButton.swift +++ b/iOS/TUIKit/TUICallKit/TUICallKit-Swift/View/Component/InviteUserButton.swift @@ -50,7 +50,7 @@ class InviteUserButton: UIView { func activateConstraints() { inviteUserButton.snp.makeConstraints { make in make.center.equalTo(self) - make.size.equalTo(CGSize(width: 40, height: 40)) + make.size.equalTo(kInviteUserButtonSize) } } diff --git a/iOS/TUIKit/TUICallKit/TUICallKit-Swift/View/Component/Recents/TUICallRecordCallsCell.swift b/iOS/TUIKit/TUICallKit/TUICallKit-Swift/View/Component/Recents/TUICallRecordCallsCell.swift new file mode 100644 index 000000000..e82ab9be2 --- /dev/null +++ b/iOS/TUIKit/TUICallKit/TUICallKit-Swift/View/Component/Recents/TUICallRecordCallsCell.swift @@ -0,0 +1,188 @@ +// +// TUICallRecordCallsCell.swift +// +// +// Created by vincepzhang on 2023/8/28. +// + +import Foundation +import UIKit +import SDWebImage +import TUICallEngine + +class TUICallRecordCallsCell: UITableViewCell { + + private let faceURLObserver = Observer() + private let titleObserver = Observer() + + typealias TUICallRecordCallsCellMoreBtnClickedHandler = () -> Void + var moreBtnClickedHandler: TUICallRecordCallsCellMoreBtnClickedHandler = {} + + private var isViewReady = false + private var viewModel: TUICallRecordCallsCellViewModel = TUICallRecordCallsCellViewModel(TUICallRecords()) + + private lazy var avatarImageView: UIImageView = { + let imageView = UIImageView() + imageView.contentMode = .scaleAspectFit + imageView.layer.cornerRadius = 20 + imageView.clipsToBounds = true + return imageView + }() + + private lazy var titleLabel: UILabel = { + let label = UILabel() + label.numberOfLines = 1 + label.font = UIFont(name: "PingFangHK-Semibold", size: 14) + label.textAlignment = TUICoreDefineConvert.getIsRTL() ? .right : .left + return label + }() + + private lazy var mediaTypeImageView: UIImageView = { + let imageView = UIImageView() + imageView.contentMode = .scaleAspectFit + return imageView + }() + + private lazy var resultLabel: UILabel = { + let label = UILabel() + label.textColor = TUICoreDefineConvert.getTUICallKitDynamicColor(colorKey: "callkit_recents_cell_subtitle_color", + defaultHex: "#888888") + label.font = UIFont.systemFont(ofSize: 12) + label.textAlignment = TUICoreDefineConvert.getIsRTL() ? .right : .left + return label + }() + + private lazy var timeLabel: UILabel = { + let label = UILabel() + label.textColor = TUICoreDefineConvert.getTUICallKitDynamicColor(colorKey: "callkit_recents_cell_time_color", + defaultHex: "#BBBBBB") + label.font = UIFont.systemFont(ofSize: 12) + label.textAlignment = TUICoreDefineConvert.getIsRTL() ? .left : .right + return label + }() + + private lazy var moreButton: UIButton = { + let button = UIButton(type: .custom) + button.setImage(TUICallKitCommon.getBundleImage(name: "ic_recents_more"), for: .normal) + button.imageView?.contentMode = .scaleAspectFit + return button + }() + + override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { + super.init(style: style, reuseIdentifier: reuseIdentifier) + contentView.backgroundColor = TUICoreDefineConvert.getTUICallKitDynamicColor(colorKey: "callkit_recents_cell_bg_color", + defaultHex: "#FFFFFF") + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + deinit { + unregisterObserve() + } + + override func didMoveToWindow() { + super.didMoveToWindow() + if isViewReady { + return + } + isViewReady = true + constructViewHierarchy() + activateConstraints() + bindInteraction() + } + + override func prepareForReuse() { + super.prepareForReuse() + } + + private func constructViewHierarchy() { + contentView.addSubview(avatarImageView) + contentView.addSubview(titleLabel) + contentView.addSubview(mediaTypeImageView) + contentView.addSubview(resultLabel) + contentView.addSubview(timeLabel) + contentView.addSubview(moreButton) + } + + private func activateConstraints() { + avatarImageView.snp.makeConstraints { make in + make.centerY.equalTo(contentView) + make.leading.equalTo(contentView).offset(8) + make.width.height.equalTo(40) + } + titleLabel.snp.makeConstraints { make in + make.top.equalTo(contentView).offset(14) + make.leading.equalTo(avatarImageView.snp.trailing).offset(8) + make.trailing.lessThanOrEqualTo(timeLabel.snp.leading).offset(-20) + } + mediaTypeImageView.snp.makeConstraints { make in + make.bottom.equalTo(contentView).offset(-14) + make.leading.equalTo(avatarImageView.snp.trailing).offset(8) + make.width.equalTo(19) + make.height.equalTo(12) + } + resultLabel.snp.makeConstraints { make in + make.centerY.equalTo(mediaTypeImageView) + make.leading.equalTo(mediaTypeImageView.snp.trailing).offset(4) + make.width.equalTo(100) + } + timeLabel.snp.makeConstraints { make in + make.centerY.equalTo(contentView) + make.trailing.equalTo(moreButton.snp.leading).offset(-4) + make.width.equalTo(100) + } + moreButton.snp.makeConstraints { make in + make.centerY.equalTo(contentView) + make.trailing.equalTo(-8) + make.width.height.equalTo(24) + } + } + + private func bindInteraction() { + moreButton.addTarget(self, action: #selector(moreButtonClick(_:)), for: .touchUpInside) + } + + func configViewModel(_ viewModel: TUICallRecordCallsCellViewModel) { + // 获得cell对应的viewModel实例后再对viewModel进行监听 + self.viewModel = viewModel + registerObserve() + + titleLabel.text = viewModel.titleLabelStr.value + avatarImageView.sd_setImage(with: URL(string: viewModel.faceURL.value), placeholderImage: viewModel.avatarImage) + resultLabel.text = viewModel.resultLabelStr + timeLabel.text = viewModel.timeLabelStr + mediaTypeImageView.image = TUICallKitCommon.getBundleImage(name: viewModel.mediaTypeImageStr) + + if viewModel.callRecord.result == .missed { + titleLabel.textColor = UIColor.red + } else { + titleLabel.textColor = TUICoreDefineConvert.getTUICallKitDynamicColor(colorKey: "callkit_recents_cell_title_color", + defaultHex: "#000000") + } + } + + // IM获得faceURL、titleLabelStr为异步,结局时序问题 + func registerObserve() { + viewModel.faceURL.addObserver(faceURLObserver) { [weak self] _, _ in + guard let self = self else { return } + self.avatarImageView.sd_setImage(with: URL(string: self.viewModel.faceURL.value), + placeholderImage: self.viewModel.avatarImage) + } + + viewModel.titleLabelStr.addObserver(titleObserver) { [weak self] _, _ in + guard let self = self else { return } + self.titleLabel.text = self.viewModel.titleLabelStr.value + } + } + + func unregisterObserve() { + viewModel.faceURL.removeObserver(faceURLObserver) + viewModel.titleLabelStr.removeObserver(titleObserver) + } + + @objc private func moreButtonClick(_ button: UIButton) { + moreBtnClickedHandler() + } +} diff --git a/iOS/TUIKit/TUICallKit/TUICallKit-Swift/View/Component/Recents/TUICallRecordCallsViewController.swift b/iOS/TUIKit/TUICallKit/TUICallKit-Swift/View/Component/Recents/TUICallRecordCallsViewController.swift new file mode 100644 index 000000000..2cd867b72 --- /dev/null +++ b/iOS/TUIKit/TUICallKit/TUICallKit-Swift/View/Component/Recents/TUICallRecordCallsViewController.swift @@ -0,0 +1,311 @@ +// +// TUICallRecordCallsViewController.swift +// +// +// Created by vincepzhang on 2023/8/28. +// + +import Foundation +import UIKit +import SnapKit +import TUICore + +class TUICallRecordCallsViewController: UIViewController { + + private let viewModel = TUICallRecordCallsViewModel() + private let dataSourceObserver = Observer() + + // 头部导航容器视图 + private lazy var containerView: UIView = { + let view = UIView() + if viewModel.recordCallsUIStyle == .classic { + view.backgroundColor = TUICoreDefineConvert.getTUICoreDynamicColor(colorKey: "head_bg_gradient_start_color", + defaultHex: "#EBF0F6") + } else { + view.backgroundColor = TUICoreDefineConvert.getTUICoreDynamicColor(colorKey: "callkit_recents_bg_color", + defaultHex: "#FFFFFF") + } + return view + }() + + // 开始编辑按钮 + private lazy var editButton: UIButton = { + let button = UIButton(type: .custom) + button.setImage(TUICallKitCommon.getBundleImage(name: "ic_calls_edit"), for: .normal) + button.titleLabel?.textAlignment = TUICoreDefineConvert.getIsRTL() ? .right : .left + button.imageView?.contentMode = .scaleAspectFit + return button + }() + + // 清除所有记录按钮 + private lazy var clearButton: UIButton = { + let button = UIButton(type: .custom) + button.setTitle(TUICallKitLocalize(key: "TUICallKit.Recents.clear"), for: .normal) + button.titleLabel?.textAlignment = TUICoreDefineConvert.getIsRTL() ? .right : .left + button.contentHorizontalAlignment = TUICoreDefineConvert.getIsRTL() ? .right : .left + button.setTitleColor(TUICoreDefineConvert.getTUICallKitDynamicColor(colorKey: "callkit_nav_title_text_color", + defaultHex: "#000000"), for: .normal) + button.isHidden = true + button.titleLabel?.sizeToFit() + button.titleLabel?.adjustsFontSizeToFitWidth = true + return button + }() + + // 编辑完成按钮 + private lazy var doneButton: UIButton = { + let button = UIButton(type: .custom) + button.setTitle(TUICallKitLocalize(key: "TUICallKit.Recents.done"), for: .normal) + button.contentHorizontalAlignment = .right + button.setTitleColor(TUICoreDefineConvert.getTUICallKitDynamicColor(colorKey: "callkit_nav_title_text_color", + defaultHex: "#000000"), for: .normal) + button.titleLabel?.sizeToFit() + button.titleLabel?.adjustsFontSizeToFitWidth = true + button.isHidden = true + return button + }() + + // 分段控制视图 + private lazy var segmentedControl: UISegmentedControl = { + let items = [TUICallKitLocalize(key: "TUICallKit.Recents.all"), TUICallKitLocalize(key: "TUICallKit.Recents.missed")] + let control = UISegmentedControl(items: items as [Any]) + control.selectedSegmentIndex = 0 + return control + }() + + // 无最近通话提示文本 + private lazy var notRecordCallsLabel: UILabel = { + let label = UILabel(frame: .zero) + label.textColor = UIColor.gray + label.font = UIFont.systemFont(ofSize: 20) + label.textAlignment = .center + label.isHidden = true + return label + }() + + // 列表表头视图 + private lazy var tableHeaderView: UIView = { + let tableHeaderView = UIView(frame: CGRect(x: 0, y: 0, width: UIScreen.main.bounds.size.width, height: 80)) + let label = UILabel() + label.textColor = TUICoreDefineConvert.getTUICallKitDynamicColor(colorKey: "callkit_recents_tableHeader_title_text_color", + defaultHex: "#000000") + label.text = TUICallKitLocalize(key: "TUICallKit.Recents.calls") + label.font = UIFont(name: "PingFangHK-Semibold", size: 34) + label.textAlignment = TUICoreDefineConvert.getIsRTL() ? .right : .left + tableHeaderView.addSubview(label) + label.snp.makeConstraints { make in + make.center.equalToSuperview() + make.leading.equalTo(tableHeaderView).offset(20) + } + return tableHeaderView + }() + + // 通话记录列表 + private lazy var recordCallsList: UITableView = { + let tableView = UITableView(frame: .zero, style: .plain) + tableView.tableHeaderView = tableHeaderView + tableView.backgroundColor = view.backgroundColor + return tableView + }() + + + init(recordCallsUIStyle: TUICallKitRecordCallsUIStyle) { + super.init(nibName: nil, bundle: nil) + + viewModel.recordCallsUIStyle = recordCallsUIStyle + + view.backgroundColor = TUICoreDefineConvert.getTUICallKitDynamicColor(colorKey: "callkit_recents_bg_color", + defaultHex: "#FFFFFF") + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + // MARK: Observe + func registerObserve() { + NotificationCenter.default.addObserver(self, selector: #selector(windowDidChange), + name: UIWindow.didBecomeKeyNotification, object: nil) + + viewModel.dataSource.addObserver(dataSourceObserver) {[weak self] _, _ in + guard let self = self else { return } + DispatchQueue.main.async { [weak self] in + guard let self = self else { return } + self.recordCallsList.reloadData() + } + } + } + + func unregisterObserve() { + NotificationCenter.default.removeObserver(self, name: UIWindow.didBecomeKeyNotification, object: nil) + viewModel.dataSource.removeObserver(dataSourceObserver) + } + + // 页面出现的时候注册刷行UI的数据回调,页面消失关闭,防止页面UI刷新在非主线程中运行 + override func viewWillAppear(_ animated: Bool) { + registerObserve() + viewModel.queryRecentCalls() + } + + override func viewWillDisappear(_ animated: Bool) { + unregisterObserve() + } + + //MARK: UI Specification Processing + override func viewDidLoad() { + super.viewDidLoad() + constructViewHierarchy() + activateConstraints() + bindInteraction() + viewModel.queryRecentCalls() + } + + func constructViewHierarchy() { + view.addSubview(containerView) + containerView.addSubview(segmentedControl) + containerView.addSubview(editButton) + containerView.addSubview(clearButton) + containerView.addSubview(doneButton) + view.addSubview(notRecordCallsLabel) + view.addSubview(recordCallsList) + } + + func activateConstraints() { + containerView.snp.makeConstraints { make in + make.top.centerX.width.equalTo(view) + make.height.equalTo(StatusBar_Height + 44) + } + segmentedControl.snp.makeConstraints { make in + make.top.equalTo(containerView).offset(StatusBar_Height + 6.0) + make.centerX.equalTo(containerView) + make.width.equalTo(180) + make.height.equalTo(32) + } + editButton.snp.makeConstraints { make in + make.centerY.equalTo(segmentedControl) + make.trailing.equalTo(containerView).offset(-20) + make.width.height.equalTo(32) + } + clearButton.snp.makeConstraints { make in + make.centerY.equalTo(segmentedControl) + make.leading.equalTo(containerView).offset(20) + make.height.equalTo(32) + } + doneButton.snp.makeConstraints { make in + make.centerY.equalTo(segmentedControl) + make.trailing.equalTo(containerView).offset(-20) + make.height.equalTo(32) + } + recordCallsList.snp.makeConstraints { make in + make.top.equalTo(view).offset(StatusBar_Height + 44) + make.centerX.width.bottom.equalTo(view) + } + notRecordCallsLabel.snp.makeConstraints { make in + make.center.width.equalTo(view) + } + } + + func bindInteraction() { + recordCallsList.delegate = self + recordCallsList.dataSource = self + recordCallsList.register(TUICallRecordCallsCell.self, forCellReuseIdentifier: NSStringFromClass(TUICallRecordCallsCell.self)) + + clearButton.addTarget(self, action: #selector(clearButtonClick(_:)), for: .touchUpInside) + editButton.addTarget(self, action: #selector(editButtonClick(_:)), for: .touchUpInside) + doneButton.addTarget(self, action: #selector(doneButtonClick(_:)), for: .touchUpInside) + segmentedControl.addTarget(self, action: #selector(segmentSelectItem(_:)), for: .valueChanged) + } + + @objc func windowDidChange() { + viewModel.queryRecentCalls() + } + + @objc func clearButtonClick(_ button: UIButton) { + let alertController = UIAlertController(title: nil, message: nil, preferredStyle: .actionSheet) + let clearAction = UIAlertAction(title: TUICallKitLocalize(key: "TUICallKit.Recents.clear.all"), + style: .destructive) { [weak self] _ in + guard let self = self else { return } + self.recordCallsList.setEditing(false, animated: true) + self.setShowEditButton(true) + self.viewModel.deleteAllRecordCalls() + } + let cancelAction = UIAlertAction(title: TUICallKitLocalize(key: "TUICallKit.Recents.clear.cancel"), style: .cancel) + alertController.addAction(clearAction) + alertController.addAction(cancelAction) + present(alertController, animated: true, completion: nil) + } + + @objc func editButtonClick(_ button: UIButton) { + recordCallsList.setEditing(true, animated: true) + setShowEditButton(false) + } + + @objc func doneButtonClick(_ button: UIButton) { + recordCallsList.setEditing(false, animated: true) + setShowEditButton(true) + } + + @objc func segmentSelectItem(_ sender: UISegmentedControl) { + var type: TUICallRecordCallsType = .all + + if sender.selectedSegmentIndex == 1 { + type = .missed + } + + viewModel.switchRecordCallsType(type) + } + + func setShowEditButton(_ isShow: Bool) { + editButton.isHidden = !isShow + clearButton.isHidden = isShow + doneButton.isHidden = isShow + } +} + +extension TUICallRecordCallsViewController: UITableViewDataSource, UITableViewDelegate { + func tableView(_ tableView: UITableView, canEditRowAt indexPath: IndexPath) -> Bool { + return true + } + + func tableView(_ tableView: UITableView, editingStyleForRowAt indexPath: IndexPath) -> UITableViewCell.EditingStyle { + return .delete + } + + @available(iOS 11.0, *) + func tableView(_ tableView: UITableView, trailingSwipeActionsConfigurationForRowAt indexPath: IndexPath) -> UISwipeActionsConfiguration? { + let deleteRowAction = UIContextualAction(style: .normal, + title: TUICallKitLocalize(key: "TUICallKit.Recents.delete")) + { [weak self] action, sourceView, completionHandler in + guard let self = self else { return } + self.viewModel.deleteRecordCall(indexPath) + } + deleteRowAction.backgroundColor = .red + let config = UISwipeActionsConfiguration(actions: [deleteRowAction]) + config.performsFirstActionWithFullSwipe = false + self.setShowEditButton(false) + return config + } + + func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat { + return 64.0 + } + + func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { + return viewModel.dataSource.value.count + } + + func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { + guard let cell = tableView.dequeueReusableCell(withIdentifier: NSStringFromClass(TUICallRecordCallsCell.self), + for: indexPath) as? TUICallRecordCallsCell else { return UITableViewCell() } + cell.moreBtnClickedHandler = { [weak self] in + guard let self = self else { return } + guard let navigationController = self.navigationController else { return } + self.viewModel.jumpUserInfoController(indexPath: indexPath, navigationController: navigationController) + } + cell.configViewModel(viewModel.dataSource.value[indexPath.row]) + return cell + } + + func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { + viewModel.repeatCall(indexPath) + } +} diff --git a/iOS/TUIKit/TUICallKit/TUICallKit-Swift/View/Component/SwitchAudioView.swift b/iOS/TUIKit/TUICallKit/TUICallKit-Swift/View/Component/SwitchAudioView.swift index 6fff1389d..bbcd25d15 100644 --- a/iOS/TUIKit/TUICallKit/TUICallKit-Swift/View/Component/SwitchAudioView.swift +++ b/iOS/TUIKit/TUICallKit/TUICallKit-Swift/View/Component/SwitchAudioView.swift @@ -12,9 +12,9 @@ class SwitchAudioView: UIView { let viewModel = SwitchAudioViewModel() lazy var switchToAudioBtn: BaseControlButton = { weak var weakSelf = self - let switchToAudioBtn = BaseControlButton.create(frame: CGRectZero, + let switchToAudioBtn = BaseControlButton.create(frame: CGRect.zero, title: TUICallKitLocalize(key: "Demo.TRTC.Calling.switchtoaudio") ?? "", - imageSize: CGSizeMake(28,18)) { sender in + imageSize: CGSize(width: 28,height: 18)) { sender in weakSelf?.switchToAudioTouchAudio(sender: sender) } if let image = TUICallKitCommon.getBundleImage(name: "switch2audio") { diff --git a/iOS/TUIKit/TUICallKit/TUICallKit-Swift/View/Component/TimerView.swift b/iOS/TUIKit/TUICallKit/TUICallKit-Swift/View/Component/TimerView.swift index e2ed63aaa..ec7cac03c 100644 --- a/iOS/TUIKit/TUICallKit/TUICallKit-Swift/View/Component/TimerView.swift +++ b/iOS/TUIKit/TUICallKit/TUICallKit-Swift/View/Component/TimerView.swift @@ -15,7 +15,7 @@ class TimerView: UIView { let mediaTypeObserver = Observer() lazy var timerLabel: UILabel = { - let timerLabel = UILabel(frame: CGRectZero) + let timerLabel = UILabel(frame: CGRect.zero) timerLabel.font = UIFont.boldSystemFont(ofSize: 14.0) timerLabel.backgroundColor = UIColor.clear timerLabel.textAlignment = .center diff --git a/iOS/TUIKit/TUICallKit/TUICallKit-Swift/View/Component/UserInfoView/Group/GroupCallerUserInfoView.swift b/iOS/TUIKit/TUICallKit/TUICallKit-Swift/View/Component/UserInfoView/Group/GroupCallerUserInfoView.swift index 11a309fb0..f92fe8c25 100644 --- a/iOS/TUIKit/TUICallKit/TUICallKit-Swift/View/Component/UserInfoView/Group/GroupCallerUserInfoView.swift +++ b/iOS/TUIKit/TUICallKit/TUICallKit-Swift/View/Component/UserInfoView/Group/GroupCallerUserInfoView.swift @@ -11,7 +11,7 @@ class GroupCallerUserInfoView: UIView { let viewModel = GroupCallerUserInfoViewModel() let remoteUserListObserver = Observer() let userHeadImageView: UIImageView = { - let userHeadImageView = UIImageView(frame: CGRectZero) + let userHeadImageView = UIImageView(frame: CGRect.zero) userHeadImageView.layer.masksToBounds = true userHeadImageView.layer.cornerRadius = 5.0 if let image = TUICallKitCommon.getBundleImage(name: "userIcon") { @@ -21,7 +21,7 @@ class GroupCallerUserInfoView: UIView { }() let userNameLabel: UILabel = { - let userNameLabel = UILabel(frame: CGRectZero) + let userNameLabel = UILabel(frame: CGRect.zero) userNameLabel.textColor = UIColor.t_colorWithHexString(color: "#242424") userNameLabel.font = UIFont.boldSystemFont(ofSize: 24.0) userNameLabel.backgroundColor = UIColor.clear @@ -30,7 +30,7 @@ class GroupCallerUserInfoView: UIView { }() let waitingInviteLabel: UILabel = { - let waitingInviteLabel = UILabel(frame: CGRectZero) + let waitingInviteLabel = UILabel(frame: CGRect.zero) waitingInviteLabel.textColor = UIColor.t_colorWithHexString(color: "#242424") waitingInviteLabel.font = UIFont.boldSystemFont(ofSize: 14.0) waitingInviteLabel.backgroundColor = UIColor.clear @@ -92,10 +92,6 @@ class GroupCallerUserInfoView: UIView { // MARK: Register TUICallState Observer && Update UI func registerObserveState() { - remmoteUserListChanged() - } - - func remmoteUserListChanged() { viewModel.remoteUserList.addObserver(remoteUserListObserver, closure: { [weak self] newValue, _ in guard let self = self else { return } self.setUserImageAndName() diff --git a/iOS/TUIKit/TUICallKit/TUICallKit-Swift/View/Component/UserInfoView/Group/InviteeAvatarCell.swift b/iOS/TUIKit/TUICallKit/TUICallKit-Swift/View/Component/UserInfoView/Group/InviteeAvatarCell.swift index d7a5ac2fa..1ff8f3d5f 100644 --- a/iOS/TUIKit/TUICallKit/TUICallKit-Swift/View/Component/UserInfoView/Group/InviteeAvatarCell.swift +++ b/iOS/TUIKit/TUICallKit/TUICallKit-Swift/View/Component/UserInfoView/Group/InviteeAvatarCell.swift @@ -11,7 +11,7 @@ class InviteeAvatarCell: UICollectionViewCell { private var user: User = User() private let userIcon = { - let imageView = UIImageView(frame: CGRectZero) + let imageView = UIImageView(frame: CGRect.zero) imageView.contentMode = .scaleAspectFill if let image = TUICallKitCommon.getBundleImage(name: "userIcon") { imageView.image = image diff --git a/iOS/TUIKit/TUICallKit/TUICallKit-Swift/View/Component/UserInfoView/Group/InviteeAvatarListView.swift b/iOS/TUIKit/TUICallKit/TUICallKit-Swift/View/Component/UserInfoView/Group/InviteeAvatarListView.swift index eb6a96a8e..66d535cf7 100644 --- a/iOS/TUIKit/TUICallKit/TUICallKit-Swift/View/Component/UserInfoView/Group/InviteeAvatarListView.swift +++ b/iOS/TUIKit/TUICallKit/TUICallKit-Swift/View/Component/UserInfoView/Group/InviteeAvatarListView.swift @@ -18,7 +18,7 @@ class InviteeAvatarListView: UIView, UICollectionViewDelegate, UICollectionViewD let flowLayout = UICollectionViewFlowLayout() flowLayout.minimumLineSpacing = 0 flowLayout.minimumInteritemSpacing = 0 - let calleeCollectionView = UICollectionView(frame: CGRectZero, collectionViewLayout: flowLayout) + let calleeCollectionView = UICollectionView(frame: CGRect.zero, collectionViewLayout: flowLayout) calleeCollectionView.delegate = self calleeCollectionView.dataSource = self calleeCollectionView.showsVerticalScrollIndicator = false diff --git a/iOS/TUIKit/TUICallKit/TUICallKit-Swift/View/Component/UserInfoView/Single/AudioCallUserInfoView.swift b/iOS/TUIKit/TUICallKit/TUICallKit-Swift/View/Component/UserInfoView/Single/AudioCallUserInfoView.swift index 9c5ffcdaf..65eb0a491 100644 --- a/iOS/TUIKit/TUICallKit/TUICallKit-Swift/View/Component/UserInfoView/Single/AudioCallUserInfoView.swift +++ b/iOS/TUIKit/TUICallKit/TUICallKit-Swift/View/Component/UserInfoView/Single/AudioCallUserInfoView.swift @@ -13,7 +13,7 @@ class AudioCallUserInfoView: UIView { let selfCallStatusObserver = Observer() let remoteUserListObserver = Observer() let userHeadImageView: UIImageView = { - let userHeadImageView = UIImageView(frame: CGRectZero) + let userHeadImageView = UIImageView(frame: CGRect.zero) userHeadImageView.layer.masksToBounds = true userHeadImageView.layer.cornerRadius = 5.0 if let image = TUICallKitCommon.getBundleImage(name: "userIcon") { @@ -23,7 +23,7 @@ class AudioCallUserInfoView: UIView { }() let userNameLabel: UILabel = { - let userNameLabel = UILabel(frame: CGRectZero) + let userNameLabel = UILabel(frame: CGRect.zero) userNameLabel.textColor = UIColor.t_colorWithHexString(color: "#242424") userNameLabel.font = UIFont.boldSystemFont(ofSize: 24.0) userNameLabel.backgroundColor = UIColor.clear @@ -32,7 +32,7 @@ class AudioCallUserInfoView: UIView { }() let waitingInviteLabel: UILabel = { - let waitingInviteLabel = UILabel(frame: CGRectZero) + let waitingInviteLabel = UILabel(frame: CGRect.zero) waitingInviteLabel.textColor = UIColor.t_colorWithHexString(color: "#242424") waitingInviteLabel.font = UIFont.boldSystemFont(ofSize: 14.0) waitingInviteLabel.backgroundColor = UIColor.clear diff --git a/iOS/TUIKit/TUICallKit/TUICallKit-Swift/View/Component/UserInfoView/Single/VideoCallUserInfoView.swift b/iOS/TUIKit/TUICallKit/TUICallKit-Swift/View/Component/UserInfoView/Single/VideoCallUserInfoView.swift index 8d7b3f076..3a632579d 100644 --- a/iOS/TUIKit/TUICallKit/TUICallKit-Swift/View/Component/UserInfoView/Single/VideoCallUserInfoView.swift +++ b/iOS/TUIKit/TUICallKit/TUICallKit-Swift/View/Component/UserInfoView/Single/VideoCallUserInfoView.swift @@ -13,7 +13,7 @@ class VideoCallUserInfoView: UIView { let selfCallStatusObserver = Observer() let remoteUserListObserver = Observer() let userHeadImageView: UIImageView = { - let userHeadImageView = UIImageView(frame: CGRectZero) + let userHeadImageView = UIImageView(frame: CGRect.zero) userHeadImageView.layer.masksToBounds = true userHeadImageView.layer.cornerRadius = 5.0 if let image = TUICallKitCommon.getBundleImage(name: "userIcon") { @@ -23,7 +23,7 @@ class VideoCallUserInfoView: UIView { }() let userNameLabel: UILabel = { - let userNameLabel = UILabel(frame: CGRectZero) + let userNameLabel = UILabel(frame: CGRect.zero) userNameLabel.textColor = UIColor.t_colorWithHexString(color: "#F2F2F2") userNameLabel.font = UIFont.boldSystemFont(ofSize: 24.0) userNameLabel.backgroundColor = UIColor.clear @@ -32,7 +32,7 @@ class VideoCallUserInfoView: UIView { }() let waitingInviteLabel: UILabel = { - let waitingInviteLabel = UILabel(frame: CGRectZero) + let waitingInviteLabel = UILabel(frame: CGRect.zero) waitingInviteLabel.textColor = UIColor.t_colorWithHexString(color: "#F2F2F2") waitingInviteLabel.font = UIFont.boldSystemFont(ofSize: 14.0) waitingInviteLabel.backgroundColor = UIColor.clear @@ -43,6 +43,7 @@ class VideoCallUserInfoView: UIView { override init(frame: CGRect) { super.init(frame: frame) updateWaitingText() + setUserImageAndName() registerObserveState() } @@ -73,18 +74,19 @@ class VideoCallUserInfoView: UIView { func activateConstraints() { self.userHeadImageView.snp.makeConstraints { make in - make.top.right.equalTo(self) + make.top.equalTo(self) + make.trailing.equalTo(self) make.size.equalTo(CGSize(width: 100, height: 100)) } self.userNameLabel.snp.makeConstraints { make in make.top.equalTo(userHeadImageView.snp.top).offset(20) - make.right.equalTo(userHeadImageView.snp.left).offset(-20) + make.trailing.equalTo(userHeadImageView.snp.leading).offset(-20) } self.waitingInviteLabel.snp.makeConstraints { make in make.top.equalTo(userHeadImageView.snp.top).offset(60) - make.right.equalTo(userHeadImageView.snp.left).offset(-20) + make.trailing.equalTo(userHeadImageView.snp.leading).offset(-20) } } diff --git a/iOS/TUIKit/TUICallKit/TUICallKit-Swift/View/Component/VideoLayout/GroupCallVideoCell.swift b/iOS/TUIKit/TUICallKit/TUICallKit-Swift/View/Component/VideoLayout/GroupCallVideoCell.swift index 8dc00c5c3..656f29fe1 100644 --- a/iOS/TUIKit/TUICallKit/TUICallKit-Swift/View/Component/VideoLayout/GroupCallVideoCell.swift +++ b/iOS/TUIKit/TUICallKit/TUICallKit-Swift/View/Component/VideoLayout/GroupCallVideoCell.swift @@ -18,22 +18,22 @@ class GroupCallVideoCell: UICollectionViewCell { let isCameraOpenObserver = Observer() let remotePlayoutVolumeObserver = Observer() let selfPlayoutVolumeObserver = Observer() - + private var viewModel = GroupCallVideoCellViewModel(remote: User()) private var user: User = User() private var renderView = VideoView() - + private let titleLabel = { - let titleLabel = UILabel(frame: CGRectZero) + let titleLabel = UILabel(frame: CGRect.zero) titleLabel.textColor = UIColor.t_colorWithHexString(color: "FFFFFF") titleLabel.font = UIFont.systemFont(ofSize: 12) - titleLabel.textAlignment = .left + titleLabel.textAlignment = TUICoreDefineConvert.getIsRTL() ? .right : .left return titleLabel }() - + private let loadingImageView = { - let imageView = UIImageView(frame: CGRectZero) + let imageView = UIImageView(frame: CGRect.zero) imageView.contentMode = .scaleAspectFill guard let filePath = TUICallKitCommon.getTUICallKitBundle()?.path(forResource: "loading", ofType: "gif") else { return imageView } guard let data = NSData(contentsOfFile: filePath) as? Data else { return imageView } @@ -42,13 +42,13 @@ class GroupCallVideoCell: UICollectionViewCell { }() private let avatarImageView = { - let imageView = UIImageView(frame: CGRectZero) + let imageView = UIImageView(frame: CGRect.zero) imageView.contentMode = .scaleAspectFill return imageView }() private let micImageView = { - let imageView = UIImageView(frame: CGRectZero) + let imageView = UIImageView(frame: CGRect.zero) imageView.contentMode = .scaleAspectFill if let image = TUICallKitCommon.getBundleImage(name: "ic_mute") { imageView.image = image @@ -96,7 +96,7 @@ class GroupCallVideoCell: UICollectionViewCell { activateConstraints() isViewReady = true } - + func constructViewHierarchy() { contentView.addSubview(renderView) contentView.addSubview(avatarImageView) @@ -104,7 +104,7 @@ class GroupCallVideoCell: UICollectionViewCell { contentView.addSubview(titleLabel) contentView.addSubview(micImageView) } - + func activateConstraints() { renderView.snp.makeConstraints { make in make.edges.equalTo(self.contentView) @@ -119,7 +119,7 @@ class GroupCallVideoCell: UICollectionViewCell { } titleLabel.snp.makeConstraints { make in - make.left.equalTo(self.contentView).offset(20) + make.leading.equalTo(self.contentView).offset(20) make.bottom.equalTo(self.contentView).offset(-5) make.width.equalTo(self.contentView) make.height.equalTo(20) @@ -127,11 +127,11 @@ class GroupCallVideoCell: UICollectionViewCell { micImageView.snp.makeConstraints { make in make.size.equalTo(CGSize(width: 20, height: 20)) - make.right.equalTo(self.contentView).offset(-20) + make.trailing.equalTo(self.contentView).offset(-20) make.bottom.equalTo(self.contentView).offset(-5) } } - + func initCell(user: User) { self.user = user viewModel = GroupCallVideoCellViewModel(remote: user) @@ -146,7 +146,7 @@ class GroupCallVideoCell: UICollectionViewCell { isCameraOpenChanged() volumChanged() } - + func callStatusChanged() { if viewModel.isSelf { viewModel.selfUserStatus.addObserver(selfUserStatusObserver, closure: { [weak self] newValue, _ in @@ -203,9 +203,9 @@ class GroupCallVideoCell: UICollectionViewCell { //MARK: Update UI func initWaitingUI() { - titleLabel.text = viewModel.remoteUser.id.value + titleLabel.text = viewModel.remoteUser.nickname.value setUserAvatar() - + if viewModel.isSelf { initSelfUserUI() } else { @@ -219,13 +219,13 @@ class GroupCallVideoCell: UICollectionViewCell { if viewModel.mediaType.value == .video { if viewModel.selfUserStatus.value == .waiting { if !VideoFactory.instance.isExistVideoView(videoView: renderView) { - renderView = VideoFactory.instance.createVideoView(userId: viewModel.selfUser.value.id.value, frame: CGRectZero) + renderView = VideoFactory.instance.createVideoView(userId: viewModel.selfUser.value.id.value, frame: CGRect.zero) renderView.isHidden = false viewModel.openCamera(videoView: renderView) } } else if viewModel.selfUserStatus.value == .accept { if !VideoFactory.instance.isExistVideoView(videoView: renderView) { - renderView = VideoFactory.instance.createVideoView(userId: viewModel.selfUser.value.id.value, frame: CGRectZero) + renderView = VideoFactory.instance.createVideoView(userId: viewModel.selfUser.value.id.value, frame: CGRect.zero) viewModel.openCamera(videoView: renderView) } if viewModel.isCameraOpen.value == true { @@ -240,7 +240,7 @@ class GroupCallVideoCell: UICollectionViewCell { avatarImageView.isHidden = false } } - + func updateSelfUsertUI() { hiddenAllSubView() @@ -256,8 +256,8 @@ class GroupCallVideoCell: UICollectionViewCell { avatarImageView.isHidden = false } } - - + + func updateRemoteUserCellUI() { hiddenAllSubView() @@ -284,7 +284,7 @@ class GroupCallVideoCell: UICollectionViewCell { } } } - + func hiddenAllSubView() { renderView.isHidden = true titleLabel.isHidden = true diff --git a/iOS/TUIKit/TUICallKit/TUICallKit-Swift/View/Component/VideoLayout/GroupCallVideoLayout.swift b/iOS/TUIKit/TUICallKit/TUICallKit-Swift/View/Component/VideoLayout/GroupCallVideoLayout.swift index 96071fdc1..09ca0e486 100644 --- a/iOS/TUIKit/TUICallKit/TUICallKit-Swift/View/Component/VideoLayout/GroupCallVideoLayout.swift +++ b/iOS/TUIKit/TUICallKit/TUICallKit-Swift/View/Component/VideoLayout/GroupCallVideoLayout.swift @@ -15,7 +15,7 @@ class GroupCallVideoLayout: UIView, UICollectionViewDelegate, UICollectionViewDa let selfCallStatusObserver = Observer() lazy var colleeCollectionView = { let flowLayout = UICollectionViewFlowLayout() - let colleeCollectionView = UICollectionView(frame: CGRectZero, collectionViewLayout: flowLayout) + let colleeCollectionView = UICollectionView(frame: CGRect.zero, collectionViewLayout: flowLayout) colleeCollectionView.delegate = self colleeCollectionView.dataSource = self colleeCollectionView.showsVerticalScrollIndicator = false @@ -61,7 +61,7 @@ class GroupCallVideoLayout: UIView, UICollectionViewDelegate, UICollectionViewDa func activateConstraints() { colleeCollectionView.snp.makeConstraints { make in make.centerX.equalTo(self) - make.top.equalTo(snp.top).offset(60) + make.top.equalToSuperview().offset(StatusBar_Height + kFloatWindowButtonSize.height) make.width.height.equalTo(Screen_Width - 10) } } diff --git a/iOS/TUIKit/TUICallKit/TUICallKit-Swift/View/Component/VideoLayout/SingleCallVideoLayout.swift b/iOS/TUIKit/TUICallKit/TUICallKit-Swift/View/Component/VideoLayout/SingleCallVideoLayout.swift index d9327ed6d..ec33bdc1b 100644 --- a/iOS/TUIKit/TUICallKit/TUICallKit-Swift/View/Component/VideoLayout/SingleCallVideoLayout.swift +++ b/iOS/TUIKit/TUICallKit/TUICallKit-Swift/View/Component/VideoLayout/SingleCallVideoLayout.swift @@ -8,8 +8,10 @@ import Foundation private let kCallKitSingleSmallVideoViewWidth = 100.0 -private let kCallKitSingleSmallVideoViewFrame = CGRectMake(ScreenSize.width - kCallKitSingleSmallVideoViewWidth - 18, -StatusBar_Height + 20, kCallKitSingleSmallVideoViewWidth, kCallKitSingleSmallVideoViewWidth / 9.0 * 16.0) +private let kCallKitSingleSmallVideoViewFrame = CGRect(x: ScreenSize.width - kCallKitSingleSmallVideoViewWidth - 18, + y: StatusBar_Height + 20, + width: kCallKitSingleSmallVideoViewWidth, + height: kCallKitSingleSmallVideoViewWidth / 9.0 * 16.0) private let kCallKitSingleLargeVideoViewFrame = CGRect(x: 0, y: 0, width: ScreenSize.width, height: ScreenSize.height) class SingleCallVideoLayout: UIView { @@ -17,21 +19,21 @@ class SingleCallVideoLayout: UIView { let viewModel = SingleCallVideoLayoutModel() let selfCallStatusObserver = Observer() let isCameraOpenObserver = Observer() - var isLocalPreViewLargr: Bool = true - + var isLocalPreViewLarge: Bool = true + var localPreView: VideoView { if VideoFactory.instance.viewMap[viewModel.selfUser.value.id.value] == nil { - let _ = VideoFactory.instance.createVideoView(userId: viewModel.selfUser.value.id.value, frame: CGRectZero) + let _ = VideoFactory.instance.createVideoView(userId: viewModel.selfUser.value.id.value, frame: CGRect.zero) } - return VideoFactory.instance.viewMap[viewModel.selfUser.value.id.value]?.videoView ?? VideoView(frame: CGRectZero) + return VideoFactory.instance.viewMap[viewModel.selfUser.value.id.value]?.videoView ?? VideoView(frame: CGRect.zero) } var remotePreView: VideoView { - guard let remoteUser = self.viewModel.remoteUserList.value.first else { return VideoView(frame: CGRectZero) } + guard let remoteUser = self.viewModel.remoteUserList.value.first else { return VideoView(frame: CGRect.zero) } if VideoFactory.instance.viewMap[remoteUser.id.value] == nil { - let _ = VideoFactory.instance.createVideoView(userId: remoteUser.id.value, frame: CGRectZero) + let _ = VideoFactory.instance.createVideoView(userId: remoteUser.id.value, frame: CGRect.zero) } - return VideoFactory.instance.viewMap[remoteUser.id.value]?.videoView ?? VideoView(frame: CGRectZero) + return VideoFactory.instance.viewMap[remoteUser.id.value]?.videoView ?? VideoView(frame: CGRect.zero) } var remoteUser: User? @@ -57,7 +59,7 @@ class SingleCallVideoLayout: UIView { callStatusChanged() cameraStateChanged() } - + func callStatusChanged() { viewModel.selfCallStatus.addObserver(selfCallStatusObserver, closure: { [weak self] newValue, _ in guard let self = self else { return } @@ -78,7 +80,7 @@ class SingleCallVideoLayout: UIView { func cameraStateChanged() { viewModel.isCameraOpen.addObserver(isCameraOpenObserver) { [weak self] newValue, _ in guard let self = self else { return } - if newValue == false && self.isLocalPreViewLargr == false { + if newValue == false && self.isLocalPreViewLarge == false { self.localPreView.isHidden = true } else { self.localPreView.isHidden = false @@ -88,7 +90,7 @@ class SingleCallVideoLayout: UIView { //MARK: update UI func switchPreview() { - if isLocalPreViewLargr { + if isLocalPreViewLarge { UIView.animate(withDuration: 0.3) { self.localPreView.frame = kCallKitSingleSmallVideoViewFrame self.remotePreView.frame = kCallKitSingleLargeVideoViewFrame @@ -98,24 +100,24 @@ class SingleCallVideoLayout: UIView { self.localPreView.isUserInteractionEnabled = true self.remotePreView.isUserInteractionEnabled = false } - isLocalPreViewLargr = false + isLocalPreViewLarge = false } else { UIView.animate(withDuration: 0.3) { self.localPreView.frame = kCallKitSingleLargeVideoViewFrame self.remotePreView.frame = kCallKitSingleSmallVideoViewFrame } completion: { finished in self.sendSubviewToBack(self.localPreView) - + self.localPreView.isUserInteractionEnabled = false self.remotePreView.isUserInteractionEnabled = true } - isLocalPreViewLargr = true + isLocalPreViewLarge = true } } - + func setBeginAcceptPreview() { remotePreView.isHidden = false - + UIView.animate(withDuration: 0.3) { self.localPreView.frame = kCallKitSingleSmallVideoViewFrame self.remotePreView.frame = kCallKitSingleLargeVideoViewFrame @@ -125,7 +127,7 @@ class SingleCallVideoLayout: UIView { self.localPreView.isUserInteractionEnabled = true self.remotePreView.isUserInteractionEnabled = false } - isLocalPreViewLargr = false + isLocalPreViewLarge = false } func setEndPreview() { @@ -133,7 +135,7 @@ class SingleCallVideoLayout: UIView { self.viewModel.stopRemoteView(user: self.remoteUser ?? User()) self.remoteUser = nil - isLocalPreViewLargr = true + isLocalPreViewLarge = true } func initPreView() { @@ -189,7 +191,7 @@ extension SingleCallVideoLayout: VideoViewDelegate { if tapGesture.view?.frame.size.width == CGFloat(kCallKitSingleSmallVideoViewWidth) { switchPreview() } - if viewModel.isCameraOpen.value == false && self.isLocalPreViewLargr == false { + if viewModel.isCameraOpen.value == false && self.isLocalPreViewLarge == false { self.localPreView.isHidden = true } else { self.localPreView.isHidden = false @@ -214,7 +216,7 @@ extension SingleCallVideoLayout: VideoViewDelegate { newCenterY > self.bounds.size.height - (smallView?.bounds.size.height ?? 0.0) / 2.0 { return } - + UIView.animate(withDuration: 0.1) { smallView?.center = CGPoint(x: newCenterX, y: newCenterY) } diff --git a/iOS/TUIKit/TUICallKit/TUICallKit-Swift/View/Component/VideoLayout/VideoFactory.swift b/iOS/TUIKit/TUICallKit/TUICallKit-Swift/View/Component/VideoLayout/VideoFactory.swift index ba6379f32..54e4cefd7 100644 --- a/iOS/TUIKit/TUICallKit/TUICallKit-Swift/View/Component/VideoLayout/VideoFactory.swift +++ b/iOS/TUIKit/TUICallKit/TUICallKit-Swift/View/Component/VideoLayout/VideoFactory.swift @@ -40,5 +40,5 @@ class VideoFactory { class UserVideoEntity { var userId: String = "" var user: User = User() - var videoView: VideoView = VideoView(frame: CGRectZero) + var videoView: VideoView = VideoView(frame: CGRect.zero) } diff --git a/iOS/TUIKit/TUICallKit/TUICallKit-Swift/View/Root/GroupCallView.swift b/iOS/TUIKit/TUICallKit/TUICallKit-Swift/View/Root/GroupCallView.swift index f14296139..f6f413a44 100644 --- a/iOS/TUIKit/TUICallKit/TUICallKit-Swift/View/Root/GroupCallView.swift +++ b/iOS/TUIKit/TUICallKit/TUICallKit-Swift/View/Root/GroupCallView.swift @@ -13,48 +13,48 @@ class GroupCallView: UIView { private var isViewReady: Bool = false let layoutView = { - return GroupCallVideoLayout(frame: CGRectZero) + return GroupCallVideoLayout(frame: CGRect.zero) }() let floatingWindowBtn = { - return FloatingWindowButton(frame: CGRectZero) + return FloatingWindowButton(frame: CGRect.zero) }() let inviteUserBUtton = { - return InviteUserButton(frame: CGRectZero) + return InviteUserButton(frame: CGRect.zero) }() let inviterUserInfoView = { - return GroupCallerUserInfoView(frame: CGRectZero) + return GroupCallerUserInfoView(frame: CGRect.zero) }() let inviteeAvatarListView = { - return InviteeAvatarListView(frame: CGRectZero) + return InviteeAvatarListView(frame: CGRect.zero) }() let waitingHintView = { - return CallWaitingHintView(frame: CGRectZero) + return CallWaitingHintView(frame: CGRect.zero) }() let audioFunctionView = { - return AudioCallerWaitingAndAcceptedView(frame: CGRectZero) + return AudioCallerWaitingAndAcceptedView(frame: CGRect.zero) }() let videoFunctionView = { - return VideoCallerAndCalleeAcceptedView(frame: CGRectZero) + return VideoCallerAndCalleeAcceptedView(frame: CGRect.zero) }() let inviteeWaitFunctionView = { - return AudioAndVideoCalleeWaitingView(frame: CGRectZero) + return AudioAndVideoCalleeWaitingView(frame: CGRect.zero) }() let timerView: TimerView = { - return TimerView(frame: CGRectZero) + return TimerView(frame: CGRect.zero) }() override init(frame: CGRect) { super.init(frame: frame) - self.frame = CGRectMake(0, 0, Screen_Width, Screen_Height) + self.frame = CGRect(x: 0, y: 0, width: Screen_Width, height: Screen_Height) createGroupCallView() registerObserveState() } @@ -95,26 +95,28 @@ class GroupCallView: UIView { } func activateConstraints() { + let isAuidoCall: Bool = TUICallState.instance.mediaType.value == .audio ? true : false + layoutView.snp.makeConstraints { make in make.size.equalTo(self) } floatingWindowBtn.snp.makeConstraints { make in - make.size.equalTo(CGSize(width: 30, height: 30)) - make.top.equalTo(snp.top).offset(20) - make.left.equalTo(snp.left).offset(20) + make.size.equalTo(kFloatWindowButtonSize) + make.top.equalToSuperview().offset(StatusBar_Height) + make.leading.equalTo(snp.leading).offset(20) } inviteUserBUtton.snp.makeConstraints { make in - make.size.equalTo(CGSize(width: 30, height: 30)) - make.top.equalTo(snp.top).offset(20) - make.right.equalTo(snp.right).offset(-20) + make.size.equalTo(kInviteUserButtonSize) + make.top.equalToSuperview().offset(StatusBar_Height) + make.trailing.equalTo(snp.trailing).offset(-20) } inviterUserInfoView.snp.makeConstraints { make in make.top.equalTo(self).offset(StatusBar_Height + 75.0) - make.left.equalTo(self).offset(20) - make.right.equalTo(self).offset(-20) + make.leading.equalTo(self).offset(20) + make.trailing.equalTo(self).offset(-20) make.height.equalTo(180) } @@ -150,7 +152,7 @@ class GroupCallView: UIView { make.centerX.equalTo(self) make.height.equalTo(20) make.width.equalTo(self) - make.bottom.equalTo(self.videoFunctionView.snp.top).offset(10) + make.bottom.equalTo(isAuidoCall ? self.audioFunctionView.snp.top : self.videoFunctionView.snp.top).offset(-10) } waitingHintView.snp.makeConstraints { make in diff --git a/iOS/TUIKit/TUICallKit/TUICallKit-Swift/View/Root/SingleCallView.swift b/iOS/TUIKit/TUICallKit/TUICallKit-Swift/View/Root/SingleCallView.swift index 41b2b7a1c..850fe9673 100644 --- a/iOS/TUIKit/TUICallKit/TUICallKit-Swift/View/Root/SingleCallView.swift +++ b/iOS/TUIKit/TUICallKit/TUICallKit-Swift/View/Root/SingleCallView.swift @@ -14,49 +14,49 @@ class SingleCallView: UIView { private var isViewReady: Bool = false let userInfoAudioView = { - return AudioCallUserInfoView(frame: CGRectZero) + return AudioCallUserInfoView(frame: CGRect.zero) }() let userInfoVideoView = { - return VideoCallUserInfoView(frame: CGRectZero) + return VideoCallUserInfoView(frame: CGRect.zero) }() let audioFunctionView = { - return AudioCallerWaitingAndAcceptedView(frame: CGRectZero) + return AudioCallerWaitingAndAcceptedView(frame: CGRect.zero) }() let videoFunctionView = { - return VideoCallerAndCalleeAcceptedView(frame: CGRectZero) + return VideoCallerAndCalleeAcceptedView(frame: CGRect.zero) }() let videoInviteFunctionView = { - return VideoCallerWaitingView(frame: CGRectZero) + return VideoCallerWaitingView(frame: CGRect.zero) }() let inviteeWaitFunctionView = { - return AudioAndVideoCalleeWaitingView(frame: CGRectZero) + return AudioAndVideoCalleeWaitingView(frame: CGRect.zero) }() let renderBackgroundView = { - return SingleCallVideoLayout(frame: CGRectZero) + return SingleCallVideoLayout(frame: CGRect.zero) }() let switchToAudioView = { - return SwitchAudioView(frame: CGRectZero) + return SwitchAudioView(frame: CGRect.zero) }() let timerView = { - return TimerView(frame: CGRectZero) + return TimerView(frame: CGRect.zero) }() let floatingWindowBtn = { - return FloatingWindowButton(frame: CGRectZero) + return FloatingWindowButton(frame: CGRect.zero) }() override init(frame: CGRect) { super.init(frame: frame) let screenSize = UIScreen.main.bounds.size - self.frame = CGRectMake(0, 0, screenSize.width, screenSize.height) + self.frame = CGRect(x: 0, y: 0, width: screenSize.width, height: screenSize.height) backgroundColor = UIColor.t_colorWithHexString(color: "#F2F2F2") createView() @@ -100,6 +100,8 @@ class SingleCallView: UIView { } func activateConstraints() { + let isAuidoCall: Bool = TUICallState.instance.mediaType.value == .audio ? true : false + renderBackgroundView.snp.makeConstraints { make in make.size.equalTo(self) } @@ -113,8 +115,8 @@ class SingleCallView: UIView { userInfoVideoView.snp.makeConstraints { make in make.top.equalTo(self).offset(StatusBar_Height + 20.0) - make.left.equalTo(self).offset(20) - make.right.equalTo(self).offset(-20) + make.leading.equalTo(self).offset(20) + make.trailing.equalTo(self).offset(-20) } audioFunctionView.snp.makeConstraints({ make in @@ -158,13 +160,13 @@ class SingleCallView: UIView { make.centerX.equalTo(self) make.height.equalTo(30) make.width.equalTo(snp.width) - make.bottom.equalTo(self.switchToAudioView.snp.top).offset(-10) + make.bottom.equalTo(isAuidoCall ? self.audioFunctionView.snp.top : self.switchToAudioView.snp.top).offset(-10) } floatingWindowBtn.snp.makeConstraints { make in - make.size.equalTo(CGSize(width: 40, height: 40)) - make.top.equalTo(snp.top).offset(30) - make.left.equalTo(snp.left).offset(30) + make.size.equalTo(kFloatWindowButtonSize) + make.top.equalToSuperview().offset(StatusBar_Height + 10) + make.leading.equalToSuperview().offset(20) } } diff --git a/iOS/TUIKit/TUICallKit/TUICallKit-Swift/View/WindowManager.swift b/iOS/TUIKit/TUICallKit/TUICallKit-Swift/View/WindowManager.swift index 58f39920b..9b66c588f 100644 --- a/iOS/TUIKit/TUICallKit/TUICallKit-Swift/View/WindowManager.swift +++ b/iOS/TUIKit/TUICallKit/TUICallKit-Swift/View/WindowManager.swift @@ -8,16 +8,25 @@ import Foundation class WindowManager: NSObject, FloatingWindowViewDelegate { + + enum FloatWindowCornerType { + case all + case left + case right + } static let instance = WindowManager() var isFloating = false let mediaTypeObserver = Observer() - let remoteUserListObserver = Observer() let callWindow = UIWindow() - let floatWindow = UIWindow() + let floatWindow: UIWindow = { + let view = UIWindow() + view.layer.masksToBounds = true + return view + }() var floatWindowBeganPoint: CGPoint? var floatWindowBeganOrigin: CGPoint? @@ -29,7 +38,6 @@ class WindowManager: NSObject, FloatingWindowViewDelegate { deinit { TUICallState.instance.mediaType.removeObserver(mediaTypeObserver) - TUICallState.instance.timeCount.removeObserver(mediaTypeObserver) } func showCallWindow() { @@ -46,15 +54,16 @@ class WindowManager: NSObject, FloatingWindowViewDelegate { func showFloatWindow() { closeCallWindow() - floatWindow.frame = getFloatWindowFrame() - floatWindow.backgroundColor = UIColor.t_colorWithHexString(color: "#F2F2F2") let floatViewController = FloatWindowViewController() floatViewController.delegate = self floatWindow.rootViewController = floatViewController + floatWindow.backgroundColor = UIColor.t_colorWithHexString(color: "#F2F2F2") floatWindow.isHidden = false + floatWindow.frame = getFloatWindowFrame() + updateFloatWindowFrame() + setFloatWindowCorner(.left) floatWindow.t_makeKeyAndVisible() isFloating = true - updateFloatWindowFrame() } func closeFloatWindow() { @@ -82,10 +91,10 @@ class WindowManager: NSObject, FloatingWindowViewDelegate { let originY = floatWindow.frame.origin.y if TUICallState.instance.scene.value == .single { if TUICallState.instance.mediaType.value == .audio { - let dstX = floatWindow.frame.origin.x < Screen_Width / 2.0 ? 0 : Screen_Width - kMicroAudioViewWidth + let dstX = floatWindow.frame.origin.x < (Screen_Width / 2.0) ? 0 : (Screen_Width - kMicroAudioViewWidth) floatWindow.frame = CGRect(x: dstX, y: originY, width: kMicroAudioViewWidth, height: kMicroAudioViewHeight) } else { - let dstX = floatWindow.frame.origin.x < Screen_Width / 2.0 ? 0 : Screen_Width - kMicroVideoViewWidth + let dstX = floatWindow.frame.origin.x < (Screen_Width / 2.0) ? 0 : (Screen_Width - kMicroVideoViewWidth) if TUICallState.instance.remoteUserList.value.first != nil { if TUICallState.instance.remoteUserList.value[0].videoAvailable.value { floatWindow.frame = CGRect(x: dstX, y: originY, width: kMicroVideoViewWidth, height: kMicroVideoViewHeight) @@ -95,7 +104,7 @@ class WindowManager: NSObject, FloatingWindowViewDelegate { } } } else { - let dstX = floatWindow.frame.origin.x < Screen_Width / 2.0 ? 0 : Screen_Width - kMicroAudioViewWidth + let dstX = floatWindow.frame.origin.x < (Screen_Width / 2.0) ? 0 : (Screen_Width - kMicroAudioViewWidth) floatWindow.frame = CGRect(x: dstX, y: originY, width: kMicroAudioViewWidth, height: kMicroAudioViewHeight) } } @@ -103,7 +112,9 @@ class WindowManager: NSObject, FloatingWindowViewDelegate { func registerObserveState() { TUICallState.instance.mediaType.addObserver(mediaTypeObserver, closure: { [weak self] newValue, _ in guard let self = self else { return } - self.updateFloatWindowFrame() + if self.isFloating { + self.updateFloatWindowFrame() + } }) } @@ -135,11 +146,13 @@ class WindowManager: NSObject, FloatingWindowViewDelegate { dstY = Screen_Height - floatWindow.frame.size.height } - floatWindow.frame = CGRect(x: dstX, - y: dstY, - width: floatWindow.frame.size.width, - height: floatWindow.frame.size.height) + y: dstY, + width: floatWindow.frame.size.width, + height: floatWindow.frame.size.height) + + setFloatWindowCorner(.all) + break case.cancelled: break @@ -152,12 +165,40 @@ class WindowManager: NSObject, FloatingWindowViewDelegate { } floatWindow.frame = CGRect(x: dstX, y: floatWindow.frame.origin.y, - width: floatWindow.frame.size.width, - height: floatWindow.frame.size.height) + width: floatWindow.frame.size.width, + height: floatWindow.frame.size.height) + + if dstX == 0 { + setFloatWindowCorner(.right) + } else { + setFloatWindowCorner(.left) + } + break default: break } } + + func setFloatWindowCorner(_ type: FloatWindowCornerType) { + var roundingCorners: UIRectCorner + switch type { + case .all: + roundingCorners = [.allCorners] + break + case .right: + roundingCorners = [.topRight, .bottomRight] + break + case .left: + roundingCorners = [.topLeft, .bottomLeft] + break + } + + let maskLayer = CAShapeLayer() + let path = UIBezierPath(roundedRect: floatWindow.bounds, + byRoundingCorners: roundingCorners, + cornerRadii: CGSize(width: 10, height: 10)) + maskLayer.path = path.cgPath + floatWindow.layer.mask = maskLayer + } } - diff --git a/iOS/TUIKit/TUICallKit/TUICallKit-Swift/ViewModel/Component/InviteUser/SelectGroupMeberViewModel.swift b/iOS/TUIKit/TUICallKit/TUICallKit-Swift/ViewModel/Component/InviteUser/SelectGroupMemberViewModel.swift similarity index 69% rename from iOS/TUIKit/TUICallKit/TUICallKit-Swift/ViewModel/Component/InviteUser/SelectGroupMeberViewModel.swift rename to iOS/TUIKit/TUICallKit/TUICallKit-Swift/ViewModel/Component/InviteUser/SelectGroupMemberViewModel.swift index 8c59c4114..5455107f6 100644 --- a/iOS/TUIKit/TUICallKit/TUICallKit-Swift/ViewModel/Component/InviteUser/SelectGroupMeberViewModel.swift +++ b/iOS/TUIKit/TUICallKit/TUICallKit-Swift/ViewModel/Component/InviteUser/SelectGroupMemberViewModel.swift @@ -8,12 +8,12 @@ import Foundation import ImSDK_Plus -class SelectGroupMeberViewModel { +class SelectGroupMemberViewModel { var selfUser: Observable = Observable(User()) - var groupMerberList: Observable<[User]> = Observable([]) - var groupMerberState: [String: Bool] = [:] - var groupMerberStateOrigin: [String: Bool] = [:] - + var groupMemberList: Observable<[User]> = Observable([]) + var groupMemberState: [String: Bool] = [:] + var groupMemberStateOrigin: [String: Bool] = [:] + init() { updateUserState() } @@ -31,18 +31,18 @@ class SelectGroupMeberViewModel { continue } let user = User.convertUserFromImFullInfo(user: imUserInfo) - self.groupMerberList.value.append(user) - self.groupMerberState[user.id.value] = false - self.groupMerberStateOrigin[user.id.value] = false + self.groupMemberList.value.append(user) + self.groupMemberState[user.id.value] = false + self.groupMemberStateOrigin[user.id.value] = false } for user in TUICallState.instance.remoteUserList.value { - self.groupMerberState[user.id.value] = true - self.groupMerberStateOrigin[user.id.value] = true + self.groupMemberState[user.id.value] = true + self.groupMemberStateOrigin[user.id.value] = true } } fail: { code, message in - + } } } diff --git a/iOS/TUIKit/TUICallKit/TUICallKit-Swift/ViewModel/Component/InviteUserButtonViewModel.swift b/iOS/TUIKit/TUICallKit/TUICallKit-Swift/ViewModel/Component/InviteUserButtonViewModel.swift index 450828ccb..884f54b5c 100644 --- a/iOS/TUIKit/TUICallKit/TUICallKit-Swift/ViewModel/Component/InviteUserButtonViewModel.swift +++ b/iOS/TUIKit/TUICallKit/TUICallKit-Swift/ViewModel/Component/InviteUserButtonViewModel.swift @@ -34,7 +34,7 @@ class InviteUserButtonViewModel { } func inviteUser() { - let navigationController = UINavigationController(rootViewController: SelectGroupMeberViewController()) + let navigationController = UINavigationController(rootViewController: SelectGroupMemberViewController()) navigationController.modalPresentationStyle = .fullScreen navigationController.navigationBar.barTintColor = UIColor.t_colorWithHexString(color: "#F2F2F2") let keyWindow = TUICallKitCommon.getKeyWindow() diff --git a/iOS/TUIKit/TUICallKit/TUICallKit-Swift/ViewModel/Component/Recents/TUICallRecordCallsCellViewModel.swift b/iOS/TUIKit/TUICallKit/TUICallKit-Swift/ViewModel/Component/Recents/TUICallRecordCallsCellViewModel.swift new file mode 100644 index 000000000..e6b08516d --- /dev/null +++ b/iOS/TUIKit/TUICallKit/TUICallKit-Swift/ViewModel/Component/Recents/TUICallRecordCallsCellViewModel.swift @@ -0,0 +1,194 @@ +// +// TUICallRecordCallsCellViewModel.swift +// +// +// Created by vincepzhang on 2023/8/28. +// + +import Foundation +import UIKit +import TUICallEngine +import ImSDK_Plus +import TUICore + +class TUICallRecordCallsCellViewModel { + + var avatarImage: UIImage = UIImage() + var faceURL: Observable = Observable("") + + var titleLabelStr: Observable = Observable("") + var mediaTypeImageStr: String = "" + var resultLabelStr: String = "" + var timeLabelStr: String = "" + + var callRecord: TUICallRecords + + init(_ record: TUICallRecords) { + callRecord = record + + configAvatarImage(callRecord) + configResult(callRecord.result) + configMediaTypeImageName(callRecord.mediaType) + configTitle(callRecord) + configTime(callRecord) + } + + private func configAvatarImage(_ callRecord: TUICallRecords) { + if callRecord.scene == .group { + + var inviteList = callRecord.inviteList + inviteList.insert(callRecord.inviter, at: 0) + guard let inviteList = inviteList as? [String] else { return } + configGroupAvatarImage(inviteList) + + } else if callRecord.scene == .single { + configSingleAvatarImage(callRecord) + } else { + avatarImage = TUICoreDefineConvert.getDefaultGroupAvatarImage() + } + } + + private func configGroupAvatarImage(_ inviteList: [String]) { + if inviteList.isEmpty { + avatarImage = TUICoreDefineConvert.getDefaultGroupAvatarImage() + return + } + + let inviteStr = inviteList.joined(separator: "#") + + getCacheAvatarForInviteStr(inviteStr) { [weak self] avatar in + guard let self = self else { return } + if let avatar = avatar { + self.avatarImage = avatar + } else { + V2TIMManager.sharedInstance()?.getUsersInfo(inviteList, succ: { infoList in + var avatarsList = [String]() + + infoList?.forEach { userFullInfo in + if let faceURL = userFullInfo.faceURL, !faceURL.isEmpty { + avatarsList.append(faceURL) + } else { + avatarsList.append("http://placeholder") + } + } + TUIGroupAvatar.createGroupAvatar(avatarsList, finished: { [weak self] image in + guard let self = self else { return } + self.avatarImage = image + self.cacheGroupCallAvatar(image, inviteStr: inviteStr) + }) + }, fail: nil) + } + } + } + + private func configSingleAvatarImage(_ callRecord: TUICallRecords) { + avatarImage = TUICoreDefineConvert.getDefaultAvatarImage() + var useId = callRecord.inviter + + if callRecord.role == .call { + guard let firstInvite = callRecord.inviteList.first as? String else { return } + useId = firstInvite + } + + if !useId.isEmpty { + V2TIMManager.sharedInstance()?.getUsersInfo([useId], succ: { [weak self] infoList in + guard let self = self else { return } + if let userFullInfo = infoList?.first { + if let faceURL = userFullInfo.faceURL, !faceURL.isEmpty, faceURL.hasPrefix("http") { + self.faceURL.value = faceURL + } + } + }, fail: nil) + } + } + + private func configResult(_ callResultType: TUICallResultType) { + switch callResultType { + case .missed: + resultLabelStr = "Missed" + case .incoming: + resultLabelStr = "Incoming" + case .outgoing: + resultLabelStr = "Outgoing" + case .unknown: + break + @unknown default: + break + } + } + + private func configMediaTypeImageName(_ callMediaType: TUICallMediaType) { + if callMediaType == .audio { + mediaTypeImageStr = "ic_recents_audio" + } else if callMediaType == .video { + mediaTypeImageStr = "ic_recents_video" + } + } + + func configTitle(_ callRecord: TUICallRecords) { + titleLabelStr.value = "" + var allUsers: [String] = [] + + switch callRecord.scene { + case .single: + if callRecord.role == .call { + guard let inviteList = callRecord.inviteList as? [String] else { return } + allUsers = inviteList + } else if callRecord.role == .called { + let inviter = callRecord.inviter + allUsers.append(inviter) + } + case .group: + guard let inviteList = callRecord.inviteList as? [String] else { return } + allUsers = inviteList + allUsers.append(callRecord.inviter) + case .multi: + break + @unknown default: + break + } + + V2TIMManager.sharedInstance()?.getUsersInfo(allUsers, succ: { [weak self] infoList in + guard let self = self else { return } + guard let infoList = infoList else { return } + let titleArray = infoList.map { $0.nickName ?? $0.userID } + guard let titleArray = titleArray as? [String] else { return } + self.titleLabelStr.value = titleArray.joined(separator: ",") + }, fail: nil) + } + + private func configTime(_ callRecord: TUICallRecords) { + let beginTime: TimeInterval = callRecord.beginTime / 1_000 + if beginTime <= 0 { + return + } + timeLabelStr = TUITool.convertDate(toStr: Date(timeIntervalSince1970: beginTime)) + } + + // MARK: - Cache + private func getCacheAvatarForInviteStr(_ inviteStr: String, completion: @escaping (UIImage?) -> Void) { + let cacheKey = "group_call_avatar_\(inviteStr)" + let cachePath = NSSearchPathForDirectoriesInDomains(.cachesDirectory, .userDomainMask, true).first ?? "" + let filePath = "\(cachePath)/\(cacheKey)" + let fileManager = FileManager.default + + if fileManager.fileExists(atPath: filePath) { + if let data = fileManager.contents(atPath: filePath), let image = UIImage(data: data) { + completion(image) + return + } + } + completion(nil) + } + + private func cacheGroupCallAvatar(_ avatar: UIImage, inviteStr: String) { + let cacheKey = "group_call_avatar_\(inviteStr)" + let cachePath = NSSearchPathForDirectoriesInDomains(.cachesDirectory, .userDomainMask, true).first ?? "" + let filePath = "\(cachePath)/\(cacheKey)" + let fileManager = FileManager.default + + if let data = avatar.pngData() { + fileManager.createFile(atPath: filePath, contents: data, attributes: nil) + } + } +} diff --git a/iOS/TUIKit/TUICallKit/TUICallKit-Swift/ViewModel/Component/Recents/TUICallRecordCallsViewModel.swift b/iOS/TUIKit/TUICallKit/TUICallKit-Swift/ViewModel/Component/Recents/TUICallRecordCallsViewModel.swift new file mode 100644 index 000000000..f9b61248c --- /dev/null +++ b/iOS/TUIKit/TUICallKit/TUICallKit-Swift/ViewModel/Component/Recents/TUICallRecordCallsViewModel.swift @@ -0,0 +1,204 @@ +// +// TUICallRecordCallsViewModel.swift +// +// +// Created by vincepzhang on 2023/8/28. +// + +import Foundation +import UIKit +import TUICallEngine +import TUICore + +/// 通话结果 +enum TUICallRecordCallsType: Int { + case all + case missed +} + +/// UI 风格类型 +enum TUICallKitRecordCallsUIStyle: Int { + case classic // 经典风格 + case minimalist // 简约风格 +} + +class TUICallRecordCallsViewModel { + + var dataSource: Observable<[TUICallRecordCallsCellViewModel]> = Observable(Array()) + var allDataSource: [TUICallRecordCallsCellViewModel] = [] + var missedDataSource: [TUICallRecordCallsCellViewModel] = [] + + var recordCallsUIStyle: TUICallKitRecordCallsUIStyle = .minimalist + var recordCallsType: TUICallRecordCallsType = .all + + func queryRecentCalls() { + let filter = TUICallRecentCallsFilter() + TUICallEngine.createInstance().queryRecentCalls(filter: filter, succ: { [weak self] callRecords in + guard let self = self else { return } + var viewModelList: [TUICallRecordCallsCellViewModel] = [] + callRecords.forEach { callRecord in + let viewModel = TUICallRecordCallsCellViewModel(callRecord) + viewModelList.append(viewModel) + } + self.updateDataSource(viewModelList) + }, fail: {}) + } + + func updateDataSource(_ viewModelList: [TUICallRecordCallsCellViewModel]) { + if viewModelList.isEmpty { + return + } + cleanAllSource() + allDataSource = viewModelList + viewModelList.forEach { viewModel in + if viewModel.callRecord.result == .missed { + missedDataSource.append(viewModel) + } + } + reloadDataSource() + } + + func switchRecordCallsType(_ type: TUICallRecordCallsType) { + recordCallsType = type + reloadDataSource() + } + + func reloadDataSource() { + switch recordCallsType { + case .all: + dataSource.value = allDataSource + case .missed: + dataSource.value = missedDataSource + } + } + + func cleanAllSource() { + dataSource.value.removeAll() + allDataSource.removeAll() + missedDataSource.removeAll() + } + + func cleanSource(viewModel: TUICallRecordCallsCellViewModel) { + allDataSource.removeAll() { $0.callRecord.callId == viewModel.callRecord.callId } + missedDataSource.removeAll() { $0.callRecord.callId == viewModel.callRecord.callId } + } + + func cleanSource(callId: String) { + allDataSource.removeAll() { $0.callRecord.callId == callId } + missedDataSource.removeAll() { $0.callRecord.callId == callId } + } + + + func repeatCall(_ indexPath: IndexPath) { + let cellViewModel = dataSource.value[indexPath.row] + + if cellViewModel.callRecord.scene == .single { + repeatSingleCall(cellViewModel.callRecord) + } + } + + func repeatSingleCall(_ callRecord: TUICallRecords) { + var userId = callRecord.inviteList.first + if callRecord.role == .called { + userId = callRecord.inviter + } + + guard let userId = userId as? String else { return } + + TUICallKit.createInstance().call(userId: userId, callMediaType: callRecord.mediaType) + } + + func deleteAllRecordCalls() { + var callIdList: [String] = [] + + if recordCallsType == .all { + callIdList = getCallIdList(allDataSource) + } else if recordCallsType == .missed { + callIdList = getCallIdList(missedDataSource) + } + + TUICallEngine.createInstance().deleteRecordCalls(callIdList, succ: { [weak self] succList in + guard let self = self else { return } + + succList.forEach { callId in + self.cleanSource(callId: callId) + } + + self.reloadDataSource() + }, fail: {}) + } + + func getCallIdList(_ cellViewModelArray: [TUICallRecordCallsCellViewModel]) -> [String] { + var callIdList: [String] = [] + + if cellViewModelArray.isEmpty { + return callIdList + } + + cellViewModelArray.forEach { obj in + callIdList.append(obj.callRecord.callId) + } + + return callIdList + } + + func deleteRecordCall(_ indexPath: IndexPath) { + if indexPath.row < 0 || indexPath.row >= dataSource.value.count { + return + } + let viewModel = dataSource.value[indexPath.row] + + TUICallEngine.createInstance().deleteRecordCalls([viewModel.callRecord.callId], succ: { [weak self] _ in + guard let self = self else { return } + self.cleanSource(viewModel: viewModel) + self.reloadDataSource() + + }, fail: {}) + } + + func jumpUserInfoController(indexPath: IndexPath, navigationController: UINavigationController) { + if indexPath.row < 0 || indexPath.row >= dataSource.value.count { + return + } + let cellViewModel = dataSource.value[indexPath.row] + + let groupId = cellViewModel.callRecord.groupId + var userId = cellViewModel.callRecord.inviter + + if cellViewModel.callRecord.role == .call { + guard let firstUserId = cellViewModel.callRecord.inviteList.first as? String else { return } + userId = firstUserId + } + + if !groupId.isEmpty { + let param: [String: Any] = [TUICore_TUIGroupObjectFactory_GetGroupInfoVC_GroupID: groupId] + if TUICallKitRecordCallsUIStyle.classic == recordCallsUIStyle { + navigationController.push(TUICore_TUIGroupObjectFactory_GetGroupInfoVC_Classic, param: param, forResult: nil) + } else { + navigationController.push(TUICore_TUIGroupObjectFactory_GetGroupInfoVC_Minimalist, param: param, forResult: nil) + } + } else if !userId.isEmpty { + getUserOrFriendProfileVCWithUserID(userId: userId) { viewController in + navigationController.pushViewController(viewController, animated: true) + } fail: { code, desc in + TUITool.makeToastError(Int(code), msg: desc) + } + } + } + + func getUserOrFriendProfileVCWithUserID(userId: String, succ: ((UIViewController) -> Void)?, fail: ((Int, String) -> Void)?) { + let param: [String: Any] = [ + TUICore_TUIContactObjectFactory_GetUserOrFriendProfileVCMethod_UserIDKey: userId ?? "", + TUICore_TUIContactObjectFactory_GetUserOrFriendProfileVCMethod_SuccKey: succ ?? { _ in }, + TUICore_TUIContactObjectFactory_GetUserOrFriendProfileVCMethod_FailKey: fail ?? { _, _ in }, + ] + + if TUICallKitRecordCallsUIStyle.classic == self.recordCallsUIStyle { + TUICore.createObject(TUICore_TUIContactObjectFactory, + key: TUICore_TUIContactObjectFactory_GetUserOrFriendProfileVCMethod, param: param) + } else { + TUICore.createObject(TUICore_TUIContactObjectFactory_Minimalist, + key: TUICore_TUIContactObjectFactory_GetUserOrFriendProfileVCMethod, param: param) + } + } +} diff --git a/iOS/TUIKit/TUICallKit/TUICallKit-Swift/ViewModel/Component/UserInfoView/Single/UserInfoViewModel.swift b/iOS/TUIKit/TUICallKit/TUICallKit-Swift/ViewModel/Component/UserInfoView/Single/UserInfoViewModel.swift index 11c08ecef..81dc9ce29 100644 --- a/iOS/TUIKit/TUICallKit/TUICallKit-Swift/ViewModel/Component/UserInfoView/Single/UserInfoViewModel.swift +++ b/iOS/TUIKit/TUICallKit/TUICallKit-Swift/ViewModel/Component/UserInfoView/Single/UserInfoViewModel.swift @@ -11,14 +11,14 @@ import TUICallEngine class UserInfoViewModel { let callStatusObserver = Observer() let remoteUserListObserver = Observer() - + let remoteUserList: Observable<[User]> = Observable(Array()) let selfCallStatus: Observable = Observable(.none) init() { remoteUserList.value = TUICallState.instance.remoteUserList.value selfCallStatus.value = TUICallState.instance.selfUser.value.callStatus.value - + registerObserve() } @@ -32,34 +32,34 @@ class UserInfoViewModel { guard let self = self else { return } self.selfCallStatus.value = newValue }) - + TUICallState.instance.remoteUserList.addObserver(remoteUserListObserver, closure: { [weak self] newValue, _ in guard let self = self else { return } self.remoteUserList.value = newValue }) } - + func getCurrentWaitingText() -> String { - var waitingtext = String() + var waitingText = String() switch TUICallState.instance.mediaType.value { - case .audio: - if TUICallState.instance.selfUser.value.callRole.value == .call { - waitingtext = TUICallKitLocalize(key: "Demo.TRTC.Calling.waitaccept") ?? "" - } else { - waitingtext = TUICallKitLocalize(key: "Demo.TRTC.calling.invitetoaudiocall") ?? "" - } - case .video: - if TUICallState.instance.selfUser.value.callRole.value == .call { - waitingtext = TUICallKitLocalize(key: "Demo.TRTC.Calling.waitaccept") ?? "" - } else { - waitingtext = TUICallKitLocalize(key: "Demo.TRTC.calling.invitetovideocall") ?? "" - } - case .unknown: - break - default: - break + case .audio: + if TUICallState.instance.selfUser.value.callRole.value == .call { + waitingText = TUICallKitLocalize(key: "Demo.TRTC.Calling.waitaccept") ?? "" + } else { + waitingText = TUICallKitLocalize(key: "Demo.TRTC.calling.invitetoaudiocall") ?? "" + } + case .video: + if TUICallState.instance.selfUser.value.callRole.value == .call { + waitingText = TUICallKitLocalize(key: "Demo.TRTC.Calling.waitaccept") ?? "" + } else { + waitingText = TUICallKitLocalize(key: "Demo.TRTC.calling.invitetovideocall") ?? "" + } + case .unknown: + break + default: + break } - return waitingtext + return waitingText } - + } diff --git a/iOS/TUIKit/TUICallKit/TUICallKit-Swift/ViewModel/Component/VideoLayout/GroupCallVideoCellViewModel.swift b/iOS/TUIKit/TUICallKit/TUICallKit-Swift/ViewModel/Component/VideoLayout/GroupCallVideoCellViewModel.swift index 949abc10c..c2a9b7017 100644 --- a/iOS/TUIKit/TUICallKit/TUICallKit-Swift/ViewModel/Component/VideoLayout/GroupCallVideoCellViewModel.swift +++ b/iOS/TUIKit/TUICallKit/TUICallKit-Swift/ViewModel/Component/VideoLayout/GroupCallVideoCellViewModel.swift @@ -17,8 +17,7 @@ class GroupCallVideoCellViewModel { let isCameraOpenAvailableObserver = Observer() let remotePlayoutVolumeObserver = Observer() let selfPlayoutVolumeObserver = Observer() - - + var isSelf: Bool = false let selfUser: Observable = Observable(User()) diff --git a/iOS/TUIKit/TUICallKit/TUICallKit/TUICallKit.m b/iOS/TUIKit/TUICallKit/TUICallKit/TUICallKit.m index bf533b238..a1a327059 100644 --- a/iOS/TUIKit/TUICallKit/TUICallKit/TUICallKit.m +++ b/iOS/TUIKit/TUICallKit/TUICallKit/TUICallKit.m @@ -688,6 +688,11 @@ callMediaType:(TUICallMediaType)callMediaType errMsg = TUICallingLocalize(@"TUICallKit.package.not.purchased"); } else if (errorCode == ERROR_PACKAGE_NOT_SUPPORTED) { errMsg = TUICallingLocalize(@"TUICallKit.package.not.support"); + } else if (errorCode == ERR_SVR_MSG_IN_PEER_BLACKLIST) { + errMsg = TUICallingLocalize(@"Demo.TRTC.Calling.ErrorInPeerBlacklist"); + } + else { + errMsg = [TUITool convertIMError:errorCode msg:errorMessage]; } [self makeToast:errMsg duration:4 position:nil]; } @@ -696,20 +701,6 @@ callMediaType:(TUICallMediaType)callMediaType [[TUICallEngine createInstance] init:[TUILogin getSdkAppID] userId:[TUILogin getUserID] userSig:[TUILogin getUserSig] succ:^{ } fail:^(int code, NSString *errMsg) { }]; - - TUIVideoEncoderParams *videoEncoderParams = [[TUIVideoEncoderParams alloc] init]; - videoEncoderParams.resolution = TUIVideoEncoderParamsResolution_640_360; - videoEncoderParams.resolutionMode = TUIVideoEncoderParamsResolutionModePortrait; - [[TUICallEngine createInstance] setVideoEncoderParams:videoEncoderParams succ:nil fail:nil]; - - TUIVideoRenderParams *videoRenderParams = [[TUIVideoRenderParams alloc] init]; - videoRenderParams.fillMode = TUIVideoRenderParamsFillModeFill; - videoRenderParams.rotation = TUIVideoRenderParamsRotation_0; - [[TUICallEngine createInstance] setVideoRenderParams:[TUILogin getUserID] params:videoRenderParams succ:nil fail:nil]; - - TXBeautyManager *beauty = [[[TUICallEngine createInstance] getTRTCCloudInstance] getBeautyManager]; - [beauty setBeautyStyle:TXBeautyStyleNature]; - [beauty setBeautyLevel:6]; } - (void)stopCurrentCall { diff --git a/iOS/TUIKit/TUICallKit/TUICallKit/UI/Common/UIImage+TUICallKitRTL.h b/iOS/TUIKit/TUICallKit/TUICallKit/UI/Common/UIImage+TUICallKitRTL.h new file mode 100644 index 000000000..3218e858d --- /dev/null +++ b/iOS/TUIKit/TUICallKit/TUICallKit/UI/Common/UIImage+TUICallKitRTL.h @@ -0,0 +1,21 @@ +// +// UIImage+TUICallKitRTL.h +// TUICallKit +// +// Created by noah on 2023/7/31. +// Copyright © 2023 Tencent. All rights reserved +// + +#import + +NS_ASSUME_NONNULL_BEGIN + +@interface UIImage (TUICallKitRTL) + +- (UIImage *_Nonnull)checkOverturn; + +- (UIImage *)callKitImageFlippedForRightToLeftLayoutDirection; + +@end + +NS_ASSUME_NONNULL_END diff --git a/iOS/TUIKit/TUICallKit/TUICallKit/UI/Common/UIImage+TUICallKitRTL.m b/iOS/TUIKit/TUICallKit/TUICallKit/UI/Common/UIImage+TUICallKitRTL.m new file mode 100644 index 000000000..b7f8f7c69 --- /dev/null +++ b/iOS/TUIKit/TUICallKit/TUICallKit/UI/Common/UIImage+TUICallKitRTL.m @@ -0,0 +1,41 @@ +// +// UIImage+TUICallKitRTL.m +// TUICallKit +// +// Created by noah on 2023/7/31. +// Copyright © 2023 Tencent. All rights reserved +// + +#import "UIImage+TUICallKitRTL.h" +#import + +@interface UIImage (TUICallKitRTL) + +@end + +@implementation UIImage (TUICallKitRTL) + +- (UIImage *_Nonnull)checkOverturn { + if (isRTL()) { + UIGraphicsBeginImageContextWithOptions(self.size, false, self.scale); + CGContextRef bitmap = UIGraphicsGetCurrentContext(); + CGContextTranslateCTM(bitmap, self.size.width / 2, self.size.height / 2); + CGContextScaleCTM(bitmap, -1.0, -1.0); + CGContextTranslateCTM(bitmap, -self.size.width / 2, -self.size.height / 2); + CGContextDrawImage(bitmap, CGRectMake(0, 0, self.size.width, self.size.height), self.CGImage); + UIImage *image = UIGraphicsGetImageFromCurrentImageContext(); + return image; + } + return self; +} + +- (UIImage *)callKitImageFlippedForRightToLeftLayoutDirection { + if (isRTL()) { + return [UIImage imageWithCGImage:self.CGImage + scale:self.scale + orientation:UIImageOrientationUpMirrored]; + } + + return self; +} +@end diff --git a/iOS/TUIKit/TUICallKit/TUICallKit/UI/Extensions/InviteUser/TUICallKitGroupMemberInfo.h b/iOS/TUIKit/TUICallKit/TUICallKit/UI/Extensions/InviteUser/TUICallKitGroupMemberInfo.h index 2ade91574..c453baf8c 100644 --- a/iOS/TUIKit/TUICallKit/TUICallKit/UI/Extensions/InviteUser/TUICallKitGroupMemberInfo.h +++ b/iOS/TUIKit/TUICallKit/TUICallKit/UI/Extensions/InviteUser/TUICallKitGroupMemberInfo.h @@ -9,7 +9,7 @@ NS_ASSUME_NONNULL_BEGIN -@interface TUICallKitGroupMemberInfo: NSObject +@interface TUICallKitGroupMemberInfo : NSObject @property (nonatomic, strong) NSString *userId; @property (nonatomic, strong) NSString *name; diff --git a/iOS/TUIKit/TUICallKit/TUICallKit/UI/Extensions/InviteUser/TUICallKitSelectGroupMeberCell.h b/iOS/TUIKit/TUICallKit/TUICallKit/UI/Extensions/InviteUser/TUICallKitSelectGroupMemberCell.h similarity index 77% rename from iOS/TUIKit/TUICallKit/TUICallKit/UI/Extensions/InviteUser/TUICallKitSelectGroupMeberCell.h rename to iOS/TUIKit/TUICallKit/TUICallKit/UI/Extensions/InviteUser/TUICallKitSelectGroupMemberCell.h index 55808f501..abf7fbcef 100644 --- a/iOS/TUIKit/TUICallKit/TUICallKit/UI/Extensions/InviteUser/TUICallKitSelectGroupMeberCell.h +++ b/iOS/TUIKit/TUICallKit/TUICallKit/UI/Extensions/InviteUser/TUICallKitSelectGroupMemberCell.h @@ -1,5 +1,5 @@ // -// TUICallKitSelectGroupMeberCell.h +// TUICallKitSelectGroupMemberCell.h // Pods // // Created by vincepzhang on 2023/4/7. @@ -13,7 +13,7 @@ NS_ASSUME_NONNULL_BEGIN -@interface TUICallKitSelectGroupMeberCell: UITableViewCell +@interface TUICallKitSelectGroupMemberCell : UITableViewCell - (void)configCell:(TUICallKitGroupMemberInfo *)userInfo isAdded:(BOOL)isAdded; diff --git a/iOS/TUIKit/TUICallKit/TUICallKit/UI/Extensions/InviteUser/TUICallKitSelectGroupMeberCell.m b/iOS/TUIKit/TUICallKit/TUICallKit/UI/Extensions/InviteUser/TUICallKitSelectGroupMemberCell.m similarity index 87% rename from iOS/TUIKit/TUICallKit/TUICallKit/UI/Extensions/InviteUser/TUICallKitSelectGroupMeberCell.m rename to iOS/TUIKit/TUICallKit/TUICallKit/UI/Extensions/InviteUser/TUICallKitSelectGroupMemberCell.m index 8cc4780b9..9cbd59d67 100644 --- a/iOS/TUIKit/TUICallKit/TUICallKit/UI/Extensions/InviteUser/TUICallKitSelectGroupMeberCell.m +++ b/iOS/TUIKit/TUICallKit/TUICallKit/UI/Extensions/InviteUser/TUICallKitSelectGroupMemberCell.m @@ -1,11 +1,11 @@ // -// InviteUserSelectCell.m +// TUICallKitSelectGroupMemberCell.m // TUICallKit // // Created by vincepzhang on 2023/4/7. // Copyright © 2021 Tencent. All rights reserved -#import "TUICallKitSelectGroupMeberCell.h" +#import "TUICallKitSelectGroupMemberCell.h" #import "TUICore.h" #import "UIColor+TUICallingHex.h" #import "Masonry.h" @@ -15,7 +15,7 @@ #import "UIImageView+WebCache.h" #import "TUIThemeManager.h" -@interface TUICallKitSelectGroupMeberCell () +@interface TUICallKitSelectGroupMemberCell () @property (nonatomic, strong) UIImageView *selectImageView; @property (nonatomic, strong) UIImageView *userImageView; @@ -24,12 +24,12 @@ @end -@implementation TUICallKitSelectGroupMeberCell { +@implementation TUICallKitSelectGroupMemberCell { BOOL _isViewReady; } -- (instancetype)init { - self = [super init]; +- (instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier { + self = [super initWithStyle:style reuseIdentifier:reuseIdentifier]; if (self) { _isViewReady = NO; self.contentView.backgroundColor = TUICallKitDynamicColor(@"callkit_recents_cell_bg_color", @"#FFFFFF"); @@ -55,17 +55,15 @@ - (void)activateConstraints { [self.selectImageView mas_makeConstraints:^(MASConstraintMaker *make) { - make.leading.equalTo(self.superview).offset(20); + make.leading.equalTo(self.contentView.mas_leading).offset(20); make.width.height.equalTo(@(15)); make.centerY.equalTo(self); }]; - [self.userImageView mas_makeConstraints:^(MASConstraintMaker *make) { make.leading.equalTo(self.selectImageView.mas_trailing).offset(20); make.width.height.equalTo(@(40)); make.centerY.equalTo(self); }]; - [self.nameLabel mas_makeConstraints:^(MASConstraintMaker *make) { make.leading.equalTo(self.userImageView.mas_trailing).offset(12); make.centerY.equalTo(self); @@ -84,7 +82,7 @@ self.selectImageView.image = [TUICallingCommon getBundleImageWithName:@"tuicallkit_check_box_group_unselected"]; } - if (userInfo.name == NULL || [userInfo.name isEqual: @""]) { + if (userInfo.name == NULL || [userInfo.name isEqual:@""]) { self.nameLabel.text = userInfo.userId; } else { self.nameLabel.text = userInfo.name; @@ -92,6 +90,7 @@ } #pragma mark - Lazy + - (UIImageView *)userImageView { if (!_userImageView) { _userImageView = [[UIImageView alloc] initWithFrame:CGRectZero]; diff --git a/iOS/TUIKit/TUICallKit/TUICallKit/UI/Extensions/InviteUser/TUICallKitSelectGroupMeberViewController.h b/iOS/TUIKit/TUICallKit/TUICallKit/UI/Extensions/InviteUser/TUICallKitSelectGroupMemberViewController.h similarity index 62% rename from iOS/TUIKit/TUICallKit/TUICallKit/UI/Extensions/InviteUser/TUICallKitSelectGroupMeberViewController.h rename to iOS/TUIKit/TUICallKit/TUICallKit/UI/Extensions/InviteUser/TUICallKitSelectGroupMemberViewController.h index dcc5e556d..62374c8fe 100644 --- a/iOS/TUIKit/TUICallKit/TUICallKit/UI/Extensions/InviteUser/TUICallKitSelectGroupMeberViewController.h +++ b/iOS/TUIKit/TUICallKit/TUICallKit/UI/Extensions/InviteUser/TUICallKitSelectGroupMemberViewController.h @@ -12,15 +12,15 @@ NS_ASSUME_NONNULL_BEGIN -@protocol SelectGroupMeberViewControllerDelegate +@protocol SelectGroupMemberViewControllerDelegate - (void)addNewGroupUser:(NSArray *)inviteUsers; @end -@interface TUICallKitSelectGroupMeberViewController : UIViewController +@interface TUICallKitSelectGroupMemberViewController : UIViewController -@property (nonatomic, weak) id delegate; +@property (nonatomic, weak) id delegate; @end diff --git a/iOS/TUIKit/TUICallKit/TUICallKit/UI/Extensions/InviteUser/TUICallKitSelectGroupMeberViewController.m b/iOS/TUIKit/TUICallKit/TUICallKit/UI/Extensions/InviteUser/TUICallKitSelectGroupMemberViewController.m similarity index 85% rename from iOS/TUIKit/TUICallKit/TUICallKit/UI/Extensions/InviteUser/TUICallKitSelectGroupMeberViewController.m rename to iOS/TUIKit/TUICallKit/TUICallKit/UI/Extensions/InviteUser/TUICallKitSelectGroupMemberViewController.m index 8dbf174c7..839b7565f 100644 --- a/iOS/TUIKit/TUICallKit/TUICallKit/UI/Extensions/InviteUser/TUICallKitSelectGroupMeberViewController.m +++ b/iOS/TUIKit/TUICallKit/TUICallKit/UI/Extensions/InviteUser/TUICallKitSelectGroupMemberViewController.m @@ -1,24 +1,25 @@ // -// TUICallKitSelectGroupMeberViewController.m +// TUICallKitSelectGroupMemberViewController.m // TUICallKit // // Created by vincepzhang on 2023/4/7. // Copyright © 2021 Tencent. All rights reserved + +#import "TUICallKitSelectGroupMemberViewController.h" #import "TUICommonModel.h" -#import "TUICallKitSelectGroupMeberViewController.h" #import "TUICore.h" #import "Masonry.h" #import "TUICallingCommon.h" #import "CallingLocalized.h" -#import "TUICallKitSelectGroupMeberCell.h" +#import "TUICallKitSelectGroupMemberCell.h" #import "TUICallKitGroupMemberInfo.h" #import "TUICallingStatusManager.h" #import "TUIDefine.h" #import "TUICallingAction.h" #import "TUICallingUserManager.h" +#import "UIImage+TUICallKitRTL.h" - -@interface TUICallKitSelectGroupMeberViewController () +@interface TUICallKitSelectGroupMemberViewController () @property (nonatomic, strong) UITableView *selectTableView; @property (nonatomic, strong) NSMutableArray *remoteMemberList; @@ -26,7 +27,7 @@ @end -@implementation TUICallKitSelectGroupMeberViewController { +@implementation TUICallKitSelectGroupMemberViewController { BOOL _isViewReady; } @@ -49,7 +50,6 @@ [self constructViewHierarchy]; [self activateConstraints]; _isViewReady = YES; - self.navigationItem.title = TUICallingLocalize(@"TUICallKit.Recents.addUser"); UIBarButtonItem *rightBtn = [[UIBarButtonItem alloc] initWithTitle:TUICallingLocalize(@"LoginNetwork.AppUtils.determine") @@ -62,7 +62,9 @@ UIImage *defaultImage = [TUICallingCommon getBundleImageWithName:@"main_mine_about_back"]; UIButton *leftBtn = [[UIButton alloc] initWithFrame:CGRectMake(0, 0, 30, 30)]; [leftBtn addTarget:self action:@selector(goBack:) forControlEvents:UIControlEventTouchUpInside]; - [leftBtn setImage:TIMCommonDynamicImage(@"nav_back_img", defaultImage) forState:UIControlStateNormal]; + UIImage *leftBtnIcon = TIMCommonDynamicImage(@"nav_back_img", defaultImage); + leftBtnIcon = [leftBtnIcon callKitImageFlippedForRightToLeftLayoutDirection]; + [leftBtn setImage:leftBtnIcon forState:UIControlStateNormal]; UIBarButtonItem *leftItem = [[UIBarButtonItem alloc] initWithCustomView:leftBtn]; self.navigationItem.leftBarButtonItem = leftItem; @@ -82,16 +84,15 @@ - (void)updateMemberList { NSString *groupId = [[TUICallingStatusManager shareInstance] groupId]; if (!groupId) { - [TUITool makeToast: @"groupId unavailable"]; + [TUITool makeToast:@"groupId unavailable"]; return; } + [[V2TIMManager sharedInstance] getGroupMemberList:groupId filter:V2TIM_GROUP_MEMBER_FILTER_ALL nextSeq:0 succ:^(uint64_t nextSeq, NSArray *memberList) { - for (V2TIMGroupMemberFullInfo *userFullInfo in memberList) { - if ([userFullInfo.userID isEqualToString:self.selfInfo.userId]) { self.selfInfo.name = userFullInfo.nickName; self.selfInfo.avatar = userFullInfo.faceURL; @@ -111,18 +112,19 @@ break; } } - [self.remoteMemberList addObject: userModel]; + [self.remoteMemberList addObject:userModel]; } - [self.selectTableView registerClass: [TUICallKitSelectGroupMeberCell classForCoder] forCellReuseIdentifier: @"SelectCell"]; + [self.selectTableView registerClass:[TUICallKitSelectGroupMemberCell classForCoder] forCellReuseIdentifier:@"SelectCell"]; [self.selectTableView reloadData]; [self.view layoutIfNeeded]; } fail:^(int code, NSString *desc) { - [TUITool makeToast: @"get group members file"]; + [TUITool makeToast:@"get group members file"]; }]; } #pragma mark - UITableViewDelegate, UITableViewDataSource + - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { if (self.remoteMemberList.count == 0) { return 0; @@ -132,7 +134,8 @@ } - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { - TUICallKitSelectGroupMeberCell *cell = (TUICallKitSelectGroupMeberCell *)[tableView dequeueReusableCellWithIdentifier:@"SelectCell" forIndexPath:indexPath]; + TUICallKitSelectGroupMemberCell *cell = (TUICallKitSelectGroupMemberCell *)[tableView dequeueReusableCellWithIdentifier:@"SelectCell" + forIndexPath:indexPath]; cell.selectionStyle = UITableViewCellSelectionStyleNone; if (indexPath.row == 0) { [cell configCell:self.selfInfo isAdded:YES]; @@ -179,6 +182,7 @@ } #pragma mark - Lazy + - (UITableView *)selectTableView { if (!_selectTableView) { _selectTableView = [[UITableView alloc] initWithFrame:CGRectZero]; @@ -189,6 +193,7 @@ } #pragma mark - EventAction + - (void)addUsers:(UIButton *)sender { NSMutableArray *inviteUsers = [[NSMutableArray alloc] init]; @@ -206,7 +211,7 @@ addUser.name = user.name; addUser.avatar = user.avatar; addUser.userId = user.userId; - [inviteUsers addObject: addUser]; + [inviteUsers addObject:addUser]; } } @@ -220,4 +225,5 @@ - (void)goBack:(UIButton *)sender { [self dismissViewControllerAnimated:YES completion:nil]; } + @end diff --git a/iOS/TUIKit/TUICallKit/TUICallKit/UI/Recents/TUICallRecordCallsCell.m b/iOS/TUIKit/TUICallKit/TUICallKit/UI/Recents/TUICallRecordCallsCell.m index 2317760ea..a9d6c9709 100644 --- a/iOS/TUIKit/TUICallKit/TUICallKit/UI/Recents/TUICallRecordCallsCell.m +++ b/iOS/TUIKit/TUICallKit/TUICallKit/UI/Recents/TUICallRecordCallsCell.m @@ -70,33 +70,33 @@ static NSString *const gRecordCallsCellViewModelKVOTitle = @"titleLabelStr"; - (void)activateConstraints { [self.avatarImageView mas_makeConstraints:^(MASConstraintMaker *make) { make.centerY.equalTo(self.contentView); - make.left.equalTo(self.contentView).offset(8); + make.leading.equalTo(self.contentView).offset(8); make.width.height.mas_equalTo(40); }]; [self.titleLabel mas_makeConstraints:^(MASConstraintMaker *make) { make.top.equalTo(self.contentView).offset(14); - make.left.equalTo(self.avatarImageView.mas_right).offset(8); - make.right.lessThanOrEqualTo(self.timeLabel.mas_left).offset(-20); + make.leading.equalTo(self.avatarImageView.mas_trailing).offset(8); + make.trailing.lessThanOrEqualTo(self.timeLabel.mas_leading).offset(-20); }]; [self.mediaTypeImageView mas_makeConstraints:^(MASConstraintMaker *make) { make.bottom.equalTo(self.contentView).offset(-14); - make.left.equalTo(self.avatarImageView.mas_right).offset(8); + make.leading.equalTo(self.avatarImageView.mas_trailing).offset(8); make.width.mas_equalTo(19); make.height.mas_equalTo(12); }]; [self.resultLabel mas_makeConstraints:^(MASConstraintMaker *make) { make.centerY.equalTo(self.mediaTypeImageView); - make.left.equalTo(self.mediaTypeImageView.mas_right).offset(4); + make.leading.equalTo(self.mediaTypeImageView.mas_trailing).offset(4); make.width.mas_equalTo(100); }]; [self.timeLabel mas_makeConstraints:^(MASConstraintMaker *make) { make.centerY.equalTo(self.contentView); - make.right.equalTo(self.moreButton.mas_left).offset(-4); + make.trailing.equalTo(self.moreButton.mas_leading).offset(-4); make.width.mas_equalTo(100); }]; [self.moreButton mas_makeConstraints:^(MASConstraintMaker *make) { make.centerY.equalTo(self.contentView); - make.right.mas_equalTo(-8); + make.trailing.mas_equalTo(-8); make.width.height.mas_equalTo(24); }]; } @@ -180,7 +180,7 @@ static NSString *const gRecordCallsCellViewModelKVOTitle = @"titleLabelStr"; _titleLabel = [[UILabel alloc] initWithFrame:CGRectZero]; _titleLabel.numberOfLines = 1; _titleLabel.font = [UIFont fontWithName:@"PingFangHK-Semibold" size:14]; - _titleLabel.textAlignment = NSTextAlignmentLeft; + _titleLabel.textAlignment = isRTL() ? NSTextAlignmentRight : NSTextAlignmentLeft; } return _titleLabel; } @@ -198,7 +198,7 @@ static NSString *const gRecordCallsCellViewModelKVOTitle = @"titleLabelStr"; _resultLabel = [[UILabel alloc] initWithFrame:CGRectZero]; _resultLabel.textColor = TUICallKitDynamicColor(@"callkit_recents_cell_subtitle_color", @"#888888"); _resultLabel.font = [UIFont systemFontOfSize:12]; - _resultLabel.textAlignment = NSTextAlignmentLeft; + _resultLabel.textAlignment = isRTL() ? NSTextAlignmentRight : NSTextAlignmentLeft; } return _resultLabel; } @@ -208,7 +208,7 @@ static NSString *const gRecordCallsCellViewModelKVOTitle = @"titleLabelStr"; _timeLabel = [[UILabel alloc] initWithFrame:CGRectZero]; _timeLabel.textColor = TUICallKitDynamicColor(@"callkit_recents_cell_time_color", @"#BBBBBB"); _timeLabel.font = [UIFont systemFontOfSize:12]; - _timeLabel.textAlignment = NSTextAlignmentRight; + _timeLabel.textAlignment = isRTL() ? NSTextAlignmentLeft : NSTextAlignmentRight; } return _timeLabel; } diff --git a/iOS/TUIKit/TUICallKit/TUICallKit/UI/Recents/TUICallRecordCallsCellViewModel.h b/iOS/TUIKit/TUICallKit/TUICallKit/UI/Recents/TUICallRecordCallsCellViewModel.h index 24d240c64..fafcc63e7 100644 --- a/iOS/TUIKit/TUICallKit/TUICallKit/UI/Recents/TUICallRecordCallsCellViewModel.h +++ b/iOS/TUIKit/TUICallKit/TUICallKit/UI/Recents/TUICallRecordCallsCellViewModel.h @@ -7,6 +7,7 @@ // #import +#import @class TUICallRecords; diff --git a/iOS/TUIKit/TUICallKit/TUICallKit/UI/Recents/TUICallRecordCallsCellViewModel.m b/iOS/TUIKit/TUICallKit/TUICallKit/UI/Recents/TUICallRecordCallsCellViewModel.m index 451b2e484..ba8bf71bb 100644 --- a/iOS/TUIKit/TUICallKit/TUICallKit/UI/Recents/TUICallRecordCallsCellViewModel.m +++ b/iOS/TUIKit/TUICallKit/TUICallKit/UI/Recents/TUICallRecordCallsCellViewModel.m @@ -10,6 +10,7 @@ #import "TUICallEngineHeader.h" #import "TUITool.h" #import "TUIConfig.h" +#import "CallingLocalized.h" @interface TUICallRecordCallsCellViewModel () @@ -112,13 +113,13 @@ self.resultLabelStr = @""; switch (callResultType) { case TUICallResultTypeMissed: - self.resultLabelStr = @"Missed"; + self.resultLabelStr = TUICallingLocalize(@"TUICallKit.Recents.missed"); break; case TUICallResultTypeIncoming: - self.resultLabelStr = @"Incoming"; + self.resultLabelStr = TUICallingLocalize(@"TUICallKit.Recents.incoming"); break; case TUICallResultTypeOutgoing: - self.resultLabelStr = @"Outgoing"; + self.resultLabelStr = TUICallingLocalize(@"TUICallKit.Recents.outgoing"); break; case TUICallResultTypeUnknown: default: diff --git a/iOS/TUIKit/TUICallKit/TUICallKit/UI/Recents/TUICallRecordCallsViewController.m b/iOS/TUIKit/TUICallKit/TUICallKit/UI/Recents/TUICallRecordCallsViewController.m index 8ae7d19cc..d84423493 100644 --- a/iOS/TUIKit/TUICallKit/TUICallKit/UI/Recents/TUICallRecordCallsViewController.m +++ b/iOS/TUIKit/TUICallKit/TUICallKit/UI/Recents/TUICallRecordCallsViewController.m @@ -103,17 +103,17 @@ static NSString *const gRecordCallsViewModelKVOKeyPath = @"dataSource"; }]; [self.editButton mas_makeConstraints:^(MASConstraintMaker *make) { make.centerY.equalTo(self.segmentedControl); - make.right.equalTo(self.containerView).offset(-20); + make.trailing.equalTo(self.containerView).offset(-20); make.width.height.equalTo(@(32)); }]; [self.clearButton mas_makeConstraints:^(MASConstraintMaker *make) { make.centerY.equalTo(self.segmentedControl); - make.left.equalTo(self.containerView).offset(20); + make.leading.equalTo(self.containerView).offset(20); make.height.equalTo(@(32)); }]; [self.doneButton mas_makeConstraints:^(MASConstraintMaker *make) { make.centerY.equalTo(self.segmentedControl); - make.right.equalTo(self.containerView).offset(-20); + make.trailing.equalTo(self.containerView).offset(-20); make.height.equalTo(@(32)); }]; [self.recordCallsList mas_makeConstraints:^(MASConstraintMaker *make) { @@ -322,7 +322,7 @@ trailingSwipeActionsConfigurationForRowAtIndexPath:(NSIndexPath *)indexPath API if (!_clearButton) { UIButton *clearButton = [UIButton buttonWithType:UIButtonTypeCustom]; [clearButton setTitle:TUICallingLocalize(@"TUICallKit.Recents.clear") forState:UIControlStateNormal]; - clearButton.titleLabel.textAlignment = NSTextAlignmentLeft; + clearButton.titleLabel.textAlignment = isRTL() ? NSTextAlignmentRight : NSTextAlignmentLeft; clearButton.contentHorizontalAlignment = UIControlContentHorizontalAlignmentLeft; [clearButton setTitleColor:TUICallKitDynamicColor(@"callkit_nav_title_text_color", @"#000000") forState:UIControlStateNormal]; clearButton.hidden = YES; @@ -337,7 +337,7 @@ trailingSwipeActionsConfigurationForRowAtIndexPath:(NSIndexPath *)indexPath API if (!_editButton) { UIButton *editButton = [UIButton buttonWithType:UIButtonTypeCustom]; [editButton setImage:[TUICallingCommon getBundleImageWithName:@"ic_calls_edit"] forState:UIControlStateNormal]; - editButton.titleLabel.textAlignment = NSTextAlignmentLeft; + editButton.titleLabel.textAlignment = isRTL() ? NSTextAlignmentRight : NSTextAlignmentLeft; editButton.imageView.contentMode = UIViewContentModeScaleAspectFit; _editButton = editButton; } @@ -362,7 +362,7 @@ trailingSwipeActionsConfigurationForRowAtIndexPath:(NSIndexPath *)indexPath API if (!_segmentedControl) { NSArray *array = [NSArray arrayWithObjects:TUICallingLocalize(@"TUICallKit.Recents.all"), TUICallingLocalize(@"TUICallKit.Recents.missed"), nil]; - UISegmentedControl *segment = [[UISegmentedControl alloc]initWithItems:array]; + UISegmentedControl *segment = [[UISegmentedControl alloc] initWithItems:array]; segment.selectedSegmentIndex = 0; _segmentedControl = segment; } @@ -376,11 +376,11 @@ trailingSwipeActionsConfigurationForRowAtIndexPath:(NSIndexPath *)indexPath API label.textColor = TUICallKitDynamicColor(@"callkit_recents_tableHeader_title_text_color", @"#000000"); label.text = TUICallingLocalize(@"TUICallKit.Recents.calls"); label.font = [UIFont fontWithName:@"PingFangHK-Semibold" size:34]; - label.textAlignment = NSTextAlignmentLeft; + label.textAlignment = isRTL() ? NSTextAlignmentRight : NSTextAlignmentLeft; [tableHeaderView addSubview:label]; [label mas_makeConstraints:^(MASConstraintMaker *make) { make.center.equalTo(tableHeaderView); - make.left.equalTo(tableHeaderView).offset(20); + make.leading.equalTo(tableHeaderView).offset(20); }]; _tableHeaderView = tableHeaderView; } diff --git a/iOS/TUIKit/TUICallKit/TUICallKit/UI/Recents/TUICallRecordCallsViewModel.h b/iOS/TUIKit/TUICallKit/TUICallKit/UI/Recents/TUICallRecordCallsViewModel.h index 11f2c4362..a6d944d4e 100644 --- a/iOS/TUIKit/TUICallKit/TUICallKit/UI/Recents/TUICallRecordCallsViewModel.h +++ b/iOS/TUIKit/TUICallKit/TUICallKit/UI/Recents/TUICallRecordCallsViewModel.h @@ -7,6 +7,7 @@ // #import +#import /// 通话结果 typedef NS_ENUM(NSUInteger, TUICallRecordCallsType) { diff --git a/iOS/TUIKit/TUICallKit/TUICallKit/UI/TUICallingNavigationController.h b/iOS/TUIKit/TUICallKit/TUICallKit/UI/TUICallingNavigationController.h index 6d8baccc2..024924fb0 100644 --- a/iOS/TUIKit/TUICallKit/TUICallKit/UI/TUICallingNavigationController.h +++ b/iOS/TUIKit/TUICallKit/TUICallKit/UI/TUICallingNavigationController.h @@ -5,6 +5,8 @@ // Created by vincepzhang on 2023/3/13. // Copyright © 2022 Tencent. All rights reserved +#import + #ifndef TUICallingWindow_h #define TUICallingWindow_h diff --git a/iOS/TUIKit/TUICallKit/TUICallKit/UI/TUICallingViewManager.m b/iOS/TUIKit/TUICallKit/TUICallKit/UI/TUICallingViewManager.m index 56e25a51b..ade158078 100644 --- a/iOS/TUIKit/TUICallKit/TUICallKit/UI/TUICallingViewManager.m +++ b/iOS/TUIKit/TUICallKit/TUICallKit/UI/TUICallingViewManager.m @@ -20,7 +20,6 @@ #import "TUICallingVideoInviteFunctionView.h" #import "TUICallingSwitchToAudioView.h" #import "TUICallingTimerView.h" -#import "TUICallingVideoRenderView.h" #import "UIWindow+TUICalling.h" #import "Masonry.h" #import "UIColor+TUICallingHex.h" @@ -31,11 +30,10 @@ #import "TUIDefine.h" #import "TUICallingUserModel.h" #import "TUICallEngineHeader.h" -#import "TUICore.h" #import "TUICallingNavigationController.h" -#import "TUICallKitSelectGroupMeberViewController.h" +#import "TUICallKitSelectGroupMemberViewController.h" -@interface TUICallingViewManager () +@interface TUICallingViewManager () @property (nonatomic, strong) UIWindow *callingWindow; @property (nonatomic, strong) UIView *containerView; @@ -307,7 +305,7 @@ [self.containerView addSubview:self.addOtherUserBtn]; [self.addOtherUserBtn mas_makeConstraints:^(MASConstraintMaker *make) { make.top.equalTo(self.containerView).offset(StatusBar_Height + 3); - make.right.equalTo(self.containerView).offset(-10); + make.trailing.equalTo(self.containerView).offset(-10); make.width.height.equalTo(@(32)); }]; } @@ -376,8 +374,8 @@ - (void)makeUserViewConstraints:(CGFloat)topOffset { [self.callingUserView mas_remakeConstraints:^(MASConstraintMaker *make) { make.top.equalTo(self.containerView).offset(StatusBar_Height + topOffset); - make.left.equalTo(self.containerView).offset(20); - make.right.equalTo(self.containerView).offset(-20); + make.leading.equalTo(self.containerView).offset(20); + make.trailing.equalTo(self.containerView).offset(-20); }]; } @@ -419,7 +417,7 @@ - (void)makeFloatingWindowBtnConstraints { [self.floatingWindowBtn mas_makeConstraints:^(MASConstraintMaker *make) { make.top.equalTo(self.containerView).offset(StatusBar_Height + 3); - make.left.equalTo(self.containerView).offset(10); + make.leading.equalTo(self.containerView).offset(10); make.width.height.equalTo(@(32)); }]; } @@ -563,7 +561,7 @@ } - (void)addOtherUserTouchEvent:(UIButton *)sender { - TUICallKitSelectGroupMeberViewController *vc = [[TUICallKitSelectGroupMeberViewController alloc] init]; + TUICallKitSelectGroupMemberViewController *vc = [[TUICallKitSelectGroupMemberViewController alloc] init]; vc.delegate = self; UINavigationController *navigationController = [[UINavigationController alloc] initWithRootViewController:vc]; navigationController.modalPresentationStyle = UIModalPresentationFullScreen; @@ -571,9 +569,10 @@ } #pragma mark -SelectGroupMeberViewControllerDelegate -- (void)addNewGroupUser:(NSArray *)inviteUsersn { + +- (void)addNewGroupUser:(NSArray *)inviteUsers { __weak typeof(self) weakSelf = self; - [TUICallingAction inviteUser:inviteUsersn succ:^(NSArray * _Nonnull userIDs) { + [TUICallingAction inviteUser:inviteUsers succ:^(NSArray * _Nonnull userIDs) { [[V2TIMManager sharedInstance] getUsersInfo:userIDs succ:^(NSArray *infoList) { __strong typeof(self) strongSelf = weakSelf; for (V2TIMUserFullInfo *userInfo in infoList) { diff --git a/iOS/TUIKit/TUICallKit/TUICallKit/UI/View/Base/TUICallingGroupCell.m b/iOS/TUIKit/TUICallKit/TUICallKit/UI/View/Base/TUICallingGroupCell.m index 451a2a388..0e2bc0cfa 100644 --- a/iOS/TUIKit/TUICallKit/TUICallKit/UI/View/Base/TUICallingGroupCell.m +++ b/iOS/TUIKit/TUICallKit/TUICallKit/UI/View/Base/TUICallingGroupCell.m @@ -7,6 +7,7 @@ // #import "TUICallingGroupCell.h" +#import #import "UIImageView+WebCache.h" #import "UIColor+TUICallingHex.h" #import "TUICallingCommon.h" @@ -40,7 +41,6 @@ self.maskView.hidden = YES; } else { self.maskView.hidden = NO; - [self.loadingImageView startAnimating]; } if (model.isAudioAvailable) { @@ -65,6 +65,14 @@ return [UIImage imageNamed:name inBundle:[self callingBundle] compatibleWithTraitCollection:nil]; } +- (void)setHighlighted:(BOOL)highlighted { + [super setHighlighted:highlighted]; + if (!self.maskView.isHidden && self.loadingImageView) { + [self.loadingImageView removeFromSuperview]; + [self addLoadingImageView]; + } +} + - (instancetype)initWithFrame:(CGRect)frame { if (self = [super initWithFrame:frame]) { // renderView @@ -81,19 +89,13 @@ maskView.backgroundColor = [UIColor t_colorWithHexString:@"#000000" alpha:0.3]; [self.contentView addSubview:maskView]; self.maskView = maskView; - // loadingImageView - NSString *filePath = [[TUICallingCommon callingBundle] pathForResource:@"loading" ofType:@"gif"]; - NSData *imageData = [NSData dataWithContentsOfFile:filePath]; - UIImageView *loadingImageView = [[UIImageView alloc] init]; - loadingImageView.image = [UIImage sd_imageWithGIFData:imageData]; - self.loadingImageView = loadingImageView; - [self.maskView addSubview:loadingImageView]; + [self addLoadingImageView]; // titleLabel UILabel *label = [[UILabel alloc] initWithFrame:CGRectZero]; label.textColor = [UIColor t_colorWithHexString:@"#FFFFFF"]; label.font = [UIFont systemFontOfSize:12]; - label.textAlignment = NSTextAlignmentLeft; + label.textAlignment = isRTL() ? NSTextAlignmentRight : NSTextAlignmentLeft; [self.contentView addSubview:label]; self.titleLabel = label; // volumeImageView @@ -112,17 +114,14 @@ [self.maskView mas_makeConstraints:^(MASConstraintMaker *make) { make.edges.equalTo(self.contentView); }]; - [loadingImageView mas_makeConstraints:^(MASConstraintMaker *make) { - make.center.equalTo(self.maskView); - make.height.width.equalTo(@(42)); - }]; [label mas_makeConstraints:^(MASConstraintMaker *make) { - make.left.equalTo(self.contentView).offset(10); + make.leading.equalTo(self.contentView.mas_leading).offset(10); make.bottom.equalTo(self.contentView).offset(-5); - make.right.equalTo(self.volumeImageView.mas_left).offset(-5); + make.trailing.equalTo(self.volumeImageView.mas_leading).offset(-5); }]; [volumeImageView mas_makeConstraints:^(MASConstraintMaker *make) { - make.right.bottom.equalTo(self.contentView).offset(-5); + make.trailing.equalTo(self.contentView.mas_trailing).offset(-5); + make.bottom.equalTo(self.contentView).offset(-5); make.centerY.equalTo(label); make.width.height.equalTo(@(20)); }]; @@ -130,4 +129,17 @@ return self; } +- (void)addLoadingImageView { + NSString *filePath = [[TUICallingCommon callingBundle] pathForResource:@"loading" ofType:@"gif"]; + NSData *imageData = [NSData dataWithContentsOfFile:filePath]; + UIImageView *loadingImageView = [[UIImageView alloc] init]; + loadingImageView.image = [UIImage sd_imageWithGIFData:imageData]; + self.loadingImageView = loadingImageView; + [self.maskView addSubview:loadingImageView]; + [loadingImageView mas_makeConstraints:^(MASConstraintMaker *make) { + make.center.equalTo(self.maskView); + make.height.width.equalTo(@(42)); + }]; +} + @end diff --git a/iOS/TUIKit/TUICallKit/TUICallKit/UI/View/Component/TUICallingCalleeView.m b/iOS/TUIKit/TUICallKit/TUICallKit/UI/View/Component/TUICallingCalleeView.m index 9176089a4..3bde54a6b 100644 --- a/iOS/TUIKit/TUICallKit/TUICallKit/UI/View/Component/TUICallingCalleeView.m +++ b/iOS/TUIKit/TUICallKit/TUICallKit/UI/View/Component/TUICallingCalleeView.m @@ -46,14 +46,14 @@ static CGFloat const kSpacing = 5.0f; // 视图约束 [self.calleeTipLabel mas_makeConstraints:^(MASConstraintMaker *make) { make.centerX.top.equalTo(self); - make.left.equalTo(self).offset(20); - make.right.equalTo(self).offset(-20); + make.leading.equalTo(self).offset(20); + make.trailing.equalTo(self).offset(-20); make.height.equalTo(@(20)); }]; [self.calleeCollectionView mas_makeConstraints:^(MASConstraintMaker *make) { make.top.equalTo(self.calleeTipLabel.mas_bottom).offset(15); - make.left.equalTo(self).offset(20); - make.right.equalTo(self).offset(-20); + make.leading.equalTo(self).offset(20); + make.trailing.equalTo(self).offset(-20); make.height.equalTo(@(32)); }]; } diff --git a/iOS/TUIKit/TUICallKit/TUICallKit/UI/View/Component/TUICallingSingleVideoUserView.m b/iOS/TUIKit/TUICallKit/TUICallKit/UI/View/Component/TUICallingSingleVideoUserView.m index 53ac482e8..3b5ecddca 100644 --- a/iOS/TUIKit/TUICallKit/TUICallKit/UI/View/Component/TUICallingSingleVideoUserView.m +++ b/iOS/TUIKit/TUICallKit/TUICallKit/UI/View/Component/TUICallingSingleVideoUserView.m @@ -11,6 +11,7 @@ #import "Masonry.h" #import "TUICallEngineHeader.h" #import "TUICallingUserModel.h" +#import @interface TUICallingSingleVideoUserView () @@ -36,18 +37,18 @@ - (void)makeConstraints { [self.userHeadImageView mas_makeConstraints:^(MASConstraintMaker *make) { - make.top.right.mas_equalTo(self); + make.top.trailing.mas_equalTo(self); make.size.mas_equalTo(CGSizeMake(100, 100)); }]; [self.userNameLabel mas_makeConstraints:^(MASConstraintMaker *make) { make.top.equalTo(self.userHeadImageView.mas_top); - make.left.equalTo(self); - make.right.equalTo(self.userHeadImageView.mas_left).offset(-20); + make.leading.equalTo(self); + make.trailing.equalTo(self.userHeadImageView.mas_leading).offset(-20); }]; [self.waitingInviteLabel mas_makeConstraints:^(MASConstraintMaker *make) { make.top.equalTo(self.userNameLabel.mas_bottom).offset(8.0f); - make.left.equalTo(self); - make.right.equalTo(self.userHeadImageView.mas_left).offset(-20); + make.leading.equalTo(self); + make.trailing.equalTo(self.userHeadImageView.mas_leading).offset(-20); }]; } @@ -77,7 +78,7 @@ [_userNameLabel setTextColor:[UIColor t_colorWithHexString:@"#FFFFFF"]]; [_userNameLabel setFont:[UIFont boldSystemFontOfSize:24.0f]]; [_userNameLabel setBackgroundColor:[UIColor clearColor]]; - [_userNameLabel setTextAlignment:NSTextAlignmentRight]; + [_userNameLabel setTextAlignment:(isRTL() ? NSTextAlignmentLeft : NSTextAlignmentRight)]; } return _userNameLabel; } @@ -88,7 +89,7 @@ [_waitingInviteLabel setBackgroundColor:[UIColor clearColor]]; [_waitingInviteLabel setTextColor:[UIColor t_colorWithHexString:@"#FFFFFF"]]; [_waitingInviteLabel setFont:[UIFont systemFontOfSize:12.0f]]; - [_waitingInviteLabel setTextAlignment:NSTextAlignmentRight]; + [_waitingInviteLabel setTextAlignment:(isRTL() ? NSTextAlignmentLeft : NSTextAlignmentRight)]; } return _waitingInviteLabel; } diff --git a/iOS/TUIKit/TUICallKit/TUICallKit/UI/View/FloatWindow/TUICallingFloatingWindow.m b/iOS/TUIKit/TUICallKit/TUICallKit/UI/View/FloatWindow/TUICallingFloatingWindow.m index 9c9cbe6c8..974162123 100644 --- a/iOS/TUIKit/TUICallKit/TUICallKit/UI/View/FloatWindow/TUICallingFloatingWindow.m +++ b/iOS/TUIKit/TUICallKit/TUICallKit/UI/View/FloatWindow/TUICallingFloatingWindow.m @@ -60,11 +60,11 @@ static CGFloat const kMicroContainerViewOffset = 8; }]; [self.avatarImageView mas_makeConstraints:^(MASConstraintMaker *make) { make.center.mas_equalTo(self); - make.top.left.mas_equalTo(self).offset(kMicroContainerViewOffset); + make.top.leading.mas_equalTo(self).offset(kMicroContainerViewOffset); }]; [self.containerView mas_makeConstraints:^(MASConstraintMaker *make) { make.center.mas_equalTo(self); - make.top.left.mas_equalTo(self).offset(kMicroContainerViewOffset); + make.top.leading.mas_equalTo(self).offset(kMicroContainerViewOffset); }]; [self.imageView mas_makeConstraints:^(MASConstraintMaker *make) { make.top.mas_equalTo(self.containerView).offset(5); diff --git a/iOS/TUIKit/TUICallKit/TUICallKit/UI/View/Function/TUICallingAudioFunctionView.m b/iOS/TUIKit/TUICallKit/TUICallKit/UI/View/Function/TUICallingAudioFunctionView.m index e7292aa50..81ea3f6eb 100644 --- a/iOS/TUIKit/TUICallKit/TUICallKit/UI/View/Function/TUICallingAudioFunctionView.m +++ b/iOS/TUIKit/TUICallKit/TUICallKit/UI/View/Function/TUICallingAudioFunctionView.m @@ -34,7 +34,7 @@ - (void)makeConstraints { [self.muteBtn mas_makeConstraints:^(MASConstraintMaker *make) { - make.right.equalTo(self.hangupBtn.mas_left).offset(-5); + make.trailing.equalTo(self.hangupBtn.mas_leading).offset(-5); make.centerY.equalTo(self.hangupBtn); make.size.equalTo(@(kControlBtnSize)); }]; @@ -44,7 +44,7 @@ make.size.equalTo(@(kControlBtnSize)); }]; [self.handsfreeBtn mas_makeConstraints:^(MASConstraintMaker *make) { - make.left.equalTo(self.hangupBtn.mas_right).offset(5); + make.leading.equalTo(self.hangupBtn.mas_trailing).offset(5); make.centerY.equalTo(self.hangupBtn); make.size.equalTo(@(kControlBtnSize)); }]; diff --git a/iOS/TUIKit/TUICallKit/TUICallKit/UI/View/Function/TUICallingVideoFunctionView.m b/iOS/TUIKit/TUICallKit/TUICallKit/UI/View/Function/TUICallingVideoFunctionView.m index 19287a8c3..3664c33bf 100644 --- a/iOS/TUIKit/TUICallKit/TUICallKit/UI/View/Function/TUICallingVideoFunctionView.m +++ b/iOS/TUIKit/TUICallKit/TUICallKit/UI/View/Function/TUICallingVideoFunctionView.m @@ -39,7 +39,7 @@ - (void)makeConstraints { [self.muteBtn mas_makeConstraints:^(MASConstraintMaker *make) { - make.right.equalTo(self.handsfreeBtn.mas_left); + make.trailing.equalTo(self.handsfreeBtn.mas_leading); make.centerY.equalTo(self.handsfreeBtn); make.size.equalTo(@(kControlBtnSize)); }]; @@ -49,7 +49,7 @@ make.size.equalTo(@(kControlBtnSize)); }]; [self.closeCameraBtn mas_makeConstraints:^(MASConstraintMaker *make) { - make.left.equalTo(self.handsfreeBtn.mas_right); + make.leading.equalTo(self.handsfreeBtn.mas_trailing); make.centerY.equalTo(self.handsfreeBtn); make.size.equalTo(@(kControlBtnSize)); }]; @@ -60,7 +60,7 @@ }]; [self.switchCameraBtn mas_makeConstraints:^(MASConstraintMaker *make) { make.centerY.equalTo(self.hangupBtn); - make.left.equalTo(self.hangupBtn.mas_right).offset(20); + make.leading.equalTo(self.hangupBtn.mas_trailing).offset(20); make.size.equalTo(@(CGSizeMake(36, 36))); }]; } diff --git a/iOS/TUIKit/TUICallKit/TUICallKit/UI/View/Function/TUICallingVideoInviteFunctionView.m b/iOS/TUIKit/TUICallKit/TUICallKit/UI/View/Function/TUICallingVideoInviteFunctionView.m index 5bb3187cd..3e033213f 100644 --- a/iOS/TUIKit/TUICallKit/TUICallKit/UI/View/Function/TUICallingVideoInviteFunctionView.m +++ b/iOS/TUIKit/TUICallKit/TUICallKit/UI/View/Function/TUICallingVideoInviteFunctionView.m @@ -36,7 +36,7 @@ }]; [self.switchCameraBtn mas_makeConstraints:^(MASConstraintMaker *make) { make.centerY.equalTo(self.hangupBtn); - make.left.equalTo(self.hangupBtn.mas_right).offset(20); + make.leading.equalTo(self.hangupBtn.mas_trailing).offset(20); make.size.equalTo(@(CGSizeMake(36, 36))); }]; } diff --git a/iOS/TUIKit/TUICallKit/TUICallKit/UI/View/Function/TUICallingWaitFunctionView.m b/iOS/TUIKit/TUICallKit/TUICallKit/UI/View/Function/TUICallingWaitFunctionView.m index e7ea4cd19..4263b5be0 100644 --- a/iOS/TUIKit/TUICallKit/TUICallKit/UI/View/Function/TUICallingWaitFunctionView.m +++ b/iOS/TUIKit/TUICallKit/TUICallKit/UI/View/Function/TUICallingWaitFunctionView.m @@ -8,6 +8,7 @@ #import "TUICallingWaitFunctionView.h" #import "Masonry.h" +#import @interface TUICallingWaitFunctionView () @@ -31,13 +32,13 @@ - (void)makeConstraints { [self.rejectBtn mas_makeConstraints:^(MASConstraintMaker *make) { - make.centerX.equalTo(self).offset(-80); + make.centerX.equalTo(self).offset(isRTL() ? 80 : -80); make.bottom.equalTo(self); make.width.equalTo(@(100)); make.height.equalTo(@(94)); }]; [self.acceptBtn mas_makeConstraints:^(MASConstraintMaker *make) { - make.centerX.equalTo(self).offset(80); + make.centerX.equalTo(self).offset(isRTL() ? -80 : 80); make.bottom.equalTo(self); make.width.equalTo(@(100)); make.height.equalTo(@(94)); diff --git a/iOS/TUIKit/TUICallKit/TUICallKit/UI/View/Protocol/BaseCallViewProtocol.h b/iOS/TUIKit/TUICallKit/TUICallKit/UI/View/Protocol/BaseCallViewProtocol.h index 8f5d5038b..2f40d15b1 100644 --- a/iOS/TUIKit/TUICallKit/TUICallKit/UI/View/Protocol/BaseCallViewProtocol.h +++ b/iOS/TUIKit/TUICallKit/TUICallKit/UI/View/Protocol/BaseCallViewProtocol.h @@ -10,6 +10,7 @@ #import "UIColor+TUICallingHex.h" #import "TUICallingVideoRenderView.h" #import "TUICallingAction.h" +#import "TUICallingCommon.h" NS_ASSUME_NONNULL_BEGIN diff --git a/iOS/TUIKit/TUICallKit/TUICallKit/UI/View/Root/TUICallingGroupView.m b/iOS/TUIKit/TUICallKit/TUICallKit/UI/View/Root/TUICallingGroupView.m index f8767cb2a..511e187cf 100644 --- a/iOS/TUIKit/TUICallKit/TUICallKit/UI/View/Root/TUICallingGroupView.m +++ b/iOS/TUIKit/TUICallKit/TUICallKit/UI/View/Root/TUICallingGroupView.m @@ -14,6 +14,7 @@ #import "TUILogin.h" #import "TUICallEngineHeader.h" #import "TUICallingUserModel.h" +#import "TUICallingStatusManager.h" @interface TUICallingGroupView () @@ -170,6 +171,9 @@ #pragma mark - Action Event - (void)startRemoteView:(NSString *)userId view:(UIView *)view { + if (self.callType != TUICallMediaTypeVideo) { + return; + } [TUICallingAction startRemoteView:userId videoView:view onPlaying:nil onLoading:nil onError:nil]; } @@ -180,7 +184,7 @@ #pragma mark - Private - (void)handleLocalRenderView { - if (self.callType != TUICallMediaTypeVideo) { + if ((self.callType != TUICallMediaTypeVideo) || (TUICallStatusNone == [TUICallingStatusManager shareInstance].callStatus)) { return; } diff --git a/iOS/TUIKit/TUICallKit/TUICallKit/UI/View/Root/TUICallingSingleView.m b/iOS/TUIKit/TUICallKit/TUICallKit/UI/View/Root/TUICallingSingleView.m index 83b7113e5..cc60cb805 100644 --- a/iOS/TUIKit/TUICallKit/TUICallKit/UI/View/Root/TUICallingSingleView.m +++ b/iOS/TUIKit/TUICallKit/TUICallKit/UI/View/Root/TUICallingSingleView.m @@ -15,8 +15,9 @@ #import "TUICallingUserModel.h" static CGFloat const kCallingSingleSmallVideoViewWidth = 100.0f; -#define kTUICallingSingleViewMicroRenderFrame CGRectMake(self.frame.size.width - kCallingSingleSmallVideoViewWidth - 18,\ -StatusBar_Height + 20, kCallingSingleSmallVideoViewWidth, kCallingSingleSmallVideoViewWidth / 9.0 * 16.0) + +#define kTUICallingSingleViewMicroRenderFrame CGRectMake(isRTL() ? 18 : (self.frame.size.width - kCallingSingleSmallVideoViewWidth - 18),\ +StatusBar_Height + 40, kCallingSingleSmallVideoViewWidth, kCallingSingleSmallVideoViewWidth / 9.0 * 16.0) @interface TUICallingSingleView () @@ -46,7 +47,6 @@ StatusBar_Height + 20, kCallingSingleSmallVideoViewWidth, kCallingSingleSmallVid - (void)setupCallingSingleView { self.localPreView.frame = self.bounds; - self.remotePreView.frame = CGRectMake(self.bounds.size.width - 120, 74 + 20, 100, 216); [self.localPreView setUserInteractionEnabled:NO]; self.remotePreView.hidden = YES; self.localPreView.hidden = NO; diff --git a/iOS/TUIKit/TUIChat/BaseCell/TUIChatPopEmojiView.m b/iOS/TUIKit/TUIChat/BaseCell/TUIChatPopEmojiView.m index 2b09ea5b9..0ba00d109 100644 --- a/iOS/TUIKit/TUIChat/BaseCell/TUIChatPopEmojiView.m +++ b/iOS/TUIKit/TUIChat/BaseCell/TUIChatPopEmojiView.m @@ -70,6 +70,7 @@ TUIFaceCellData *data = [[TUIFaceCellData alloc] init]; data.path = TUIChatFaceImagePath(@"del_normal"); [cell setData:data]; + cell.face.image = [cell.face.image rtl_imageFlippedForRightToLeftLayoutDirection]; } else { NSNumber *index = [self.itemIndexs objectForKey:indexPath]; if (index.integerValue < group.faces.count) { diff --git a/iOS/TUIKit/TUIChat/BaseCell/TUIChatPopMenu.h b/iOS/TUIKit/TUIChat/BaseCell/TUIChatPopMenu.h index ecbe19ce2..62943cb1a 100644 --- a/iOS/TUIKit/TUIChat/BaseCell/TUIChatPopMenu.h +++ b/iOS/TUIKit/TUIChat/BaseCell/TUIChatPopMenu.h @@ -20,10 +20,8 @@ typedef void (^TUIChatPopMenuActionCallback)(void); @property(nonatomic, copy) TUIChatPopMenuActionCallback callback; /** - * 排序优先级: 复制(1)、转发(2)、多选(3)、引用(4)、回复(5)、撤回(6)、删除(7)、翻译(8) - * Sort priorities: copy, forward, multiselect, reference, reply, Withdraw, delete - * 权重越大越靠前weight: 复制 10000 转发 9000 多选 8000 引用 7000 回复 5000 撤回4000 删除 3000 翻译 2000 - * The higher the weight, the more prominent it is: Copy 10000, Forward 9000, Multiple Choice 8000, Quote 7000, Reply 5000, Withdraw 4000, Delete 3000. + * 权重越大越靠前weight: 语音播放风格(11000) 复制 10000 转发 9000 多选 8000 引用 7000 回复 5000 撤回4000 删除 3000 翻译 2000 + * The higher the weight, the more prominent it is: audioPlayback 11000 Copy 10000, Forward 9000, Multiple Choice 8000, Quote 7000, Reply 5000, Withdraw 4000, Delete 3000. */ @property(nonatomic, assign) NSInteger weight; diff --git a/iOS/TUIKit/TUIChat/BaseCell/TUIChatPopMenu.m b/iOS/TUIKit/TUIChat/BaseCell/TUIChatPopMenu.m index ff2e8280a..9c145cee1 100644 --- a/iOS/TUIKit/TUIChat/BaseCell/TUIChatPopMenu.m +++ b/iOS/TUIKit/TUIChat/BaseCell/TUIChatPopMenu.m @@ -191,8 +191,21 @@ [self setupContainerPosition]; [self updateLayout]; + + if (isRTL()) { + [self fitRTLViews]; + } + +} +- (void)fitRTLViews { + if (self.actionsView) { + for (UIView *subview in self.actionsView.subviews) { + if ([subview respondsToSelector:@selector(resetFrameToFitRTL)]) { + [subview resetFrameToFitRTL]; + } + } + } } - - (void)updateActionByRank { NSArray *ageSortResultArray = [self.actions sortedArrayUsingComparator:^NSComparisonResult(id obj1, id obj2) { TUIChatPopMenuAction *per1 = obj1; @@ -426,8 +439,11 @@ - (UIButton *)buttonWithAction:(TUIChatPopMenuAction *)action tag:(NSInteger)tag { UIButton *actionButton = [UIButton buttonWithType:UIButtonTypeCustom]; - [actionButton setTitleColor:TUIChatDynamicColor(@"chat_pop_menu_text_color", @"#444444") forState:UIControlStateNormal]; + [actionButton setTitleColor:TUIChatDynamicColor(@"chat_pop_menu_text_color", @"#444444") + forState:UIControlStateNormal]; actionButton.titleLabel.font = [UIFont systemFontOfSize:10.0]; + actionButton.titleLabel.numberOfLines = 2; + actionButton.titleLabel.lineBreakMode = NSLineBreakByWordWrapping; [actionButton setTitle:action.title forState:UIControlStateNormal]; [actionButton setImage:action.image forState:UIControlStateNormal]; actionButton.contentMode = UIViewContentModeScaleAspectFit; @@ -446,6 +462,7 @@ if (titleSize.width + 0.5 < frameSize.width) { titleSize.width = frameSize.width; } + titleSize.width = MIN(titleSize.width, 48); CGFloat totalHeight = (imageSize.height + titleSize.height + 8); actionButton.imageEdgeInsets = UIEdgeInsetsMake(-(totalHeight - imageSize.height), 0.0, 0.0, -titleSize.width); actionButton.titleEdgeInsets = UIEdgeInsetsMake(0, -imageSize.width, -(totalHeight - titleSize.height), 0); diff --git a/iOS/TUIKit/TUIChat/BaseCell/TUIChatPopRecentView.m b/iOS/TUIKit/TUIChat/BaseCell/TUIChatPopRecentView.m index 9dcfa2bd3..28518517c 100644 --- a/iOS/TUIKit/TUIChat/BaseCell/TUIChatPopRecentView.m +++ b/iOS/TUIKit/TUIChat/BaseCell/TUIChatPopRecentView.m @@ -27,6 +27,15 @@ - (void)layoutSubviews { [super layoutSubviews]; [self defaultLayout]; + + if (isRTL()) { + for (UIView *subview in self.subviews) { + if ([subview respondsToSelector:@selector(resetFrameToFitRTL)]) { + [subview resetFrameToFitRTL]; + } + } + } + } - (void)defaultLayout { diff --git a/iOS/TUIKit/TUIChat/BaseCell/TUIEmojiCell.m b/iOS/TUIKit/TUIChat/BaseCell/TUIEmojiCell.m index 00ee7ec51..ee2466ac8 100644 --- a/iOS/TUIKit/TUIChat/BaseCell/TUIEmojiCell.m +++ b/iOS/TUIKit/TUIChat/BaseCell/TUIEmojiCell.m @@ -33,11 +33,13 @@ _displayName = [[UILabel alloc] init]; _displayName.font = [UIFont boldSystemFontOfSize:kScale390(16)]; _displayName.textColor = [UIColor tui_colorWithHex:@"#666666"]; + _displayName.textAlignment = isRTL()?NSTextAlignmentRight:NSTextAlignmentLeft; [self addSubview:_displayName]; _tapToRemoveLabel = [[UILabel alloc] init]; _tapToRemoveLabel.font = [UIFont systemFontOfSize:kScale390(12)]; _tapToRemoveLabel.textColor = [UIColor tui_colorWithHex:@"#666666"]; + _tapToRemoveLabel.textAlignment = isRTL()?NSTextAlignmentRight:NSTextAlignmentLeft; [self addSubview:_tapToRemoveLabel]; _emoji = [[UIImageView alloc] init]; @@ -61,27 +63,64 @@ _displayName.text = TIMCommonLocalizableString(You); _tapToRemoveLabel.text = TIMCommonLocalizableString(TUIKitChatTap2Remove); } - + [_emoji setImage:[data.emojiName getEmojiImage]]; + + // tell constraints they need updating + [self setNeedsUpdateConstraints]; + + // update constraints now so we can animate the change + [self updateConstraintsIfNeeded]; + + [self layoutIfNeeded]; } -- (void)layoutSubviews { - [super layoutSubviews]; - _avatar.frame = CGRectMake(kScale390(26), (self.contentView.frame.size.height - kScale390(40)) * 0.5, kScale390(40), kScale390(40)); ++ (BOOL)requiresConstraintBasedLayout { + return YES; +} + +// this is Apple's recommended place for adding/updating constraints +- (void)updateConstraints { + [super updateConstraints]; + + CGFloat avatarSize = kScale390(40); + + [_avatar mas_remakeConstraints:^(MASConstraintMaker *make) { + make.leading.mas_equalTo(kScale390(26)); + make.centerY.mas_equalTo(self.contentView); + make.width.height.mas_equalTo(avatarSize); + }]; + + [_displayName mas_remakeConstraints:^(MASConstraintMaker *make) { + make.leading.mas_equalTo(_avatar.mas_trailing).mas_offset(kScale390(16)); + make.trailing.mas_equalTo(-kScale390(60)); + make.height.mas_equalTo(kScale390(22)); + make.centerY.mas_equalTo(self.contentView); + }]; - _displayName.frame = - CGRectMake(_avatar.frame.origin.x + _avatar.frame.size.width + kScale390(16), (self.contentView.frame.size.height - kScale390(22)) * 0.5, - self.contentView.frame.size.width - kScale390(60), kScale390(22)); if (self.data.isCurrentUser) { - _displayName.frame = CGRectMake(_avatar.frame.origin.x + _avatar.frame.size.width + kScale390(16), _avatar.frame.origin.y, - self.contentView.frame.size.width - kScale390(60), kScale390(22)); - _tapToRemoveLabel.frame = CGRectMake(_avatar.frame.origin.x + _avatar.frame.size.width + kScale390(16), - _displayName.frame.origin.y + _displayName.frame.size.height + kScale390(4), - self.contentView.frame.size.width - kScale390(60), kScale390(12)); + [_displayName mas_remakeConstraints:^(MASConstraintMaker *make) { + make.leading.mas_equalTo(_avatar.mas_trailing).mas_offset(kScale390(16)); + make.top.mas_equalTo(_avatar.mas_top); + make.trailing.mas_equalTo(-kScale390(60)); + make.height.mas_equalTo(kScale390(22)); + }]; + [_tapToRemoveLabel mas_remakeConstraints:^(MASConstraintMaker *make) { + make.leading.mas_equalTo(_displayName.mas_leading); + make.top.mas_equalTo(_displayName.mas_bottom).mas_offset(kScale390(4)); + make.trailing.mas_equalTo(-kScale390(60)); + make.height.mas_equalTo(kScale390(12)); + }]; } - _emoji.frame = - CGRectMake(self.contentView.frame.size.width - kScale390(32), (self.contentView.frame.size.height - kScale390(16)) * 0.5, kScale390(16), kScale390(16)); + [_emoji mas_remakeConstraints:^(MASConstraintMaker *make) { + make.trailing.mas_equalTo(self.contentView.mas_trailing).mas_offset(-kScale390(32)); + make.centerY.mas_equalTo(self.contentView); + make.width.height.mas_equalTo(kScale390(16)); + }]; +} +- (void)layoutSubviews { + [super layoutSubviews]; } @end diff --git a/iOS/TUIKit/TUIChat/BaseCell/TUIFaceView.m b/iOS/TUIKit/TUIChat/BaseCell/TUIFaceView.m index 8d9bb305e..6d5ffcd57 100644 --- a/iOS/TUIKit/TUIChat/BaseCell/TUIFaceView.m +++ b/iOS/TUIKit/TUIChat/BaseCell/TUIFaceView.m @@ -34,7 +34,7 @@ - (void)setupViews { self.backgroundColor = TUIChatDynamicColor(@"chat_input_controller_bg_color", @"#EBF0F6"); - _faceFlowLayout = [[UICollectionViewFlowLayout alloc] init]; + _faceFlowLayout = [[TUICollectionRTLFitFlowLayout alloc] init]; _faceFlowLayout.scrollDirection = UICollectionViewScrollDirectionHorizontal; _faceFlowLayout.minimumLineSpacing = TFaceView_Margin; _faceFlowLayout.minimumInteritemSpacing = TFaceView_Margin; @@ -133,6 +133,7 @@ TUIFaceCellData *data = [[TUIFaceCellData alloc] init]; data.path = TUIChatFaceImagePath(@"del_normal"); [cell setData:data]; + cell.face.image = [cell.face.image rtl_imageFlippedForRightToLeftLayoutDirection]; } else { NSNumber *index = [_itemIndexs objectForKey:indexPath]; if (index.integerValue < group.faces.count) { diff --git a/iOS/TUIKit/TUIChat/BaseCellData/Base/TUIGroupCreatedCellData.m b/iOS/TUIKit/TUIChat/BaseCellData/Base/TUIGroupCreatedCellData.m index 1e79f2a6d..2428c3990 100644 --- a/iOS/TUIKit/TUIChat/BaseCellData/Base/TUIGroupCreatedCellData.m +++ b/iOS/TUIKit/TUIChat/BaseCellData/Base/TUIGroupCreatedCellData.m @@ -17,11 +17,22 @@ cellData.innerMessage = message; cellData.msgID = message.msgID; cellData.content = param[@"content"]; - cellData.opUser = param[@"opUser"]; + cellData.opUser = [self.class getOpUserName:message]; cellData.cmd = param[@"cmd"]; return cellData; } ++ (NSString *)getOpUserName:(V2TIMMessage *)info { + NSString *opUser; + if (info.nameCard.length > 0) { + opUser = info.nameCard; + } else if (info.nickName.length > 0) { + opUser = info.nickName; + } else { + opUser = info.userID; + } + return opUser; +} - (NSMutableAttributedString *)attributedString { NSString *localizableContent = self.content; if (self.cmd && [self.cmd isKindOfClass:NSNumber.class]) { @@ -33,6 +44,7 @@ } } NSString *str = [NSString stringWithFormat:@"\"%@\" %@", self.opUser, localizableContent]; + str = rtlString(str); NSMutableAttributedString *attributeString = [[NSMutableAttributedString alloc] initWithString:str]; NSDictionary *attributeDict = @{NSForegroundColorAttributeName : [UIColor d_systemGrayColor]}; [attributeString setAttributes:attributeDict range:NSMakeRange(0, attributeString.length)]; @@ -67,7 +79,8 @@ localizableContent = TIMCommonLocalizableString(TUIGroupCreateTipsMessage); } } - return [NSString stringWithFormat:@"\"%@\" %@", param[@"opUser"], localizableContent]; + NSString *str = [NSString stringWithFormat:@"\"%@\" %@", param[@"opUser"], localizableContent]; + return rtlString(str); } @end diff --git a/iOS/TUIKit/TUIChat/BaseCellData/Chat/TUIImageMessageCellData.m b/iOS/TUIKit/TUIChat/BaseCellData/Chat/TUIImageMessageCellData.m index 7feb706e8..976594ba5 100644 --- a/iOS/TUIKit/TUIChat/BaseCellData/Chat/TUIImageMessageCellData.m +++ b/iOS/TUIKit/TUIChat/BaseCellData/Chat/TUIImageMessageCellData.m @@ -203,7 +203,7 @@ V2TIMMessage *imMsg = self.innerMessage; if (imMsg.elemType == V2TIM_ELEM_TYPE_IMAGE) { for (V2TIMImage *imImage in imMsg.imageElem.imageList) { - if (type == TImage_Type_Thumb && imImage.type == V2TIM_IMAGE_TYPE_LARGE) { + if (type == TImage_Type_Thumb && imImage.type == V2TIM_IMAGE_TYPE_THUMB) { return imImage; } else if (type == TImage_Type_Origin && imImage.type == V2TIM_IMAGE_TYPE_ORIGIN) { return imImage; diff --git a/iOS/TUIKit/TUIChat/BaseCellData/Chat/TUIMergeMessageCellData.h b/iOS/TUIKit/TUIChat/BaseCellData/Chat/TUIMergeMessageCellData.h index 584da0813..aa3903802 100644 --- a/iOS/TUIKit/TUIChat/BaseCellData/Chat/TUIMergeMessageCellData.h +++ b/iOS/TUIKit/TUIChat/BaseCellData/Chat/TUIMergeMessageCellData.h @@ -17,6 +17,10 @@ NS_ASSUME_NONNULL_BEGIN @property(nonatomic, strong) NSArray *abstractList; @property(nonatomic, strong) V2TIMMergerElem *mergerElem; @property(nonatomic, assign) CGSize abstractSize; +@property(nonatomic, assign) CGSize abstractRow1Size; +@property(nonatomic, assign) CGSize abstractRow2Size; +@property(nonatomic, assign) CGSize abstractRow3Size; +@property(nonatomic, strong) NSArray *abstractSendDetailList; - (NSAttributedString *)abstractAttributedString; @end diff --git a/iOS/TUIKit/TUIChat/BaseCellData/Chat/TUIMergeMessageCellData.m b/iOS/TUIKit/TUIChat/BaseCellData/Chat/TUIMergeMessageCellData.m index 99a3c2c9d..5a8a85a8a 100644 --- a/iOS/TUIKit/TUIChat/BaseCellData/Chat/TUIMergeMessageCellData.m +++ b/iOS/TUIKit/TUIChat/BaseCellData/Chat/TUIMergeMessageCellData.m @@ -23,6 +23,7 @@ TUIMergeMessageCellData *relayData = [[TUIMergeMessageCellData alloc] initWithDirection:(message.isSelf ? MsgDirectionOutgoing : MsgDirectionIncoming)]; relayData.title = elem.title; relayData.abstractList = [NSArray arrayWithArray:elem.abstractList]; + relayData.abstractSendDetailList = [self.class formatAbstractSendDetailList:elem.abstractList]; relayData.mergerElem = elem; relayData.reuseId = TRelayMessageCell_ReuserId; return relayData; @@ -43,6 +44,7 @@ - (NSAttributedString *)abstractAttributedString { NSMutableParagraphStyle *style = [[NSMutableParagraphStyle alloc] init]; style.lineSpacing = 4; + style.alignment = isRTL()? NSTextAlignmentRight:NSTextAlignmentLeft; NSDictionary *attribute = @{ NSForegroundColorAttributeName : [UIColor colorWithRed:187 / 255.0 green:187 / 255.0 blue:187 / 255.0 alpha:1 / 1.0], NSFontAttributeName : [UIFont systemFontOfSize:12.0], @@ -55,11 +57,62 @@ if (i >= 4) { break; } - NSString *str = [NSString stringWithFormat:@"%@\n", ab]; + NSString *resultStr = [NSString stringWithFormat:@"%@\n", ab]; + NSString *str = resultStr; [abstr appendAttributedString:[[NSAttributedString alloc] initWithString:str attributes:attribute]]; i++; } return abstr; } ++ (NSMutableArray *)formatAbstractSendDetailList:(NSArray *)originAbstractList { + NSMutableArray *array = [NSMutableArray arrayWithCapacity:3]; + NSMutableParagraphStyle *style = [[NSMutableParagraphStyle alloc] init]; + style.lineSpacing = 4; + style.alignment = isRTL()? NSTextAlignmentRight:NSTextAlignmentLeft; + NSDictionary *attribute = @{ + NSForegroundColorAttributeName : [UIColor colorWithRed:187 / 255.0 green:187 / 255.0 blue:187 / 255.0 alpha:1 / 1.0], + NSFontAttributeName : [UIFont systemFontOfSize:12.0], + NSParagraphStyleAttributeName : style + }; + int i = 0; + for (NSString *ab in originAbstractList) { + if (i >= 4) { + break; + } + NSString *str = ab; + NSString * splitStr = @":"; + if ([str containsString:@"\u202C:"]) { + splitStr = @"\u202C:"; + } + NSArray *result = [str componentsSeparatedByString:splitStr]; + NSString *sender = result[0]; + NSString *detail = result[1]; + sender = [NSString stringWithFormat:@"%@",sender]; + detail = [NSString stringWithFormat:@"%@",detail]; + NSMutableDictionary *dic = [NSMutableDictionary dictionaryWithCapacity:3]; + if(sender.length>0 ){ + NSMutableAttributedString *abstr = [[NSMutableAttributedString alloc] initWithString:@""]; + [abstr appendAttributedString:[[NSAttributedString alloc] initWithString:sender attributes:attribute]]; + [dic setObject:abstr forKey:@"sender"]; + } + if(detail.length>0 ){ + NSMutableAttributedString *abstr = [[NSMutableAttributedString alloc] initWithString:@""]; + [abstr appendAttributedString:[[NSAttributedString alloc] initWithString:detail attributes:attribute]]; + [dic setObject:abstr forKey:@"detail"]; + } + [array addObject:dic]; + + i++; + } + return array; +} +- (BOOL)isArString:(NSString *)text { + NSString *isoLangCode = (__bridge_transfer NSString *)CFStringTokenizerCopyBestStringLanguage((__bridge CFStringRef)text, CFRangeMake(0, text.length)); + + if ([isoLangCode isEqualToString:@"ar"]) { + return YES; + } + return NO; +} @end diff --git a/iOS/TUIKit/TUIChat/BaseCellData/Chat/TUIVoiceMessageCellData.h b/iOS/TUIKit/TUIChat/BaseCellData/Chat/TUIVoiceMessageCellData.h index 0f576a7dd..3bf185acd 100644 --- a/iOS/TUIKit/TUIChat/BaseCellData/Chat/TUIVoiceMessageCellData.h +++ b/iOS/TUIKit/TUIChat/BaseCellData/Chat/TUIVoiceMessageCellData.h @@ -9,6 +9,11 @@ NS_ASSUME_NONNULL_BEGIN typedef void (^VoicePlayTime)(CGFloat); +typedef NS_ENUM(NSUInteger, TUIVoiceAudioPlaybackStyle) { + TUIVoiceAudioPlaybackStyleLoudspeaker = 1, + TUIVoiceAudioPlaybackStyleHandset = 2, +}; + @interface TUIVoiceMessageCellData : TUIBubbleMessageCellData @property(nonatomic, strong) NSString *path; @@ -63,6 +68,11 @@ typedef void (^VoicePlayTime)(CGFloat); - (void)playVoiceMessage; @property(nonatomic, copy) void (^audioPlayerDidFinishPlayingBlock)(void); + + +//The style of audio playback. ++ (TUIVoiceAudioPlaybackStyle)getAudioplaybackStyle; ++ (void)changeAudioPlaybackStyle; @end NS_ASSUME_NONNULL_END diff --git a/iOS/TUIKit/TUIChat/BaseCellData/Chat/TUIVoiceMessageCellData.m b/iOS/TUIKit/TUIChat/BaseCellData/Chat/TUIVoiceMessageCellData.m index b3f161d88..a0c3a40ec 100644 --- a/iOS/TUIKit/TUIChat/BaseCellData/Chat/TUIVoiceMessageCellData.m +++ b/iOS/TUIKit/TUIChat/BaseCellData/Chat/TUIVoiceMessageCellData.m @@ -50,19 +50,19 @@ self.cellLayout = [TUIMessageCellLayout incommingVoiceMessageLayout]; _voiceImage = TUIChatDynamicImage(@"chat_voice_message_receiver_voice_normal_img", [[TUIImageCache sharedInstance] getResourceFromCache:TUIChatImagePath(@"message_voice_receiver_normal")]); - _voiceAnimationImages = - [NSArray arrayWithObjects:[[TUIImageCache sharedInstance] getResourceFromCache:TUIChatImagePath(@"message_voice_receiver_playing_1")], - [[TUIImageCache sharedInstance] getResourceFromCache:TUIChatImagePath(@"message_voice_receiver_playing_2")], - [[TUIImageCache sharedInstance] getResourceFromCache:TUIChatImagePath(@"message_voice_receiver_playing_3")], nil]; + _voiceImage = [_voiceImage rtl_imageFlippedForRightToLeftLayoutDirection]; + _voiceAnimationImages = [NSArray arrayWithObjects:[self.class formatImageByName:@"message_voice_receiver_playing_1"], + [self.class formatImageByName:@"message_voice_receiver_playing_2"], + [self.class formatImageByName:@"message_voice_receiver_playing_3"], nil]; _voiceTop = [[self class] incommingVoiceTop]; } else { self.cellLayout = [TUIMessageCellLayout outgoingVoiceMessageLayout]; _voiceImage = TUIChatDynamicImage(@"chat_voice_message_sender_voice_normal_img", [[TUIImageCache sharedInstance] getResourceFromCache:TUIChatImagePath(@"message_voice_sender_normal")]); - _voiceAnimationImages = - [NSArray arrayWithObjects:[[TUIImageCache sharedInstance] getResourceFromCache:TUIChatImagePath(@"message_voice_sender_playing_1")], - [[TUIImageCache sharedInstance] getResourceFromCache:TUIChatImagePath(@"message_voice_sender_playing_2")], - [[TUIImageCache sharedInstance] getResourceFromCache:TUIChatImagePath(@"message_voice_sender_playing_3")], nil]; + _voiceImage = [_voiceImage rtl_imageFlippedForRightToLeftLayoutDirection]; + _voiceAnimationImages = [NSArray arrayWithObjects:[self.class formatImageByName:@"message_voice_sender_playing_1"], + [self.class formatImageByName:@"message_voice_sender_playing_2"], + [self.class formatImageByName:@"message_voice_sender_playing_3"], nil]; _voiceTop = [[self class] outgoingVoiceTop]; } _voiceHeight = 21; @@ -71,6 +71,12 @@ return self; } ++ (UIImage *)formatImageByName:(NSString *)imgName { + NSString *path = TUIChatImagePath(imgName); + UIImage *img = [[TUIImageCache sharedInstance] getResourceFromCache:path]; + return [img rtl_imageFlippedForRightToLeftLayoutDirection]; +} + - (NSString *)getVoicePath:(BOOL *)isExist { NSString *path = nil; BOOL isDir = false; @@ -151,7 +157,13 @@ - (void)playInternal:(NSString *)path { if (!self.isPlaying) return; // play current - [[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayback error:nil]; + TUIVoiceAudioPlaybackStyle playbackStyle = [self.class getAudioplaybackStyle]; + if(playbackStyle == TUIVoiceAudioPlaybackStyleHandset) { + [[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayAndRecord error:nil]; + } + else { + [[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayback error:nil]; + } NSURL *url = [NSURL fileURLWithPath:path]; self.audioPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL:url error:nil]; self.audioPlayer.delegate = self; @@ -178,7 +190,28 @@ // Fallback on earlier versions } } +//The style of audio playback. ++ (TUIVoiceAudioPlaybackStyle)getAudioplaybackStyle { + NSString *style = [NSUserDefaults.standardUserDefaults objectForKey:@"tui_audioPlaybackStyle"]; + if ([style isEqualToString:@"1"]) { + return TUIVoiceAudioPlaybackStyleLoudspeaker; + } else if ([style isEqualToString:@"2"]) { + return TUIVoiceAudioPlaybackStyleHandset; + } + return TUIVoiceAudioPlaybackStyleLoudspeaker; +} ++ (void)changeAudioPlaybackStyle { + TUIVoiceAudioPlaybackStyle style = [self getAudioplaybackStyle]; + if (style == TUIVoiceAudioPlaybackStyleLoudspeaker) { + [NSUserDefaults.standardUserDefaults setObject:@"2" forKey:@"tui_audioPlaybackStyle"]; + } + else { + [NSUserDefaults.standardUserDefaults setObject:@"1" forKey:@"tui_audioPlaybackStyle"]; + } + [NSUserDefaults.standardUserDefaults synchronize]; + +} - (void)updateProgress { @weakify(self); dispatch_async(dispatch_get_main_queue(), ^{ diff --git a/iOS/TUIKit/TUIChat/BaseCellData/Reply/TUIVoiceReplyQuoteViewData.m b/iOS/TUIKit/TUIChat/BaseCellData/Reply/TUIVoiceReplyQuoteViewData.m index d85cfda10..d381e41dd 100644 --- a/iOS/TUIKit/TUIChat/BaseCellData/Reply/TUIVoiceReplyQuoteViewData.m +++ b/iOS/TUIKit/TUIChat/BaseCellData/Reply/TUIVoiceReplyQuoteViewData.m @@ -22,7 +22,7 @@ } TUIVoiceReplyQuoteViewData *myData = [[TUIVoiceReplyQuoteViewData alloc] init]; - myData.text = [NSString stringWithFormat:@"%ds\"", [(TUIVoiceMessageCellData *)originCellData duration]]; + myData.text = [NSString stringWithFormat:@"%d\"", [(TUIVoiceMessageCellData *)originCellData duration]]; myData.icon = TUIChatCommonBundleImage(@"voice_reply"); myData.originCellData = originCellData; return myData; diff --git a/iOS/TUIKit/TUIChat/BaseDataProvider/Base/TUIChatCallingDataProvider.m b/iOS/TUIKit/TUIChat/BaseDataProvider/Base/TUIChatCallingDataProvider.m index 018185019..6b1d2787f 100644 --- a/iOS/TUIKit/TUIChat/BaseDataProvider/Base/TUIChatCallingDataProvider.m +++ b/iOS/TUIKit/TUIChat/BaseDataProvider/Base/TUIChatCallingDataProvider.m @@ -256,8 +256,7 @@ typedef NSDictionary *TUIChatCallingJsonData; NSUInteger duration = [[self.jsonData objectForKey:@"call_end"] unsignedIntegerValue]; display = isGroup ? TIMCommonLocalizableString(TUIKitSignalingFinishGroupChat) - : [NSString stringWithFormat:TIMCommonLocalizableString(TUIKitSignalingFinishConversationAndTimeFormat), duration / 60, duration % 60]; - + : [NSString stringWithFormat:@"%@:%.2d:%.2d",TIMCommonLocalizableString(TUIKitSignalingFinishConversationAndTimeFormat),duration / 60, duration % 60]; } else if (protocolType == TUICallProtocolTypeTimeout) { // Call timeout NSMutableString *mutableContent = [NSMutableString string]; @@ -285,7 +284,7 @@ typedef NSDictionary *TUIChatCallingJsonData; display = TIMCommonLocalizableString(TUIKitSignalingComfirmSwitchToAudio); } - return display; + return rtlString(display); } - (TUICallMessageDirection)directionForDetailsAppearance { @@ -321,7 +320,7 @@ typedef NSDictionary *TUIChatCallingJsonData; display = isCaller ? TUIChatLocalizableString(TUIChatCallCancelInCaller) : TUIChatLocalizableString(TUIChatCallCancelInCallee); } else if (protocolType == TUICallProtocolTypeHangup) { NSInteger duration = [[self.jsonData objectForKey:@"call_end"] integerValue]; - display = [NSString stringWithFormat:TUIChatLocalizableString(TUIChatCallDurationFormat), duration / 60, duration % 60]; + display = [NSString stringWithFormat:@"%@:%.2d:%.2d",TUIChatLocalizableString(TUIChatCallDurationFormat),duration / 60, duration % 60]; } else if (protocolType == TUICallProtocolTypeTimeout) { display = isCaller ? TUIChatLocalizableString(TUIChatCallTimeoutInCaller) : TUIChatLocalizableString(TUIChatCallTimeoutInCallee); } else if (protocolType == TUICallProtocolTypeLineBusy) { @@ -375,7 +374,7 @@ typedef NSDictionary *TUIChatCallingJsonData; } else { display = TUIChatLocalizableString(TUIChatCallUnrecognized); } - return display; + return rtlString(display); } - (TUICallMessageDirection)directionForSimplifyAppearance { diff --git a/iOS/TUIKit/TUIChat/BaseDataProvider/Base/TUIMessageBaseDataProvider.m b/iOS/TUIKit/TUIChat/BaseDataProvider/Base/TUIMessageBaseDataProvider.m index 335a5e16c..5763470b5 100644 --- a/iOS/TUIKit/TUIChat/BaseDataProvider/Base/TUIMessageBaseDataProvider.m +++ b/iOS/TUIKit/TUIChat/BaseDataProvider/Base/TUIMessageBaseDataProvider.m @@ -994,11 +994,13 @@ } + (void)markC2CMessageAsRead:(NSString *)userID succ:(nullable V2TIMSucc)succ fail:(nullable V2TIMFail)fail { - [[V2TIMManager sharedInstance] markC2CMessageAsRead:userID succ:succ fail:fail]; + NSString * conversationID = [NSString stringWithFormat:@"c2c_%@",userID]; + [[V2TIMManager sharedInstance] cleanConversationUnreadMessageCount:conversationID cleanTimestamp:0 cleanSequence:0 succ:succ fail:fail]; } + (void)markGroupMessageAsRead:(NSString *)groupID succ:(nullable V2TIMSucc)succ fail:(nullable V2TIMFail)fail { - [[V2TIMManager sharedInstance] markGroupMessageAsRead:groupID succ:succ fail:fail]; + NSString * conversationID = [NSString stringWithFormat:@"group_%@",groupID]; + [[V2TIMManager sharedInstance] cleanConversationUnreadMessageCount:conversationID cleanTimestamp:0 cleanSequence:0 succ:succ fail:fail]; } + (void)markConversationAsUndead:(NSArray *)conversationIDList enableMark:(BOOL)enableMark { @@ -1096,7 +1098,7 @@ } else if (message.userID != nil) { str = TIMCommonLocalizableString(TUIKitMessageTipsOthersRecallMessage); } - return str; + return rtlString(str); } + (NSString *)getGroupTipsDisplayString:(V2TIMMessage *)message { @@ -1167,7 +1169,7 @@ default: break; } - return str; + return rtlString(str); } + (V2TIMMessage *)getCustomMessageWithJsonData:(NSData *)data { @@ -1176,7 +1178,7 @@ + (NSString *)opGroupInfoChagedFormatStr:(NSString *)opUser ofUserList:(NSMutableArray *)userList ofTips:(V2TIMGroupTipsElem *)tips{ NSString *str = nil; - str = [NSString stringWithFormat:@"\"%@\"", opUser]; + str = [NSString stringWithFormat:@"%@", opUser]; for (V2TIMGroupChangeInfo *info in tips.groupChangeInfoList) { switch (info.type) { case V2TIM_GROUP_INFO_CHANGE_TYPE_NAME: { @@ -1238,7 +1240,7 @@ break; } } - return str; + return rtlString(str); } + (NSString *)getOpUserName:(V2TIMGroupMemberInfo *)info { NSString *opUser; diff --git a/iOS/TUIKit/TUIChat/BaseDataProvider/Impl/TUIChatDataProvider.h b/iOS/TUIKit/TUIChat/BaseDataProvider/Impl/TUIChatDataProvider.h index 717fe5d85..c51ab938b 100644 --- a/iOS/TUIKit/TUIChat/BaseDataProvider/Impl/TUIChatDataProvider.h +++ b/iOS/TUIKit/TUIChat/BaseDataProvider/Impl/TUIChatDataProvider.h @@ -20,10 +20,12 @@ NS_ASSUME_NONNULL_BEGIN #pragma mark - CellData - (NSMutableArray *)moreMenuCellDataArray:(NSString *)groupID userID:(NSString *)userID + conversationModel:(TUIChatConversationModel *)conversationModel actionController:(id)actionController; - (NSArray *)getInputMoreActionItemList:(nullable NSString *)userID groupID:(nullable NSString *)groupID + conversationModel:(TUIChatConversationModel *)conversationModel pushVC:(nullable UINavigationController *)pushVC actionController:(id)actionController; diff --git a/iOS/TUIKit/TUIChat/BaseDataProvider/Impl/TUIChatDataProvider.m b/iOS/TUIKit/TUIChat/BaseDataProvider/Impl/TUIChatDataProvider.m index 27ae88303..6b6d50a68 100644 --- a/iOS/TUIKit/TUIChat/BaseDataProvider/Impl/TUIChatDataProvider.m +++ b/iOS/TUIKit/TUIChat/BaseDataProvider/Impl/TUIChatDataProvider.m @@ -13,6 +13,7 @@ #import "TUIChatDataProvider.h" #import "TUIMessageDataProvider.h" #import "TUIVideoMessageCellData.h" +#import "TUIChatConversationModel.h" #define Input_SendBtn_Key @"Input_SendBtn_Key" #define Input_SendBtn_Title @"Input_SendBtn_Title" @@ -219,8 +220,11 @@ if (display.length == 0) { display = [TUIMessageDataProvider getDisplayString:msg]; } + NSString * splitStr = @":"; + splitStr = @"\u202C:"; if (desc.length > 0 && display.length > 0) { - desc = [desc stringByAppendingFormat:@":%@", display]; + desc = [desc stringByAppendingFormat:@"%@", splitStr]; + desc = [desc stringByAppendingFormat:@"%@", display]; } return desc; } @@ -229,9 +233,12 @@ - (NSMutableArray *)moreMenuCellDataArray:(NSString *)groupID userID:(NSString *)userID + conversationModel:(TUIChatConversationModel *)conversationModel actionController:(id)actionController { - BOOL isNeedVideoCall = [TUIChatConfig defaultConfig].enableVideoCall; - BOOL isNeedAudioCall = [TUIChatConfig defaultConfig].enableAudioCall; + + BOOL isNeedVideoCall = [TUIChatConfig defaultConfig].enableVideoCall && conversationModel.enabelVideo; + BOOL isNeedAudioCall = [TUIChatConfig defaultConfig].enableAudioCall && conversationModel.enabelAudio; + BOOL isNeedRoom = conversationModel.enabelRoom; BOOL isNeedGroupLive = NO; BOOL isNeedLink = [TUIChatConfig defaultConfig].enableWelcomeCustomMessage; @@ -248,6 +255,7 @@ } extensionParam[TUICore_TUIChatExtension_InputViewMoreItem_FilterVideoCall] = @(!isNeedVideoCall); extensionParam[TUICore_TUIChatExtension_InputViewMoreItem_FilterAudioCall] = @(!isNeedAudioCall); + extensionParam[TUICore_TUIChatExtension_InputViewMoreItem_FilterRoom] = @(!isNeedRoom); extensionParam[TUICore_TUIChatExtension_InputViewMoreItem_ActionVC] = actionController; NSArray *extensionList = [TUICore getExtensionList:TUICore_TUIChatExtension_InputViewMoreItem_ClassicExtensionID param:extensionParam]; for (TUIExtensionInfo *info in extensionList) { @@ -271,6 +279,7 @@ - (NSArray *)getInputMoreActionItemList:(NSString *)userID groupID:(NSString *)groupID + conversationModel:(TUIChatConversationModel *)conversationModel pushVC:(UINavigationController *)pushVC actionController:(id)actionController { NSMutableArray *result = [NSMutableArray array]; diff --git a/iOS/TUIKit/TUIChat/BaseDataProvider/Impl/TUIMessageSearchDataProvider.m b/iOS/TUIKit/TUIChat/BaseDataProvider/Impl/TUIMessageSearchDataProvider.m index 4a9a96e67..7531f1fa5 100644 --- a/iOS/TUIKit/TUIChat/BaseDataProvider/Impl/TUIMessageSearchDataProvider.m +++ b/iOS/TUIKit/TUIChat/BaseDataProvider/Impl/TUIMessageSearchDataProvider.m @@ -53,13 +53,13 @@ typedef void (^LoadMsgSucceedBlock)(BOOL isOlderNoMoreMsg, BOOL isNewerNoMoreMsg __block NSString *failDesc = nil; /** - * 以定位消息为起点,加载最旧的10条消息 - * Load the oldest 10 messages starting from locating message + * 以定位消息为起点,加载最旧的pageCount条消息 + * Load the oldest pageCount messages starting from locating message */ { dispatch_group_enter(group); V2TIMMessageListGetOption *option = [[V2TIMMessageListGetOption alloc] init]; - option.getType = V2TIM_GET_LOCAL_OLDER_MSG; + option.getType = V2TIM_GET_CLOUD_OLDER_MSG; option.count = self.pageCount; option.groupID = conversation.groupID; option.userID = conversation.userID; @@ -85,13 +85,13 @@ typedef void (^LoadMsgSucceedBlock)(BOOL isOlderNoMoreMsg, BOOL isNewerNoMoreMsg }]; } /** - * 以定位消息为起点,加载最新的10条消息 - * Load the latest 10 messages starting from the locating message + * 以定位消息为起点,加载最新的pageCount条消息 + * Load the latest pageCount messages starting from the locating message */ { dispatch_group_enter(group); V2TIMMessageListGetOption *option = [[V2TIMMessageListGetOption alloc] init]; - option.getType = V2TIM_GET_LOCAL_NEWER_MSG; + option.getType = V2TIM_GET_CLOUD_NEWER_MSG; option.count = self.pageCount; option.groupID = conversation.groupID; option.userID = conversation.userID; diff --git a/iOS/TUIKit/TUIChat/CommonModel/TUIAudioRecorder.m b/iOS/TUIKit/TUIChat/CommonModel/TUIAudioRecorder.m index 4f012ad75..2e9d640cb 100644 --- a/iOS/TUIKit/TUIChat/CommonModel/TUIAudioRecorder.m +++ b/iOS/TUIKit/TUIChat/CommonModel/TUIAudioRecorder.m @@ -101,7 +101,7 @@ #pragma mark-- Timer - (void)triggerRecordTimer { self.currentRecordTime = 0; - self.recordTimer = [NSTimer scheduledTimerWithTimeInterval:0.5 target:self selector:@selector(onRecordTimerTriggered:) userInfo:nil repeats:YES]; + self.recordTimer = [NSTimer scheduledTimerWithTimeInterval:0.2 target:self selector:@selector(onRecordTimerTriggered:) userInfo:nil repeats:YES]; } - (void)onRecordTimerTriggered:(NSTimer *)timer { @@ -109,7 +109,7 @@ if (self.isUsingCallKitRecorder) { /// To ensure the callkit recorder's recording time is enough for 60 seconds. - self.currentRecordTime += 0.495; + self.currentRecordTime += 0.1958; if (self.delegate && [self.delegate respondsToSelector:@selector(audioRecorder:didRecordTimeChanged:)]) { [self.delegate audioRecorder:self didRecordTimeChanged:self.currentRecordTime]; } diff --git a/iOS/TUIKit/TUIChat/CommonModel/TUIChatConfig.h b/iOS/TUIKit/TUIChat/CommonModel/TUIChatConfig.h index 4b0852fe8..d80ca5ebb 100644 --- a/iOS/TUIKit/TUIChat/CommonModel/TUIChatConfig.h +++ b/iOS/TUIKit/TUIChat/CommonModel/TUIChatConfig.h @@ -70,6 +70,12 @@ NS_ASSUME_NONNULL_BEGIN */ @property(nonatomic, assign) BOOL enableTypingStatus; +/** + * 聊天对话框是否展示 输入框 默认 YES + * Whether the chat dialog box displays "InputBar", the default is YES + */ +@property(nonatomic, assign) BOOL enableMainPageInputBar; + /** * 设置聊天界面背景颜色 * Setup the backgroud color of chat page diff --git a/iOS/TUIKit/TUIChat/CommonModel/TUIChatConfig.m b/iOS/TUIKit/TUIChat/CommonModel/TUIChatConfig.m index 2997c0e11..2583f4ebf 100644 --- a/iOS/TUIKit/TUIChat/CommonModel/TUIChatConfig.m +++ b/iOS/TUIKit/TUIChat/CommonModel/TUIChatConfig.m @@ -21,6 +21,7 @@ self.enablePopMenuEmojiReactAction = YES; self.enablePopMenuReplyAction = YES; self.enablePopMenuReferenceAction = YES; + self.enableMainPageInputBar = YES; self.enableTypingStatus = YES; self.enableFloatWindowForCall = YES; self.enableMultiDeviceForCall = NO; diff --git a/iOS/TUIKit/TUIChat/CommonModel/TUIChatConversationModel.h b/iOS/TUIKit/TUIChat/CommonModel/TUIChatConversationModel.h index b60adbbde..2c26034da 100644 --- a/iOS/TUIKit/TUIChat/CommonModel/TUIChatConversationModel.h +++ b/iOS/TUIKit/TUIChat/CommonModel/TUIChatConversationModel.h @@ -75,6 +75,12 @@ NS_ASSUME_NONNULL_BEGIN @property(nonatomic, assign) BOOL otherSideTyping; +@property(nonatomic, assign) BOOL enabelVideo; + +@property(nonatomic, assign) BOOL enabelAudio; + +@property(nonatomic, assign) BOOL enabelRoom; + @end NS_ASSUME_NONNULL_END diff --git a/iOS/TUIKit/TUIChat/CommonModel/TUIChatConversationModel.m b/iOS/TUIKit/TUIChat/CommonModel/TUIChatConversationModel.m index e5fc0635e..53bd693ed 100644 --- a/iOS/TUIKit/TUIChat/CommonModel/TUIChatConversationModel.m +++ b/iOS/TUIKit/TUIChat/CommonModel/TUIChatConversationModel.m @@ -10,4 +10,13 @@ @implementation TUIChatConversationModel +- (instancetype)init { + self = [super init]; + if (self){ + self.enabelVideo = YES; + self.enabelAudio = YES; + self.enabelRoom = YES; + } + return self; +} @end diff --git a/iOS/TUIKit/TUIChat/CommonModel/UIAlertController+TUICustomStyle.m b/iOS/TUIKit/TUIChat/CommonModel/UIAlertController+TUICustomStyle.m index 78368a212..60c8fa69b 100644 --- a/iOS/TUIKit/TUIChat/CommonModel/UIAlertController+TUICustomStyle.m +++ b/iOS/TUIKit/TUIChat/CommonModel/UIAlertController+TUICustomStyle.m @@ -54,10 +54,15 @@ CGFloat itemCount = 2; l.frame = CGRectMake(icon.frame.origin.x + icon.frame.size.width + padding + kScale390(15), 0, alertVCWidth * 0.5, itemHeight); l.text = items[i].title; l.font = [UIFont systemFontOfSize:17]; - l.textAlignment = NSTextAlignmentLeft; + l.textAlignment = isRTL()? NSTextAlignmentRight:NSTextAlignmentLeft; l.textColor = [UIColor systemBlueColor]; l.userInteractionEnabled = false; [itemView addSubview:l]; + + if (isRTL()) { + [icon resetFrameToFitRTL]; + [l resetFrameToFitRTL]; + } } } diff --git a/iOS/TUIKit/TUIChat/CommonUI/Camera/TUICameraView.m b/iOS/TUIKit/TUIChat/CommonUI/Camera/TUICameraView.m index 47302e65e..3fa596e81 100644 --- a/iOS/TUIKit/TUIChat/CommonUI/Camera/TUICameraView.m +++ b/iOS/TUIKit/TUIChat/CommonUI/Camera/TUICameraView.m @@ -112,6 +112,10 @@ static CGFloat gProgressLayerLineWidth = 5.0; self.switchCameraButton.frame = CGRectMake(self.contentView.bounds.size.width - switchCameraButtonWidth - 16.0, 30.0, switchCameraButtonWidth, switchCameraButtonWidth); + if (isRTL()) { + [self.switchCameraButton resetFrameToFitRTL]; + } + CGFloat photoBtnWidth = 100.0; self.photoBtn.frame = CGRectMake((self.contentView.bounds.size.width - photoBtnWidth) / 2.0, self.contentView.bounds.size.height - photoBtnWidth - 30, photoBtnWidth, photoBtnWidth); @@ -139,11 +143,15 @@ static CGFloat gProgressLayerLineWidth = 5.0; CGFloat closeButtonX = (self.photoBtn.frame.origin.x - closeButtonWidth) / 2.0; CGFloat closeButtonY = self.photoBtn.center.y - closeButtonWidth / 2.0; self.closeButton.frame = CGRectMake(closeButtonX, closeButtonY, closeButtonWidth, closeButtonWidth); - + if (isRTL()) { + [self.closeButton resetFrameToFitRTL]; + } CGFloat pictureButtonWidth = 30.0; self.pictureLibButton.frame = CGRectMake(self.contentView.frame.size.width - closeButtonX, closeButtonY, pictureButtonWidth, pictureButtonWidth); - + if (isRTL()) { + [self.pictureLibButton resetFrameToFitRTL]; + } self.slider.transform = CGAffineTransformMakeRotation(M_PI_2); self.slider.frame = CGRectMake(self.bounds.size.width - 50, 50, 15, 200); } @@ -348,7 +356,7 @@ static CGFloat gProgressLayerLineWidth = 5.0; if (!_closeButton) { _closeButton = [UIButton buttonWithType:UIButtonTypeCustom]; UIImage *closeButtonImage = [[TUIImageCache sharedInstance] getResourceFromCache:TUIChatImagePath(@"camera_back")]; - [_closeButton setBackgroundImage:closeButtonImage forState:UIControlStateNormal]; + [_closeButton setBackgroundImage:[closeButtonImage rtl_imageFlippedForRightToLeftLayoutDirection] forState:UIControlStateNormal]; [_closeButton addTarget:self action:@selector(closeButtonClick:) forControlEvents:UIControlEventTouchUpInside]; } return _closeButton; diff --git a/iOS/TUIKit/TUIChat/CommonUI/Camera/TUICaptureImagePreviewController.m b/iOS/TUIKit/TUIChat/CommonUI/Camera/TUICaptureImagePreviewController.m index 22075a231..8f10f0830 100644 --- a/iOS/TUIKit/TUIChat/CommonUI/Camera/TUICaptureImagePreviewController.m +++ b/iOS/TUIKit/TUIChat/CommonUI/Camera/TUICaptureImagePreviewController.m @@ -68,6 +68,11 @@ CGFloat cancelButtonX = commitButtonWidth; self.cancelButton.frame = CGRectMake(cancelButtonX, commitButtonY, commitButtonWidth, commitButtonWidth); + + if (isRTL()) { + [self.commitButton resetFrameToFitRTL]; + [self.cancelButton resetFrameToFitRTL]; + } } } diff --git a/iOS/TUIKit/TUIChat/CommonUI/Camera/TUICaptureVideoPreviewViewController.m b/iOS/TUIKit/TUIChat/CommonUI/Camera/TUICaptureVideoPreviewViewController.m index c48440f0e..2c340072a 100644 --- a/iOS/TUIKit/TUIChat/CommonUI/Camera/TUICaptureVideoPreviewViewController.m +++ b/iOS/TUIKit/TUIChat/CommonUI/Camera/TUICaptureVideoPreviewViewController.m @@ -54,7 +54,7 @@ self.cancelButton = [UIButton buttonWithType:UIButtonTypeCustom]; UIImage *cancelButtonBGImage = [[TUIImageCache sharedInstance] getResourceFromCache:TUIChatImagePath(@"camera_cancel")]; - [self.cancelButton setBackgroundImage:cancelButtonBGImage forState:UIControlStateNormal]; + [self.cancelButton setBackgroundImage:[cancelButtonBGImage rtl_imageFlippedForRightToLeftLayoutDirection] forState:UIControlStateNormal]; [self.cancelButton addTarget:self action:@selector(cancelButtonClick:) forControlEvents:UIControlEventTouchUpInside]; [self.view addSubview:self.cancelButton]; @@ -100,9 +100,13 @@ CGFloat commitButtonY = self.view.bounds.size.height - commitButtonWidth - 50.0; CGFloat commitButtonX = 2 * buttonDistance + commitButtonWidth; self.commitButton.frame = CGRectMake(commitButtonX, commitButtonY, commitButtonWidth, commitButtonWidth); - + CGFloat cancelButtonX = commitButtonWidth; self.cancelButton.frame = CGRectMake(cancelButtonX, commitButtonY, commitButtonWidth, commitButtonWidth); + if (isRTL()) { + [self.commitButton resetFrameToFitRTL]; + [self.cancelButton resetFrameToFitRTL]; + } } } diff --git a/iOS/TUIKit/TUIChat/CommonUI/Pop/TUIChatContextEmojiDetailController.m b/iOS/TUIKit/TUIChat/CommonUI/Pop/TUIChatContextEmojiDetailController.m index b1f7461c8..c47d42b52 100644 --- a/iOS/TUIKit/TUIChat/CommonUI/Pop/TUIChatContextEmojiDetailController.m +++ b/iOS/TUIKit/TUIChat/CommonUI/Pop/TUIChatContextEmojiDetailController.m @@ -122,6 +122,36 @@ self.containerView.frame.size.height - self.topGestureView.frame.size.height); } +- (NSArray *)getChatPopMenuQueue { + NSArray *emojis = [[NSUserDefaults standardUserDefaults] objectForKey:@"TUIChatPopMenuQueue"]; + if (emojis && [emojis isKindOfClass:[NSArray class]]) { + if (emojis.count > 0) { + return emojis; + } + } + return [NSArray arrayWithContentsOfFile:TUIChatFaceImagePath(@"emoji/emojiRecentDefaultList.plist")]; +} +- (void)updateRecentMenuQueue:(NSString *)faceName { + NSArray *emojis = [self getChatPopMenuQueue]; + NSMutableArray *muArray = [NSMutableArray arrayWithArray:emojis]; + + BOOL hasInQueue = NO; + for (NSDictionary *dic in emojis) { + NSString *name = [dic objectForKey:@"face_name"]; + if ([name isEqualToString:faceName]) { + hasInQueue = YES; + } + } + if (hasInQueue) { + return; + } + + [muArray removeObjectAtIndex:0]; + [muArray addObject:@{@"face_name" : faceName, @"face_id" : @""}]; + [[NSUserDefaults standardUserDefaults] setObject:muArray forKey:@"TUIChatPopMenuQueue"]; + [[NSUserDefaults standardUserDefaults] synchronize]; +} + - (void)faceView:(TUIFaceView *)faceView scrollToFaceGroupIndex:(NSInteger)index { } @@ -132,6 +162,7 @@ if (indexPath.section == 0) { NSString *faceName = face.name; NSLog(@"%@", faceName); + [self updateRecentMenuQueue:faceName]; [self dismissViewControllerAnimated:NO completion:nil]; if (self.reactClickCallback) { self.reactClickCallback(faceName); diff --git a/iOS/TUIKit/TUIChat/CommonUI/Pop/TUIChatPopContextController.m b/iOS/TUIKit/TUIChat/CommonUI/Pop/TUIChatPopContextController.m index bad4399b2..241687a5c 100644 --- a/iOS/TUIKit/TUIChat/CommonUI/Pop/TUIChatPopContextController.m +++ b/iOS/TUIKit/TUIChat/CommonUI/Pop/TUIChatPopContextController.m @@ -13,6 +13,7 @@ @interface TUIChatPopContextController () @property(nonatomic, strong) TUIChatPopContextRecentView *recentView; +@property(nonatomic, strong) UIView *alertContainerView; @property(nonatomic, strong) TUIMessageCell *alertView; @property(nonatomic, strong) TUIChatPopContextExtionView *extionView; @@ -113,9 +114,9 @@ // alertView [UIView animateWithDuration:0.3 animations:^{ - self.alertView.container.frame = - CGRectMake(self.originFrame.origin.x, self.recentView.frame.origin.y + kScale390(8) + self.recentView.frame.size.height, - self.originFrame.size.width, self.originFrame.size.height); + self.alertContainerView.frame = + CGRectMake(0, self.recentView.frame.origin.y + kScale390(8) + self.recentView.frame.size.height, + self.view.frame.size.width, self.originFrame.size.height); } completion:^(BOOL finished){ @@ -145,8 +146,7 @@ if (moveY != 0) { [UIView animateWithDuration:0.3 animations:^{ - self.alertView.container.frame = CGRectMake(self.originFrame.origin.x, self.originFrame.origin.y + moveY, - self.originFrame.size.width, self.originFrame.size.height); + self.alertContainerView.frame = CGRectMake(0, self.originFrame.origin.y + moveY, self.view.frame.size.width, self.originFrame.size.height); } completion:^(BOOL finished){ @@ -222,18 +222,29 @@ } - (void)configureAlertView { + self.alertContainerView = [[UIView alloc] init]; + [self.view addSubview:self.alertContainerView]; _alertView = [[self.alertCellClass alloc] init]; + [self.alertContainerView addSubview:_alertView]; _alertView.userInteractionEnabled = YES; if ([self.alertView isKindOfClass:NSClassFromString(@"TUIMergeMessageCell_Minimalist")]) { - _alertView.container.userInteractionEnabled = NO; + _alertView.userInteractionEnabled = NO; } - [self.view addSubview:_alertView.container]; - _alertView.translatesAutoresizingMaskIntoConstraints = NO; - [_alertView fillWithData:self.alertViewCellData]; [_alertView layoutIfNeeded]; - - _alertView.container.frame = _originFrame; + + self.alertContainerView.frame = CGRectMake(0, _originFrame.origin.y, self.view.frame.size.width, _originFrame.size.height); + _alertView.frame = CGRectMake(0, 0, self.alertContainerView.frame.size.width, self.alertContainerView.frame.size.height); + for (UIView *view in _alertView.contentView.subviews) { + if(view != _alertView.container) { + view.hidden = YES; + } + } + [_alertView.container mas_remakeConstraints:^(MASConstraintMaker *make) { + make.leading.mas_equalTo(_originFrame.origin.x); + make.top.mas_equalTo(0); + make.size.mas_equalTo(_originFrame.size); + }]; } - (void)configRecentView { @@ -400,8 +411,7 @@ [UIView animateWithDuration:0.3 animations:^{ - self.alertView.container.frame = - CGRectMake(self.originFrame.origin.x, self.originFrame.origin.y, self.originFrame.size.width, self.originFrame.size.height); + self.alertContainerView.frame = CGRectMake(0, self.originFrame.origin.y , self.view.frame.size.width, self.originFrame.size.height); } completion:^(BOOL finished) { if (finished) { diff --git a/iOS/TUIKit/TUIChat/CommonUI/Pop/TUIChatPopContextRecentView.m b/iOS/TUIKit/TUIChat/CommonUI/Pop/TUIChatPopContextRecentView.m index 51c180a72..cf194deb6 100644 --- a/iOS/TUIKit/TUIChat/CommonUI/Pop/TUIChatPopContextRecentView.m +++ b/iOS/TUIKit/TUIChat/CommonUI/Pop/TUIChatPopContextRecentView.m @@ -164,6 +164,11 @@ [self addSubview:self.arrowButton]; self.arrowButton.mm_width(kScale390(24)).mm_height(kScale390(24)).mm_right(margin).mm_top(kScale390(8)); + if (isRTL()) { + for (UIView *subview in self.subviews) { + [subview resetFrameToFitRTL]; + } + } } - (UIButton *)buttonWithCellImage:(UIImage *)img Tag:(NSInteger)tag { @@ -230,7 +235,7 @@ l.frame = CGRectMake(padding, 0, itemWidth * 0.5, itemHeight); l.text = self.item.title; l.font = item.titleFont ?: [UIFont systemFontOfSize:kScale390(16)]; - l.textAlignment = NSTextAlignmentLeft; + l.textAlignment = isRTL()? NSTextAlignmentRight:NSTextAlignmentLeft; l.textColor = item.titleColor ?: [UIColor blackColor]; l.userInteractionEnabled = false; [self addSubview:l]; @@ -249,6 +254,11 @@ [self addSubview:line]; } self.layer.masksToBounds = YES; + if (isRTL()) { + for (UIView *subview in self.subviews) { + [subview resetFrameToFitRTL]; + } + } } - (void)buttonclick { diff --git a/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/ReceiverTextNodeBkg@2x.png b/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/ReceiverTextNodeBkg@2x.png index 8766f785e..6ec18e153 100644 Binary files a/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/ReceiverTextNodeBkg@2x.png and b/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/ReceiverTextNodeBkg@2x.png differ diff --git a/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/ReceiverTextNodeBkg@3x.png b/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/ReceiverTextNodeBkg@3x.png index 8766f785e..6316fd6d6 100644 Binary files a/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/ReceiverTextNodeBkg@3x.png and b/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/ReceiverTextNodeBkg@3x.png differ diff --git a/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/ReceiverTextNodeBkgHL@2x.png b/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/ReceiverTextNodeBkgHL@2x.png index 8766f785e..6316fd6d6 100644 Binary files a/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/ReceiverTextNodeBkgHL@2x.png and b/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/ReceiverTextNodeBkgHL@2x.png differ diff --git a/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/ReceiverTextNodeBkgHL@3x.png b/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/ReceiverTextNodeBkgHL@3x.png index 8766f785e..6ec18e153 100644 Binary files a/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/ReceiverTextNodeBkgHL@3x.png and b/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/ReceiverTextNodeBkgHL@3x.png differ diff --git a/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/ReceiverTextNodeBkg_alpha20@2x.png b/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/ReceiverTextNodeBkg_alpha20@2x.png index b52221804..4bd14de7a 100644 Binary files a/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/ReceiverTextNodeBkg_alpha20@2x.png and b/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/ReceiverTextNodeBkg_alpha20@2x.png differ diff --git a/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/ReceiverTextNodeBkg_alpha20@3x.png b/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/ReceiverTextNodeBkg_alpha20@3x.png index b52221804..4bd14de7a 100644 Binary files a/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/ReceiverTextNodeBkg_alpha20@3x.png and b/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/ReceiverTextNodeBkg_alpha20@3x.png differ diff --git a/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/ReceiverTextNodeBkg_alpha50@2x.png b/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/ReceiverTextNodeBkg_alpha50@2x.png index c108f762e..6b0a8a120 100644 Binary files a/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/ReceiverTextNodeBkg_alpha50@2x.png and b/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/ReceiverTextNodeBkg_alpha50@2x.png differ diff --git a/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/ReceiverTextNodeBkg_alpha50@3x.png b/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/ReceiverTextNodeBkg_alpha50@3x.png index c108f762e..6b0a8a120 100644 Binary files a/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/ReceiverTextNodeBkg_alpha50@3x.png and b/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/ReceiverTextNodeBkg_alpha50@3x.png differ diff --git a/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/SenderTextNodeBkg@2x.png b/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/SenderTextNodeBkg@2x.png index 0f1b7bf6c..b5fbcd8d0 100644 Binary files a/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/SenderTextNodeBkg@2x.png and b/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/SenderTextNodeBkg@2x.png differ diff --git a/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/SenderTextNodeBkg@3x.png b/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/SenderTextNodeBkg@3x.png index 0f1b7bf6c..b5fbcd8d0 100644 Binary files a/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/SenderTextNodeBkg@3x.png and b/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/SenderTextNodeBkg@3x.png differ diff --git a/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/SenderTextNodeBkgHL@2x.png b/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/SenderTextNodeBkgHL@2x.png index 0f1b7bf6c..b5fbcd8d0 100644 Binary files a/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/SenderTextNodeBkgHL@2x.png and b/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/SenderTextNodeBkgHL@2x.png differ diff --git a/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/SenderTextNodeBkgHL@3x.png b/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/SenderTextNodeBkgHL@3x.png index 0f1b7bf6c..b5fbcd8d0 100644 Binary files a/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/SenderTextNodeBkgHL@3x.png and b/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/SenderTextNodeBkgHL@3x.png differ diff --git a/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/SenderTextNodeBkg_alpha20@2x.png b/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/SenderTextNodeBkg_alpha20@2x.png index 5b8cb8b87..611b1a996 100644 Binary files a/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/SenderTextNodeBkg_alpha20@2x.png and b/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/SenderTextNodeBkg_alpha20@2x.png differ diff --git a/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/SenderTextNodeBkg_alpha20@3x.png b/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/SenderTextNodeBkg_alpha20@3x.png index 5b8cb8b87..611b1a996 100644 Binary files a/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/SenderTextNodeBkg_alpha20@3x.png and b/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/SenderTextNodeBkg_alpha20@3x.png differ diff --git a/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/SenderTextNodeBkg_alpha50@2x.png b/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/SenderTextNodeBkg_alpha50@2x.png index c2954e158..a3aaca417 100644 Binary files a/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/SenderTextNodeBkg_alpha50@2x.png and b/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/SenderTextNodeBkg_alpha50@2x.png differ diff --git a/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/SenderTextNodeBkg_alpha50@3x.png b/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/SenderTextNodeBkg_alpha50@3x.png index c2954e158..a3aaca417 100644 Binary files a/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/SenderTextNodeBkg_alpha50@3x.png and b/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/SenderTextNodeBkg_alpha50@3x.png differ diff --git a/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/ToolViewEmotion@2x.png b/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/ToolViewEmotion@2x.png index dfea3ade9..0e6834e39 100644 Binary files a/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/ToolViewEmotion@2x.png and b/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/ToolViewEmotion@2x.png differ diff --git a/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/ToolViewEmotion@3x.png b/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/ToolViewEmotion@3x.png index d202f4a66..269e654d6 100644 Binary files a/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/ToolViewEmotion@3x.png and b/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/ToolViewEmotion@3x.png differ diff --git a/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/ToolViewEmotionHL@2x.png b/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/ToolViewEmotionHL@2x.png index dfea3ade9..5fd107f5a 100644 Binary files a/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/ToolViewEmotionHL@2x.png and b/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/ToolViewEmotionHL@2x.png differ diff --git a/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/ToolViewEmotionHL@3x.png b/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/ToolViewEmotionHL@3x.png index d202f4a66..269e654d6 100644 Binary files a/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/ToolViewEmotionHL@3x.png and b/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/ToolViewEmotionHL@3x.png differ diff --git a/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/ToolViewInputVoice@2x.png b/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/ToolViewInputVoice@2x.png index cefbff3df..40cb04c74 100644 Binary files a/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/ToolViewInputVoice@2x.png and b/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/ToolViewInputVoice@2x.png differ diff --git a/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/ToolViewInputVoice@3x.png b/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/ToolViewInputVoice@3x.png index aa696b69f..8907870ff 100644 Binary files a/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/ToolViewInputVoice@3x.png and b/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/ToolViewInputVoice@3x.png differ diff --git a/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/ToolViewInputVoiceHL@2x.png b/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/ToolViewInputVoiceHL@2x.png index cefbff3df..932f12689 100644 Binary files a/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/ToolViewInputVoiceHL@2x.png and b/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/ToolViewInputVoiceHL@2x.png differ diff --git a/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/ToolViewInputVoiceHL@3x.png b/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/ToolViewInputVoiceHL@3x.png index aa696b69f..8907870ff 100644 Binary files a/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/ToolViewInputVoiceHL@3x.png and b/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/ToolViewInputVoiceHL@3x.png differ diff --git a/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/ToolViewKeyboard@3x.png b/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/ToolViewKeyboard@3x.png index 316e9d8b3..b37face07 100644 Binary files a/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/ToolViewKeyboard@3x.png and b/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/ToolViewKeyboard@3x.png differ diff --git a/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/TypeSelectorBtnHL_Black@2x.png b/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/TypeSelectorBtnHL_Black@2x.png index f4225d888..7402fbace 100644 Binary files a/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/TypeSelectorBtnHL_Black@2x.png and b/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/TypeSelectorBtnHL_Black@2x.png differ diff --git a/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/TypeSelectorBtnHL_Black@3x.png b/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/TypeSelectorBtnHL_Black@3x.png index 91865b35f..766619785 100644 Binary files a/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/TypeSelectorBtnHL_Black@3x.png and b/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/TypeSelectorBtnHL_Black@3x.png differ diff --git a/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/TypeSelectorBtn_Black@2x.png b/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/TypeSelectorBtn_Black@2x.png index f4225d888..16d5cd7f2 100644 Binary files a/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/TypeSelectorBtn_Black@2x.png and b/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/TypeSelectorBtn_Black@2x.png differ diff --git a/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/TypeSelectorBtn_Black@3x.png b/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/TypeSelectorBtn_Black@3x.png index 91865b35f..36ef45901 100644 Binary files a/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/TypeSelectorBtn_Black@3x.png and b/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/TypeSelectorBtn_Black@3x.png differ diff --git a/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/audio_call.png b/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/audio_call.png index 496ebf549..0bec747f4 100644 Binary files a/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/audio_call.png and b/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/audio_call.png differ diff --git a/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/audio_call@2x.png b/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/audio_call@2x.png index fe53c6998..5fe62dc7e 100644 Binary files a/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/audio_call@2x.png and b/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/audio_call@2x.png differ diff --git a/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/audio_call@3x.png b/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/audio_call@3x.png index 43ebc6a12..60cdc3819 100644 Binary files a/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/audio_call@3x.png and b/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/audio_call@3x.png differ diff --git a/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/back@3x.png b/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/back@3x.png index 069f4b13d..feed5cbeb 100644 Binary files a/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/back@3x.png and b/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/back@3x.png differ diff --git a/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/camer_commit@2x.png b/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/camer_commit@2x.png index dd1b34830..7f203a2f0 100644 Binary files a/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/camer_commit@2x.png and b/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/camer_commit@2x.png differ diff --git a/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/camer_commit@3x.png b/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/camer_commit@3x.png index ad25b85e1..86d7d9346 100644 Binary files a/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/camer_commit@3x.png and b/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/camer_commit@3x.png differ diff --git a/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/camer_commitBg@2x.png b/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/camer_commitBg@2x.png index bee7df823..33e1f94dc 100644 Binary files a/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/camer_commitBg@2x.png and b/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/camer_commitBg@2x.png differ diff --git a/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/camer_commitBg@3x.png b/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/camer_commitBg@3x.png index 394aa39cd..7d8332bf1 100644 Binary files a/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/camer_commitBg@3x.png and b/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/camer_commitBg@3x.png differ diff --git a/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/camera_back@2x.png b/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/camera_back@2x.png index da3dad58c..0733c38e4 100644 Binary files a/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/camera_back@2x.png and b/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/camera_back@2x.png differ diff --git a/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/camera_back@3x.png b/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/camera_back@3x.png index 22927db1e..36423bb32 100644 Binary files a/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/camera_back@3x.png and b/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/camera_back@3x.png differ diff --git a/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/camera_cancel@2x.png b/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/camera_cancel@2x.png index c1cd7864b..c4de9f419 100644 Binary files a/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/camera_cancel@2x.png and b/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/camera_cancel@2x.png differ diff --git a/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/camera_cancel@3x.png b/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/camera_cancel@3x.png index 4d2db351d..91a22c68d 100644 Binary files a/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/camera_cancel@3x.png and b/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/camera_cancel@3x.png differ diff --git a/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/camera_switchCamera@2x.png b/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/camera_switchCamera@2x.png index dae652ec8..2c60cdcce 100644 Binary files a/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/camera_switchCamera@2x.png and b/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/camera_switchCamera@2x.png differ diff --git a/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/camera_switchCamera@3x.png b/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/camera_switchCamera@3x.png index c2498bc64..935a57eb2 100644 Binary files a/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/camera_switchCamera@3x.png and b/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/camera_switchCamera@3x.png differ diff --git a/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/chat_more_group_live@3x.png b/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/chat_more_group_live@3x.png index 605035498..03b40dbb5 100644 Binary files a/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/chat_more_group_live@3x.png and b/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/chat_more_group_live@3x.png differ diff --git a/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/chat_more_link_img@2x.png b/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/chat_more_link_img@2x.png index 0d7795b6e..2442a3f01 100644 Binary files a/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/chat_more_link_img@2x.png and b/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/chat_more_link_img@2x.png differ diff --git a/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/chat_more_link_img@3x.png b/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/chat_more_link_img@3x.png index 2e7b20f12..09ee4f102 100644 Binary files a/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/chat_more_link_img@3x.png and b/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/chat_more_link_img@3x.png differ diff --git a/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/chat_nav_more_menu@3x.png b/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/chat_nav_more_menu@3x.png index 84b00e342..3dabae0da 100644 Binary files a/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/chat_nav_more_menu@3x.png and b/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/chat_nav_more_menu@3x.png differ diff --git a/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/chat_reference_guide@2x.png b/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/chat_reference_guide@2x.png index b15393390..8c6b4f4db 100644 Binary files a/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/chat_reference_guide@2x.png and b/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/chat_reference_guide@2x.png differ diff --git a/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/chat_reply_guide@2x.png b/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/chat_reply_guide@2x.png index be44c5a1a..5744e3e9b 100644 Binary files a/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/chat_reply_guide@2x.png and b/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/chat_reply_guide@2x.png differ diff --git a/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/download.png b/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/download.png index 4a61619f8..80237a25b 100644 Binary files a/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/download.png and b/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/download.png differ diff --git a/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/download2x.png b/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/download2x.png index 6f0529df2..30218df8e 100644 Binary files a/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/download2x.png and b/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/download2x.png differ diff --git a/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/download@3x.png b/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/download@3x.png index 568d0fc1a..809770a56 100644 Binary files a/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/download@3x.png and b/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/download@3x.png differ diff --git a/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/drop_down.png b/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/drop_down.png index e271a1b29..96b989fb4 100644 Binary files a/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/drop_down.png and b/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/drop_down.png differ diff --git a/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/drop_down@2x.png b/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/drop_down@2x.png index 27cfee88b..f4fbb44b9 100644 Binary files a/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/drop_down@2x.png and b/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/drop_down@2x.png differ diff --git a/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/drop_down@3x.png b/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/drop_down@3x.png index 1d5312211..6623a0fb2 100644 Binary files a/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/drop_down@3x.png and b/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/drop_down@3x.png differ diff --git a/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/emojiArrowDown@2x.png b/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/emojiArrowDown@2x.png index ea98c763b..d7bb485a1 100644 Binary files a/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/emojiArrowDown@2x.png and b/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/emojiArrowDown@2x.png differ diff --git a/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/emojiArrowUp@2x.png b/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/emojiArrowUp@2x.png index 79e819467..8647b9c53 100644 Binary files a/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/emojiArrowUp@2x.png and b/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/emojiArrowUp@2x.png differ diff --git a/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/file_icon_download@2x.png b/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/file_icon_download@2x.png index f440bd578..2384455d1 100644 Binary files a/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/file_icon_download@2x.png and b/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/file_icon_download@2x.png differ diff --git a/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/group_live@2x.png b/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/group_live@2x.png index 532a8b85c..7eb3e0549 100644 Binary files a/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/group_live@2x.png and b/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/group_live@2x.png differ diff --git a/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/icon_close.png b/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/icon_close.png index 8d03206af..bdd8a162a 100644 Binary files a/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/icon_close.png and b/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/icon_close.png differ diff --git a/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/icon_close@2x.png b/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/icon_close@2x.png index 142912ce4..8b0eb924e 100644 Binary files a/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/icon_close@2x.png and b/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/icon_close@2x.png differ diff --git a/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/icon_close@3x.png b/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/icon_close@3x.png index 606a272cb..bb808c4a4 100644 Binary files a/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/icon_close@3x.png and b/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/icon_close@3x.png differ diff --git a/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/icon_convert_voice_to_text@2x.png b/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/icon_convert_voice_to_text@2x.png new file mode 100644 index 000000000..d8c352861 Binary files /dev/null and b/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/icon_convert_voice_to_text@2x.png differ diff --git a/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/icon_convert_voice_to_text@3x.png b/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/icon_convert_voice_to_text@3x.png new file mode 100644 index 000000000..ad1ea0600 Binary files /dev/null and b/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/icon_convert_voice_to_text@3x.png differ diff --git a/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/icon_copy@2x.png b/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/icon_copy@2x.png index 279139798..8274c335b 100644 Binary files a/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/icon_copy@2x.png and b/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/icon_copy@2x.png differ diff --git a/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/icon_copy@3x.png b/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/icon_copy@3x.png index f3d51c524..474cf1798 100644 Binary files a/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/icon_copy@3x.png and b/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/icon_copy@3x.png differ diff --git a/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/icon_delete@2x.png b/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/icon_delete@2x.png index 6cf633142..4bf52c2ee 100644 Binary files a/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/icon_delete@2x.png and b/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/icon_delete@2x.png differ diff --git a/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/icon_delete@3x.png b/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/icon_delete@3x.png index 402d75e0f..1efd12002 100644 Binary files a/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/icon_delete@3x.png and b/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/icon_delete@3x.png differ diff --git a/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/icon_forward@2x.png b/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/icon_forward@2x.png index d9092cf4f..e8ec071b3 100644 Binary files a/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/icon_forward@2x.png and b/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/icon_forward@2x.png differ diff --git a/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/icon_forward@3x.png b/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/icon_forward@3x.png index 55dfecaeb..813fb1fc6 100644 Binary files a/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/icon_forward@3x.png and b/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/icon_forward@3x.png differ diff --git a/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/icon_handset@3x.png b/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/icon_handset@3x.png new file mode 100644 index 000000000..04232aabf Binary files /dev/null and b/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/icon_handset@3x.png differ diff --git a/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/icon_hide@2x.png b/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/icon_hide@2x.png index 866fa04f1..876e0df0f 100644 Binary files a/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/icon_hide@2x.png and b/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/icon_hide@2x.png differ diff --git a/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/icon_hide@3x.png b/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/icon_hide@3x.png index 0566f314f..9336e6663 100644 Binary files a/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/icon_hide@3x.png and b/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/icon_hide@3x.png differ diff --git a/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/icon_loudspeaker@3x.png b/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/icon_loudspeaker@3x.png new file mode 100644 index 000000000..07bf9aab3 Binary files /dev/null and b/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/icon_loudspeaker@3x.png differ diff --git a/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/icon_multi@2x.png b/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/icon_multi@2x.png index c6fc8fe2e..8f85e9473 100644 Binary files a/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/icon_multi@2x.png and b/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/icon_multi@2x.png differ diff --git a/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/icon_multi@3x.png b/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/icon_multi@3x.png index 8f78515aa..2edf568aa 100644 Binary files a/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/icon_multi@3x.png and b/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/icon_multi@3x.png differ diff --git a/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/icon_recall@2x.png b/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/icon_recall@2x.png index 419a18788..c7d91ca0d 100644 Binary files a/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/icon_recall@2x.png and b/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/icon_recall@2x.png differ diff --git a/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/icon_recall@3x.png b/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/icon_recall@3x.png index bced43714..e02a66be0 100644 Binary files a/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/icon_recall@3x.png and b/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/icon_recall@3x.png differ diff --git a/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/icon_reference@2x.png b/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/icon_reference@2x.png index 1a5cc333f..4dbac64ae 100644 Binary files a/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/icon_reference@2x.png and b/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/icon_reference@2x.png differ diff --git a/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/icon_reference@3x.png b/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/icon_reference@3x.png index eea853186..a1ac9e7df 100644 Binary files a/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/icon_reference@3x.png and b/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/icon_reference@3x.png differ diff --git a/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/icon_reply@2x.png b/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/icon_reply@2x.png index d2c9a3a0c..a7f080755 100644 Binary files a/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/icon_reply@2x.png and b/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/icon_reply@2x.png differ diff --git a/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/icon_reply@3x.png b/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/icon_reply@3x.png index 422ca0b05..5cbb972f4 100644 Binary files a/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/icon_reply@3x.png and b/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/icon_reply@3x.png differ diff --git a/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/icon_translate@2x.png b/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/icon_translate@2x.png index 0ddaef6d9..2fc93ba53 100644 Binary files a/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/icon_translate@2x.png and b/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/icon_translate@2x.png differ diff --git a/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/icon_translate@3x.png b/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/icon_translate@3x.png index 2ae4e9ba8..72bede4bf 100644 Binary files a/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/icon_translate@3x.png and b/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/icon_translate@3x.png differ diff --git a/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/message_custom_evaluation@2x.png b/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/message_custom_evaluation@2x.png index c7ec78845..fae0cfd1b 100644 Binary files a/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/message_custom_evaluation@2x.png and b/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/message_custom_evaluation@2x.png differ diff --git a/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/message_custom_evaluation@3x.png b/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/message_custom_evaluation@3x.png index de1234d69..b6b283cf4 100644 Binary files a/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/message_custom_evaluation@3x.png and b/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/message_custom_evaluation@3x.png differ diff --git a/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/message_custom_order@2x.png b/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/message_custom_order@2x.png index 8fd3942ba..9a58ca988 100644 Binary files a/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/message_custom_order@2x.png and b/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/message_custom_order@2x.png differ diff --git a/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/message_custom_order@3x.png b/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/message_custom_order@3x.png index ba1188433..bc5a4c59d 100644 Binary files a/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/message_custom_order@3x.png and b/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/message_custom_order@3x.png differ diff --git a/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/message_voice_receiver_normal@2x.png b/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/message_voice_receiver_normal@2x.png index 3ca551ba1..487036cab 100644 Binary files a/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/message_voice_receiver_normal@2x.png and b/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/message_voice_receiver_normal@2x.png differ diff --git a/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/message_voice_receiver_normal@3x.png b/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/message_voice_receiver_normal@3x.png index 2407ace48..32a68b04f 100644 Binary files a/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/message_voice_receiver_normal@3x.png and b/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/message_voice_receiver_normal@3x.png differ diff --git a/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/message_voice_receiver_playing_1@2x.png b/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/message_voice_receiver_playing_1@2x.png index 27a0abdf0..ff26e7163 100755 Binary files a/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/message_voice_receiver_playing_1@2x.png and b/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/message_voice_receiver_playing_1@2x.png differ diff --git a/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/message_voice_sender_normal@2x.png b/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/message_voice_sender_normal@2x.png index e6828fdc7..5771bc60b 100644 Binary files a/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/message_voice_sender_normal@2x.png and b/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/message_voice_sender_normal@2x.png differ diff --git a/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/message_voice_sender_normal@3x.png b/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/message_voice_sender_normal@3x.png index 98c856972..9394328b0 100644 Binary files a/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/message_voice_sender_normal@3x.png and b/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/message_voice_sender_normal@3x.png differ diff --git a/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/message_voice_sender_playing_2@2x.png b/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/message_voice_sender_playing_2@2x.png index 350d3884d..03f3aa78d 100755 Binary files a/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/message_voice_sender_playing_2@2x.png and b/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/message_voice_sender_playing_2@2x.png differ diff --git a/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/message_voice_sender_playing_2@3x.png b/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/message_voice_sender_playing_2@3x.png index 4eaad525a..89865a8dd 100755 Binary files a/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/message_voice_sender_playing_2@3x.png and b/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/message_voice_sender_playing_2@3x.png differ diff --git a/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/more_camera@2x.png b/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/more_camera@2x.png index e9742b038..d9c8828d5 100644 Binary files a/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/more_camera@2x.png and b/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/more_camera@2x.png differ diff --git a/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/more_camera@3x.png b/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/more_camera@3x.png index f201c4fe8..e6a9d319d 100644 Binary files a/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/more_camera@3x.png and b/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/more_camera@3x.png differ diff --git a/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/more_file@2x.png b/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/more_file@2x.png index ca99c61a0..5efd667cc 100644 Binary files a/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/more_file@2x.png and b/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/more_file@2x.png differ diff --git a/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/more_file@3x.png b/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/more_file@3x.png index ad2ff712e..5d4f807df 100644 Binary files a/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/more_file@3x.png and b/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/more_file@3x.png differ diff --git a/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/more_groupnote@2x.png b/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/more_groupnote@2x.png index 6e09e1e02..a8774392a 100644 Binary files a/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/more_groupnote@2x.png and b/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/more_groupnote@2x.png differ diff --git a/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/more_groupnote@3x.png b/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/more_groupnote@3x.png index acc41a783..8fb611a9e 100644 Binary files a/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/more_groupnote@3x.png and b/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/more_groupnote@3x.png differ diff --git a/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/more_picture@2x.png b/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/more_picture@2x.png index 97042fc7f..cc2817fbf 100644 Binary files a/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/more_picture@2x.png and b/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/more_picture@2x.png differ diff --git a/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/more_picture@3x.png b/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/more_picture@3x.png index 09f26ea43..88fd7579d 100644 Binary files a/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/more_picture@3x.png and b/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/more_picture@3x.png differ diff --git a/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/more_poll@2x.png b/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/more_poll@2x.png index c90a74d45..cbe92506a 100644 Binary files a/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/more_poll@2x.png and b/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/more_poll@2x.png differ diff --git a/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/more_poll@3x.png b/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/more_poll@3x.png index be52e9a1b..addad7591 100644 Binary files a/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/more_poll@3x.png and b/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/more_poll@3x.png differ diff --git a/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/more_video@2x.png b/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/more_video@2x.png index f153cd288..6665734da 100644 Binary files a/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/more_video@2x.png and b/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/more_video@2x.png differ diff --git a/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/more_video@3x.png b/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/more_video@3x.png index 4d41ed8b2..f9714116a 100644 Binary files a/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/more_video@3x.png and b/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/more_video@3x.png differ diff --git a/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/more_video_call@2x.png b/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/more_video_call@2x.png index f153cd288..6665734da 100644 Binary files a/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/more_video_call@2x.png and b/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/more_video_call@2x.png differ diff --git a/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/more_video_call@3x.png b/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/more_video_call@3x.png index 4d41ed8b2..f9714116a 100644 Binary files a/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/more_video_call@3x.png and b/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/more_video_call@3x.png differ diff --git a/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/more_voice_call@2x.png b/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/more_voice_call@2x.png index 0c9e81498..d847912eb 100644 Binary files a/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/more_voice_call@2x.png and b/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/more_voice_call@2x.png differ diff --git a/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/more_voice_call@3x.png b/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/more_voice_call@3x.png index 4c0455089..f333fe9ed 100644 Binary files a/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/more_voice_call@3x.png and b/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/more_voice_call@3x.png differ diff --git a/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/msg_error@2x.png b/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/msg_error@2x.png index 9ad140657..38ab5e071 100644 Binary files a/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/msg_error@2x.png and b/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/msg_error@2x.png differ diff --git a/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/msg_error@3x.png b/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/msg_error@3x.png index 7c8d19954..f725d7635 100644 Binary files a/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/msg_error@3x.png and b/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/msg_error@3x.png differ diff --git a/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/msg_file@2x.png b/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/msg_file@2x.png index d66bbe462..240180c7f 100644 Binary files a/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/msg_file@2x.png and b/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/msg_file@2x.png differ diff --git a/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/msg_file@3x.png b/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/msg_file@3x.png index 7676fa71b..169bf0ab0 100644 Binary files a/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/msg_file@3x.png and b/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/msg_file@3x.png differ diff --git a/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/msg_file_p@2x.png b/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/msg_file_p@2x.png index cc6286fe0..08d61a196 100644 Binary files a/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/msg_file_p@2x.png and b/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/msg_file_p@2x.png differ diff --git a/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/play_normal@2x.png b/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/play_normal@2x.png index 15957a982..affe5cc6b 100644 Binary files a/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/play_normal@2x.png and b/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/play_normal@2x.png differ diff --git a/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/play_normal@3x.png b/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/play_normal@3x.png index 9c7c3abcb..e2d0e9ad4 100644 Binary files a/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/play_normal@3x.png and b/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/play_normal@3x.png differ diff --git a/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/pull_up.png b/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/pull_up.png index 0a6d5f67f..faf2f2c85 100644 Binary files a/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/pull_up.png and b/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/pull_up.png differ diff --git a/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/pull_up@2x.png b/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/pull_up@2x.png index d532cf535..ecbc9714e 100644 Binary files a/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/pull_up@2x.png and b/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/pull_up@2x.png differ diff --git a/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/pull_up@3x.png b/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/pull_up@3x.png index e4a0d03c0..6fb5d12d8 100644 Binary files a/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/pull_up@3x.png and b/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/pull_up@3x.png differ diff --git a/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/receiver_voice_play_1@2x.png b/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/receiver_voice_play_1@2x.png index 27a0abdf0..ff26e7163 100644 Binary files a/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/receiver_voice_play_1@2x.png and b/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/receiver_voice_play_1@2x.png differ diff --git a/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/record_1@2x.png b/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/record_1@2x.png index 769f0d26a..3a67e8029 100644 Binary files a/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/record_1@2x.png and b/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/record_1@2x.png differ diff --git a/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/record_2@2x.png b/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/record_2@2x.png index 64bd92171..f9f536c34 100644 Binary files a/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/record_2@2x.png and b/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/record_2@2x.png differ diff --git a/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/record_3@2x.png b/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/record_3@2x.png index c1840f497..37950147e 100644 Binary files a/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/record_3@2x.png and b/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/record_3@2x.png differ diff --git a/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/record_4@2x.png b/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/record_4@2x.png index 8a235ee73..d32afd7aa 100644 Binary files a/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/record_4@2x.png and b/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/record_4@2x.png differ diff --git a/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/record_5@2x.png b/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/record_5@2x.png index da138b24f..a7cf7eceb 100644 Binary files a/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/record_5@2x.png and b/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/record_5@2x.png differ diff --git a/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/record_6@2x.png b/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/record_6@2x.png index 86ec3d8ed..6dd838ca5 100644 Binary files a/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/record_6@2x.png and b/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/record_6@2x.png differ diff --git a/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/record_7@2x.png b/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/record_7@2x.png index 77797533a..5343dbb1f 100644 Binary files a/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/record_7@2x.png and b/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/record_7@2x.png differ diff --git a/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/record_8@2x.png b/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/record_8@2x.png index b9987df90..5cd62a795 100644 Binary files a/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/record_8@2x.png and b/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/record_8@2x.png differ diff --git a/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/thumb_1.png b/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/thumb_1.png index 201e79306..46b9bac70 100644 Binary files a/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/thumb_1.png and b/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/thumb_1.png differ diff --git a/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/video_call.png b/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/video_call.png index 16cc2b373..7e29fb5d0 100644 Binary files a/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/video_call.png and b/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/video_call.png differ diff --git a/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/video_call2x.png b/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/video_call2x.png index 109f429c5..2347d0c6d 100644 Binary files a/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/video_call2x.png and b/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/video_call2x.png differ diff --git a/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/video_call@3x.png b/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/video_call@3x.png index b36fadaa7..46217a257 100644 Binary files a/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/video_call@3x.png and b/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/video_call@3x.png differ diff --git a/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/video_call_self.png b/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/video_call_self.png index 097f4295e..113361e8b 100644 Binary files a/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/video_call_self.png and b/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/video_call_self.png differ diff --git a/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/video_call_self@2x.png b/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/video_call_self@2x.png index a304fd07b..dce1a6c3a 100644 Binary files a/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/video_call_self@2x.png and b/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/video_call_self@2x.png differ diff --git a/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/video_call_self@3x.png b/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/video_call_self@3x.png index 608e36fb7..5e8cd8a5c 100644 Binary files a/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/video_call_self@3x.png and b/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/video_call_self@3x.png differ diff --git a/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/video_close.png b/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/video_close.png index 8d0b67480..96bdf19dc 100644 Binary files a/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/video_close.png and b/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/video_close.png differ diff --git a/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/video_close@2x.png b/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/video_close@2x.png index 7392796ce..3a97de97b 100644 Binary files a/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/video_close@2x.png and b/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/video_close@2x.png differ diff --git a/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/video_close@3x.png b/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/video_close@3x.png index 026a38558..d5ed488ff 100644 Binary files a/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/video_close@3x.png and b/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/video_close@3x.png differ diff --git a/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/video_pause.png b/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/video_pause.png index 419b55cb8..3cb874c66 100644 Binary files a/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/video_pause.png and b/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/video_pause.png differ diff --git a/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/video_pause@2x.png b/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/video_pause@2x.png index 45f2f1f46..9f2d319f1 100644 Binary files a/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/video_pause@2x.png and b/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/video_pause@2x.png differ diff --git a/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/video_pause@3x.png b/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/video_pause@3x.png index 6db10672c..f56485587 100644 Binary files a/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/video_pause@3x.png and b/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/video_pause@3x.png differ diff --git a/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/video_play.png b/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/video_play.png index 7e1687491..3e0fa9baf 100644 Binary files a/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/video_play.png and b/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/video_play.png differ diff --git a/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/video_play2x.png b/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/video_play2x.png index ba47d63e8..da45ddf6c 100644 Binary files a/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/video_play2x.png and b/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/video_play2x.png differ diff --git a/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/video_play@3x.png b/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/video_play@3x.png index 3bbf19e42..4eaa5a3c4 100644 Binary files a/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/video_play@3x.png and b/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/video_play@3x.png differ diff --git a/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/video_play_big.png b/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/video_play_big.png index d70fe3d4f..f71a00add 100644 Binary files a/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/video_play_big.png and b/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/video_play_big.png differ diff --git a/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/video_play_big@2x.png b/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/video_play_big@2x.png index 494b7d468..9ca951550 100644 Binary files a/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/video_play_big@2x.png and b/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/video_play_big@2x.png differ diff --git a/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/video_play_big@3x.png b/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/video_play_big@3x.png index e26c4c773..6cf690370 100644 Binary files a/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/video_play_big@3x.png and b/iOS/TUIKit/TUIChat/Resources/TUIChat.bundle/video_play_big@3x.png differ diff --git a/iOS/TUIKit/TUIChat/Resources/TUIChatFace.bundle/Localizable/ar.lproj/Localizable.strings b/iOS/TUIKit/TUIChat/Resources/TUIChatFace.bundle/Localizable/ar.lproj/Localizable.strings new file mode 100644 index 000000000..65b37d5b4 --- /dev/null +++ b/iOS/TUIKit/TUIChat/Resources/TUIChatFace.bundle/Localizable/ar.lproj/Localizable.strings @@ -0,0 +1,140 @@ +"[龇牙]" = "[ابتسامة متكلسة]"; +"[调皮]" = "[مشاغب]"; +"[流汗]" = "[تعرق]"; +"[偷笑]" = "[ضحكة مستحية]"; +"[再见]" = "[وداعاً]"; +"[敲打]" = "[ضرب]"; +"[擦汗]" = "[مسح العرق]"; +"[猪头]" = "[رأس خنزير]"; +"[玫瑰]" = "[وردة]"; +"[流泪]" = "[دموع]"; +"[大哭]" = "[بكاء]"; +"[嘘]" = "[تصريح سري]"; +"[酷]" = "[رائع]"; +"[抓狂]" = "[جنون]"; +"[委屈]" = "[مظلوم]"; +"[便便]" = "[براز]"; +"[炸弹]" = "[قنبلة]"; +"[菜刀]" = "[سكين مطبخ]"; +"[可爱]" = "[جميل]"; +"[色]" = "[مثير]"; +"[害羞]" = "[خجول]"; +"[得意]" = "[فخور]"; +"[吐]" = "[قيء]"; +"[微笑]" = "[ابتسامة]"; +"[怒]" = "[غضب]"; +"[尴尬]" = "[محرج]"; +"[惊恐]" = "[صدمة]"; +"[冷汗]" = "[عرق بارد]"; +"[爱心]" = "[قلب محبوب]"; +"[示爱]" = "[إظهار الحب]"; +"[白眼]" = "[عين بيضاء]"; +"[傲慢]" = "[غطرسة]"; +"[难过]" = "[حزين]"; +"[惊讶]" = "[مفاجأة]"; +"[疑问]" = "[استفهام]"; +"[困]" = "[تعب]"; +"[么么哒]" = "[قبلة]"; + +"[憨笑]" = "[ابتسامة طفولية]"; +"[爱情]" = "[حب]"; +"[衰]" = "[فاشل]"; +"[撇嘴]" = "[تجاهل]"; +"[阴险]" = "[غدر]"; +"[奋斗]" = "[مكافحة]"; +"[发呆]" = "[تفكير]"; +"[右哼哼]" = "[تذمر]"; +"[抱抱]" = "[عناق]"; +"[坏笑]" = "[ابتسامة شريرة]"; +"[飞吻]" = "[قبلة جوائز]"; +"[鄙视]" = "[ازدراء]"; +"[晕]" = "[دوار]"; +"[大兵]" = "[جندي]"; +"[可怜]" = "[مؤسف]"; +"[强]" = "[قوة]"; +"[弱]" = "[ضعف]"; +"[握手]" = "[مصافحة]"; +"[胜利]" = "[انتصار]"; +"[抱拳]" = "[تحية بالقبضة]"; +"[凋谢]" = "[ذبول]"; +"[米饭]" = "[أرز]"; +"[蛋糕]" = "[كعكة]"; +"[西瓜]" = "[بطيخ]"; +"[啤酒]" = "[بيرة]"; +"[瓢虫]" = "[دعسوقة]"; +"[勾引]" = "[اغراء]"; +"[OK]" = "[موافق]"; +"[爱你]" = "[أحبك]"; +"[咖啡]" = "[قهوة]"; +"[月亮]" = "[قمر]"; +"[刀]" = "[سكين]"; +"[发抖]" = "[رجفة]"; +"[差劲]" = "[سيء]"; +"[拳头]" = "[قبضة]"; +"[心碎了]" = "[قلب مكسور]"; +"[太阳]" = "[شمس]"; +"[礼物]" = "[هدية]"; +"[皮球]" = "[كرة]"; +"[骷髅]" = "[جمجمة]"; +"[挥手]" = "[موجة يد]"; +"[闪电]" = "[صاعقة]"; +"[饥饿]" = "[جوع]"; +"[困]" = "[تعب]"; +"[咒骂]" = "[سب]"; +"[折磨]" = "[تعذيب]"; +"[抠鼻]" = "[حك الأنف]"; +"[鼓掌]" = "[تصفيق]"; +"[糗大了]" = "[محرج جدًا]"; +"[左哼哼]" = "[تذمر من اليسار]"; +"[打哈欠]" = "[تثاؤب]"; +"[快哭了]" = "[على وشك البكاء]"; +"[吓]" = "[خوف]"; +"[篮球]" = "[كرة سلة]"; +"[乒乓]" = "[تنس الطاولة]"; +"[NO]" = "[لا]"; +"[跳跳]" = "[قفزة]"; +"[怄火]" = "[غضب]"; +"[转圈]" = "[دوران]"; +"[磕头]" = "[الجمجمة]"; +"[回头]" = "[التفاتة]"; +"[跳绳]" = "[قفز حبل]"; +"[激动]" = "[إثارة]"; +"[街舞]" = "[رقص الشوارع]"; +"[献吻]" = "[تقبيل]"; +"[左太极]" = "[ينغ تشي الأيسر]"; +"[右太极]" = "[ينغ تشي الأيمن]"; +"[闭嘴]" = "[أغلق فمك]"; +"[猫咪]" = "[قطة]"; +"[红双喜]" = "[مزدوجة حمراء السعادة]"; +"[鞭炮]" = "[ألعاب نارية]"; +"[红灯笼]" = "[مصباح أحمر]"; +"[麻将]" = "[ماجونغ]"; +"[麦克风]" = "[ميكروفون]"; +"[礼品袋]" = "[حقيبة هدايا]"; +"[信封]" = "[ظرف]"; +"[象棋]" = "[شطرنج]"; +"[彩带]" = "[شريط ملون]"; +"[蜡烛]" = "[شمعة]"; +"[爆筋]" = "[تمزق عضلي]"; +"[棒棒糖]" = "[عصا سكرية]"; +"[奶瓶]" = "[زجاجة حليب]"; +"[面条]" = "[شعرية]"; +"[香蕉]" = "[موز]"; +"[飞机]" = "[طائرة]"; +"[左车头]" = "[رأس القطار الأيسر]"; +"[车厢]" = "[عربة القطار]"; +"[右车头]" = "[رأس القطار الأيمن]"; +"[多云]" = "[غائم]"; +"[下雨]" = "[مطر]"; +"[钞票]" = "[ورقة نقدية]"; +"[熊猫]" = "[باندا]"; +"[灯泡]" = "[مصباح]"; +"[风车]" = "[طاحونة الهواء]"; +"[闹钟]" = "[منبه]"; +"[雨伞]" = "[مظلة]"; +"[彩球]" = "[كرة ملونة]"; +"[钻戒]" = "[خاتم ماس]"; +"[沙发]" = "[أريكة]"; +"[纸巾]" = "[منديل ورقي]"; +"[手枪]" = "[مسدس]"; +"[青蛙]" = "[ضفدع]"; diff --git a/iOS/TUIKit/TUIChat/Resources/TUIChatFace.bundle/del_normal@2x.png b/iOS/TUIKit/TUIChat/Resources/TUIChatFace.bundle/del_normal@2x.png index a2f1e0dd0..4417ec517 100644 Binary files a/iOS/TUIKit/TUIChat/Resources/TUIChatFace.bundle/del_normal@2x.png and b/iOS/TUIKit/TUIChat/Resources/TUIChatFace.bundle/del_normal@2x.png differ diff --git a/iOS/TUIKit/TUIChat/Resources/TUIChatFace.bundle/del_pressed@2x.png b/iOS/TUIKit/TUIChat/Resources/TUIChatFace.bundle/del_pressed@2x.png index 260aa0cee..1c23e4885 100644 Binary files a/iOS/TUIKit/TUIChat/Resources/TUIChatFace.bundle/del_pressed@2x.png and b/iOS/TUIKit/TUIChat/Resources/TUIChatFace.bundle/del_pressed@2x.png differ diff --git a/iOS/TUIKit/TUIChat/Resources/TUIChatFace.bundle/emoji/emoj_normal@2x.png b/iOS/TUIKit/TUIChat/Resources/TUIChatFace.bundle/emoji/emoj_normal@2x.png index 122bda250..f7774f003 100644 Binary files a/iOS/TUIKit/TUIChat/Resources/TUIChatFace.bundle/emoji/emoj_normal@2x.png and b/iOS/TUIKit/TUIChat/Resources/TUIChatFace.bundle/emoji/emoj_normal@2x.png differ diff --git a/iOS/TUIKit/TUIChat/Resources/TUIChatFace.bundle/emoji/emoj_pressed@2x.png b/iOS/TUIKit/TUIChat/Resources/TUIChatFace.bundle/emoji/emoj_pressed@2x.png index c4ce400fb..81bb1a659 100644 Binary files a/iOS/TUIKit/TUIChat/Resources/TUIChatFace.bundle/emoji/emoj_pressed@2x.png and b/iOS/TUIKit/TUIChat/Resources/TUIChatFace.bundle/emoji/emoj_pressed@2x.png differ diff --git a/iOS/TUIKit/TUIChat/Resources/TUIChatFace.bundle/ic_unknown_image@2x.png b/iOS/TUIKit/TUIChat/Resources/TUIChatFace.bundle/ic_unknown_image@2x.png index b8cf01ebd..945869147 100644 Binary files a/iOS/TUIKit/TUIChat/Resources/TUIChatFace.bundle/ic_unknown_image@2x.png and b/iOS/TUIKit/TUIChat/Resources/TUIChatFace.bundle/ic_unknown_image@2x.png differ diff --git a/iOS/TUIKit/TUIChat/Resources/TUIChatLocalizable.bundle/Localizable/ar.lproj/Localizable.strings b/iOS/TUIKit/TUIChat/Resources/TUIChatLocalizable.bundle/Localizable/ar.lproj/Localizable.strings new file mode 100644 index 000000000..e297f276b --- /dev/null +++ b/iOS/TUIKit/TUIChat/Resources/TUIChatLocalizable.bundle/Localizable/ar.lproj/Localizable.strings @@ -0,0 +1,33 @@ +/* + Localizable.strings + Chinese Simplized + + Created by harvy on 2020/10/9. + +*/ +"TUIChatCallDurationFormat" = "مدة المكالمة"; +"TUIChatCallCancelInCaller" = "تم الإلغاء"; +"TUIChatCallCancelInCallee" = "تم إلغاءه من الطرف الآخر"; +"TUIChatCallRejectInCaller" = "تم رفضه من الطرف الآخر"; +"TUIChatCallRejectInCallee" = "تم الرفض"; +"TUIChatCallTimeoutInCaller" = "لا يوجد رد من الطرف الآخر"; +"TUIChatCallTimeoutInCallee" = "تم الإلغاء من الطرف الآخر"; +"TUIChatCallLinebusyInCaller" = "الطرف الآخر مشغول"; +"TUIChatCallLinebusyInCallee" = "تم الإلغاء من الطرف الآخر"; +"TUIChatCallSend" = "بدء المكالمة"; +"TUIChatCallAccept" = "قبول المكالمة"; +"TUIChatCallSwitchToAudio" = "تحويل الفيديو إلى صوت"; +"TUIChatCallConfirmSwitchToAudio" = "تأكيد التحويل إلى صوت"; +"TUIChatCallUnrecognized" = "أمر المكالمة غير معروف"; +"TUIChatGroupCallSendFormat" = "\"%@\" بدأ مكالمة جماعية"; +"TUIChatGroupCallEnd" = "انتهت المكالمة"; +"TUIChatGroupCallNoAnswer" = "لم يتم الرد"; +"TUIChatGroupCallRejectFormat" = "\"%@\" رفض المكالمة الجماعية"; +"TUIChatGroupCallAcceptFormat" = "\"%@\" قبل المكالمة"; +"TUIChatGroupCallSwitchToAudioFormat" = "\"%@\" قام بتحويل الفيديو إلى صوت"; +"TUIChatGroupCallConfirmSwitchToAudioFormat" = "\"%@\" قبل تحويل الفيديو إلى صوت"; +"TUIChatVideoCall" = "مكالمة فيديو"; +"TUIChatAudioCall" = "مكالمة صوتية"; +"TUIChatUnknownCall" = "مكالمة غير معروفة"; + + diff --git a/iOS/TUIKit/TUIChat/Resources/TUIChatLocalizable.bundle/Localizable/en.lproj/Localizable.strings b/iOS/TUIKit/TUIChat/Resources/TUIChatLocalizable.bundle/Localizable/en.lproj/Localizable.strings index c27dfcb30..df546dc72 100644 --- a/iOS/TUIKit/TUIChat/Resources/TUIChatLocalizable.bundle/Localizable/en.lproj/Localizable.strings +++ b/iOS/TUIKit/TUIChat/Resources/TUIChatLocalizable.bundle/Localizable/en.lproj/Localizable.strings @@ -5,7 +5,7 @@ Created by harvy on 2020/10/9. */ -"TUIChatCallDurationFormat" = "Duration %.2d:%.2d"; +"TUIChatCallDurationFormat" = "Duration"; "TUIChatCallCancelInCaller" = "Canceled"; "TUIChatCallCancelInCallee" = "Call canceled by caller"; "TUIChatCallRejectInCaller" = "Call declined by user"; diff --git a/iOS/TUIKit/TUIChat/Resources/TUIChatLocalizable.bundle/Localizable/zh-Hans.lproj/Localizable.strings b/iOS/TUIKit/TUIChat/Resources/TUIChatLocalizable.bundle/Localizable/zh-Hans.lproj/Localizable.strings index 82dfc95a5..570d367ca 100644 --- a/iOS/TUIKit/TUIChat/Resources/TUIChatLocalizable.bundle/Localizable/zh-Hans.lproj/Localizable.strings +++ b/iOS/TUIKit/TUIChat/Resources/TUIChatLocalizable.bundle/Localizable/zh-Hans.lproj/Localizable.strings @@ -5,7 +5,7 @@ Created by harvy on 2020/10/9. */ -"TUIChatCallDurationFormat" = "通话时长 %.2d:%.2d"; +"TUIChatCallDurationFormat" = "通话时长"; "TUIChatCallCancelInCaller" = "已取消"; "TUIChatCallCancelInCallee" = "对方已取消"; "TUIChatCallRejectInCaller" = "对方已拒绝"; diff --git a/iOS/TUIKit/TUIChat/Resources/TUIChatTheme.bundle/dark/manifest.plist b/iOS/TUIKit/TUIChat/Resources/TUIChatTheme.bundle/dark/manifest.plist index 0f9ba253c..52b487818 100644 --- a/iOS/TUIKit/TUIChat/Resources/TUIChatTheme.bundle/dark/manifest.plist +++ b/iOS/TUIKit/TUIChat/Resources/TUIChatTheme.bundle/dark/manifest.plist @@ -142,8 +142,14 @@ icon_reference chat_icon_translate_img icon_translate + chat_icon_convert_voice_to_text_img + icon_convert_voice_to_text chat_icon_hide_img icon_hide + chat_icon_audio_loudspeaker_img + icon_loudspeaker + chat_icon_audio_handset_img + icon_handset chat_icon_emojiArrowDown_img emojiArrowDown.png chat_icon_emojiArrowUp_img diff --git a/iOS/TUIKit/TUIChat/Resources/TUIChatTheme.bundle/dark/resource/ToolViewEmotion@3x.png b/iOS/TUIKit/TUIChat/Resources/TUIChatTheme.bundle/dark/resource/ToolViewEmotion@3x.png index a734428aa..d249b70ad 100644 Binary files a/iOS/TUIKit/TUIChat/Resources/TUIChatTheme.bundle/dark/resource/ToolViewEmotion@3x.png and b/iOS/TUIKit/TUIChat/Resources/TUIChatTheme.bundle/dark/resource/ToolViewEmotion@3x.png differ diff --git a/iOS/TUIKit/TUIChat/Resources/TUIChatTheme.bundle/dark/resource/ToolViewInputVoice@3x.png b/iOS/TUIKit/TUIChat/Resources/TUIChatTheme.bundle/dark/resource/ToolViewInputVoice@3x.png index 991847ed7..22c0e0b86 100644 Binary files a/iOS/TUIKit/TUIChat/Resources/TUIChatTheme.bundle/dark/resource/ToolViewInputVoice@3x.png and b/iOS/TUIKit/TUIChat/Resources/TUIChatTheme.bundle/dark/resource/ToolViewInputVoice@3x.png differ diff --git a/iOS/TUIKit/TUIChat/Resources/TUIChatTheme.bundle/dark/resource/ToolViewKeyboard@3x.png b/iOS/TUIKit/TUIChat/Resources/TUIChatTheme.bundle/dark/resource/ToolViewKeyboard@3x.png index a64ef9e0c..5cae80851 100644 Binary files a/iOS/TUIKit/TUIChat/Resources/TUIChatTheme.bundle/dark/resource/ToolViewKeyboard@3x.png and b/iOS/TUIKit/TUIChat/Resources/TUIChatTheme.bundle/dark/resource/ToolViewKeyboard@3x.png differ diff --git a/iOS/TUIKit/TUIChat/Resources/TUIChatTheme.bundle/dark/resource/TypeSelectorBtnHL_Black@3x.png b/iOS/TUIKit/TUIChat/Resources/TUIChatTheme.bundle/dark/resource/TypeSelectorBtnHL_Black@3x.png index c83e8699f..984a27fb3 100644 Binary files a/iOS/TUIKit/TUIChat/Resources/TUIChatTheme.bundle/dark/resource/TypeSelectorBtnHL_Black@3x.png and b/iOS/TUIKit/TUIChat/Resources/TUIChatTheme.bundle/dark/resource/TypeSelectorBtnHL_Black@3x.png differ diff --git a/iOS/TUIKit/TUIChat/Resources/TUIChatTheme.bundle/dark/resource/TypeSelectorBtn_Black@3x.png b/iOS/TUIKit/TUIChat/Resources/TUIChatTheme.bundle/dark/resource/TypeSelectorBtn_Black@3x.png index c83e8699f..984a27fb3 100644 Binary files a/iOS/TUIKit/TUIChat/Resources/TUIChatTheme.bundle/dark/resource/TypeSelectorBtn_Black@3x.png and b/iOS/TUIKit/TUIChat/Resources/TUIChatTheme.bundle/dark/resource/TypeSelectorBtn_Black@3x.png differ diff --git a/iOS/TUIKit/TUIChat/Resources/TUIChatTheme.bundle/dark/resource/chat_bubble_receive@3x.png b/iOS/TUIKit/TUIChat/Resources/TUIChatTheme.bundle/dark/resource/chat_bubble_receive@3x.png index feb6eb054..dc47f3214 100644 Binary files a/iOS/TUIKit/TUIChat/Resources/TUIChatTheme.bundle/dark/resource/chat_bubble_receive@3x.png and b/iOS/TUIKit/TUIChat/Resources/TUIChatTheme.bundle/dark/resource/chat_bubble_receive@3x.png differ diff --git a/iOS/TUIKit/TUIChat/Resources/TUIChatTheme.bundle/dark/resource/chat_bubble_receive_alpha20@3x.png b/iOS/TUIKit/TUIChat/Resources/TUIChatTheme.bundle/dark/resource/chat_bubble_receive_alpha20@3x.png index b52221804..4bd14de7a 100644 Binary files a/iOS/TUIKit/TUIChat/Resources/TUIChatTheme.bundle/dark/resource/chat_bubble_receive_alpha20@3x.png and b/iOS/TUIKit/TUIChat/Resources/TUIChatTheme.bundle/dark/resource/chat_bubble_receive_alpha20@3x.png differ diff --git a/iOS/TUIKit/TUIChat/Resources/TUIChatTheme.bundle/dark/resource/chat_bubble_receive_alpha50@3x.png b/iOS/TUIKit/TUIChat/Resources/TUIChatTheme.bundle/dark/resource/chat_bubble_receive_alpha50@3x.png index c108f762e..6b0a8a120 100644 Binary files a/iOS/TUIKit/TUIChat/Resources/TUIChatTheme.bundle/dark/resource/chat_bubble_receive_alpha50@3x.png and b/iOS/TUIKit/TUIChat/Resources/TUIChatTheme.bundle/dark/resource/chat_bubble_receive_alpha50@3x.png differ diff --git a/iOS/TUIKit/TUIChat/Resources/TUIChatTheme.bundle/dark/resource/chat_bubble_send@3x.png b/iOS/TUIKit/TUIChat/Resources/TUIChatTheme.bundle/dark/resource/chat_bubble_send@3x.png index 1afaaf873..3075fdf4a 100644 Binary files a/iOS/TUIKit/TUIChat/Resources/TUIChatTheme.bundle/dark/resource/chat_bubble_send@3x.png and b/iOS/TUIKit/TUIChat/Resources/TUIChatTheme.bundle/dark/resource/chat_bubble_send@3x.png differ diff --git a/iOS/TUIKit/TUIChat/Resources/TUIChatTheme.bundle/dark/resource/chat_bubble_send_alpha20@3x.png b/iOS/TUIKit/TUIChat/Resources/TUIChatTheme.bundle/dark/resource/chat_bubble_send_alpha20@3x.png index 5b8cb8b87..611b1a996 100644 Binary files a/iOS/TUIKit/TUIChat/Resources/TUIChatTheme.bundle/dark/resource/chat_bubble_send_alpha20@3x.png and b/iOS/TUIKit/TUIChat/Resources/TUIChatTheme.bundle/dark/resource/chat_bubble_send_alpha20@3x.png differ diff --git a/iOS/TUIKit/TUIChat/Resources/TUIChatTheme.bundle/dark/resource/chat_bubble_send_alpha50@3x.png b/iOS/TUIKit/TUIChat/Resources/TUIChatTheme.bundle/dark/resource/chat_bubble_send_alpha50@3x.png index c2954e158..a3aaca417 100644 Binary files a/iOS/TUIKit/TUIChat/Resources/TUIChatTheme.bundle/dark/resource/chat_bubble_send_alpha50@3x.png and b/iOS/TUIKit/TUIChat/Resources/TUIChatTheme.bundle/dark/resource/chat_bubble_send_alpha50@3x.png differ diff --git a/iOS/TUIKit/TUIChat/Resources/TUIChatTheme.bundle/dark/resource/chat_more_camera@3x.png b/iOS/TUIKit/TUIChat/Resources/TUIChatTheme.bundle/dark/resource/chat_more_camera@3x.png index 755602081..7191b4012 100644 Binary files a/iOS/TUIKit/TUIChat/Resources/TUIChatTheme.bundle/dark/resource/chat_more_camera@3x.png and b/iOS/TUIKit/TUIChat/Resources/TUIChatTheme.bundle/dark/resource/chat_more_camera@3x.png differ diff --git a/iOS/TUIKit/TUIChat/Resources/TUIChatTheme.bundle/dark/resource/chat_more_file@3x.png b/iOS/TUIKit/TUIChat/Resources/TUIChatTheme.bundle/dark/resource/chat_more_file@3x.png index 709082e1f..c2276f3b7 100644 Binary files a/iOS/TUIKit/TUIChat/Resources/TUIChatTheme.bundle/dark/resource/chat_more_file@3x.png and b/iOS/TUIKit/TUIChat/Resources/TUIChatTheme.bundle/dark/resource/chat_more_file@3x.png differ diff --git a/iOS/TUIKit/TUIChat/Resources/TUIChatTheme.bundle/dark/resource/chat_more_group_live@3x.png b/iOS/TUIKit/TUIChat/Resources/TUIChatTheme.bundle/dark/resource/chat_more_group_live@3x.png index 677acf2ea..0b7471526 100644 Binary files a/iOS/TUIKit/TUIChat/Resources/TUIChatTheme.bundle/dark/resource/chat_more_group_live@3x.png and b/iOS/TUIKit/TUIChat/Resources/TUIChatTheme.bundle/dark/resource/chat_more_group_live@3x.png differ diff --git a/iOS/TUIKit/TUIChat/Resources/TUIChatTheme.bundle/dark/resource/chat_more_link@3x.png b/iOS/TUIKit/TUIChat/Resources/TUIChatTheme.bundle/dark/resource/chat_more_link@3x.png index e4e679a99..4204fc62d 100644 Binary files a/iOS/TUIKit/TUIChat/Resources/TUIChatTheme.bundle/dark/resource/chat_more_link@3x.png and b/iOS/TUIKit/TUIChat/Resources/TUIChatTheme.bundle/dark/resource/chat_more_link@3x.png differ diff --git a/iOS/TUIKit/TUIChat/Resources/TUIChatTheme.bundle/dark/resource/chat_more_picture@3x.png b/iOS/TUIKit/TUIChat/Resources/TUIChatTheme.bundle/dark/resource/chat_more_picture@3x.png index ff329ba20..99c844519 100644 Binary files a/iOS/TUIKit/TUIChat/Resources/TUIChatTheme.bundle/dark/resource/chat_more_picture@3x.png and b/iOS/TUIKit/TUIChat/Resources/TUIChatTheme.bundle/dark/resource/chat_more_picture@3x.png differ diff --git a/iOS/TUIKit/TUIChat/Resources/TUIChatTheme.bundle/dark/resource/chat_more_video@3x.png b/iOS/TUIKit/TUIChat/Resources/TUIChatTheme.bundle/dark/resource/chat_more_video@3x.png index 7e8124d3b..757c99e27 100644 Binary files a/iOS/TUIKit/TUIChat/Resources/TUIChatTheme.bundle/dark/resource/chat_more_video@3x.png and b/iOS/TUIKit/TUIChat/Resources/TUIChatTheme.bundle/dark/resource/chat_more_video@3x.png differ diff --git a/iOS/TUIKit/TUIChat/Resources/TUIChatTheme.bundle/dark/resource/emojiArrowDown.png b/iOS/TUIKit/TUIChat/Resources/TUIChatTheme.bundle/dark/resource/emojiArrowDown.png index ee1e983fd..fd89e98ad 100644 Binary files a/iOS/TUIKit/TUIChat/Resources/TUIChatTheme.bundle/dark/resource/emojiArrowDown.png and b/iOS/TUIKit/TUIChat/Resources/TUIChatTheme.bundle/dark/resource/emojiArrowDown.png differ diff --git a/iOS/TUIKit/TUIChat/Resources/TUIChatTheme.bundle/dark/resource/emojiArrowUp.png b/iOS/TUIKit/TUIChat/Resources/TUIChatTheme.bundle/dark/resource/emojiArrowUp.png index 82681b167..c27181936 100644 Binary files a/iOS/TUIKit/TUIChat/Resources/TUIChatTheme.bundle/dark/resource/emojiArrowUp.png and b/iOS/TUIKit/TUIChat/Resources/TUIChatTheme.bundle/dark/resource/emojiArrowUp.png differ diff --git a/iOS/TUIKit/TUIChat/Resources/TUIChatTheme.bundle/dark/resource/icon_convert_voice_to_text@2x.png b/iOS/TUIKit/TUIChat/Resources/TUIChatTheme.bundle/dark/resource/icon_convert_voice_to_text@2x.png new file mode 100644 index 000000000..54d44f823 Binary files /dev/null and b/iOS/TUIKit/TUIChat/Resources/TUIChatTheme.bundle/dark/resource/icon_convert_voice_to_text@2x.png differ diff --git a/iOS/TUIKit/TUIChat/Resources/TUIChatTheme.bundle/dark/resource/icon_convert_voice_to_text@3x.png b/iOS/TUIKit/TUIChat/Resources/TUIChatTheme.bundle/dark/resource/icon_convert_voice_to_text@3x.png new file mode 100644 index 000000000..0f90fd03c Binary files /dev/null and b/iOS/TUIKit/TUIChat/Resources/TUIChatTheme.bundle/dark/resource/icon_convert_voice_to_text@3x.png differ diff --git a/iOS/TUIKit/TUIChat/Resources/TUIChatTheme.bundle/dark/resource/icon_copy@3x.png b/iOS/TUIKit/TUIChat/Resources/TUIChatTheme.bundle/dark/resource/icon_copy@3x.png index a8083af17..ae4349c1c 100644 Binary files a/iOS/TUIKit/TUIChat/Resources/TUIChatTheme.bundle/dark/resource/icon_copy@3x.png and b/iOS/TUIKit/TUIChat/Resources/TUIChatTheme.bundle/dark/resource/icon_copy@3x.png differ diff --git a/iOS/TUIKit/TUIChat/Resources/TUIChatTheme.bundle/dark/resource/icon_delete@3x.png b/iOS/TUIKit/TUIChat/Resources/TUIChatTheme.bundle/dark/resource/icon_delete@3x.png index 476e6111e..1f47d01fd 100644 Binary files a/iOS/TUIKit/TUIChat/Resources/TUIChatTheme.bundle/dark/resource/icon_delete@3x.png and b/iOS/TUIKit/TUIChat/Resources/TUIChatTheme.bundle/dark/resource/icon_delete@3x.png differ diff --git a/iOS/TUIKit/TUIChat/Resources/TUIChatTheme.bundle/dark/resource/icon_forward@3x.png b/iOS/TUIKit/TUIChat/Resources/TUIChatTheme.bundle/dark/resource/icon_forward@3x.png index 5d33d3fa2..ba72a62d4 100644 Binary files a/iOS/TUIKit/TUIChat/Resources/TUIChatTheme.bundle/dark/resource/icon_forward@3x.png and b/iOS/TUIKit/TUIChat/Resources/TUIChatTheme.bundle/dark/resource/icon_forward@3x.png differ diff --git a/iOS/TUIKit/TUIChat/Resources/TUIChatTheme.bundle/dark/resource/icon_handset@3x.png b/iOS/TUIKit/TUIChat/Resources/TUIChatTheme.bundle/dark/resource/icon_handset@3x.png new file mode 100644 index 000000000..8bbcea9f7 Binary files /dev/null and b/iOS/TUIKit/TUIChat/Resources/TUIChatTheme.bundle/dark/resource/icon_handset@3x.png differ diff --git a/iOS/TUIKit/TUIChat/Resources/TUIChatTheme.bundle/dark/resource/icon_loudspeaker@3x.png b/iOS/TUIKit/TUIChat/Resources/TUIChatTheme.bundle/dark/resource/icon_loudspeaker@3x.png new file mode 100644 index 000000000..795c73644 Binary files /dev/null and b/iOS/TUIKit/TUIChat/Resources/TUIChatTheme.bundle/dark/resource/icon_loudspeaker@3x.png differ diff --git a/iOS/TUIKit/TUIChat/Resources/TUIChatTheme.bundle/dark/resource/icon_multi@3x.png b/iOS/TUIKit/TUIChat/Resources/TUIChatTheme.bundle/dark/resource/icon_multi@3x.png index 2e9499435..44db73c99 100644 Binary files a/iOS/TUIKit/TUIChat/Resources/TUIChatTheme.bundle/dark/resource/icon_multi@3x.png and b/iOS/TUIKit/TUIChat/Resources/TUIChatTheme.bundle/dark/resource/icon_multi@3x.png differ diff --git a/iOS/TUIKit/TUIChat/Resources/TUIChatTheme.bundle/dark/resource/icon_recall@3x.png b/iOS/TUIKit/TUIChat/Resources/TUIChatTheme.bundle/dark/resource/icon_recall@3x.png index 333877fcc..c29f7a55a 100644 Binary files a/iOS/TUIKit/TUIChat/Resources/TUIChatTheme.bundle/dark/resource/icon_recall@3x.png and b/iOS/TUIKit/TUIChat/Resources/TUIChatTheme.bundle/dark/resource/icon_recall@3x.png differ diff --git a/iOS/TUIKit/TUIChat/Resources/TUIChatTheme.bundle/dark/resource/icon_reference@3x.png b/iOS/TUIKit/TUIChat/Resources/TUIChatTheme.bundle/dark/resource/icon_reference@3x.png index 4a9c20a8a..00f8bc196 100644 Binary files a/iOS/TUIKit/TUIChat/Resources/TUIChatTheme.bundle/dark/resource/icon_reference@3x.png and b/iOS/TUIKit/TUIChat/Resources/TUIChatTheme.bundle/dark/resource/icon_reference@3x.png differ diff --git a/iOS/TUIKit/TUIChat/Resources/TUIChatTheme.bundle/dark/resource/icon_reply@3x.png b/iOS/TUIKit/TUIChat/Resources/TUIChatTheme.bundle/dark/resource/icon_reply@3x.png index db37f1145..fadecb72c 100644 Binary files a/iOS/TUIKit/TUIChat/Resources/TUIChatTheme.bundle/dark/resource/icon_reply@3x.png and b/iOS/TUIKit/TUIChat/Resources/TUIChatTheme.bundle/dark/resource/icon_reply@3x.png differ diff --git a/iOS/TUIKit/TUIChat/Resources/TUIChatTheme.bundle/dark/resource/icon_translate@2x.png b/iOS/TUIKit/TUIChat/Resources/TUIChatTheme.bundle/dark/resource/icon_translate@2x.png index 39a060963..31f852d65 100644 Binary files a/iOS/TUIKit/TUIChat/Resources/TUIChatTheme.bundle/dark/resource/icon_translate@2x.png and b/iOS/TUIKit/TUIChat/Resources/TUIChatTheme.bundle/dark/resource/icon_translate@2x.png differ diff --git a/iOS/TUIKit/TUIChat/Resources/TUIChatTheme.bundle/dark/resource/icon_translate@3x.png b/iOS/TUIKit/TUIChat/Resources/TUIChatTheme.bundle/dark/resource/icon_translate@3x.png index c5dd5382c..0a685a756 100644 Binary files a/iOS/TUIKit/TUIChat/Resources/TUIChatTheme.bundle/dark/resource/icon_translate@3x.png and b/iOS/TUIKit/TUIChat/Resources/TUIChatTheme.bundle/dark/resource/icon_translate@3x.png differ diff --git a/iOS/TUIKit/TUIChat/Resources/TUIChatTheme.bundle/dark/resource/message_voice_receiver_normal@3x.png b/iOS/TUIKit/TUIChat/Resources/TUIChatTheme.bundle/dark/resource/message_voice_receiver_normal@3x.png index 2407ace48..32a68b04f 100644 Binary files a/iOS/TUIKit/TUIChat/Resources/TUIChatTheme.bundle/dark/resource/message_voice_receiver_normal@3x.png and b/iOS/TUIKit/TUIChat/Resources/TUIChatTheme.bundle/dark/resource/message_voice_receiver_normal@3x.png differ diff --git a/iOS/TUIKit/TUIChat/Resources/TUIChatTheme.bundle/dark/resource/message_voice_sender_normal@3x.png b/iOS/TUIKit/TUIChat/Resources/TUIChatTheme.bundle/dark/resource/message_voice_sender_normal@3x.png index 98c856972..418265b61 100644 Binary files a/iOS/TUIKit/TUIChat/Resources/TUIChatTheme.bundle/dark/resource/message_voice_sender_normal@3x.png and b/iOS/TUIKit/TUIChat/Resources/TUIChatTheme.bundle/dark/resource/message_voice_sender_normal@3x.png differ diff --git a/iOS/TUIKit/TUIChat/Resources/TUIChatTheme.bundle/light/resource/chat_bubble_receive@3x.png b/iOS/TUIKit/TUIChat/Resources/TUIChatTheme.bundle/light/resource/chat_bubble_receive@3x.png index 8766f785e..6316fd6d6 100644 Binary files a/iOS/TUIKit/TUIChat/Resources/TUIChatTheme.bundle/light/resource/chat_bubble_receive@3x.png and b/iOS/TUIKit/TUIChat/Resources/TUIChatTheme.bundle/light/resource/chat_bubble_receive@3x.png differ diff --git a/iOS/TUIKit/TUIChat/Resources/TUIChatTheme.bundle/light/resource/chat_bubble_receive_alpha20@3x.png b/iOS/TUIKit/TUIChat/Resources/TUIChatTheme.bundle/light/resource/chat_bubble_receive_alpha20@3x.png index b52221804..4bd14de7a 100644 Binary files a/iOS/TUIKit/TUIChat/Resources/TUIChatTheme.bundle/light/resource/chat_bubble_receive_alpha20@3x.png and b/iOS/TUIKit/TUIChat/Resources/TUIChatTheme.bundle/light/resource/chat_bubble_receive_alpha20@3x.png differ diff --git a/iOS/TUIKit/TUIChat/Resources/TUIChatTheme.bundle/light/resource/chat_bubble_receive_alpha50@3x.png b/iOS/TUIKit/TUIChat/Resources/TUIChatTheme.bundle/light/resource/chat_bubble_receive_alpha50@3x.png index c108f762e..6b0a8a120 100644 Binary files a/iOS/TUIKit/TUIChat/Resources/TUIChatTheme.bundle/light/resource/chat_bubble_receive_alpha50@3x.png and b/iOS/TUIKit/TUIChat/Resources/TUIChatTheme.bundle/light/resource/chat_bubble_receive_alpha50@3x.png differ diff --git a/iOS/TUIKit/TUIChat/Resources/TUIChatTheme.bundle/light/resource/chat_bubble_send@3x.png b/iOS/TUIKit/TUIChat/Resources/TUIChatTheme.bundle/light/resource/chat_bubble_send@3x.png index 0f1b7bf6c..b5fbcd8d0 100644 Binary files a/iOS/TUIKit/TUIChat/Resources/TUIChatTheme.bundle/light/resource/chat_bubble_send@3x.png and b/iOS/TUIKit/TUIChat/Resources/TUIChatTheme.bundle/light/resource/chat_bubble_send@3x.png differ diff --git a/iOS/TUIKit/TUIChat/Resources/TUIChatTheme.bundle/light/resource/chat_bubble_send_alpha20@3x.png b/iOS/TUIKit/TUIChat/Resources/TUIChatTheme.bundle/light/resource/chat_bubble_send_alpha20@3x.png index 5b8cb8b87..611b1a996 100644 Binary files a/iOS/TUIKit/TUIChat/Resources/TUIChatTheme.bundle/light/resource/chat_bubble_send_alpha20@3x.png and b/iOS/TUIKit/TUIChat/Resources/TUIChatTheme.bundle/light/resource/chat_bubble_send_alpha20@3x.png differ diff --git a/iOS/TUIKit/TUIChat/Resources/TUIChatTheme.bundle/light/resource/chat_bubble_send_alpha50@3x.png b/iOS/TUIKit/TUIChat/Resources/TUIChatTheme.bundle/light/resource/chat_bubble_send_alpha50@3x.png index c2954e158..a3aaca417 100644 Binary files a/iOS/TUIKit/TUIChat/Resources/TUIChatTheme.bundle/light/resource/chat_bubble_send_alpha50@3x.png and b/iOS/TUIKit/TUIChat/Resources/TUIChatTheme.bundle/light/resource/chat_bubble_send_alpha50@3x.png differ diff --git a/iOS/TUIKit/TUIChat/Resources/TUIChatTheme.bundle/light/resource/chat_more_camera@3x.png b/iOS/TUIKit/TUIChat/Resources/TUIChatTheme.bundle/light/resource/chat_more_camera@3x.png index f201c4fe8..e6a9d319d 100644 Binary files a/iOS/TUIKit/TUIChat/Resources/TUIChatTheme.bundle/light/resource/chat_more_camera@3x.png and b/iOS/TUIKit/TUIChat/Resources/TUIChatTheme.bundle/light/resource/chat_more_camera@3x.png differ diff --git a/iOS/TUIKit/TUIChat/Resources/TUIChatTheme.bundle/light/resource/chat_more_file@3x.png b/iOS/TUIKit/TUIChat/Resources/TUIChatTheme.bundle/light/resource/chat_more_file@3x.png index 64c49e6cc..57d7d3d83 100644 Binary files a/iOS/TUIKit/TUIChat/Resources/TUIChatTheme.bundle/light/resource/chat_more_file@3x.png and b/iOS/TUIKit/TUIChat/Resources/TUIChatTheme.bundle/light/resource/chat_more_file@3x.png differ diff --git a/iOS/TUIKit/TUIChat/Resources/TUIChatTheme.bundle/light/resource/chat_more_groupnote@3x.png b/iOS/TUIKit/TUIChat/Resources/TUIChatTheme.bundle/light/resource/chat_more_groupnote@3x.png index acc41a783..8fb611a9e 100644 Binary files a/iOS/TUIKit/TUIChat/Resources/TUIChatTheme.bundle/light/resource/chat_more_groupnote@3x.png and b/iOS/TUIKit/TUIChat/Resources/TUIChatTheme.bundle/light/resource/chat_more_groupnote@3x.png differ diff --git a/iOS/TUIKit/TUIChat/Resources/TUIChatTheme.bundle/light/resource/chat_more_link@3x.png b/iOS/TUIKit/TUIChat/Resources/TUIChatTheme.bundle/light/resource/chat_more_link@3x.png index 2e7b20f12..09ee4f102 100644 Binary files a/iOS/TUIKit/TUIChat/Resources/TUIChatTheme.bundle/light/resource/chat_more_link@3x.png and b/iOS/TUIKit/TUIChat/Resources/TUIChatTheme.bundle/light/resource/chat_more_link@3x.png differ diff --git a/iOS/TUIKit/TUIChat/Resources/TUIChatTheme.bundle/light/resource/chat_more_picture@3x.png b/iOS/TUIKit/TUIChat/Resources/TUIChatTheme.bundle/light/resource/chat_more_picture@3x.png index 09f26ea43..88fd7579d 100644 Binary files a/iOS/TUIKit/TUIChat/Resources/TUIChatTheme.bundle/light/resource/chat_more_picture@3x.png and b/iOS/TUIKit/TUIChat/Resources/TUIChatTheme.bundle/light/resource/chat_more_picture@3x.png differ diff --git a/iOS/TUIKit/TUIChat/Resources/TUIChatTheme.bundle/light/resource/chat_more_poll@3x.png b/iOS/TUIKit/TUIChat/Resources/TUIChatTheme.bundle/light/resource/chat_more_poll@3x.png index be52e9a1b..addad7591 100644 Binary files a/iOS/TUIKit/TUIChat/Resources/TUIChatTheme.bundle/light/resource/chat_more_poll@3x.png and b/iOS/TUIKit/TUIChat/Resources/TUIChatTheme.bundle/light/resource/chat_more_poll@3x.png differ diff --git a/iOS/TUIKit/TUIChat/Resources/TUIChatTheme.bundle/light/resource/chat_more_video@3x.png b/iOS/TUIKit/TUIChat/Resources/TUIChatTheme.bundle/light/resource/chat_more_video@3x.png index cc3776137..7d89281fb 100644 Binary files a/iOS/TUIKit/TUIChat/Resources/TUIChatTheme.bundle/light/resource/chat_more_video@3x.png and b/iOS/TUIKit/TUIChat/Resources/TUIChatTheme.bundle/light/resource/chat_more_video@3x.png differ diff --git a/iOS/TUIKit/TUIChat/Resources/TUIChatTheme.bundle/light/resource/message_voice_receiver_normal@3x.png b/iOS/TUIKit/TUIChat/Resources/TUIChatTheme.bundle/light/resource/message_voice_receiver_normal@3x.png index 2407ace48..32a68b04f 100644 Binary files a/iOS/TUIKit/TUIChat/Resources/TUIChatTheme.bundle/light/resource/message_voice_receiver_normal@3x.png and b/iOS/TUIKit/TUIChat/Resources/TUIChatTheme.bundle/light/resource/message_voice_receiver_normal@3x.png differ diff --git a/iOS/TUIKit/TUIChat/Resources/TUIChatTheme.bundle/light/resource/message_voice_sender_normal@3x.png b/iOS/TUIKit/TUIChat/Resources/TUIChatTheme.bundle/light/resource/message_voice_sender_normal@3x.png index 98c856972..9394328b0 100644 Binary files a/iOS/TUIKit/TUIChat/Resources/TUIChatTheme.bundle/light/resource/message_voice_sender_normal@3x.png and b/iOS/TUIKit/TUIChat/Resources/TUIChatTheme.bundle/light/resource/message_voice_sender_normal@3x.png differ diff --git a/iOS/TUIKit/TUIChat/Resources/TUIChatTheme.bundle/lively/resource/chat_bubble_receive@3x.png b/iOS/TUIKit/TUIChat/Resources/TUIChatTheme.bundle/lively/resource/chat_bubble_receive@3x.png index f84fdbff0..957d8efb0 100644 Binary files a/iOS/TUIKit/TUIChat/Resources/TUIChatTheme.bundle/lively/resource/chat_bubble_receive@3x.png and b/iOS/TUIKit/TUIChat/Resources/TUIChatTheme.bundle/lively/resource/chat_bubble_receive@3x.png differ diff --git a/iOS/TUIKit/TUIChat/Resources/TUIChatTheme.bundle/lively/resource/chat_bubble_receive_alpha20@3x.png b/iOS/TUIKit/TUIChat/Resources/TUIChatTheme.bundle/lively/resource/chat_bubble_receive_alpha20@3x.png index b52221804..4bd14de7a 100644 Binary files a/iOS/TUIKit/TUIChat/Resources/TUIChatTheme.bundle/lively/resource/chat_bubble_receive_alpha20@3x.png and b/iOS/TUIKit/TUIChat/Resources/TUIChatTheme.bundle/lively/resource/chat_bubble_receive_alpha20@3x.png differ diff --git a/iOS/TUIKit/TUIChat/Resources/TUIChatTheme.bundle/lively/resource/chat_bubble_receive_alpha50@3x.png b/iOS/TUIKit/TUIChat/Resources/TUIChatTheme.bundle/lively/resource/chat_bubble_receive_alpha50@3x.png index c108f762e..6b0a8a120 100644 Binary files a/iOS/TUIKit/TUIChat/Resources/TUIChatTheme.bundle/lively/resource/chat_bubble_receive_alpha50@3x.png and b/iOS/TUIKit/TUIChat/Resources/TUIChatTheme.bundle/lively/resource/chat_bubble_receive_alpha50@3x.png differ diff --git a/iOS/TUIKit/TUIChat/Resources/TUIChatTheme.bundle/lively/resource/chat_bubble_send@3x.png b/iOS/TUIKit/TUIChat/Resources/TUIChatTheme.bundle/lively/resource/chat_bubble_send@3x.png index 9bfb754e7..4c4a44b55 100644 Binary files a/iOS/TUIKit/TUIChat/Resources/TUIChatTheme.bundle/lively/resource/chat_bubble_send@3x.png and b/iOS/TUIKit/TUIChat/Resources/TUIChatTheme.bundle/lively/resource/chat_bubble_send@3x.png differ diff --git a/iOS/TUIKit/TUIChat/Resources/TUIChatTheme.bundle/lively/resource/chat_bubble_send_alpha20@3x.png b/iOS/TUIKit/TUIChat/Resources/TUIChatTheme.bundle/lively/resource/chat_bubble_send_alpha20@3x.png index 5b8cb8b87..611b1a996 100644 Binary files a/iOS/TUIKit/TUIChat/Resources/TUIChatTheme.bundle/lively/resource/chat_bubble_send_alpha20@3x.png and b/iOS/TUIKit/TUIChat/Resources/TUIChatTheme.bundle/lively/resource/chat_bubble_send_alpha20@3x.png differ diff --git a/iOS/TUIKit/TUIChat/Resources/TUIChatTheme.bundle/lively/resource/chat_bubble_send_alpha50@3x.png b/iOS/TUIKit/TUIChat/Resources/TUIChatTheme.bundle/lively/resource/chat_bubble_send_alpha50@3x.png index c2954e158..a3aaca417 100644 Binary files a/iOS/TUIKit/TUIChat/Resources/TUIChatTheme.bundle/lively/resource/chat_bubble_send_alpha50@3x.png and b/iOS/TUIKit/TUIChat/Resources/TUIChatTheme.bundle/lively/resource/chat_bubble_send_alpha50@3x.png differ diff --git a/iOS/TUIKit/TUIChat/Resources/TUIChatTheme.bundle/lively/resource/chat_drop_down.png b/iOS/TUIKit/TUIChat/Resources/TUIChatTheme.bundle/lively/resource/chat_drop_down.png index 9d668627b..1c12e165a 100644 Binary files a/iOS/TUIKit/TUIChat/Resources/TUIChatTheme.bundle/lively/resource/chat_drop_down.png and b/iOS/TUIKit/TUIChat/Resources/TUIChatTheme.bundle/lively/resource/chat_drop_down.png differ diff --git a/iOS/TUIKit/TUIChat/Resources/TUIChatTheme.bundle/lively/resource/chat_drop_down@2x.png b/iOS/TUIKit/TUIChat/Resources/TUIChatTheme.bundle/lively/resource/chat_drop_down@2x.png index 93218c8ac..f288816d1 100644 Binary files a/iOS/TUIKit/TUIChat/Resources/TUIChatTheme.bundle/lively/resource/chat_drop_down@2x.png and b/iOS/TUIKit/TUIChat/Resources/TUIChatTheme.bundle/lively/resource/chat_drop_down@2x.png differ diff --git a/iOS/TUIKit/TUIChat/Resources/TUIChatTheme.bundle/lively/resource/chat_drop_down@3x.png b/iOS/TUIKit/TUIChat/Resources/TUIChatTheme.bundle/lively/resource/chat_drop_down@3x.png index 38a9477d9..bfa90b62a 100644 Binary files a/iOS/TUIKit/TUIChat/Resources/TUIChatTheme.bundle/lively/resource/chat_drop_down@3x.png and b/iOS/TUIKit/TUIChat/Resources/TUIChatTheme.bundle/lively/resource/chat_drop_down@3x.png differ diff --git a/iOS/TUIKit/TUIChat/Resources/TUIChatTheme.bundle/lively/resource/chat_more_camera@3x.png b/iOS/TUIKit/TUIChat/Resources/TUIChatTheme.bundle/lively/resource/chat_more_camera@3x.png index f201c4fe8..e6a9d319d 100644 Binary files a/iOS/TUIKit/TUIChat/Resources/TUIChatTheme.bundle/lively/resource/chat_more_camera@3x.png and b/iOS/TUIKit/TUIChat/Resources/TUIChatTheme.bundle/lively/resource/chat_more_camera@3x.png differ diff --git a/iOS/TUIKit/TUIChat/Resources/TUIChatTheme.bundle/lively/resource/chat_more_file@3x.png b/iOS/TUIKit/TUIChat/Resources/TUIChatTheme.bundle/lively/resource/chat_more_file@3x.png index 64c49e6cc..57d7d3d83 100644 Binary files a/iOS/TUIKit/TUIChat/Resources/TUIChatTheme.bundle/lively/resource/chat_more_file@3x.png and b/iOS/TUIKit/TUIChat/Resources/TUIChatTheme.bundle/lively/resource/chat_more_file@3x.png differ diff --git a/iOS/TUIKit/TUIChat/Resources/TUIChatTheme.bundle/lively/resource/chat_more_groupnote@3x.png b/iOS/TUIKit/TUIChat/Resources/TUIChatTheme.bundle/lively/resource/chat_more_groupnote@3x.png index acc41a783..8fb611a9e 100644 Binary files a/iOS/TUIKit/TUIChat/Resources/TUIChatTheme.bundle/lively/resource/chat_more_groupnote@3x.png and b/iOS/TUIKit/TUIChat/Resources/TUIChatTheme.bundle/lively/resource/chat_more_groupnote@3x.png differ diff --git a/iOS/TUIKit/TUIChat/Resources/TUIChatTheme.bundle/lively/resource/chat_more_link@3x.png b/iOS/TUIKit/TUIChat/Resources/TUIChatTheme.bundle/lively/resource/chat_more_link@3x.png index 2e7b20f12..09ee4f102 100644 Binary files a/iOS/TUIKit/TUIChat/Resources/TUIChatTheme.bundle/lively/resource/chat_more_link@3x.png and b/iOS/TUIKit/TUIChat/Resources/TUIChatTheme.bundle/lively/resource/chat_more_link@3x.png differ diff --git a/iOS/TUIKit/TUIChat/Resources/TUIChatTheme.bundle/lively/resource/chat_more_picture@3x.png b/iOS/TUIKit/TUIChat/Resources/TUIChatTheme.bundle/lively/resource/chat_more_picture@3x.png index 09f26ea43..88fd7579d 100644 Binary files a/iOS/TUIKit/TUIChat/Resources/TUIChatTheme.bundle/lively/resource/chat_more_picture@3x.png and b/iOS/TUIKit/TUIChat/Resources/TUIChatTheme.bundle/lively/resource/chat_more_picture@3x.png differ diff --git a/iOS/TUIKit/TUIChat/Resources/TUIChatTheme.bundle/lively/resource/chat_more_poll@3x.png b/iOS/TUIKit/TUIChat/Resources/TUIChatTheme.bundle/lively/resource/chat_more_poll@3x.png index be52e9a1b..addad7591 100644 Binary files a/iOS/TUIKit/TUIChat/Resources/TUIChatTheme.bundle/lively/resource/chat_more_poll@3x.png and b/iOS/TUIKit/TUIChat/Resources/TUIChatTheme.bundle/lively/resource/chat_more_poll@3x.png differ diff --git a/iOS/TUIKit/TUIChat/Resources/TUIChatTheme.bundle/lively/resource/chat_more_video@3x.png b/iOS/TUIKit/TUIChat/Resources/TUIChatTheme.bundle/lively/resource/chat_more_video@3x.png index cc3776137..7d89281fb 100644 Binary files a/iOS/TUIKit/TUIChat/Resources/TUIChatTheme.bundle/lively/resource/chat_more_video@3x.png and b/iOS/TUIKit/TUIChat/Resources/TUIChatTheme.bundle/lively/resource/chat_more_video@3x.png differ diff --git a/iOS/TUIKit/TUIChat/Resources/TUIChatTheme.bundle/lively/resource/chat_pull_up.png b/iOS/TUIKit/TUIChat/Resources/TUIChatTheme.bundle/lively/resource/chat_pull_up.png index 53eb8b134..3f90f5496 100644 Binary files a/iOS/TUIKit/TUIChat/Resources/TUIChatTheme.bundle/lively/resource/chat_pull_up.png and b/iOS/TUIKit/TUIChat/Resources/TUIChatTheme.bundle/lively/resource/chat_pull_up.png differ diff --git a/iOS/TUIKit/TUIChat/Resources/TUIChatTheme.bundle/lively/resource/chat_pull_up@2x.png b/iOS/TUIKit/TUIChat/Resources/TUIChatTheme.bundle/lively/resource/chat_pull_up@2x.png index 20f941703..639854c40 100644 Binary files a/iOS/TUIKit/TUIChat/Resources/TUIChatTheme.bundle/lively/resource/chat_pull_up@2x.png and b/iOS/TUIKit/TUIChat/Resources/TUIChatTheme.bundle/lively/resource/chat_pull_up@2x.png differ diff --git a/iOS/TUIKit/TUIChat/Resources/TUIChatTheme.bundle/lively/resource/chat_pull_up@3x.png b/iOS/TUIKit/TUIChat/Resources/TUIChatTheme.bundle/lively/resource/chat_pull_up@3x.png index 4dc1525a7..e4626b2eb 100644 Binary files a/iOS/TUIKit/TUIChat/Resources/TUIChatTheme.bundle/lively/resource/chat_pull_up@3x.png and b/iOS/TUIKit/TUIChat/Resources/TUIChatTheme.bundle/lively/resource/chat_pull_up@3x.png differ diff --git a/iOS/TUIKit/TUIChat/Resources/TUIChatTheme.bundle/serious/resource/chat_bubble_receive@3x.png b/iOS/TUIKit/TUIChat/Resources/TUIChatTheme.bundle/serious/resource/chat_bubble_receive@3x.png index f84fdbff0..957d8efb0 100644 Binary files a/iOS/TUIKit/TUIChat/Resources/TUIChatTheme.bundle/serious/resource/chat_bubble_receive@3x.png and b/iOS/TUIKit/TUIChat/Resources/TUIChatTheme.bundle/serious/resource/chat_bubble_receive@3x.png differ diff --git a/iOS/TUIKit/TUIChat/Resources/TUIChatTheme.bundle/serious/resource/chat_bubble_receive_alpha20@3x.png b/iOS/TUIKit/TUIChat/Resources/TUIChatTheme.bundle/serious/resource/chat_bubble_receive_alpha20@3x.png index b52221804..4bd14de7a 100644 Binary files a/iOS/TUIKit/TUIChat/Resources/TUIChatTheme.bundle/serious/resource/chat_bubble_receive_alpha20@3x.png and b/iOS/TUIKit/TUIChat/Resources/TUIChatTheme.bundle/serious/resource/chat_bubble_receive_alpha20@3x.png differ diff --git a/iOS/TUIKit/TUIChat/Resources/TUIChatTheme.bundle/serious/resource/chat_bubble_receive_alpha50@3x.png b/iOS/TUIKit/TUIChat/Resources/TUIChatTheme.bundle/serious/resource/chat_bubble_receive_alpha50@3x.png index c108f762e..6b0a8a120 100644 Binary files a/iOS/TUIKit/TUIChat/Resources/TUIChatTheme.bundle/serious/resource/chat_bubble_receive_alpha50@3x.png and b/iOS/TUIKit/TUIChat/Resources/TUIChatTheme.bundle/serious/resource/chat_bubble_receive_alpha50@3x.png differ diff --git a/iOS/TUIKit/TUIChat/Resources/TUIChatTheme.bundle/serious/resource/chat_bubble_send@3x.png b/iOS/TUIKit/TUIChat/Resources/TUIChatTheme.bundle/serious/resource/chat_bubble_send@3x.png index a2000b69f..07c119069 100644 Binary files a/iOS/TUIKit/TUIChat/Resources/TUIChatTheme.bundle/serious/resource/chat_bubble_send@3x.png and b/iOS/TUIKit/TUIChat/Resources/TUIChatTheme.bundle/serious/resource/chat_bubble_send@3x.png differ diff --git a/iOS/TUIKit/TUIChat/Resources/TUIChatTheme.bundle/serious/resource/chat_bubble_send_alpha20@3x.png b/iOS/TUIKit/TUIChat/Resources/TUIChatTheme.bundle/serious/resource/chat_bubble_send_alpha20@3x.png index 5b8cb8b87..611b1a996 100644 Binary files a/iOS/TUIKit/TUIChat/Resources/TUIChatTheme.bundle/serious/resource/chat_bubble_send_alpha20@3x.png and b/iOS/TUIKit/TUIChat/Resources/TUIChatTheme.bundle/serious/resource/chat_bubble_send_alpha20@3x.png differ diff --git a/iOS/TUIKit/TUIChat/Resources/TUIChatTheme.bundle/serious/resource/chat_bubble_send_alpha50@3x.png b/iOS/TUIKit/TUIChat/Resources/TUIChatTheme.bundle/serious/resource/chat_bubble_send_alpha50@3x.png index c2954e158..a3aaca417 100644 Binary files a/iOS/TUIKit/TUIChat/Resources/TUIChatTheme.bundle/serious/resource/chat_bubble_send_alpha50@3x.png and b/iOS/TUIKit/TUIChat/Resources/TUIChatTheme.bundle/serious/resource/chat_bubble_send_alpha50@3x.png differ diff --git a/iOS/TUIKit/TUIChat/Resources/TUIChatTheme.bundle/serious/resource/chat_more_camera@3x.png b/iOS/TUIKit/TUIChat/Resources/TUIChatTheme.bundle/serious/resource/chat_more_camera@3x.png index f201c4fe8..e6a9d319d 100644 Binary files a/iOS/TUIKit/TUIChat/Resources/TUIChatTheme.bundle/serious/resource/chat_more_camera@3x.png and b/iOS/TUIKit/TUIChat/Resources/TUIChatTheme.bundle/serious/resource/chat_more_camera@3x.png differ diff --git a/iOS/TUIKit/TUIChat/Resources/TUIChatTheme.bundle/serious/resource/chat_more_file@3x.png b/iOS/TUIKit/TUIChat/Resources/TUIChatTheme.bundle/serious/resource/chat_more_file@3x.png index 64c49e6cc..57d7d3d83 100644 Binary files a/iOS/TUIKit/TUIChat/Resources/TUIChatTheme.bundle/serious/resource/chat_more_file@3x.png and b/iOS/TUIKit/TUIChat/Resources/TUIChatTheme.bundle/serious/resource/chat_more_file@3x.png differ diff --git a/iOS/TUIKit/TUIChat/Resources/TUIChatTheme.bundle/serious/resource/chat_more_groupnote@3x.png b/iOS/TUIKit/TUIChat/Resources/TUIChatTheme.bundle/serious/resource/chat_more_groupnote@3x.png index acc41a783..8fb611a9e 100644 Binary files a/iOS/TUIKit/TUIChat/Resources/TUIChatTheme.bundle/serious/resource/chat_more_groupnote@3x.png and b/iOS/TUIKit/TUIChat/Resources/TUIChatTheme.bundle/serious/resource/chat_more_groupnote@3x.png differ diff --git a/iOS/TUIKit/TUIChat/Resources/TUIChatTheme.bundle/serious/resource/chat_more_link@3x.png b/iOS/TUIKit/TUIChat/Resources/TUIChatTheme.bundle/serious/resource/chat_more_link@3x.png index 2e7b20f12..09ee4f102 100644 Binary files a/iOS/TUIKit/TUIChat/Resources/TUIChatTheme.bundle/serious/resource/chat_more_link@3x.png and b/iOS/TUIKit/TUIChat/Resources/TUIChatTheme.bundle/serious/resource/chat_more_link@3x.png differ diff --git a/iOS/TUIKit/TUIChat/Resources/TUIChatTheme.bundle/serious/resource/chat_more_picture@3x.png b/iOS/TUIKit/TUIChat/Resources/TUIChatTheme.bundle/serious/resource/chat_more_picture@3x.png index 09f26ea43..88fd7579d 100644 Binary files a/iOS/TUIKit/TUIChat/Resources/TUIChatTheme.bundle/serious/resource/chat_more_picture@3x.png and b/iOS/TUIKit/TUIChat/Resources/TUIChatTheme.bundle/serious/resource/chat_more_picture@3x.png differ diff --git a/iOS/TUIKit/TUIChat/Resources/TUIChatTheme.bundle/serious/resource/chat_more_poll@3x.png b/iOS/TUIKit/TUIChat/Resources/TUIChatTheme.bundle/serious/resource/chat_more_poll@3x.png index be52e9a1b..addad7591 100644 Binary files a/iOS/TUIKit/TUIChat/Resources/TUIChatTheme.bundle/serious/resource/chat_more_poll@3x.png and b/iOS/TUIKit/TUIChat/Resources/TUIChatTheme.bundle/serious/resource/chat_more_poll@3x.png differ diff --git a/iOS/TUIKit/TUIChat/Resources/TUIChatTheme.bundle/serious/resource/chat_more_video@3x.png b/iOS/TUIKit/TUIChat/Resources/TUIChatTheme.bundle/serious/resource/chat_more_video@3x.png index cc3776137..7d89281fb 100644 Binary files a/iOS/TUIKit/TUIChat/Resources/TUIChatTheme.bundle/serious/resource/chat_more_video@3x.png and b/iOS/TUIKit/TUIChat/Resources/TUIChatTheme.bundle/serious/resource/chat_more_video@3x.png differ diff --git a/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/ReceiverTextNodeBkg@3x.png b/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/ReceiverTextNodeBkg@3x.png index 35e58918e..649376490 100644 Binary files a/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/ReceiverTextNodeBkg@3x.png and b/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/ReceiverTextNodeBkg@3x.png differ diff --git a/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/ReceiverTextNodeBkg_Same@3x.png b/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/ReceiverTextNodeBkg_Same@3x.png index fb8c20ef5..06e2f9ca7 100644 Binary files a/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/ReceiverTextNodeBkg_Same@3x.png and b/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/ReceiverTextNodeBkg_Same@3x.png differ diff --git a/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/SenderTextNodeBkg@3x.png b/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/SenderTextNodeBkg@3x.png index a6bfaecb9..bdcd3e8a8 100644 Binary files a/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/SenderTextNodeBkg@3x.png and b/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/SenderTextNodeBkg@3x.png differ diff --git a/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/SenderTextNodeBkg_Same@3x.png b/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/SenderTextNodeBkg_Same@3x.png index 61ea689e1..10d60356f 100644 Binary files a/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/SenderTextNodeBkg_Same@3x.png and b/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/SenderTextNodeBkg_Same@3x.png differ diff --git a/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/ToolViewEmotion@3x.png b/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/ToolViewEmotion@3x.png index 01cd89652..7df9b6b44 100644 Binary files a/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/ToolViewEmotion@3x.png and b/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/ToolViewEmotion@3x.png differ diff --git a/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/ToolViewInputCamera@3x.png b/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/ToolViewInputCamera@3x.png index 2af0c75a3..b04efbeeb 100644 Binary files a/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/ToolViewInputCamera@3x.png and b/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/ToolViewInputCamera@3x.png differ diff --git a/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/ToolViewInputVoice@3x.png b/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/ToolViewInputVoice@3x.png index 34dd5d62e..44bb93146 100644 Binary files a/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/ToolViewInputVoice@3x.png and b/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/ToolViewInputVoice@3x.png differ diff --git a/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/TypeSelectorBtnHL_Black@3x.png b/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/TypeSelectorBtnHL_Black@3x.png index dc787bcc9..9ba965fb9 100644 Binary files a/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/TypeSelectorBtnHL_Black@3x.png and b/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/TypeSelectorBtnHL_Black@3x.png differ diff --git a/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/audio_call@3x.png b/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/audio_call@3x.png index e4e369740..00fc282b3 100644 Binary files a/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/audio_call@3x.png and b/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/audio_call@3x.png differ diff --git a/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/file_download@3x.png b/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/file_download@3x.png index 022c26b2a..4c83f9653 100644 Binary files a/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/file_download@3x.png and b/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/file_download@3x.png differ diff --git a/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/icon_emoji_more@3x.png b/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/icon_emoji_more@3x.png index 7b36c2aab..88d861753 100644 Binary files a/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/icon_emoji_more@3x.png and b/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/icon_emoji_more@3x.png differ diff --git a/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/icon_extion_copy@3x.png b/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/icon_extion_copy@3x.png index 9ef35161f..b5bccd468 100644 Binary files a/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/icon_extion_copy@3x.png and b/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/icon_extion_copy@3x.png differ diff --git a/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/icon_extion_delete@3x.png b/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/icon_extion_delete@3x.png index deea720b0..09f9cb226 100644 Binary files a/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/icon_extion_delete@3x.png and b/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/icon_extion_delete@3x.png differ diff --git a/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/icon_extion_forward@3x.png b/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/icon_extion_forward@3x.png index d84aa969c..63c9916f2 100644 Binary files a/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/icon_extion_forward@3x.png and b/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/icon_extion_forward@3x.png differ diff --git a/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/icon_extion_handset.png b/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/icon_extion_handset.png new file mode 100644 index 000000000..7695c4010 Binary files /dev/null and b/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/icon_extion_handset.png differ diff --git a/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/icon_extion_info@3x.png b/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/icon_extion_info@3x.png index 756ba10f2..364e7e05f 100644 Binary files a/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/icon_extion_info@3x.png and b/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/icon_extion_info@3x.png differ diff --git a/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/icon_extion_loudspeaker.png b/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/icon_extion_loudspeaker.png new file mode 100644 index 000000000..2758b78a6 Binary files /dev/null and b/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/icon_extion_loudspeaker.png differ diff --git a/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/icon_extion_more@3x.png b/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/icon_extion_more@3x.png index 32cf375fe..089fa3b9d 100644 Binary files a/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/icon_extion_more@3x.png and b/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/icon_extion_more@3x.png differ diff --git a/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/icon_extion_multi@3x.png b/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/icon_extion_multi@3x.png index 7702af967..170d2bb98 100644 Binary files a/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/icon_extion_multi@3x.png and b/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/icon_extion_multi@3x.png differ diff --git a/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/icon_extion_quote@3x.png b/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/icon_extion_quote@3x.png index cb8fbec5f..2dc5259f9 100644 Binary files a/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/icon_extion_quote@3x.png and b/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/icon_extion_quote@3x.png differ diff --git a/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/icon_extion_reply@3x.png b/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/icon_extion_reply@3x.png index 95d53a965..aa55e5abd 100644 Binary files a/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/icon_extion_reply@3x.png and b/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/icon_extion_reply@3x.png differ diff --git a/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/icon_extion_revocation@3x.png b/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/icon_extion_revocation@3x.png index eef52ef7d..77e04eb0c 100644 Binary files a/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/icon_extion_revocation@3x.png and b/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/icon_extion_revocation@3x.png differ diff --git a/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/icon_flex_arrow@3x.png b/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/icon_flex_arrow@3x.png index c92575a1a..d4f63158c 100644 Binary files a/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/icon_flex_arrow@3x.png and b/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/icon_flex_arrow@3x.png differ diff --git a/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/icon_more_camera@3x.png b/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/icon_more_camera@3x.png index 05512b25b..a9b80c144 100644 Binary files a/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/icon_more_camera@3x.png and b/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/icon_more_camera@3x.png differ diff --git a/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/icon_more_contact@3x.png b/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/icon_more_contact@3x.png index 7ca26b817..aeaba838a 100644 Binary files a/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/icon_more_contact@3x.png and b/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/icon_more_contact@3x.png differ diff --git a/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/icon_more_custom@3x.png b/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/icon_more_custom@3x.png index 9807ab43c..908cdae5f 100644 Binary files a/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/icon_more_custom@3x.png and b/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/icon_more_custom@3x.png differ diff --git a/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/icon_more_document@3x.png b/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/icon_more_document@3x.png index 736cca8e4..42a17dfc2 100644 Binary files a/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/icon_more_document@3x.png and b/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/icon_more_document@3x.png differ diff --git a/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/icon_more_photo@3x.png b/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/icon_more_photo@3x.png index 22a07f608..bef3e8bb9 100644 Binary files a/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/icon_more_photo@3x.png and b/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/icon_more_photo@3x.png differ diff --git a/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/icon_more_video@3x.png b/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/icon_more_video@3x.png index 5379c1a00..dc01ba53a 100644 Binary files a/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/icon_more_video@3x.png and b/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/icon_more_video@3x.png differ diff --git a/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/icon_mutilselect_delete@3x.png b/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/icon_mutilselect_delete@3x.png index e8229c203..02a99e6e2 100644 Binary files a/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/icon_mutilselect_delete@3x.png and b/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/icon_mutilselect_delete@3x.png differ diff --git a/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/icon_mutilselect_forward@3x.png b/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/icon_mutilselect_forward@3x.png index 4ed283e32..23129a8e5 100644 Binary files a/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/icon_mutilselect_forward@3x.png and b/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/icon_mutilselect_forward@3x.png differ diff --git a/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/icon_translate@2x.png b/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/icon_translate@2x.png index 62ba2c5f1..a94f75cfd 100644 Binary files a/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/icon_translate@2x.png and b/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/icon_translate@2x.png differ diff --git a/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/icon_translate@3x.png b/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/icon_translate@3x.png index 8b0a6c336..cad3dc177 100644 Binary files a/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/icon_translate@3x.png and b/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/icon_translate@3x.png differ diff --git a/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/msg_reply_line_income@3x.png b/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/msg_reply_line_income@3x.png index bc7020674..f4418c263 100644 Binary files a/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/msg_reply_line_income@3x.png and b/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/msg_reply_line_income@3x.png differ diff --git a/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/msg_reply_line_outcome@3x.png b/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/msg_reply_line_outcome@3x.png index 2d0382ea4..022dc982f 100644 Binary files a/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/msg_reply_line_outcome@3x.png and b/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/msg_reply_line_outcome@3x.png differ diff --git a/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/msg_reply_more_icon@3x.png b/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/msg_reply_more_icon@3x.png index e2e29fb43..20c7ce5ed 100644 Binary files a/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/msg_reply_more_icon@3x.png and b/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/msg_reply_more_icon@3x.png differ diff --git a/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/msg_status_all_people_read@3x.png b/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/msg_status_all_people_read@3x.png index fb55ce97d..6e6107e09 100644 Binary files a/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/msg_status_all_people_read@3x.png and b/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/msg_status_all_people_read@3x.png differ diff --git a/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/msg_status_send_succ@3x.png b/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/msg_status_send_succ@3x.png index 7f5e7abc5..64508c7e1 100644 Binary files a/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/msg_status_send_succ@3x.png and b/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/msg_status_send_succ@3x.png differ diff --git a/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/msg_status_sending_10@3x.png b/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/msg_status_sending_10@3x.png index 5f83d43d6..da9929a7f 100644 Binary files a/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/msg_status_sending_10@3x.png and b/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/msg_status_sending_10@3x.png differ diff --git a/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/msg_status_sending_11@3x.png b/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/msg_status_sending_11@3x.png index 66c6907e3..b1bf4640a 100644 Binary files a/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/msg_status_sending_11@3x.png and b/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/msg_status_sending_11@3x.png differ diff --git a/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/msg_status_sending_12@3x.png b/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/msg_status_sending_12@3x.png index 728a6716f..7b0c3094e 100644 Binary files a/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/msg_status_sending_12@3x.png and b/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/msg_status_sending_12@3x.png differ diff --git a/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/msg_status_sending_13@3x.png b/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/msg_status_sending_13@3x.png index 85bd8295e..884cdffb6 100644 Binary files a/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/msg_status_sending_13@3x.png and b/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/msg_status_sending_13@3x.png differ diff --git a/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/msg_status_sending_14@3x.png b/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/msg_status_sending_14@3x.png index e1e160d63..917febaed 100644 Binary files a/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/msg_status_sending_14@3x.png and b/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/msg_status_sending_14@3x.png differ diff --git a/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/msg_status_sending_15@3x.png b/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/msg_status_sending_15@3x.png index 9fe2306a7..4a36751b1 100644 Binary files a/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/msg_status_sending_15@3x.png and b/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/msg_status_sending_15@3x.png differ diff --git a/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/msg_status_sending_16@3x.png b/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/msg_status_sending_16@3x.png index 6ed58695e..779105fd4 100644 Binary files a/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/msg_status_sending_16@3x.png and b/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/msg_status_sending_16@3x.png differ diff --git a/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/msg_status_sending_17@3x.png b/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/msg_status_sending_17@3x.png index 3f5bfcfc8..9ce95ae84 100644 Binary files a/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/msg_status_sending_17@3x.png and b/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/msg_status_sending_17@3x.png differ diff --git a/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/msg_status_sending_18@3x.png b/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/msg_status_sending_18@3x.png index 258dcfd2b..32d66ae5b 100644 Binary files a/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/msg_status_sending_18@3x.png and b/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/msg_status_sending_18@3x.png differ diff --git a/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/msg_status_sending_19@3x.png b/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/msg_status_sending_19@3x.png index a43e88dab..92d117482 100644 Binary files a/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/msg_status_sending_19@3x.png and b/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/msg_status_sending_19@3x.png differ diff --git a/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/msg_status_sending_1@3x.png b/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/msg_status_sending_1@3x.png index f287949d7..0333d66df 100644 Binary files a/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/msg_status_sending_1@3x.png and b/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/msg_status_sending_1@3x.png differ diff --git a/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/msg_status_sending_20@3x.png b/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/msg_status_sending_20@3x.png index 46fa5e562..672181d1e 100644 Binary files a/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/msg_status_sending_20@3x.png and b/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/msg_status_sending_20@3x.png differ diff --git a/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/msg_status_sending_21@3x.png b/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/msg_status_sending_21@3x.png index f23c6c77e..e4ba599ab 100644 Binary files a/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/msg_status_sending_21@3x.png and b/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/msg_status_sending_21@3x.png differ diff --git a/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/msg_status_sending_22@3x.png b/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/msg_status_sending_22@3x.png index a893b1d05..98cff8e4e 100644 Binary files a/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/msg_status_sending_22@3x.png and b/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/msg_status_sending_22@3x.png differ diff --git a/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/msg_status_sending_23@3x.png b/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/msg_status_sending_23@3x.png index 3939e27ce..583b064c4 100644 Binary files a/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/msg_status_sending_23@3x.png and b/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/msg_status_sending_23@3x.png differ diff --git a/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/msg_status_sending_24@3x.png b/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/msg_status_sending_24@3x.png index b54b91e77..990b64b28 100644 Binary files a/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/msg_status_sending_24@3x.png and b/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/msg_status_sending_24@3x.png differ diff --git a/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/msg_status_sending_25@3x.png b/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/msg_status_sending_25@3x.png index 67b94e5e7..8490ea9e7 100644 Binary files a/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/msg_status_sending_25@3x.png and b/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/msg_status_sending_25@3x.png differ diff --git a/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/msg_status_sending_26@3x.png b/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/msg_status_sending_26@3x.png index 20c57657b..5830e1cef 100644 Binary files a/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/msg_status_sending_26@3x.png and b/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/msg_status_sending_26@3x.png differ diff --git a/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/msg_status_sending_27@3x.png b/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/msg_status_sending_27@3x.png index 980a47d14..4c53415fe 100644 Binary files a/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/msg_status_sending_27@3x.png and b/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/msg_status_sending_27@3x.png differ diff --git a/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/msg_status_sending_28@3x.png b/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/msg_status_sending_28@3x.png index 37d60fb54..a46bf2778 100644 Binary files a/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/msg_status_sending_28@3x.png and b/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/msg_status_sending_28@3x.png differ diff --git a/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/msg_status_sending_29@3x.png b/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/msg_status_sending_29@3x.png index d86bef85b..c32d2e0e9 100644 Binary files a/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/msg_status_sending_29@3x.png and b/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/msg_status_sending_29@3x.png differ diff --git a/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/msg_status_sending_2@3x.png b/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/msg_status_sending_2@3x.png index 7ce6de6bb..27021aae7 100644 Binary files a/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/msg_status_sending_2@3x.png and b/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/msg_status_sending_2@3x.png differ diff --git a/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/msg_status_sending_30@3x.png b/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/msg_status_sending_30@3x.png index 6d70dd33b..6025ba7a0 100644 Binary files a/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/msg_status_sending_30@3x.png and b/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/msg_status_sending_30@3x.png differ diff --git a/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/msg_status_sending_31@3x.png b/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/msg_status_sending_31@3x.png index 0de4d1082..a6ebf210d 100644 Binary files a/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/msg_status_sending_31@3x.png and b/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/msg_status_sending_31@3x.png differ diff --git a/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/msg_status_sending_32@3x.png b/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/msg_status_sending_32@3x.png index 50f84af67..281a9e363 100644 Binary files a/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/msg_status_sending_32@3x.png and b/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/msg_status_sending_32@3x.png differ diff --git a/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/msg_status_sending_33@3x.png b/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/msg_status_sending_33@3x.png index 22e37c8a2..0dc299cda 100644 Binary files a/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/msg_status_sending_33@3x.png and b/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/msg_status_sending_33@3x.png differ diff --git a/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/msg_status_sending_34@3x.png b/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/msg_status_sending_34@3x.png index 1bac7a316..d868ac970 100644 Binary files a/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/msg_status_sending_34@3x.png and b/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/msg_status_sending_34@3x.png differ diff --git a/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/msg_status_sending_35@3x.png b/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/msg_status_sending_35@3x.png index 96e2fca49..58f97e522 100644 Binary files a/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/msg_status_sending_35@3x.png and b/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/msg_status_sending_35@3x.png differ diff --git a/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/msg_status_sending_36@3x.png b/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/msg_status_sending_36@3x.png index e89bb9b2f..040edf721 100644 Binary files a/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/msg_status_sending_36@3x.png and b/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/msg_status_sending_36@3x.png differ diff --git a/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/msg_status_sending_37@3x.png b/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/msg_status_sending_37@3x.png index 9a087b17a..2135b4781 100644 Binary files a/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/msg_status_sending_37@3x.png and b/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/msg_status_sending_37@3x.png differ diff --git a/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/msg_status_sending_38@3x.png b/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/msg_status_sending_38@3x.png index 4570e9743..f5582bf63 100644 Binary files a/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/msg_status_sending_38@3x.png and b/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/msg_status_sending_38@3x.png differ diff --git a/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/msg_status_sending_39@3x.png b/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/msg_status_sending_39@3x.png index a61814996..e6a366ccf 100644 Binary files a/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/msg_status_sending_39@3x.png and b/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/msg_status_sending_39@3x.png differ diff --git a/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/msg_status_sending_3@3x.png b/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/msg_status_sending_3@3x.png index e0b9263b4..23aac5188 100644 Binary files a/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/msg_status_sending_3@3x.png and b/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/msg_status_sending_3@3x.png differ diff --git a/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/msg_status_sending_40@3x.png b/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/msg_status_sending_40@3x.png index d962c8b90..bf0cc0272 100644 Binary files a/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/msg_status_sending_40@3x.png and b/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/msg_status_sending_40@3x.png differ diff --git a/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/msg_status_sending_41@3x.png b/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/msg_status_sending_41@3x.png index 13387ccc9..a824e2d33 100644 Binary files a/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/msg_status_sending_41@3x.png and b/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/msg_status_sending_41@3x.png differ diff --git a/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/msg_status_sending_42@3x.png b/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/msg_status_sending_42@3x.png index 052666df3..a0960b589 100644 Binary files a/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/msg_status_sending_42@3x.png and b/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/msg_status_sending_42@3x.png differ diff --git a/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/msg_status_sending_43@3x.png b/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/msg_status_sending_43@3x.png index 8c8c642f1..31c1c8c9e 100644 Binary files a/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/msg_status_sending_43@3x.png and b/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/msg_status_sending_43@3x.png differ diff --git a/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/msg_status_sending_44@3x.png b/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/msg_status_sending_44@3x.png index 6c8e2a79b..c2aae37e8 100644 Binary files a/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/msg_status_sending_44@3x.png and b/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/msg_status_sending_44@3x.png differ diff --git a/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/msg_status_sending_45@3x.png b/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/msg_status_sending_45@3x.png index fb68c457d..a7d64daa3 100644 Binary files a/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/msg_status_sending_45@3x.png and b/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/msg_status_sending_45@3x.png differ diff --git a/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/msg_status_sending_4@3x.png b/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/msg_status_sending_4@3x.png index caaddaada..32cc0f676 100644 Binary files a/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/msg_status_sending_4@3x.png and b/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/msg_status_sending_4@3x.png differ diff --git a/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/msg_status_sending_5@3x.png b/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/msg_status_sending_5@3x.png index f0571d99f..526cfd4a2 100644 Binary files a/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/msg_status_sending_5@3x.png and b/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/msg_status_sending_5@3x.png differ diff --git a/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/msg_status_sending_6@3x.png b/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/msg_status_sending_6@3x.png index 2de9f1e1b..576209d39 100644 Binary files a/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/msg_status_sending_6@3x.png and b/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/msg_status_sending_6@3x.png differ diff --git a/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/msg_status_sending_7@3x.png b/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/msg_status_sending_7@3x.png index d963a97e4..9002debd9 100644 Binary files a/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/msg_status_sending_7@3x.png and b/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/msg_status_sending_7@3x.png differ diff --git a/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/msg_status_sending_8@3x.png b/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/msg_status_sending_8@3x.png index 506a79ca9..844326180 100644 Binary files a/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/msg_status_sending_8@3x.png and b/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/msg_status_sending_8@3x.png differ diff --git a/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/msg_status_sending_9@3x.png b/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/msg_status_sending_9@3x.png index 89f94cdca..800f0a734 100644 Binary files a/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/msg_status_sending_9@3x.png and b/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/msg_status_sending_9@3x.png differ diff --git a/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/msg_status_some_people_read@3x.png b/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/msg_status_some_people_read@3x.png index 7cec345b3..299fe3a8f 100644 Binary files a/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/msg_status_some_people_read@3x.png and b/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/msg_status_some_people_read@3x.png differ diff --git a/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/small_tongue_bk@3x.png b/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/small_tongue_bk@3x.png index 72db94d83..90aa69124 100644 Binary files a/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/small_tongue_bk@3x.png and b/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/small_tongue_bk@3x.png differ diff --git a/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/small_tongue_scroll_to_boom@3x.png b/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/small_tongue_scroll_to_boom@3x.png index d68ad594d..bbd42c674 100644 Binary files a/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/small_tongue_scroll_to_boom@3x.png and b/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/small_tongue_scroll_to_boom@3x.png differ diff --git a/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/small_tongue_someone_at_me@3x.png b/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/small_tongue_someone_at_me@3x.png index ae3fd3cfe..3abc88144 100644 Binary files a/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/small_tongue_someone_at_me@3x.png and b/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/small_tongue_someone_at_me@3x.png differ diff --git a/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/vc_back@3x.png b/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/vc_back@3x.png index 09a49a126..61acb534a 100644 Binary files a/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/vc_back@3x.png and b/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/vc_back@3x.png differ diff --git a/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/video_call@3x.png b/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/video_call@3x.png index e2d7d5390..701ccd5c5 100644 Binary files a/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/video_call@3x.png and b/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/video_call@3x.png differ diff --git a/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/voice_pause@3x.png b/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/voice_pause@3x.png index 7aad209d8..85b5b69a6 100644 Binary files a/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/voice_pause@3x.png and b/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/voice_pause@3x.png differ diff --git a/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/voice_play@3x.png b/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/voice_play@3x.png index 47986a688..93a0c9313 100644 Binary files a/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/voice_play@3x.png and b/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/voice_play@3x.png differ diff --git a/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/voice_play_animation@3x.png b/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/voice_play_animation@3x.png index 74425262c..6ce8c80e1 100644 Binary files a/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/voice_play_animation@3x.png and b/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/voice_play_animation@3x.png differ diff --git a/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/voice_record_animation@3x.png b/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/voice_record_animation@3x.png index 31902ac51..a54805f22 100644 Binary files a/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/voice_record_animation@3x.png and b/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/voice_record_animation@3x.png differ diff --git a/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/voice_record_delete@3x.png b/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/voice_record_delete@3x.png index dd73efcba..be8cf2d40 100644 Binary files a/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/voice_record_delete@3x.png and b/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/voice_record_delete@3x.png differ diff --git a/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/voice_record_delete_ready@3x.png b/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/voice_record_delete_ready@3x.png index 25029b8e9..709d4b765 100644 Binary files a/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/voice_record_delete_ready@3x.png and b/iOS/TUIKit/TUIChat/Resources/TUIChat_Minimalist.bundle/voice_record_delete_ready@3x.png differ diff --git a/iOS/TUIKit/TUIChat/TUIChat.podspec b/iOS/TUIKit/TUIChat/TUIChat.podspec index ba466318e..e065bd127 100644 --- a/iOS/TUIKit/TUIChat/TUIChat.podspec +++ b/iOS/TUIKit/TUIChat/TUIChat.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |spec| spec.name = 'TUIChat' - spec.version = '7.4.4643' + spec.version = '7.5.4852' spec.platform = :ios spec.ios.deployment_target = '9.0' spec.license = { :type => 'Proprietary', diff --git a/iOS/TUIKit/TUIChat/UI_Classic/Cell/Base/TUIMemberCell.m b/iOS/TUIKit/TUIChat/UI_Classic/Cell/Base/TUIMemberCell.m index e7119cff0..af8dee8be 100644 --- a/iOS/TUIKit/TUIChat/UI_Classic/Cell/Base/TUIMemberCell.m +++ b/iOS/TUIKit/TUIChat/UI_Classic/Cell/Base/TUIMemberCell.m @@ -31,25 +31,15 @@ self.avatarView = [[UIImageView alloc] initWithImage:DefaultAvatarImage]; [self.contentView addSubview:self.avatarView]; - self.avatarView.mm_width(34).mm_height(34).mm__centerY(28).mm_left(12); - if ([TUIConfig defaultConfig].avatarType == TAvatarTypeRounded) { - self.avatarView.layer.masksToBounds = YES; - self.avatarView.layer.cornerRadius = self.avatarView.frame.size.height / 2; - } else if ([TUIConfig defaultConfig].avatarType == TAvatarTypeRadiusCorner) { - self.avatarView.layer.masksToBounds = YES; - self.avatarView.layer.cornerRadius = [TUIConfig defaultConfig].avatarCornerRadius; - } self.titleLabel = [[UILabel alloc] initWithFrame:CGRectZero]; [self.contentView addSubview:self.titleLabel]; self.titleLabel.textColor = TIMCommonDynamicColor(@"form_title_color", @"#000000"); - self.titleLabel.mm_left(self.avatarView.mm_maxX + 12).mm_height(20).mm_width(200).mm__centerY(self.avatarView.mm_centerY); self.detailLabel = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, 100, 20)]; [self.contentView addSubview:self.detailLabel]; - self.detailLabel.textAlignment = NSTextAlignmentRight; + self.detailLabel.rtlAlignment = TUITextRTLAlignmentTrailing; self.detailLabel.textColor = TIMCommonDynamicColor(@"form_title_color", @"#000000"); - self.detailLabel.mm__centerY(self.avatarView.mm_centerY); [self setSelectionStyle:UITableViewCellSelectionStyleNone]; @@ -60,8 +50,6 @@ - (void)layoutSubviews { [super layoutSubviews]; - self.detailLabel.mm_sizeToFit(); - self.detailLabel.mm_right(12); } #pragma mark - Public @@ -73,6 +61,55 @@ [self.avatarView sd_setImageWithURL:cellData.avatarUrL placeholderImage:DefaultAvatarImage]; self.detailLabel.hidden = cellData.detail.length == 0; self.detailLabel.text = cellData.detail; + + // tell constraints they need updating + [self setNeedsUpdateConstraints]; + + // update constraints now so we can animate the change + [self updateConstraintsIfNeeded]; + + [self layoutIfNeeded]; } ++ (BOOL)requiresConstraintBasedLayout { + return YES; +} + +// this is Apple's recommended place for adding/updating constraints +- (void)updateConstraints { + + [super updateConstraints]; + + CGFloat imgWidth = kScale390(34); + + [self.avatarView mas_remakeConstraints:^(MASConstraintMaker *make) { + make.width.height.mas_equalTo(imgWidth); + make.centerY.mas_equalTo(self.contentView.mas_centerY); + make.leading.mas_equalTo(kScale390(12)); + }]; + if ([TUIConfig defaultConfig].avatarType == TAvatarTypeRounded) { + self.avatarView.layer.masksToBounds = YES; + self.avatarView.layer.cornerRadius = imgWidth / 2; + } else if ([TUIConfig defaultConfig].avatarType == TAvatarTypeRadiusCorner) { + self.avatarView.layer.masksToBounds = YES; + self.avatarView.layer.cornerRadius = [TUIConfig defaultConfig].avatarCornerRadius; + } + + [self.titleLabel mas_remakeConstraints:^(MASConstraintMaker *make) { + make.centerY.mas_equalTo(self.avatarView.mas_centerY); + make.leading.mas_equalTo(self.avatarView.mas_trailing).mas_offset(12); + make.height.mas_equalTo(20); + make.trailing.lessThanOrEqualTo(self.detailLabel.mas_leading).mas_offset(-5); + }]; + + [self.detailLabel sizeToFit]; + [self.detailLabel mas_remakeConstraints:^(MASConstraintMaker *make) { + make.centerY.mas_equalTo(self.avatarView.mas_centerY); + make.height.mas_equalTo(20); + make.trailing.mas_equalTo(self.contentView.mas_trailing).mas_offset(-3); + make.width.mas_equalTo(self.detailLabel.frame.size.width); + }]; + + +} @end diff --git a/iOS/TUIKit/TUIChat/UI_Classic/Cell/Base/TUITextMessageCell.m b/iOS/TUIKit/TUIChat/UI_Classic/Cell/Base/TUITextMessageCell.m index 72062260d..fd8d5fa65 100644 --- a/iOS/TUIKit/TUIChat/UI_Classic/Cell/Base/TUITextMessageCell.m +++ b/iOS/TUIKit/TUIChat/UI_Classic/Cell/Base/TUITextMessageCell.m @@ -84,23 +84,41 @@ self.textView.attributedText = [data getAttributedString:textFont]; self.textView.textColor = textColor; self.textView.font = textFont; + + // tell constraints they need updating + [self setNeedsUpdateConstraints]; + + // update constraints now so we can animate the change + [self updateConstraintsIfNeeded]; + + [self layoutIfNeeded]; } -- (void)layoutSubviews { - [super layoutSubviews]; - self.textView.frame = (CGRect){.origin = self.textData.textOrigin, .size = self.textData.textSize}; - if (self.voiceReadPoint.hidden == NO) { - self.voiceReadPoint.frame = CGRectMake(CGRectGetMaxX(self.bubbleView.frame), 0, 5, 5); - } - if (self.messageData.messageModifyReactsSize.height > 0) { - if (self.tagView) { - CGFloat tagViewTopPadding = 6; - self.tagView.frame = CGRectMake(0, self.container.mm_h - self.messageData.messageModifyReactsSize.height - tagViewTopPadding, - self.container.frame.size.width, self.messageData.messageModifyReactsSize.height); - } - } ++ (BOOL)requiresConstraintBasedLayout { + return YES; +} +// this is Apple's recommended place for adding/updating constraints +- (void)updateConstraints { + + [super updateConstraints]; + + [self.textView mas_remakeConstraints:^(MASConstraintMaker *make) { + make.leading.mas_equalTo(self.bubbleView.mas_leading).mas_offset(self.textData.textOrigin.x); + make.top.mas_equalTo(self.bubbleView.mas_top).mas_offset(self.textData.textOrigin.y); + make.size.mas_equalTo(self.textData.textSize); + }]; + + if (self.voiceReadPoint.hidden == NO) { + [self.voiceReadPoint mas_remakeConstraints:^(MASConstraintMaker *make) { + make.top.mas_equalTo(self.bubbleView); + make.leading.mas_equalTo(self.bubbleView.mas_trailing).mas_offset(1); + make.size.mas_equalTo(CGSizeMake(5, 5)); + }]; + } + [self layoutBottomContainer]; + } - (void)layoutBottomContainer { @@ -109,18 +127,29 @@ } CGSize size = self.textData.bottomContainerSize; - CGFloat topMargin = self.bubbleView.mm_maxY + self.nameLabel.mm_h + 6; - if (self.textData.direction == MsgDirectionOutgoing) { - self.bottomContainer.mm_top(topMargin).mm_width(size.width).mm_height(size.height).mm_right(self.mm_w - self.container.mm_maxX); - } else { - self.bottomContainer.mm_top(topMargin).mm_width(size.width).mm_height(size.height).mm_left(self.container.mm_minX); - } + [self.bottomContainer mas_remakeConstraints:^(MASConstraintMaker *make) { + if (self.textData.direction == MsgDirectionIncoming) { + make.leading.mas_equalTo(self.container.mas_leading); + } + else { + make.trailing.mas_equalTo(self.container.mas_trailing); + } + make.top.mas_equalTo(self.container.mas_bottom).offset(6); + make.size.mas_equalTo(size); + }]; + CGFloat repliesBtnTextWidth = self.messageModifyRepliesButton.frame.size.width; if (!self.messageModifyRepliesButton.hidden) { - CGRect oldRect = self.messageModifyRepliesButton.frame; - CGRect newRect = CGRectMake(oldRect.origin.x, CGRectGetMaxY(self.bottomContainer.frame), oldRect.size.width, oldRect.size.height); - self.messageModifyRepliesButton.frame = newRect; + [self.messageModifyRepliesButton mas_remakeConstraints:^(MASConstraintMaker *make) { + if (self.textData.direction == MsgDirectionIncoming) { + make.leading.mas_equalTo(self.container.mas_leading); + } else { + make.trailing.mas_equalTo(self.container.mas_trailing); + } + make.top.mas_equalTo(self.bottomContainer.mas_bottom); + make.size.mas_equalTo(CGSizeMake(repliesBtnTextWidth + 10, 30)); + }]; } } diff --git a/iOS/TUIKit/TUIChat/UI_Classic/Cell/Chat/TUIFaceMessageCell.m b/iOS/TUIKit/TUIChat/UI_Classic/Cell/Chat/TUIFaceMessageCell.m index d3806abe2..049a98e80 100644 --- a/iOS/TUIKit/TUIChat/UI_Classic/Cell/Chat/TUIFaceMessageCell.m +++ b/iOS/TUIKit/TUIChat/UI_Classic/Cell/Chat/TUIFaceMessageCell.m @@ -28,32 +28,50 @@ - (void)layoutSubviews { [super layoutSubviews]; +} ++ (BOOL)requiresConstraintBasedLayout { + return YES; +} + +// this is Apple's recommended place for adding/updating constraints +- (void)updateConstraints { + [super updateConstraints]; + + CGFloat topMargin = 0; + CGFloat height = self.container.mm_h; if (self.messageData.messageModifyReactsSize.height > 0) { if (self.tagView) { - CGFloat topMargin = 10; + topMargin = 10; CGFloat tagViewTopPadding = 6; - CGFloat height = self.container.mm_h - topMargin - self.messageData.messageModifyReactsSize.height - tagViewTopPadding; - _face.mm_height(height).mm_left(0).mm_top(topMargin).mm_width(self.container.mm_w); - self.tagView.frame = CGRectMake(0, self.container.mm_h - self.messageData.messageModifyReactsSize.height - tagViewTopPadding, - self.container.frame.size.width, self.messageData.messageModifyReactsSize.height); + height = self.container.mm_h - topMargin - self.messageData.messageModifyReactsSize.height - tagViewTopPadding; } self.bubbleView.hidden = NO; } else { - CGFloat topMargin = 0; - CGFloat height = self.container.mm_h; - _face.mm_height(height).mm_left(0).mm_top(topMargin).mm_width(self.container.mm_w); self.bubbleView.hidden = YES; } - _face.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight; + [self.face mas_remakeConstraints:^(MASConstraintMaker *make) { + make.height.mas_equalTo(height); + make.centerX.mas_equalTo(self.container.mas_centerX); + make.top.mas_equalTo(topMargin); + make.width.mas_equalTo(self.container); + }]; + + } - (void)fillWithData:(TUIFaceMessageCellData *)data { // set data [super fillWithData:data]; self.faceData = data; - _face.image = [[TUIImageCache sharedInstance] getFaceFromCache:data.path]; - ; + + // tell constraints they need updating + [self setNeedsUpdateConstraints]; + + // update constraints now so we can animate the change + [self updateConstraintsIfNeeded]; + + [self layoutIfNeeded]; } #pragma mark - TUIMessageCellProtocol diff --git a/iOS/TUIKit/TUIChat/UI_Classic/Cell/Chat/TUIFileMessageCell.m b/iOS/TUIKit/TUIChat/UI_Classic/Cell/Chat/TUIFileMessageCell.m index bdee4d227..67ebc2352 100644 --- a/iOS/TUIKit/TUIChat/UI_Classic/Cell/Chat/TUIFileMessageCell.m +++ b/iOS/TUIKit/TUIChat/UI_Classic/Cell/Chat/TUIFileMessageCell.m @@ -72,6 +72,15 @@ NSInteger downloadProgress = [TUIMessageProgressManager.shareManager downloadProgressForMessage:self.fileData.msgID]; [self onUploadProgress:self.fileData.msgID progress:uploadProgress]; [self onDownloadProgress:self.fileData.msgID progress:downloadProgress]; + + // tell constraints they need updating + [self setNeedsUpdateConstraints]; + + // update constraints now so we can animate the change + [self updateConstraintsIfNeeded]; + + [self layoutIfNeeded]; + }); } @@ -119,22 +128,20 @@ } - (void)showProgressLodingAnimation:(NSInteger)progress { self.progressView.hidden = NO; - self.progressView.frame = CGRectMake(0, 0, self.progressView.mm_w ?: 1, self.fileContainer.mm_h); NSLog(@"showProgressLodingAnimation:%ld", (long)progress); [UIView animateWithDuration:0.25 animations:^{ - self.progressView.mm_x = 0; - self.progressView.mm_y = 0; - self.progressView.mm_h = self.fileContainer.mm_h; - self.progressView.mm_w = self.fileContainer.mm_w * progress / 100.0; - } - completion:^(BOOL finished) { - if (progress == 0 || progress >= 100) { - self.progressView.hidden = YES; - [self.indicator stopAnimating]; - self.length.text = [self formatLength:self.fileData.length]; - } + [self.progressView mas_updateConstraints:^(MASConstraintMaker *make) { + make.width.mas_equalTo(self.fileContainer.mm_w * progress / 100.0); }]; + } + completion:^(BOOL finished) { + if (progress == 0 || progress >= 100) { + self.progressView.hidden = YES; + [self.indicator stopAnimating]; + self.length.text = [self formatLength:self.fileData.length]; + } + }]; self.length.text = [self formatLength:self.fileData.length]; } @@ -181,28 +188,60 @@ return TUIChatImagePath(@"msg_file"); } -- (void)layoutSubviews { - [super layoutSubviews]; ++ (BOOL)requiresConstraintBasedLayout { + return YES; +} +// this is Apple's recommended place for adding/updating constraints +- (void)updateConstraints { + [super updateConstraints]; + CGSize containerSize = [self.class getContentSize:self.fileData]; - self.fileContainer.frame = CGRectMake(0, 0, containerSize.width, containerSize.height); + [self.fileContainer mas_remakeConstraints:^(MASConstraintMaker *make) { + make.center.mas_equalTo(self.container); + make.size.mas_equalTo(containerSize); + }]; + CGFloat imageHeight = containerSize.height - 2 * TFileMessageCell_Margin; CGFloat imageWidth = imageHeight; - _image.frame = CGRectMake(TFileMessageCell_Margin, TFileMessageCell_Margin, imageWidth, imageHeight); + [self.image mas_remakeConstraints:^(MASConstraintMaker *make) { + make.leading.mas_equalTo(self.container.mas_leading).mas_offset(TFileMessageCell_Margin); + make.top.mas_equalTo(self.container.mas_top).mas_offset(TFileMessageCell_Margin); + make.size.mas_equalTo(CGSizeMake(imageWidth, imageHeight)); + }]; + CGFloat textWidth = containerSize.width - 2 * TFileMessageCell_Margin - imageWidth; CGSize nameSize = [_fileName sizeThatFits:containerSize]; - _fileName.frame = - CGRectMake(_image.frame.origin.x + _image.frame.size.width + TFileMessageCell_Margin, TFileMessageCell_Margin, textWidth, nameSize.height); - CGSize lengthSize = [_length sizeThatFits:containerSize]; - _length.frame = - CGRectMake(_fileName.frame.origin.x, _fileName.frame.origin.y + nameSize.height + TFileMessageCell_Margin * 0.5, textWidth, lengthSize.height); + [self.fileName mas_remakeConstraints:^(MASConstraintMaker *make) { + make.leading.mas_equalTo(self.image.mas_trailing).mas_offset(TFileMessageCell_Margin); + make.top.mas_equalTo(self.image); + make.size.mas_equalTo(CGSizeMake(textWidth, nameSize.height)); + }]; + + CGSize lengthSize = [_length sizeThatFits:containerSize]; + [self.length mas_remakeConstraints:^(MASConstraintMaker *make) { + make.leading.mas_equalTo(self.fileName); + make.top.mas_equalTo(self.fileName.mas_bottom).mas_offset(TFileMessageCell_Margin * 0.5); + make.size.mas_equalTo(CGSizeMake(textWidth, nameSize.height)); + }]; + + if (self.messageData.messageModifyReactsSize.height > 0) { - self.fileContainer.frame = CGRectMake(0, 0, self.container.frame.size.width, self.container.frame.size.height); + [self.fileContainer mas_remakeConstraints:^(MASConstraintMaker *make) { + make.center.mas_equalTo(self.container); + make.size.mas_equalTo(self.container); + }]; + if (self.tagView) { - self.tagView.frame = - CGRectMake(0, TFileMessageCell_Margin + imageHeight, self.fileContainer.frame.size.width, self.messageData.messageModifyReactsSize.height); + [self.tagView mas_remakeConstraints:^(MASConstraintMaker *make) { + make.leading.mas_equalTo(self.container); + make.bottom.mas_equalTo(self.container); + make.width.mas_equalTo(self.container); + make.height.mas_equalTo(self.messageData.messageModifyReactsSize.height); + }]; } + self.bubble.hidden = NO; } else { self.bubble.hidden = YES; @@ -218,6 +257,17 @@ UIBezierPath *bezierPath = [UIBezierPath bezierPathWithRoundedRect:self.fileContainer.bounds byRoundingCorners:corner cornerRadii:CGSizeMake(10, 10)]; self.maskLayer.path = bezierPath.CGPath; self.borderLayer.path = bezierPath.CGPath; + + [self.progressView mas_remakeConstraints:^(MASConstraintMaker *make) { + make.leading.mas_equalTo(0); + make.top.mas_equalTo(0); + make.width.mas_equalTo(self.progressView.mm_w ?: 1); + make.height.mas_equalTo(self.fileContainer.mm_h); + }]; +} + +- (void)layoutSubviews { + [super layoutSubviews]; } - (CAShapeLayer *)maskLayer { diff --git a/iOS/TUIKit/TUIChat/UI_Classic/Cell/Chat/TUIImageMessageCell.m b/iOS/TUIKit/TUIChat/UI_Classic/Cell/Chat/TUIImageMessageCell.m index 16f3f56d3..62c785dbd 100644 --- a/iOS/TUIKit/TUIChat/UI_Classic/Cell/Chat/TUIImageMessageCell.m +++ b/iOS/TUIKit/TUIChat/UI_Classic/Cell/Chat/TUIImageMessageCell.m @@ -36,6 +36,7 @@ _progress.backgroundColor = TImageMessageCell_Progress_Color; [_progress.layer setMasksToBounds:YES]; [self.container addSubview:_progress]; + [self makeConstraints]; } return self; } @@ -64,31 +65,92 @@ self.progress.text = [NSString stringWithFormat:@"%d%%", progress]; self.progress.hidden = (progress >= 100 || progress == 0); }]; + + // tell constraints they need updating + [self setNeedsUpdateConstraints]; + + // update constraints now so we can animate the change + [self updateConstraintsIfNeeded]; + + [self layoutIfNeeded]; + +} + ++ (BOOL)requiresConstraintBasedLayout { + return YES; +} + +- (void)makeConstraints { + [self.thumb mas_makeConstraints:^(MASConstraintMaker *make) { + make.height.mas_equalTo(self.container); + make.width.mas_equalTo(self.container); + make.top.mas_equalTo(self.container); + make.leading.mas_equalTo(self.container); + }]; + + [self.progress mas_makeConstraints:^(MASConstraintMaker *make) { + make.edges.mas_equalTo(self.container); + }]; +} +// this is Apple's recommended place for adding/updating constraints +- (void)updateConstraints { + + [super updateConstraints]; + + CGFloat topMargin = 0; + CGFloat height = self.container.mm_h; + if (self.messageData.messageModifyReactsSize.height > 0) { + if (self.tagView) { + topMargin = 10; + CGFloat tagViewTopMargin = 6; + height = self.container.mm_h - topMargin - self.messageData.messageModifyReactsSize.height - tagViewTopMargin; + } + self.bubbleView.hidden = NO; + } else { + self.bubbleView.hidden = YES; + } + + [self.thumb mas_remakeConstraints:^(MASConstraintMaker *make) { + make.height.mas_equalTo(height); + make.width.mas_equalTo(self.container.mas_width); + make.top.mas_equalTo(self.container).mas_offset(topMargin); + make.leading.mas_equalTo(self.container); + }]; + + [self.progress mas_remakeConstraints:^(MASConstraintMaker *make) { + make.edges.mas_equalTo(self.container); + }]; + [self.selectedView mas_remakeConstraints:^(MASConstraintMaker *make) { + make.edges.mas_equalTo(self.contentView); + }]; + [self.selectedIcon mas_remakeConstraints:^(MASConstraintMaker *make) { + make.leading.mas_equalTo(self.contentView.mas_leading).mas_offset(3); + make.top.mas_equalTo(self.avatarView.mas_centerY).mas_offset(-10); + if (self.messageData.showCheckBox) { + make.width.mas_equalTo(20); + make.height.mas_equalTo(20); + } else { + make.size.mas_equalTo(CGSizeZero); + } + }]; + + [self.timeLabel sizeToFit]; + [self.timeLabel mas_remakeConstraints:^(MASConstraintMaker *make) { + make.trailing.mas_equalTo(self.contentView.mas_trailing).mas_offset(-10); + make.top.mas_equalTo(self.avatarView); + if (self.messageData.showMessageTime) { + make.width.mas_equalTo(self.timeLabel.frame.size.width); + make.height.mas_equalTo(self.timeLabel.frame.size.height); + } else { + make.width.mas_equalTo(0); + make.height.mas_equalTo(0); + } + }]; + } - (void)layoutSubviews { [super layoutSubviews]; - if (self.messageData.messageModifyReactsSize.height > 0) { - if (self.tagView) { - CGFloat topMargin = 10; - CGFloat tagViewTopMargin = 6; - CGFloat thumbHeight = self.container.mm_h - topMargin - self.messageData.messageModifyReactsSize.height - tagViewTopMargin; - _thumb.mm_height(thumbHeight).mm_left(0).mm_top(topMargin).mm_width(self.container.mm_w); - self.tagView.frame = CGRectMake(0, self.container.mm_h - self.messageData.messageModifyReactsSize.height - tagViewTopMargin, - self.container.frame.size.width, self.messageData.messageModifyReactsSize.height); - } - self.bubbleView.hidden = NO; - } else { - CGFloat topMargin = 0; - CGFloat height = self.container.mm_h; - _thumb.mm_height(height).mm_left(0).mm_top(topMargin).mm_width(self.container.mm_w); - self.bubbleView.hidden = YES; - } - - _thumb.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight; - - _progress.mm_fill(); - _progress.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight; } - (void)highlightWhenMatchKeyword:(NSString *)keyword { if (keyword) { diff --git a/iOS/TUIKit/TUIChat/UI_Classic/Cell/Chat/TUIJoinGroupMessageCell.m b/iOS/TUIKit/TUIChat/UI_Classic/Cell/Chat/TUIJoinGroupMessageCell.m index 920bb1501..d2b816d56 100644 --- a/iOS/TUIKit/TUIChat/UI_Classic/Cell/Chat/TUIJoinGroupMessageCell.m +++ b/iOS/TUIKit/TUIChat/UI_Classic/Cell/Chat/TUIJoinGroupMessageCell.m @@ -40,7 +40,7 @@ self.avatarView.hidden = YES; self.retryView.hidden = YES; [self.indicator stopAnimating]; - + NSMutableAttributedString *attributeString = [[NSMutableAttributedString alloc] initWithString:[NSString stringWithFormat:@"%@", data.content]]; NSMutableParagraphStyle *paragraphStyle = [[NSMutableParagraphStyle alloc] init]; paragraphStyle.alignment = NSTextAlignmentCenter; @@ -50,7 +50,7 @@ NSParagraphStyleAttributeName : paragraphStyle }; [attributeString setAttributes:attributeDict range:NSMakeRange(0, attributeString.length)]; - + if (data.userNameList.count > 0) { NSArray *nameRangeList = [self findRightRangeOfAllString:data.userNameList inText:attributeString.string]; int i = 0; @@ -61,9 +61,37 @@ } } self.textView.attributedText = attributeString; - [self setNeedsLayout]; + + // tell constraints they need updating + [self setNeedsUpdateConstraints]; + + // update constraints now so we can animate the change + [self updateConstraintsIfNeeded]; + + [self layoutIfNeeded]; + } ++ (BOOL)requiresConstraintBasedLayout { + return YES; +} + +// this is Apple's recommended place for adding/updating constraints +- (void)updateConstraints { + [super updateConstraints]; + + [self.container mas_remakeConstraints:^(MASConstraintMaker *make) { + make.center.mas_equalTo(self.contentView); + make.size.mas_equalTo(self.contentView); + }]; + + if(self.textView.superview) { + [self.textView mas_remakeConstraints:^(MASConstraintMaker *make) { + make.center.mas_equalTo(self.container); + make.size.mas_equalTo(self.contentView); + }]; + } +} - (void)layoutSubviews { [super layoutSubviews]; self.container.tui_mm_center(); diff --git a/iOS/TUIKit/TUIChat/UI_Classic/Cell/Chat/TUIMergeMessageCell.h b/iOS/TUIKit/TUIChat/UI_Classic/Cell/Chat/TUIMergeMessageCell.h index 8872150fb..2bef4ba30 100644 --- a/iOS/TUIKit/TUIChat/UI_Classic/Cell/Chat/TUIMergeMessageCell.h +++ b/iOS/TUIKit/TUIChat/UI_Classic/Cell/Chat/TUIMergeMessageCell.h @@ -33,12 +33,6 @@ NS_ASSUME_NONNULL_BEGIN */ @property(nonatomic, strong) UILabel *relayTitleLabel; -/** - * 转发消息的摘要信息 abstract - * Abstract of merged-forward message - */ -@property(nonatomic, strong) UILabel *abstractLabel; - /** * 水平分割线 * Horizontal dividing line diff --git a/iOS/TUIKit/TUIChat/UI_Classic/Cell/Chat/TUIMergeMessageCell.m b/iOS/TUIKit/TUIChat/UI_Classic/Cell/Chat/TUIMergeMessageCell.m index 3eb8482d2..b09d6e724 100644 --- a/iOS/TUIKit/TUIChat/UI_Classic/Cell/Chat/TUIMergeMessageCell.m +++ b/iOS/TUIKit/TUIChat/UI_Classic/Cell/Chat/TUIMergeMessageCell.m @@ -18,11 +18,120 @@ #endif #endif +@interface TUIMergeMessageDetailRow : UIView +@property(nonatomic, strong) UILabel *abstractName; +@property(nonatomic, strong) UILabel *abstractBreak; +@property(nonatomic, strong) UILabel *abstractDetail; +- (void)fillWithData:(NSAttributedString *)name detailContent:(NSAttributedString *)detailContent; +@end +@implementation TUIMergeMessageDetailRow + +- (instancetype)init { + self = [super init]; + if(self){ + [self setupview]; + } + return self; +} +- (void)setupview { + [self addSubview:self.abstractName]; + [self addSubview:self.abstractBreak]; + [self addSubview:self.abstractDetail]; +} + +- (UILabel *)abstractName { + if(!_abstractName) { + _abstractName = [[UILabel alloc] init]; + _abstractName.numberOfLines = 1; + _abstractName.font = [UIFont systemFontOfSize:12.0]; + _abstractName.textColor = [UIColor colorWithRed:187 / 255.0 green:187 / 255.0 blue:187 / 255.0 alpha:1 / 1.0]; + _abstractName.textAlignment = isRTL()? NSTextAlignmentRight:NSTextAlignmentLeft; + } + return _abstractName; +} +- (UILabel *)abstractBreak { + if(!_abstractBreak) { + _abstractBreak = [[UILabel alloc] init]; + _abstractBreak.text = @":"; + _abstractBreak.font = [UIFont systemFontOfSize:12.0]; + _abstractBreak.textColor = TUIChatDynamicColor(@"chat_merge_message_content_color", @"#d5d5d5"); + } + return _abstractBreak; +} +- (UILabel *)abstractDetail { + if(!_abstractDetail) { + _abstractDetail = [[UILabel alloc] init]; + _abstractDetail.numberOfLines = 0; + _abstractDetail.font = [UIFont systemFontOfSize:12.0]; + _abstractDetail.textColor = TUIChatDynamicColor(@"chat_merge_message_content_color", @"#d5d5d5"); + _abstractDetail.textAlignment = isRTL()? NSTextAlignmentRight:NSTextAlignmentLeft; + + } + return _abstractDetail; +} + ++ (BOOL)requiresConstraintBasedLayout { + return YES; +} + +// this is Apple's recommended place for adding/updating constraints +- (void)updateConstraints { + + [super updateConstraints]; + + [self.abstractName sizeToFit]; + [self.abstractName mas_remakeConstraints:^(MASConstraintMaker *make) { + make.leading.mas_equalTo(0); + make.top.mas_equalTo(0); + make.trailing.mas_lessThanOrEqualTo(self.abstractBreak.mas_leading); + make.width.mas_lessThanOrEqualTo(self.mas_width).multipliedBy(0.33); + }]; + + [self.abstractBreak sizeToFit]; + [self.abstractBreak mas_remakeConstraints:^(MASConstraintMaker *make) { + make.leading.mas_equalTo(self.abstractName.mas_trailing); + make.top.mas_equalTo(self.abstractName); + make.width.mas_offset(self.abstractBreak.frame.size.width); + make.height.mas_offset(self.abstractBreak.frame.size.height); + }]; + + [self.abstractDetail sizeToFit]; + [self.abstractDetail mas_remakeConstraints:^(MASConstraintMaker *make) { + make.leading.mas_equalTo(self.abstractBreak.mas_trailing); + make.top.mas_equalTo(0); + make.trailing.mas_lessThanOrEqualTo(self.mas_trailing).mas_offset(-15); + make.bottom.mas_equalTo(self); + }]; +} +- (void)fillWithData:(NSAttributedString *)name detailContent:(NSAttributedString *)detailContent { + + self.abstractName.text = name.string; + self.abstractDetail.attributedText = detailContent; + // tell constraints they need updating + [self setNeedsUpdateConstraints]; + + // update constraints now so we can animate the change + [self updateConstraintsIfNeeded]; + + [self layoutIfNeeded]; + + +} +- (void)layoutSubviews { + + + [super layoutSubviews]; +} + + +@end @interface TUIMergeMessageCell () @property(nonatomic, strong) CAShapeLayer *maskLayer; @property(nonatomic, strong) CAShapeLayer *borderLayer; - +@property(nonatomic, strong) TUIMergeMessageDetailRow *contentRowView1; +@property(nonatomic, strong) TUIMergeMessageDetailRow *contentRowView2; +@property(nonatomic, strong) TUIMergeMessageDetailRow *contentRowView3; @end @implementation TUIMergeMessageCell @@ -44,12 +153,13 @@ _relayTitleLabel.textColor = TUIChatDynamicColor(@"chat_merge_message_title_color", @"#000000"); [self.container addSubview:_relayTitleLabel]; - _abstractLabel = [[UILabel alloc] initWithFrame:CGRectZero]; - _abstractLabel.text = @"Me: ******"; - _abstractLabel.numberOfLines = 0; - _abstractLabel.textColor = TUIChatDynamicColor(@"chat_merge_message_content_color", @"#d5d5d5"); - [self.container addSubview:_abstractLabel]; - + _contentRowView1 = [[TUIMergeMessageDetailRow alloc] init]; + [self.container addSubview:_contentRowView1]; + _contentRowView2 = [[TUIMergeMessageDetailRow alloc] init]; + [self.container addSubview:_contentRowView2]; + _contentRowView3 = [[TUIMergeMessageDetailRow alloc] init]; + [self.container addSubview:_contentRowView3]; + _separtorView = [[UIView alloc] init]; _separtorView.backgroundColor = TIMCommonDynamicColor(@"separator_color", @"#DBDBDB"); [self.container addSubview:_separtorView]; @@ -66,13 +176,65 @@ [self prepareReactTagUI:self.container]; } -- (void)layoutSubviews { - [super layoutSubviews]; - self.relayTitleLabel.mm_sizeToFit().mm_top(10).mm_left(10).mm_flexToRight(10); - self.abstractLabel.frame = CGRectMake(10, 3 + self.relayTitleLabel.mm_maxY, self.relayData.abstractSize.width, self.relayData.abstractSize.height); - self.separtorView.frame = CGRectMake(10, self.abstractLabel.mm_maxY, self.container.mm_w - 20, 1); - self.bottomTipsLabel.frame = CGRectMake(10, CGRectGetMaxY(self.separtorView.frame) + 5, self.abstractLabel.mm_w, 20); ++ (BOOL)requiresConstraintBasedLayout { + return YES; +} +// this is Apple's recommended place for adding/updating constraints +- (void)updateConstraints { + + [super updateConstraints]; + [self.relayTitleLabel sizeToFit]; + [self.relayTitleLabel mas_remakeConstraints:^(MASConstraintMaker *make) { + make.leading.mas_equalTo(self.container).mas_offset(10); + make.width.mas_lessThanOrEqualTo(self.container); + make.height.mas_equalTo(self.relayTitleLabel.font.lineHeight); + make.top.mas_equalTo(self.container).mas_offset(10); + }]; + + [self.contentRowView1 mas_remakeConstraints:^(MASConstraintMaker *make) { + make.leading.mas_equalTo(self.relayTitleLabel); + make.top.mas_equalTo(self.relayTitleLabel.mas_bottom).mas_offset(3); + make.trailing.mas_equalTo(self.container); + make.height.mas_lessThanOrEqualTo(self.relayData.abstractRow1Size.height); + }]; + [self.contentRowView2 mas_remakeConstraints:^(MASConstraintMaker *make) { + make.leading.mas_equalTo(self.relayTitleLabel); + make.top.mas_equalTo(self.contentRowView1.mas_bottom).mas_offset(3); + make.trailing.mas_equalTo(self.container); + make.height.mas_equalTo(self.relayData.abstractRow2Size.height); + }]; + [self.contentRowView3 mas_remakeConstraints:^(MASConstraintMaker *make) { + make.leading.mas_equalTo(self.relayTitleLabel); + make.top.mas_equalTo(self.contentRowView2.mas_bottom).mas_offset(3); + make.trailing.mas_equalTo(self.container); + make.height.mas_lessThanOrEqualTo(self.relayData.abstractRow3Size.height); + }]; + + + UIView *lastView = self.contentRowView1; + int count = self.relayData.abstractSendDetailList.count; + if (count == 3) { + lastView = self.contentRowView3; + } + else if (count == 2){ + lastView = self.contentRowView2; + } + + [self.separtorView mas_remakeConstraints:^(MASConstraintMaker *make) { + make.leading.mas_equalTo(self.container).mas_offset(10); + make.trailing.mas_equalTo(self.container).mas_offset(-10); + make.top.mas_equalTo(lastView.mas_bottom).mas_offset(3); + make.height.mas_equalTo(1); + }]; + + [self.bottomTipsLabel mas_remakeConstraints:^(MASConstraintMaker *make) { + make.leading.mas_equalTo(self.contentRowView1); + make.top.mas_equalTo(self.separtorView.mas_bottom).mas_offset(5); + make.width.mas_lessThanOrEqualTo(self.container); + make.height.mas_equalTo(self.bottomTipsLabel.font.lineHeight); + }]; + self.maskLayer.frame = self.container.bounds; self.borderLayer.frame = self.container.bounds; @@ -83,13 +245,53 @@ UIBezierPath *bezierPath = [UIBezierPath bezierPathWithRoundedRect:self.container.bounds byRoundingCorners:corner cornerRadii:CGSizeMake(10, 10)]; self.maskLayer.path = bezierPath.CGPath; self.borderLayer.path = bezierPath.CGPath; + +} + +- (void)layoutSubviews { + [super layoutSubviews]; } - (void)fillWithData:(TUIMergeMessageCellData *)data { [super fillWithData:data]; self.relayData = data; self.relayTitleLabel.text = data.title; - self.abstractLabel.attributedText = [self.relayData abstractAttributedString]; + int count = self.relayData.abstractSendDetailList.count; + switch (count) { + case 1: + [self.contentRowView1 fillWithData:self.relayData.abstractSendDetailList[0][@"sender"] detailContent:self.relayData.abstractSendDetailList[0][@"detail"]]; + self.contentRowView1.hidden = NO; + self.contentRowView2.hidden = YES; + self.contentRowView3.hidden = YES; + break; + case 2: + [self.contentRowView1 fillWithData:self.relayData.abstractSendDetailList[0][@"sender"] detailContent:self.relayData.abstractSendDetailList[0][@"detail"]]; + [self.contentRowView2 fillWithData:self.relayData.abstractSendDetailList[1][@"sender"] detailContent:self.relayData.abstractSendDetailList[1][@"detail"]]; + + self.contentRowView1.hidden = NO; + self.contentRowView2.hidden = NO; + self.contentRowView3.hidden = YES; + break; + case 3: + + [self.contentRowView1 fillWithData:self.relayData.abstractSendDetailList[0][@"sender"] detailContent:self.relayData.abstractSendDetailList[0][@"detail"]]; + [self.contentRowView2 fillWithData:self.relayData.abstractSendDetailList[1][@"sender"] detailContent:self.relayData.abstractSendDetailList[1][@"detail"]]; + [self.contentRowView3 fillWithData:self.relayData.abstractSendDetailList[2][@"sender"] detailContent:self.relayData.abstractSendDetailList[2][@"detail"]]; + self.contentRowView1.hidden = NO; + self.contentRowView2.hidden = NO; + self.contentRowView3.hidden = NO; + break; + default: + break; + } + // tell constraints they need updating + [self setNeedsUpdateConstraints]; + + // update constraints now so we can animate the change + [self updateConstraintsIfNeeded]; + + [self layoutIfNeeded]; + } - (CAShapeLayer *)maskLayer { @@ -124,19 +326,39 @@ + (CGSize)getContentSize:(TUIMessageCellData *)data { NSAssert([data isKindOfClass:TUIMergeMessageCellData.class], @"data must be kind of TUIMergeMessageCellData"); TUIMergeMessageCellData *mergeCellData = (TUIMergeMessageCellData *)data; + + mergeCellData.abstractRow1Size = [self.class caculate:mergeCellData index:0]; + mergeCellData.abstractRow2Size = [self.class caculate:mergeCellData index:1]; + mergeCellData.abstractRow3Size = [self.class caculate:mergeCellData index:2]; + CGRect rect = [[mergeCellData abstractAttributedString] boundingRectWithSize:CGSizeMake(200 - 20, MAXFLOAT) options:NSStringDrawingUsesLineFragmentOrigin | NSStringDrawingUsesFontLeading context:nil]; CGSize size = CGSizeMake(CGFLOAT_CEIL(rect.size.width), CGFLOAT_CEIL(rect.size.height) - 10); mergeCellData.abstractSize = size; - CGFloat height = size.height; - if (height > TRelayMessageCell_Text_Height_Max) { - mergeCellData.abstractSize = CGSizeMake(size.width, size.height - (height - TRelayMessageCell_Text_Height_Max)); - height = TRelayMessageCell_Text_Height_Max; - } + CGFloat height = mergeCellData.abstractRow1Size.height + mergeCellData.abstractRow2Size.height + mergeCellData.abstractRow3Size.height; + UIFont *titleFont = [UIFont systemFontOfSize:16]; - height = (10 + titleFont.lineHeight + 3) + height + 1 + 5 + 20 + 5; + height = (10 + titleFont.lineHeight + 3) + height + 1 + 5 + 20 + 5 +3; return CGSizeMake(200, height); } ++ (CGSize)caculate:(TUIMergeMessageCellData *)data index:(NSInteger)index { + + NSArray *abstractSendDetailList = data.abstractSendDetailList; + if (abstractSendDetailList.count <= index){ + return CGSizeZero; + } + NSAttributedString * str = abstractSendDetailList[index][@"sender"]; + NSMutableAttributedString *abstr = [[NSMutableAttributedString alloc] initWithAttributedString:str]; + [abstr appendAttributedString:[[NSAttributedString alloc] initWithString:@":"]]; + [abstr appendAttributedString:abstractSendDetailList[index][@"detail"]]; + + CGRect rect = [abstr boundingRectWithSize:CGSizeMake(200 - 20, MAXFLOAT) + options:NSStringDrawingUsesLineFragmentOrigin | NSStringDrawingUsesFontLeading + context:nil]; + CGSize size = CGSizeMake(200, MIN(TRelayMessageCell_Text_Height_Max/3.0, CGFLOAT_CEIL(rect.size.height))); + + return size; +} @end diff --git a/iOS/TUIKit/TUIChat/UI_Classic/Cell/Chat/TUIVideoMessageCell.m b/iOS/TUIKit/TUIChat/UI_Classic/Cell/Chat/TUIVideoMessageCell.m index c2d7fbec1..9740c2efc 100644 --- a/iOS/TUIKit/TUIChat/UI_Classic/Cell/Chat/TUIVideoMessageCell.m +++ b/iOS/TUIKit/TUIChat/UI_Classic/Cell/Chat/TUIVideoMessageCell.m @@ -29,7 +29,7 @@ _thumb = [[UIImageView alloc] init]; _thumb.layer.cornerRadius = 5.0; [_thumb.layer setMasksToBounds:YES]; - _thumb.contentMode = UIViewContentModeScaleAspectFit; + _thumb.contentMode = UIViewContentModeScaleAspectFill; _thumb.backgroundColor = [UIColor clearColor]; [self.container addSubview:_thumb]; _thumb.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight; @@ -103,6 +103,14 @@ if (data.thumbImage) { self.thumb.image = data.thumbImage; } + // tell constraints they need updating + [self setNeedsUpdateConstraints]; + + // update constraints now so we can animate the change + [self updateConstraintsIfNeeded]; + + [self layoutIfNeeded]; + return; } @@ -212,31 +220,84 @@ }]; } } + // tell constraints they need updating + [self setNeedsUpdateConstraints]; + + // update constraints now so we can animate the change + [self updateConstraintsIfNeeded]; + + [self layoutIfNeeded]; + } -- (void)layoutSubviews { - [super layoutSubviews]; ++ (BOOL)requiresConstraintBasedLayout { + return YES; +} + +// this is Apple's recommended place for adding/updating constraints +- (void)updateConstraints { + + [super updateConstraints]; if (self.messageData.messageModifyReactsSize.height > 0) { if (self.tagView) { CGFloat topMargin = 10; CGFloat tagViewTopMargin = 6; CGFloat thumbHeight = self.container.mm_h - topMargin - self.messageData.messageModifyReactsSize.height - tagViewTopMargin; - _thumb.mm_height(thumbHeight).mm_left(0).mm_top(topMargin).mm_width(self.container.mm_w); - self.tagView.frame = CGRectMake(0, self.container.mm_h - self.messageData.messageModifyReactsSize.height - tagViewTopMargin, - self.container.frame.size.width, self.messageData.messageModifyReactsSize.height); + [self.thumb mas_remakeConstraints:^(MASConstraintMaker *make) { + make.height.mas_equalTo(thumbHeight); + make.width.mas_equalTo(self.container).multipliedBy(0.7); + make.centerX.mas_equalTo(self.container); + make.top.mas_equalTo(self.container).mas_offset(topMargin); + }]; + [self.tagView mas_remakeConstraints:^(MASConstraintMaker *make) { + make.height.mas_equalTo(self.messageData.messageModifyReactsSize.height); + make.width.mas_equalTo(self.container); + make.trailing.mas_equalTo(self.container.mas_trailing); + make.bottom.mas_equalTo(self.container.mas_bottom); + }]; + [self.duration mas_remakeConstraints:^(MASConstraintMaker *make) { + make.trailing.mas_equalTo(self.thumb.mas_trailing).mas_offset(-2); + + // make.centerX.mas_equalTo(self.thumb).mas_offset(20); + make.width.mas_greaterThanOrEqualTo(20); + make.height.mas_equalTo(20); + make.bottom.mas_equalTo(self.thumb.mas_bottom); + }]; } self.bubbleView.hidden = NO; } else { - CGFloat topMargin = 0; - CGFloat height = self.container.mm_h; - _thumb.mm_height(height).mm_left(0).mm_top(topMargin).mm_width(self.container.mm_w); + [self.thumb mas_remakeConstraints:^(MASConstraintMaker *make) { + make.height.mas_equalTo(self.container.mas_height); + make.width.mas_equalTo(self.container); + make.leading.mas_equalTo(self.container.mas_leading); + make.top.mas_equalTo(self.container); + }]; + [self.duration mas_remakeConstraints:^(MASConstraintMaker *make) { + make.trailing.mas_equalTo(self.thumb.mas_trailing).mas_offset(-2); + make.width.mas_greaterThanOrEqualTo(20); + make.height.mas_equalTo(20); + make.bottom.mas_equalTo(self.thumb.mas_bottom); + }]; self.bubbleView.hidden = YES; } - _play.mm_width(TVideoMessageCell_Play_Size.width).mm_height(TVideoMessageCell_Play_Size.height).tui_mm_center(); - _downloadImage.mm_width(TVideoMessageCell_Play_Size.width).mm_height(TVideoMessageCell_Play_Size.height).tui_mm_center(); - [self.duration setFrame:CGRectMake(self.thumb.mm_w - 20 - 17, self.thumb.frame.size.height - 20, 20, 20)]; - self.duration.mm_sizeToFitThan(20, 20); - self.animateCircleView.tui_mm_center(); + + [self.play mas_remakeConstraints:^(MASConstraintMaker *make) { + make.size.mas_equalTo(TVideoMessageCell_Play_Size); + make.center.mas_equalTo(self.thumb); + }]; + [self.downloadImage mas_remakeConstraints:^(MASConstraintMaker *make) { + make.size.mas_equalTo(TVideoMessageCell_Play_Size); + make.center.mas_equalTo(self.thumb); + }]; + + [self.animateCircleView mas_remakeConstraints:^(MASConstraintMaker *make) { + make.center.mas_equalTo(self.thumb); + make.size.mas_equalTo(CGSizeMake(kScale390(40), kScale390(40))); + }]; +} + +- (void)layoutSubviews { + [super layoutSubviews]; } - (void)highlightWhenMatchKeyword:(NSString *)keyword { diff --git a/iOS/TUIKit/TUIChat/UI_Classic/Cell/Chat/TUIVoiceMessageCell.m b/iOS/TUIKit/TUIChat/UI_Classic/Cell/Chat/TUIVoiceMessageCell.m index e5cdffb55..ade8aa2a3 100644 --- a/iOS/TUIKit/TUIChat/UI_Classic/Cell/Chat/TUIVoiceMessageCell.m +++ b/iOS/TUIKit/TUIChat/UI_Classic/Cell/Chat/TUIVoiceMessageCell.m @@ -9,6 +9,7 @@ #import "TUIVoiceMessageCell.h" #import #import +#import @implementation TUIVoiceMessageCell @@ -22,6 +23,9 @@ _duration = [[UILabel alloc] init]; _duration.font = [UIFont boldSystemFontOfSize:12]; [self.bubbleView addSubview:_duration]; + + self.bottomContainer = [[UIView alloc] init]; + [self.contentView addSubview:self.bottomContainer]; _voiceReadPoint = [[UIImageView alloc] init]; _voiceReadPoint.backgroundColor = [UIColor redColor]; @@ -34,11 +38,25 @@ return self; } -- (void)fillWithData:(TUIVoiceMessageCellData *)data; -{ +- (void)prepareForReuse { + [super prepareForReuse]; + for (UIView *view in self.bottomContainer.subviews) { + [view removeFromSuperview]; + } +} + +// Override +- (void)notifyBottomContainerReadyOfData:(TUIMessageCellData *)cellData { + NSDictionary *param = @{TUICore_TUIChatExtension_BottomContainer_CellData : self.voiceData}; + [TUICore raiseExtension:TUICore_TUIChatExtension_BottomContainer_ClassicExtensionID parentView:self.bottomContainer param:param]; +} + +- (void)fillWithData:(TUIVoiceMessageCellData *)data { // set data [super fillWithData:data]; self.voiceData = data; + self.bottomContainer.hidden = CGSizeEqualToSize(data.bottomContainerSize, CGSizeZero); + if (data.duration > 0) { _duration.text = [NSString stringWithFormat:@"%ld\"", (long)data.duration]; } else { @@ -61,39 +79,111 @@ }]; [self applyStyleFromDirection:data.direction]; + + // tell constraints they need updating + [self setNeedsUpdateConstraints]; + + // update constraints now so we can animate the change + [self updateConstraintsIfNeeded]; + + [self layoutIfNeeded]; + } - (void)applyStyleFromDirection:(TMsgDirection)direction { if (direction == MsgDirectionIncoming) { - _duration.textAlignment = NSTextAlignmentLeft; + _duration.rtlAlignment = TUITextRTLAlignmentLeading; _duration.textColor = TUIChatDynamicColor(@"chat_voice_message_recv_duration_time_color", @"#000000"); } else { - _duration.textAlignment = NSTextAlignmentRight; + _duration.rtlAlignment = TUITextRTLAlignmentTrailing; _duration.textColor = TUIChatDynamicColor(@"chat_voice_message_send_duration_time_color", @"#000000"); } } -- (void)layoutSubviews { - [super layoutSubviews]; - self.duration.mm_sizeToFitThan(10, TVoiceMessageCell_Duration_Size.height); ++ (BOOL)requiresConstraintBasedLayout { + return YES; +} - self.voice.mm_sizeToFit().mm_top(self.voiceData.voiceTop); +// This is Apple's recommended place for adding/updating constraints +- (void)updateConstraints { + [super updateConstraints]; + [self.voice sizeToFit]; + [self.voice mas_remakeConstraints:^(MASConstraintMaker *make) { + make.top.mas_equalTo(self.voiceData.voiceTop); + make.width.height.mas_equalTo(_voiceData.voiceHeight); + if (self.voiceData.direction == MsgDirectionOutgoing) { + make.trailing.mas_equalTo(-self.voiceData.cellLayout.bubbleInsets.right); + } else { + make.leading.mas_equalTo(self.voiceData.cellLayout.bubbleInsets.left); + } + }]; + + [self.duration mas_remakeConstraints:^(MASConstraintMaker *make) { + make.width.mas_greaterThanOrEqualTo(10); + make.height.mas_greaterThanOrEqualTo(TVoiceMessageCell_Duration_Size.height); + make.centerY.mas_equalTo(self.voice); + if (self.voiceData.direction == MsgDirectionOutgoing) { + make.trailing.mas_equalTo(self.voice.mas_leading).mas_offset(-5); + } else { + make.leading.mas_equalTo(self.voice.mas_trailing).mas_offset(5); + } + }]; + if (self.voiceData.direction == MsgDirectionOutgoing) { - self.voice.mm_right(self.voiceData.cellLayout.bubbleInsets.right); - self.duration.mm_left(self.voice.mm_x - self.duration.mm_w - 5); self.voiceReadPoint.hidden = YES; } else { - self.voice.mm_left(self.voiceData.cellLayout.bubbleInsets.left); - self.duration.mm_left(self.voice.mm_x + self.voice.mm_w + 5); - self.voiceReadPoint.mm_top(0).mm_right(-self.voiceReadPoint.mm_w); + [self.voiceReadPoint mas_remakeConstraints:^(MASConstraintMaker *make) { + make.top.mas_equalTo(self.bubbleView); + make.leading.mas_equalTo(self.bubbleView.mas_trailing).mas_offset(1); + make.size.mas_equalTo(CGSizeMake(5, 5)); + }]; + } + + [self layoutBottomContainer]; +} + +- (void)layoutBottomContainer { + if (CGSizeEqualToSize(self.voiceData.bottomContainerSize, CGSizeZero)) { + return; + } + + CGSize size = self.voiceData.bottomContainerSize; + + [self.bottomContainer mas_remakeConstraints:^(MASConstraintMaker *make) { + if (self.voiceData.direction == MsgDirectionIncoming) { + make.leading.mas_equalTo(self.container.mas_leading); + } else { + make.trailing.mas_equalTo(self.container.mas_trailing); + } + make.top.mas_equalTo(self.container.mas_bottom).offset(6); + make.size.mas_equalTo(size); + }]; + + CGFloat repliesBtnTextWidth = self.messageModifyRepliesButton.frame.size.width; + if (!self.messageModifyRepliesButton.hidden) { + [self.messageModifyRepliesButton mas_remakeConstraints:^(MASConstraintMaker *make) { + if (self.voiceData.direction == MsgDirectionIncoming) { + make.leading.mas_equalTo(self.container.mas_leading); + } else { + make.trailing.mas_equalTo(self.container.mas_trailing); + } + make.top.mas_equalTo(self.bottomContainer.mas_bottom); + make.size.mas_equalTo(CGSizeMake(repliesBtnTextWidth + 10, 30)); + }]; } - self.duration.mm_centerY = self.voice.mm_centerY; } #pragma mark - TUIMessageCellProtocol ++ (CGFloat)getHeight:(TUIMessageCellData *)data withWidth:(CGFloat)width { + CGFloat height = [super getHeight:data withWidth:width]; + if (data.bottomContainerSize.height > 0) { + height += data.bottomContainerSize.height + kScale375(6); + } + return height; +} + + (CGSize)getContentSize:(TUIMessageCellData *)data { - NSAssert([data isKindOfClass:TUIVoiceMessageCellData.class], @"data must be kind of TUIVoiceMessageCellData"); TUIVoiceMessageCellData *voiceCellData = (TUIVoiceMessageCellData *)data; CGFloat bubbleWidth = TVoiceMessageCell_Back_Width_Min + voiceCellData.duration / TVoiceMessageCell_Max_Duration * Screen_Width; @@ -113,4 +203,5 @@ return CGSizeMake(bubbleWidth + TVoiceMessageCell_Duration_Size.width, bubbleHeight); } + @end diff --git a/iOS/TUIKit/TUIChat/UI_Classic/Cell/Custom/TUIEvaluationCell.m b/iOS/TUIKit/TUIChat/UI_Classic/Cell/Custom/TUIEvaluationCell.m index fdc76fc14..39016b1ac 100644 --- a/iOS/TUIKit/TUIChat/UI_Classic/Cell/Custom/TUIEvaluationCell.m +++ b/iOS/TUIKit/TUIChat/UI_Classic/Cell/Custom/TUIEvaluationCell.m @@ -49,23 +49,51 @@ UIImageView *starView = [self.starImageArray objectAtIndex:i]; starView.hidden = (i >= data.score); } + // tell constraints they need updating + [self setNeedsUpdateConstraints]; + + // update constraints now so we can animate the change + [self updateConstraintsIfNeeded]; + + [self layoutIfNeeded]; + +} ++ (BOOL)requiresConstraintBasedLayout { + return YES; } -- (void)layoutSubviews { - [super layoutSubviews]; - - self.titleLabel.mm_top(10).mm_left(10).mm_width(225).mm_height(18); - +// this is Apple's recommended place for adding/updating constraints +- (void)updateConstraints { + + [super updateConstraints]; + + [self.titleLabel mas_remakeConstraints:^(MASConstraintMaker *make) { + make.top.mas_equalTo(10); + make.leading.mas_equalTo(10); + make.width.mas_equalTo(225); + make.height.mas_equalTo(18); + }]; + UIImageView *leftView = nil; for (UIImageView *starView in self.starImageArray) { if (leftView == nil) { - starView.mm_left(10).mm_top(self.titleLabel.mm_y + self.titleLabel.mm_h + 6).mm_width(30).mm_height(30); + [starView mas_remakeConstraints:^(MASConstraintMaker *make) { + make.leading.mas_equalTo(10); + make.top.mas_equalTo(self.titleLabel.mas_bottom).mas_offset(6); + make.width.mas_equalTo(30); + make.height.mas_equalTo(30); + }]; } else { - starView.mm_left(leftView.mm_x + leftView.mm_w).mm_top(self.titleLabel.mm_y + self.titleLabel.mm_h + 6).mm_width(30).mm_height(30); + [starView mas_remakeConstraints:^(MASConstraintMaker *make) { + make.leading.mas_equalTo(leftView.mas_trailing); + make.top.mas_equalTo(self.titleLabel.mas_bottom).mas_offset(6); + make.width.mas_equalTo(30); + make.height.mas_equalTo(30); + }]; } leftView = starView; } - + UIImageView *starView = self.starImageArray.firstObject; self.commentLabel.hidden = self.commentLabel.text.length == 0; @@ -75,8 +103,18 @@ attributes:@{NSFontAttributeName : [UIFont systemFontOfSize:15]} context:nil]; CGSize size = CGSizeMake(225, ceilf(rect.size.height)); - self.commentLabel.mm_width(size.width).mm_height(size.height).mm_left(10).mm_top(starView.mm_y + starView.mm_h + 6); + [self.commentLabel mas_remakeConstraints:^(MASConstraintMaker *make) { + make.top.mas_equalTo(starView.mas_bottom).mas_offset(6); + make.leading.mas_equalTo(10); + make.width.mas_equalTo(size.width); + make.height.mas_equalTo(size.height); + }]; } + +} + +- (void)layoutSubviews { + [super layoutSubviews]; } - (NSMutableArray *)starImageArray { diff --git a/iOS/TUIKit/TUIChat/UI_Classic/Cell/Custom/TUILinkCell.m b/iOS/TUIKit/TUIChat/UI_Classic/Cell/Custom/TUILinkCell.m index 5970223d9..72dbf9c19 100644 --- a/iOS/TUIKit/TUIChat/UI_Classic/Cell/Custom/TUILinkCell.m +++ b/iOS/TUIKit/TUIChat/UI_Classic/Cell/Custom/TUILinkCell.m @@ -21,12 +21,14 @@ _myTextLabel = [[UILabel alloc] init]; _myTextLabel.numberOfLines = 0; _myTextLabel.font = [UIFont systemFontOfSize:15]; + _myTextLabel.textAlignment = isRTL()?NSTextAlignmentRight:NSTextAlignmentLeft; _myTextLabel.textColor = TUIChatDynamicColor(@"chat_link_message_title_color", @"#000000"); [self.container addSubview:_myTextLabel]; _myLinkLabel = [[UILabel alloc] initWithFrame:CGRectZero]; _myLinkLabel.text = TIMCommonLocalizableString(TUIKitMoreLinkDetails); _myLinkLabel.font = [UIFont systemFontOfSize:15]; + _myLinkLabel.textAlignment = isRTL()?NSTextAlignmentRight:NSTextAlignmentLeft; _myLinkLabel.textColor = TUIChatDynamicColor(@"chat_link_message_subtitle_color", @"#0000FF"); [self.container addSubview:_myLinkLabel]; } @@ -38,17 +40,45 @@ [super fillWithData:data]; self.customData = data; self.myTextLabel.text = data.text; + + // tell constraints they need updating + [self setNeedsUpdateConstraints]; + + // update constraints now so we can animate the change + [self updateConstraintsIfNeeded]; + + [self layoutIfNeeded]; } -- (void)layoutSubviews { - [super layoutSubviews]; ++ (BOOL)requiresConstraintBasedLayout { + return YES; +} + +// this is Apple's recommended place for adding/updating constraints +- (void)updateConstraints { + + [super updateConstraints]; CGRect rect = [self.myTextLabel.text boundingRectWithSize:CGSizeMake(245, MAXFLOAT) options:NSStringDrawingUsesLineFragmentOrigin | NSStringDrawingUsesFontLeading attributes:@{NSFontAttributeName : [UIFont systemFontOfSize:15]} context:nil]; - self.myTextLabel.mm_top(10).mm_left(10).mm_width(245).mm_height(rect.size.height); - self.myLinkLabel.mm_sizeToFit().mm_left(10).mm_top(self.myTextLabel.mm_y + self.myTextLabel.mm_h + 15); + [self.myTextLabel mas_remakeConstraints:^(MASConstraintMaker *make) { + make.top.mas_equalTo(10); + make.leading.mas_equalTo(10); + make.width.mas_equalTo(245); + make.height.mas_equalTo(rect.size.height); + }]; + [self.myLinkLabel sizeToFit]; + [self.myLinkLabel mas_remakeConstraints:^(MASConstraintMaker *make) { + make.top.mas_equalTo(self.myTextLabel.mas_bottom).mas_offset(15); + make.leading.mas_equalTo(10); + make.width.mas_equalTo(self.myLinkLabel.frame.size.width); + make.height.mas_equalTo(self.myLinkLabel.frame.size.height); + }]; +} +- (void)layoutSubviews { + [super layoutSubviews]; } #pragma mark - TUIMessageCellProtocol diff --git a/iOS/TUIKit/TUIChat/UI_Classic/Cell/Custom/TUIOrderCell.m b/iOS/TUIKit/TUIChat/UI_Classic/Cell/Custom/TUIOrderCell.m index e8eb512ce..56bf61892 100644 --- a/iOS/TUIKit/TUIChat/UI_Classic/Cell/Custom/TUIOrderCell.m +++ b/iOS/TUIKit/TUIChat/UI_Classic/Cell/Custom/TUIOrderCell.m @@ -54,15 +54,53 @@ } else { [self.iconView setImage:[UIImage sd_imageWithData:[NSData dataWithContentsOfURL:[NSURL URLWithString:data.imageUrl]]]]; } + // tell constraints they need updating + [self setNeedsUpdateConstraints]; + + // update constraints now so we can animate the change + [self updateConstraintsIfNeeded]; + + [self layoutIfNeeded]; } ++ (BOOL)requiresConstraintBasedLayout { + return YES; +} + +// this is Apple's recommended place for adding/updating constraints +- (void)updateConstraints { + + [super updateConstraints]; + + [self.iconView mas_remakeConstraints:^(MASConstraintMaker *make) { + make.top.mas_equalTo(10); + make.leading.mas_equalTo(12); + make.width.mas_equalTo(60); + make.height.mas_equalTo(60); + }]; + [self.titleLabel mas_remakeConstraints:^(MASConstraintMaker *make) { + make.top.mas_equalTo(10); + make.leading.mas_equalTo(80); + make.width.mas_equalTo(150); + make.height.mas_equalTo(17); + }]; + + [self.descLabel mas_remakeConstraints:^(MASConstraintMaker *make) { + make.top.mas_equalTo(30); + make.leading.mas_equalTo(80); + make.width.mas_equalTo(150); + make.height.mas_equalTo(17); + }]; + + [self.priceLabel mas_remakeConstraints:^(MASConstraintMaker *make) { + make.top.mas_equalTo(49); + make.leading.mas_equalTo(80); + make.width.mas_equalTo(150); + make.height.mas_equalTo(25); + }]; +} - (void)layoutSubviews { [super layoutSubviews]; - - self.iconView.mm_top(10).mm_left(12).mm_width(60).mm_height(60); - self.titleLabel.mm_top(10).mm_left(80).mm_width(150).mm_height(17); - self.descLabel.mm_top(30).mm_left(80).mm_width(150).mm_height(17); - self.priceLabel.mm_top(49).mm_left(80).mm_width(150).mm_height(25); } #pragma mark - TUIMessageCellProtocol diff --git a/iOS/TUIKit/TUIChat/UI_Classic/Cell/Reply/TUIImageReplyQuoteView.m b/iOS/TUIKit/TUIChat/UI_Classic/Cell/Reply/TUIImageReplyQuoteView.m index c2082080d..d9afc8955 100644 --- a/iOS/TUIKit/TUIChat/UI_Classic/Cell/Reply/TUIImageReplyQuoteView.m +++ b/iOS/TUIKit/TUIChat/UI_Classic/Cell/Reply/TUIImageReplyQuoteView.m @@ -31,13 +31,36 @@ if (myData.image == nil) { [myData downloadImage]; } - self.imageView.frame = CGRectMake(0, 0, myData.imageSize.width, myData.imageSize.height); + // tell constraints they need updating + [self setNeedsUpdateConstraints]; + + // update constraints now so we can animate the change + [self updateConstraintsIfNeeded]; + + [self layoutIfNeeded]; + } ++ (BOOL)requiresConstraintBasedLayout { + return YES; +} +// this is Apple's recommended place for adding/updating constraints +- (void)updateConstraints { + + [super updateConstraints]; + TUIImageReplyQuoteViewData *myData = (TUIImageReplyQuoteViewData *)self.data; + + [self.imageView mas_remakeConstraints:^(MASConstraintMaker *make) { + make.leading.mas_equalTo(self); + make.top.mas_equalTo(self); + make.size.mas_equalTo(myData.imageSize); + }]; + +} - (void)reset { [super reset]; self.imageView.image = nil; - self.imageView.frame = CGRectMake(0, 0, 60, 60); + self.imageView.frame = CGRectMake(self.imageView.frame.origin.x, self.imageView.frame.origin.y, 60, 60); } @end diff --git a/iOS/TUIKit/TUIChat/UI_Classic/Cell/Reply/TUIMergeReplyQuoteView.m b/iOS/TUIKit/TUIChat/UI_Classic/Cell/Reply/TUIMergeReplyQuoteView.m index 929dd498a..14fcd1047 100644 --- a/iOS/TUIKit/TUIChat/UI_Classic/Cell/Reply/TUIMergeReplyQuoteView.m +++ b/iOS/TUIKit/TUIChat/UI_Classic/Cell/Reply/TUIMergeReplyQuoteView.m @@ -35,15 +35,6 @@ - (void)layoutSubviews { [super layoutSubviews]; - - self.titleLabel.mm_x = 0; - self.titleLabel.mm_y = 0; - self.titleLabel.mm_sizeToFit(); - self.titleLabel.mm_w = self.mm_w - self.titleLabel.mm_x; - - self.subTitleLabel.mm_x = self.titleLabel.mm_x; - self.subTitleLabel.mm_y = CGRectGetMaxY(self.titleLabel.frame) + 3; - self.subTitleLabel.mm_flexToRight(8).mm_sizeToFit(); } - (void)fillWithData:(TUIReplyQuoteViewData *)data { @@ -56,6 +47,40 @@ TUIMergeReplyQuoteViewData *myData = (TUIMergeReplyQuoteViewData *)data; self.titleLabel.text = myData.title; self.subTitleLabel.text = myData.abstract; + + // tell constraints they need updating + [self setNeedsUpdateConstraints]; + + // update constraints now so we can animate the change + [self updateConstraintsIfNeeded]; + + [self layoutIfNeeded]; + +} + ++ (BOOL)requiresConstraintBasedLayout { + return YES; +} +// this is Apple's recommended place for adding/updating constraints +- (void)updateConstraints { + + [super updateConstraints]; + + [self.titleLabel sizeToFit]; + [self.titleLabel mas_remakeConstraints:^(MASConstraintMaker *make) { + make.leading.mas_equalTo(self); + make.top.mas_equalTo(self); + make.trailing.mas_equalTo(self.mas_trailing); + make.height.mas_equalTo(self.titleLabel.font.lineHeight); + }]; + + [self.subTitleLabel mas_remakeConstraints:^(MASConstraintMaker *make) { + make.leading.mas_equalTo(self.titleLabel); + make.top.mas_equalTo(self.titleLabel.mas_bottom).mas_offset(3); + make.trailing.mas_equalTo(self.mas_trailing).mas_offset(-8); + make.height.mas_equalTo(self.subTitleLabel.font.lineHeight); + }]; + } - (void)reset { diff --git a/iOS/TUIKit/TUIChat/UI_Classic/Cell/Reply/TUIReferenceMessageCell.m b/iOS/TUIKit/TUIChat/UI_Classic/Cell/Reply/TUIReferenceMessageCell.m index 2de9c1675..67bf4fb50 100644 --- a/iOS/TUIKit/TUIChat/UI_Classic/Cell/Reply/TUIReferenceMessageCell.m +++ b/iOS/TUIKit/TUIChat/UI_Classic/Cell/Reply/TUIReferenceMessageCell.m @@ -93,11 +93,38 @@ @weakify(self); [[RACObserve(data, originMessage) takeUntil:self.rac_prepareForReuseSignal] subscribeNext:^(V2TIMMessage *originMessage) { @strongify(self); - [self updateUI:data]; - [self layoutIfNeeded]; + // tell constraints they need updating + [self setNeedsUpdateConstraints]; + + // update constraints now so we can animate the change + [self updateConstraintsIfNeeded]; + + [self layoutIfNeeded]; }]; + // tell constraints they need updating + [self setNeedsUpdateConstraints]; + + // update constraints now so we can animate the change + [self updateConstraintsIfNeeded]; + [self layoutIfNeeded]; + +} + ++ (BOOL)requiresConstraintBasedLayout { + return YES; +} + +// this is Apple's recommended place for adding/updating constraints +- (void)updateConstraints { + + [super updateConstraints]; + + [self updateUI:self.referenceData]; + + [self layoutBottomContainer]; + } // Override @@ -113,7 +140,11 @@ [self.currentOriginView fillWithData:referenceData.quoteData]; - self.textView.frame = (CGRect){.origin = self.referenceData.textOrigin, .size = self.referenceData.textSize}; + [self.textView mas_remakeConstraints:^(MASConstraintMaker *make) { + make.leading.mas_equalTo(self.bubbleView.mas_leading).mas_offset(self.referenceData.textOrigin.x); + make.top.mas_equalTo(self.bubbleView.mas_top).mas_offset(self.referenceData.textOrigin.y); + make.size.mas_equalTo(self.referenceData.textSize); + }]; if (referenceData.direction == MsgDirectionIncoming) { self.textView.textColor = TUIChatDynamicColor(@"chat_reference_message_content_recv_text_color", @"#000000"); @@ -127,37 +158,44 @@ if (referenceData.textColor) { self.textView.textColor = referenceData.textColor; } - - CGFloat marginX = 6; - CGFloat marginY = 8; - - self.senderLabel.mm_x = marginX; - self.senderLabel.mm_y = marginY; - self.senderLabel.mm_w = self.referenceData.senderSize.width + 4; - self.senderLabel.mm_h = self.referenceData.senderSize.height; - - self.quoteView.mm_w = self.referenceData.quoteSize.width; - self.quoteView.mm_h = self.referenceData.quoteSize.height; - self.quoteView.mm_bottom(self.container.mm_b - self.quoteView.mm_h - 6); - if (self.referenceData.direction == MsgDirectionIncoming) { - self.quoteView.mm_left(self.container.mm_x); - } else { - self.quoteView.mm_right(self.container.mm_r); - } - - if (self.referenceData.showMessageModifyReplies) { - self.messageModifyRepliesButton.mm_bottom(self.contentView.mm_b + self.messageModifyRepliesButton.mm_h - 18); - + + [self.senderLabel mas_remakeConstraints:^(MASConstraintMaker *make) { + make.leading.mas_equalTo(self.quoteView).mas_offset(6); + make.top.mas_equalTo(self.quoteView).mas_offset(8); + make.width.mas_equalTo(referenceData.senderSize.width); + make.height.mas_equalTo(referenceData.senderSize.height); + }]; + + [self.quoteView mas_remakeConstraints:^(MASConstraintMaker *make) { if (self.referenceData.direction == MsgDirectionIncoming) { - self.messageModifyRepliesButton.mm_left(self.quoteView.mm_x); - } else { - self.messageModifyRepliesButton.mm_right(self.quoteView.mm_r); + make.leading.mas_equalTo(self.bubbleView); } + else { + make.trailing.mas_equalTo(self.bubbleView); + } + make.top.mas_equalTo(self.container.mas_bottom).mas_offset(6); + make.size.mas_equalTo(self.referenceData.quoteSize); + }]; + + if (self.referenceData.showMessageModifyReplies) { + [self.messageModifyRepliesButton mas_remakeConstraints:^(MASConstraintMaker *make) { + if (self.referenceData.direction == MsgDirectionIncoming) { + make.leading.mas_equalTo(self.quoteView.mas_leading); + } + else { + make.trailing.mas_equalTo(self.quoteView.mas_trailing); + } + make.top.mas_equalTo(self.quoteView.mas_bottom).mas_offset(3); + make.size.mas_equalTo(self.messageModifyRepliesButton.frame.size); + }]; } - self.currentOriginView.mm_y = marginY + 1; - self.currentOriginView.mm_x = self.senderLabel.mm_w + self.senderLabel.mm_x + marginX; - self.currentOriginView.mm_w = self.referenceData.quotePlaceholderSize.width; - self.currentOriginView.mm_h = self.referenceData.quotePlaceholderSize.height; + [self.currentOriginView mas_remakeConstraints:^(MASConstraintMaker *make) { + make.leading.mas_equalTo(self.senderLabel.mas_trailing).mas_offset(3); + make.top.mas_equalTo(self.senderLabel.mas_top).mas_offset(1); + make.trailing.mas_lessThanOrEqualTo(self.quoteView.mas_trailing); + make.height.mas_equalTo(self.referenceData.quotePlaceholderSize); + }]; + } - (TUIReplyQuoteView *)getCustomOriginView:(TUIMessageCellData *)originCellData { @@ -217,10 +255,6 @@ - (void)layoutSubviews { [super layoutSubviews]; - - [self updateUI:self.referenceData]; - - [self layoutBottomContainer]; } - (void)layoutBottomContainer { @@ -231,11 +265,21 @@ CGSize size = self.referenceData.bottomContainerSize; CGFloat topMargin = self.bubbleView.mm_maxY + self.nameLabel.mm_h + 6; - if (self.referenceData.direction == MsgDirectionOutgoing) { - self.bottomContainer.mm_top(topMargin).mm_width(size.width).mm_height(size.height).mm_right(self.mm_w - self.container.mm_maxX); - } else { - self.bottomContainer.mm_top(topMargin).mm_width(size.width).mm_height(size.height).mm_left(self.container.mm_minX); - } + [self.bottomContainer mas_remakeConstraints:^(MASConstraintMaker *make) { + if (!self.messageModifyRepliesButton.isHidden){ + make.top.mas_equalTo(self.messageModifyRepliesButton.mas_bottom).mas_offset(8); + } + else { + make.top.mas_equalTo(self.quoteView.mas_bottom).mas_offset(8); + } + make.size.mas_equalTo(size); + if (self.referenceData.direction == MsgDirectionOutgoing) { + make.trailing.mas_equalTo(self.container); + } + else { + make.leading.mas_equalTo(self.container); + } + }]; if (!self.quoteView.hidden) { CGRect oldRect = self.quoteView.frame; @@ -339,7 +383,7 @@ // 动态计算发送者的尺寸 // Calculate the size of label which displays the sender's displayname CGSize senderSize = [@"0" sizeWithAttributes:@{NSFontAttributeName : [UIFont boldSystemFontOfSize:12.0]}]; - CGRect senderRect = [referenceCellData.sender boundingRectWithSize:CGSizeMake(quoteMaxWidth, senderSize.height) + CGRect senderRect = [[NSString stringWithFormat:@"%@:",referenceCellData.sender] boundingRectWithSize:CGSizeMake(quoteMaxWidth, senderSize.height) options:NSStringDrawingUsesLineFragmentOrigin | NSStringDrawingUsesFontLeading attributes:@{NSFontAttributeName : [UIFont boldSystemFontOfSize:12.0]} context:nil]; diff --git a/iOS/TUIKit/TUIChat/UI_Classic/Cell/Reply/TUIReplyMessageCell.h b/iOS/TUIKit/TUIChat/UI_Classic/Cell/Reply/TUIReplyMessageCell.h index 46c46296e..a4fba0595 100644 --- a/iOS/TUIKit/TUIChat/UI_Classic/Cell/Reply/TUIReplyMessageCell.h +++ b/iOS/TUIKit/TUIChat/UI_Classic/Cell/Reply/TUIReplyMessageCell.h @@ -20,7 +20,7 @@ NS_ASSUME_NONNULL_BEGIN @interface TUIReplyMessageCell : TUIBubbleMessageCell -@property(nonatomic, strong) CALayer *quoteBorderLayer; +@property(nonatomic, strong) UIView *quoteBorderLine; @property(nonatomic, strong) UIView *quoteView; @property(nonatomic, strong) TUITextView *textView; diff --git a/iOS/TUIKit/TUIChat/UI_Classic/Cell/Reply/TUIReplyMessageCell.m b/iOS/TUIKit/TUIChat/UI_Classic/Cell/Reply/TUIReplyMessageCell.m index 7f68099a8..14ecdf8db 100644 --- a/iOS/TUIKit/TUIChat/UI_Classic/Cell/Reply/TUIReplyMessageCell.m +++ b/iOS/TUIKit/TUIChat/UI_Classic/Cell/Reply/TUIReplyMessageCell.m @@ -51,7 +51,7 @@ - (void)setupViews { [self.quoteView addSubview:self.senderLabel]; - [self.quoteView.layer addSublayer:self.quoteBorderLayer]; + [self.quoteView addSubview:self.quoteBorderLine]; [self.bubbleView addSubview:self.quoteView]; [self.bubbleView addSubview:self.textView]; @@ -86,13 +86,39 @@ @weakify(self); [[RACObserve(data, originMessage) takeUntil:self.rac_prepareForReuseSignal] subscribeNext:^(V2TIMMessage *originMessage) { @strongify(self); - [self updateUI:data]; - [self layoutIfNeeded]; + // tell constraints they need updating + [self setNeedsUpdateConstraints]; + + // update constraints now so we can animate the change + [self updateConstraintsIfNeeded]; + + [self layoutIfNeeded]; + }]; + // tell constraints they need updating + [self setNeedsUpdateConstraints]; + + // update constraints now so we can animate the change + [self updateConstraintsIfNeeded]; [self layoutIfNeeded]; } ++ (BOOL)requiresConstraintBasedLayout { + return YES; +} + +// this is Apple's recommended place for adding/updating constraints +- (void)updateConstraints { + + [super updateConstraints]; + + [self updateUI:self.replyData]; + + [self layoutBottomContainer]; + +} + - (void)updateUI:(TUIReplyMessageCellData *)replyData { self.currentOriginView = [self getCustomOriginView:replyData.originCellData]; [self hiddenAllCustomOriginViews:YES]; @@ -100,27 +126,41 @@ [self.currentOriginView fillWithData:replyData.quoteData]; - self.quoteView.mm_x = 16; - self.quoteView.mm_y = 12; - self.quoteView.mm_w = self.replyData.quoteSize.width; - self.quoteView.mm_h = self.replyData.quoteSize.height; + [self.quoteView mas_remakeConstraints:^(MASConstraintMaker *make) { + make.leading.mas_equalTo(self.bubbleView).mas_offset(16); + make.top.mas_equalTo(12); + make.trailing.mas_lessThanOrEqualTo(self.bubbleView).mas_offset(-16); + make.width.mas_greaterThanOrEqualTo(self.senderLabel); + make.height.mas_equalTo(self.replyData.quoteSize.height); + }]; - self.quoteBorderLayer.frame = CGRectMake(0, 0, 3, self.quoteView.mm_h); + [self.quoteBorderLine mas_remakeConstraints:^(MASConstraintMaker *make) { + make.leading.mas_equalTo(self.quoteView); + make.top.mas_equalTo(self.quoteView); + make.width.mas_equalTo(3); + make.bottom.mas_equalTo(self.quoteView); + }]; + + [self.textView mas_remakeConstraints:^(MASConstraintMaker *make) { + make.leading.mas_equalTo(self.quoteView).mas_offset(4); + make.top.mas_equalTo(self.quoteView.mas_bottom).mas_offset(12); + make.trailing.mas_lessThanOrEqualTo(self.quoteView).mas_offset(-4);; + make.bottom.mas_equalTo(self.bubbleView).mas_offset(-4); + }]; - self.textView.mm_y = CGRectGetMaxY(self.quoteView.frame) + 12.0; - self.textView.mm_x = 18; - self.textView.mm_w = self.replyData.replyContentSize.width; - self.textView.mm_h = self.replyData.replyContentSize.height; - - self.senderLabel.mm_x = 6; - self.senderLabel.mm_y = 3; - self.senderLabel.mm_w = self.replyData.senderSize.width; - self.senderLabel.mm_h = self.replyData.senderSize.height; - - self.currentOriginView.mm_y = CGRectGetMaxY(self.senderLabel.frame) + 4; - self.currentOriginView.mm_x = self.senderLabel.mm_x; - self.currentOriginView.mm_w = self.replyData.quotePlaceholderSize.width; - self.currentOriginView.mm_h = self.replyData.quotePlaceholderSize.height; + [self.senderLabel mas_remakeConstraints:^(MASConstraintMaker *make) { + make.leading.mas_equalTo(self.textView); + make.top.mas_equalTo(3); + make.size.mas_equalTo(self.replyData.senderSize); + }]; + + [self.currentOriginView mas_remakeConstraints:^(MASConstraintMaker *make) { + make.leading.mas_equalTo(self.senderLabel); + make.top.mas_equalTo(self.senderLabel.mas_bottom).mas_offset(4); +// make.width.mas_greaterThanOrEqualTo(self.replyData.quotePlaceholderSize); + make.trailing.mas_lessThanOrEqualTo(self.quoteView.mas_trailing); + make.height.mas_equalTo(self.replyData.quotePlaceholderSize); + }]; } - (TUIReplyQuoteView *)getCustomOriginView:(TUIMessageCellData *)originCellData { @@ -180,36 +220,26 @@ - (void)layoutSubviews { [super layoutSubviews]; - [self updateUI:self.replyData]; - - [self updateTagView]; - - [self layoutBottomContainer]; } -- (void)updateTagView { - if (self.messageData.messageModifyReactsSize.height > 0) { - if (self.tagView) { - CGFloat tagViewTopPadding = 6; - self.tagView.frame = CGRectMake(0, self.container.mm_h - self.messageData.messageModifyReactsSize.height - tagViewTopPadding, - self.container.frame.size.width, self.messageData.messageModifyReactsSize.height); - } - } -} - (void)layoutBottomContainer { if (CGSizeEqualToSize(self.replyData.bottomContainerSize, CGSizeZero)) { return; } CGSize size = self.replyData.bottomContainerSize; - CGFloat topMargin = self.bubbleView.mm_maxY + self.nameLabel.mm_h + 6; - - if (self.replyData.direction == MsgDirectionOutgoing) { - self.bottomContainer.mm_top(topMargin).mm_width(size.width).mm_height(size.height).mm_right(self.mm_w - self.container.mm_maxX); - } else { - self.bottomContainer.mm_top(topMargin).mm_width(size.width).mm_height(size.height).mm_left(self.container.mm_minX); - } - + CGFloat topMargin = self.bubbleView.mm_maxY + self.nameLabel.mm_h + 8; + [self.bottomContainer mas_remakeConstraints:^(MASConstraintMaker *make) { + make.top.mas_equalTo(self.bubbleView.mas_bottom).mas_offset(8); + make.size.mas_equalTo(size); + if (self.replyData.direction == MsgDirectionOutgoing) { + make.trailing.mas_equalTo(self.container); + } + else { + make.leading.mas_equalTo(self.container); + } + }]; + if (!self.messageModifyRepliesButton.hidden) { CGRect oldRect = self.messageModifyRepliesButton.frame; CGRect newRect = CGRectMake(oldRect.origin.x, CGRectGetMaxY(self.bottomContainer.frame), oldRect.size.width, oldRect.size.height); @@ -223,6 +253,7 @@ _senderLabel.text = @"harvy:"; _senderLabel.font = [UIFont boldSystemFontOfSize:12.0]; _senderLabel.textColor = TUIChatDynamicColor(@"chat_reply_message_sender_text_color", @"#888888"); + _senderLabel.textAlignment = isRTL()?NSTextAlignmentRight:NSTextAlignmentLeft; } return _senderLabel; } @@ -235,12 +266,12 @@ return _quoteView; } -- (CALayer *)quoteBorderLayer { - if (_quoteBorderLayer == nil) { - _quoteBorderLayer = [CALayer layer]; - _quoteBorderLayer.backgroundColor = [UIColor colorWithRed:68 / 255.0 green:68 / 255.0 blue:68 / 255.0 alpha:0.1].CGColor; +- (UIView *)quoteBorderLine { + if (_quoteBorderLine == nil) { + _quoteBorderLine = [[UIView alloc] init]; + _quoteBorderLine.backgroundColor = [UIColor colorWithRed:68 / 255.0 green:68 / 255.0 blue:68 / 255.0 alpha:0.1]; } - return _quoteBorderLayer; + return _quoteBorderLine; } - (TUITextView *)textView { @@ -254,6 +285,7 @@ _textView.scrollEnabled = NO; _textView.editable = NO; _textView.delegate = self; + _textView.textAlignment = isRTL()?NSTextAlignmentRight:NSTextAlignmentLeft; } return _textView; } diff --git a/iOS/TUIKit/TUIChat/UI_Classic/Cell/Reply/TUITextReplyQuoteView.m b/iOS/TUIKit/TUIChat/UI_Classic/Cell/Reply/TUITextReplyQuoteView.m index ae23209ca..48514d038 100644 --- a/iOS/TUIKit/TUIChat/UI_Classic/Cell/Reply/TUITextReplyQuoteView.m +++ b/iOS/TUIKit/TUIChat/UI_Classic/Cell/Reply/TUITextReplyQuoteView.m @@ -24,11 +24,19 @@ return self; } -- (void)layoutSubviews { - [super layoutSubviews]; - self.textLabel.frame = self.bounds; + ++ (BOOL)requiresConstraintBasedLayout { + return YES; } +// this is Apple's recommended place for adding/updating constraints +- (void)updateConstraints { + + [super updateConstraints]; + [self.textLabel mas_remakeConstraints:^(MASConstraintMaker *make) { + make.edges.mas_equalTo(self); + }]; +} - (void)fillWithData:(TUIReplyQuoteViewData *)data { [super fillWithData:data]; if (![data isKindOfClass:TUITextReplyQuoteViewData.class]) { @@ -36,6 +44,14 @@ } TUITextReplyQuoteViewData *myData = (TUITextReplyQuoteViewData *)data; self.textLabel.attributedText = [myData.text getFormatEmojiStringWithFont:self.textLabel.font emojiLocations:nil]; + // tell constraints they need updating + [self setNeedsUpdateConstraints]; + + // update constraints now so we can animate the change + [self updateConstraintsIfNeeded]; + + [self layoutIfNeeded]; + } - (void)reset { diff --git a/iOS/TUIKit/TUIChat/UI_Classic/Cell/Reply/TUIVideoReplyQuoteView.m b/iOS/TUIKit/TUIChat/UI_Classic/Cell/Reply/TUIVideoReplyQuoteView.m index 8d981dba2..906c086a7 100644 --- a/iOS/TUIKit/TUIChat/UI_Classic/Cell/Reply/TUIVideoReplyQuoteView.m +++ b/iOS/TUIKit/TUIChat/UI_Classic/Cell/Reply/TUIVideoReplyQuoteView.m @@ -6,9 +6,9 @@ // Copyright © 2023 Tencent. All rights reserved. // -#import "TUIVideoReplyQuoteView.h" #import #import +#import "TUIVideoReplyQuoteView.h" #import "TUIVideoReplyQuoteViewData.h" @implementation TUIVideoReplyQuoteView @@ -25,9 +25,29 @@ - (void)layoutSubviews { [super layoutSubviews]; - self.playView.center = self.imageView.center; } ++ (BOOL)requiresConstraintBasedLayout { + return YES; +} + +// this is Apple's recommended place for adding/updating constraints +- (void)updateConstraints { + + [super updateConstraints]; + + TUIVideoReplyQuoteViewData *myData = (TUIVideoReplyQuoteViewData *)self.data; + + [self.imageView mas_remakeConstraints:^(MASConstraintMaker *make) { + make.leading.top.mas_equalTo(self); + make.size.mas_equalTo(myData.imageSize); + }]; + + [self.playView mas_remakeConstraints:^(MASConstraintMaker *make) { + make.size.mas_equalTo(CGSizeMake(30, 30)); + make.center.mas_equalTo(self.imageView); + }]; +} - (void)fillWithData:(TUIReplyQuoteViewData *)data { [super fillWithData:data]; @@ -39,7 +59,14 @@ if (myData.image == nil) { [myData downloadImage]; } - self.imageView.frame = CGRectMake(0, 0, myData.imageSize.width, myData.imageSize.height); + + // tell constraints they need updating + [self setNeedsUpdateConstraints]; + + // update constraints now so we can animate the change + [self updateConstraintsIfNeeded]; + + [self layoutIfNeeded]; } @end diff --git a/iOS/TUIKit/TUIChat/UI_Classic/Cell/Reply/TUIVoiceReplyQuoteView.m b/iOS/TUIKit/TUIChat/UI_Classic/Cell/Reply/TUIVoiceReplyQuoteView.m index bda714762..ce1a16839 100644 --- a/iOS/TUIKit/TUIChat/UI_Classic/Cell/Reply/TUIVoiceReplyQuoteView.m +++ b/iOS/TUIKit/TUIChat/UI_Classic/Cell/Reply/TUIVoiceReplyQuoteView.m @@ -28,12 +28,6 @@ - (void)layoutSubviews { [super layoutSubviews]; - - self.iconView.frame = CGRectMake(0, 0, 15, 15); - [self.textLabel sizeToFit]; - self.textLabel.mm_centerY = self.iconView.mm_centerY; - self.textLabel.mm_x = CGRectGetMaxX(self.iconView.frame) + 3; - self.textLabel.mm_w = self.mm_w - self.textLabel.mm_x; } - (void)fillWithData:(TUIReplyQuoteViewData *)data { @@ -44,6 +38,42 @@ TUIVoiceReplyQuoteViewData *myData = (TUIVoiceReplyQuoteViewData *)data; self.iconView.image = myData.icon; self.textLabel.numberOfLines = 1; + + // tell constraints they need updating + [self setNeedsUpdateConstraints]; + + // update constraints now so we can animate the change + [self updateConstraintsIfNeeded]; + + [self layoutIfNeeded]; + } ++ (BOOL)requiresConstraintBasedLayout { + return YES; +} + +// this is Apple's recommended place for adding/updating constraints +- (void)updateConstraints { + + [super updateConstraints]; + [self.iconView mas_remakeConstraints:^(MASConstraintMaker *make) { + make.leading.mas_equalTo(self); + make.top.mas_equalTo(self); + make.width.mas_equalTo(15); + make.height.mas_equalTo(15); + }]; + + [self.textLabel sizeToFit]; + [self.textLabel mas_remakeConstraints:^(MASConstraintMaker *make) { + make.leading.mas_equalTo(self.iconView.mas_trailing).mas_offset(3); + make.centerY.mas_equalTo(self.mas_centerY); + make.trailing.mas_equalTo(self.mas_trailing); + make.height.mas_equalTo(self.textLabel.font.lineHeight); + }]; + + +} + + @end diff --git a/iOS/TUIKit/TUIChat/UI_Classic/Chat/TUIBaseChatViewController.m b/iOS/TUIKit/TUIChat/UI_Classic/Chat/TUIBaseChatViewController.m index 60f3888d4..b807a5ac2 100644 --- a/iOS/TUIKit/TUIChat/UI_Classic/Chat/TUIBaseChatViewController.m +++ b/iOS/TUIKit/TUIChat/UI_Classic/Chat/TUIBaseChatViewController.m @@ -169,6 +169,9 @@ static UIView *gCustomTopView; TUINavigationController *naviController = (TUINavigationController *)self.navigationController; if ([naviController isKindOfClass:TUINavigationController.class]) { naviController.uiNaviDelegate = self; + UIImage *backimg = TIMCommonDynamicImage(@"nav_back_img", [UIImage imageNamed:TIMCommonImagePath(@"nav_back")]); + backimg = [backimg rtl_imageFlippedForRightToLeftLayoutDirection]; + naviController.navigationItemBackArrowImage = backimg; } _titleView = [[TUINaviBarIndicatorView alloc] init]; self.navigationItem.titleView = _titleView; @@ -232,8 +235,10 @@ static UIView *gCustomTopView; _messageController = vc; _messageController.delegate = self; [_messageController setConversation:self.conversationData]; + + CGFloat textViewHeight = TUIChatConfig.defaultConfig.enableMainPageInputBar? TTextView_Height:0; _messageController.view.frame = CGRectMake(0, [self topMarginByCustomView], self.view.frame.size.width, - self.view.frame.size.height - TTextView_Height - Bottom_SafeHeight - [self topMarginByCustomView]); + self.view.frame.size.height - textViewHeight - Bottom_SafeHeight - [self topMarginByCustomView]); [self addChildViewController:_messageController]; [self.view addSubview:_messageController.view]; [_messageController didMoveToParentViewController:self]; @@ -260,8 +265,11 @@ static UIView *gCustomTopView; [self addChildViewController:_inputController]; [self.view addSubview:_inputController.view]; + _inputController.view.hidden = !TUIChatConfig.defaultConfig.enableMainPageInputBar; + self.moreMenus = [self.dataProvider moreMenuCellDataArray:self.conversationData.groupID userID:self.conversationData.userID + conversationModel:self.conversationData actionController:self]; } @@ -278,8 +286,10 @@ static UIView *gCustomTopView; } else if (IS_NOT_EMPTY_NSSTRING(imgUrl)) { [self.backgroudView sd_setImageWithURL:[NSURL URLWithString:imgUrl] placeholderImage:nil]; } + CGFloat textViewHeight = TUIChatConfig.defaultConfig.enableMainPageInputBar? TTextView_Height:0; + self.backgroudView.frame = - CGRectMake(0, self.view.frame.origin.y, self.view.frame.size.width, self.view.frame.size.height - TTextView_Height - Bottom_SafeHeight); + CGRectMake(0, self.view.frame.origin.y, self.view.frame.size.width, self.view.frame.size.height - textViewHeight - Bottom_SafeHeight); [self.view insertSubview:self.backgroudView atIndex:0]; } @@ -340,6 +350,7 @@ static UIView *gCustomTopView; } - (void)loadDraft { + NSString *draft = self.conversationData.draftText; if (draft.length == 0) { return; @@ -352,7 +363,7 @@ static UIView *gCustomTopView; textColor:kTUIInputNormalTextColor emojiLocations:nil]; - [self.inputController.inputBar.inputTextView.textStorage insertAttributedString:formatEmojiString atIndex:0]; + [self.inputController.inputBar addDraftToInputBar:formatEmojiString]; return; } @@ -366,7 +377,7 @@ static UIView *gCustomTopView; textColor:kTUIInputNormalTextColor emojiLocations:nil]; - [self.inputController.inputBar.inputTextView.textStorage insertAttributedString:formatEmojiString atIndex:0]; + [self.inputController.inputBar addDraftToInputBar:formatEmojiString]; NSString *messageRootID = [jsonDict.allKeys containsObject:@"messageRootID"] ? jsonDict[@"messageRootID"] : @""; @@ -445,7 +456,7 @@ static UIView *gCustomTopView; friendInfoResult.friendInfo.friendRemark.length > 0) { self.conversationData.title = friendInfoResult.friendInfo.friendRemark; } else { - [TUIChatDataProvider getUserInfoWithUserId:friendInfoResult.friendInfo.userID + [TUIChatDataProvider getUserInfoWithUserId:self.conversationData.userID SuccBlock:^(V2TIMUserFullInfo *_Nonnull userInfo) { if (userInfo.nickName.length > 0) { self.conversationData.title = userInfo.nickName; diff --git a/iOS/TUIKit/TUIChat/UI_Classic/Chat/TUIBaseMessageController.m b/iOS/TUIKit/TUIChat/UI_Classic/Chat/TUIBaseMessageController.m index f933ed3d6..0b0cb1d9c 100644 --- a/iOS/TUIKit/TUIChat/UI_Classic/Chat/TUIBaseMessageController.m +++ b/iOS/TUIKit/TUIChat/UI_Classic/Chat/TUIBaseMessageController.m @@ -129,9 +129,16 @@ } - (void)registerEvents { - [TUICore registerEvent:TUICore_TUIPluginNotify subKey:TUICore_TUIPluginNotify_PluginViewSizeChangedSubKey object:self]; - [TUICore registerEvent:TUICore_TUITranslationNotify subKey:TUICore_TUITranslationNotify_WillForwardTranslationSubKey object:self]; - [TUICore registerEvent:TUICore_TUITranslationNotify subKey:TUICore_TUITranslationNotify_DidChangeTranslationSubKey object:self]; + [TUICore registerEvent:TUICore_TUIPluginNotify + subKey:TUICore_TUIPluginNotify_PluginViewSizeChangedSubKey + object:self]; + [TUICore registerEvent:TUICore_TUIPluginNotify + subKey:TUICore_TUIPluginNotify_WillForwardTextSubKey + object:self]; + [TUICore registerEvent:TUICore_TUIPluginNotify + subKey:TUICore_TUIPluginNotify_DidChangePluginViewSubKey + object:self]; + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(applicationBecomeActive) name:UIApplicationDidBecomeActiveNotification @@ -312,19 +319,25 @@ } FailBlock:^(int code, NSString *desc) { @strongify(self); + NSString *errorMsg = @""; if (self.isMsgNeedReadReceipt && code == ERR_SDK_INTERFACE_NOT_SUPPORT) { - NSString *msg = [NSString stringWithFormat:@"%@%@", TUIKitLocalizableString(TUIKitErrorUnsupportIntefaceMessageRead), - TUIKitLocalizableString(TUIKitErrorUnsupporInterfaceSuffix)]; - [TUITool makeToast:msg]; + errorMsg = [NSString stringWithFormat:@"%@%@", TUIKitLocalizableString(TUIKitErrorUnsupportIntefaceMessageRead), + TUIKitLocalizableString(TUIKitErrorUnsupporInterfaceSuffix)]; } else { - [TUITool makeToastError:code msg:desc]; + errorMsg = [TUITool convertIMError:code msg:desc]; } + [self makeSendErrorHud:errorMsg]; [self changeMsg:cellData status:Msg_Status_Fail]; NSDictionary *param = @{TUICore_TUIChatNotify_SendMessageSubKey_Code : @(code), TUICore_TUIChatNotify_SendMessageSubKey_Desc : desc}; [TUICore notifyEvent:TUICore_TUIChatNotify subKey:TUICore_TUIChatNotify_SendMessageSubKey object:self param:param]; }]; } +- (void)makeSendErrorHud:(NSString *)msg { + UIAlertController *ac = [UIAlertController alertControllerWithTitle:msg message:nil preferredStyle:UIAlertControllerStyleAlert]; + [ac tuitheme_addAction:[UIAlertAction actionWithTitle:TIMCommonLocalizableString(Confirm) style:UIAlertActionStyleDefault handler:nil]]; + [self presentViewController:ac animated:YES completion:nil]; +} - (void)sendMessage:(V2TIMMessage *)message { [self sendMessage:message placeHolderCellData:nil]; @@ -402,14 +415,13 @@ break; } } - } else if ([key isEqualToString:TUICore_TUITranslationNotify] && [subKey isEqualToString:TUICore_TUITranslationNotify_DidChangeTranslationSubKey]) { - // Translation View is Shown or content changed. - TUIMessageCellData *data = param[TUICore_TUITranslationNotify_DidChangeTranslationSubKey_Data]; + } else if ([key isEqualToString: TUICore_TUIPluginNotify] && [subKey isEqualToString:TUICore_TUIPluginNotify_DidChangePluginViewSubKey]) { + // Plugin View is Shown or content changed. + TUIMessageCellData *data = param[TUICore_TUIPluginNotify_DidChangePluginViewSubKey_Data]; [self clearAndReloadCellOfData:data]; - } - if ([key isEqualToString:TUICore_TUITranslationNotify] && [subKey isEqualToString:TUICore_TUITranslationNotify_WillForwardTranslationSubKey]) { - // Translation will be forwarded. - NSString *text = param[TUICore_TUITranslationNotify_WillForwardTranslationSubKey_Text]; + } else if ([key isEqualToString:TUICore_TUIPluginNotify] && [subKey isEqualToString:TUICore_TUIPluginNotify_WillForwardTextSubKey]) { + // Text will be forwarded. + NSString *text = param[TUICore_TUIPluginNotify_WillForwardTextSubKey_Text]; if (self.delegate && [self.delegate respondsToSelector:@selector(messageController:onForwardText:)]) { [self.delegate messageController:self onForwardText:text]; } @@ -786,7 +798,7 @@ ReceiveReadMsgWithGroupID:(NSString *)groupID #pragma mark - TUIMessageCellDelegate - (void)onSelectMessage:(TUIMessageCell *)cell { - if (self.showCheckBox) { + if (self.showCheckBox && [self supportCheckBox:(TUIMessageCellData *)cell.data]) { TUIMessageCellData *data = (TUIMessageCellData *)cell.data; data.selected = !data.selected; [self.tableView reloadData]; @@ -834,6 +846,9 @@ ReceiveReadMsgWithGroupID:(NSString *)groupID } - (void)tryShowGuidance { + if (isRTL()){ + return; + } BOOL hasShow = [NSUserDefaults.standardUserDefaults boolForKey:@"chat_reply_guide_showKey"]; if (hasShow) { return; @@ -878,6 +893,7 @@ ReceiveReadMsgWithGroupID:(NSString *)groupID } - (void)onLongPressMessage:(TUIMessageCell *)cell { + [UIApplication.sharedApplication.keyWindow endEditing:NO]; TUIMessageCellData *data = cell.messageData; if ([data isKindOfClass:[TUISystemMessageCellData class]]) { return; @@ -960,10 +976,14 @@ ReceiveReadMsgWithGroupID:(NSString *)groupID TUIChatPopMenuAction *forwardAction = [self setupForwardAction:cell]; TUIChatPopMenuAction *quoteAction = [self setupQuoteAction:cell]; TUIChatPopMenuAction *referenceAction = [self setupReferenceAction:cell]; + TUIChatPopMenuAction *audioPlaybackStyleAction = [self setupAudioPlaybackStyleAction:cell]; TUIMessageCellData *data = cell.messageData; V2TIMMessage *imMsg = data.innerMessage; + if (imMsg.status == V2TIM_MSG_STATUS_SEND_SUCC && imMsg.soundElem) { + [menu addAction:audioPlaybackStyleAction]; + } if ([data isKindOfClass:[TUITextMessageCellData class]] || [data isKindOfClass:TUIReplyMessageCellData.class] || [data isKindOfClass:TUIReferenceMessageCellData.class]) { [menu addAction:copyAction]; @@ -1196,6 +1216,42 @@ ReceiveReadMsgWithGroupID:(NSString *)groupID return referenceAction; } +- (TUIChatPopMenuAction *)setupAudioPlaybackStyleAction:(TUIMessageCell *)cell { + @weakify(self); + TUIChatPopMenuAction *audioPlaybackStyleAction = nil; + __weak typeof(audioPlaybackStyleAction) weakAction = audioPlaybackStyleAction; + TUIVoiceAudioPlaybackStyle originStyle = [TUIVoiceMessageCellData getAudioplaybackStyle]; + NSString *title = @""; + UIImage *img = nil; + if (originStyle == TUIVoiceAudioPlaybackStyleLoudspeaker) { + title = TIMCommonLocalizableString(TUIKitAudioPlaybackStyleHandset); + img = TUIChatBundleThemeImage(@"chat_icon_audio_handset_img", @"icon_handset"); + } + else { + title = TIMCommonLocalizableString(TUIKitAudioPlaybackStyleLoudspeaker); + img = TUIChatBundleThemeImage(@"chat_icon_audio_loudspeaker_img", @"icon_loudspeaker"); + } + + audioPlaybackStyleAction = [[TUIChatPopMenuAction alloc] initWithTitle:title + image:img + weight:11000 + callback:^{ + if (originStyle == TUIVoiceAudioPlaybackStyleLoudspeaker) { + //Change To Handset + weakAction.title = TIMCommonLocalizableString(TUIKitAudioPlaybackStyleLoudspeaker); + [TUITool hideToast]; + [TUITool makeToast:TIMCommonLocalizableString(TUIKitAudioPlaybackStyleChange2Handset) duration:2]; + } + else { + weakAction.title = TIMCommonLocalizableString(TUIKitAudioPlaybackStyleHandset); + [TUITool hideToast]; + [TUITool makeToast:TIMCommonLocalizableString(TUIKitAudioPlaybackStyleChange2Loudspeaker) duration:2]; + } + [TUIVoiceMessageCellData changeAudioPlaybackStyle]; + + }]; + return audioPlaybackStyleAction; +} - (BOOL)canForward:(TUIMessageCellData *)data { return ![TUIMessageCellConfig isPluginCustomMessageCellData:data]; } diff --git a/iOS/TUIKit/TUIChat/UI_Classic/Chat/TUIC2CChatViewController.m b/iOS/TUIKit/TUIChat/UI_Classic/Chat/TUIC2CChatViewController.m index d5945b9eb..5bcadf0f9 100644 --- a/iOS/TUIKit/TUIChat/UI_Classic/Chat/TUIC2CChatViewController.m +++ b/iOS/TUIKit/TUIChat/UI_Classic/Chat/TUIC2CChatViewController.m @@ -38,7 +38,8 @@ #pragma mark - Override Methods - (NSString *)forwardTitleWithMyName:(NSString *)nameStr { - return [NSString stringWithFormat:TIMCommonLocalizableString(TUIKitRelayChatHistoryForSomebodyFormat), self.conversationData.title, nameStr]; + NSString *title = [NSString stringWithFormat:TIMCommonLocalizableString(TUIKitRelayChatHistoryForSomebodyFormat), self.conversationData.title, nameStr]; + return rtlString(title); } - (void)inputController:(TUIInputController *)inputController didSelectMoreCell:(TUIInputMoreCell *)cell { diff --git a/iOS/TUIKit/TUIChat/UI_Classic/Chat/TUIChatSmallTongueView.m b/iOS/TUIKit/TUIChat/UI_Classic/Chat/TUIChatSmallTongueView.m index f5738cfed..ed0a84630 100644 --- a/iOS/TUIKit/TUIChat/UI_Classic/Chat/TUIChatSmallTongueView.m +++ b/iOS/TUIKit/TUIChat/UI_Classic/Chat/TUIChatSmallTongueView.m @@ -9,7 +9,8 @@ #import "TUIChatSmallTongueView.h" #import #import - +#import "TUIChatConfig.h" +#import #define TongueHeight 35.f #define TongueImageWidth 12.f #define TongueImageHeight 12.f @@ -68,7 +69,6 @@ [self addSubview:self.imageView]; } self.imageView.image = [TUIChatSmallTongueView getTongueImage:tongue]; - self.imageView.mm_width(TongueImageWidth).mm_height(TongueImageHeight).mm_left(TongueLeftSpace).mm_top(10); if (!self.label) { self.label = [[UILabel alloc] init]; @@ -76,8 +76,19 @@ [self addSubview:self.label]; } self.label.text = [TUIChatSmallTongueView getTongueText:tongue]; + self.label.rtlAlignment = TUITextRTLAlignmentLeading; self.label.textColor = TUIChatDynamicColor(@"chat_drop_down_color", @"#147AFF"); - self.label.mm_flexToRight(TongueRightSpace).mm_height(TongueImageHeight).mm_left(self.imageView.mm_maxX + TongueMiddleSpace).mm_top(10); + [self.imageView mas_remakeConstraints:^(MASConstraintMaker *make) { + make.width.height.mas_equalTo(TongueImageWidth); + make.leading.mas_equalTo(TongueLeftSpace); + make.top.mas_equalTo(10); + }]; + [self.label mas_remakeConstraints:^(MASConstraintMaker *make) { + make.trailing.mas_lessThanOrEqualTo(self.mas_trailing).mas_offset(-TongueRightSpace); + make.height.mas_equalTo(TongueImageHeight); + make.leading.mas_equalTo(self.imageView.mas_trailing).mas_offset(TongueMiddleSpace); + make.top.mas_equalTo(10); + }]; } + (CGFloat)getTongueWidth:(TUIChatSmallTongue *)tongue { @@ -87,7 +98,7 @@ attributes:@{NSFontAttributeName : [UIFont systemFontOfSize:TongueFontSize]} context:nil] .size; - CGFloat tongueWidth = TongueLeftSpace + TongueImageWidth + TongueMiddleSpace + titleSize.width + TongueRightSpace; + CGFloat tongueWidth = TongueLeftSpace + TongueImageWidth + TongueMiddleSpace + ceil(titleSize.width) + TongueRightSpace; return tongueWidth; } @@ -164,9 +175,15 @@ static UIWindow *gWindow = nil; } } CGFloat tongueWidth = [TUIChatSmallTongueView getTongueWidth:gTongue]; - gWindow.frame = - CGRectMake(Screen_Width - tongueWidth - 16, Screen_Height - Bottom_SafeHeight - TTextView_Height - 20 - TongueHeight, tongueWidth, TongueHeight); + if(isRTL()) { + gWindow.frame = + CGRectMake(16, Screen_Height - Bottom_SafeHeight - TTextView_Height - 20 - TongueHeight, tongueWidth, TongueHeight); + } + else { + gWindow.frame = + CGRectMake(Screen_Width - tongueWidth - 16, Screen_Height - Bottom_SafeHeight - TTextView_Height - 20 - TongueHeight, tongueWidth, TongueHeight); + } if (!gTongueView) { gTongueView = [[TUIChatSmallTongueView alloc] initWithFrame:CGRectZero]; [gWindow addSubview:gTongueView]; diff --git a/iOS/TUIKit/TUIChat/UI_Classic/Chat/TUIFileViewController.m b/iOS/TUIKit/TUIChat/UI_Classic/Chat/TUIFileViewController.m index 7429ef6c4..610a2cfda 100644 --- a/iOS/TUIKit/TUIChat/UI_Classic/Chat/TUIFileViewController.m +++ b/iOS/TUIKit/TUIChat/UI_Classic/Chat/TUIFileViewController.m @@ -33,14 +33,17 @@ titleLabel.text = TIMCommonLocalizableString(File); titleLabel.font = [UIFont boldSystemFontOfSize:17.0]; titleLabel.textColor = TIMCommonDynamicColor(@"nav_title_text_color", @"#000000"); + titleLabel.textAlignment = isRTL()?NSTextAlignmentRight:NSTextAlignmentLeft; [titleLabel sizeToFit]; self.navigationItem.titleView = titleLabel; // left UIImage *defaultImage = [UIImage imageNamed:TUIChatImagePath(@"back")]; UIButton *leftButton = [[UIButton alloc] initWithFrame:CGRectMake(0, 0, 30, 30)]; + UIImage *formatImage = [TIMCommonDynamicImage(@"nav_back_img", defaultImage) rtl_imageFlippedForRightToLeftLayoutDirection]; + [leftButton addTarget:self action:@selector(onBack:) forControlEvents:UIControlEventTouchUpInside]; - [leftButton setImage:TIMCommonDynamicImage(@"nav_back_img", defaultImage) forState:UIControlStateNormal]; + [leftButton setImage:formatImage forState:UIControlStateNormal]; UIBarButtonItem *leftItem = [[UIBarButtonItem alloc] initWithCustomView:leftButton]; self.navigationItem.leftBarButtonItem = leftItem; diff --git a/iOS/TUIKit/TUIChat/UI_Classic/Chat/TUIGroupChatViewController.m b/iOS/TUIKit/TUIChat/UI_Classic/Chat/TUIGroupChatViewController.m index ba6cb5135..db1cfbea9 100644 --- a/iOS/TUIKit/TUIChat/UI_Classic/Chat/TUIGroupChatViewController.m +++ b/iOS/TUIKit/TUIChat/UI_Classic/Chat/TUIGroupChatViewController.m @@ -203,19 +203,13 @@ continue; } [weakSelf.atUserList addObject:model]; - if (i == 0) { - [atText appendString:[NSString stringWithFormat:@"%@ ", model.name]]; - } else { - [atText appendString:[NSString stringWithFormat:@"@%@ ", model.name]]; - } + [atText appendString:[NSString stringWithFormat:@"@%@ ", model.name]]; } NSAttributedString *spaceString = [[NSAttributedString alloc] initWithString:atText attributes:@{NSFontAttributeName : kTUIInputNoramlFont, NSForegroundColorAttributeName : kTUIInputNormalTextColor}]; - NSRange range = weakSelf.inputController.inputBar.inputTextView.selectedRange; - [weakSelf.inputController.inputBar.inputTextView.textStorage insertAttributedString:spaceString atIndex:range.location + range.length]; - [weakSelf.inputController.inputBar updateTextViewFrame]; + [weakSelf.inputController.inputBar addWordsToInputBar:spaceString ]; }]; } } @@ -259,11 +253,7 @@ NSString *nameString = [NSString stringWithFormat:@"@%@ ", user.name]; UIFont *textFont = kTUIInputNoramlFont; NSAttributedString *spaceString = [[NSAttributedString alloc] initWithString:nameString attributes:@{NSFontAttributeName : textFont}]; - [self.inputController.inputBar.inputTextView.textStorage insertAttributedString:spaceString - atIndex:self.inputController.inputBar.inputTextView.textStorage.length]; - [self.inputController.inputBar.inputTextView becomeFirstResponder]; - self.inputController.inputBar.inputTextView.selectedRange = - NSMakeRange(spaceString.length + self.inputController.inputBar.inputTextView.textStorage.length, 0); + [self.inputController.inputBar addWordsToInputBar:spaceString ]; } } diff --git a/iOS/TUIKit/TUIChat/UI_Classic/Chat/TUIMediaView.m b/iOS/TUIKit/TUIChat/UI_Classic/Chat/TUIMediaView.m index f62e90cd2..9b7ad5600 100644 --- a/iOS/TUIKit/TUIChat/UI_Classic/Chat/TUIMediaView.m +++ b/iOS/TUIKit/TUIChat/UI_Classic/Chat/TUIMediaView.m @@ -57,7 +57,7 @@ self.mediaView.backgroundColor = [UIColor clearColor]; [self addSubview:self.mediaView]; - UICollectionViewFlowLayout *menuFlowLayout = [[UICollectionViewFlowLayout alloc] init]; + TUICollectionRTLFitFlowLayout *menuFlowLayout = [[TUICollectionRTLFitFlowLayout alloc] init]; menuFlowLayout.scrollDirection = UICollectionViewScrollDirectionHorizontal; menuFlowLayout.minimumLineSpacing = 0; menuFlowLayout.minimumInteritemSpacing = 0; diff --git a/iOS/TUIKit/TUIChat/UI_Classic/Chat/TUIMessageController.m b/iOS/TUIKit/TUIChat/UI_Classic/Chat/TUIMessageController.m index 48729cb72..8afda250e 100644 --- a/iOS/TUIKit/TUIChat/UI_Classic/Chat/TUIMessageController.m +++ b/iOS/TUIKit/TUIChat/UI_Classic/Chat/TUIMessageController.m @@ -7,7 +7,6 @@ #import #import #import -#import "ReactiveObjC.h" #import "TUIBaseMessageController+ProtectedAPI.h" #import "TUIChatConfig.h" #import "TUIChatModifyMessageHelper.h" @@ -187,7 +186,7 @@ } - (void)loadLocateMessages:(BOOL)firstLoad { - if (!self.locateMessage) { + if (!self.locateMessage && self.locateGroupMessageSeq == 0) { return; } @weakify(self); @@ -379,7 +378,6 @@ } - (void)showReplyMessage:(TUIReplyMessageCell *)cell { - [UIApplication.sharedApplication.keyWindow endEditing:YES]; NSString *originMsgID = @""; NSString *msgAbstract = @""; if ([cell isKindOfClass:TUIReplyMessageCell.class]) { diff --git a/iOS/TUIKit/TUIChat/UI_Classic/Chat/TUIMessageMultiChooseView.m b/iOS/TUIKit/TUIChat/UI_Classic/Chat/TUIMessageMultiChooseView.m index 4cc538b2c..104544309 100644 --- a/iOS/TUIKit/TUIChat/UI_Classic/Chat/TUIMessageMultiChooseView.m +++ b/iOS/TUIKit/TUIChat/UI_Classic/Chat/TUIMessageMultiChooseView.m @@ -11,6 +11,7 @@ #import #import #import +#import @interface TUIMessageMultiChooseView () @@ -77,6 +78,14 @@ sub.frame = CGRectMake(i * width, centerY -= 0.5 * centerBottomOffset, width, height); } } + if(isRTL()) { + for (UIView *subview in self.toolView.subviews) { + [subview resetFrameToFitRTL]; + } + for (UIView *subview in self.menuView.subviews) { + [subview resetFrameToFitRTL]; + } + } } #pragma mark - Views diff --git a/iOS/TUIKit/TUIChat/UI_Classic/Chat/TUIMessageReadViewController.m b/iOS/TUIKit/TUIChat/UI_Classic/Chat/TUIMessageReadViewController.m index 01b0104a5..75db65b47 100644 --- a/iOS/TUIKit/TUIChat/UI_Classic/Chat/TUIMessageReadViewController.m +++ b/iOS/TUIKit/TUIChat/UI_Classic/Chat/TUIMessageReadViewController.m @@ -175,12 +175,25 @@ } - (void)layoutViews { - float backViewTop = self.navigationController.navigationBar.mm_maxY; - self.messageBackView.mm_left(0).mm_width(self.view.mm_w).mm_top(backViewTop); - + id content = [self content]; + CGFloat messageBackViewHeight = 69 ; + if ([content isKindOfClass:UIImage.class]) { + messageBackViewHeight = 87; + } + [self.messageBackView mas_makeConstraints:^(MASConstraintMaker *make) { + make.top.mas_equalTo(self.view.mas_safeAreaLayoutGuideTop); + make.leading.mas_equalTo(0); + make.height.mas_equalTo(messageBackViewHeight); + make.width.mas_equalTo(self.view); + }]; // content label may not exist when content is not text if (self.contentLabel) { - self.contentLabel.mm_left(16).mm_top(33).mm_height(24).mm_width(self.messageBackView.mm_w - 32); + [self.contentLabel mas_remakeConstraints:^(MASConstraintMaker *make) { + make.leading.mas_equalTo(16); + make.top.mas_equalTo(33); + make.height.mas_equalTo(24); + make.trailing.mas_equalTo(-16); + }]; } UIView *readView = [self layoutSelectView:self.selectViewsDict[@(TUIMessageReadViewTagRead)] leftView:nil]; @@ -200,10 +213,17 @@ if (count == 0) { return nil; } - view.mm_width(self.view.mm_w / count) - .mm_height(48) - .mm_left(leftView == nil ? 0 : leftView.mm_maxX) - .mm_top(self.messageBackView.mm_y + self.messageBackView.mm_h + 10); + [view mas_remakeConstraints:^(MASConstraintMaker *make) { + make.width.mas_equalTo(self.view).multipliedBy(1.0/count); + make.height.mas_equalTo(48); + if (leftView) { + make.leading.mas_equalTo(leftView.mas_trailing); + } + else { + make.leading.mas_equalTo(0); + } + make.top.mas_equalTo(self.messageBackView.mas_bottom).mas_offset(10); + }]; return view; } @@ -226,19 +246,31 @@ nameLabel.text = self.cellData.name; nameLabel.font = [UIFont systemFontOfSize:12.0]; nameLabel.textColor = TUIChatDynamicColor(@"chat_message_read_name_date_text_color", @"#999999"); + nameLabel.textAlignment = isRTL()?NSTextAlignmentRight:NSTextAlignmentLeft; [messageBackView addSubview:nameLabel]; - nameLabel.mm_sizeToFit().mm_top(12).mm_left(16); - + [nameLabel sizeToFit]; + [nameLabel mas_makeConstraints:^(MASConstraintMaker *make) { + make.top.mas_equalTo(12); + make.leading.mas_equalTo(16); + make.width.mas_equalTo(nameLabel.frame.size.width); + make.height.mas_equalTo(nameLabel.frame.size.height); + }]; UILabel *dateLabel = [[UILabel alloc] init]; NSDateFormatter *formatter = [[NSDateFormatter alloc] init]; [formatter setDateFormat:@"MM-dd HH:mm"]; NSString *dateString = [formatter stringFromDate:self.cellData.innerMessage.timestamp]; dateLabel.text = dateString; dateLabel.font = [UIFont systemFontOfSize:12]; + dateLabel.textAlignment = isRTL()?NSTextAlignmentRight:NSTextAlignmentLeft; dateLabel.textColor = TUIChatDynamicColor(@"chat_message_read_name_date_text_color", @"#999999"); [messageBackView addSubview:dateLabel]; - dateLabel.mm_sizeToFit().mm_left(nameLabel.mm_x + nameLabel.mm_w + 12).mm__centerY(nameLabel.mm_centerY); - + [dateLabel sizeToFit]; + [dateLabel mas_makeConstraints:^(MASConstraintMaker *make) { + make.centerY.mas_equalTo(nameLabel); + make.leading.mas_equalTo(nameLabel.mas_trailing).mas_offset(12); + make.width.mas_equalTo(dateLabel.frame.size.width); + make.height.mas_equalTo(dateLabel.frame.size.height); + }]; id content = [self content]; if ([content isKindOfClass:NSString.class]) { UILabel *contentLabel = [[UILabel alloc] init]; @@ -246,22 +278,26 @@ contentLabel.font = [UIFont systemFontOfSize:16]; contentLabel.textColor = TUIChatDynamicColor(@"chat_input_text_color", @"#111111"); contentLabel.lineBreakMode = NSLineBreakByTruncatingTail; + contentLabel.textAlignment = isRTL()?NSTextAlignmentRight:NSTextAlignmentLeft; self.contentLabel = contentLabel; [messageBackView addSubview:contentLabel]; - messageBackView.mm_height(69); } else if ([content isKindOfClass:UIImage.class]) { UIImageView *imageView = [[UIImageView alloc] init]; imageView.image = content; [messageBackView addSubview:imageView]; - messageBackView.mm_height(87); - - imageView.mm_left(16).mm_top(33).mm_height([self scaledSizeOfImage:content].height).mm_width([self scaledSizeOfImage:content].width); + [imageView mas_makeConstraints:^(MASConstraintMaker *make) { + make.top.mas_equalTo(33); + make.leading.mas_equalTo(16); + make.width.mas_equalTo([self scaledSizeOfImage:content].width); + make.height.mas_equalTo([self scaledSizeOfImage:content].height); + }]; } } - (void)setupSelectView { NSMutableDictionary *dataDict = [self selectViewsData]; NSInteger count = dataDict.count; + NSMutableArray * selectViewsArray = [NSMutableArray arrayWithCapacity:2]; UIView *tmp = nil; for (NSNumber *tag in dataDict) { NSDictionary *data = dataDict[tag]; @@ -271,6 +307,7 @@ selectView.backgroundColor = TIMCommonDynamicColor(@"form_bg_color", @"#FFFFFF"); selectView.delegate = self; [self.view addSubview:selectView]; + [selectViewsArray addObject:selectView]; [self.selectViewsDict setObject:selectView forKey:data[@"tag"]]; selectView.mm_width(self.view.mm_w / count) diff --git a/iOS/TUIKit/TUIChat/UI_Classic/Chat/TUIRepliesDetailViewController.m b/iOS/TUIKit/TUIChat/UI_Classic/Chat/TUIRepliesDetailViewController.m index b239ffc83..e5ef88d89 100644 --- a/iOS/TUIKit/TUIChat/UI_Classic/Chat/TUIRepliesDetailViewController.m +++ b/iOS/TUIKit/TUIChat/UI_Classic/Chat/TUIRepliesDetailViewController.m @@ -12,6 +12,7 @@ #import "TUIMessageDataProvider.h" #import "TUITextMessageCell.h" #import "TUITextMessageCellData.h" +#import "TUIChatConfig.h" #import #import @@ -77,7 +78,9 @@ [self setupInputViewController]; - [TUICore registerEvent:TUICore_TUITranslationNotify subKey:TUICore_TUITranslationNotify_DidChangeTranslationSubKey object:self]; + [TUICore registerEvent:TUICore_TUIPluginNotify + subKey:TUICore_TUIPluginNotify_DidChangePluginViewSubKey + object:self]; } - (void)viewWillAppear:(BOOL)animated { [self updateRootMsg]; @@ -162,7 +165,8 @@ } - (void)updateTableViewConstraint { - CGFloat height = CGRectGetMaxY(self.inputController.inputBar.frame) + Bottom_SafeHeight; + CGFloat textViewHeight = TUIChatConfig.defaultConfig.enableMainPageInputBar? CGRectGetMaxY(self.inputController.inputBar.frame):0; + CGFloat height = textViewHeight + Bottom_SafeHeight; CGRect msgFrame = self.tableView.frame; msgFrame.size.height = self.view.frame.size.height - height; self.tableView.frame = msgFrame; @@ -193,7 +197,7 @@ data.path = group.menuPath; data.isSelected = YES; [_inputController.menuView setData:(id) @[ data ]]; - + _inputController.view.hidden = !TUIChatConfig.defaultConfig.enableMainPageInputBar; CGFloat margin = 20; CGFloat padding = 10; _inputController.inputBar.inputTextView.frame = @@ -650,8 +654,9 @@ #pragma mark - TUINotificationProtocol - (void)onNotifyEvent:(NSString *)key subKey:(NSString *)subKey object:(id)anObject param:(NSDictionary *)param { - if ([key isEqualToString:TUICore_TUITranslationNotify] && [subKey isEqualToString:TUICore_TUITranslationNotify_DidChangeTranslationSubKey]) { - TUIMessageCellData *data = param[TUICore_TUITranslationNotify_DidChangeTranslationSubKey_Data]; + if ([key isEqualToString:TUICore_TUIPluginNotify] && + [subKey isEqualToString:TUICore_TUIPluginNotify_DidChangePluginViewSubKey]) { + TUIMessageCellData *data = param[TUICore_TUIPluginNotify_DidChangePluginViewSubKey_Data]; [self.messageCellConfig removeHeightCacheOfMessageCellData:data]; [self reloadAndScrollToBottomOfMessage:data.innerMessage.msgID section:1]; } diff --git a/iOS/TUIKit/TUIChat/UI_Classic/Input/TUIInputBar.h b/iOS/TUIKit/TUIChat/UI_Classic/Input/TUIInputBar.h index d376987f8..b108256bd 100644 --- a/iOS/TUIKit/TUIChat/UI_Classic/Input/TUIInputBar.h +++ b/iOS/TUIKit/TUIChat/UI_Classic/Input/TUIInputBar.h @@ -223,4 +223,6 @@ - (void)changeToKeyboard; +- (void)addDraftToInputBar:(NSAttributedString *)draft; +- (void)addWordsToInputBar:(NSAttributedString *)words; @end diff --git a/iOS/TUIKit/TUIChat/UI_Classic/Input/TUIInputBar.m b/iOS/TUIKit/TUIChat/UI_Classic/Input/TUIInputBar.m index 6988b15d8..083362f1f 100644 --- a/iOS/TUIKit/TUIChat/UI_Classic/Input/TUIInputBar.m +++ b/iOS/TUIKit/TUIChat/UI_Classic/Input/TUIInputBar.m @@ -100,6 +100,7 @@ [_inputTextView setFont:kTUIInputNoramlFont]; _inputTextView.backgroundColor = TUIChatDynamicColor(@"chat_input_bg_color", @"#FFFFFF"); _inputTextView.textColor = TUIChatDynamicColor(@"chat_input_text_color", @"#000000"); + _inputTextView.textAlignment = isRTL()?NSTextAlignmentRight: NSTextAlignmentLeft; [_inputTextView setReturnKeyType:UIReturnKeySend]; [self addSubview:_inputTextView]; @@ -139,6 +140,12 @@ CGFloat endX = _faceButton.frame.origin.x - TTextView_Margin; _recordButton.frame = CGRectMake(beginX, (TTextView_Height - TTextView_TextView_Height_Min) * 0.5, endX - beginX, TTextView_TextView_Height_Min); _inputTextView.frame = _recordButton.frame; + + if(isRTL()) { + for (UIView *subviews in self.subviews) { + [subviews resetFrameToFitRTL]; + } + } } - (void)layoutButton:(CGFloat)height { @@ -438,6 +445,7 @@ if (self.delegate && [self.delegate respondsToSelector:@selector(inputBarDidInputAt:)]) { [self.delegate inputBarDidInputAt:self]; } + return NO; } return YES; } @@ -462,7 +470,7 @@ TUIEmojiTextAttachment *emojiTextAttachment = [[TUIEmojiTextAttachment alloc] init]; emojiTextAttachment.faceCellData = emoji; - NSString *localizableFaceName = emoji.localizableName.length ? emoji.localizableName : emoji.name; + NSString *localizableFaceName = emoji.name; // Set tag and image emojiTextAttachment.emojiTag = localizableFaceName; @@ -502,6 +510,8 @@ [_inputTextView.textStorage addAttribute:NSFontAttributeName value:kTUIInputNoramlFont range:wholeRange]; [_inputTextView setFont:kTUIInputNoramlFont]; + _inputTextView.textAlignment = isRTL()?NSTextAlignmentRight: NSTextAlignmentLeft; + // In iOS 15.0 and later, you need set styles again as belows _inputTextView.textColor = kTUIInputNormalTextColor; _inputTextView.font = kTUIInputNoramlFont; @@ -522,6 +532,25 @@ [self onKeyboardButtonClicked:self.keyboardButton]; } +- (void)addDraftToInputBar:(NSAttributedString *)draft { + [self addWordsToInputBar:draft]; +} + +- (void)addWordsToInputBar:(NSAttributedString *)words { + NSRange selectedRange = self.inputTextView.selectedRange; + if (selectedRange.length > 0) { + [self.inputTextView.textStorage deleteCharactersInRange:selectedRange]; + } + // Insert draft + [self.inputTextView.textStorage insertAttributedString:words atIndex:self.inputTextView.selectedRange.location]; + + self.inputTextView.selectedRange = NSMakeRange(self.inputTextView.textStorage.length + 1, 0); + [self resetTextStyle]; + + [self updateTextViewFrame]; + +} + #pragma mark - TUIAudioRecorderDelegate - (void)audioRecorder:(TUIAudioRecorder *)recorder didCheckPermission:(BOOL)isGranted isFirstTime:(BOOL)isFirstTime { if (isFirstTime) { @@ -569,8 +598,9 @@ } - (void)audioRecorder:(TUIAudioRecorder *)recorder didRecordTimeChanged:(NSTimeInterval)time { - if (time >= 55 && time < 60) { - NSInteger seconds = 60 - time; + float maxDuration = 59; + if (time >= 55 && time <= maxDuration) { + NSInteger seconds = maxDuration - time; /** * 此处强转了 long 型,是为了消除编译器警告。 * 此处 +1 是为了向上取整,优化时间逻辑。 @@ -579,7 +609,7 @@ * Here +1 is to round up and optimize the time logic. */ self.recordView.title.text = [NSString stringWithFormat:TIMCommonLocalizableString(TUIKitInputWillFinishRecordInSeconds), (long)seconds + 1]; - } else if (time >= 60) { + } else if (time > maxDuration) { [self.recorder stop]; NSString *path = self.recorder.recordedFilePath; [self.recordView setStatus:Record_Status_TooLong]; diff --git a/iOS/TUIKit/TUIChat/UI_Classic/Input/TUIInputController.m b/iOS/TUIKit/TUIChat/UI_Classic/Input/TUIInputController.m index bd9a37c93..fc04bbf29 100644 --- a/iOS/TUIKit/TUIChat/UI_Classic/Input/TUIInputController.m +++ b/iOS/TUIKit/TUIChat/UI_Classic/Input/TUIInputController.m @@ -396,7 +396,7 @@ - (void)inputBar:(TUIInputBar *)textView didSendVoice:(NSString *)path { NSURL *url = [NSURL fileURLWithPath:path]; AVURLAsset *audioAsset = [AVURLAsset URLAssetWithURL:url options:nil]; - int duration = (int)CMTimeGetSeconds(audioAsset.duration); + int duration = CMTimeGetSeconds(audioAsset.duration) > 59 ? 60 : (int)CMTimeGetSeconds(audioAsset.duration); V2TIMMessage *message = [[V2TIMManager sharedInstance] createSoundMessage:path duration:duration]; if (message && _delegate && [_delegate respondsToSelector:@selector(inputController:didSendMessage:)]) { [_delegate inputController:self didSendMessage:message]; diff --git a/iOS/TUIKit/TUIChat/UI_Classic/Input/TUIMenuView.m b/iOS/TUIKit/TUIChat/UI_Classic/Input/TUIMenuView.m index 569238f5e..fb8becc83 100644 --- a/iOS/TUIKit/TUIChat/UI_Classic/Input/TUIMenuView.m +++ b/iOS/TUIKit/TUIChat/UI_Classic/Input/TUIMenuView.m @@ -45,7 +45,7 @@ [_sendButton addTarget:self action:@selector(sendUpInside:) forControlEvents:UIControlEventTouchUpInside]; [self addSubview:_sendButton]; - _menuFlowLayout = [[UICollectionViewFlowLayout alloc] init]; + _menuFlowLayout = [[TUICollectionRTLFitFlowLayout alloc] init]; _menuFlowLayout.scrollDirection = UICollectionViewScrollDirectionHorizontal; _menuFlowLayout.minimumLineSpacing = 0; _menuFlowLayout.minimumInteritemSpacing = 0; @@ -67,8 +67,18 @@ - (void)defaultLayout { CGFloat buttonWidth = self.frame.size.height * 1.3; - _sendButton.frame = CGRectMake(self.frame.size.width - buttonWidth, 0, buttonWidth, self.frame.size.height); - _menuCollectionView.frame = CGRectMake(0, 0, self.frame.size.width - 2 * buttonWidth, self.frame.size.height); + [_sendButton mas_remakeConstraints:^(MASConstraintMaker *make) { + make.trailing.mas_equalTo(self.mas_trailing); + make.width.mas_equalTo(buttonWidth); + make.height.mas_equalTo(self); + make.centerY.mas_equalTo(self); + }]; + [_menuCollectionView mas_remakeConstraints:^(MASConstraintMaker *make) { + make.leading.mas_equalTo(0); + make.trailing.mas_equalTo(_sendButton.mas_leading).mas_offset(- 30); + make.height.mas_equalTo(self); + make.centerY.mas_equalTo(self); + }]; } - (void)sendUpInside:(UIButton *)sender { diff --git a/iOS/TUIKit/TUIChat/UI_Classic/Input/TUIMoreView.m b/iOS/TUIKit/TUIChat/UI_Classic/Input/TUIMoreView.m index 324e3652b..23e7a3154 100644 --- a/iOS/TUIKit/TUIChat/UI_Classic/Input/TUIMoreView.m +++ b/iOS/TUIKit/TUIChat/UI_Classic/Input/TUIMoreView.m @@ -33,7 +33,7 @@ - (void)setupViews { self.backgroundColor = TUIChatDynamicColor(@"chat_input_controller_bg_color", @"#EBF0F6"); - _moreFlowLayout = [[UICollectionViewFlowLayout alloc] init]; + _moreFlowLayout = [[TUICollectionRTLFitFlowLayout alloc] init]; _moreFlowLayout.scrollDirection = UICollectionViewScrollDirectionHorizontal; _moreFlowLayout.minimumLineSpacing = 0; _moreFlowLayout.minimumInteritemSpacing = 0; diff --git a/iOS/TUIKit/TUIChat/UI_Classic/Service/TUIChatObjectFactory.m b/iOS/TUIKit/TUIChat/UI_Classic/Service/TUIChatObjectFactory.m index 940fd7530..1ab6654ce 100644 --- a/iOS/TUIKit/TUIChat/UI_Classic/Service/TUIChatObjectFactory.m +++ b/iOS/TUIKit/TUIChat/UI_Classic/Service/TUIChatObjectFactory.m @@ -52,7 +52,10 @@ V2TIMMessage *locateMessage = [param tui_objectForKey:TUICore_TUIChatObjectFactory_ChatViewController_LocateMessage asClass:V2TIMMessage.class]; NSArray * atMsgSeqs = [param tui_objectForKey:TUICore_TUIChatObjectFactory_ChatViewController_AtMsgSeqs asClass:NSArray.class]; NSString *draft = [param tui_objectForKey:TUICore_TUIChatObjectFactory_ChatViewController_Draft asClass:NSString.class]; - + NSString *isEnableVideoInfoStr = [param tui_objectForKey:TUICore_TUIChatObjectFactory_ChatViewController_Enable_Video_Call asClass:NSString.class]; + NSString *isEnableAudioInfoStr = [param tui_objectForKey:TUICore_TUIChatObjectFactory_ChatViewController_Enable_Audio_Call asClass:NSString.class]; + NSString *isEnableRoomInfoStr = [param tui_objectForKey:TUICore_TUIChatObjectFactory_ChatViewController_Enable_Room asClass:NSString.class]; + TUIChatConversationModel *conversationModel = [[TUIChatConversationModel alloc] init]; conversationModel.title = title; conversationModel.userID = userID; @@ -63,6 +66,18 @@ conversationModel.atMsgSeqs = [NSMutableArray arrayWithArray:atMsgSeqs]; conversationModel.draftText = draft; + if ([isEnableVideoInfoStr isEqualToString:@"0"]) { + conversationModel.enabelVideo = NO; + } + + if ([isEnableAudioInfoStr isEqualToString:@"0"]) { + conversationModel.enabelAudio = NO; + } + + if ([isEnableRoomInfoStr isEqualToString:@"0"]) { + conversationModel.enabelRoom = NO; + } + TUIBaseChatViewController *chatVC = nil; if (conversationModel.groupID.length > 0) { chatVC = [[TUIGroupChatViewController alloc] init]; diff --git a/iOS/TUIKit/TUIChat/UI_Classic/Service/TUIChatService.m b/iOS/TUIKit/TUIChat/UI_Classic/Service/TUIChatService.m index 48b354f29..308d712b1 100644 --- a/iOS/TUIKit/TUIChat/UI_Classic/Service/TUIChatService.m +++ b/iOS/TUIKit/TUIChat/UI_Classic/Service/TUIChatService.m @@ -70,13 +70,6 @@ if (![key isKindOfClass:NSString.class] || ![obj isKindOfClass:NSNumber.class]) { return; } - if ([key isEqualToString:TUICore_TUIChatService_SetChatExtensionMethod_EnableVideoCallKey]) { - TUIChatConfig.defaultConfig.enableVideoCall = obj.boolValue; - } else if ([key isEqualToString:TUICore_TUIChatService_SetChatExtensionMethod_EnableAudioCallKey]) { - TUIChatConfig.defaultConfig.enableAudioCall = obj.boolValue; - } else if ([key isEqualToString:TUICore_TUIChatService_SetChatExtensionMethod_EnableLinkKey]) { - TUIChatConfig.defaultConfig.enableWelcomeCustomMessage = obj.boolValue; - } }]; } else if ([method isEqualToString:TUICore_TUIChatService_AppendCustomMessageMethod]) { if ([param isKindOfClass:NSDictionary.class]) { diff --git a/iOS/TUIKit/TUIChat/UI_Minimalist/Cell/Base/TUIMemberCell_Minimalist.m b/iOS/TUIKit/TUIChat/UI_Minimalist/Cell/Base/TUIMemberCell_Minimalist.m index 496c7bc06..b92c84630 100644 --- a/iOS/TUIKit/TUIChat/UI_Minimalist/Cell/Base/TUIMemberCell_Minimalist.m +++ b/iOS/TUIKit/TUIChat/UI_Minimalist/Cell/Base/TUIMemberCell_Minimalist.m @@ -49,11 +49,6 @@ - (void)layoutSubviews { [super layoutSubviews]; - CGFloat margin = kScale390(16); - self.containerView.frame = CGRectMake(margin, 0, self.contentView.frame.size.width - 2 * margin, kScale390(57)); - self.icon.frame = CGRectMake(kScale390(20), kScale390(20), kScale390(16), kScale390(16)); - self.titleLabel.frame = CGRectMake(self.icon.frame.origin.x + self.icon.frame.size.width + kScale390(11), kScale390(20), - self.containerView.frame.size.width * 0.5, kScale390(17)); } #pragma mark - Public @@ -63,6 +58,45 @@ self.titleLabel.text = cellData.title; [self.icon setImage:cellData.icon]; + + // tell constraints they need updating + [self setNeedsUpdateConstraints]; + + // update constraints now so we can animate the change + [self updateConstraintsIfNeeded]; + + [self layoutIfNeeded]; +} + ++ (BOOL)requiresConstraintBasedLayout { + return YES; +} + +// this is Apple's recommended place for adding/updating constraints +- (void)updateConstraints { + + [super updateConstraints]; + + CGFloat margin = kScale390(16); + [self.containerView mas_remakeConstraints:^(MASConstraintMaker *make) { + make.leading.mas_equalTo(margin); + make.top.mas_equalTo(0); + make.trailing.mas_equalTo(-margin); + make.height.mas_equalTo(kScale390(57)); + }]; + [self.icon mas_remakeConstraints:^(MASConstraintMaker *make) { + make.leading.mas_equalTo(kScale390(20)); + make.centerY.mas_equalTo(self.containerView); + make.width.height.mas_equalTo(kScale390(16)); + }]; + + [self.titleLabel sizeToFit]; + [self.titleLabel mas_remakeConstraints:^(MASConstraintMaker *make) { + make.centerY.mas_equalTo(self.containerView); + make.leading.mas_equalTo(self.icon.mas_trailing).mas_offset(kScale390(11)); + make.height.mas_equalTo(self.titleLabel.frame.size.height); + make.trailing.mas_equalTo(-kScale390(11)); + }]; } @end @@ -86,24 +120,15 @@ self.avatarView = [[UIImageView alloc] initWithImage:DefaultAvatarImage]; [self.contentView addSubview:self.avatarView]; - self.avatarView.mm_width(kScale390(32)).mm_height(kScale390(32)).mm__centerY(28).mm_left(kScale390(24)); - if ([TUIConfig defaultConfig].avatarType == TAvatarTypeRounded) { - self.avatarView.layer.masksToBounds = YES; - self.avatarView.layer.cornerRadius = self.avatarView.frame.size.height / 2; - } else if ([TUIConfig defaultConfig].avatarType == TAvatarTypeRadiusCorner) { - self.avatarView.layer.masksToBounds = YES; - self.avatarView.layer.cornerRadius = [TUIConfig defaultConfig].avatarCornerRadius; - } self.titleLabel = [[UILabel alloc] initWithFrame:CGRectZero]; [self.contentView addSubview:self.titleLabel]; self.titleLabel.textColor = TIMCommonDynamicColor(@"form_title_color", @"#000000"); self.titleLabel.font = [UIFont boldSystemFontOfSize:kScale390(14)]; - self.titleLabel.mm_left(self.avatarView.mm_maxX + kScale390(4)).mm_height(kScale390(17)).mm_width(200).mm__centerY(self.avatarView.mm_centerY); self.detailLabel = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, 100, 20)]; [self.contentView addSubview:self.detailLabel]; - self.detailLabel.textAlignment = NSTextAlignmentRight; + self.detailLabel.rtlAlignment = TUITextRTLAlignmentTrailing; self.detailLabel.textColor = TIMCommonDynamicColor(@"form_title_color", @"#000000"); self.detailLabel.mm__centerY(self.avatarView.mm_centerY); @@ -116,8 +141,6 @@ - (void)layoutSubviews { [super layoutSubviews]; - self.detailLabel.mm_sizeToFit(); - self.detailLabel.mm_right(12); } #pragma mark - Public @@ -129,6 +152,54 @@ [self.avatarView sd_setImageWithURL:cellData.avatarUrL placeholderImage:DefaultAvatarImage]; self.detailLabel.hidden = cellData.detail.length == 0; self.detailLabel.text = cellData.detail; + // tell constraints they need updating + [self setNeedsUpdateConstraints]; + + // update constraints now so we can animate the change + [self updateConstraintsIfNeeded]; + + [self layoutIfNeeded]; } ++ (BOOL)requiresConstraintBasedLayout { + return YES; +} + +// this is Apple's recommended place for adding/updating constraints +- (void)updateConstraints { + + [super updateConstraints]; + + CGFloat imgWidth = kScale390(32); + + [self.avatarView mas_remakeConstraints:^(MASConstraintMaker *make) { + make.width.height.mas_equalTo(imgWidth); + make.centerY.mas_equalTo(self.contentView.mas_centerY); + make.leading.mas_equalTo(kScale390(24)); + }]; + if ([TUIConfig defaultConfig].avatarType == TAvatarTypeRounded) { + self.avatarView.layer.masksToBounds = YES; + self.avatarView.layer.cornerRadius = imgWidth / 2; + } else if ([TUIConfig defaultConfig].avatarType == TAvatarTypeRadiusCorner) { + self.avatarView.layer.masksToBounds = YES; + self.avatarView.layer.cornerRadius = [TUIConfig defaultConfig].avatarCornerRadius; + } + + [self.titleLabel mas_remakeConstraints:^(MASConstraintMaker *make) { + make.centerY.mas_equalTo(self.avatarView.mas_centerY); + make.leading.mas_equalTo(self.avatarView.mas_trailing).mas_offset(4); + make.height.mas_equalTo(kScale390(17)); + make.trailing.lessThanOrEqualTo(self.detailLabel.mas_leading).mas_offset(-5); + }]; + + [self.detailLabel sizeToFit]; + [self.detailLabel mas_remakeConstraints:^(MASConstraintMaker *make) { + make.centerY.mas_equalTo(self.avatarView.mas_centerY); + make.height.mas_equalTo(20); + make.trailing.mas_equalTo(self.contentView.mas_trailing).mas_offset(-12); + make.width.mas_equalTo(self.detailLabel.frame.size.width); + }]; + + +} @end diff --git a/iOS/TUIKit/TUIChat/UI_Minimalist/Cell/Base/TUITextMessageCell_Minimalist.m b/iOS/TUIKit/TUIChat/UI_Minimalist/Cell/Base/TUITextMessageCell_Minimalist.m index 42d19ebca..f2c448d1f 100644 --- a/iOS/TUIKit/TUIChat/UI_Minimalist/Cell/Base/TUITextMessageCell_Minimalist.m +++ b/iOS/TUIKit/TUIChat/UI_Minimalist/Cell/Base/TUITextMessageCell_Minimalist.m @@ -74,16 +74,46 @@ self.textView.attributedText = [data getAttributedString:textFont]; self.textView.textColor = textColor; self.textView.font = textFont; + self.textView.textAlignment = isRTL()?NSTextAlignmentRight:NSTextAlignmentLeft; + + // tell constraints they need updating + [self setNeedsUpdateConstraints]; + + // update constraints now so we can animate the change + [self updateConstraintsIfNeeded]; + + [self layoutIfNeeded]; } ++ (BOOL)requiresConstraintBasedLayout { + return YES; +} + +// this is Apple's recommended place for adding/updating constraints +- (void)updateConstraints { + + [super updateConstraints]; +// self.textView.frame = (CGRect){.origin = self.textData.textOrigin, .size = self.textData.textSize}; + [self.textView mas_remakeConstraints:^(MASConstraintMaker *make) { + make.leading.mas_equalTo(self.bubbleView.mas_leading).mas_offset(ceil(self.textData.textOrigin.x)); + make.top.mas_equalTo(self.bubbleView.mas_top).mas_offset(ceil(self.textData.textOrigin.y)); + make.width.mas_equalTo(ceil(self.textData.textSize.width)); + make.height.mas_equalTo(ceil(self.textData.textSize.height)); + }]; + MASAttachKeys(self.textView); + if (self.voiceReadPoint.hidden == NO) { + [self.voiceReadPoint mas_remakeConstraints:^(MASConstraintMaker *make) { + make.top.mas_equalTo(self.bubbleView); + make.leading.mas_equalTo(self.bubbleView.mas_trailing).mas_offset(1); + make.size.mas_equalTo(CGSizeMake(5, 5)); + }]; + } + MASAttachKeys(self.voiceReadPoint); + [self layoutBottomContainer]; + +} - (void)layoutSubviews { [super layoutSubviews]; - self.textView.frame = (CGRect){.origin = self.textData.textOrigin, .size = self.textData.textSize}; - if (self.voiceReadPoint.hidden == NO) { - self.voiceReadPoint.frame = CGRectMake(CGRectGetMaxX(self.bubbleView.frame), 0, 5, 5); - } - - [self layoutBottomContainer]; } - (void)layoutBottomContainer { @@ -96,19 +126,23 @@ /// Add an extra tiny offset to the left or right of TransitionView if replyView is visible. CGFloat offset = self.replyLineView.hidden ? 0 : 1; UIView *view = self.replyEmojiView.hidden ? self.bubbleView : self.replyEmojiView; - CGFloat topMargin = view.mm_maxY + self.nameLabel.mm_h + 6; - if (self.textData.direction == MsgDirectionOutgoing) { - self.bottomContainer.mm_top(topMargin).mm_width(size.width).mm_height(size.height).mm_right(self.mm_w - self.container.mm_maxX + offset); - } else { - self.bottomContainer.mm_top(topMargin).mm_width(size.width).mm_height(size.height).mm_left(self.container.mm_minX + offset); - } + [self.bottomContainer mas_remakeConstraints:^(MASConstraintMaker *make) { + if (self.textData.direction == MsgDirectionIncoming) { + make.leading.mas_equalTo(self.container.mas_leading).mas_offset(offset); + } else { + make.trailing.mas_equalTo(self.container.mas_trailing).mas_offset(-offset); + } + make.top.mas_equalTo(view.mas_bottom).mas_offset(6); + make.size.mas_equalTo(size); + }]; if (!self.messageModifyRepliesButton.hidden) { CGRect oldRect = self.messageModifyRepliesButton.frame; CGRect newRect = CGRectMake(oldRect.origin.x, CGRectGetMaxY(self.bottomContainer.frame) + 5, oldRect.size.width, oldRect.size.height); self.messageModifyRepliesButton.frame = newRect; } + for (UIView *view in self.replyAvatarImageViews) { CGRect oldRect = view.frame; CGRect newRect = CGRectMake(oldRect.origin.x, CGRectGetMaxY(self.bottomContainer.frame) + 5, oldRect.size.width, oldRect.size.height); @@ -168,7 +202,7 @@ CGFloat height = [super getHeight:textCellData withWidth:width]; if (textCellData.bottomContainerSize.height > 0) { - height += textCellData.bottomContainerSize.height + kScale375(6); + height += textCellData.bottomContainerSize.height + 6; } return height; } diff --git a/iOS/TUIKit/TUIChat/UI_Minimalist/Cell/Chat/TUIFaceMessageCell_Minimalist.m b/iOS/TUIKit/TUIChat/UI_Minimalist/Cell/Chat/TUIFaceMessageCell_Minimalist.m index acfd341ce..6d299a969 100644 --- a/iOS/TUIKit/TUIChat/UI_Minimalist/Cell/Chat/TUIFaceMessageCell_Minimalist.m +++ b/iOS/TUIKit/TUIChat/UI_Minimalist/Cell/Chat/TUIFaceMessageCell_Minimalist.m @@ -27,19 +27,43 @@ return self; } ++ (BOOL)requiresConstraintBasedLayout { + return YES; +} + +// this is Apple's recommended place for adding/updating constraints +- (void)updateConstraints { + + [super updateConstraints]; + + CGFloat topMargin = 0; + CGFloat height = self.container.mm_h; + [self.face mas_remakeConstraints:^(MASConstraintMaker *make) { + make.height.mas_equalTo(kScale390(88)); + make.centerX.mas_equalTo(self.container.mas_centerX); + make.top.mas_equalTo(topMargin); + make.width.mas_equalTo(kScale390(90)); + }]; + + +} - (void)layoutSubviews { [super layoutSubviews]; - _face.mm_width(kScale390(90)).mm_height(kScale390(88)).mm_left(kScale390(16)).mm_top(kScale390(8)); - - _face.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight; } + - (void)fillWithData:(TUIFaceMessageCellData *)data { // set data [super fillWithData:data]; self.faceData = data; - _face.image = [[TUIImageCache sharedInstance] getFaceFromCache:data.path]; - ; + + // tell constraints they need updating + [self setNeedsUpdateConstraints]; + + // update constraints now so we can animate the change + [self updateConstraintsIfNeeded]; + + [self layoutIfNeeded]; } #pragma mark - TUIMessageCellProtocol diff --git a/iOS/TUIKit/TUIChat/UI_Minimalist/Cell/Chat/TUIFileMessageCell_Minimalist.m b/iOS/TUIKit/TUIChat/UI_Minimalist/Cell/Chat/TUIFileMessageCell_Minimalist.m index 74098e8f5..73592cb78 100644 --- a/iOS/TUIKit/TUIChat/UI_Minimalist/Cell/Chat/TUIFileMessageCell_Minimalist.m +++ b/iOS/TUIKit/TUIChat/UI_Minimalist/Cell/Chat/TUIFileMessageCell_Minimalist.m @@ -77,7 +77,81 @@ NSInteger downloadProgress = [TUIMessageProgressManager.shareManager downloadProgressForMessage:self.fileData.msgID]; [self onUploadProgress:self.fileData.msgID progress:uploadProgress]; [self onDownloadProgress:self.fileData.msgID progress:downloadProgress]; + }); + // tell constraints they need updating + [self setNeedsUpdateConstraints]; + + // update constraints now so we can animate the change + [self updateConstraintsIfNeeded]; + + [self layoutIfNeeded]; + +} + ++ (BOOL)requiresConstraintBasedLayout { + return YES; +} + +// this is Apple's recommended place for adding/updating constraints +- (void)updateConstraints { + + [super updateConstraints]; + + CGSize containerSize = [self.class getContentSize:self.fileData]; + [self.fileContainer mas_remakeConstraints:^(MASConstraintMaker *make) { + make.width.mas_equalTo(containerSize.width - kScale390(32)); + make.height.mas_equalTo(48); + make.leading.mas_equalTo(kScale390(16)); + make.top.mas_equalTo(self.bubbleView).mas_offset(8); + }]; + + + CGFloat fileImageSize = 24; + + [self.fileImage mas_remakeConstraints:^(MASConstraintMaker *make) { + make.leading.mas_equalTo(self.container.mas_leading).mas_offset(kScale390(17)); + make.top.mas_equalTo(self.container.mas_top).mas_offset(kScale390(12)); + make.size.mas_equalTo(fileImageSize); + }]; + + [self.fileName mas_remakeConstraints:^(MASConstraintMaker *make) { + make.leading.mas_equalTo(self.fileImage.mas_trailing).mas_offset(kScale390(8)); + make.top.mas_equalTo(15); + make.trailing.mas_equalTo(self.container.mas_trailing).mas_offset(- kScale390(12)); + make.height.mas_equalTo(17); + }]; + + [self.length mas_remakeConstraints:^(MASConstraintMaker *make) { + make.leading.mas_equalTo(self.container).mas_offset(kScale390(22)); + make.bottom.mas_equalTo(self.container.mas_bottom).mas_offset(- 11); + make.size.mas_equalTo(CGSizeMake(150, 14)); + }]; + + if (!self.fileData.isLocalExist && !self.fileData.isDownloading) { + CGFloat downloadSize = 16; + [self.downloadImage mas_remakeConstraints:^(MASConstraintMaker *make) { + if (self.fileData.direction == MsgDirectionIncoming) { + make.leading.mas_equalTo(self.bubbleView.mas_trailing).mas_offset(kScale390(8)); + } else { + make.trailing.mas_equalTo(self.bubbleView.mas_leading).mas_offset(- kScale390(8)); + } + make.centerY.mas_equalTo(self.length.mas_centerY); + make.height.width.mas_equalTo(downloadSize); + }]; + } else { + _downloadImage.frame = CGRectZero; + } + [self.progressView mas_remakeConstraints:^(MASConstraintMaker *make) { + make.leading.mas_equalTo(0); + make.top.mas_equalTo(0); + make.width.mas_equalTo(self.progressView.mm_w ?: 1); + make.height.mas_equalTo(self.fileContainer.mm_h); + }]; +} + +- (void)layoutSubviews { + [super layoutSubviews]; } #pragma mark - TUIMessageProgressManagerDelegate @@ -130,23 +204,21 @@ - (void)showProgressLoadingAnimation:(NSInteger)progress { self.progressView.hidden = NO; - self.progressView.frame = CGRectMake(0, 0, self.progressView.mm_w ?: 1, self.fileContainer.mm_h); NSLog(@"showProgressLodingAnimation:%ld", (long)progress); [UIView animateWithDuration:0.25 animations:^{ - self.progressView.mm_x = 0; - self.progressView.mm_y = 0; - self.progressView.mm_h = self.fileContainer.mm_h; - self.progressView.mm_w = self.fileContainer.mm_w * progress / 100.0; - } - completion:^(BOOL finished) { - if (progress == 0 || progress >= 100) { - self.progressView.hidden = YES; - [self.indicator stopAnimating]; - self.length.text = [self formatLength:self.fileData.length]; - self.downloadImage.hidden = YES; - } + [self.progressView mas_updateConstraints:^(MASConstraintMaker *make) { + make.width.mas_equalTo(self.fileContainer.mm_w * progress / 100.0); }]; + } + completion:^(BOOL finished) { + if (progress == 0 || progress >= 100) { + self.progressView.hidden = YES; + [self.indicator stopAnimating]; + self.length.text = [self formatLength:self.fileData.length]; + self.downloadImage.hidden = YES; + } + }]; self.length.text = [self formatLength:self.fileData.length]; } @@ -179,34 +251,6 @@ return str; } -- (void)layoutSubviews { - [super layoutSubviews]; - - CGSize containerSize = [self.class getContentSize:self.fileData]; - - _fileContainer.mm_width(containerSize.width - kScale390(32)).mm_height(48).mm_left(kScale390(16)).mm_top(8); - - CGFloat fileImageSize = 24; - _fileImage.mm_width(fileImageSize).mm_height(fileImageSize).mm_left(kScale390(12)).mm_top(12); - - CGFloat fileNameX = _fileImage.mm_maxX + kScale390(8); - _fileName.mm_width(_fileContainer.mm_w - fileNameX - kScale390(12)).mm_height(17).mm_left(fileNameX).mm_top(15); - - _length.mm_width(150).mm_height(14).mm_left(kScale390(22)).mm_top(_fileContainer.mm_maxY + 11); - - if (!self.fileData.isLocalExist && !self.fileData.isDownloading) { - CGFloat downloadSize = 16; - CGFloat downloadX = 0; - if (self.fileData.direction == MsgDirectionIncoming) { - downloadX = self.container.mm_maxX + kScale390(8); - } else { - downloadX = self.container.mm_x - kScale390(8) - downloadSize; - } - _downloadImage.frame = CGRectMake(downloadX, self.fileContainer.mm_y + _fileName.mm_y, downloadSize, downloadSize); - } else { - _downloadImage.frame = CGRectZero; - } -} - (UIView *)progressView { if (_progressView == nil) { diff --git a/iOS/TUIKit/TUIChat/UI_Minimalist/Cell/Chat/TUIImageCollectionCell_Minimalist.m b/iOS/TUIKit/TUIChat/UI_Minimalist/Cell/Chat/TUIImageCollectionCell_Minimalist.m index 3239f8ee2..bcf740b36 100644 --- a/iOS/TUIKit/TUIChat/UI_Minimalist/Cell/Chat/TUIImageCollectionCell_Minimalist.m +++ b/iOS/TUIKit/TUIChat/UI_Minimalist/Cell/Chat/TUIImageCollectionCell_Minimalist.m @@ -62,11 +62,22 @@ { [super fillWithData:data]; self.imageView.image = nil; - if (data.largeImage == nil) { + if (data.thumbImage == nil) { + [data downloadImage:TImage_Type_Thumb]; + } + if (data.thumbImage && data.largeImage == nil) { [data downloadImage:TImage_Type_Large]; } @weakify(self); + [[RACObserve(data, thumbImage) takeUntil:self.rac_prepareForReuseSignal] subscribeNext:^(UIImage *thumbImage) { + @strongify(self); + if (thumbImage) { + self.imageView.image = thumbImage; + } + }]; + + // largeImage [[RACObserve(data, largeImage) takeUntil:self.rac_prepareForReuseSignal] subscribeNext:^(UIImage *largeImage) { @strongify(self); if (largeImage) { diff --git a/iOS/TUIKit/TUIChat/UI_Minimalist/Cell/Chat/TUIImageMessageCell_Minimalist.m b/iOS/TUIKit/TUIChat/UI_Minimalist/Cell/Chat/TUIImageMessageCell_Minimalist.m index 8a0a206a5..7b1f26f4c 100644 --- a/iOS/TUIKit/TUIChat/UI_Minimalist/Cell/Chat/TUIImageMessageCell_Minimalist.m +++ b/iOS/TUIKit/TUIChat/UI_Minimalist/Cell/Chat/TUIImageMessageCell_Minimalist.m @@ -38,6 +38,8 @@ [self.container addSubview:_progress]; self.msgTimeLabel.textColor = RGB(255, 255, 255); + [self makeConstraints]; + } return self; } @@ -57,39 +59,95 @@ @strongify(self); if (thumbImage) { self.thumb.image = thumbImage; + // tell constraints they need updating + [self setNeedsUpdateConstraints]; + + // update constraints now so we can animate the change + [self updateConstraintsIfNeeded]; + + [self layoutIfNeeded]; } }]; if (data.direction == MsgDirectionIncoming) { [[[RACObserve(data, thumbProgress) takeUntil:self.rac_prepareForReuseSignal] distinctUntilChanged] subscribeNext:^(NSNumber *x) { - @strongify(self); - int progress = [x intValue]; - self.progress.text = [NSString stringWithFormat:@"%d%%", progress]; - self.progress.hidden = (progress >= 100 || progress == 0); + @strongify(self); + int progress = [x intValue]; + self.progress.text = [NSString stringWithFormat:@"%d%%", progress]; + self.progress.hidden = (progress >= 100 || progress == 0); + + // tell constraints they need updating + [self setNeedsUpdateConstraints]; + + // update constraints now so we can animate the change + [self updateConstraintsIfNeeded]; + + [self layoutIfNeeded]; }]; } } +- (void)makeConstraints { + [self.thumb mas_makeConstraints:^(MASConstraintMaker *make) { + make.height.mas_equalTo(self.container); + make.width.mas_equalTo(self.container); + make.top.mas_equalTo(self.container); + make.leading.mas_equalTo(self.container); + }]; + + [self.progress mas_makeConstraints:^(MASConstraintMaker *make) { + make.edges.mas_equalTo(self.container); + }]; +} -- (void)layoutSubviews { - [super layoutSubviews]; +// this is Apple's recommended place for adding/updating constraints +- (void)updateConstraints { + + [super updateConstraints]; CGFloat topMargin = 0; CGFloat height = self.container.mm_h; + + [self.thumb mas_remakeConstraints:^(MASConstraintMaker *make) { + make.height.mas_equalTo(height); + make.width.mas_equalTo(self.container.mas_width); + make.top.mas_equalTo(self.container).mas_offset(topMargin); + make.leading.mas_equalTo(self.container); + }]; + + [self.progress mas_remakeConstraints:^(MASConstraintMaker *make) { + make.edges.mas_equalTo(self.container); + }]; + + [self.msgTimeLabel mas_makeConstraints:^(MASConstraintMaker *make) { + make.width.mas_equalTo(38); + make.height.mas_equalTo(self.messageData.msgStatusSize.height); + make.bottom.mas_equalTo(self.container).mas_offset(-kScale390(9)); + make.trailing.mas_equalTo(self.container).mas_offset(-kScale390(8)); + }]; + + [self.msgStatusView mas_makeConstraints:^(MASConstraintMaker *make) { + make.width.mas_equalTo(16); + make.height.mas_equalTo(self.messageData.msgStatusSize.height); + make.bottom.mas_equalTo(self.msgTimeLabel); + make.trailing.mas_equalTo(self.msgTimeLabel.mas_leading); + }]; - if (self.messageData.messageModifyReactsSize.height > 0) { - topMargin = 10; - height = (self.container.mm_h - self.messageData.messageModifyReactsSize.height - topMargin); - } - - _thumb.mm_height(height).mm_left(0).mm_top(topMargin).mm_width(self.container.mm_w); - - _thumb.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight; - - _progress.mm_fill(); - _progress.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight; - - self.msgStatusView.frame = CGRectOffset(self.msgStatusView.frame, kScale390(8), 0); - self.msgTimeLabel.frame = CGRectOffset(self.msgTimeLabel.frame, kScale390(8), 0); + [self.selectedView mas_remakeConstraints:^(MASConstraintMaker *make) { + make.edges.mas_equalTo(self.contentView); + }]; + [self.selectedIcon mas_remakeConstraints:^(MASConstraintMaker *make) { + make.leading.mas_equalTo(self.contentView.mas_leading).mas_offset(3); + make.top.mas_equalTo(self.avatarView.mas_centerY).mas_offset(-10); + if (self.messageData.showCheckBox) { + make.width.mas_equalTo(20); + make.height.mas_equalTo(20); + } else { + make.size.mas_equalTo(CGSizeZero); + } + }]; +} +- (void)layoutSubviews { + [super layoutSubviews]; } - (void)highlightWhenMatchKeyword:(NSString *)keyword { diff --git a/iOS/TUIKit/TUIChat/UI_Minimalist/Cell/Chat/TUIJoinGroupMessageCell_Minimalist.m b/iOS/TUIKit/TUIChat/UI_Minimalist/Cell/Chat/TUIJoinGroupMessageCell_Minimalist.m index 73cfc9d6a..ca115ba5d 100644 --- a/iOS/TUIKit/TUIChat/UI_Minimalist/Cell/Chat/TUIJoinGroupMessageCell_Minimalist.m +++ b/iOS/TUIKit/TUIChat/UI_Minimalist/Cell/Chat/TUIJoinGroupMessageCell_Minimalist.m @@ -62,10 +62,29 @@ [self setNeedsLayout]; } ++ (BOOL)requiresConstraintBasedLayout { + return YES; +} + +// this is Apple's recommended place for adding/updating constraints +- (void)updateConstraints { + + [super updateConstraints]; + + [self.container mas_remakeConstraints:^(MASConstraintMaker *make) { + make.center.mas_equalTo(self.contentView); + make.size.mas_equalTo(self.contentView); + }]; + + if(self.textView.superview) { + [self.textView mas_remakeConstraints:^(MASConstraintMaker *make) { + make.center.mas_equalTo(self.container); + make.size.mas_equalTo(self.contentView); + }]; + } +} - (void)layoutSubviews { [super layoutSubviews]; - self.container.tui_mm_center(); - self.textView.mm_fill(); } - (void)onSelectUserName:(NSInteger)index { diff --git a/iOS/TUIKit/TUIChat/UI_Minimalist/Cell/Chat/TUIMergeMessageCell_Minimalist.h b/iOS/TUIKit/TUIChat/UI_Minimalist/Cell/Chat/TUIMergeMessageCell_Minimalist.h index ad90950ea..728c77836 100644 --- a/iOS/TUIKit/TUIChat/UI_Minimalist/Cell/Chat/TUIMergeMessageCell_Minimalist.h +++ b/iOS/TUIKit/TUIChat/UI_Minimalist/Cell/Chat/TUIMergeMessageCell_Minimalist.h @@ -31,11 +31,6 @@ NS_ASSUME_NONNULL_BEGIN */ @property(nonatomic, strong) UILabel *relayTitleLabel; -/** - * 转发消息的摘要信息 abstract - * Abstract of merged-forward message - */ -@property(nonatomic, strong) UILabel *abstractLabel; /** * 水平分割线 diff --git a/iOS/TUIKit/TUIChat/UI_Minimalist/Cell/Chat/TUIMergeMessageCell_Minimalist.m b/iOS/TUIKit/TUIChat/UI_Minimalist/Cell/Chat/TUIMergeMessageCell_Minimalist.m index 51b1bc879..3a0701990 100644 --- a/iOS/TUIKit/TUIChat/UI_Minimalist/Cell/Chat/TUIMergeMessageCell_Minimalist.m +++ b/iOS/TUIKit/TUIChat/UI_Minimalist/Cell/Chat/TUIMergeMessageCell_Minimalist.m @@ -18,6 +18,117 @@ #endif #endif +@interface TUIMergeMessageDetailRow_Minimalist : UIView +@property(nonatomic, strong) UILabel *abstractName; +@property(nonatomic, strong) UILabel *abstractBreak; +@property(nonatomic, strong) UILabel *abstractDetail; +- (void)fillWithData:(NSAttributedString *)name detailContent:(NSAttributedString *)detailContent; +@end +@implementation TUIMergeMessageDetailRow_Minimalist + +- (instancetype)init { + self = [super init]; + if(self){ + [self setupview]; + } + return self; +} +- (void)setupview { + [self addSubview:self.abstractName]; + [self addSubview:self.abstractBreak]; + [self addSubview:self.abstractDetail]; +} + +- (UILabel *)abstractName { + if(!_abstractName) { + _abstractName = [[UILabel alloc] init]; + _abstractName.numberOfLines = 1; + _abstractName.font = [UIFont systemFontOfSize:12.0]; + _abstractName.textColor = [UIColor colorWithRed:187 / 255.0 green:187 / 255.0 blue:187 / 255.0 alpha:1 / 1.0]; + _abstractName.textAlignment = isRTL()? NSTextAlignmentRight:NSTextAlignmentLeft; + } + return _abstractName; +} +- (UILabel *)abstractBreak { + if(!_abstractBreak) { + _abstractBreak = [[UILabel alloc] init]; + _abstractBreak.text = @":"; + _abstractBreak.font = [UIFont systemFontOfSize:12.0]; + _abstractBreak.textColor = TUIChatDynamicColor(@"chat_merge_message_content_color", @"#d5d5d5"); + } + return _abstractBreak; +} +- (UILabel *)abstractDetail { + if(!_abstractDetail) { + _abstractDetail = [[UILabel alloc] init]; + _abstractDetail.numberOfLines = 0; + _abstractName.font = [UIFont systemFontOfSize:12.0]; + _abstractDetail.textColor = TUIChatDynamicColor(@"chat_merge_message_content_color", @"#d5d5d5"); + _abstractDetail.textAlignment = isRTL()? NSTextAlignmentRight:NSTextAlignmentLeft; + } + return _abstractDetail; +} + ++ (BOOL)requiresConstraintBasedLayout { + return YES; +} + +// this is Apple's recommended place for adding/updating constraints +- (void)updateConstraints { + + [super updateConstraints]; + [self.abstractName sizeToFit]; + [self.abstractName mas_remakeConstraints:^(MASConstraintMaker *make) { + make.leading.mas_equalTo(0); + make.top.mas_equalTo(0); + make.trailing.mas_lessThanOrEqualTo(self.abstractBreak.mas_leading); + make.width.mas_lessThanOrEqualTo(self.mas_width).multipliedBy(0.33); + }]; + + [self.abstractBreak sizeToFit]; + [self.abstractBreak mas_remakeConstraints:^(MASConstraintMaker *make) { + make.leading.mas_equalTo(self.abstractName.mas_trailing); + make.top.mas_equalTo(self.abstractName); + make.width.mas_offset(self.abstractBreak.frame.size.width); + make.height.mas_offset(self.abstractBreak.frame.size.height); + }]; + + [self.abstractDetail sizeToFit]; + [self.abstractDetail mas_remakeConstraints:^(MASConstraintMaker *make) { + make.leading.mas_equalTo(self.abstractBreak.mas_trailing); + make.top.mas_equalTo(0); + make.trailing.mas_lessThanOrEqualTo(self.mas_trailing).mas_offset(-15); + make.bottom.mas_equalTo(self); + }]; +} +- (void)fillWithData:(NSAttributedString *)name detailContent:(NSAttributedString *)detailContent { + + self.abstractName.text = name.string; + self.abstractDetail.attributedText = detailContent; + // tell constraints they need updating + [self setNeedsUpdateConstraints]; + + // update constraints now so we can animate the change + [self updateConstraintsIfNeeded]; + + [self layoutIfNeeded]; + + +} +- (void)layoutSubviews { + [super layoutSubviews]; +} + + +@end +@interface TUIMergeMessageCell_Minimalist () + +@property(nonatomic, strong) CAShapeLayer *borderLayer; +@property(nonatomic, strong) TUIMergeMessageDetailRow_Minimalist *contentRowView1; +@property(nonatomic, strong) TUIMergeMessageDetailRow_Minimalist *contentRowView2; +@property(nonatomic, strong) TUIMergeMessageDetailRow_Minimalist *contentRowView3; + +@end @implementation TUIMergeMessageCell_Minimalist - (instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier { @@ -36,12 +147,12 @@ _relayTitleLabel.textColor = RGBA(0, 0, 0, 0.8); [self.container addSubview:_relayTitleLabel]; - _abstractLabel = [[UILabel alloc] initWithFrame:CGRectZero]; - _abstractLabel.text = @"Me: ******"; - _abstractLabel.font = [UIFont systemFontOfSize:12]; - _abstractLabel.numberOfLines = 0; - _abstractLabel.textColor = RGBA(153, 153, 153, 1); - [self.container addSubview:_abstractLabel]; + _contentRowView1 = [[TUIMergeMessageDetailRow_Minimalist alloc] init]; + [self.container addSubview:_contentRowView1]; + _contentRowView2 = [[TUIMergeMessageDetailRow_Minimalist alloc] init]; + [self.container addSubview:_contentRowView2]; + _contentRowView3 = [[TUIMergeMessageDetailRow_Minimalist alloc] init]; + [self.container addSubview:_contentRowView3]; _separtorView = [[UIView alloc] init]; _separtorView.backgroundColor = TIMCommonDynamicColor(@"separator_color", @"#DBDBDB"); @@ -54,19 +165,111 @@ [self.container addSubview:_bottomTipsLabel]; } ++ (BOOL)requiresConstraintBasedLayout { + return YES; +} + +// this is Apple's recommended place for adding/updating constraints +- (void)updateConstraints { + + [super updateConstraints]; + + [self.relayTitleLabel sizeToFit]; + [self.relayTitleLabel mas_remakeConstraints:^(MASConstraintMaker *make) { + make.leading.mas_equalTo(self.container).mas_offset(10); + make.width.mas_lessThanOrEqualTo(self.container); + make.height.mas_equalTo(self.relayTitleLabel.font.lineHeight); + make.top.mas_equalTo(self.container).mas_offset(10); + }]; + + [self.contentRowView1 mas_remakeConstraints:^(MASConstraintMaker *make) { + make.leading.mas_equalTo(self.relayTitleLabel); + make.top.mas_equalTo(self.relayTitleLabel.mas_bottom).mas_offset(3); + make.trailing.mas_equalTo(self.container); + make.height.mas_equalTo(self.relayData.abstractRow1Size.height); + }]; + + [self.contentRowView2 mas_remakeConstraints:^(MASConstraintMaker *make) { + make.leading.mas_equalTo(self.relayTitleLabel); + make.top.mas_equalTo(self.contentRowView1.mas_bottom).mas_offset(3); + make.trailing.mas_equalTo(self.container); + make.height.mas_equalTo(self.relayData.abstractRow2Size.height); + }]; + + [self.contentRowView3 mas_remakeConstraints:^(MASConstraintMaker *make) { + make.leading.mas_equalTo(self.relayTitleLabel); + make.top.mas_equalTo(self.contentRowView2.mas_bottom).mas_offset(3); + make.trailing.mas_equalTo(self.container); + make.height.mas_equalTo(self.relayData.abstractRow3Size.height); + }]; + + UIView *lastView = self.contentRowView1; + int count = self.relayData.abstractSendDetailList.count; + if (count == 3) { + lastView = self.contentRowView3; + } + else if (count == 2){ + lastView = self.contentRowView2; + } + [self.separtorView mas_remakeConstraints:^(MASConstraintMaker *make) { + make.leading.mas_equalTo(self.container).mas_offset(10); + make.trailing.mas_equalTo(self.container).mas_offset(-10); + make.top.mas_equalTo(lastView.mas_bottom).mas_offset(3); + make.height.mas_equalTo(1); + }]; + + [self.bottomTipsLabel mas_remakeConstraints:^(MASConstraintMaker *make) { + make.leading.mas_equalTo(self.contentRowView1); + make.top.mas_equalTo(self.separtorView.mas_bottom).mas_offset(5); + make.width.mas_lessThanOrEqualTo(self.container); + make.height.mas_equalTo(self.bottomTipsLabel.font.lineHeight); + }]; + +} - (void)layoutSubviews { [super layoutSubviews]; - self.relayTitleLabel.mm_sizeToFit().mm_top(10).mm_left(10).mm_flexToRight(10); - self.abstractLabel.frame = CGRectMake(10, 3 + self.relayTitleLabel.mm_maxY, self.relayData.abstractSize.width, self.relayData.abstractSize.height); - self.separtorView.frame = CGRectMake(10, self.abstractLabel.mm_maxY, self.container.mm_w - 20, 1); - self.bottomTipsLabel.frame = CGRectMake(10, CGRectGetMaxY(self.separtorView.frame) + 5, self.abstractLabel.mm_w, 20); } - (void)fillWithData:(TUIMergeMessageCellData *)data { [super fillWithData:data]; self.relayData = data; self.relayTitleLabel.text = data.title; - self.abstractLabel.attributedText = [self.relayData abstractAttributedString]; + int count = self.relayData.abstractSendDetailList.count; + switch (count) { + case 1: + [self.contentRowView1 fillWithData:self.relayData.abstractSendDetailList[0][@"sender"] detailContent:self.relayData.abstractSendDetailList[0][@"detail"]]; + self.contentRowView1.hidden = NO; + self.contentRowView2.hidden = YES; + self.contentRowView3.hidden = YES; + break; + case 2: + [self.contentRowView1 fillWithData:self.relayData.abstractSendDetailList[0][@"sender"] detailContent:self.relayData.abstractSendDetailList[0][@"detail"]]; + [self.contentRowView2 fillWithData:self.relayData.abstractSendDetailList[1][@"sender"] detailContent:self.relayData.abstractSendDetailList[1][@"detail"]]; + + self.contentRowView1.hidden = NO; + self.contentRowView2.hidden = NO; + self.contentRowView3.hidden = YES; + break; + case 3: + + [self.contentRowView1 fillWithData:self.relayData.abstractSendDetailList[0][@"sender"] detailContent:self.relayData.abstractSendDetailList[0][@"detail"]]; + [self.contentRowView2 fillWithData:self.relayData.abstractSendDetailList[1][@"sender"] detailContent:self.relayData.abstractSendDetailList[1][@"detail"]]; + [self.contentRowView3 fillWithData:self.relayData.abstractSendDetailList[2][@"sender"] detailContent:self.relayData.abstractSendDetailList[2][@"detail"]]; + self.contentRowView1.hidden = NO; + self.contentRowView2.hidden = NO; + self.contentRowView3.hidden = NO; + break; + default: + break; + } + // tell constraints they need updating + [self setNeedsUpdateConstraints]; + + // update constraints now so we can animate the change + [self updateConstraintsIfNeeded]; + + [self layoutIfNeeded]; + } @@ -75,19 +278,38 @@ NSAssert([data isKindOfClass:TUIMergeMessageCellData.class], @"data must be kind of TUIMergeMessageCellData"); TUIMergeMessageCellData *mergeCellData = (TUIMergeMessageCellData *)data; + mergeCellData.abstractRow1Size = [self.class caculate:mergeCellData index:0]; + mergeCellData.abstractRow2Size = [self.class caculate:mergeCellData index:1]; + mergeCellData.abstractRow3Size = [self.class caculate:mergeCellData index:2]; + CGRect rect = [[mergeCellData abstractAttributedString] boundingRectWithSize:CGSizeMake(200 - 20, MAXFLOAT) - options:NSStringDrawingUsesLineFragmentOrigin | NSStringDrawingUsesFontLeading - context:nil]; + options:NSStringDrawingUsesLineFragmentOrigin | NSStringDrawingUsesFontLeading + context:nil]; CGSize size = CGSizeMake(CGFLOAT_CEIL(rect.size.width), CGFLOAT_CEIL(rect.size.height) - 10); mergeCellData.abstractSize = size; - CGFloat height = size.height; - if (height > TRelayMessageCell_Text_Height_Max) { - mergeCellData.abstractSize = CGSizeMake(size.width, size.height - (height - TRelayMessageCell_Text_Height_Max)); - height = TRelayMessageCell_Text_Height_Max; - } + CGFloat height = mergeCellData.abstractRow1Size.height + mergeCellData.abstractRow2Size.height + mergeCellData.abstractRow3Size.height; UIFont *titleFont = [UIFont systemFontOfSize:16]; - height = (10 + titleFont.lineHeight + 3) + height + 1 + 5 + 20 + 5; + height = (10 + titleFont.lineHeight + 3) + height + 1 + 5 + 20 + 5 + 3; return CGSizeMake(kScale390(250), height + mergeCellData.msgStatusSize.height); } ++ (CGSize)caculate:(TUIMergeMessageCellData *)data index:(NSInteger)index { + + NSArray *abstractSendDetailList = data.abstractSendDetailList; + if (abstractSendDetailList.count <= index){ + return CGSizeZero; + } + NSAttributedString * str = abstractSendDetailList[index][@"sender"]; + NSMutableAttributedString *abstr = [[NSMutableAttributedString alloc] initWithAttributedString:str]; + [abstr appendAttributedString:[[NSAttributedString alloc] initWithString:@":"]]; + [abstr appendAttributedString:abstractSendDetailList[index][@"detail"]]; + + CGRect rect = [abstr boundingRectWithSize:CGSizeMake(200 - 20, MAXFLOAT) + options:NSStringDrawingUsesLineFragmentOrigin | NSStringDrawingUsesFontLeading + context:nil]; + CGSize size = CGSizeMake(200, MIN(TRelayMessageCell_Text_Height_Max/3.0, CGFLOAT_CEIL(rect.size.height))); + + return size; +} + @end diff --git a/iOS/TUIKit/TUIChat/UI_Minimalist/Cell/Chat/TUIVideoMessageCell_Minimalist.m b/iOS/TUIKit/TUIChat/UI_Minimalist/Cell/Chat/TUIVideoMessageCell_Minimalist.m index a0fd59238..41fed5851 100644 --- a/iOS/TUIKit/TUIChat/UI_Minimalist/Cell/Chat/TUIVideoMessageCell_Minimalist.m +++ b/iOS/TUIKit/TUIChat/UI_Minimalist/Cell/Chat/TUIVideoMessageCell_Minimalist.m @@ -86,6 +86,14 @@ if (data.thumbImage) { self.thumb.image = data.thumbImage; } + // tell constraints they need updating + [self setNeedsUpdateConstraints]; + + // update constraints now so we can animate the change + [self updateConstraintsIfNeeded]; + + [self layoutIfNeeded]; + return; } else { @@ -114,26 +122,58 @@ self.play.hidden = !self.progress.hidden; }]; } + // tell constraints they need updating + [self setNeedsUpdateConstraints]; + + // update constraints now so we can animate the change + [self updateConstraintsIfNeeded]; + + [self layoutIfNeeded]; + +} ++ (BOOL)requiresConstraintBasedLayout { + return YES; +} + +// this is Apple's recommended place for adding/updating constraints +- (void)updateConstraints { + + [super updateConstraints]; + + [self.thumb mas_remakeConstraints:^(MASConstraintMaker *make) { + make.height.mas_equalTo(self.container.mas_height); + make.width.mas_equalTo(self.container); + make.leading.mas_equalTo(self.container.mas_leading); + make.top.mas_equalTo(self.container); + }]; + + [self.play mas_remakeConstraints:^(MASConstraintMaker *make) { + make.size.mas_equalTo(TVideoMessageCell_Play_Size); + make.center.mas_equalTo(self.thumb); + }]; + + [self.msgTimeLabel mas_makeConstraints:^(MASConstraintMaker *make) { + make.width.mas_equalTo(38); + make.height.mas_equalTo(self.messageData.msgStatusSize.height); + make.bottom.mas_equalTo(self.container).mas_offset(-kScale390(9)); + make.trailing.mas_equalTo(self.container).mas_offset(-kScale390(8)); + }]; + + [self.msgStatusView mas_makeConstraints:^(MASConstraintMaker *make) { + make.width.mas_equalTo(16); + make.height.mas_equalTo(self.messageData.msgStatusSize.height); + make.bottom.mas_equalTo(self.msgTimeLabel); + make.trailing.mas_equalTo(self.msgTimeLabel.mas_leading); + }]; + + [self.animateCircleView mas_remakeConstraints:^(MASConstraintMaker *make) { + make.center.mas_equalTo(self.thumb); + make.size.mas_equalTo(CGSizeMake(kScale390(40), kScale390(40))); + }]; } - (void)layoutSubviews { [super layoutSubviews]; - - CGFloat topMargin = 0; - CGFloat height = self.container.mm_h; - - if (self.messageData.messageModifyReactsSize.height > 0) { - topMargin = 10; - height = (self.container.mm_h - self.messageData.messageModifyReactsSize.height - topMargin); - } - - _thumb.mm_height(height).mm_left(0).mm_top(topMargin).mm_width(self.container.mm_w); - - _play.mm_width(TVideoMessageCell_Play_Size.width).mm_height(TVideoMessageCell_Play_Size.height).tui_mm_center(); - - self.msgStatusView.frame = CGRectOffset(self.msgStatusView.frame, kScale390(8), 0); - self.msgTimeLabel.frame = CGRectOffset(self.msgTimeLabel.frame, kScale390(8), 0); - self.animateCircleView.tui_mm_center(); } - (void)highlightWhenMatchKeyword:(NSString *)keyword { diff --git a/iOS/TUIKit/TUIChat/UI_Minimalist/Cell/Chat/TUIVoiceMessageCell_Minimalist.m b/iOS/TUIKit/TUIChat/UI_Minimalist/Cell/Chat/TUIVoiceMessageCell_Minimalist.m index 9c3763f0a..4a8e14309 100644 --- a/iOS/TUIKit/TUIChat/UI_Minimalist/Cell/Chat/TUIVoiceMessageCell_Minimalist.m +++ b/iOS/TUIKit/TUIChat/UI_Minimalist/Cell/Chat/TUIVoiceMessageCell_Minimalist.m @@ -11,7 +11,7 @@ #import @interface TUIVoiceMessageCell_Minimalist () -@property(nonatomic, assign) CGRect animationCoverFrame; + @end @implementation TUIVoiceMessageCell_Minimalist @@ -33,7 +33,7 @@ _duration = [[UILabel alloc] init]; _duration.font = [UIFont boldSystemFontOfSize:14]; - _duration.textAlignment = NSTextAlignmentRight; + _duration.rtlAlignment = TUITextRTLAlignmentTrailing; [self.bubbleView addSubview:_duration]; _voiceReadPoint = [[UIImageView alloc] init]; @@ -76,6 +76,59 @@ @strongify(self); self.duration.text = [NSString stringWithFormat:@"%d:%.2d", (int)time / 60, (int)time % 60]; }; + + // tell constraints they need updating + [self setNeedsUpdateConstraints]; + + // update constraints now so we can animate the change + [self updateConstraintsIfNeeded]; + + [self layoutIfNeeded]; +} + ++ (BOOL)requiresConstraintBasedLayout { + return YES; +} + +// this is Apple's recommended place for adding/updating constraints +- (void)updateConstraints { + + [super updateConstraints]; + + [self.voicePlay mas_remakeConstraints:^(MASConstraintMaker *make) { + make.top.mas_equalTo(12); + make.leading.mas_equalTo(kScale390(16)); + make.width.mas_equalTo(11); + make.height.mas_equalTo(13); + }]; + + CGFloat animationStartX = kScale390(35); + for (int i = 0; i < self.voiceAnimations.count; ++i) { + UIImageView *animation = self.voiceAnimations[i]; + [animation mas_remakeConstraints:^(MASConstraintMaker *make) { + make.leading.mas_equalTo(self.bubbleView).mas_offset(animationStartX + kScale390(25) * i); + make.top.mas_equalTo(self.bubbleView).mas_offset(self.voiceData.voiceTop); + make.width.height.mas_equalTo(_voiceData.voiceHeight); + }]; + } + + [self.duration mas_remakeConstraints:^(MASConstraintMaker *make) { + make.width.mas_greaterThanOrEqualTo(kScale390(34)); + make.height.mas_greaterThanOrEqualTo(17); + make.top.mas_equalTo(self.voiceData.voiceTop + 2); + make.trailing.mas_equalTo(self.container).mas_offset(- kScale390(14)); + }]; + + if (self.voiceData.direction == MsgDirectionOutgoing) { + self.voiceReadPoint.hidden = YES; + } + else { + [self.voiceReadPoint mas_remakeConstraints:^(MASConstraintMaker *make) { + make.top.mas_equalTo(self.bubbleView); + make.leading.mas_equalTo(self.bubbleView.mas_trailing).mas_offset(1); + make.size.mas_equalTo(CGSizeMake(5, 5)); + }]; + } } - (void)startAnimating { @@ -88,25 +141,6 @@ - (void)layoutSubviews { [super layoutSubviews]; - - _voicePlay.frame = CGRectMake(kScale390(16), 12, 11, 13); - - CGFloat animationWidth = 0; - CGFloat animationStartX = kScale390(35); - for (int i = 0; i < self.voiceAnimations.count; ++i) { - UIImageView *animation = self.voiceAnimations[i]; - animation.frame = CGRectMake(animationStartX + kScale390(25) * i, self.voiceData.voiceTop, self.voiceData.voiceHeight, self.voiceData.voiceHeight); - animationWidth = animation.mm_maxX - animationStartX; - } - _animationCoverFrame = CGRectMake(animationStartX, self.voiceData.voiceTop, animationWidth, self.voiceData.voiceHeight); - - _duration.mm_width(kScale390(34)).mm_height(17).mm_top(self.voiceData.voiceTop + 2).mm_flexToRight(kScale390(14)); - - if (self.voiceData.direction == MsgDirectionOutgoing) { - self.voiceReadPoint.hidden = YES; - } else { - self.voiceReadPoint.mm_top(0).mm_right(-self.voiceReadPoint.mm_w); - } } #pragma mark - TUIMessageCellProtocol diff --git a/iOS/TUIKit/TUIChat/UI_Minimalist/Cell/Custom/TUIEvaluationCell_Minimalist.m b/iOS/TUIKit/TUIChat/UI_Minimalist/Cell/Custom/TUIEvaluationCell_Minimalist.m index 8d46b8180..847fc1b20 100644 --- a/iOS/TUIKit/TUIChat/UI_Minimalist/Cell/Custom/TUIEvaluationCell_Minimalist.m +++ b/iOS/TUIKit/TUIChat/UI_Minimalist/Cell/Custom/TUIEvaluationCell_Minimalist.m @@ -49,23 +49,51 @@ UIImageView *starView = [self.starImageArray objectAtIndex:i]; starView.hidden = (i >= data.score); } + // tell constraints they need updating + [self setNeedsUpdateConstraints]; + + // update constraints now so we can animate the change + [self updateConstraintsIfNeeded]; + + [self layoutIfNeeded]; } -- (void)layoutSubviews { - [super layoutSubviews]; - - self.titleLabel.mm_top(10).mm_left(10).mm_width(225).mm_height(18); ++ (BOOL)requiresConstraintBasedLayout { + return YES; +} +// this is Apple's recommended place for adding/updating constraints +- (void)updateConstraints { + + [super updateConstraints]; + + [self.titleLabel mas_remakeConstraints:^(MASConstraintMaker *make) { + make.top.mas_equalTo(10); + make.leading.mas_equalTo(10); + make.width.mas_equalTo(225); + make.height.mas_equalTo(18); + }]; + UIImageView *leftView = nil; for (UIImageView *starView in self.starImageArray) { if (leftView == nil) { - starView.mm_left(10).mm_top(self.titleLabel.mm_y + self.titleLabel.mm_h + 6).mm_width(30).mm_height(30); + [starView mas_remakeConstraints:^(MASConstraintMaker *make) { + make.leading.mas_equalTo(10); + make.top.mas_equalTo(self.titleLabel.mas_bottom).mas_offset(6); + make.width.mas_equalTo(30); + make.height.mas_equalTo(30); + }]; } else { - starView.mm_left(leftView.mm_x + leftView.mm_w).mm_top(self.titleLabel.mm_y + self.titleLabel.mm_h + 6).mm_width(30).mm_height(30); + [starView mas_remakeConstraints:^(MASConstraintMaker *make) { + make.leading.mas_equalTo(leftView.mas_trailing); + make.top.mas_equalTo(self.titleLabel.mas_bottom).mas_offset(6); + make.width.mas_equalTo(30); + make.height.mas_equalTo(30); + }]; } leftView = starView; } - + UIImageView *starView = self.starImageArray.firstObject; self.commentLabel.hidden = self.commentLabel.text.length == 0; @@ -75,8 +103,25 @@ attributes:@{NSFontAttributeName : [UIFont systemFontOfSize:15]} context:nil]; CGSize size = CGSizeMake(225, ceilf(rect.size.height)); - self.commentLabel.mm_width(size.width).mm_height(size.height).mm_left(10).mm_top(starView.mm_y + starView.mm_h + 6); + [self.commentLabel mas_remakeConstraints:^(MASConstraintMaker *make) { + make.top.mas_equalTo(starView.mas_bottom).mas_offset(6); + make.leading.mas_equalTo(10); + make.width.mas_equalTo(size.width); + make.height.mas_equalTo(size.height); + }]; } + + // tell constraints they need updating + [self setNeedsUpdateConstraints]; + + // update constraints now so we can animate the change + [self updateConstraintsIfNeeded]; + + [self layoutIfNeeded]; + +} +- (void)layoutSubviews { + [super layoutSubviews]; } - (NSMutableArray *)starImageArray { diff --git a/iOS/TUIKit/TUIChat/UI_Minimalist/Cell/Custom/TUILinkCell_Minimalist.m b/iOS/TUIKit/TUIChat/UI_Minimalist/Cell/Custom/TUILinkCell_Minimalist.m index d46ac0352..f2596d314 100644 --- a/iOS/TUIKit/TUIChat/UI_Minimalist/Cell/Custom/TUILinkCell_Minimalist.m +++ b/iOS/TUIKit/TUIChat/UI_Minimalist/Cell/Custom/TUILinkCell_Minimalist.m @@ -38,17 +38,45 @@ [super fillWithData:data]; self.customData = data; self.myTextLabel.text = data.text; + + // tell constraints they need updating + [self setNeedsUpdateConstraints]; + + // update constraints now so we can animate the change + [self updateConstraintsIfNeeded]; + + [self layoutIfNeeded]; + } -- (void)layoutSubviews { - [super layoutSubviews]; ++ (BOOL)requiresConstraintBasedLayout { + return YES; +} +// this is Apple's recommended place for adding/updating constraints +- (void)updateConstraints { + + [super updateConstraints]; CGRect rect = [self.myTextLabel.text boundingRectWithSize:CGSizeMake(245, MAXFLOAT) options:NSStringDrawingUsesLineFragmentOrigin | NSStringDrawingUsesFontLeading attributes:@{NSFontAttributeName : [UIFont systemFontOfSize:15]} context:nil]; - self.myTextLabel.mm_top(10).mm_left(10).mm_width(245).mm_height(rect.size.height); - self.myLinkLabel.mm_sizeToFit().mm_left(10).mm_top(self.myTextLabel.mm_y + self.myTextLabel.mm_h + 15); + [self.myTextLabel mas_remakeConstraints:^(MASConstraintMaker *make) { + make.top.mas_equalTo(10); + make.leading.mas_equalTo(10); + make.width.mas_equalTo(245); + make.height.mas_equalTo(rect.size.height); + }]; + [self.myLinkLabel sizeToFit]; + [self.myLinkLabel mas_remakeConstraints:^(MASConstraintMaker *make) { + make.top.mas_equalTo(self.myTextLabel.mas_bottom).mas_offset(15); + make.leading.mas_equalTo(10); + make.width.mas_equalTo(self.myLinkLabel.frame.size.width); + make.height.mas_equalTo(self.myLinkLabel.frame.size.height); + }]; +} +- (void)layoutSubviews { + [super layoutSubviews]; } #pragma mark - TUIMessageCellProtocol diff --git a/iOS/TUIKit/TUIChat/UI_Minimalist/Cell/Custom/TUIOrderCell_Minimalist.m b/iOS/TUIKit/TUIChat/UI_Minimalist/Cell/Custom/TUIOrderCell_Minimalist.m index 5800113d4..656c2c76b 100644 --- a/iOS/TUIKit/TUIChat/UI_Minimalist/Cell/Custom/TUIOrderCell_Minimalist.m +++ b/iOS/TUIKit/TUIChat/UI_Minimalist/Cell/Custom/TUIOrderCell_Minimalist.m @@ -54,15 +54,54 @@ } else { [self.iconView setImage:[UIImage sd_imageWithData:[NSData dataWithContentsOfURL:[NSURL URLWithString:data.imageUrl]]]]; } + // tell constraints they need updating + [self setNeedsUpdateConstraints]; + + // update constraints now so we can animate the change + [self updateConstraintsIfNeeded]; + + [self layoutIfNeeded]; +} + ++ (BOOL)requiresConstraintBasedLayout { + return YES; +} + +// this is Apple's recommended place for adding/updating constraints +- (void)updateConstraints { + + [super updateConstraints]; + + [self.iconView mas_remakeConstraints:^(MASConstraintMaker *make) { + make.top.mas_equalTo(10); + make.leading.mas_equalTo(12); + make.width.mas_equalTo(60); + make.height.mas_equalTo(60); + }]; + [self.titleLabel mas_remakeConstraints:^(MASConstraintMaker *make) { + make.top.mas_equalTo(10); + make.leading.mas_equalTo(80); + make.width.mas_equalTo(150); + make.height.mas_equalTo(17); + }]; + + [self.descLabel mas_remakeConstraints:^(MASConstraintMaker *make) { + make.top.mas_equalTo(30); + make.leading.mas_equalTo(80); + make.width.mas_equalTo(150); + make.height.mas_equalTo(17); + }]; + + [self.priceLabel mas_remakeConstraints:^(MASConstraintMaker *make) { + make.top.mas_equalTo(49); + make.leading.mas_equalTo(80); + make.width.mas_equalTo(150); + make.height.mas_equalTo(25); + }]; } - (void)layoutSubviews { [super layoutSubviews]; - - self.iconView.mm_top(10).mm_left(12).mm_width(60).mm_height(60); - self.titleLabel.mm_top(10).mm_left(80).mm_width(150).mm_height(17); - self.descLabel.mm_top(30).mm_left(80).mm_width(150).mm_height(17); - self.priceLabel.mm_top(49).mm_left(80).mm_width(150).mm_height(25); } #pragma mark - TUIMessageCellProtocol diff --git a/iOS/TUIKit/TUIChat/UI_Minimalist/Cell/Reply/TUIImageReplyQuoteView_Minimalist.m b/iOS/TUIKit/TUIChat/UI_Minimalist/Cell/Reply/TUIImageReplyQuoteView_Minimalist.m index 970949681..44c143d63 100644 --- a/iOS/TUIKit/TUIChat/UI_Minimalist/Cell/Reply/TUIImageReplyQuoteView_Minimalist.m +++ b/iOS/TUIKit/TUIChat/UI_Minimalist/Cell/Reply/TUIImageReplyQuoteView_Minimalist.m @@ -31,13 +31,36 @@ if (myData.image == nil) { [myData downloadImage]; } - self.imageView.frame = CGRectMake(0, 0, myData.imageSize.width, myData.imageSize.height); + // tell constraints they need updating + [self setNeedsUpdateConstraints]; + + // update constraints now so we can animate the change + [self updateConstraintsIfNeeded]; + + [self layoutIfNeeded]; + +} ++ (BOOL)requiresConstraintBasedLayout { + return YES; +} +// this is Apple's recommended place for adding/updating constraints +- (void)updateConstraints { + + [super updateConstraints]; + TUIImageReplyQuoteViewData *myData = (TUIImageReplyQuoteViewData *)self.data; + + [self.imageView mas_remakeConstraints:^(MASConstraintMaker *make) { + make.leading.mas_equalTo(self); + make.top.mas_equalTo(self); + make.size.mas_equalTo(myData.imageSize); + }]; + } - (void)reset { [super reset]; self.imageView.image = nil; - self.imageView.frame = CGRectMake(0, 0, 60, 60); + self.imageView.frame = CGRectMake(self.imageView.frame.origin.x, self.imageView.frame.origin.y, 60, 60); } @end diff --git a/iOS/TUIKit/TUIChat/UI_Minimalist/Cell/Reply/TUIMergeReplyQuoteView_Minimalist.m b/iOS/TUIKit/TUIChat/UI_Minimalist/Cell/Reply/TUIMergeReplyQuoteView_Minimalist.m index 6382af80b..0b2193af0 100644 --- a/iOS/TUIKit/TUIChat/UI_Minimalist/Cell/Reply/TUIMergeReplyQuoteView_Minimalist.m +++ b/iOS/TUIKit/TUIChat/UI_Minimalist/Cell/Reply/TUIMergeReplyQuoteView_Minimalist.m @@ -35,15 +35,6 @@ - (void)layoutSubviews { [super layoutSubviews]; - - self.titleLabel.mm_x = 0; - self.titleLabel.mm_y = 0; - self.titleLabel.mm_sizeToFit(); - self.titleLabel.mm_w = self.mm_w - self.titleLabel.mm_x; - - self.subTitleLabel.mm_x = self.titleLabel.mm_x; - self.subTitleLabel.mm_y = CGRectGetMaxY(self.titleLabel.frame) + 3; - self.subTitleLabel.mm_flexToRight(8).mm_sizeToFit(); } - (void)fillWithData:(TUIReplyQuoteViewData *)data { @@ -56,6 +47,39 @@ TUIMergeReplyQuoteViewData *myData = (TUIMergeReplyQuoteViewData *)data; self.titleLabel.text = myData.title; self.subTitleLabel.text = myData.abstract; + + // tell constraints they need updating + [self setNeedsUpdateConstraints]; + + // update constraints now so we can animate the change + [self updateConstraintsIfNeeded]; + + [self layoutIfNeeded]; +} + ++ (BOOL)requiresConstraintBasedLayout { + return YES; +} +// this is Apple's recommended place for adding/updating constraints +- (void)updateConstraints { + + [super updateConstraints]; + + [self.titleLabel sizeToFit]; + [self.titleLabel mas_remakeConstraints:^(MASConstraintMaker *make) { + make.leading.mas_equalTo(self); + make.top.mas_equalTo(self); + make.trailing.mas_equalTo(self.mas_trailing); + make.height.mas_equalTo(self.titleLabel.font.lineHeight); + }]; + + [self.subTitleLabel mas_remakeConstraints:^(MASConstraintMaker *make) { + make.leading.mas_equalTo(self.titleLabel); + make.top.mas_equalTo(self.titleLabel.mas_bottom).mas_offset(3); + make.trailing.mas_equalTo(self.mas_trailing).mas_offset(-8); + make.height.mas_equalTo(self.subTitleLabel.font.lineHeight); + }]; + } - (void)reset { diff --git a/iOS/TUIKit/TUIChat/UI_Minimalist/Cell/Reply/TUIReferenceMessageCell_Minimalist.m b/iOS/TUIKit/TUIChat/UI_Minimalist/Cell/Reply/TUIReferenceMessageCell_Minimalist.m index 3fa353b6b..ffc8be162 100644 --- a/iOS/TUIKit/TUIChat/UI_Minimalist/Cell/Reply/TUIReferenceMessageCell_Minimalist.m +++ b/iOS/TUIKit/TUIChat/UI_Minimalist/Cell/Reply/TUIReferenceMessageCell_Minimalist.m @@ -86,26 +86,49 @@ self.referenceData = data; self.senderLabel.text = [NSString stringWithFormat:@"%@:", data.sender]; + self.senderLabel.rtlAlignment = TUITextRTLAlignmentLeading; self.selectContent = data.content; self.textView.attributedText = [data.content getFormatEmojiStringWithFont:self.textView.font emojiLocations:self.referenceData.emojiLocations]; + if (isRTL()) { + self.textView.textAlignment = NSTextAlignmentRight; + } + else { + self.textView.textAlignment = NSTextAlignmentLeft; + } + UIImage *lineImage = nil; if (self.bubbleData.direction == MsgDirectionIncoming) { lineImage = [[TUIImageCache sharedInstance] getResourceFromCache:TUIChatImagePath_Minimalist(@"msg_reply_line_income")]; } else { lineImage = [[TUIImageCache sharedInstance] getResourceFromCache:TUIChatImagePath_Minimalist(@"msg_reply_line_outcome")]; } - self.quoteLineView.image = [lineImage resizableImageWithCapInsets:UIEdgeInsetsFromString(@"{10,0,20,0}") resizingMode:UIImageResizingModeStretch]; + lineImage = [lineImage rtl_imageFlippedForRightToLeftLayoutDirection]; + + UIEdgeInsets ei = UIEdgeInsetsFromString(@"{10,0,20,0}"); + ei = rtlEdgeInsetsWithInsets(ei); + self.quoteLineView.image = [lineImage resizableImageWithCapInsets:ei resizingMode:UIImageResizingModeStretch]; self.bottomContainer.hidden = CGSizeEqualToSize(data.bottomContainerSize, CGSizeZero); @weakify(self); [[RACObserve(data, originMessage) takeUntil:self.rac_prepareForReuseSignal] subscribeNext:^(V2TIMMessage *originMessage) { @strongify(self); - [self updateUI:data]; - [self layoutIfNeeded]; + // tell constraints they need updating + [self setNeedsUpdateConstraints]; + + // update constraints now so we can animate the change + [self updateConstraintsIfNeeded]; + + [self layoutIfNeeded]; }]; + // tell constraints they need updating + [self setNeedsUpdateConstraints]; + + // update constraints now so we can animate the change + [self updateConstraintsIfNeeded]; + [self layoutIfNeeded]; } @@ -119,11 +142,8 @@ self.currentOriginView = [self getCustomOriginView:referenceData.originCellData]; [self hiddenAllCustomOriginViews:YES]; self.currentOriginView.hidden = NO; - [self.currentOriginView fillWithData:referenceData.quoteData]; - - self.textView.frame = (CGRect){.origin = self.referenceData.textOrigin, .size = self.referenceData.textSize}; - + if (referenceData.direction == MsgDirectionIncoming) { self.textView.textColor = TUIChatDynamicColor(@"chat_reference_message_content_recv_text_color", @"#000000"); self.senderLabel.textColor = TUIChatDynamicColor(@"chat_reference_message_quoteView_recv_text_color", @"#888888"); @@ -136,37 +156,55 @@ if (referenceData.textColor) { self.textView.textColor = referenceData.textColor; } + + [self.textView mas_remakeConstraints:^(MASConstraintMaker *make) { + make.leading.mas_equalTo(self.bubbleView.mas_leading).mas_offset(self.referenceData.textOrigin.x); + make.top.mas_equalTo(self.bubbleView.mas_top).mas_offset(self.referenceData.textOrigin.y); + make.size.mas_equalTo(self.referenceData.textSize); + }]; + + [self.quoteView mas_remakeConstraints:^(MASConstraintMaker *make) { + if (self.referenceData.direction == MsgDirectionIncoming) { + make.leading.mas_equalTo(self.bubbleView).mas_offset(15); + } + else { + make.trailing.mas_equalTo(self.bubbleView).mas_offset(- 15); + } + if (self.replyEmojiView.isHidden) { + make.top.mas_equalTo(self.container.mas_bottom).mas_offset(6); + } + else { + make.top.mas_equalTo(self.replyEmojiView.mas_bottom).mas_offset(6); + } + make.size.mas_equalTo(self.referenceData.quoteSize); + }]; + + [self.senderLabel mas_remakeConstraints:^(MASConstraintMaker *make) { + make.leading.mas_equalTo(self.quoteView).mas_offset(6); + make.top.mas_equalTo(self.quoteView).mas_offset(8); + make.width.mas_equalTo(referenceData.senderSize.width); + make.height.mas_equalTo(referenceData.senderSize.height); + }]; - CGFloat marginX = 6; - CGFloat marginY = 8; + [self.currentOriginView mas_remakeConstraints:^(MASConstraintMaker *make) { + make.leading.mas_equalTo(self.senderLabel.mas_trailing).mas_offset(4); + make.top.mas_equalTo(self.senderLabel.mas_top).mas_offset(1); + make.trailing.mas_lessThanOrEqualTo(self.quoteView.mas_trailing); + make.height.mas_equalTo(self.referenceData.quotePlaceholderSize); + }]; + + [self.quoteLineView mas_remakeConstraints:^(MASConstraintMaker *make) { + make.top.mas_equalTo(self.bubbleView.mas_bottom); + make.bottom.mas_equalTo(self.quoteView.mas_centerY); + make.width.mas_equalTo(17); + if (self.referenceData.direction == MsgDirectionIncoming) { + make.leading.mas_equalTo(self.container.mas_leading).mas_offset(- 1); + } else { + make.trailing.mas_equalTo(self.container.mas_trailing); + } + }]; - self.senderLabel.mm_x = marginX; - self.senderLabel.mm_y = marginY; - self.senderLabel.mm_w = self.referenceData.senderSize.width + 4; - self.senderLabel.mm_h = self.referenceData.senderSize.height; - self.quoteView.mm_w = self.referenceData.quoteSize.width; - self.quoteView.mm_h = self.referenceData.quoteSize.height; - self.quoteView.mm_bottom(self.container.mm_b - self.quoteView.mm_h - self.replyEmojiView.mm_h - 6); - if (self.referenceData.direction == MsgDirectionIncoming) { - self.quoteView.mm_left(self.container.mm_x + 15); - } else { - self.quoteView.mm_right(self.container.mm_r + 15); - } - - self.quoteLineView.mm_y = self.container.mm_maxY - 14; - self.quoteLineView.mm_w = 17; - self.quoteLineView.mm_h = self.quoteView.mm_centerY - self.quoteLineView.mm_y; - if (self.referenceData.direction == MsgDirectionIncoming) { - self.quoteLineView.mm_left(self.container.mm_x - 1); - } else { - self.quoteLineView.mm_right(self.container.mm_r); - } - - self.currentOriginView.mm_y = marginY + 1; - self.currentOriginView.mm_x = self.senderLabel.mm_w + self.senderLabel.mm_x + marginX; - self.currentOriginView.mm_w = self.referenceData.quotePlaceholderSize.width; - self.currentOriginView.mm_h = self.referenceData.quotePlaceholderSize.height; } - (TUIReplyQuoteView_Minimalist *)getCustomOriginView:(TUIMessageCellData *)originCellData { @@ -180,6 +218,11 @@ if (view == nil) { Class class = [originCellData getReplyQuoteViewClass]; + NSString *clsStr = NSStringFromClass(class); + if (![clsStr containsString:@"_Minimalist"]) { + clsStr = [clsStr stringByAppendingString:@"_Minimalist"]; + class = NSClassFromString(clsStr); + } if (class) { view = [[class alloc] init]; } @@ -224,12 +267,19 @@ }]; } -- (void)layoutSubviews { - [super layoutSubviews]; ++ (BOOL)requiresConstraintBasedLayout { + return YES; +} +// this is Apple's recommended place for adding/updating constraints +- (void)updateConstraints { + + [super updateConstraints]; + [self updateUI:self.referenceData]; - + [self layoutBottomContainer]; + } - (void)layoutBottomContainer { @@ -244,11 +294,17 @@ UIView *view = self.replyEmojiView.hidden ? self.bubbleView : self.replyEmojiView; CGFloat topMargin = view.mm_maxY + self.nameLabel.mm_h + 6; - if (self.referenceData.direction == MsgDirectionOutgoing) { - self.bottomContainer.mm_top(topMargin).mm_width(size.width).mm_height(size.height).mm_right(self.mm_w - self.container.mm_maxX); - } else { - self.bottomContainer.mm_top(topMargin).mm_width(size.width).mm_height(size.height).mm_left(self.container.mm_minX); - } + + [self.bottomContainer mas_remakeConstraints:^(MASConstraintMaker *make) { + if (self.referenceData.direction == MsgDirectionIncoming) { + make.leading.mas_equalTo(self.container.mas_leading).mas_offset(offset); + } else { + make.trailing.mas_equalTo(self.container.mas_trailing).mas_offset(-offset); + } + make.top.mas_equalTo(view.mas_bottom).mas_offset(6); + make.size.mas_equalTo(size); + }]; + if (!self.quoteView.hidden) { CGRect oldRect = self.quoteView.frame; CGRect newRect = CGRectMake(oldRect.origin.x, CGRectGetMaxY(self.bottomContainer.frame) + 5, oldRect.size.width, oldRect.size.height); @@ -368,7 +424,7 @@ // 动态计算发送者的尺寸 // Calculate the size of label which displays the sender's displayname CGSize senderSize = [@"0" sizeWithAttributes:@{NSFontAttributeName : [UIFont boldSystemFontOfSize:12.0]}]; - CGRect senderRect = [referenceCellData.sender boundingRectWithSize:CGSizeMake(quoteMaxWidth, senderSize.height) + CGRect senderRect = [[NSString stringWithFormat:@"%@:",referenceCellData.sender] boundingRectWithSize:CGSizeMake(quoteMaxWidth, senderSize.height) options:NSStringDrawingUsesLineFragmentOrigin | NSStringDrawingUsesFontLeading attributes:@{NSFontAttributeName : [UIFont boldSystemFontOfSize:12.0]} context:nil]; @@ -421,10 +477,10 @@ quoteHeight = MAX(senderRect.size.height, placeholderSize.height); quoteHeight += (8 + 8); - referenceCellData.senderSize = CGSizeMake(senderRect.size.width, senderRect.size.height); - referenceCellData.quotePlaceholderSize = placeholderSize; + referenceCellData.senderSize = CGSizeMake(CGFLOAT_CEIL(senderRect.size.width)+3, senderRect.size.height); + referenceCellData.quotePlaceholderSize = CGSizeMake(CGFLOAT_CEIL(placeholderSize.width), placeholderSize.height); // self.replyContentSize = CGSizeMake(replyContentRect.size.width, replyContentRect.size.height); - referenceCellData.quoteSize = CGSizeMake(quoteWidth, quoteHeight); + referenceCellData.quoteSize = CGSizeMake(CGFLOAT_CEIL(quoteWidth), quoteHeight); return size; } diff --git a/iOS/TUIKit/TUIChat/UI_Minimalist/Cell/Reply/TUIReplyMessageCell_Minimalist.h b/iOS/TUIKit/TUIChat/UI_Minimalist/Cell/Reply/TUIReplyMessageCell_Minimalist.h index 45a345c34..49a2fa29c 100644 --- a/iOS/TUIKit/TUIChat/UI_Minimalist/Cell/Reply/TUIReplyMessageCell_Minimalist.h +++ b/iOS/TUIKit/TUIChat/UI_Minimalist/Cell/Reply/TUIReplyMessageCell_Minimalist.h @@ -19,7 +19,7 @@ NS_ASSUME_NONNULL_BEGIN @interface TUIReplyMessageCell_Minimalist : TUIBubbleMessageCell_Minimalist -@property(nonatomic, strong) CALayer *quoteBorderLayer; +@property(nonatomic, strong) UIView *quoteBorderLine; @property(nonatomic, strong) UIView *quoteView; @property(nonatomic, strong) UILabel *contentLabel; @property(nonatomic, strong) UILabel *senderLabel; diff --git a/iOS/TUIKit/TUIChat/UI_Minimalist/Cell/Reply/TUIReplyMessageCell_Minimalist.m b/iOS/TUIKit/TUIChat/UI_Minimalist/Cell/Reply/TUIReplyMessageCell_Minimalist.m index 9af2746b4..ae9e99a89 100644 --- a/iOS/TUIKit/TUIChat/UI_Minimalist/Cell/Reply/TUIReplyMessageCell_Minimalist.m +++ b/iOS/TUIKit/TUIChat/UI_Minimalist/Cell/Reply/TUIReplyMessageCell_Minimalist.m @@ -51,7 +51,7 @@ - (void)setupViews { [self.quoteView addSubview:self.senderLabel]; - [self.quoteView.layer addSublayer:self.quoteBorderLayer]; + [self.quoteView addSubview:self.quoteBorderLine]; [self.bubbleView addSubview:self.quoteView]; [self.bubbleView addSubview:self.contentLabel]; @@ -87,13 +87,39 @@ @weakify(self); [[RACObserve(data, originMessage) takeUntil:self.rac_prepareForReuseSignal] subscribeNext:^(V2TIMMessage *originMessage) { @strongify(self); - [self updateUI:data]; - [self layoutIfNeeded]; + // tell constraints they need updating + [self setNeedsUpdateConstraints]; + + // update constraints now so we can animate the change + [self updateConstraintsIfNeeded]; + + [self layoutIfNeeded]; }]; + // tell constraints they need updating + [self setNeedsUpdateConstraints]; + + // update constraints now so we can animate the change + [self updateConstraintsIfNeeded]; + [self layoutIfNeeded]; } ++ (BOOL)requiresConstraintBasedLayout { + return YES; +} + +// this is Apple's recommended place for adding/updating constraints +- (void)updateConstraints { + + [super updateConstraints]; + + [self updateUI:self.replyData]; + + [self layoutBottomContainer]; + +} + - (void)updateUI:(TUIReplyMessageCellData *)replyData { self.currentOriginView = [self getCustomOriginView:replyData.originCellData]; [self hiddenAllCustomOriginViews:YES]; @@ -101,27 +127,42 @@ [self.currentOriginView fillWithData:replyData.quoteData]; - self.quoteView.mm_x = 16; - self.quoteView.mm_y = 12; - self.quoteView.mm_w = self.replyData.quoteSize.width; - self.quoteView.mm_h = self.replyData.quoteSize.height; + [self.quoteView mas_remakeConstraints:^(MASConstraintMaker *make) { + make.leading.mas_equalTo(self.bubbleView).mas_offset(16); + make.top.mas_equalTo(12); + make.trailing.mas_lessThanOrEqualTo(self.bubbleView).mas_offset(-16); + make.width.mas_greaterThanOrEqualTo(self.senderLabel); + make.height.mas_equalTo(self.replyData.quoteSize.height); + }]; - self.quoteBorderLayer.frame = CGRectMake(0, 0, 3, self.quoteView.mm_h); + [self.quoteBorderLine mas_remakeConstraints:^(MASConstraintMaker *make) { + make.leading.mas_equalTo(self.quoteView); + make.top.mas_equalTo(self.quoteView); + make.width.mas_equalTo(3); + make.bottom.mas_equalTo(self.quoteView); + }]; - self.contentLabel.mm_y = CGRectGetMaxY(self.quoteView.frame) + 12.0; - self.contentLabel.mm_x = 18; - self.contentLabel.mm_w = self.replyData.replyContentSize.width; - self.contentLabel.mm_h = self.replyData.replyContentSize.height; + [self.contentLabel mas_remakeConstraints:^(MASConstraintMaker *make) { + make.leading.mas_equalTo(self.quoteView).mas_offset(4); + make.top.mas_equalTo(self.quoteView.mas_bottom).mas_offset(12); + make.trailing.mas_lessThanOrEqualTo(self.quoteView); + make.bottom.mas_equalTo(self.bubbleView).mas_offset(-4); + }]; - self.senderLabel.mm_x = 6; - self.senderLabel.mm_y = 3; - self.senderLabel.mm_w = self.replyData.senderSize.width; - self.senderLabel.mm_h = self.replyData.senderSize.height; + [self.senderLabel mas_remakeConstraints:^(MASConstraintMaker *make) { + make.leading.mas_equalTo(self.contentLabel); + make.top.mas_equalTo(3); + make.size.mas_equalTo(self.replyData.senderSize); + }]; + + [self.currentOriginView mas_remakeConstraints:^(MASConstraintMaker *make) { + make.leading.mas_equalTo(self.senderLabel); + make.top.mas_equalTo(self.senderLabel.mas_bottom).mas_offset(4); +// make.width.mas_greaterThanOrEqualTo(self.replyData.quotePlaceholderSize); + make.trailing.mas_lessThanOrEqualTo(self.quoteView.mas_trailing); + make.height.mas_equalTo(self.replyData.quotePlaceholderSize); + }]; - self.currentOriginView.mm_y = CGRectGetMaxY(self.senderLabel.frame) + 4; - self.currentOriginView.mm_x = self.senderLabel.mm_x; - self.currentOriginView.mm_w = self.replyData.quotePlaceholderSize.width; - self.currentOriginView.mm_h = self.replyData.quotePlaceholderSize.height; } - (TUIReplyQuoteView_Minimalist *)getCustomOriginView:(TUIMessageCellData *)originCellData { @@ -134,7 +175,13 @@ } if (view == nil) { + //FIXME: celldata应该区分不同的Cell Class class = [originCellData getReplyQuoteViewClass]; + NSString *clsStr = NSStringFromClass(class); + if (![clsStr containsString:@"_Minimalist"]) { + clsStr = [clsStr stringByAppendingString:@"_Minimalist"]; + class = NSClassFromString(clsStr); + } if (class) { view = [[class alloc] init]; } @@ -194,12 +241,15 @@ CGSize size = self.replyData.bottomContainerSize; UIView *view = self.replyEmojiView.hidden ? self.bubbleView : self.replyEmojiView; CGFloat topMargin = view.mm_maxY + self.nameLabel.mm_h + 6; - - if (self.replyData.direction == MsgDirectionOutgoing) { - self.bottomContainer.mm_top(topMargin).mm_width(size.width).mm_height(size.height).mm_right(self.mm_w - self.container.mm_maxX); - } else { - self.bottomContainer.mm_top(topMargin).mm_width(size.width).mm_height(size.height).mm_left(self.container.mm_minX); - } + [self.bottomContainer mas_remakeConstraints:^(MASConstraintMaker *make) { + if (self.replyData.direction == MsgDirectionIncoming) { + make.leading.mas_equalTo(self.container.mas_leading); + } else { + make.trailing.mas_equalTo(self.container.mas_trailing); + } + make.top.mas_equalTo(view.mas_bottom).mas_offset(6); + make.size.mas_equalTo(size); + }]; if (!self.messageModifyRepliesButton.hidden) { CGRect oldRect = self.messageModifyRepliesButton.frame; @@ -220,6 +270,7 @@ _senderLabel.text = @"harvy:"; _senderLabel.font = [UIFont boldSystemFontOfSize:12.0]; _senderLabel.textColor = TUIChatDynamicColor(@"chat_reply_message_sender_text_color", @"#888888"); + _senderLabel.textAlignment = isRTL()?NSTextAlignmentRight:NSTextAlignmentLeft; } return _senderLabel; } @@ -232,12 +283,12 @@ return _quoteView; } -- (CALayer *)quoteBorderLayer { - if (_quoteBorderLayer == nil) { - _quoteBorderLayer = [CALayer layer]; - _quoteBorderLayer.backgroundColor = [UIColor colorWithRed:68 / 255.0 green:68 / 255.0 blue:68 / 255.0 alpha:0.1].CGColor; +- (UIView *)quoteBorderLine { + if (_quoteBorderLine == nil) { + _quoteBorderLine = [[UIView alloc] init]; + _quoteBorderLine.backgroundColor = [UIColor colorWithRed:68 / 255.0 green:68 / 255.0 blue:68 / 255.0 alpha:0.1]; } - return _quoteBorderLayer; + return _quoteBorderLine; } - (UILabel *)contentLabel { @@ -245,6 +296,7 @@ _contentLabel = [[UILabel alloc] init]; _contentLabel.font = [UIFont systemFontOfSize:16.0]; _contentLabel.textColor = TUIChatDynamicColor(@"chat_reply_message_content_text_color", @"#000000"); + _contentLabel.textAlignment = isRTL()?NSTextAlignmentRight:NSTextAlignmentLeft; _contentLabel.numberOfLines = 0; } return _contentLabel; diff --git a/iOS/TUIKit/TUIChat/UI_Minimalist/Cell/Reply/TUITextReplyQuoteView_Minimalist.m b/iOS/TUIKit/TUIChat/UI_Minimalist/Cell/Reply/TUITextReplyQuoteView_Minimalist.m index ba4e058ab..99ca56a30 100644 --- a/iOS/TUIKit/TUIChat/UI_Minimalist/Cell/Reply/TUITextReplyQuoteView_Minimalist.m +++ b/iOS/TUIKit/TUIChat/UI_Minimalist/Cell/Reply/TUITextReplyQuoteView_Minimalist.m @@ -24,11 +24,18 @@ return self; } -- (void)layoutSubviews { - [super layoutSubviews]; - self.textLabel.frame = self.bounds; ++ (BOOL)requiresConstraintBasedLayout { + return YES; } +// this is Apple's recommended place for adding/updating constraints +- (void)updateConstraints { + + [super updateConstraints]; + [self.textLabel mas_remakeConstraints:^(MASConstraintMaker *make) { + make.edges.mas_equalTo(self); + }]; +} - (void)fillWithData:(TUIReplyQuoteViewData *)data { [super fillWithData:data]; if (![data isKindOfClass:TUITextReplyQuoteViewData.class]) { @@ -36,6 +43,22 @@ } TUITextReplyQuoteViewData *myData = (TUITextReplyQuoteViewData *)data; self.textLabel.attributedText = [myData.text getFormatEmojiStringWithFont:self.textLabel.font emojiLocations:nil]; + + if (isRTL()) { + self.textLabel.textAlignment = NSTextAlignmentRight; + } + else { + self.textLabel.textAlignment = NSTextAlignmentLeft; + } + + // tell constraints they need updating + [self setNeedsUpdateConstraints]; + + // update constraints now so we can animate the change + [self updateConstraintsIfNeeded]; + + [self layoutIfNeeded]; + } - (void)reset { diff --git a/iOS/TUIKit/TUIChat/UI_Minimalist/Cell/Reply/TUIVideoReplyQuoteView_Minimalist.m b/iOS/TUIKit/TUIChat/UI_Minimalist/Cell/Reply/TUIVideoReplyQuoteView_Minimalist.m index a24d64824..e115dda33 100644 --- a/iOS/TUIKit/TUIChat/UI_Minimalist/Cell/Reply/TUIVideoReplyQuoteView_Minimalist.m +++ b/iOS/TUIKit/TUIChat/UI_Minimalist/Cell/Reply/TUIVideoReplyQuoteView_Minimalist.m @@ -25,7 +25,27 @@ - (void)layoutSubviews { [super layoutSubviews]; - self.playView.center = self.imageView.center; +} ++ (BOOL)requiresConstraintBasedLayout { + return YES; +} + +// this is Apple's recommended place for adding/updating constraints +- (void)updateConstraints { + + [super updateConstraints]; + + TUIVideoReplyQuoteViewData *myData = (TUIVideoReplyQuoteViewData *)self.data; + + [self.imageView mas_remakeConstraints:^(MASConstraintMaker *make) { + make.leading.top.mas_equalTo(self); + make.size.mas_equalTo(myData.imageSize); + }]; + + [self.playView mas_remakeConstraints:^(MASConstraintMaker *make) { + make.size.mas_equalTo(CGSizeMake(30, 30)); + make.center.mas_equalTo(self.imageView); + }]; } - (void)fillWithData:(TUIReplyQuoteViewData *)data { @@ -39,7 +59,13 @@ if (myData.image == nil) { [myData downloadImage]; } - self.imageView.frame = CGRectMake(0, 0, myData.imageSize.width, myData.imageSize.height); + // tell constraints they need updating + [self setNeedsUpdateConstraints]; + + // update constraints now so we can animate the change + [self updateConstraintsIfNeeded]; + + [self layoutIfNeeded]; } @end diff --git a/iOS/TUIKit/TUIChat/UI_Minimalist/Cell/Reply/TUIVoiceReplyQuoteView_Minimalist.m b/iOS/TUIKit/TUIChat/UI_Minimalist/Cell/Reply/TUIVoiceReplyQuoteView_Minimalist.m index 2b2e2ebca..686d42ba2 100644 --- a/iOS/TUIKit/TUIChat/UI_Minimalist/Cell/Reply/TUIVoiceReplyQuoteView_Minimalist.m +++ b/iOS/TUIKit/TUIChat/UI_Minimalist/Cell/Reply/TUIVoiceReplyQuoteView_Minimalist.m @@ -28,12 +28,6 @@ - (void)layoutSubviews { [super layoutSubviews]; - - self.iconView.frame = CGRectMake(0, 0, 15, 15); - [self.textLabel sizeToFit]; - self.textLabel.mm_centerY = self.iconView.mm_centerY; - self.textLabel.mm_x = CGRectGetMaxX(self.iconView.frame) + 3; - self.textLabel.mm_w = self.mm_w - self.textLabel.mm_x; } - (void)fillWithData:(TUIReplyQuoteViewData *)data { @@ -44,6 +38,39 @@ TUIVoiceReplyQuoteViewData *myData = (TUIVoiceReplyQuoteViewData *)data; self.iconView.image = myData.icon; self.textLabel.numberOfLines = 1; + // tell constraints they need updating + [self setNeedsUpdateConstraints]; + + // update constraints now so we can animate the change + [self updateConstraintsIfNeeded]; + + [self layoutIfNeeded]; +} + ++ (BOOL)requiresConstraintBasedLayout { + return YES; +} + +// this is Apple's recommended place for adding/updating constraints +- (void)updateConstraints { + + [super updateConstraints]; + [self.iconView mas_remakeConstraints:^(MASConstraintMaker *make) { + make.leading.mas_equalTo(self); + make.top.mas_equalTo(self); + make.width.mas_equalTo(15); + make.height.mas_equalTo(15); + }]; + + [self.textLabel sizeToFit]; + [self.textLabel mas_remakeConstraints:^(MASConstraintMaker *make) { + make.leading.mas_equalTo(self.iconView.mas_trailing).mas_offset(3); + make.centerY.mas_equalTo(self.mas_centerY); + make.trailing.mas_equalTo(self.mas_trailing); + make.height.mas_equalTo(self.textLabel.font.lineHeight); + }]; + + } @end diff --git a/iOS/TUIKit/TUIChat/UI_Minimalist/Chat/TUIBaseChatViewController_Minimalist.m b/iOS/TUIKit/TUIChat/UI_Minimalist/Chat/TUIBaseChatViewController_Minimalist.m index 87b08a681..9c2e16bb0 100644 --- a/iOS/TUIKit/TUIChat/UI_Minimalist/Chat/TUIBaseChatViewController_Minimalist.m +++ b/iOS/TUIKit/TUIChat/UI_Minimalist/Chat/TUIBaseChatViewController_Minimalist.m @@ -181,11 +181,16 @@ static UIView *gCustomTopView; TUINavigationController *naviController = (TUINavigationController *)self.navigationController; if ([naviController isKindOfClass:TUINavigationController.class]) { naviController.uiNaviDelegate = self; + UIImage *backimg = TIMCommonDynamicImage(@"nav_back_img", TIMCommonImagePath(@"nav_back")); + backimg = [backimg rtl_imageFlippedForRightToLeftLayoutDirection]; + naviController.navigationItemBackArrowImage = backimg; } UIButton *backButton = [[UIButton alloc] initWithFrame:CGRectMake(0, 0, 24, 24)]; [backButton addTarget:self action:@selector(backButtonClick) forControlEvents:UIControlEventTouchUpInside]; - [backButton setImage:[[TUIImageCache sharedInstance] getResourceFromCache:TUIChatImagePath_Minimalist(@"vc_back")] forState:UIControlStateNormal]; + UIImage *imgicon = [[TUIImageCache sharedInstance] getResourceFromCache:TUIChatImagePath_Minimalist(@"vc_back")]; + imgicon = [imgicon rtl_imageFlippedForRightToLeftLayoutDirection]; + [backButton setImage:imgicon forState:UIControlStateNormal]; UIBarButtonItem *backButtonItem = [[UIBarButtonItem alloc] initWithCustomView:backButton]; UIView *infoView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, kScale390(200), 40)]; @@ -202,13 +207,22 @@ static UIView *gCustomTopView; UILabel *mainTitleLabel = [[UILabel alloc] initWithFrame:CGRectMake(avatarView.mm_x + avatarView.mm_w + kScale390(8), 0, kScale390(200), 20)]; mainTitleLabel.font = [UIFont boldSystemFontOfSize:14]; mainTitleLabel.text = [self getMainTitleLabelText]; + mainTitleLabel.rtlAlignment = TUITextRTLAlignmentLeading; [infoView addSubview:mainTitleLabel]; self.mainTitleLabel = mainTitleLabel; self.subTitleLabel = [[UILabel alloc] initWithFrame:CGRectMake(mainTitleLabel.mm_x, 20, mainTitleLabel.mm_w, 20)]; self.subTitleLabel.font = [UIFont systemFontOfSize:12]; + self.subTitleLabel.rtlAlignment = TUITextRTLAlignmentLeading; [self updateSubTitleLabelText]; [infoView addSubview:self.subTitleLabel]; + + if (isRTL()) { + [avatarView resetFrameToFitRTL]; + [mainTitleLabel resetFrameToFitRTL]; + [self.subTitleLabel resetFrameToFitRTL]; + } + UIBarButtonItem *infoViewItem = [[UIBarButtonItem alloc] initWithCustomView:infoView]; self.navigationItem.leftBarButtonItems = @[ backButtonItem, infoViewItem ]; @@ -345,8 +359,9 @@ static UIView *gCustomTopView; _messageController = vc; _messageController.delegate = self; [_messageController setConversation:self.conversationData]; + CGFloat textViewHeight = TUIChatConfig.defaultConfig.enableMainPageInputBar? TTextView_Height:0; _messageController.view.frame = CGRectMake(0, [self topMarginByCustomView], self.view.frame.size.width, - self.view.frame.size.height - TTextView_Height - Bottom_SafeHeight - [self topMarginByCustomView]); + self.view.frame.size.height - textViewHeight - Bottom_SafeHeight - [self topMarginByCustomView]); [self addChildViewController:_messageController]; [self.view addSubview:_messageController.view]; [_messageController didMoveToParentViewController:self]; @@ -365,6 +380,8 @@ static UIView *gCustomTopView; _inputController.view.autoresizingMask = UIViewAutoresizingFlexibleTopMargin; [self addChildViewController:_inputController]; [self.view addSubview:_inputController.view]; + _inputController.view.hidden = !TUIChatConfig.defaultConfig.enableMainPageInputBar; + } - (void)configHeadImageView:(TUIChatConversationModel *)convData { /** @@ -415,8 +432,10 @@ static UIView *gCustomTopView; } else if (IS_NOT_EMPTY_NSSTRING(imgUrl)) { [self.backgroudView sd_setImageWithURL:[NSURL URLWithString:imgUrl] placeholderImage:nil]; } + CGFloat textViewHeight = TUIChatConfig.defaultConfig.enableMainPageInputBar? TTextView_Height:0; + self.backgroudView.frame = - CGRectMake(0, self.view.frame.origin.y, self.view.frame.size.width, self.view.frame.size.height - TTextView_Height - Bottom_SafeHeight); + CGRectMake(0, self.view.frame.origin.y, self.view.frame.size.width, self.view.frame.size.height - textViewHeight - Bottom_SafeHeight); [self.view insertSubview:self.backgroudView atIndex:0]; } @@ -489,7 +508,7 @@ static UIView *gCustomTopView; textColor:kTUIInputNormalTextColor emojiLocations:nil]; - [self.inputController.inputBar.inputTextView.textStorage insertAttributedString:formatEmojiString atIndex:0]; + [self.inputController.inputBar addDraftToInputBar:formatEmojiString]; return; } @@ -503,7 +522,7 @@ static UIView *gCustomTopView; textColor:kTUIInputNormalTextColor emojiLocations:nil]; - [self.inputController.inputBar.inputTextView.textStorage insertAttributedString:formatEmojiString atIndex:0]; + [self.inputController.inputBar addDraftToInputBar:formatEmojiString]; NSString *messageRootID = [jsonDict.allKeys containsObject:@"messageRootID"] ? jsonDict[@"messageRootID"] : @""; @@ -576,7 +595,7 @@ static UIView *gCustomTopView; self.conversationData.faceUrl = friendInfoResult.friendInfo.userFullInfo.faceURL; } else { [TUIChatDataProvider - getUserInfoWithUserId:friendInfoResult.friendInfo.userID + getUserInfoWithUserId:self.conversationData.userID SuccBlock:^(V2TIMUserFullInfo *_Nonnull userInfo) { if (userInfo.nickName.length > 0) { self.conversationData.title = userInfo.nickName; @@ -715,6 +734,7 @@ static UIView *gCustomTopView; - (void)inputControllerDidSelectMoreButton:(TUIInputController_Minimalist *)inputController { NSArray *items = [self.dataProvider getInputMoreActionItemList:self.conversationData.userID groupID:self.conversationData.groupID + conversationModel:self.conversationData pushVC:self.navigationController actionController:self]; if (items.count) { diff --git a/iOS/TUIKit/TUIChat/UI_Minimalist/Chat/TUIBaseMessageController_Minimalist.m b/iOS/TUIKit/TUIChat/UI_Minimalist/Chat/TUIBaseMessageController_Minimalist.m index 5710ac96d..b545f76f4 100644 --- a/iOS/TUIKit/TUIChat/UI_Minimalist/Chat/TUIBaseMessageController_Minimalist.m +++ b/iOS/TUIKit/TUIChat/UI_Minimalist/Chat/TUIBaseMessageController_Minimalist.m @@ -44,6 +44,7 @@ #import "TUIVideoMessageCell_Minimalist.h" #import "TUIVoiceMessageCell_Minimalist.h" #import "TUIMessageCellConfig_Minimalist.h" +#import "TUIVoiceMessageCell_Minimalist.h" typedef NSString * CellDataClassName; typedef Class CellClass; @@ -137,8 +138,8 @@ typedef NSNumber * HeightNumber; } - (void)registerEvents { - [TUICore registerEvent:TUICore_TUITranslationNotify subKey:TUICore_TUITranslationNotify_WillForwardTranslationSubKey object:self]; - [TUICore registerEvent:TUICore_TUITranslationNotify subKey:TUICore_TUITranslationNotify_DidChangeTranslationSubKey object:self]; + [TUICore registerEvent:TUICore_TUIPluginNotify subKey:TUICore_TUIPluginNotify_WillForwardTextSubKey object:self]; + [TUICore registerEvent:TUICore_TUIPluginNotify subKey:TUICore_TUIPluginNotify_DidChangePluginViewSubKey object:self]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(applicationBecomeActive) name:UIApplicationDidBecomeActiveNotification @@ -313,11 +314,18 @@ typedef NSNumber * HeightNumber; } FailBlock:^(int code, NSString *desc) { @strongify(self); - [TUITool makeToastError:code msg:desc]; + NSString * errorMsg = [TUITool convertIMError:code msg:desc]; + [self makeSendErrorHud:errorMsg]; [self changeMsg:cellData status:Msg_Status_Fail]; }]; } +- (void)makeSendErrorHud:(NSString *)msg { + UIAlertController *ac = [UIAlertController alertControllerWithTitle:msg message:nil preferredStyle:UIAlertControllerStyleAlert]; + [ac tuitheme_addAction:[UIAlertAction actionWithTitle:TIMCommonLocalizableString(Confirm) style:UIAlertActionStyleDefault handler:nil]]; + [self presentViewController:ac animated:YES completion:nil]; +} + - (void)sendMessage:(V2TIMMessage *)message { [self sendMessage:message placeHolderCellData:nil]; } @@ -370,14 +378,14 @@ typedef NSNumber * HeightNumber; #pragma mark - TUINotificationProtocol - (void)onNotifyEvent:(NSString *)key subKey:(NSString *)subKey object:(id)anObject param:(NSDictionary *)param { - if ([key isEqualToString:TUICore_TUITranslationNotify] && [subKey isEqualToString:TUICore_TUITranslationNotify_DidChangeTranslationSubKey]) { + if ([key isEqualToString:TUICore_TUIPluginNotify] && [subKey isEqualToString:TUICore_TUIPluginNotify_DidChangePluginViewSubKey]) { // Translation View is shown, hidden or changed. - TUIMessageCellData *data = param[TUICore_TUITranslationNotify_DidChangeTranslationSubKey_Data]; + TUIMessageCellData *data = param[TUICore_TUIPluginNotify_DidChangePluginViewSubKey_Data]; [self clearAndReloadCellOfData:data]; } - if ([key isEqualToString:TUICore_TUITranslationNotify] && [subKey isEqualToString:TUICore_TUITranslationNotify_WillForwardTranslationSubKey]) { + if ([key isEqualToString:TUICore_TUIPluginNotify] && [subKey isEqualToString:TUICore_TUIPluginNotify_WillForwardTextSubKey]) { // Translation will be forwarded. - NSString *text = param[TUICore_TUITranslationNotify_WillForwardTranslationSubKey_Text]; + NSString *text = param[TUICore_TUIPluginNotify_WillForwardTextSubKey_Text]; if (self.delegate && [self.delegate respondsToSelector:@selector(messageController:onForwardText:)]) { [self.delegate messageController:self onForwardText:text]; } @@ -790,7 +798,7 @@ static NSMutableArray *reloadMsgIndexs = nil; #pragma mark - TUIMessageCellDelegate - (void)onSelectMessage:(TUIMessageCell *)cell { - if (self.showCheckBox) { + if (self.showCheckBox && [self supportCheckBox:(TUIMessageCellData *)cell.data]) { TUIMessageCellData *data = (TUIMessageCellData *)cell.data; data.selected = !data.selected; [self.tableView reloadData]; @@ -830,6 +838,9 @@ static NSMutableArray *reloadMsgIndexs = nil; } - (void)tryShowGuidance { + if (isRTL()){ + return; + } BOOL hasShow = [NSUserDefaults.standardUserDefaults boolForKey:@"chat_reply_guide_showKey"]; if (hasShow) { return; @@ -938,7 +949,12 @@ static NSMutableArray *reloadMsgIndexs = nil; TUIChatPopContextExtionItem *deleteItem = [self setupDeleteAction:alertController targetCell:cell]; + TUIChatPopContextExtionItem *audioPlaybackStyleItem = [self setupAudioPlaybackStyleAction:alertController targetCell:cell]; + if (isChatNoramlMessageOrCustomMessage) { + if (imMsg.status == V2TIM_MSG_STATUS_SEND_SUCC && imMsg.soundElem) { + [items addObject:audioPlaybackStyleItem]; + } if ([data isKindOfClass:[TUITextMessageCellData class]] || [data isKindOfClass:TUIReferenceMessageCellData.class]) { [items addObject:copyItem]; } @@ -1156,20 +1172,28 @@ static NSMutableArray *reloadMsgIndexs = nil; } - (void)onJumpToMessageInfoPage:(TUIMessageCellData *)data selectCell:(TUIMessageCell *)cell { - TUIMessageReadViewController_Minimalist *readViewController = - [[TUIMessageReadViewController_Minimalist alloc] initWithCellData:data - dataProvider:self.messageDataProvider - showReadStatusDisable:NO - c2cReceiverName:self.conversationData.title - c2cReceiverAvatar:self.conversationData.faceUrl]; - CGRect frame = [UIApplication.sharedApplication.keyWindow convertRect:cell.frame fromView:cell]; - readViewController.alertViewCellData = data; - readViewController.originFrame = frame; - readViewController.alertCellClass = cell.class; - readViewController.viewWillShowHandler = ^(TUIMessageCell *_Nonnull alertView) { - alertView.delegate = self; - }; - [self.navigationController pushViewController:readViewController animated:YES]; + + TUIMessageCellData *alertViewCellData = [TUIMessageDataProvider getCellData:cell.messageData.innerMessage];; + @weakify(self); + [self.messageDataProvider preProcessMessage:@[alertViewCellData] callback:^{ + @strongify(self); + TUIMessageReadViewController_Minimalist *readViewController = + [[TUIMessageReadViewController_Minimalist alloc] initWithCellData:data + dataProvider:self.messageDataProvider + showReadStatusDisable:NO + c2cReceiverName:self.conversationData.title + c2cReceiverAvatar:self.conversationData.faceUrl]; + CGRect frame = [UIApplication.sharedApplication.keyWindow convertRect:cell.frame fromView:cell]; + readViewController.originFrame = frame; + readViewController.alertCellClass = cell.class; + @weakify(self); + readViewController.viewWillShowHandler = ^(TUIMessageCell *_Nonnull alertView) { + alertView.delegate = self; + }; + readViewController.alertViewCellData = alertViewCellData; + [self.navigationController pushViewController:readViewController animated:YES]; + }]; + } - (BOOL)canPerformAction:(SEL)action withSender:(id)sender { @@ -1208,7 +1232,8 @@ static NSMutableArray *reloadMsgIndexs = nil; content = txtCell.textView.text; } if ([sender isKindOfClass:TUIReferenceMessageCell_Minimalist.class]) { - TUIReferenceMessageCellData *replyMsg = (TUIReferenceMessageCellData *)sender; + TUIReferenceMessageCell_Minimalist *replyMsgCell = (TUIReferenceMessageCell_Minimalist *)sender; + TUIReferenceMessageCellData *replyMsg = (TUIReferenceMessageCellData *)replyMsgCell.data; content = replyMsg.content; } if (content.length > 0) { @@ -1594,4 +1619,50 @@ static NSMutableArray *reloadMsgIndexs = nil; return deleteItem; } +- (TUIChatPopContextExtionItem *)setupAudioPlaybackStyleAction:(TUIChatPopContextController *)alertController targetCell:(TUIMessageCell *)cell { + + + @weakify(self); + @weakify(cell); + @weakify(alertController); + + TUIVoiceAudioPlaybackStyle originStyle = [TUIVoiceMessageCellData getAudioplaybackStyle]; + + TUIChatPopContextExtionItem *styleActionItem = nil; + __weak typeof(styleActionItem) weakStyleActionItem = styleActionItem; + + NSString *title = @""; + UIImage * img = nil; + if (originStyle == TUIVoiceAudioPlaybackStyleLoudspeaker) { + title = TIMCommonLocalizableString(TUIKitAudioPlaybackStyleHandset); + img = [UIImage imageNamed:TUIChatImagePath_Minimalist(@"icon_extion_loudspeaker")]; + } + else { + title = TIMCommonLocalizableString(TUIKitAudioPlaybackStyleLoudspeaker); + img = [UIImage imageNamed:TUIChatImagePath_Minimalist(@"icon_extion_handset")]; + } + + styleActionItem = + [[TUIChatPopContextExtionItem alloc] initWithTitle:title + markIcon:img + weight:11000 + withActionHandler:^(TUIChatPopContextExtionItem *action) { + @strongify(alertController); + [alertController blurDismissViewControllerAnimated:NO + completion:^(BOOL finished) { + if (originStyle == TUIVoiceAudioPlaybackStyleLoudspeaker) { + // Change To Handset + weakStyleActionItem.title = TIMCommonLocalizableString(TUIKitAudioPlaybackStyleLoudspeaker); + [TUITool hideToast]; + [TUITool makeToast:TIMCommonLocalizableString(TUIKitAudioPlaybackStyleChange2Handset) duration:2]; + } else { + weakStyleActionItem.title = TIMCommonLocalizableString(TUIKitAudioPlaybackStyleHandset); + [TUITool hideToast]; + [TUITool makeToast:TIMCommonLocalizableString(TUIKitAudioPlaybackStyleChange2Loudspeaker) duration:2]; + } + [TUIVoiceMessageCellData changeAudioPlaybackStyle]; + }]; + }]; + return styleActionItem; +} @end diff --git a/iOS/TUIKit/TUIChat/UI_Minimalist/Chat/TUIC2CChatViewController_Minimalist.m b/iOS/TUIKit/TUIChat/UI_Minimalist/Chat/TUIC2CChatViewController_Minimalist.m index a5e37eb08..5bddbf692 100644 --- a/iOS/TUIKit/TUIChat/UI_Minimalist/Chat/TUIC2CChatViewController_Minimalist.m +++ b/iOS/TUIKit/TUIChat/UI_Minimalist/Chat/TUIC2CChatViewController_Minimalist.m @@ -38,7 +38,8 @@ #pragma mark - Override Methods - (NSString *)forwardTitleWithMyName:(NSString *)nameStr { - return [NSString stringWithFormat:TIMCommonLocalizableString(TUIKitRelayChatHistoryForSomebodyFormat), self.conversationData.title, nameStr]; + NSString *title = [NSString stringWithFormat:TIMCommonLocalizableString(TUIKitRelayChatHistoryForSomebodyFormat), self.conversationData.title, nameStr]; + return rtlString(title); } - (void)inputControllerBeginTyping:(TUIInputController_Minimalist *)inputController { diff --git a/iOS/TUIKit/TUIChat/UI_Minimalist/Chat/TUIChatMembersSegementScrollView.m b/iOS/TUIKit/TUIChat/UI_Minimalist/Chat/TUIChatMembersSegementScrollView.m index b0c3e5a84..5bc27d466 100644 --- a/iOS/TUIKit/TUIChat/UI_Minimalist/Chat/TUIChatMembersSegementScrollView.m +++ b/iOS/TUIKit/TUIChat/UI_Minimalist/Chat/TUIChatMembersSegementScrollView.m @@ -60,6 +60,13 @@ [self.segementScrollView addSubview:self.selectedLine]; self.segementScrollView.contentSize = CGSizeMake(titleCount * SEGEMENT_BTN_WIDTH + (padding * titleCount - 1), 0); + if (isRTL()) { + self.segementScrollView.transform = CGAffineTransformMakeRotation(M_PI); + NSArray *subViews = self.segementScrollView.subviews; + for (UIView *subView in subViews) { + subView.transform = CGAffineTransformMakeRotation(M_PI); + } + } } return self; } @@ -172,6 +179,13 @@ [self.pageScrollView addSubview:viewController.view]; } self.pageScrollView.contentSize = CGSizeMake(viewArray.count * SCROLLVIEW_WIDTH, self.pageScrollView.frame.size.height); + if (isRTL()) { + _pageScrollView.transform = CGAffineTransformMakeRotation(M_PI); + NSArray *subViews = _pageScrollView.subviews; + for (UIView *subView in subViews) { + subView.transform = CGAffineTransformMakeRotation(M_PI); + } + } } return self; diff --git a/iOS/TUIKit/TUIChat/UI_Minimalist/Chat/TUIChatSmallTongueView_Minimalist.m b/iOS/TUIKit/TUIChat/UI_Minimalist/Chat/TUIChatSmallTongueView_Minimalist.m index c54e4acc4..73c70036c 100644 --- a/iOS/TUIKit/TUIChat/UI_Minimalist/Chat/TUIChatSmallTongueView_Minimalist.m +++ b/iOS/TUIKit/TUIChat/UI_Minimalist/Chat/TUIChatSmallTongueView_Minimalist.m @@ -10,6 +10,7 @@ #import #import #import +#import "TUIChatConfig.h" #define TongueMiddleSpace 5.f #define TongueRightSpace 10.f @@ -42,7 +43,10 @@ backgroudView.mm_fill(); backgroudView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight; UIImage *bkImage = [[TUIImageCache sharedInstance] getResourceFromCache:TUIChatImagePath_Minimalist(@"small_tongue_bk")]; - backgroudView.image = [bkImage resizableImageWithCapInsets:UIEdgeInsetsFromString(@"{5,12,5,5}") resizingMode:UIImageResizingModeStretch]; + bkImage = [bkImage rtl_imageFlippedForRightToLeftLayoutDirection]; + UIEdgeInsets ei = UIEdgeInsetsFromString(@"{5,12,5,5}"); + ei = rtlEdgeInsetsWithInsets(ei); + backgroudView.image = [bkImage resizableImageWithCapInsets:ei resizingMode:UIImageResizingModeStretch]; // 点击事件 UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(onTap)]; @@ -186,9 +190,14 @@ static UIWindow *gWindow = nil; CGFloat tongueWidth = [TUIChatSmallTongueView_Minimalist getTongueWidth:gTongue]; CGFloat tongueHeight = [TUIChatSmallTongueView_Minimalist getTongueHeight:gTongue]; - gWindow.frame = - CGRectMake(Screen_Width - kScale390(54), Screen_Height - Bottom_SafeHeight - TTextView_Height - 20 - tongueHeight, tongueWidth, tongueHeight); - + if(isRTL()) { + gWindow.frame = + CGRectMake(kScale390(16), Screen_Height - Bottom_SafeHeight - TTextView_Height - 20 - tongueHeight, tongueWidth, tongueHeight); + } + else { + gWindow.frame = + CGRectMake(Screen_Width - kScale390(54), Screen_Height - Bottom_SafeHeight - TTextView_Height - 20 - tongueHeight, tongueWidth, tongueHeight); + } if (!gTongueView) { gTongueView = [[TUIChatSmallTongueView_Minimalist alloc] initWithFrame:CGRectZero]; [gWindow addSubview:gTongueView]; diff --git a/iOS/TUIKit/TUIChat/UI_Minimalist/Chat/TUIFileViewController_Minimalist.m b/iOS/TUIKit/TUIChat/UI_Minimalist/Chat/TUIFileViewController_Minimalist.m index dc1e60996..84524bb20 100644 --- a/iOS/TUIKit/TUIChat/UI_Minimalist/Chat/TUIFileViewController_Minimalist.m +++ b/iOS/TUIKit/TUIChat/UI_Minimalist/Chat/TUIFileViewController_Minimalist.m @@ -39,8 +39,9 @@ // left UIImage *defaultImage = [UIImage imageNamed:TUIChatImagePath(@"back")]; UIButton *leftButton = [[UIButton alloc] initWithFrame:CGRectMake(0, 0, 30, 30)]; + UIImage *formatImage = [TIMCommonDynamicImage(@"nav_back_img", defaultImage) rtl_imageFlippedForRightToLeftLayoutDirection]; [leftButton addTarget:self action:@selector(onBack:) forControlEvents:UIControlEventTouchUpInside]; - [leftButton setImage:TIMCommonDynamicImage(@"nav_back_img", defaultImage) forState:UIControlStateNormal]; + [leftButton setImage:formatImage forState:UIControlStateNormal]; UIBarButtonItem *leftItem = [[UIBarButtonItem alloc] initWithCustomView:leftButton]; self.navigationItem.leftBarButtonItem = leftItem; diff --git a/iOS/TUIKit/TUIChat/UI_Minimalist/Chat/TUIGroupChatViewController_Minimalist.m b/iOS/TUIKit/TUIChat/UI_Minimalist/Chat/TUIGroupChatViewController_Minimalist.m index b3280ea16..68b15e153 100644 --- a/iOS/TUIKit/TUIChat/UI_Minimalist/Chat/TUIGroupChatViewController_Minimalist.m +++ b/iOS/TUIKit/TUIChat/UI_Minimalist/Chat/TUIGroupChatViewController_Minimalist.m @@ -204,19 +204,12 @@ continue; } [self.atUserList addObject:model]; - if (i == 0) { - [atText appendString:[NSString stringWithFormat:@"%@ ", model.name]]; - } else { - [atText appendString:[NSString stringWithFormat:@"@%@ ", model.name]]; - } + [atText appendString:[NSString stringWithFormat:@"@%@ ", model.name]]; } UIFont *textFont = kTUIInputNoramlFont; NSAttributedString *spaceString = [[NSAttributedString alloc] initWithString:atText attributes:@{NSFontAttributeName : textFont}]; - [weakSelf.inputController.inputBar.inputTextView.textStorage - insertAttributedString:spaceString - atIndex:weakSelf.inputController.inputBar.inputTextView.textStorage.length]; - [weakSelf.inputController.inputBar updateTextViewFrame]; + [weakSelf.inputController.inputBar addWordsToInputBar:spaceString ]; }]; } } @@ -256,11 +249,7 @@ NSString *nameString = [NSString stringWithFormat:@"@%@ ", user.name]; UIFont *textFont = kTUIInputNoramlFont; NSAttributedString *spaceString = [[NSAttributedString alloc] initWithString:nameString attributes:@{NSFontAttributeName : textFont}]; - [self.inputController.inputBar.inputTextView.textStorage insertAttributedString:spaceString - atIndex:self.inputController.inputBar.inputTextView.textStorage.length]; - [self.inputController.inputBar.inputTextView becomeFirstResponder]; - self.inputController.inputBar.inputTextView.selectedRange = - NSMakeRange(spaceString.length + self.inputController.inputBar.inputTextView.textStorage.length, 0); + [self.inputController.inputBar addWordsToInputBar:spaceString ]; } } diff --git a/iOS/TUIKit/TUIChat/UI_Minimalist/Chat/TUIMediaView_Minimalist.m b/iOS/TUIKit/TUIChat/UI_Minimalist/Chat/TUIMediaView_Minimalist.m index 5a69e9144..57a562d70 100644 --- a/iOS/TUIKit/TUIChat/UI_Minimalist/Chat/TUIMediaView_Minimalist.m +++ b/iOS/TUIKit/TUIChat/UI_Minimalist/Chat/TUIMediaView_Minimalist.m @@ -49,7 +49,7 @@ self.mediaView.backgroundColor = [UIColor clearColor]; [self addSubview:self.mediaView]; - UICollectionViewFlowLayout *menuFlowLayout = [[UICollectionViewFlowLayout alloc] init]; + UICollectionViewFlowLayout *menuFlowLayout = [[TUICollectionRTLFitFlowLayout alloc] init]; menuFlowLayout.scrollDirection = UICollectionViewScrollDirectionHorizontal; menuFlowLayout.minimumLineSpacing = 0; menuFlowLayout.minimumInteritemSpacing = 0; diff --git a/iOS/TUIKit/TUIChat/UI_Minimalist/Chat/TUIMergeMessageListController_Minimalist.m b/iOS/TUIKit/TUIChat/UI_Minimalist/Chat/TUIMergeMessageListController_Minimalist.m index d49eab63e..ce1b5e266 100644 --- a/iOS/TUIKit/TUIChat/UI_Minimalist/Chat/TUIMergeMessageListController_Minimalist.m +++ b/iOS/TUIKit/TUIChat/UI_Minimalist/Chat/TUIMergeMessageListController_Minimalist.m @@ -165,8 +165,9 @@ self.tableView.contentInset = UIEdgeInsetsMake(5, 0, 0, 0); [self.messageCellConfig bindTableView:self.tableView]; - UIImage *image = TIMCommonDynamicImage(@"nav_back_img", [UIImage imageNamed:@"ic_back_white"]); + UIImage *image = TIMCommonDynamicImage(@"nav_back_img", [UIImage imageNamed:TIMCommonImagePath(@"nav_back")]); image = [image imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal]; + image = [image rtl_imageFlippedForRightToLeftLayoutDirection]; UIButton *backButton = [UIButton buttonWithType:UIButtonTypeCustom]; [backButton setImage:image forState:UIControlStateNormal]; [backButton addTarget:self action:@selector(back) forControlEvents:UIControlEventTouchUpInside]; diff --git a/iOS/TUIKit/TUIChat/UI_Minimalist/Chat/TUIMessageController_Minimalist.m b/iOS/TUIKit/TUIChat/UI_Minimalist/Chat/TUIMessageController_Minimalist.m index 4b5448ca4..5df5e6d1d 100644 --- a/iOS/TUIKit/TUIChat/UI_Minimalist/Chat/TUIMessageController_Minimalist.m +++ b/iOS/TUIKit/TUIChat/UI_Minimalist/Chat/TUIMessageController_Minimalist.m @@ -7,7 +7,6 @@ #import #import #import -#import "ReactiveObjC.h" #import "TUIBaseMessageController_Minimalist+ProtectedAPI.h" #import "TUIChatConfig.h" #import "TUIChatModifyMessageHelper.h" @@ -225,7 +224,7 @@ } - (void)loadLocateMessages:(BOOL)firstLoad { - if (!self.locateMessage) { + if (!self.locateMessage && self.locateGroupMessageSeq == 0) { return; } @weakify(self); @@ -420,7 +419,6 @@ } - (void)showReplyMessage:(TUIReplyMessageCell_Minimalist *)cell { - [UIApplication.sharedApplication.keyWindow endEditing:YES]; NSString *originMsgID = @""; NSString *msgAbstract = @""; if ([cell isKindOfClass:TUIReplyMessageCell_Minimalist.class]) { diff --git a/iOS/TUIKit/TUIChat/UI_Minimalist/Chat/TUIMessageMultiChooseView_Minimalist.m b/iOS/TUIKit/TUIChat/UI_Minimalist/Chat/TUIMessageMultiChooseView_Minimalist.m index 67f4f967b..febf2ad4c 100644 --- a/iOS/TUIKit/TUIChat/UI_Minimalist/Chat/TUIMessageMultiChooseView_Minimalist.m +++ b/iOS/TUIKit/TUIChat/UI_Minimalist/Chat/TUIMessageMultiChooseView_Minimalist.m @@ -11,6 +11,7 @@ #import #import #import +#import @interface TUIMessageMultiChooseView_Minimalist () @@ -78,6 +79,14 @@ self.selectedCountLabel.frame = CGRectMake((width - labelWidth) * 0.5, kScale390(14), labelWidth, kScale390(30)); self.bottomCancelButton.frame = CGRectMake((width - kScale390(50) - kScale390(23)), kScale390(14), kScale390((50)), kScale390(30)); } + if(isRTL()) { + for (UIView *subview in self.toolView.subviews) { + [subview resetFrameToFitRTL]; + } + for (UIView *subview in self.menuView.subviews) { + [subview resetFrameToFitRTL]; + } + } } #pragma mark - Views diff --git a/iOS/TUIKit/TUIChat/UI_Minimalist/Chat/TUIMessageReadViewController_Minimalist.m b/iOS/TUIKit/TUIChat/UI_Minimalist/Chat/TUIMessageReadViewController_Minimalist.m index 32b8ee9da..b1d758b57 100644 --- a/iOS/TUIKit/TUIChat/UI_Minimalist/Chat/TUIMessageReadViewController_Minimalist.m +++ b/iOS/TUIKit/TUIChat/UI_Minimalist/Chat/TUIMessageReadViewController_Minimalist.m @@ -16,8 +16,12 @@ #import "TUIMemberCell_Minimalist.h" #import "TUIMessageDataProvider.h" #import "TUIVideoMessageCellData.h" +#import "TUITextMessageCellData.h" +#import "TUIReplyMessageCellData.h" +#import "TUIVoiceMessageCellData.h" +#import "TUIMessageCellConfig_Minimalist.h" -@interface TUIMessageReadViewController_Minimalist () +@interface TUIMessageReadViewController_Minimalist () @property(nonatomic, strong) TUIMessageCellData *cellData; @property(nonatomic, assign) BOOL showReadStatusDisable; @@ -33,7 +37,7 @@ @property(nonatomic, copy) NSString *c2cReceiverName; @property(nonatomic, copy) NSString *c2cReceiverAvatarUrl; @property(nonatomic, strong) TUIMessageCell_Minimalist *alertView; - +@property(nonatomic, strong) TUIMessageCellConfig_Minimalist *messageCellConfig; @end @implementation TUIMessageReadViewController_Minimalist @@ -46,6 +50,8 @@ } [self setupViews]; // Do any additional setup after loading the view. + + [TUICore registerEvent:TUICore_TUIPluginNotify subKey:TUICore_TUIPluginNotify_DidChangePluginViewSubKey object:self]; } - (void)viewWillLayoutSubviews { @@ -56,6 +62,7 @@ - (void)viewWillAppear:(BOOL)animated { [super viewWillAppear:animated]; + [self updateRootMsg]; if (_viewWillShowHandler) { _viewWillShowHandler(_alertView); } @@ -100,7 +107,7 @@ - (void)layoutViews { float backViewTop = self.navigationController.navigationBar.mm_maxY; - + self.messageBackView.frame = CGRectMake(0, 0, self.view.bounds.size.width, kScale390(17)+ kScale390(24)+ kScale390(4)); self.tableView.mm_top(backViewTop).mm_left(0).mm_width(self.view.mm_w).mm_height(self.view.mm_h - _tableView.mm_y); } @@ -128,27 +135,33 @@ NSString *dateString = [formatter stringFromDate:self.cellData.innerMessage.timestamp]; dateLabel.text = dateString; dateLabel.font = [UIFont systemFontOfSize:kScale390(14)]; + dateLabel.textAlignment = isRTL()?NSTextAlignmentRight:NSTextAlignmentLeft; dateLabel.textColor = TUIChatDynamicColor(@"chat_message_read_name_date_text_color", @"#999999"); [dateLabel sizeToFit]; - dateLabel.frame = CGRectMake((self.view.frame.size.width - dateLabel.frame.size.width) * 0.5, kScale390(17), dateLabel.frame.size.width, kScale390(24)); + [dateLabel mas_makeConstraints:^(MASConstraintMaker *make) { + make.centerX.mas_equalTo(self.view); + make.top.mas_equalTo(kScale390(17)); + make.width.mas_equalTo(dateLabel.frame.size.width); + make.height.mas_equalTo(kScale390(24)); + }]; +} - _alertView = [[self.alertCellClass alloc] init]; - _alertView.userInteractionEnabled = NO; - [messageBackView addSubview:_alertView]; - - _alertView.translatesAutoresizingMaskIntoConstraints = NO; - [_alertView fillWithData:self.alertViewCellData]; - [_alertView notifyBottomContainerReadyOfData:nil]; - [_alertView layoutIfNeeded]; - if (self.alertViewCellData.direction == MsgDirectionIncoming) { - _alertView.frame = CGRectMake(kScale390(16), dateLabel.frame.origin.y + dateLabel.frame.size.height, _originFrame.size.width, _originFrame.size.height); - } else { - _alertView.frame = CGRectMake(self.view.bounds.size.width - _originFrame.size.width - kScale390(12), - dateLabel.frame.origin.y + dateLabel.frame.size.height, _originFrame.size.width, _originFrame.size.height); +- (void)updateRootMsg { + TUIMessageCellData *data = self.alertViewCellData; + TUIMessageCellLayout *layout = TUIMessageCellLayout.incommingMessageLayout; + if ([data isKindOfClass:TUITextMessageCellData.class]) { + layout = TUIMessageCellLayout.incommingTextMessageLayout; } - - messageBackView.mm_width(self.view.bounds.size.width); - messageBackView.mm_height(_alertView.frame.origin.y + _alertView.frame.size.height + kScale390(4)); + if ([data isKindOfClass:TUIReferenceMessageCellData.class]) { + layout = TUIMessageCellLayout.incommingTextMessageLayout; + } + if ([data isKindOfClass:TUIVoiceMessageCellData.class]) { + layout = [TUIMessageCellLayout incommingVoiceMessageLayout]; + } + self.alertViewCellData.cellLayout = layout; + self.alertViewCellData.direction = MsgDirectionIncoming; + self.alertViewCellData.showAvatar = NO; + self.alertViewCellData.showMessageModifyReplies = NO; } - (void)loadMembers { @@ -240,14 +253,29 @@ } - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView { - return 1; + return 2; } - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { + + if(section == 0){ + return 1; + } return [self members].count; } - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { + + if (indexPath.section == 0) { + TUIMessageCell *cell = nil; + TUIMessageCellData *data = self.alertViewCellData; + cell = [tableView dequeueReusableCellWithIdentifier:data.reuseId forIndexPath:indexPath]; + cell.delegate = self; + [cell fillWithData:data]; + [cell notifyBottomContainerReadyOfData:nil]; + return cell; + } + TUICommonCellData *data = [self members][indexPath.row]; TUICommonTableViewCell *cell = nil; @@ -261,6 +289,10 @@ return cell; } - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath { + if (indexPath.section == 0) { + return [self.messageCellConfig getHeightFromMessageCellData:self.cellData]; + } + TUICommonCellData *data = [self members][indexPath.row]; if ([data isKindOfClass:TUIMemberDescribeCellData.class]) { return kScale390(57); @@ -370,8 +402,35 @@ _tableView.separatorStyle = UITableViewCellSeparatorStyleNone; [_tableView registerClass:[TUIMemberCell_Minimalist class] forCellReuseIdentifier:kMemberCellReuseId]; [_tableView registerClass:[TUIMemberDescribeCell_Minimalist class] forCellReuseIdentifier:@"TUIMemberDescribeCell_Minimalist"]; + [self.messageCellConfig bindTableView:self.tableView]; } return _tableView; } +- (void)dataProvider:(TUIMessageBaseDataProvider *)dataProvider onRemoveHeightCache:(TUIMessageCellData *)cellData { + if (cellData) { + [self.messageCellConfig removeHeightCacheOfMessageCellData:cellData]; + } +} +- (TUIMessageCellConfig_Minimalist *)messageCellConfig { + if (_messageCellConfig == nil) { + _messageCellConfig = [[TUIMessageCellConfig_Minimalist alloc] init]; + } + return _messageCellConfig; +} + +#pragma mark - TUINotificationProtocol +- (void)onNotifyEvent:(NSString *)key subKey:(NSString *)subKey object:(id)anObject param:(NSDictionary *)param { + + if ([key isEqualToString:TUICore_TUIPluginNotify] && [subKey isEqualToString:TUICore_TUIPluginNotify_DidChangePluginViewSubKey]) { + // Translation View is Shown or content changed. + TUIMessageCellData *data = param[TUICore_TUIPluginNotify_DidChangePluginViewSubKey_Data]; + [self clearAndReloadCellOfData:data]; + } +} + +- (void)clearAndReloadCellOfData:(TUIMessageCellData *)data { + [self.messageCellConfig removeHeightCacheOfMessageCellData:data]; + [self.tableView reloadData]; +} @end diff --git a/iOS/TUIKit/TUIChat/UI_Minimalist/Chat/TUIRepliesDetailViewController_Minimalist.m b/iOS/TUIKit/TUIChat/UI_Minimalist/Chat/TUIRepliesDetailViewController_Minimalist.m index 663a52f8a..f2609f0c6 100644 --- a/iOS/TUIKit/TUIChat/UI_Minimalist/Chat/TUIRepliesDetailViewController_Minimalist.m +++ b/iOS/TUIKit/TUIChat/UI_Minimalist/Chat/TUIRepliesDetailViewController_Minimalist.m @@ -13,7 +13,7 @@ #import "TUIMessageDataProvider.h" #import "TUITextMessageCellData.h" #import "TUITextMessageCell_Minimalist.h" - +#import "TUIChatConfig.h" #import #import #import @@ -112,7 +112,7 @@ [self updateSubContainerView]; - [TUICore registerEvent:TUICore_TUITranslationNotify subKey:TUICore_TUITranslationNotify_DidChangeTranslationSubKey object:self]; + [TUICore registerEvent:TUICore_TUIPluginNotify subKey:TUICore_TUIPluginNotify_DidChangePluginViewSubKey object:self]; } - (void)updateSubContainerView { @@ -125,6 +125,9 @@ self.tableView.frame = CGRectMake(0, self.topGestureView.frame.size.height, self.containerView.frame.size.width, self.containerView.frame.size.height - self.topGestureView.frame.size.height); + if (isRTL()) { + [self.cancelButton resetFrameToFitRTL]; + } } - (void)viewWillAppear:(BOOL)animated { @@ -210,7 +213,8 @@ } - (void)updateTableViewConstraint { - CGFloat height = CGRectGetMaxY(self.inputController.inputBar.frame) + Bottom_SafeHeight; + CGFloat textViewHeight = TUIChatConfig.defaultConfig.enableMainPageInputBar? CGRectGetMaxY(self.inputController.inputBar.frame):0; + CGFloat height = textViewHeight + Bottom_SafeHeight; CGRect msgFrame = self.tableView.frame; msgFrame.size.height = self.view.frame.size.height - height; self.tableView.frame = msgFrame; @@ -704,8 +708,8 @@ #pragma mark - TUINotificationProtocol - (void)onNotifyEvent:(NSString *)key subKey:(NSString *)subKey object:(id)anObject param:(NSDictionary *)param { - if ([key isEqualToString:TUICore_TUITranslationNotify] && [subKey isEqualToString:TUICore_TUITranslationNotify_DidChangeTranslationSubKey]) { - TUIMessageCellData *data = param[TUICore_TUITranslationNotify_DidChangeTranslationSubKey_Data]; + if ([key isEqualToString:TUICore_TUIPluginNotify] && [subKey isEqualToString:TUICore_TUIPluginNotify_DidChangePluginViewSubKey]) { + TUIMessageCellData *data = param[TUICore_TUIPluginNotify_DidChangePluginViewSubKey_Data]; [self.messageCellConfig removeHeightCacheOfMessageCellData:data]; [self reloadAndScrollToBottomOfMessage:data.innerMessage.msgID section:1]; } diff --git a/iOS/TUIKit/TUIChat/UI_Minimalist/Input/TUIInputBar_Minimalist.h b/iOS/TUIKit/TUIChat/UI_Minimalist/Input/TUIInputBar_Minimalist.h index 19c798999..653c34f98 100644 --- a/iOS/TUIKit/TUIChat/UI_Minimalist/Input/TUIInputBar_Minimalist.h +++ b/iOS/TUIKit/TUIChat/UI_Minimalist/Input/TUIInputBar_Minimalist.h @@ -244,5 +244,7 @@ typedef NS_ENUM(NSInteger, TUIRecordStatus) { - (void)updateTextViewFrame; - (void)changeToKeyboard; +- (void)addDraftToInputBar:(NSAttributedString *)draft; +- (void)addWordsToInputBar:(NSAttributedString *)words; @end diff --git a/iOS/TUIKit/TUIChat/UI_Minimalist/Input/TUIInputBar_Minimalist.m b/iOS/TUIKit/TUIChat/UI_Minimalist/Input/TUIInputBar_Minimalist.m index 36e23c88b..b65da3693 100644 --- a/iOS/TUIKit/TUIChat/UI_Minimalist/Input/TUIInputBar_Minimalist.m +++ b/iOS/TUIKit/TUIChat/UI_Minimalist/Input/TUIInputBar_Minimalist.m @@ -68,7 +68,9 @@ [_inputTextView setFont:kTUIInputNoramlFont]; _inputTextView.backgroundColor = TUIChatDynamicColor(@"chat_input_bg_color", @"#FFFFFF"); _inputTextView.textColor = TUIChatDynamicColor(@"chat_input_text_color", @"#000000"); - _inputTextView.textContainerInset = UIEdgeInsetsMake(kScale390(9), kScale390(16), kScale390(9), kScale390(30)); + UIEdgeInsets ei = UIEdgeInsetsMake(kScale390(9), kScale390(16), kScale390(9), kScale390(30)); + _inputTextView.textContainerInset = rtlEdgeInsetsWithInsets(ei); + _inputTextView.textAlignment = isRTL()?NSTextAlignmentRight: NSTextAlignmentLeft; [_inputTextView setReturnKeyType:UIReturnKeySend]; [self addSubview:_inputTextView]; @@ -158,6 +160,9 @@ case TUIRecordStatus_Record: case TUIRecordStatus_Cancel: { _recordDeleteView.frame = CGRectMake(kScale390(16), _recordDeleteView.mm_y, 24, 24); + if (isRTL()){ + [_recordDeleteView resetFrameToFitRTL]; + } _recordDeleteView.image = [[TUIImageCache sharedInstance] getResourceFromCache:TUIChatImagePath_Minimalist(@"voice_record_delete")]; _recordBackgroudView.backgroundColor = RGBA(20, 122, 255, 1); _recordAnimateCoverView.backgroundColor = _recordBackgroudView.backgroundColor; @@ -173,6 +178,9 @@ } break; case TUIRecordStatus_Delete: { _recordDeleteView.frame = CGRectMake(0, _recordDeleteView.mm_y, 20, 24); + if (isRTL()){ + [_recordDeleteView resetFrameToFitRTL]; + } _recordDeleteView.image = [[TUIImageCache sharedInstance] getResourceFromCache:TUIChatImagePath_Minimalist(@"voice_record_delete_ready")]; _recordBackgroudView.backgroundColor = RGBA(255, 88, 76, 1); _recordAnimateCoverView.backgroundColor = _recordBackgroudView.backgroundColor; @@ -229,6 +237,15 @@ _recordAnimateCoverViewFrame = CGRectMake(animationStartX, animationY, animationCoverWidth, animationSize); _recordAnimateCoverView.frame = self.recordAnimateCoverViewFrame; [self applyBorderTheme]; + + if(isRTL()) { + for (UIView *subviews in self.subviews) { + [subviews resetFrameToFitRTL]; + } + for (UIView *subview in _recordView.subviews) { + [subview resetFrameToFitRTL]; + } + } } - (void)layoutButton:(CGFloat)height { @@ -479,6 +496,7 @@ if (self.delegate && [self.delegate respondsToSelector:@selector(inputBarDidInputAt:)]) { [self.delegate inputBarDidInputAt:self]; } + return NO; } return YES; } @@ -503,10 +521,8 @@ TUIEmojiTextAttachment *emojiTextAttachment = [[TUIEmojiTextAttachment alloc] init]; emojiTextAttachment.faceCellData = emoji; - NSString *localizableFaceName = emoji.localizableName.length ? emoji.localizableName : emoji.name; - // Set tag and image - emojiTextAttachment.emojiTag = localizableFaceName; + emojiTextAttachment.emojiTag = emoji.name; emojiTextAttachment.image = [[TUIImageCache sharedInstance] getFaceFromCache:emoji.path]; // Set emoji size @@ -542,6 +558,8 @@ [_inputTextView.textStorage addAttribute:NSFontAttributeName value:kTUIInputNoramlFont range:wholeRange]; [_inputTextView setFont:kTUIInputNoramlFont]; + _inputTextView.textAlignment = isRTL()?NSTextAlignmentRight: NSTextAlignmentLeft; + } - (void)backDelete { @@ -563,6 +581,24 @@ [self applyBorderTheme]; } +- (void)addDraftToInputBar:(NSAttributedString *)draft { + [self addWordsToInputBar:draft]; +} + +- (void)addWordsToInputBar:(NSAttributedString *)words { + NSRange selectedRange = self.inputTextView.selectedRange; + if (selectedRange.length > 0) { + [self.inputTextView.textStorage deleteCharactersInRange:selectedRange]; + } + // Insert words + [self.inputTextView.textStorage insertAttributedString:words atIndex:self.inputTextView.selectedRange.location]; + + self.inputTextView.selectedRange = NSMakeRange(self.inputTextView.textStorage.length + 1, 0); + + [self resetTextStyle]; + + [self updateTextViewFrame]; +} #pragma mark - TUIAudioRecorderDelegate - (void)audioRecorder:(TUIAudioRecorder *)recorder didCheckPermission:(BOOL)isGranted isFirstTime:(BOOL)isFirstTime { if (isFirstTime) { diff --git a/iOS/TUIKit/TUIChat/UI_Minimalist/Input/TUIMenuView_Minimalist.m b/iOS/TUIKit/TUIChat/UI_Minimalist/Input/TUIMenuView_Minimalist.m index 34b0b0321..3085220dd 100644 --- a/iOS/TUIKit/TUIChat/UI_Minimalist/Input/TUIMenuView_Minimalist.m +++ b/iOS/TUIKit/TUIChat/UI_Minimalist/Input/TUIMenuView_Minimalist.m @@ -45,7 +45,7 @@ [_sendButton addTarget:self action:@selector(sendUpInside:) forControlEvents:UIControlEventTouchUpInside]; [self addSubview:_sendButton]; - _menuFlowLayout = [[UICollectionViewFlowLayout alloc] init]; + _menuFlowLayout = [[TUICollectionRTLFitFlowLayout alloc] init]; _menuFlowLayout.scrollDirection = UICollectionViewScrollDirectionHorizontal; _menuFlowLayout.minimumLineSpacing = 0; _menuFlowLayout.minimumInteritemSpacing = 0; @@ -66,8 +66,19 @@ - (void)defaultLayout { CGFloat buttonWidth = self.frame.size.height * 1.3; - _sendButton.frame = CGRectMake(self.frame.size.width - buttonWidth, 0, buttonWidth, self.frame.size.height); - _menuCollectionView.frame = CGRectMake(16, 0, self.frame.size.width - 2 * buttonWidth, self.frame.size.height); + [_sendButton mas_remakeConstraints:^(MASConstraintMaker *make) { + make.trailing.mas_equalTo(self.mas_trailing); + make.width.mas_equalTo(buttonWidth); + make.height.mas_equalTo(self); + make.centerY.mas_equalTo(self); + }]; + [_menuCollectionView mas_remakeConstraints:^(MASConstraintMaker *make) { + make.leading.mas_equalTo(16); + make.trailing.mas_equalTo(_sendButton.mas_leading).mas_offset(- 30); + make.height.mas_equalTo(self); + make.centerY.mas_equalTo(self); + }]; + } - (void)sendUpInside:(UIButton *)sender { diff --git a/iOS/TUIKit/TUIChat/UI_Minimalist/Service/TUIChatObjectFactory_Minimalist.m b/iOS/TUIKit/TUIChat/UI_Minimalist/Service/TUIChatObjectFactory_Minimalist.m index b0df4a2c2..d2eca16e7 100644 --- a/iOS/TUIKit/TUIChat/UI_Minimalist/Service/TUIChatObjectFactory_Minimalist.m +++ b/iOS/TUIKit/TUIChat/UI_Minimalist/Service/TUIChatObjectFactory_Minimalist.m @@ -52,7 +52,10 @@ V2TIMMessage *locateMessage = [param tui_objectForKey:TUICore_TUIChatObjectFactory_ChatViewController_LocateMessage asClass:V2TIMMessage.class]; NSArray * atMsgSeqs = [param tui_objectForKey:TUICore_TUIChatObjectFactory_ChatViewController_AtMsgSeqs asClass:NSArray.class]; NSString *draft = [param tui_objectForKey:TUICore_TUIChatObjectFactory_ChatViewController_Draft asClass:NSString.class]; - + NSString *isEnableVideoInfoStr = [param tui_objectForKey:TUICore_TUIChatObjectFactory_ChatViewController_Enable_Video_Call asClass:NSString.class]; + NSString *isEnableAudioInfoStr = [param tui_objectForKey:TUICore_TUIChatObjectFactory_ChatViewController_Enable_Audio_Call asClass:NSString.class]; + NSString *isEnableRoomInfoStr = [param tui_objectForKey:TUICore_TUIChatObjectFactory_ChatViewController_Enable_Room asClass:NSString.class]; + TUIChatConversationModel *conversationModel = [[TUIChatConversationModel alloc] init]; conversationModel.title = title; conversationModel.userID = userID; @@ -63,6 +66,17 @@ conversationModel.atMsgSeqs = [NSMutableArray arrayWithArray:atMsgSeqs]; conversationModel.draftText = draft; + if ([isEnableVideoInfoStr isEqualToString:@"0"]) { + conversationModel.enabelVideo = NO; + } + + if ([isEnableAudioInfoStr isEqualToString:@"0"]) { + conversationModel.enabelAudio = NO; + } + if ([isEnableRoomInfoStr isEqualToString:@"0"]) { + conversationModel.enabelRoom = NO; + } + TUIBaseChatViewController_Minimalist *chatVC = nil; if (conversationModel.groupID.length > 0) { chatVC = [[TUIGroupChatViewController_Minimalist alloc] init]; diff --git a/iOS/TUIKit/TUIContact/BaseCell/CellUI/TUICommonContactCell.h b/iOS/TUIKit/TUIContact/BaseCell/CellUI/TUICommonContactCell.h index daa6642a7..8b101233a 100644 --- a/iOS/TUIKit/TUIContact/BaseCell/CellUI/TUICommonContactCell.h +++ b/iOS/TUIKit/TUIContact/BaseCell/CellUI/TUICommonContactCell.h @@ -1,6 +1,11 @@ - +// +// TUICommonContactCell.h +// +// // Created by Tencent on 2023/06/09. // Copyright © 2023 Tencent. All rights reserved. + + #import #import #import diff --git a/iOS/TUIKit/TUIContact/BaseCell/CellUI/TUICommonContactCell.m b/iOS/TUIKit/TUIContact/BaseCell/CellUI/TUICommonContactCell.m index d8e39eaed..859141765 100644 --- a/iOS/TUIKit/TUIContact/BaseCell/CellUI/TUICommonContactCell.m +++ b/iOS/TUIKit/TUIContact/BaseCell/CellUI/TUICommonContactCell.m @@ -26,27 +26,14 @@ self.contentView.backgroundColor = TIMCommonDynamicColor(@"form_bg_color", @"#FFFFFF"); self.avatarView = [[UIImageView alloc] initWithImage:DefaultAvatarImage]; [self.contentView addSubview:self.avatarView]; - self.avatarView.mm_width(34).mm_height(34).mm__centerY(28).mm_left(12); - if ([TUIConfig defaultConfig].avatarType == TAvatarTypeRounded) { - self.avatarView.layer.masksToBounds = YES; - self.avatarView.layer.cornerRadius = self.avatarView.frame.size.height / 2; - } else if ([TUIConfig defaultConfig].avatarType == TAvatarTypeRadiusCorner) { - self.avatarView.layer.masksToBounds = YES; - self.avatarView.layer.cornerRadius = [TUIConfig defaultConfig].avatarCornerRadius; - } self.titleLabel = [[UILabel alloc] initWithFrame:CGRectZero]; [self.contentView addSubview:self.titleLabel]; self.titleLabel.textColor = TIMCommonDynamicColor(@"form_title_color", @"#000000"); - self.titleLabel.mm_left(self.avatarView.mm_maxX + 12).mm_height(20).mm__centerY(self.avatarView.mm_centerY).mm_flexToRight(0); - + self.onlineStatusIcon = [[UIImageView alloc] init]; [self.contentView addSubview:self.onlineStatusIcon]; - self.onlineStatusIcon.mm_width(kScale * 15).mm_height(kScale * 15); - self.onlineStatusIcon.mm_x = CGRectGetMaxX(self.avatarView.frame) - 0.5 * self.onlineStatusIcon.mm_w - 3 * kScale; - self.onlineStatusIcon.mm_y = CGRectGetMaxY(self.avatarView.frame) - self.onlineStatusIcon.mm_w; - self.onlineStatusIcon.layer.cornerRadius = 0.5 * self.onlineStatusIcon.mm_w; - + [self setSelectionStyle:UITableViewCellSelectionStyleNone]; self.changeColorWhenTouched = YES; @@ -75,6 +62,53 @@ self.onlineStatusIcon.image = nil; } }]; + // tell constraints they need updating + [self setNeedsUpdateConstraints]; + + // update constraints now so we can animate the change + [self updateConstraintsIfNeeded]; + + [self layoutIfNeeded]; + +} + ++ (BOOL)requiresConstraintBasedLayout { + return YES; +} + +// this is Apple's recommended place for adding/updating constraints +- (void)updateConstraints { + + [super updateConstraints]; + CGFloat imgWidth = kScale390(34); + + [self.avatarView mas_remakeConstraints:^(MASConstraintMaker *make) { + make.width.height.mas_equalTo(imgWidth); + make.centerY.mas_equalTo(self.contentView.mas_centerY); + make.leading.mas_equalTo(kScale390(12)); + }]; + if ([TUIConfig defaultConfig].avatarType == TAvatarTypeRounded) { + self.avatarView.layer.masksToBounds = YES; + self.avatarView.layer.cornerRadius = imgWidth / 2; + } else if ([TUIConfig defaultConfig].avatarType == TAvatarTypeRadiusCorner) { + self.avatarView.layer.masksToBounds = YES; + self.avatarView.layer.cornerRadius = [TUIConfig defaultConfig].avatarCornerRadius; + } + + [self.titleLabel mas_remakeConstraints:^(MASConstraintMaker *make) { + make.centerY.mas_equalTo(self.avatarView.mas_centerY); + make.leading.mas_equalTo(self.avatarView.mas_trailing).mas_offset(12); + make.height.mas_equalTo(20); + make.trailing.mas_greaterThanOrEqualTo(self.contentView.mas_trailing); + + }]; + + [self.onlineStatusIcon mas_remakeConstraints:^(MASConstraintMaker *make) { + make.width.height.mas_equalTo(kScale375(15)); + make.trailing.mas_equalTo(self.avatarView.mas_trailing).mas_offset(kScale375(5)); + make.bottom.mas_equalTo(self.avatarView.mas_bottom); + }]; + self.onlineStatusIcon.layer.cornerRadius = 0.5 * kScale375(15); } @end diff --git a/iOS/TUIKit/TUIContact/BaseCell/CellUI/TUICommonContactProfileCardCell.h b/iOS/TUIKit/TUIContact/BaseCell/CellUI/TUICommonContactProfileCardCell.h index 4434a5dc2..f24073300 100644 --- a/iOS/TUIKit/TUIContact/BaseCell/CellUI/TUICommonContactProfileCardCell.h +++ b/iOS/TUIKit/TUIContact/BaseCell/CellUI/TUICommonContactProfileCardCell.h @@ -1,6 +1,10 @@ - +// +// TUICommonContactProfileCardCell.m +// +// // Created by Tencent on 2023/06/09. // Copyright © 2023 Tencent. All rights reserved. + #import #import #import diff --git a/iOS/TUIKit/TUIContact/BaseCell/CellUI/TUICommonContactProfileCardCell.m b/iOS/TUIKit/TUIContact/BaseCell/CellUI/TUICommonContactProfileCardCell.m index 0886e6500..28df286ad 100644 --- a/iOS/TUIKit/TUIContact/BaseCell/CellUI/TUICommonContactProfileCardCell.m +++ b/iOS/TUIKit/TUIContact/BaseCell/CellUI/TUICommonContactProfileCardCell.m @@ -54,13 +54,6 @@ [_avatar addGestureRecognizer:tapAvatar]; _avatar.userInteractionEnabled = YES; - if ([TUIConfig defaultConfig].avatarType == TAvatarTypeRounded) { - self.avatar.layer.masksToBounds = YES; - self.avatar.layer.cornerRadius = headSize.height / 2; - } else if ([TUIConfig defaultConfig].avatarType == TAvatarTypeRadiusCorner) { - self.avatar.layer.masksToBounds = YES; - self.avatar.layer.cornerRadius = [TUIConfig defaultConfig].avatarCornerRadius; - } [self.contentView addSubview:_avatar]; // CGSize genderIconSize = CGSizeMake(20, 20); @@ -125,34 +118,92 @@ } else { self.accessoryType = UITableViewCellAccessoryNone; } + + // tell constraints they need updating + [self setNeedsUpdateConstraints]; + + // update constraints now so we can animate the change + [self updateConstraintsIfNeeded]; + + [self layoutIfNeeded]; } -- (void)layoutSubviews { - [super layoutSubviews]; - // 此处解除 nameLabel 的 fit 宽度,使性别 icon 能够在短昵称情况下和 nameLabel 相邻。 - CGFloat maxLabelWidth = self.contentView.mm_w - CGRectGetMaxX(_avatar.frame) - 30; - _name.mm_sizeToFitThan(0, _avatar.mm_h / 3).mm_top(_avatar.mm_y).mm_left(_avatar.mm_maxX + TPersonalCommonCell_Margin); - if (CGRectGetMaxX(_name.frame) >= self.contentView.mm_w) { - _name.mm_w = maxLabelWidth; - } ++ (BOOL)requiresConstraintBasedLayout { + return YES; +} - _identifier.mm_sizeToFitThan(80, _avatar.mm_h / 3).mm_left(_name.mm_x); +// this is Apple's recommended place for adding/updating constraints +- (void)updateConstraints { + + [super updateConstraints]; + CGSize headSize = TPersonalCommonCell_Image_Size; + + [self.avatar mas_remakeConstraints:^(MASConstraintMaker *make) { + make.size.mas_equalTo(headSize); + make.top.mas_equalTo(TPersonalCommonCell_Margin); + make.leading.mas_equalTo(TPersonalCommonCell_Margin); + }]; + + if ([TUIConfig defaultConfig].avatarType == TAvatarTypeRounded) { + self.avatar.layer.masksToBounds = YES; + self.avatar.layer.cornerRadius = headSize.height / 2; + } else if ([TUIConfig defaultConfig].avatarType == TAvatarTypeRadiusCorner) { + self.avatar.layer.masksToBounds = YES; + self.avatar.layer.cornerRadius = [TUIConfig defaultConfig].avatarCornerRadius; + } + + [self.name sizeToFit]; + [self.name mas_remakeConstraints:^(MASConstraintMaker *make) { + make.top.mas_equalTo(TPersonalCommonCell_Margin); + make.leading.mas_equalTo(self.avatar.mas_trailing).mas_offset(15); + make.width.mas_lessThanOrEqualTo(self.name.frame.size.width); + make.height.mas_greaterThanOrEqualTo(self.name.frame.size.height); + make.trailing.mas_lessThanOrEqualTo(self.genderIcon.mas_leading).mas_offset(- 1); + }]; + + [self.genderIcon mas_remakeConstraints:^(MASConstraintMaker *make) { + make.width.height.mas_equalTo(self.name.font.pointSize *0.9); + make.centerY.mas_equalTo(self.name); + make.leading.mas_equalTo(self.name.mas_trailing).mas_offset(1); + make.trailing.mas_lessThanOrEqualTo(self.contentView.mas_trailing).mas_offset(- 10); + }]; + + [self.identifier sizeToFit]; + [self.identifier mas_remakeConstraints:^(MASConstraintMaker *make) { + make.leading.mas_equalTo(self.name); + make.top.mas_equalTo(self.name.mas_bottom).mas_offset(5); + if(self.identifier.frame.size.width > 80) { + make.width.mas_greaterThanOrEqualTo(self.identifier.frame.size.width); + } + else { + make.width.mas_greaterThanOrEqualTo(@80); + } + make.height.mas_greaterThanOrEqualTo(self.identifier.frame.size.height); + make.trailing.mas_lessThanOrEqualTo(self.contentView.mas_trailing).mas_offset(-1); + }]; if (self.cardData.showSignature) { - _identifier.mm_y = _name.mm_y + _name.mm_h + 5; + [self.signature sizeToFit]; + [self.signature mas_remakeConstraints:^(MASConstraintMaker *make) { + make.leading.mas_equalTo(self.name); + make.top.mas_equalTo(self.identifier.mas_bottom).mas_offset(5); + if(self.signature.frame.size.width > 80) { + make.width.mas_greaterThanOrEqualTo(self.signature.frame.size.width); + } + else { + make.width.mas_greaterThanOrEqualTo(@80); + } + make.height.mas_greaterThanOrEqualTo(self.signature.frame.size.height); + make.trailing.mas_lessThanOrEqualTo(self.contentView.mas_trailing).mas_offset(-1); + }]; + } else { - _identifier.mm_bottom(_avatar.mm_b); + self.signature.frame = CGRectZero; } - _signature.mm_sizeToFitThan(80, _avatar.mm_h / 3).mm_left(_name.mm_x); - _signature.mm_y = CGRectGetMaxY(_identifier.frame) + 5; - if (CGRectGetMaxX(_signature.frame) >= self.contentView.mm_w) { - _signature.mm_w = maxLabelWidth; - } - - _genderIcon.mm_sizeToFitThan(_name.font.pointSize * 0.9, _name.font.pointSize * 0.9) - .mm__centerY(_name.mm_centerY) - .mm_left(_name.mm_x + _name.mm_w + TPersonalCommonCell_Margin); +} +- (void)layoutSubviews { + [super layoutSubviews]; } - (void)onTapAvatar { diff --git a/iOS/TUIKit/TUIContact/BaseCell/CellUI/TUICommonContactSelectCell.h b/iOS/TUIKit/TUIContact/BaseCell/CellUI/TUICommonContactSelectCell.h index 79019f219..97a1eb9c1 100644 --- a/iOS/TUIKit/TUIContact/BaseCell/CellUI/TUICommonContactSelectCell.h +++ b/iOS/TUIKit/TUIContact/BaseCell/CellUI/TUICommonContactSelectCell.h @@ -1,4 +1,7 @@ - +// +// TUICommonContactSelectCell.h +// +// // Created by Tencent on 2023/06/09. // Copyright © 2023 Tencent. All rights reserved. diff --git a/iOS/TUIKit/TUIContact/BaseCell/CellUI/TUICommonContactSelectCell.m b/iOS/TUIKit/TUIContact/BaseCell/CellUI/TUICommonContactSelectCell.m index c7c4bdab8..28cf82168 100644 --- a/iOS/TUIKit/TUIContact/BaseCell/CellUI/TUICommonContactSelectCell.m +++ b/iOS/TUIKit/TUIContact/BaseCell/CellUI/TUICommonContactSelectCell.m @@ -1,4 +1,7 @@ - +// +// TUICommonContactSelectCell.m +// +// // Created by Tencent on 2023/06/09. // Copyright © 2023 Tencent. All rights reserved. @@ -32,18 +35,15 @@ [self.selectButton setImage:[UIImage imageNamed:TIMCommonImagePath(@"icon_select_pressed")] forState:UIControlStateHighlighted]; [self.selectButton setImage:[UIImage imageNamed:TIMCommonImagePath(@"icon_select_selected")] forState:UIControlStateSelected]; [self.selectButton setImage:[UIImage imageNamed:TIMCommonImagePath(@"icon_select_selected_disable")] forState:UIControlStateDisabled]; - self.selectButton.mm_sizeToFit().mm__centerY(self.mm_centerY).mm_left(12); self.selectButton.autoresizingMask = UIViewAutoresizingFlexibleTopMargin | UIViewAutoresizingFlexibleBottomMargin; self.avatarView = [[UIImageView alloc] initWithImage:DefaultAvatarImage]; [self.contentView addSubview:self.avatarView]; - self.avatarView.mm_width(34).mm_height(34).mm__centerY(self.mm_centerY).mm_left(self.selectButton.mm_maxX + 12); self.avatarView.autoresizingMask = UIViewAutoresizingFlexibleTopMargin | UIViewAutoresizingFlexibleBottomMargin; self.titleLabel = [[UILabel alloc] initWithFrame:CGRectZero]; [self.contentView addSubview:self.titleLabel]; self.titleLabel.textColor = TIMCommonDynamicColor(@"form_title_color", @"#000000"); - self.titleLabel.mm_left(self.avatarView.mm_maxX + 12).mm_height(20).mm__centerY(self.avatarView.mm_centerY).mm_flexToRight(0); self.titleLabel.autoresizingMask = UIViewAutoresizingFlexibleTopMargin | UIViewAutoresizingFlexibleBottomMargin; self.selectionStyle = UITableViewCellSelectionStyleNone; @@ -51,9 +51,6 @@ return self; } -- (void)setupBinds { -} - - (void)fillWithData:(TUICommonContactSelectCellData *)selectData { [super fillWithData:selectData]; self.selectData = selectData; @@ -74,6 +71,50 @@ } [self.selectButton setSelected:selectData.isSelected]; self.selectButton.enabled = selectData.enabled; + + // tell constraints they need updating + [self setNeedsUpdateConstraints]; + + // update constraints now so we can animate the change + [self updateConstraintsIfNeeded]; + + [self layoutIfNeeded]; } ++ (BOOL)requiresConstraintBasedLayout { + return YES; +} + +// this is Apple's recommended place for adding/updating constraints +- (void)updateConstraints { + + [super updateConstraints]; + CGFloat imgWidth = kScale390(34); + + [self.avatarView mas_remakeConstraints:^(MASConstraintMaker *make) { + make.width.height.mas_equalTo(imgWidth); + make.centerY.mas_equalTo(self.contentView.mas_centerY); + make.leading.mas_equalTo(kScale390(12)); + }]; + if ([TUIConfig defaultConfig].avatarType == TAvatarTypeRounded) { + self.avatarView.layer.masksToBounds = YES; + self.avatarView.layer.cornerRadius = imgWidth / 2; + } else if ([TUIConfig defaultConfig].avatarType == TAvatarTypeRadiusCorner) { + self.avatarView.layer.masksToBounds = YES; + self.avatarView.layer.cornerRadius = [TUIConfig defaultConfig].avatarCornerRadius; + } + + [self.titleLabel mas_remakeConstraints:^(MASConstraintMaker *make) { + make.centerY.mas_equalTo(self.avatarView.mas_centerY); + make.leading.mas_equalTo(self.avatarView.mas_trailing).mas_offset(12); + make.height.mas_equalTo(20); + make.trailing.mas_greaterThanOrEqualTo(self.contentView.mas_trailing); + }]; + + [self.selectButton mas_remakeConstraints:^(MASConstraintMaker *make) { + make.centerY.mas_equalTo(self.contentView.mas_centerY); + make.trailing.mas_equalTo(self.contentView.mas_trailing).mas_offset(-kScale390(20)); + make.width.height.mas_equalTo(20); + }]; +} @end diff --git a/iOS/TUIKit/TUIContact/BaseCell/CellUI/TUICommonContactSwitchCell.m b/iOS/TUIKit/TUIContact/BaseCell/CellUI/TUICommonContactSwitchCell.m index 9834b4bff..c39d3dc9d 100644 --- a/iOS/TUIKit/TUIContact/BaseCell/CellUI/TUICommonContactSwitchCell.m +++ b/iOS/TUIKit/TUIContact/BaseCell/CellUI/TUICommonContactSwitchCell.m @@ -48,14 +48,14 @@ _titleLabel = [[UILabel alloc] init]; _titleLabel.textColor = TIMCommonDynamicColor(@"form_key_text_color", @"#444444"); _titleLabel.font = [UIFont systemFontOfSize:16]; - _titleLabel.textAlignment = NSTextAlignmentLeft; + _titleLabel.rtlAlignment = TUITextRTLAlignmentLeading; [self.contentView addSubview:_titleLabel]; _descLabel = [[UILabel alloc] init]; _descLabel.textColor = TIMCommonDynamicColor(@"group_modify_desc_color", @"#888888"); _descLabel.font = [UIFont systemFontOfSize:12]; _descLabel.numberOfLines = 0; - _descLabel.textAlignment = NSTextAlignmentLeft; + _descLabel.rtlAlignment = TUITextRTLAlignmentLeading; _descLabel.hidden = YES; [self.contentView addSubview:_descLabel]; @@ -73,16 +73,30 @@ - (void)fillWithData:(TUICommonContactSwitchCellData *)switchData { [super fillWithData:switchData]; - self.switchData = switchData; _titleLabel.text = switchData.title; [_switcher setOn:switchData.isOn]; + // tell constraints they need updating + [self setNeedsUpdateConstraints]; - if (switchData.desc.length > 0) { - _descLabel.text = switchData.desc; + // update constraints now so we can animate the change + [self updateConstraintsIfNeeded]; + + [self layoutIfNeeded]; +} ++ (BOOL)requiresConstraintBasedLayout { + return YES; +} + +// this is Apple's recommended place for adding/updating constraints +- (void)updateConstraints { + + [super updateConstraints]; + if (self.switchData.desc.length > 0) { + _descLabel.text = self.switchData.desc; _descLabel.hidden = NO; - NSString *str = switchData.desc; + NSString *str = self.switchData.desc; NSDictionary *attribute = @{NSFontAttributeName : [UIFont systemFontOfSize:12]}; CGSize size = [str boundingRectWithSize:CGSizeMake(264, 999) options:NSStringDrawingTruncatesLastVisibleLine | NSStringDrawingUsesLineFragmentOrigin | NSStringDrawingUsesFontLeading @@ -90,11 +104,27 @@ context:nil] .size; - _titleLabel.mm_width(size.width).mm_height(24).mm_left(switchData.margin).mm_top(12); - _descLabel.mm_width(size.width).mm_height(size.height).mm_left(_titleLabel.mm_x).mm_top(self.titleLabel.mm_maxY + 2); + [self.titleLabel mas_remakeConstraints:^(MASConstraintMaker *make) { + make.width.mas_equalTo(size.width); + make.height.mas_equalTo(24); + make.leading.mas_equalTo(self.switchData.margin); + make.top.mas_equalTo(12); + }]; + [self.descLabel mas_remakeConstraints:^(MASConstraintMaker *make) { + make.width.mas_equalTo(size.width); + make.height.mas_equalTo(size.height); + make.leading.mas_equalTo(self.titleLabel.mas_leading); + make.top.mas_equalTo(self.titleLabel.mas_bottom).mas_offset(2); + }]; } else { - _titleLabel.mm_sizeToFit().mm_left(switchData.margin).mm__centerY(self.contentView.mm_h / 2); + [self.titleLabel sizeToFit]; + [self.titleLabel mas_remakeConstraints:^(MASConstraintMaker *make) { + make.size.mas_equalTo(self.titleLabel.frame.size); + make.leading.mas_equalTo(self.switchData.margin); + make.centerY.mas_equalTo(self.contentView); + }]; } + } - (void)switchClick { diff --git a/iOS/TUIKit/TUIContact/BaseCell/CellUI/TUICommonContactTextCell.m b/iOS/TUIKit/TUIContact/BaseCell/CellUI/TUICommonContactTextCell.m index 67e9d9aa6..d4fef4ad8 100644 --- a/iOS/TUIKit/TUIContact/BaseCell/CellUI/TUICommonContactTextCell.m +++ b/iOS/TUIKit/TUIContact/BaseCell/CellUI/TUICommonContactTextCell.m @@ -45,38 +45,24 @@ self.backgroundColor = TIMCommonDynamicColor(@"form_bg_color", @"#FFFFFF"); self.contentView.backgroundColor = TIMCommonDynamicColor(@"form_bg_color", @"#FFFFFF"); - _keyLabel = self.textLabel; + _keyLabel = [[UILabel alloc] init]; _keyLabel.textColor = TIMCommonDynamicColor(@"form_key_text_color", @"#444444"); _keyLabel.font = [UIFont systemFontOfSize:16.0]; + [self.contentView addSubview:_keyLabel]; + [_keyLabel setRtlAlignment:TUITextRTLAlignmentTrailing]; + + _valueLabel = [[UILabel alloc] init]; + [self.contentView addSubview:_valueLabel]; - _valueLabel = self.detailTextLabel; _valueLabel.textColor = TIMCommonDynamicColor(@"form_value_text_color", @"#000000"); _valueLabel.font = [UIFont systemFontOfSize:16.0]; + [_valueLabel setRtlAlignment:TUITextRTLAlignmentTrailing]; self.selectionStyle = UITableViewCellSelectionStyleNone; } return self; } -- (void)layoutSubviews { - [super layoutSubviews]; - - if (self.textData.keyEdgeInsets.left) { - self.keyLabel.mm_left(self.textData.keyEdgeInsets.left); - } - - if (self.textData.keyEdgeInsets.top) { - self.keyLabel.mm_top(self.textData.keyEdgeInsets.top); - } - - if (self.textData.keyEdgeInsets.bottom) { - self.keyLabel.mm_bottom(self.textData.keyEdgeInsets.bottom); - } - - if (self.textData.keyEdgeInsets.right) { - self.keyLabel.mm_right(self.textData.keyEdgeInsets.right); - } -} - (void)fillWithData:(TUICommonContactTextCellData *)textData { [super fillWithData:textData]; @@ -104,6 +90,43 @@ } else { self.valueLabel.numberOfLines = 1; } + // tell constraints they need updating + [self setNeedsUpdateConstraints]; + + // update constraints now so we can animate the change + [self updateConstraintsIfNeeded]; + + [self layoutIfNeeded]; +} + ++ (BOOL)requiresConstraintBasedLayout { + return YES; +} + +// this is Apple's recommended place for adding/updating constraints +- (void)updateConstraints { + [super updateConstraints]; + + [self.keyLabel sizeToFit]; + [self.keyLabel mas_remakeConstraints:^(MASConstraintMaker *make) { + make.size.mas_equalTo(self.keyLabel.frame.size); + make.leading.mas_equalTo(self.contentView).mas_offset(self.textData.keyEdgeInsets.left); + make.centerY.mas_equalTo(self.contentView); + }]; + + + [self.valueLabel sizeToFit]; + [self.valueLabel mas_remakeConstraints:^(MASConstraintMaker *make) { + make.leading.mas_equalTo(self.keyLabel.mas_trailing).mas_offset(10); + if (self.textData.showAccessory) { + make.trailing.mas_equalTo(self.contentView.mas_trailing).mas_offset(-10); + } + else { + make.trailing.mas_equalTo(self.contentView.mas_trailing).mas_offset(-20); + } + make.centerY.mas_equalTo(self.contentView); + }]; + } @end diff --git a/iOS/TUIKit/TUIContact/BaseCell/CellUI/TUICommonPendencyCell.m b/iOS/TUIKit/TUIContact/BaseCell/CellUI/TUICommonPendencyCell.m index 142268087..5225ed190 100644 --- a/iOS/TUIKit/TUIContact/BaseCell/CellUI/TUICommonPendencyCell.m +++ b/iOS/TUIKit/TUIContact/BaseCell/CellUI/TUICommonPendencyCell.m @@ -16,31 +16,20 @@ if (self = [super initWithStyle:style reuseIdentifier:reuseIdentifier]) { self.avatarView = [[UIImageView alloc] initWithImage:DefaultAvatarImage]; [self.contentView addSubview:self.avatarView]; - self.avatarView.mm_width(70).mm_height(70).mm__centerY(43).mm_left(12); - if ([TUIConfig defaultConfig].avatarType == TAvatarTypeRounded) { - self.avatarView.layer.masksToBounds = YES; - self.avatarView.layer.cornerRadius = self.avatarView.frame.size.height / 2; - } else if ([TUIConfig defaultConfig].avatarType == TAvatarTypeRadiusCorner) { - self.avatarView.layer.masksToBounds = YES; - self.avatarView.layer.cornerRadius = [TUIConfig defaultConfig].avatarCornerRadius; - } self.titleLabel = [[UILabel alloc] initWithFrame:CGRectZero]; [self.contentView addSubview:self.titleLabel]; self.titleLabel.textColor = TIMCommonDynamicColor(@"form_title_color", @"#000000"); - self.titleLabel.mm_left(self.avatarView.mm_maxX + 12).mm_top(14).mm_height(20).mm_width(120); self.addSourceLabel = [[UILabel alloc] initWithFrame:CGRectZero]; [self.contentView addSubview:self.addSourceLabel]; self.addSourceLabel.textColor = [UIColor d_systemGrayColor]; self.addSourceLabel.font = [UIFont systemFontOfSize:15]; - self.addSourceLabel.mm_left(self.titleLabel.mm_x).mm_top(self.titleLabel.mm_maxY + 6).mm_height(15).mm_width(120); self.addWordingLabel = [[UILabel alloc] initWithFrame:CGRectZero]; [self.contentView addSubview:self.addWordingLabel]; self.addWordingLabel.textColor = [UIColor d_systemGrayColor]; self.addWordingLabel.font = [UIFont systemFontOfSize:15]; - self.addWordingLabel.mm_left(self.addSourceLabel.mm_x).mm_top(self.addSourceLabel.mm_maxY + 6).mm_height(15).mm_width(120); self.agreeButton = [UIButton buttonWithType:UIButtonTypeSystem]; [self.agreeButton setTitleColor:TIMCommonDynamicColor(@"form_title_color", @"#000000") forState:UIControlStateNormal]; @@ -111,11 +100,6 @@ self.rejectButton.layer.borderWidth = 0.2; [self.rejectButton setTitleColor:TIMCommonDynamicColor(@"primary_theme_color", @"#147AFF") forState:UIControlStateNormal]; } - - self.agreeButton.mm_sizeToFit().mm_width(self.agreeButton.mm_w + 20); - self.rejectButton.mm_left(CGRectGetMaxX(self.agreeButton.frame) + 10).mm_sizeToFit().mm_width(self.rejectButton.mm_w + 20); - self.stackView.bounds = CGRectMake(0, 0, 2 * self.agreeButton.mm_w + 10, self.agreeButton.mm_h); - if (self.pendencyData.isRejected && !self.pendencyData.isAccepted) { self.agreeButton.hidden = YES; self.rejectButton.hidden = NO; @@ -128,8 +112,75 @@ } self.addSourceLabel.hidden = self.pendencyData.hideSource; + // tell constraints they need updating + [self setNeedsUpdateConstraints]; + + // update constraints now so we can animate the change + [self updateConstraintsIfNeeded]; + + [self layoutIfNeeded]; +} ++ (BOOL)requiresConstraintBasedLayout { + return YES; } +// this is Apple's recommended place for adding/updating constraints +- (void)updateConstraints { + + [super updateConstraints]; + CGSize headSize = CGSizeMake(70, 70); + + [self.avatarView mas_remakeConstraints:^(MASConstraintMaker *make) { + make.size.mas_equalTo(headSize); + make.leading.mas_equalTo(12); + make.centerY.mas_equalTo(self.contentView); + }]; + + if ([TUIConfig defaultConfig].avatarType == TAvatarTypeRounded) { + self.avatarView.layer.masksToBounds = YES; + self.avatarView.layer.cornerRadius = headSize.height / 2; + } else if ([TUIConfig defaultConfig].avatarType == TAvatarTypeRadiusCorner) { + self.avatarView.layer.masksToBounds = YES; + self.avatarView.layer.cornerRadius = [TUIConfig defaultConfig].avatarCornerRadius; + } + + [self.titleLabel mas_remakeConstraints:^(MASConstraintMaker *make) { + make.top.mas_equalTo(self.contentView.mas_top).mas_offset(14); + make.leading.mas_equalTo(self.avatarView.mas_trailing).mas_offset(12); + make.height.mas_equalTo(20); + make.width.mas_equalTo(120); + }]; + + [self.addSourceLabel mas_remakeConstraints:^(MASConstraintMaker *make) { + make.top.mas_equalTo(self.titleLabel.mas_bottom).mas_offset(6); + make.leading.mas_equalTo(self.titleLabel.mas_leading); + make.height.mas_equalTo(15); + make.width.mas_equalTo(120); + }]; + + [self.addWordingLabel mas_remakeConstraints:^(MASConstraintMaker *make) { + make.top.mas_equalTo(self.addSourceLabel.mas_bottom).mas_offset(6); + make.leading.mas_equalTo(self.titleLabel.mas_leading); + make.height.mas_equalTo(15); + make.width.mas_equalTo(120); + }]; + + [self.agreeButton sizeToFit]; + [self.agreeButton mas_remakeConstraints:^(MASConstraintMaker *make) { + make.leading.mas_equalTo(self.stackView.mas_leading); + make.centerY.mas_equalTo(self.stackView); + make.height.mas_equalTo(self.agreeButton.frame.size.height); + make.width.mas_equalTo(self.agreeButton.frame.size.width + 20); + }]; + [self.rejectButton sizeToFit]; + [self.rejectButton mas_remakeConstraints:^(MASConstraintMaker *make) { + make.leading.mas_equalTo(self.agreeButton.mas_trailing).mas_offset(10); + make.height.mas_equalTo(self.rejectButton.frame.size.height); + make.width.mas_equalTo(self.rejectButton.frame.size.width + 20); + }]; + self.stackView.bounds = CGRectMake(0, 0, 3 * self.agreeButton.mm_w + 10, self.agreeButton.mm_h); + +} - (void)agreeClick { if (self.pendencyData.cbuttonSelector) { UIViewController *vc = self.mm_viewController; diff --git a/iOS/TUIKit/TUIContact/BaseCell/CellUI/TUIContactActionCell.m b/iOS/TUIKit/TUIContact/BaseCell/CellUI/TUIContactActionCell.m index e196b7143..ad37da4bb 100644 --- a/iOS/TUIKit/TUIContact/BaseCell/CellUI/TUIContactActionCell.m +++ b/iOS/TUIKit/TUIContact/BaseCell/CellUI/TUIContactActionCell.m @@ -23,20 +23,11 @@ if (self) { self.avatarView = [[UIImageView alloc] initWithImage:DefaultAvatarImage]; [self.contentView addSubview:self.avatarView]; - self.avatarView.mm_width(34).mm_height(34).mm__centerY(28).mm_left(12); - if ([TUIConfig defaultConfig].avatarType == TAvatarTypeRounded) { - self.avatarView.layer.masksToBounds = YES; - self.avatarView.layer.cornerRadius = self.avatarView.frame.size.height / 2; - } else if ([TUIConfig defaultConfig].avatarType == TAvatarTypeRadiusCorner) { - self.avatarView.layer.masksToBounds = YES; - self.avatarView.layer.cornerRadius = [TUIConfig defaultConfig].avatarCornerRadius; - } self.titleLabel = [[UILabel alloc] initWithFrame:CGRectZero]; [self.contentView addSubview:self.titleLabel]; self.titleLabel.textColor = TIMCommonDynamicColor(@"form_title_color", @"#000000"); - self.titleLabel.mm_left(self.avatarView.mm_maxX + 12).mm_height(20).mm__centerY(self.avatarView.mm_centerY).mm_flexToRight(0); - + self.unRead = [[TUIUnReadView alloc] init]; [self.contentView addSubview:self.unRead]; @@ -61,7 +52,56 @@ [self.unRead setNum:[x integerValue]]; }]; - self.unRead.mm__centerY(self.avatarView.mm_centerY).mm_right(self.accessoryView.mm_w); + // tell constraints they need updating + [self setNeedsUpdateConstraints]; + + // update constraints now so we can animate the change + [self updateConstraintsIfNeeded]; + + [self layoutIfNeeded]; +} ++ (BOOL)requiresConstraintBasedLayout { + return YES; +} + +// this is Apple's recommended place for adding/updating constraints +- (void)updateConstraints { + + [super updateConstraints]; + CGFloat imgWidth = kScale390(34); + [self.avatarView mas_remakeConstraints:^(MASConstraintMaker *make) { + make.width.height.mas_equalTo(imgWidth); + make.centerY.mas_equalTo(self.contentView.mas_centerY); + make.leading.mas_equalTo(kScale390(12)); + }]; + if ([TUIConfig defaultConfig].avatarType == TAvatarTypeRounded) { + self.avatarView.layer.masksToBounds = YES; + self.avatarView.layer.cornerRadius = imgWidth / 2; + } else if ([TUIConfig defaultConfig].avatarType == TAvatarTypeRadiusCorner) { + self.avatarView.layer.masksToBounds = YES; + self.avatarView.layer.cornerRadius = [TUIConfig defaultConfig].avatarCornerRadius; + } + + [self.titleLabel mas_remakeConstraints:^(MASConstraintMaker *make) { + make.centerY.mas_equalTo(self.avatarView.mas_centerY); + make.leading.mas_equalTo(self.avatarView.mas_trailing).mas_offset(12); + make.height.mas_equalTo(20); + make.trailing.mas_lessThanOrEqualTo(self.contentView.mas_trailing); + }]; + + [self.unRead.unReadLabel sizeToFit]; + [self.unRead mas_remakeConstraints:^(MASConstraintMaker *make) { + make.centerY.mas_equalTo(self.avatarView.mas_centerY); + make.trailing.mas_equalTo(self.contentView.mas_trailing).mas_offset(-5); + make.width.mas_equalTo(kScale375(20)); + make.height.mas_equalTo(kScale375(20)); + }]; + [self.unRead.unReadLabel mas_remakeConstraints:^(MASConstraintMaker *make) { + make.center.mas_equalTo(self.unRead); + make.size.mas_equalTo(self.unRead.unReadLabel); + }]; + self.unRead.layer.cornerRadius = kScale375(10); + [self.unRead.layer masksToBounds]; } @end diff --git a/iOS/TUIKit/TUIContact/BaseCell/CellUI/TUIFindContactCell.m b/iOS/TUIKit/TUIContact/BaseCell/CellUI/TUIFindContactCell.m index d6408f245..49549ce0a 100644 --- a/iOS/TUIKit/TUIContact/BaseCell/CellUI/TUIFindContactCell.m +++ b/iOS/TUIKit/TUIContact/BaseCell/CellUI/TUIFindContactCell.m @@ -38,34 +38,62 @@ [self.avatarView sd_setImageWithURL:data.avatarUrl placeholderImage:data.avatar ?: placeHolder]; self.descLabel.hidden = (data.type == TUIFindContactTypeC2C); + + // tell constraints they need updating + [self setNeedsUpdateConstraints]; + + // update constraints now so we can animate the change + [self updateConstraintsIfNeeded]; + + [self layoutIfNeeded]; } -- (void)layoutSubviews { - [super layoutSubviews]; ++ (BOOL)requiresConstraintBasedLayout { + return YES; +} - self.avatarView.mm_left(16 * kScale).mm_top(12 * kScale).mm_width(48 * kScale).mm_height(48 * kScale); +// this is Apple's recommended place for adding/updating constraints +- (void)updateConstraints { + + [super updateConstraints]; + + CGFloat imgWidth = kScale390(48); + [self.avatarView mas_remakeConstraints:^(MASConstraintMaker *make) { + make.width.height.mas_equalTo(imgWidth); + make.top.mas_equalTo(kScale390(10)); + make.leading.mas_equalTo(kScale390(16)); + }]; if ([TUIConfig defaultConfig].avatarType == TAvatarTypeRounded) { self.avatarView.layer.masksToBounds = YES; - self.avatarView.layer.cornerRadius = self.avatarView.frame.size.height / 2; + self.avatarView.layer.cornerRadius = imgWidth / 2; } else if ([TUIConfig defaultConfig].avatarType == TAvatarTypeRadiusCorner) { self.avatarView.layer.masksToBounds = YES; self.avatarView.layer.cornerRadius = [TUIConfig defaultConfig].avatarCornerRadius; } - - self.mainTitleLabel.mm_sizeToFit(); - self.mainTitleLabel.mm_x = CGRectGetMaxX(self.avatarView.frame) + 12 * kScale; - self.mainTitleLabel.mm_y = self.avatarView.mm_y; - self.mainTitleLabel.mm_flexToRight(12 * kScale); - - self.subTitleLabel.mm_sizeToFit(); - self.subTitleLabel.mm_x = self.mainTitleLabel.mm_x; - self.subTitleLabel.mm_y = CGRectGetMaxY(self.mainTitleLabel.frame) + 2 * kScale; - self.subTitleLabel.mm_flexToRight(12 * kScale); - - self.descLabel.mm_sizeToFit(); - self.descLabel.mm_x = self.mainTitleLabel.mm_x; - self.descLabel.mm_y = CGRectGetMaxY(self.subTitleLabel.frame) + 2 * kScale; - self.descLabel.mm_flexToRight(12 * kScale); + [self.mainTitleLabel sizeToFit]; + [self.mainTitleLabel mas_remakeConstraints:^(MASConstraintMaker *make) { + make.top.mas_equalTo(self.avatarView.mas_top); + make.leading.mas_equalTo(self.avatarView.mas_trailing).mas_offset(12); + make.height.mas_equalTo(20); + make.trailing.mas_lessThanOrEqualTo(self.contentView.mas_trailing).mas_offset(- kScale390(12)); + }]; + [self.subTitleLabel sizeToFit]; + [self.subTitleLabel mas_remakeConstraints:^(MASConstraintMaker *make) { + make.top.mas_equalTo(self.mainTitleLabel.mas_bottom).mas_offset(2); + make.leading.mas_equalTo(self.mainTitleLabel.mas_leading); + make.height.mas_equalTo(self.subTitleLabel.frame.size.height); + make.trailing.mas_lessThanOrEqualTo(self.contentView.mas_trailing).mas_offset(- kScale390(12)); + }]; + [self.descLabel sizeToFit]; + [self.descLabel mas_remakeConstraints:^(MASConstraintMaker *make) { + make.top.mas_equalTo(self.subTitleLabel.mas_bottom).mas_offset(2); + make.leading.mas_equalTo(self.mainTitleLabel.mas_leading); + make.height.mas_equalTo(self.subTitleLabel.frame.size.height); + make.trailing.mas_lessThanOrEqualTo(self.contentView.mas_trailing).mas_offset(- kScale390(12)); + }]; +} +- (void)layoutSubviews { + [super layoutSubviews]; } - (UIImageView *)avatarView { diff --git a/iOS/TUIKit/TUIContact/CommonUI/TUIStyleSelectViewController.m b/iOS/TUIKit/TUIContact/CommonUI/TUIStyleSelectViewController.m index 8ae369930..2cbefae99 100644 --- a/iOS/TUIKit/TUIContact/CommonUI/TUIStyleSelectViewController.m +++ b/iOS/TUIKit/TUIContact/CommonUI/TUIStyleSelectViewController.m @@ -27,25 +27,47 @@ self.nameLabel.text = cellModel.styleName; self.nameLabel.textColor = cellModel.selected ? RGBA(0, 110, 255, 1) : TIMCommonDynamicColor(@"form_title_color", @"#000000"); self.chooseIconView.hidden = !cellModel.selected; + // tell constraints they need updating + [self setNeedsUpdateConstraints]; + + // update constraints now so we can animate the change + [self updateConstraintsIfNeeded]; + + [self layoutIfNeeded]; } - (void)setupViews { [self.contentView addSubview:self.nameLabel]; [self.contentView addSubview:self.chooseIconView]; } - -- (void)layoutSubviews { - [super layoutSubviews]; - - self.chooseIconView.frame = CGRectMake(self.contentView.mm_w - 16 - 20, 0.5 * (self.contentView.mm_h - 20), 20, 20); - self.nameLabel.frame = CGRectMake(kScale375(24), 0, self.contentView.mm_w - 3 * 16 - 20, self.contentView.mm_h); ++ (BOOL)requiresConstraintBasedLayout { + return YES; } +// this is Apple's recommended place for adding/updating constraints +- (void)updateConstraints { + [super updateConstraints]; + + [self.chooseIconView mas_remakeConstraints:^(MASConstraintMaker *make) { + make.centerY.mas_equalTo(self.contentView); + make.width.mas_equalTo(20); + make.height.mas_equalTo(20); + make.trailing.mas_equalTo(-16); + }]; + + [self.nameLabel mas_remakeConstraints:^(MASConstraintMaker *make) { + make.leading.mas_equalTo(16); + make.trailing.mas_equalTo(self.chooseIconView.mas_leading).mas_offset(-2); + make.height.mas_equalTo(self.nameLabel.font.lineHeight); + make.centerY.mas_equalTo(self.contentView); + }]; +} - (UILabel *)nameLabel { if (_nameLabel == nil) { _nameLabel = [[UILabel alloc] init]; _nameLabel.font = [UIFont systemFontOfSize:16.0]; _nameLabel.text = @"1233"; + _nameLabel.textAlignment = isRTL()?NSTextAlignmentRight:NSTextAlignmentLeft; _nameLabel.textColor = TIMCommonDynamicColor(@"form_title_color", @"#000000"); } return _nameLabel; @@ -107,6 +129,7 @@ self.navigationController.navigationBar.barTintColor = self.tintColor; self.navigationController.navigationBar.shadowImage = [UIImage new]; } + self.navigationController.view.backgroundColor = TIMCommonDynamicColor(@"controller_bg_color", @"#F2F3F5"); self.navigationController.navigationBarHidden = NO; } @@ -135,8 +158,9 @@ self.navigationItem.titleView = _titleView; self.navigationItem.title = @""; - UIImage *image = TUICoreDynamicImage(@"nav_back_img", [UIImage imageNamed:@"ic_back_white"]); + UIImage *image = TIMCommonDynamicImage(@"nav_back_img", [UIImage imageNamed:@"ic_back_white"]); image = [image imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal]; + image = [image rtl_imageFlippedForRightToLeftLayoutDirection]; UIButton *backButton = [UIButton buttonWithType:UIButtonTypeCustom]; [backButton setImage:image forState:UIControlStateNormal]; [backButton addTarget:self action:@selector(back) forControlEvents:UIControlEventTouchUpInside]; @@ -231,7 +255,7 @@ _tableView = [[UITableView alloc] initWithFrame:self.view.bounds style:UITableViewStyleGrouped]; _tableView.delegate = self; _tableView.dataSource = self; - _tableView.backgroundColor = TIMCommonDynamicColor(@"controller_bg_color", @"#111111"); + _tableView.backgroundColor = TIMCommonDynamicColor(@"controller_bg_color", @"#FFFFFF"); [_tableView registerClass:TUIStyleSelectCell.class forCellReuseIdentifier:@"cell"]; } return _tableView; diff --git a/iOS/TUIKit/TUIContact/CommonUI/TUIThemeSelectController.h b/iOS/TUIKit/TUIContact/CommonUI/TUIThemeSelectController.h index 0516dbceb..cf6cc029c 100644 --- a/iOS/TUIKit/TUIContact/CommonUI/TUIThemeSelectController.h +++ b/iOS/TUIKit/TUIContact/CommonUI/TUIThemeSelectController.h @@ -43,8 +43,9 @@ typedef void (^ThemeSelectCallback)(TUIThemeSelectCollectionViewCellModel *cellM @end -@interface TUIThemeHeaderCollectionViewCell : TUIThemeSelectCollectionViewCell - +@interface TUIThemeHeaderCollectionViewCell : UICollectionViewCell +@property(nonatomic, strong) TUIThemeSelectCollectionViewCellModel *cellModel; +@property(nonatomic, copy) ThemeSelectCallback onSelect; @end @interface TUIThemeSelectController : UIViewController diff --git a/iOS/TUIKit/TUIContact/CommonUI/TUIThemeSelectController.m b/iOS/TUIKit/TUIContact/CommonUI/TUIThemeSelectController.m index e6c37ec30..cb9694910 100644 --- a/iOS/TUIKit/TUIContact/CommonUI/TUIThemeSelectController.m +++ b/iOS/TUIKit/TUIContact/CommonUI/TUIThemeSelectController.m @@ -12,6 +12,7 @@ #import #import #import +#import @implementation TUIThemeSelectCollectionViewCellModel @@ -98,50 +99,100 @@ - (instancetype)initWithFrame:(CGRect)frame { if (self = [super initWithFrame:frame]) { - [self setupViews]; + [self setupBaseViews]; } return self; } - (void)setCellModel:(TUIThemeSelectCollectionViewCellModel *)cellModel { - [super setCellModel:cellModel]; + _cellModel = cellModel; self.titleLabel.text = TIMCommonLocalizableString(TUIKitThemeNameSystemFollowTitle); self.subTitleLabel.text = TIMCommonLocalizableString(TUIKitThemeNameSystemFollowSubTitle); self.switcher.on = cellModel.selected; + + // tell constraints they need updating + [self setNeedsUpdateConstraints]; + + // update constraints now so we can animate the change + [self updateConstraintsIfNeeded]; + + [self layoutIfNeeded]; + } -- (void)setupViews { ++ (BOOL)requiresConstraintBasedLayout { + return YES; +} + +// this is Apple's recommended place for adding/updating constraints +- (void)updateConstraints { + + [super updateConstraints]; + [self.titleLabel mas_remakeConstraints:^(MASConstraintMaker *make) { + make.leading.mas_equalTo(kScale375(24)); + make.top.mas_equalTo(12); + make.trailing.mas_equalTo(self.switcher.mas_leading).mas_offset(- 3); + make.height.mas_equalTo(20); + }]; + + [self.subTitleLabel sizeToFit]; + [self.subTitleLabel mas_remakeConstraints:^(MASConstraintMaker *make) { + make.leading.mas_equalTo(self.titleLabel); + make.trailing.mas_equalTo(self.switcher.mas_leading); + make.top.mas_equalTo(self.titleLabel.mas_bottom).mas_offset(3); + make.bottom.mas_equalTo(self.contentView.mas_bottom); + }]; + + [self.switcher mas_remakeConstraints:^(MASConstraintMaker *make) { + make.trailing.mas_equalTo(self.contentView.mas_trailing).mas_offset(-kScale375(24)); + make.top.mas_equalTo(self.titleLabel); + make.width.mas_equalTo(35); + make.height.mas_equalTo(20); + }]; + + +} +- (void)setupBaseViews { self.contentView.layer.cornerRadius = 5.0; self.contentView.layer.masksToBounds = YES; - [self.contentView addGestureRecognizer:[[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(onTap)]]; self.backgroundColor = TIMCommonDynamicColor(@"form_bg_color", @"#FFFFFF"); - [self.contentView addSubview:self.switcher]; - self.titleLabel = [[UILabel alloc] initWithFrame:CGRectMake(kScale375(24), 12, self.contentView.mm_w * 0.8, 20)]; + self.titleLabel = [[UILabel alloc] initWithFrame:CGRectZero]; self.titleLabel.textColor = TIMCommonDynamicColor(@"form_title_color", @"#000000"); self.titleLabel.font = [UIFont systemFontOfSize:16.0]; - self.titleLabel.textAlignment = NSTextAlignmentLeft; + self.titleLabel.rtlAlignment = TUITextRTLAlignmentLeading; self.titleLabel.numberOfLines = 0; [self.contentView addSubview:self.titleLabel]; - self.subTitleLabel = [[UILabel alloc] initWithFrame:CGRectMake(self.titleLabel.mm_x, self.titleLabel.mm_maxY + 10, self.contentView.mm_w * 0.9, 18)]; + self.subTitleLabel = [[UILabel alloc] initWithFrame:CGRectZero]; self.subTitleLabel.textColor = TIMCommonDynamicColor(@"form_desc_color", @"#888888"); - self.subTitleLabel.textAlignment = NSTextAlignmentLeft; + self.subTitleLabel.rtlAlignment = TUITextRTLAlignmentLeading; self.subTitleLabel.font = [UIFont systemFontOfSize:12.0]; self.subTitleLabel.backgroundColor = [UIColor clearColor]; self.subTitleLabel.numberOfLines = 0; [self.contentView addSubview:self.subTitleLabel]; + + self.switcher = [[UISwitch alloc] initWithFrame:CGRectZero]; + _switcher.onTintColor = TIMCommonDynamicColor(@"common_switch_on_color", @"#147AFF"); + [_switcher addTarget:self action:@selector(switchClick:) forControlEvents:UIControlEventValueChanged]; - self.switcher = [[UISwitch alloc] initWithFrame:CGRectMake(self.contentView.mm_w - 35 - kScale375(24), self.titleLabel.mm_y - 4, 35, 20)]; - self.switcher.onTintColor = TIMCommonDynamicColor(@"common_switch_on_color", @"#147AFF"); - [self.switcher addTarget:self action:@selector(switchClick:) forControlEvents:UIControlEventValueChanged]; [self.contentView addSubview:self.switcher]; } + - (void)switchClick:(id)sw { if (self.onSelect) { self.onSelect(self.cellModel); } + // tell constraints they need updating + [self setNeedsUpdateConstraints]; + + // update constraints now so we can animate the change + [self updateConstraintsIfNeeded]; + + [self layoutIfNeeded]; + self.backgroundColor = TIMCommonDynamicColor(@"form_bg_color", @"#FFFFFF"); + } @end @@ -186,6 +237,7 @@ self.navigationController.navigationBar.barTintColor = self.tintColor; self.navigationController.navigationBar.shadowImage = [UIImage new]; } + self.navigationController.view.backgroundColor = TIMCommonDynamicColor(@"controller_bg_color", @"#F2F3F5"); self.navigationController.navigationBarHidden = NO; } @@ -209,8 +261,9 @@ self.navigationItem.titleView = _titleView; self.navigationItem.title = @""; - UIImage *image = TUICoreDynamicImage(@"nav_back_img", [UIImage imageNamed:@"ic_back_white"]); + UIImage *image = TIMCommonDynamicImage(@"nav_back_img", [UIImage imageNamed:TIMCommonImagePath(@"nav_back")]); image = [image imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal]; + image = [image rtl_imageFlippedForRightToLeftLayoutDirection]; UIButton *backButton = [UIButton buttonWithType:UIButtonTypeCustom]; [backButton setImage:image forState:UIControlStateNormal]; [backButton addTarget:self action:@selector(back) forControlEvents:UIControlEventTouchUpInside]; @@ -500,7 +553,7 @@ static BOOL gDisableFollowSystemStyle = NO; layout.sectionInset = UIEdgeInsetsMake(12, 16, 12, 16); if (!gDisableFollowSystemStyle) { - layout.headerReferenceSize = CGSizeMake((UIScreen.mainScreen.bounds.size.width), 68); + layout.headerReferenceSize = CGSizeMake((UIScreen.mainScreen.bounds.size.width), 120); } _collectionView = [[UICollectionView alloc] initWithFrame:self.view.bounds collectionViewLayout:layout]; @@ -512,7 +565,7 @@ static BOOL gDisableFollowSystemStyle = NO; [_collectionView registerClass:[TUIThemeHeaderCollectionViewCell class] forSupplementaryViewOfKind:UICollectionElementKindSectionHeader withReuseIdentifier:@"HeaderView"]; - _collectionView.backgroundColor = TIMCommonDynamicColor(@"controller_bg_color", @"#111111"); + _collectionView.backgroundColor = TIMCommonDynamicColor(@"form_bg_color", @"#FFFFFF"); } return _collectionView; } @@ -584,6 +637,7 @@ static BOOL gDisableFollowSystemStyle = NO; - (void)onThemeChanged { dispatch_async(dispatch_get_main_queue(), ^{ + [self prepareData]; [self.collectionView reloadData]; }); } diff --git a/iOS/TUIKit/TUIContact/Resources/TUIContact.bundle/add_friend@3x.png b/iOS/TUIKit/TUIContact/Resources/TUIContact.bundle/add_friend@3x.png index aaed62e5e..1f9c03f30 100644 Binary files a/iOS/TUIKit/TUIContact/Resources/TUIContact.bundle/add_friend@3x.png and b/iOS/TUIKit/TUIContact/Resources/TUIContact.bundle/add_friend@3x.png differ diff --git a/iOS/TUIKit/TUIContact/Resources/TUIContact.bundle/add_group@3x.png b/iOS/TUIKit/TUIContact/Resources/TUIContact.bundle/add_group@3x.png index 97166cced..fab2bdd3b 100644 Binary files a/iOS/TUIKit/TUIContact/Resources/TUIContact.bundle/add_group@3x.png and b/iOS/TUIKit/TUIContact/Resources/TUIContact.bundle/add_group@3x.png differ diff --git a/iOS/TUIKit/TUIContact/Resources/TUIContact.bundle/add_selected@2x.png b/iOS/TUIKit/TUIContact/Resources/TUIContact.bundle/add_selected@2x.png index 2b7c1ca62..892a9a71c 100644 Binary files a/iOS/TUIKit/TUIContact/Resources/TUIContact.bundle/add_selected@2x.png and b/iOS/TUIKit/TUIContact/Resources/TUIContact.bundle/add_selected@2x.png differ diff --git a/iOS/TUIKit/TUIContact/Resources/TUIContact.bundle/add_selected@3x.png b/iOS/TUIKit/TUIContact/Resources/TUIContact.bundle/add_selected@3x.png index ca0f6c3c7..f491e70ed 100644 Binary files a/iOS/TUIKit/TUIContact/Resources/TUIContact.bundle/add_selected@3x.png and b/iOS/TUIKit/TUIContact/Resources/TUIContact.bundle/add_selected@3x.png differ diff --git a/iOS/TUIKit/TUIContact/Resources/TUIContact.bundle/add_unselect@2x.png b/iOS/TUIKit/TUIContact/Resources/TUIContact.bundle/add_unselect@2x.png index c061a1641..47ce633b9 100644 Binary files a/iOS/TUIKit/TUIContact/Resources/TUIContact.bundle/add_unselect@2x.png and b/iOS/TUIKit/TUIContact/Resources/TUIContact.bundle/add_unselect@2x.png differ diff --git a/iOS/TUIKit/TUIContact/Resources/TUIContact.bundle/add_unselect@3x.png b/iOS/TUIKit/TUIContact/Resources/TUIContact.bundle/add_unselect@3x.png index 394c16d83..3241b9289 100644 Binary files a/iOS/TUIKit/TUIContact/Resources/TUIContact.bundle/add_unselect@3x.png and b/iOS/TUIKit/TUIContact/Resources/TUIContact.bundle/add_unselect@3x.png differ diff --git a/iOS/TUIKit/TUIContact/Resources/TUIContact.bundle/blacklist@2x.png b/iOS/TUIKit/TUIContact/Resources/TUIContact.bundle/blacklist@2x.png index 33d79421a..10ad853bb 100644 Binary files a/iOS/TUIKit/TUIContact/Resources/TUIContact.bundle/blacklist@2x.png and b/iOS/TUIKit/TUIContact/Resources/TUIContact.bundle/blacklist@2x.png differ diff --git a/iOS/TUIKit/TUIContact/Resources/TUIContact.bundle/blacklist@3x.png b/iOS/TUIKit/TUIContact/Resources/TUIContact.bundle/blacklist@3x.png index a3d59692b..55ca43f4a 100644 Binary files a/iOS/TUIKit/TUIContact/Resources/TUIContact.bundle/blacklist@3x.png and b/iOS/TUIKit/TUIContact/Resources/TUIContact.bundle/blacklist@3x.png differ diff --git a/iOS/TUIKit/TUIContact/Resources/TUIContact.bundle/chat_nav_more_menu@3x.png b/iOS/TUIKit/TUIContact/Resources/TUIContact.bundle/chat_nav_more_menu@3x.png index 84b00e342..3dabae0da 100644 Binary files a/iOS/TUIKit/TUIContact/Resources/TUIContact.bundle/chat_nav_more_menu@3x.png and b/iOS/TUIKit/TUIContact/Resources/TUIContact.bundle/chat_nav_more_menu@3x.png differ diff --git a/iOS/TUIKit/TUIContact/Resources/TUIContact.bundle/choose_style@3x.png b/iOS/TUIKit/TUIContact/Resources/TUIContact.bundle/choose_style@3x.png index dab5bb23c..53b3a79a4 100644 Binary files a/iOS/TUIKit/TUIContact/Resources/TUIContact.bundle/choose_style@3x.png and b/iOS/TUIKit/TUIContact/Resources/TUIContact.bundle/choose_style@3x.png differ diff --git a/iOS/TUIKit/TUIContact/Resources/TUIContact.bundle/new_friend@2x.png b/iOS/TUIKit/TUIContact/Resources/TUIContact.bundle/new_friend@2x.png index e2aeddf46..aa18c3d20 100644 Binary files a/iOS/TUIKit/TUIContact/Resources/TUIContact.bundle/new_friend@2x.png and b/iOS/TUIKit/TUIContact/Resources/TUIContact.bundle/new_friend@2x.png differ diff --git a/iOS/TUIKit/TUIContact/Resources/TUIContact.bundle/new_friend@3x.png b/iOS/TUIKit/TUIContact/Resources/TUIContact.bundle/new_friend@3x.png index 6e9d54982..20fa2a6dd 100644 Binary files a/iOS/TUIKit/TUIContact/Resources/TUIContact.bundle/new_friend@3x.png and b/iOS/TUIKit/TUIContact/Resources/TUIContact.bundle/new_friend@3x.png differ diff --git a/iOS/TUIKit/TUIContact/Resources/TUIContact.bundle/public_group@2x.png b/iOS/TUIKit/TUIContact/Resources/TUIContact.bundle/public_group@2x.png index 73103e1dd..ffc97532d 100644 Binary files a/iOS/TUIKit/TUIContact/Resources/TUIContact.bundle/public_group@2x.png and b/iOS/TUIKit/TUIContact/Resources/TUIContact.bundle/public_group@2x.png differ diff --git a/iOS/TUIKit/TUIContact/Resources/TUIContact.bundle/public_group@3x.png b/iOS/TUIKit/TUIContact/Resources/TUIContact.bundle/public_group@3x.png index 541c34c96..7fb376b33 100644 Binary files a/iOS/TUIKit/TUIContact/Resources/TUIContact.bundle/public_group@3x.png and b/iOS/TUIKit/TUIContact/Resources/TUIContact.bundle/public_group@3x.png differ diff --git a/iOS/TUIKit/TUIContact/Resources/TUIContact.bundle/theme_cover_dark@3x.png b/iOS/TUIKit/TUIContact/Resources/TUIContact.bundle/theme_cover_dark@3x.png index 4979df6ca..68e766ac0 100644 Binary files a/iOS/TUIKit/TUIContact/Resources/TUIContact.bundle/theme_cover_dark@3x.png and b/iOS/TUIKit/TUIContact/Resources/TUIContact.bundle/theme_cover_dark@3x.png differ diff --git a/iOS/TUIKit/TUIContact/Resources/TUIContact.bundle/theme_cover_light@3x.png b/iOS/TUIKit/TUIContact/Resources/TUIContact.bundle/theme_cover_light@3x.png index 80021047f..d3d34ce32 100644 Binary files a/iOS/TUIKit/TUIContact/Resources/TUIContact.bundle/theme_cover_light@3x.png and b/iOS/TUIKit/TUIContact/Resources/TUIContact.bundle/theme_cover_light@3x.png differ diff --git a/iOS/TUIKit/TUIContact/Resources/TUIContact.bundle/theme_cover_lively@3x.png b/iOS/TUIKit/TUIContact/Resources/TUIContact.bundle/theme_cover_lively@3x.png index 1d02750b6..df4f161be 100644 Binary files a/iOS/TUIKit/TUIContact/Resources/TUIContact.bundle/theme_cover_lively@3x.png and b/iOS/TUIKit/TUIContact/Resources/TUIContact.bundle/theme_cover_lively@3x.png differ diff --git a/iOS/TUIKit/TUIContact/Resources/TUIContact.bundle/theme_cover_serious@3x.png b/iOS/TUIKit/TUIContact/Resources/TUIContact.bundle/theme_cover_serious@3x.png index c7c17de24..77022fe83 100644 Binary files a/iOS/TUIKit/TUIContact/Resources/TUIContact.bundle/theme_cover_serious@3x.png and b/iOS/TUIKit/TUIContact/Resources/TUIContact.bundle/theme_cover_serious@3x.png differ diff --git a/iOS/TUIKit/TUIContact/Resources/TUIContactTheme.bundle/dark/resource/add_friend@3x.png b/iOS/TUIKit/TUIContact/Resources/TUIContactTheme.bundle/dark/resource/add_friend@3x.png index 156caf3e3..ef7329854 100644 Binary files a/iOS/TUIKit/TUIContact/Resources/TUIContactTheme.bundle/dark/resource/add_friend@3x.png and b/iOS/TUIKit/TUIContact/Resources/TUIContactTheme.bundle/dark/resource/add_friend@3x.png differ diff --git a/iOS/TUIKit/TUIContact/Resources/TUIContactTheme.bundle/dark/resource/add_group@3x.png b/iOS/TUIKit/TUIContact/Resources/TUIContactTheme.bundle/dark/resource/add_group@3x.png index 1b5bafe56..6f3552bb0 100644 Binary files a/iOS/TUIKit/TUIContact/Resources/TUIContactTheme.bundle/dark/resource/add_group@3x.png and b/iOS/TUIKit/TUIContact/Resources/TUIContactTheme.bundle/dark/resource/add_group@3x.png differ diff --git a/iOS/TUIKit/TUIContact/Resources/TUIContactTheme.bundle/dark/resource/blacklist@3x.png b/iOS/TUIKit/TUIContact/Resources/TUIContactTheme.bundle/dark/resource/blacklist@3x.png index a3d59692b..55ca43f4a 100644 Binary files a/iOS/TUIKit/TUIContact/Resources/TUIContactTheme.bundle/dark/resource/blacklist@3x.png and b/iOS/TUIKit/TUIContact/Resources/TUIContactTheme.bundle/dark/resource/blacklist@3x.png differ diff --git a/iOS/TUIKit/TUIContact/Resources/TUIContactTheme.bundle/dark/resource/chat_nav_more_menu@3x.png b/iOS/TUIKit/TUIContact/Resources/TUIContactTheme.bundle/dark/resource/chat_nav_more_menu@3x.png index cbc3fef2a..62f791715 100644 Binary files a/iOS/TUIKit/TUIContact/Resources/TUIContactTheme.bundle/dark/resource/chat_nav_more_menu@3x.png and b/iOS/TUIKit/TUIContact/Resources/TUIContactTheme.bundle/dark/resource/chat_nav_more_menu@3x.png differ diff --git a/iOS/TUIKit/TUIContact/Resources/TUIContactTheme.bundle/dark/resource/new_friend@3x.png b/iOS/TUIKit/TUIContact/Resources/TUIContactTheme.bundle/dark/resource/new_friend@3x.png index 6e9d54982..20fa2a6dd 100644 Binary files a/iOS/TUIKit/TUIContact/Resources/TUIContactTheme.bundle/dark/resource/new_friend@3x.png and b/iOS/TUIKit/TUIContact/Resources/TUIContactTheme.bundle/dark/resource/new_friend@3x.png differ diff --git a/iOS/TUIKit/TUIContact/Resources/TUIContactTheme.bundle/dark/resource/public_group@3x.png b/iOS/TUIKit/TUIContact/Resources/TUIContactTheme.bundle/dark/resource/public_group@3x.png index 541c34c96..7fb376b33 100644 Binary files a/iOS/TUIKit/TUIContact/Resources/TUIContactTheme.bundle/dark/resource/public_group@3x.png and b/iOS/TUIKit/TUIContact/Resources/TUIContactTheme.bundle/dark/resource/public_group@3x.png differ diff --git a/iOS/TUIKit/TUIContact/Resources/TUIContactTheme.bundle/light/resource/blacklist@3x.png b/iOS/TUIKit/TUIContact/Resources/TUIContactTheme.bundle/light/resource/blacklist@3x.png index 06a7a23d8..0984e9fdd 100644 Binary files a/iOS/TUIKit/TUIContact/Resources/TUIContactTheme.bundle/light/resource/blacklist@3x.png and b/iOS/TUIKit/TUIContact/Resources/TUIContactTheme.bundle/light/resource/blacklist@3x.png differ diff --git a/iOS/TUIKit/TUIContact/Resources/TUIContactTheme.bundle/light/resource/chat_nav_more_menu@3x.png b/iOS/TUIKit/TUIContact/Resources/TUIContactTheme.bundle/light/resource/chat_nav_more_menu@3x.png index 84b00e342..3dabae0da 100644 Binary files a/iOS/TUIKit/TUIContact/Resources/TUIContactTheme.bundle/light/resource/chat_nav_more_menu@3x.png and b/iOS/TUIKit/TUIContact/Resources/TUIContactTheme.bundle/light/resource/chat_nav_more_menu@3x.png differ diff --git a/iOS/TUIKit/TUIContact/Resources/TUIContactTheme.bundle/light/resource/new_friend@3x.png b/iOS/TUIKit/TUIContact/Resources/TUIContactTheme.bundle/light/resource/new_friend@3x.png index cbe665dc8..79cfb855a 100644 Binary files a/iOS/TUIKit/TUIContact/Resources/TUIContactTheme.bundle/light/resource/new_friend@3x.png and b/iOS/TUIKit/TUIContact/Resources/TUIContactTheme.bundle/light/resource/new_friend@3x.png differ diff --git a/iOS/TUIKit/TUIContact/Resources/TUIContactTheme.bundle/light/resource/public_group@3x.png b/iOS/TUIKit/TUIContact/Resources/TUIContactTheme.bundle/light/resource/public_group@3x.png index e928cb2a0..fa6acc9fe 100644 Binary files a/iOS/TUIKit/TUIContact/Resources/TUIContactTheme.bundle/light/resource/public_group@3x.png and b/iOS/TUIKit/TUIContact/Resources/TUIContactTheme.bundle/light/resource/public_group@3x.png differ diff --git a/iOS/TUIKit/TUIContact/Resources/TUIContactTheme.bundle/lively/resource/blacklist@3x.png b/iOS/TUIKit/TUIContact/Resources/TUIContactTheme.bundle/lively/resource/blacklist@3x.png index 4d9446669..ad12dd24f 100644 Binary files a/iOS/TUIKit/TUIContact/Resources/TUIContactTheme.bundle/lively/resource/blacklist@3x.png and b/iOS/TUIKit/TUIContact/Resources/TUIContactTheme.bundle/lively/resource/blacklist@3x.png differ diff --git a/iOS/TUIKit/TUIContact/Resources/TUIContactTheme.bundle/lively/resource/chat_nav_more_menu@3x.png b/iOS/TUIKit/TUIContact/Resources/TUIContactTheme.bundle/lively/resource/chat_nav_more_menu@3x.png index cbc3fef2a..97445f14f 100644 Binary files a/iOS/TUIKit/TUIContact/Resources/TUIContactTheme.bundle/lively/resource/chat_nav_more_menu@3x.png and b/iOS/TUIKit/TUIContact/Resources/TUIContactTheme.bundle/lively/resource/chat_nav_more_menu@3x.png differ diff --git a/iOS/TUIKit/TUIContact/Resources/TUIContactTheme.bundle/lively/resource/new_friend@3x.png b/iOS/TUIKit/TUIContact/Resources/TUIContactTheme.bundle/lively/resource/new_friend@3x.png index 3b5c16451..579ac1538 100644 Binary files a/iOS/TUIKit/TUIContact/Resources/TUIContactTheme.bundle/lively/resource/new_friend@3x.png and b/iOS/TUIKit/TUIContact/Resources/TUIContactTheme.bundle/lively/resource/new_friend@3x.png differ diff --git a/iOS/TUIKit/TUIContact/Resources/TUIContactTheme.bundle/lively/resource/public_group@3x.png b/iOS/TUIKit/TUIContact/Resources/TUIContactTheme.bundle/lively/resource/public_group@3x.png index 7aaa56a6c..bc8c24397 100644 Binary files a/iOS/TUIKit/TUIContact/Resources/TUIContactTheme.bundle/lively/resource/public_group@3x.png and b/iOS/TUIKit/TUIContact/Resources/TUIContactTheme.bundle/lively/resource/public_group@3x.png differ diff --git a/iOS/TUIKit/TUIContact/Resources/TUIContactTheme.bundle/serious/resource/blacklist@3x.png b/iOS/TUIKit/TUIContact/Resources/TUIContactTheme.bundle/serious/resource/blacklist@3x.png index ec7b63ee1..e1a5542e9 100644 Binary files a/iOS/TUIKit/TUIContact/Resources/TUIContactTheme.bundle/serious/resource/blacklist@3x.png and b/iOS/TUIKit/TUIContact/Resources/TUIContactTheme.bundle/serious/resource/blacklist@3x.png differ diff --git a/iOS/TUIKit/TUIContact/Resources/TUIContactTheme.bundle/serious/resource/chat_nav_more_menu@3x.png b/iOS/TUIKit/TUIContact/Resources/TUIContactTheme.bundle/serious/resource/chat_nav_more_menu@3x.png index cbc3fef2a..9ce9f9176 100644 Binary files a/iOS/TUIKit/TUIContact/Resources/TUIContactTheme.bundle/serious/resource/chat_nav_more_menu@3x.png and b/iOS/TUIKit/TUIContact/Resources/TUIContactTheme.bundle/serious/resource/chat_nav_more_menu@3x.png differ diff --git a/iOS/TUIKit/TUIContact/Resources/TUIContactTheme.bundle/serious/resource/new_friend@3x.png b/iOS/TUIKit/TUIContact/Resources/TUIContactTheme.bundle/serious/resource/new_friend@3x.png index 85a7deb3c..81ae5b25a 100644 Binary files a/iOS/TUIKit/TUIContact/Resources/TUIContactTheme.bundle/serious/resource/new_friend@3x.png and b/iOS/TUIKit/TUIContact/Resources/TUIContactTheme.bundle/serious/resource/new_friend@3x.png differ diff --git a/iOS/TUIKit/TUIContact/Resources/TUIContactTheme.bundle/serious/resource/public_group@3x.png b/iOS/TUIKit/TUIContact/Resources/TUIContactTheme.bundle/serious/resource/public_group@3x.png index 8a620c29b..f6c290bba 100644 Binary files a/iOS/TUIKit/TUIContact/Resources/TUIContactTheme.bundle/serious/resource/public_group@3x.png and b/iOS/TUIKit/TUIContact/Resources/TUIContactTheme.bundle/serious/resource/public_group@3x.png differ diff --git a/iOS/TUIKit/TUIContact/Resources/TUIContact_Minimalist.bundle/contact_add_failed@3x.png b/iOS/TUIKit/TUIContact/Resources/TUIContact_Minimalist.bundle/contact_add_failed@3x.png index 84d94f4f2..f9bdd8188 100644 Binary files a/iOS/TUIKit/TUIContact/Resources/TUIContact_Minimalist.bundle/contact_add_failed@3x.png and b/iOS/TUIKit/TUIContact/Resources/TUIContact_Minimalist.bundle/contact_add_failed@3x.png differ diff --git a/iOS/TUIKit/TUIContact/Resources/TUIContact_Minimalist.bundle/contact_add_success@3x.png b/iOS/TUIKit/TUIContact/Resources/TUIContact_Minimalist.bundle/contact_add_success@3x.png index 1ebe349cb..1f54070ac 100644 Binary files a/iOS/TUIKit/TUIContact/Resources/TUIContact_Minimalist.bundle/contact_add_success@3x.png and b/iOS/TUIKit/TUIContact/Resources/TUIContact_Minimalist.bundle/contact_add_success@3x.png differ diff --git a/iOS/TUIKit/TUIContact/Resources/TUIContact_Minimalist.bundle/contact_info_add_icon@3x.png b/iOS/TUIKit/TUIContact/Resources/TUIContact_Minimalist.bundle/contact_info_add_icon@3x.png index 6dfb26db1..b46e6666e 100644 Binary files a/iOS/TUIKit/TUIContact/Resources/TUIContact_Minimalist.bundle/contact_info_add_icon@3x.png and b/iOS/TUIKit/TUIContact/Resources/TUIContact_Minimalist.bundle/contact_info_add_icon@3x.png differ diff --git a/iOS/TUIKit/TUIContact/Resources/TUIContact_Minimalist.bundle/contact_info_audio@3x.png b/iOS/TUIKit/TUIContact/Resources/TUIContact_Minimalist.bundle/contact_info_audio@3x.png index 8330e19e3..a2b1445c1 100644 Binary files a/iOS/TUIKit/TUIContact/Resources/TUIContact_Minimalist.bundle/contact_info_audio@3x.png and b/iOS/TUIKit/TUIContact/Resources/TUIContact_Minimalist.bundle/contact_info_audio@3x.png differ diff --git a/iOS/TUIKit/TUIContact/Resources/TUIContact_Minimalist.bundle/contact_info_del_icon@3x.png b/iOS/TUIKit/TUIContact/Resources/TUIContact_Minimalist.bundle/contact_info_del_icon@3x.png index 778e804f7..fc38fcb20 100644 Binary files a/iOS/TUIKit/TUIContact/Resources/TUIContact_Minimalist.bundle/contact_info_del_icon@3x.png and b/iOS/TUIKit/TUIContact/Resources/TUIContact_Minimalist.bundle/contact_info_del_icon@3x.png differ diff --git a/iOS/TUIKit/TUIContact/Resources/TUIContact_Minimalist.bundle/contact_info_message@3x.png b/iOS/TUIKit/TUIContact/Resources/TUIContact_Minimalist.bundle/contact_info_message@3x.png index 05cadd116..b388a8c40 100644 Binary files a/iOS/TUIKit/TUIContact/Resources/TUIContact_Minimalist.bundle/contact_info_message@3x.png and b/iOS/TUIKit/TUIContact/Resources/TUIContact_Minimalist.bundle/contact_info_message@3x.png differ diff --git a/iOS/TUIKit/TUIContact/Resources/TUIContact_Minimalist.bundle/contact_info_video@3x.png b/iOS/TUIKit/TUIContact/Resources/TUIContact_Minimalist.bundle/contact_info_video@3x.png index 6dc431251..425b35cd0 100644 Binary files a/iOS/TUIKit/TUIContact/Resources/TUIContact_Minimalist.bundle/contact_info_video@3x.png and b/iOS/TUIKit/TUIContact/Resources/TUIContact_Minimalist.bundle/contact_info_video@3x.png differ diff --git a/iOS/TUIKit/TUIContact/Resources/TUIContact_Minimalist.bundle/contact_not_found_icon@3x.png b/iOS/TUIKit/TUIContact/Resources/TUIContact_Minimalist.bundle/contact_not_found_icon@3x.png index e3394494c..eb858ca20 100644 Binary files a/iOS/TUIKit/TUIContact/Resources/TUIContact_Minimalist.bundle/contact_not_found_icon@3x.png and b/iOS/TUIKit/TUIContact/Resources/TUIContact_Minimalist.bundle/contact_not_found_icon@3x.png differ diff --git a/iOS/TUIKit/TUIContact/TUIContact.podspec b/iOS/TUIKit/TUIContact/TUIContact.podspec index 711302a72..f4a9a5416 100644 --- a/iOS/TUIKit/TUIContact/TUIContact.podspec +++ b/iOS/TUIKit/TUIContact/TUIContact.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |spec| spec.name = 'TUIContact' - spec.version = '7.4.4643' + spec.version = '7.5.4852' spec.platform = :ios spec.ios.deployment_target = '9.0' spec.license = { :type => 'Proprietary', diff --git a/iOS/TUIKit/TUIContact/UI_Classic/UI/TUIBlackListController.m b/iOS/TUIKit/TUIContact/UI_Classic/UI/TUIBlackListController.m index 80a40e042..a98689053 100644 --- a/iOS/TUIKit/TUIContact/UI_Classic/UI/TUIBlackListController.m +++ b/iOS/TUIKit/TUIContact/UI_Classic/UI/TUIBlackListController.m @@ -9,7 +9,6 @@ #import "TUIBlackListController.h" #import #import -#import "ReactiveObjC.h" @interface TUIBlackListController () diff --git a/iOS/TUIKit/TUIContact/UI_Classic/UI/TUIContactController.m b/iOS/TUIKit/TUIContact/UI_Classic/UI/TUIContactController.m index db9efc92c..3aff2aea2 100644 --- a/iOS/TUIKit/TUIContact/UI_Classic/UI/TUIContactController.m +++ b/iOS/TUIKit/TUIContact/UI_Classic/UI/TUIContactController.m @@ -10,7 +10,6 @@ #import #import #import -#import "ReactiveObjC.h" #import "TUIBlackListController.h" #import "TUIContactActionCell.h" #import "TUIFindContactViewController.h" @@ -134,7 +133,11 @@ CGFloat height = [TUIPopCell getHeight] * menus.count + TUIPopView_Arrow_Size.height; CGFloat orginY = StatusBar_Height + NavBar_Height; - TUIPopView *popView = [[TUIPopView alloc] initWithFrame:CGRectMake(Screen_Width - 140, orginY, 130, height)]; + CGFloat orginX = Screen_Width - 140; + if(isRTL()){ + orginX = 10; + } + TUIPopView *popView = [[TUIPopView alloc] initWithFrame:CGRectMake(orginX, orginY, 130, height)]; CGRect frameInNaviView = [self.navigationController.view convertRect:rightBarButton.frame fromView:rightBarButton.superview]; popView.arrowPoint = CGPointMake(frameInNaviView.origin.x + frameInNaviView.size.width * 0.5, orginY); popView.delegate = self; @@ -210,9 +213,12 @@ textLabel.tag = TEXT_TAG; textLabel.font = [UIFont systemFontOfSize:16]; textLabel.textColor = RGB(0x80, 0x80, 0x80); + [textLabel setRtlAlignment:TUITextRTLAlignmentLeading]; [headerView addSubview:textLabel]; - textLabel.mm_fill().mm_left(12); - textLabel.autoresizingMask = UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth; + [textLabel mas_remakeConstraints:^(MASConstraintMaker *make) { + make.leading.mas_equalTo(headerView.mas_leading).mas_offset(12); + make.top.bottom.trailing.mas_equalTo(headerView); + }]; } UILabel *label = [headerView viewWithTag:TEXT_TAG]; label.text = self.viewModel.groupList[section - 1]; diff --git a/iOS/TUIKit/TUIContact/UI_Classic/UI/TUIContactSelectController.m b/iOS/TUIKit/TUIContact/UI_Classic/UI/TUIContactSelectController.m index a7b860434..d00b6756b 100644 --- a/iOS/TUIKit/TUIContact/UI_Classic/UI/TUIContactSelectController.m +++ b/iOS/TUIKit/TUIContact/UI_Classic/UI/TUIContactSelectController.m @@ -137,8 +137,12 @@ static NSString *gReuseIdentifier = @"ContactSelectCell"; textLabel.tag = TEXT_TAG; textLabel.font = [UIFont systemFontOfSize:16]; textLabel.textColor = RGB(0x80, 0x80, 0x80); + [textLabel setRtlAlignment:TUITextRTLAlignmentLeading]; [headerView addSubview:textLabel]; - textLabel.mm_fill().mm_left(12); + [textLabel mas_remakeConstraints:^(MASConstraintMaker *make) { + make.leading.mas_equalTo(headerView.mas_leading).mas_offset(12); + make.top.bottom.trailing.mas_equalTo(headerView); + }]; textLabel.autoresizingMask = UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth; } UILabel *label = [headerView viewWithTag:TEXT_TAG]; diff --git a/iOS/TUIKit/TUIContact/UI_Classic/UI/TUIFindContactViewController.m b/iOS/TUIKit/TUIContact/UI_Classic/UI/TUIFindContactViewController.m index 13a49d99b..70bce3109 100644 --- a/iOS/TUIKit/TUIContact/UI_Classic/UI/TUIFindContactViewController.m +++ b/iOS/TUIKit/TUIContact/UI_Classic/UI/TUIFindContactViewController.m @@ -146,6 +146,7 @@ self.type == TUIFindContactTypeC2C ? TIMCommonLocalizableString(TUIKitSearchUserID) : TIMCommonLocalizableString(TUIKitSearchGroupID); _searchBar.backgroundImage = [[UIImage alloc] init]; _searchBar.delegate = self; + _searchBar.searchTextField.textAlignment = isRTL()?NSTextAlignmentRight:NSTextAlignmentLeft; UITextField *searchField = [_searchBar valueForKey:@"searchField"]; if (searchField) { searchField.backgroundColor = TIMCommonDynamicColor(@"search_textfield_bg_color", @"#FEFEFE"); diff --git a/iOS/TUIKit/TUIContact/UI_Classic/UI/TUIFriendRequestViewController.m b/iOS/TUIKit/TUIContact/UI_Classic/UI/TUIFriendRequestViewController.m index a07a43b6f..1ddd69751 100644 --- a/iOS/TUIKit/TUIContact/UI_Classic/UI/TUIFriendRequestViewController.m +++ b/iOS/TUIKit/TUIContact/UI_Classic/UI/TUIFriendRequestViewController.m @@ -44,7 +44,7 @@ self.addWordTextView = [[UITextView alloc] initWithFrame:CGRectZero]; self.addWordTextView.font = [UIFont systemFontOfSize:14]; - + self.addWordTextView.textAlignment = isRTL()?NSTextAlignmentRight:NSTextAlignmentLeft; NSString *selfUserID = [[V2TIMManager sharedInstance] getLoginUser]; [[V2TIMManager sharedInstance] getUsersInfo:@[ selfUserID ] succ:^(NSArray *infoList) { @@ -62,7 +62,13 @@ }]; self.nickTextField = [[UITextField alloc] initWithFrame:CGRectZero]; - self.nickTextField.textAlignment = NSTextAlignmentRight; + if (isRTL()) { + self.nickTextField.textAlignment = NSTextAlignmentLeft; + } + else { + self.nickTextField.textAlignment = NSTextAlignmentRight; + } + _titleView = [[TUINaviBarIndicatorView alloc] init]; [_titleView setTitle:TIMCommonLocalizableString(FriendRequestFillInfo)]; diff --git a/iOS/TUIKit/TUIContact/UI_Classic/UI/TUIGroupConversationListController.m b/iOS/TUIKit/TUIContact/UI_Classic/UI/TUIGroupConversationListController.m index 40895ae11..b9eeb5d9f 100644 --- a/iOS/TUIKit/TUIContact/UI_Classic/UI/TUIGroupConversationListController.m +++ b/iOS/TUIKit/TUIContact/UI_Classic/UI/TUIGroupConversationListController.m @@ -128,8 +128,12 @@ static NSString *gConversationCell_ReuseId = @"TConversationCell"; UILabel *textLabel = [[UILabel alloc] initWithFrame:CGRectZero]; textLabel.tag = TEXT_TAG; textLabel.textColor = RGB(0x80, 0x80, 0x80); + [textLabel setRtlAlignment:TUITextRTLAlignmentLeading]; [headerView addSubview:textLabel]; - textLabel.mm_fill().mm_left(12); + [textLabel mas_remakeConstraints:^(MASConstraintMaker *make) { + make.leading.mas_equalTo(headerView.mas_leading).mas_offset(12); + make.top.bottom.trailing.mas_equalTo(headerView); + }]; textLabel.autoresizingMask = UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth; } UILabel *label = [headerView viewWithTag:TEXT_TAG]; diff --git a/iOS/TUIKit/TUIContact/UI_Classic/UI/TUIGroupCreateController.m b/iOS/TUIKit/TUIContact/UI_Classic/UI/TUIGroupCreateController.m index 93f2b5764..0292c226e 100644 --- a/iOS/TUIKit/TUIContact/UI_Classic/UI/TUIGroupCreateController.m +++ b/iOS/TUIKit/TUIContact/UI_Classic/UI/TUIGroupCreateController.m @@ -51,14 +51,14 @@ } self.groupNameTextField = [[UITextField alloc] initWithFrame:CGRectZero]; - self.groupNameTextField.textAlignment = NSTextAlignmentRight; + self.groupNameTextField.textAlignment = isRTL()?NSTextAlignmentLeft: NSTextAlignmentRight; self.groupNameTextField.placeholder = TIMCommonLocalizableString(TUIKitCreatGroupNamed_Placeholder); self.groupNameTextField.delegate = self; if (IS_NOT_EMPTY_NSSTRING(self.createGroupInfo.groupName)) { self.groupNameTextField.text = self.createGroupInfo.groupName; } self.groupIDTextField = [[UITextField alloc] initWithFrame:CGRectZero]; - self.groupIDTextField.textAlignment = NSTextAlignmentRight; + self.groupIDTextField.textAlignment = isRTL()?NSTextAlignmentLeft: NSTextAlignmentRight; self.groupIDTextField.keyboardType = UIKeyboardTypeDefault; self.groupIDTextField.placeholder = TIMCommonLocalizableString(TUIKitCreatGroupID_Placeholder); self.groupIDTextField.delegate = self; @@ -83,6 +83,7 @@ if (!_describeTextView) { _describeTextView = [[UITextView alloc] init]; _describeTextView.backgroundColor = [UIColor clearColor]; + _describeTextView.textAlignment = isRTL()?NSTextAlignmentRight:NSTextAlignmentLeft; _describeTextView.editable = NO; _describeTextView.scrollEnabled = NO; _describeTextView.textContainerInset = UIEdgeInsetsMake(0.f, 0.f, 0.f, 0.f); @@ -125,7 +126,8 @@ NSMutableParagraphStyle *paragraphStyle = [[NSMutableParagraphStyle alloc] init]; paragraphStyle.minimumLineHeight = 18; [paragraphStyle setLineBreakMode:NSLineBreakByWordWrapping]; - [paragraphStyle setAlignment:NSTextAlignmentLeft]; + [paragraphStyle setAlignment:isRTL()?NSTextAlignmentRight: NSTextAlignmentLeft]; + NSDictionary *dictionary = @{ NSFontAttributeName : [UIFont systemFontOfSize:12], NSForegroundColorAttributeName : [UIColor tui_colorWithHex:@"#888888"], @@ -154,8 +156,9 @@ return 44; } -- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView; -{ return 3; } +- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView { + return 3; +} - (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section { UIView *view = [[UIView alloc] init]; @@ -190,16 +193,24 @@ cell.textLabel.text = TIMCommonLocalizableString(TUIKitCreatGroupNamed); [cell.contentView addSubview:self.groupNameTextField]; cell.backgroundColor = TIMCommonDynamicColor(@"form_bg_color", @"#FFFFFF"); - self.groupNameTextField.mm_width(cell.contentView.mm_w / 2).mm_height(cell.contentView.mm_h).mm_right(16); - self.groupNameTextField.autoresizingMask = UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleRightMargin; + [self.groupNameTextField mas_remakeConstraints:^(MASConstraintMaker *make) { + make.trailing.mas_equalTo(cell.contentView.mas_trailing).mas_offset(- 16); + make.height.mas_equalTo(cell.contentView); + make.width.mas_equalTo(cell.contentView).multipliedBy(0.5); + make.centerY.mas_equalTo(cell.contentView); + }]; return cell; } else { UITableViewCell *cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:@"groupID"]; cell.backgroundColor = TIMCommonDynamicColor(@"form_bg_color", @"#FFFFFF"); cell.textLabel.text = TIMCommonLocalizableString(TUIKitCreatGroupID); [cell.contentView addSubview:self.groupIDTextField]; - self.groupIDTextField.mm_width(cell.contentView.mm_w / 2).mm_height(cell.contentView.mm_h).mm_right(16); - self.groupIDTextField.autoresizingMask = UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleRightMargin; + [self.groupIDTextField mas_remakeConstraints:^(MASConstraintMaker *make) { + make.trailing.mas_equalTo(cell.contentView.mas_trailing).mas_offset(- 16); + make.height.mas_equalTo(cell.contentView); + make.width.mas_equalTo(cell.contentView).multipliedBy(0.5); + make.centerY.mas_equalTo(cell.contentView); + }]; return cell; } } else if (indexPath.section == 1) { @@ -224,8 +235,11 @@ [headImage sd_setImageWithURL:[NSURL URLWithString:self.createGroupInfo.faceURL] placeholderImage:self.cacheGroupGridAvatarImage]; } CGFloat margin = 5; - headImage.frame = CGRectMake((cell.mm_w - 48 - margin), (88 - 48) / 2, 48, 48); - headImage.autoresizingMask = UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleRightMargin; + [headImage mas_remakeConstraints:^(MASConstraintMaker *make) { + make.trailing.mas_equalTo(cell.contentView.mas_trailing).mas_offset(- margin); + make.height.width.mas_equalTo(48); + make.centerY.mas_equalTo(cell.contentView); + }]; return cell; } diff --git a/iOS/TUIKit/TUIContact/UI_Classic/UI/TUIGroupTypeListController.m b/iOS/TUIKit/TUIContact/UI_Classic/UI/TUIGroupTypeListController.m index 27f95b147..995241a6b 100644 --- a/iOS/TUIKit/TUIContact/UI_Classic/UI/TUIGroupTypeListController.m +++ b/iOS/TUIKit/TUIContact/UI_Classic/UI/TUIGroupTypeListController.m @@ -81,19 +81,40 @@ _title = [[UILabel alloc] init]; _title.font = [UIFont systemFontOfSize:16]; _title.textColor = TIMCommonDynamicColor(@"form_title_color", @"#000000"); + _title.textAlignment = isRTL()?NSTextAlignmentRight:NSTextAlignmentLeft; _title.numberOfLines = 0; [self addSubview:_title]; [self addSubview:self.describeTextView]; } -- (void)layoutSubviews { - self.image.frame = CGRectMake(16, 12, 40, 40); ++ (BOOL)requiresConstraintBasedLayout { + return YES; +} - CGFloat x = _image.frame.origin.x + _image.frame.size.width + 10; - self.title.frame = CGRectMake(x, 0, self.frame.size.width - x - 10, 24); - self.title.center = CGPointMake(self.title.center.x, self.image.center.y); - self.describeTextView.mm_width(self.mm_w - 32).mm_height(_describeTextViewRect.size.height).mm_top(12 + 40 + 8).mm_left(16); +// this is Apple's recommended place for adding/updating constraints +- (void)updateConstraints { + + [super updateConstraints]; + [self.image mas_remakeConstraints:^(MASConstraintMaker *make) { + make.leading.mas_equalTo(self.contentView).mas_offset(16); + make.top.mas_equalTo(self.contentView).mas_offset(16); + make.width.height.mas_equalTo(40); + }]; + [self.title sizeToFit]; + [self.title mas_remakeConstraints:^(MASConstraintMaker *make) { + make.leading.mas_equalTo(self.image.mas_trailing).mas_offset(10); + make.centerY.mas_equalTo(self.image); + make.trailing.mas_equalTo(self.contentView).mas_offset(- 4); + }]; + + [self.describeTextView mas_remakeConstraints:^(MASConstraintMaker *make) { + make.leading.mas_equalTo(16); + make.trailing.mas_equalTo(self.contentView).mas_offset(-16); + make.top.mas_equalTo(self.image.mas_bottom).mas_offset(8); + make.height.mas_equalTo(_describeTextViewRect.size.height); + }]; + } - (void)setData:(TUIGroupTypeData *)data { @@ -110,6 +131,7 @@ _describeTextView.editable = NO; _describeTextView.scrollEnabled = NO; _describeTextView.textContainerInset = UIEdgeInsetsMake(0.f, 0.f, 0.f, 0.f); + _describeTextView.textAlignment = isRTL()?NSTextAlignmentRight:NSTextAlignmentLeft; } return _describeTextView; } @@ -121,7 +143,7 @@ if (@available(iOS 9.0, *)) { paragraphStyle.allowsDefaultTighteningForTruncation = YES; } - paragraphStyle.alignment = NSTextAlignmentJustified; + paragraphStyle.alignment = isRTL()?NSTextAlignmentRight: NSTextAlignmentLeft; NSDictionary *dictionary = @{ NSFontAttributeName : [UIFont systemFontOfSize:12], NSForegroundColorAttributeName : [UIColor tui_colorWithHex:@"#888888"], diff --git a/iOS/TUIKit/TUIContact/UI_Classic/UI/TUIProfileController.m b/iOS/TUIKit/TUIContact/UI_Classic/UI/TUIProfileController.m index d8311bbbd..3b0ee9214 100644 --- a/iOS/TUIKit/TUIContact/UI_Classic/UI/TUIProfileController.m +++ b/iOS/TUIKit/TUIContact/UI_Classic/UI/TUIProfileController.m @@ -54,7 +54,7 @@ [[V2TIMManager sharedInstance] addIMSDKListener:self]; NSString *loginUser = [[V2TIMManager sharedInstance] getLoginUser]; - [[V2TIMManager sharedInstance] getUsersInfo:@[ loginUser ] + [[V2TIMManager sharedInstance] getUsersInfo:@[ loginUser?:@"" ] succ:^(NSArray *infoList) { self.profile = infoList.firstObject; [self setupData]; diff --git a/iOS/TUIKit/TUIContact/UI_Classic/UI/TUISettingController.m b/iOS/TUIKit/TUIContact/UI_Classic/UI/TUISettingController.m index 63ce1092a..3d3ef37cd 100644 --- a/iOS/TUIKit/TUIContact/UI_Classic/UI/TUISettingController.m +++ b/iOS/TUIKit/TUIContact/UI_Classic/UI/TUISettingController.m @@ -143,9 +143,14 @@ static NSString *const kKeyViews = @"views"; // Used to pass custom views from // Extension settings. if (dict[kKeyViews] && [dict[kKeyViews] isKindOfClass:NSArray.class]) { UIView *view = dict[kKeyViews][indexPath.row]; - UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"containerCell" forIndexPath:indexPath]; - [cell addSubview:view]; - return cell; + if ([view isKindOfClass:[UITableViewCell class]] ) { + return (id)view; + } + else { + UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"containerCell" forIndexPath:indexPath]; + [cell addSubview:view]; + return cell; + } } // Built-in settings. NSArray *array = dict[kKeyItems]; diff --git a/iOS/TUIKit/TUIContact/UI_Minimalist/Cell/CellUI/TUICommonContactCell_Minimalist.h b/iOS/TUIKit/TUIContact/UI_Minimalist/Cell/CellUI/TUICommonContactCell_Minimalist.h index 69a774416..8d8b66b6c 100644 --- a/iOS/TUIKit/TUIContact/UI_Minimalist/Cell/CellUI/TUICommonContactCell_Minimalist.h +++ b/iOS/TUIKit/TUIContact/UI_Minimalist/Cell/CellUI/TUICommonContactCell_Minimalist.h @@ -1,4 +1,7 @@ - +// +// TUICommonContactCell_Minimalist.h +// +// // Created by Tencent on 2023/06/09. // Copyright © 2023 Tencent. All rights reserved. #import diff --git a/iOS/TUIKit/TUIContact/UI_Minimalist/Cell/CellUI/TUICommonContactCell_Minimalist.m b/iOS/TUIKit/TUIContact/UI_Minimalist/Cell/CellUI/TUICommonContactCell_Minimalist.m index 4bd2839d1..16e84e23b 100644 --- a/iOS/TUIKit/TUIContact/UI_Minimalist/Cell/CellUI/TUICommonContactCell_Minimalist.m +++ b/iOS/TUIKit/TUIContact/UI_Minimalist/Cell/CellUI/TUICommonContactCell_Minimalist.m @@ -68,27 +68,62 @@ self.onlineStatusIcon.image = nil; } }]; + // tell constraints they need updating + [self setNeedsUpdateConstraints]; + + // update constraints now so we can animate the change + [self updateConstraintsIfNeeded]; + + [self layoutIfNeeded]; } -- (void)layoutSubviews { - [super layoutSubviews]; - self.avatarView.frame = CGRectMake(kScale390(16), (self.bounds.size.height - kScale390(40)) * 0.5, kScale390(40), kScale390(40)); ++ (BOOL)requiresConstraintBasedLayout { + return YES; +} + +// this is Apple's recommended place for adding/updating constraints +- (void)updateConstraints { + + [super updateConstraints]; + CGFloat imgWidth = kScale390(40); + + [self.avatarView mas_remakeConstraints:^(MASConstraintMaker *make) { + make.width.height.mas_equalTo(imgWidth); + make.centerY.mas_equalTo(self.contentView.mas_centerY); + make.leading.mas_equalTo(kScale390(16)); + }]; if ([TUIConfig defaultConfig].avatarType == TAvatarTypeRounded) { self.avatarView.layer.masksToBounds = YES; - self.avatarView.layer.cornerRadius = self.avatarView.frame.size.height / 2; + self.avatarView.layer.cornerRadius = imgWidth / 2; } else if ([TUIConfig defaultConfig].avatarType == TAvatarTypeRadiusCorner) { self.avatarView.layer.masksToBounds = YES; self.avatarView.layer.cornerRadius = [TUIConfig defaultConfig].avatarCornerRadius; } - self.titleLabel.mm_left(self.avatarView.mm_maxX + 12).mm_height(20).mm__centerY(self.avatarView.mm_centerY).mm_flexToRight(0); + [self.titleLabel mas_remakeConstraints:^(MASConstraintMaker *make) { + make.centerY.mas_equalTo(self.avatarView.mas_centerY); + make.leading.mas_equalTo(self.avatarView.mas_trailing).mas_offset(12); + make.height.mas_equalTo(20); + make.trailing.mas_greaterThanOrEqualTo(self.contentView.mas_trailing); + + }]; + + [self.onlineStatusIcon mas_remakeConstraints:^(MASConstraintMaker *make) { + make.width.height.mas_equalTo(kScale375(15)); + make.trailing.mas_equalTo(self.avatarView.mas_trailing).mas_offset(kScale375(5)); + make.bottom.mas_equalTo(self.avatarView.mas_bottom); + }]; + self.onlineStatusIcon.layer.cornerRadius = 0.5 * kScale375(15); - self.onlineStatusIcon.mm_width(kScale * 15).mm_height(kScale * 15); - self.onlineStatusIcon.mm_x = CGRectGetMaxX(self.avatarView.frame) - 0.5 * self.onlineStatusIcon.mm_w - 3 * kScale; - self.onlineStatusIcon.mm_y = CGRectGetMaxY(self.avatarView.frame) - self.onlineStatusIcon.mm_w; - self.onlineStatusIcon.layer.cornerRadius = 0.5 * self.onlineStatusIcon.mm_w; - - self.separtorView.frame = CGRectMake(self.avatarView.mm_maxX, self.contentView.mm_h - 1, self.contentView.mm_w, 1); + [self.separtorView mas_remakeConstraints:^(MASConstraintMaker *make) { + make.width.mas_equalTo(self.contentView.mas_width); + make.height.mas_equalTo(1); + make.leading.mas_equalTo(self.avatarView.mas_trailing); + make.bottom.mas_equalTo(self.mas_bottom).mas_offset(-1); + }]; +} +- (void)layoutSubviews { + [super layoutSubviews]; } - (void)configHeadImageView:(TUICommonContactCellData_Minimalist *)convData { /** diff --git a/iOS/TUIKit/TUIContact/UI_Minimalist/Cell/CellUI/TUICommonContactProfileCardCell_Minimalist.h b/iOS/TUIKit/TUIContact/UI_Minimalist/Cell/CellUI/TUICommonContactProfileCardCell_Minimalist.h index 697605921..f8bd78053 100644 --- a/iOS/TUIKit/TUIContact/UI_Minimalist/Cell/CellUI/TUICommonContactProfileCardCell_Minimalist.h +++ b/iOS/TUIKit/TUIContact/UI_Minimalist/Cell/CellUI/TUICommonContactProfileCardCell_Minimalist.h @@ -1,4 +1,7 @@ - +// +// TUICommonContactProfileCardCell_Minimalist.h +// +// // Created by Tencent on 2023/06/09. // Copyright © 2023 Tencent. All rights reserved. #import diff --git a/iOS/TUIKit/TUIContact/UI_Minimalist/Cell/CellUI/TUICommonContactProfileCardCell_Minimalist.m b/iOS/TUIKit/TUIContact/UI_Minimalist/Cell/CellUI/TUICommonContactProfileCardCell_Minimalist.m index 13fdc8d48..2d631cf67 100644 --- a/iOS/TUIKit/TUIContact/UI_Minimalist/Cell/CellUI/TUICommonContactProfileCardCell_Minimalist.m +++ b/iOS/TUIKit/TUIContact/UI_Minimalist/Cell/CellUI/TUICommonContactProfileCardCell_Minimalist.m @@ -53,14 +53,6 @@ UITapGestureRecognizer *tapAvatar = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(onTapAvatar)]; [_avatar addGestureRecognizer:tapAvatar]; _avatar.userInteractionEnabled = YES; - - if ([TUIConfig defaultConfig].avatarType == TAvatarTypeRounded) { - self.avatar.layer.masksToBounds = YES; - self.avatar.layer.cornerRadius = headSize.height / 2; - } else if ([TUIConfig defaultConfig].avatarType == TAvatarTypeRadiusCorner) { - self.avatar.layer.masksToBounds = YES; - self.avatar.layer.cornerRadius = [TUIConfig defaultConfig].avatarCornerRadius; - } [self.contentView addSubview:_avatar]; // CGSize genderIconSize = CGSizeMake(20, 20); @@ -125,34 +117,89 @@ } else { self.accessoryType = UITableViewCellAccessoryNone; } + // tell constraints they need updating + [self setNeedsUpdateConstraints]; + + // update constraints now so we can animate the change + [self updateConstraintsIfNeeded]; + + [self layoutIfNeeded]; } -- (void)layoutSubviews { - [super layoutSubviews]; - // 此处解除 nameLabel 的 fit 宽度,使性别 icon 能够在短昵称情况下和 nameLabel 相邻。 - CGFloat maxLabelWidth = self.contentView.mm_w - CGRectGetMaxX(_avatar.frame) - 30; - _name.mm_sizeToFitThan(0, _avatar.mm_h / 3).mm_top(_avatar.mm_y).mm_left(_avatar.mm_maxX + kScale390(18)); - if (CGRectGetMaxX(_name.frame) >= self.contentView.mm_w) { - _name.mm_w = maxLabelWidth; + ++ (BOOL)requiresConstraintBasedLayout { + return YES; +} + +// this is Apple's recommended place for adding/updating constraints +- (void)updateConstraints { + + [super updateConstraints]; + CGSize headSize = CGSizeMake(kScale390(43), kScale390(43)); + + [self.avatar mas_remakeConstraints:^(MASConstraintMaker *make) { + make.size.mas_equalTo(headSize); + make.top.mas_equalTo(kScale390(10)); + make.leading.mas_equalTo(kScale390(16)); + }]; + + if ([TUIConfig defaultConfig].avatarType == TAvatarTypeRounded) { + self.avatar.layer.masksToBounds = YES; + self.avatar.layer.cornerRadius = headSize.height / 2; + } else if ([TUIConfig defaultConfig].avatarType == TAvatarTypeRadiusCorner) { + self.avatar.layer.masksToBounds = YES; + self.avatar.layer.cornerRadius = [TUIConfig defaultConfig].avatarCornerRadius; } - _identifier.mm_sizeToFitThan(80, _avatar.mm_h / 3).mm_left(_name.mm_x); + [self.name sizeToFit]; + [self.name mas_remakeConstraints:^(MASConstraintMaker *make) { + make.top.mas_equalTo(TPersonalCommonCell_Margin); + make.leading.mas_equalTo(self.avatar.mas_trailing).mas_offset(15); + make.width.mas_lessThanOrEqualTo(self.name.frame.size.width); + make.height.mas_greaterThanOrEqualTo(self.name.frame.size.height); + make.trailing.mas_lessThanOrEqualTo(self.genderIcon.mas_leading).mas_offset(- 1); + }]; + + [self.genderIcon mas_remakeConstraints:^(MASConstraintMaker *make) { + make.width.height.mas_equalTo(self.name.font.pointSize *0.9); + make.centerY.mas_equalTo(self.name); + make.leading.mas_equalTo(self.name.mas_trailing).mas_offset(1); + make.trailing.mas_lessThanOrEqualTo(self.contentView.mas_trailing).mas_offset(- 10); + }]; + + [self.identifier sizeToFit]; + [self.identifier mas_remakeConstraints:^(MASConstraintMaker *make) { + make.leading.mas_equalTo(self.name); + make.top.mas_equalTo(self.name.mas_bottom).mas_offset(5); + if(self.identifier.frame.size.width > 80) { + make.width.mas_greaterThanOrEqualTo(self.identifier.frame.size.width); + } + else { + make.width.mas_greaterThanOrEqualTo(@80); + } + make.height.mas_greaterThanOrEqualTo(self.identifier.frame.size.height); + make.trailing.mas_lessThanOrEqualTo(self.contentView.mas_trailing).mas_offset(-1); + }]; if (self.cardData.showSignature) { - _identifier.mm_y = _name.mm_y + _name.mm_h + 5; + [self.signature sizeToFit]; + [self.signature mas_remakeConstraints:^(MASConstraintMaker *make) { + make.leading.mas_equalTo(self.name); + make.top.mas_equalTo(self.identifier.mas_bottom).mas_offset(5); + if(self.signature.frame.size.width > 80) { + make.width.mas_greaterThanOrEqualTo(self.signature.frame.size.width); + } + else { + make.width.mas_greaterThanOrEqualTo(@80); + } + make.height.mas_greaterThanOrEqualTo(self.signature.frame.size.height); + make.trailing.mas_lessThanOrEqualTo(self.contentView.mas_trailing).mas_offset(-1); + }]; + } else { - _identifier.mm_bottom(_avatar.mm_b); + self.signature.frame = CGRectZero; } - _signature.mm_sizeToFitThan(80, _avatar.mm_h / 3).mm_left(_name.mm_x); - _signature.mm_y = CGRectGetMaxY(_identifier.frame) + 5; - if (CGRectGetMaxX(_signature.frame) >= self.contentView.mm_w) { - _signature.mm_w = maxLabelWidth; - } - - _genderIcon.mm_sizeToFitThan(_name.font.pointSize * 0.9, _name.font.pointSize * 0.9) - .mm__centerY(_name.mm_centerY) - .mm_left(_name.mm_x + _name.mm_w + kScale390(10)); } - (void)onTapAvatar { diff --git a/iOS/TUIKit/TUIContact/UI_Minimalist/Cell/CellUI/TUICommonContactSelectCell_Minimalist.h b/iOS/TUIKit/TUIContact/UI_Minimalist/Cell/CellUI/TUICommonContactSelectCell_Minimalist.h index 8091c604a..cfc69f480 100644 --- a/iOS/TUIKit/TUIContact/UI_Minimalist/Cell/CellUI/TUICommonContactSelectCell_Minimalist.h +++ b/iOS/TUIKit/TUIContact/UI_Minimalist/Cell/CellUI/TUICommonContactSelectCell_Minimalist.h @@ -1,4 +1,7 @@ - +// +// TUICommonContactSelectCell_Minimalist.h +// +// // Created by Tencent on 2023/06/09. // Copyright © 2023 Tencent. All rights reserved. diff --git a/iOS/TUIKit/TUIContact/UI_Minimalist/Cell/CellUI/TUICommonContactSelectCell_Minimalist.m b/iOS/TUIKit/TUIContact/UI_Minimalist/Cell/CellUI/TUICommonContactSelectCell_Minimalist.m index 3c6764e8a..987d4743e 100644 --- a/iOS/TUIKit/TUIContact/UI_Minimalist/Cell/CellUI/TUICommonContactSelectCell_Minimalist.m +++ b/iOS/TUIKit/TUIContact/UI_Minimalist/Cell/CellUI/TUICommonContactSelectCell_Minimalist.m @@ -51,16 +51,47 @@ self.titleLabel.textColor = TIMCommonDynamicColor(@"form_title_color", @"#000000"); self.titleLabel.autoresizingMask = UIViewAutoresizingFlexibleTopMargin | UIViewAutoresizingFlexibleBottomMargin; - - self.avatarView.mm_width(kScale390(40)).mm_height(kScale390(40)).mm__centerY(self.mm_centerY).mm_left(kScale390(16)); - self.selectButton.mm_sizeToFit().mm__centerY(self.mm_centerY).mm_right(kScale390(kScale390(42))); - self.titleLabel.mm_left(self.avatarView.mm_maxX + 12).mm_height(20).mm__centerY(self.avatarView.mm_centerY).mm_flexToRight(0); - self.selectionStyle = UITableViewCellSelectionStyleNone; } return self; } ++ (BOOL)requiresConstraintBasedLayout { + return YES; +} +// this is Apple's recommended place for adding/updating constraints +- (void)updateConstraints { + + [super updateConstraints]; + CGFloat imgWidth = kScale390(34); + + + [self.avatarView mas_remakeConstraints:^(MASConstraintMaker *make) { + make.width.height.mas_equalTo(imgWidth); + make.centerY.mas_equalTo(self.contentView.mas_centerY); + make.leading.mas_equalTo(kScale390(12)); + }]; + if ([TUIConfig defaultConfig].avatarType == TAvatarTypeRounded) { + self.avatarView.layer.masksToBounds = YES; + self.avatarView.layer.cornerRadius = imgWidth / 2; + } else if ([TUIConfig defaultConfig].avatarType == TAvatarTypeRadiusCorner) { + self.avatarView.layer.masksToBounds = YES; + self.avatarView.layer.cornerRadius = [TUIConfig defaultConfig].avatarCornerRadius; + } + + [self.titleLabel mas_remakeConstraints:^(MASConstraintMaker *make) { + make.centerY.mas_equalTo(self.avatarView.mas_centerY); + make.leading.mas_equalTo(self.avatarView.mas_trailing).mas_offset(12); + make.height.mas_equalTo(20); + make.trailing.mas_greaterThanOrEqualTo(self.contentView.mas_trailing); + }]; + + [self.selectButton mas_remakeConstraints:^(MASConstraintMaker *make) { + make.centerY.mas_equalTo(self.contentView.mas_centerY); + make.trailing.mas_equalTo(self.contentView.mas_trailing).mas_offset(-kScale390(20)); + make.width.height.mas_equalTo(20); + }]; +} - (void)layoutSubviews { [super layoutSubviews]; } @@ -76,15 +107,16 @@ } else { [self.avatarView setImage:DefaultAvatarImage]; } - if ([TUIConfig defaultConfig].avatarType == TAvatarTypeRounded) { - self.avatarView.layer.masksToBounds = YES; - self.avatarView.layer.cornerRadius = self.avatarView.frame.size.height / 2; - } else if ([TUIConfig defaultConfig].avatarType == TAvatarTypeRadiusCorner) { - self.avatarView.layer.masksToBounds = YES; - self.avatarView.layer.cornerRadius = [TUIConfig defaultConfig].avatarCornerRadius; - } [self.selectButton setSelected:selectData.isSelected]; self.selectButton.enabled = selectData.enabled; + // tell constraints they need updating + [self setNeedsUpdateConstraints]; + + // update constraints now so we can animate the change + [self updateConstraintsIfNeeded]; + + [self layoutIfNeeded]; + } @end diff --git a/iOS/TUIKit/TUIContact/UI_Minimalist/Cell/CellUI/TUICommonContactSwitchCell_Minimalist.m b/iOS/TUIKit/TUIContact/UI_Minimalist/Cell/CellUI/TUICommonContactSwitchCell_Minimalist.m index ddb47afe5..c5214a5c9 100644 --- a/iOS/TUIKit/TUIContact/UI_Minimalist/Cell/CellUI/TUICommonContactSwitchCell_Minimalist.m +++ b/iOS/TUIKit/TUIContact/UI_Minimalist/Cell/CellUI/TUICommonContactSwitchCell_Minimalist.m @@ -51,14 +51,14 @@ _titleLabel = [[UILabel alloc] init]; _titleLabel.textColor = TIMCommonDynamicColor(@"form_key_text_color", @"#444444"); _titleLabel.font = [UIFont systemFontOfSize:16]; - _titleLabel.textAlignment = NSTextAlignmentLeft; + _titleLabel.rtlAlignment = TUITextRTLAlignmentLeading; [self.contentView addSubview:_titleLabel]; _descLabel = [[UILabel alloc] init]; _descLabel.textColor = TIMCommonDynamicColor(@"group_modify_desc_color", @"#888888"); _descLabel.font = [UIFont systemFontOfSize:12]; _descLabel.numberOfLines = 0; - _descLabel.textAlignment = NSTextAlignmentLeft; + _descLabel.rtlAlignment = TUITextRTLAlignmentLeading; _descLabel.hidden = YES; [self.contentView addSubview:_descLabel]; @@ -80,11 +80,27 @@ _titleLabel.text = switchData.title; [_switcher setOn:switchData.isOn]; - if (switchData.desc.length > 0) { - _descLabel.text = switchData.desc; + // tell constraints they need updating + [self setNeedsUpdateConstraints]; + + // update constraints now so we can animate the change + [self updateConstraintsIfNeeded]; + + [self layoutIfNeeded]; +} ++ (BOOL)requiresConstraintBasedLayout { + return YES; +} + +// this is Apple's recommended place for adding/updating constraints +- (void)updateConstraints { + + [super updateConstraints]; + if (self.switchData.desc.length > 0) { + _descLabel.text = self.switchData.desc; _descLabel.hidden = NO; - NSString *str = switchData.desc; + NSString *str = self.switchData.desc; NSDictionary *attribute = @{NSFontAttributeName : [UIFont systemFontOfSize:12]}; CGSize size = [str boundingRectWithSize:CGSizeMake(264, 999) options:NSStringDrawingTruncatesLastVisibleLine | NSStringDrawingUsesLineFragmentOrigin | NSStringDrawingUsesFontLeading @@ -92,13 +108,28 @@ context:nil] .size; - _titleLabel.mm_width(size.width).mm_height(24).mm_left(switchData.margin).mm_top(12); - _descLabel.mm_width(size.width).mm_height(size.height).mm_left(_titleLabel.mm_x).mm_top(self.titleLabel.mm_maxY + 2); + [self.titleLabel mas_remakeConstraints:^(MASConstraintMaker *make) { + make.width.mas_equalTo(size.width); + make.height.mas_equalTo(24); + make.leading.mas_equalTo(self.switchData.margin); + make.top.mas_equalTo(12); + }]; + [self.descLabel mas_remakeConstraints:^(MASConstraintMaker *make) { + make.width.mas_equalTo(size.width); + make.height.mas_equalTo(size.height); + make.leading.mas_equalTo(self.titleLabel.mas_leading); + make.top.mas_equalTo(self.titleLabel.mas_bottom).mas_offset(2); + }]; } else { - _titleLabel.mm_sizeToFit().mm_left(switchData.margin).mm__centerY(self.contentView.mm_h / 2); + [self.titleLabel sizeToFit]; + [self.titleLabel mas_remakeConstraints:^(MASConstraintMaker *make) { + make.size.mas_equalTo(self.titleLabel.frame.size); + make.leading.mas_equalTo(self.switchData.margin); + make.centerY.mas_equalTo(self.contentView); + }]; } + } - - (void)switchClick { if (self.switchData.cswitchSelector) { UIViewController *vc = self.mm_viewController; diff --git a/iOS/TUIKit/TUIContact/UI_Minimalist/Cell/CellUI/TUICommonContactTextCell_Minimalist.m b/iOS/TUIKit/TUIContact/UI_Minimalist/Cell/CellUI/TUICommonContactTextCell_Minimalist.m index ca57cbe0d..d633bc7fd 100644 --- a/iOS/TUIKit/TUIContact/UI_Minimalist/Cell/CellUI/TUICommonContactTextCell_Minimalist.m +++ b/iOS/TUIKit/TUIContact/UI_Minimalist/Cell/CellUI/TUICommonContactTextCell_Minimalist.m @@ -44,39 +44,25 @@ if (self = [super initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:reuseIdentifier]) { self.backgroundColor = TIMCommonDynamicColor(@"", @"#f9f9f9"); self.contentView.backgroundColor = TIMCommonDynamicColor(@"", @"#f9f9f9"); - - _keyLabel = self.textLabel; + + _keyLabel = [[UILabel alloc] init]; _keyLabel.textColor = TIMCommonDynamicColor(@"form_key_text_color", @"#444444"); _keyLabel.font = [UIFont systemFontOfSize:16.0]; + [self.contentView addSubview:_keyLabel]; + [_keyLabel setRtlAlignment:TUITextRTLAlignmentTrailing]; + + _valueLabel = [[UILabel alloc] init]; + [self.contentView addSubview:_valueLabel]; - _valueLabel = self.detailTextLabel; _valueLabel.textColor = TIMCommonDynamicColor(@"form_value_text_color", @"#000000"); _valueLabel.font = [UIFont systemFontOfSize:16.0]; + [_valueLabel setRtlAlignment:TUITextRTLAlignmentTrailing]; self.selectionStyle = UITableViewCellSelectionStyleNone; } return self; } -- (void)layoutSubviews { - [super layoutSubviews]; - - if (self.textData.keyEdgeInsets.left) { - self.keyLabel.mm_left(self.textData.keyEdgeInsets.left); - } - - if (self.textData.keyEdgeInsets.top) { - self.keyLabel.mm_top(self.textData.keyEdgeInsets.top); - } - - if (self.textData.keyEdgeInsets.bottom) { - self.keyLabel.mm_bottom(self.textData.keyEdgeInsets.bottom); - } - - if (self.textData.keyEdgeInsets.right) { - self.keyLabel.mm_right(self.textData.keyEdgeInsets.right); - } -} - (void)fillWithData:(TUICommonContactTextCellData_Minimalist *)textData { [super fillWithData:textData]; @@ -104,6 +90,41 @@ } else { self.valueLabel.numberOfLines = 1; } + // tell constraints they need updating + [self setNeedsUpdateConstraints]; + + // update constraints now so we can animate the change + [self updateConstraintsIfNeeded]; + + [self layoutIfNeeded]; } ++ (BOOL)requiresConstraintBasedLayout { + return YES; +} + +// this is Apple's recommended place for adding/updating constraints +- (void)updateConstraints { + + [super updateConstraints]; + + [self.keyLabel sizeToFit]; + [self.keyLabel mas_remakeConstraints:^(MASConstraintMaker *make) { + make.size.mas_equalTo(self.keyLabel.frame.size); + make.leading.mas_equalTo(self.contentView).mas_offset(self.textData.keyEdgeInsets.left); + make.centerY.mas_equalTo(self.contentView); + }]; + + [self.valueLabel sizeToFit]; + [self.valueLabel mas_remakeConstraints:^(MASConstraintMaker *make) { + make.leading.mas_equalTo(self.keyLabel.mas_trailing).mas_offset(10); + if (self.textData.showAccessory) { + make.trailing.mas_equalTo(self.contentView.mas_trailing).mas_offset(-10); + } + else { + make.trailing.mas_equalTo(self.contentView.mas_trailing).mas_offset(-20); + } + make.centerY.mas_equalTo(self.contentView); + }]; +} @end diff --git a/iOS/TUIKit/TUIContact/UI_Minimalist/Cell/CellUI/TUICommonPendencyCell_Minimalist.h b/iOS/TUIKit/TUIContact/UI_Minimalist/Cell/CellUI/TUICommonPendencyCell_Minimalist.h index 87f12e00c..1948f39b7 100644 --- a/iOS/TUIKit/TUIContact/UI_Minimalist/Cell/CellUI/TUICommonPendencyCell_Minimalist.h +++ b/iOS/TUIKit/TUIContact/UI_Minimalist/Cell/CellUI/TUICommonPendencyCell_Minimalist.h @@ -14,15 +14,14 @@ NS_ASSUME_NONNULL_BEGIN @interface TUICommonPendencyCell_Minimalist : TUICommonTableViewCell -@property UIImageView *avatarView; -@property UILabel *titleLabel; -@property UILabel *addSourceLabel; -@property UILabel *addWordingLabel; -@property UIButton *agreeButton; -@property UIButton *rejectButton; -@property UIStackView *stackView; - -@property(nonatomic) TUICommonPendencyCellData_Minimalist *pendencyData; +@property(nonatomic,strong) UIImageView *avatarView; +@property(nonatomic,strong) UILabel *titleLabel; +@property(nonatomic,strong) UILabel *addSourceLabel; +@property(nonatomic,strong) UILabel *addWordingLabel; +@property(nonatomic,strong) UIButton *agreeButton; +@property(nonatomic,strong) UIButton *rejectButton; +@property(nonatomic,strong) UIStackView *stackView; +@property(nonatomic,strong) TUICommonPendencyCellData_Minimalist *pendencyData; - (void)fillWithData:(TUICommonPendencyCellData_Minimalist *)pendencyData; diff --git a/iOS/TUIKit/TUIContact/UI_Minimalist/Cell/CellUI/TUICommonPendencyCell_Minimalist.m b/iOS/TUIKit/TUIContact/UI_Minimalist/Cell/CellUI/TUICommonPendencyCell_Minimalist.m index 9e1222ce2..667c07df6 100644 --- a/iOS/TUIKit/TUIContact/UI_Minimalist/Cell/CellUI/TUICommonPendencyCell_Minimalist.m +++ b/iOS/TUIKit/TUIContact/UI_Minimalist/Cell/CellUI/TUICommonPendencyCell_Minimalist.m @@ -65,23 +65,6 @@ // Configure the view for the selected state } -- (void)layoutSubviews { - [super layoutSubviews]; - self.avatarView.mm_width(kScale390(40)).mm_height(kScale390(40)).mm__centerY(self.contentView.mm_h / 2).mm_left(kScale390(16)); - if ([TUIConfig defaultConfig].avatarType == TAvatarTypeRounded) { - self.avatarView.layer.masksToBounds = YES; - self.avatarView.layer.cornerRadius = self.avatarView.frame.size.height / 2; - } else if ([TUIConfig defaultConfig].avatarType == TAvatarTypeRadiusCorner) { - self.avatarView.layer.masksToBounds = YES; - self.avatarView.layer.cornerRadius = [TUIConfig defaultConfig].avatarCornerRadius; - } - - self.titleLabel.mm_left(self.avatarView.mm_maxX + kScale390(12)).mm_top(kScale390(8)).mm_height(20).mm_width(120); - - // self.addSourceLabel.mm_left(self.titleLabel.mm_x).mm_top(self.titleLabel.mm_maxY+6).mm_height(15).mm_width(120); - - self.addWordingLabel.mm_left(self.titleLabel.mm_x).mm_top(self.titleLabel.mm_maxY + 4).mm_height(15).mm_width(120); -} - (void)fillWithData:(TUICommonPendencyCellData_Minimalist *)pendencyData { [super fillWithData:pendencyData]; @@ -125,11 +108,6 @@ self.rejectButton.layer.cornerRadius = kScale390(10); [self.rejectButton setTitleColor:TIMCommonDynamicColor(@"", @"#FF584C") forState:UIControlStateNormal]; } - - self.agreeButton.mm_sizeToFit().mm_width(kScale390(69)); - self.rejectButton.mm_left(CGRectGetMaxX(self.agreeButton.frame) + 10).mm_sizeToFit().mm_width(kScale390(76)); - self.stackView.bounds = CGRectMake(0, 0, 2 * self.agreeButton.mm_w + 10, self.agreeButton.mm_h); - if (self.pendencyData.isRejected && !self.pendencyData.isAccepted) { self.agreeButton.hidden = YES; self.rejectButton.hidden = NO; @@ -142,8 +120,69 @@ } self.addSourceLabel.hidden = self.pendencyData.hideSource; + + // tell constraints they need updating + [self setNeedsUpdateConstraints]; + + // update constraints now so we can animate the change + [self updateConstraintsIfNeeded]; + + [self layoutIfNeeded]; } ++ (BOOL)requiresConstraintBasedLayout { + return YES; +} + +// this is Apple's recommended place for adding/updating constraints +- (void)updateConstraints { + + [super updateConstraints]; + CGSize headSize = CGSizeMake(kScale390(40), kScale390(40)); + + [self.avatarView mas_remakeConstraints:^(MASConstraintMaker *make) { + make.size.mas_equalTo(headSize); + make.leading.mas_equalTo(kScale390(16)); + make.centerY.mas_equalTo(self.contentView); + }]; + + if ([TUIConfig defaultConfig].avatarType == TAvatarTypeRounded) { + self.avatarView.layer.masksToBounds = YES; + self.avatarView.layer.cornerRadius = headSize.height / 2; + } else if ([TUIConfig defaultConfig].avatarType == TAvatarTypeRadiusCorner) { + self.avatarView.layer.masksToBounds = YES; + self.avatarView.layer.cornerRadius = [TUIConfig defaultConfig].avatarCornerRadius; + } + + [self.titleLabel mas_remakeConstraints:^(MASConstraintMaker *make) { + make.top.mas_equalTo(self.contentView.mas_top).mas_offset(kScale390(8)); + make.leading.mas_equalTo(self.avatarView.mas_trailing).mas_offset(kScale390(12)); + make.height.mas_equalTo(20); + make.width.mas_equalTo(120); + }]; + + [self.addWordingLabel mas_remakeConstraints:^(MASConstraintMaker *make) { + make.top.mas_equalTo(self.titleLabel.mas_bottom).mas_offset(4); + make.leading.mas_equalTo(self.titleLabel.mas_leading); + make.height.mas_equalTo(15); + make.width.mas_equalTo(120); + }]; + + [self.agreeButton sizeToFit]; + [self.agreeButton mas_remakeConstraints:^(MASConstraintMaker *make) { + make.leading.mas_equalTo(self.stackView.mas_leading); + make.centerY.mas_equalTo(self.stackView); + make.height.mas_equalTo(self.agreeButton.frame.size.height); + make.width.mas_equalTo(kScale390(69)); + }]; + [self.rejectButton sizeToFit]; + [self.rejectButton mas_remakeConstraints:^(MASConstraintMaker *make) { + make.leading.mas_equalTo(self.agreeButton.mas_trailing).mas_offset(10); + make.height.mas_equalTo(self.rejectButton.frame.size.height); + make.width.mas_equalTo(kScale390(76)); + }]; + self.stackView.bounds = CGRectMake(0, 0, kScale390(69) + kScale390(76) +10, self.agreeButton.mm_h); +} - (void)agreeClick { if (self.pendencyData.cbuttonSelector) { UIViewController *vc = self.mm_viewController; diff --git a/iOS/TUIKit/TUIContact/UI_Minimalist/Cell/CellUI/TUIContactAcceptRejectCell_Minimalist.m b/iOS/TUIKit/TUIContact/UI_Minimalist/Cell/CellUI/TUIContactAcceptRejectCell_Minimalist.m index f5a4e7446..6adbd3f06 100644 --- a/iOS/TUIKit/TUIContact/UI_Minimalist/Cell/CellUI/TUIContactAcceptRejectCell_Minimalist.m +++ b/iOS/TUIKit/TUIContact/UI_Minimalist/Cell/CellUI/TUIContactAcceptRejectCell_Minimalist.m @@ -71,27 +71,65 @@ self.rejectButton.backgroundColor = [UIColor tui_colorWithHex:@"f9f9f9"]; } + + // tell constraints they need updating + [self setNeedsUpdateConstraints]; + + // update constraints now so we can animate the change + [self updateConstraintsIfNeeded]; + + [self layoutIfNeeded]; +} + ++ (BOOL)requiresConstraintBasedLayout { + return YES; +} + +// this is Apple's recommended place for adding/updating constraints +- (void)updateConstraints { + + [super updateConstraints]; CGFloat margin = kScale390(25); CGFloat padding = kScale390(20); CGFloat btnWidth = (self.contentView.frame.size.width - 2 * margin - padding) * 0.5; CGFloat btnHeight = kScale390(42); - self.agreeButton.frame = CGRectMake(margin, 0, btnWidth, btnHeight); - self.rejectButton.frame = CGRectMake(margin + btnWidth + padding, 0, btnWidth, btnHeight); - - if (data.isRejected && !data.isAccepted) { + + [self.agreeButton mas_remakeConstraints:^(MASConstraintMaker *make) { + make.leading.mas_equalTo(self.contentView.mas_leading).mas_offset(margin); + make.trailing.mas_equalTo(self.rejectButton.mas_leading).mas_offset(- padding); + make.top.mas_equalTo(self.contentView); + make.height.mas_equalTo(btnHeight); + }]; + [self.rejectButton mas_remakeConstraints:^(MASConstraintMaker *make) { + make.width.mas_equalTo(self.agreeButton); + make.trailing.mas_equalTo(self.contentView.mas_trailing).mas_offset(- margin); + make.top.mas_equalTo(self.contentView); + make.height.mas_equalTo(btnHeight); + }]; + if (self.acceptRejectData.isRejected && !self.acceptRejectData.isAccepted) { self.agreeButton.hidden = YES; self.rejectButton.hidden = NO; - self.rejectButton.frame = CGRectMake(margin, 0, 2 * btnWidth + padding, btnHeight); - } else if (data.isAccepted && !data.isRejected) { + [self.rejectButton mas_remakeConstraints:^(MASConstraintMaker *make) { + make.leading.mas_equalTo(self.contentView.mas_leading).mas_offset(margin); + make.trailing.mas_equalTo(self.contentView.mas_trailing).mas_offset(- margin); + make.top.mas_equalTo(self.contentView); + make.height.mas_equalTo(btnHeight); + }]; + } else if (self.acceptRejectData.isAccepted && !self.acceptRejectData.isRejected) { self.agreeButton.hidden = NO; self.rejectButton.hidden = YES; - self.agreeButton.frame = CGRectMake(margin, 0, 2 * btnWidth + padding, btnHeight); + [self.agreeButton mas_remakeConstraints:^(MASConstraintMaker *make) { + make.leading.mas_equalTo(self.contentView.mas_leading).mas_offset(margin); + make.trailing.mas_equalTo(self.contentView.mas_trailing).mas_offset(- margin); + make.top.mas_equalTo(self.contentView); + make.height.mas_equalTo(btnHeight); + }]; } else { self.agreeButton.hidden = NO; self.rejectButton.hidden = NO; } + } - - (void)agreeClick { if (self.acceptRejectData.agreeClickCallback) { self.acceptRejectData.agreeClickCallback(); diff --git a/iOS/TUIKit/TUIContact/UI_Minimalist/Cell/CellUI/TUIContactActionCell_Minimalist.m b/iOS/TUIKit/TUIContact/UI_Minimalist/Cell/CellUI/TUIContactActionCell_Minimalist.m index 3b78e1b7d..e08a266d4 100644 --- a/iOS/TUIKit/TUIContact/UI_Minimalist/Cell/CellUI/TUIContactActionCell_Minimalist.m +++ b/iOS/TUIKit/TUIContact/UI_Minimalist/Cell/CellUI/TUIContactActionCell_Minimalist.m @@ -44,23 +44,58 @@ - (void)fillWithData:(TUIContactActionCellData_Minimalist *)actionData { [super fillWithData:actionData]; self.actionData = actionData; - self.titleLabel.text = actionData.title; - - [self.titleLabel sizeToFit]; - self.titleLabel.frame = CGRectMake(kScale390(16), (self.contentView.frame.size.height - self.titleLabel.frame.size.height) * 0.5, - self.titleLabel.frame.size.width, self.titleLabel.frame.size.height); - - self.line.hidden = actionData.needBottomLine ? NO : YES; - self.line.frame = CGRectMake(0, self.contentView.frame.size.height - 1, self.contentView.frame.size.width, 1); - @weakify(self); [[RACObserve(self.actionData, readNum) takeUntil:self.rac_prepareForReuseSignal] subscribeNext:^(NSNumber *x) { @strongify(self); [self.unRead setNum:[x integerValue]]; }]; + self.line.hidden = self.actionData.needBottomLine ? NO : YES; + + // tell constraints they need updating + [self setNeedsUpdateConstraints]; - self.unRead.mm__centerY(self.titleLabel.mm_centerY).mm_right(self.accessoryView.mm_w); + // update constraints now so we can animate the change + [self updateConstraintsIfNeeded]; + + [self layoutIfNeeded]; + +} ++ (BOOL)requiresConstraintBasedLayout { + return YES; } +// this is Apple's recommended place for adding/updating constraints +- (void)updateConstraints { + + [super updateConstraints]; + [self.titleLabel sizeToFit]; + [self.titleLabel mas_remakeConstraints:^(MASConstraintMaker *make) { + make.centerY.mas_equalTo(self.contentView.mas_centerY); + make.leading.mas_equalTo(self.contentView.mas_leading).mas_offset(kScale390(16)); + make.width.mas_equalTo(self.titleLabel.frame.size.width); + make.height.mas_equalTo(self.titleLabel.frame.size.height); + }]; + + [self.unRead.unReadLabel sizeToFit]; + [self.unRead mas_remakeConstraints:^(MASConstraintMaker *make) { + make.centerY.mas_equalTo(self.contentView.mas_centerY); + make.trailing.mas_equalTo(self.contentView.mas_trailing).mas_offset(-5); + make.width.mas_equalTo(kScale375(20)); + make.height.mas_equalTo(kScale375(20)); + }]; + [self.unRead.unReadLabel mas_remakeConstraints:^(MASConstraintMaker *make) { + make.center.mas_equalTo(self.unRead); + make.size.mas_equalTo(self.unRead.unReadLabel); + }]; + self.unRead.layer.cornerRadius = kScale375(10); + [self.unRead.layer masksToBounds]; + + [self.line mas_remakeConstraints:^(MASConstraintMaker *make) { + make.bottom.mas_equalTo(self.contentView.mas_bottom).mas_offset(-1); + make.width.mas_equalTo(self.contentView); + make.height.mas_equalTo(1); + make.leading.mas_equalTo(self.contentView.mas_leading); + }]; +} @end diff --git a/iOS/TUIKit/TUIContact/UI_Minimalist/Cell/CellUI/TUIContactButtonCell_Minimalist.m b/iOS/TUIKit/TUIContact/UI_Minimalist/Cell/CellUI/TUIContactButtonCell_Minimalist.m index 147c1c22f..0345acde4 100644 --- a/iOS/TUIKit/TUIContact/UI_Minimalist/Cell/CellUI/TUIContactButtonCell_Minimalist.m +++ b/iOS/TUIKit/TUIContact/UI_Minimalist/Cell/CellUI/TUIContactButtonCell_Minimalist.m @@ -46,7 +46,12 @@ [super fillWithData:data]; self.buttonData = data; [_button setTitle:data.title forState:UIControlStateNormal]; - _button.contentHorizontalAlignment = UIControlContentHorizontalAlignmentLeft; + if(isRTL()) { + _button.contentHorizontalAlignment = UIControlContentHorizontalAlignmentRight; + } + else { + _button.contentHorizontalAlignment = UIControlContentHorizontalAlignmentLeft; + } _button.titleEdgeInsets = UIEdgeInsetsMake(0, 0, 0, 0); switch (data.style) { @@ -83,13 +88,42 @@ } _line.hidden = data.hideSeparatorLine; + + // tell constraints they need updating + [self setNeedsUpdateConstraints]; + + // update constraints now so we can animate the change + [self updateConstraintsIfNeeded]; + + [self layoutIfNeeded]; +} + ++ (BOOL)requiresConstraintBasedLayout { + return YES; +} + +// this is Apple's recommended place for adding/updating constraints +- (void)updateConstraints { + + [super updateConstraints]; + [self.button mas_remakeConstraints:^(MASConstraintMaker *make) { + make.leading.mas_equalTo(self.contentView.mas_leading).mas_offset(kScale390(20)); + make.trailing.mas_equalTo(self.contentView.mas_trailing).mas_offset(- kScale390(20)); + make.top.mas_equalTo(self.contentView); + make.bottom.mas_equalTo(self.contentView); + }]; + + [_line mas_remakeConstraints:^(MASConstraintMaker *make) { + make.leading.mas_equalTo(self.contentView.mas_leading).mas_offset(20); + make.trailing.mas_equalTo(self.contentView.mas_trailing); + make.height.mas_equalTo(0.2); + make.bottom.mas_equalTo(self.contentView); + }]; } - (void)layoutSubviews { [super layoutSubviews]; - _button.mm_width(Screen_Width - 2 * kScale390(20)).mm_height(self.mm_h - TButtonCell_Margin).mm_left(kScale390(20)); - _line.mm_width(Screen_Width).mm_height(0.2).mm_left(20).mm_bottom(0); } - (void)onClick:(UIButton *)sender { diff --git a/iOS/TUIKit/TUIContact/UI_Minimalist/Cell/CellUI/TUIContactProfileCardCell_Minimalist.m b/iOS/TUIKit/TUIContact/UI_Minimalist/Cell/CellUI/TUIContactProfileCardCell_Minimalist.m index 48dafd841..8b103eb86 100644 --- a/iOS/TUIKit/TUIContact/UI_Minimalist/Cell/CellUI/TUIContactProfileCardCell_Minimalist.m +++ b/iOS/TUIKit/TUIContact/UI_Minimalist/Cell/CellUI/TUIContactProfileCardCell_Minimalist.m @@ -28,14 +28,6 @@ UITapGestureRecognizer *tapAvatar = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(onTapAvatar)]; [_avatar addGestureRecognizer:tapAvatar]; _avatar.userInteractionEnabled = YES; - - if ([TUIConfig defaultConfig].avatarType == TAvatarTypeRounded) { - self.avatar.layer.masksToBounds = YES; - self.avatar.layer.cornerRadius = headSize.height / 2; - } else if ([TUIConfig defaultConfig].avatarType == TAvatarTypeRadiusCorner) { - self.avatar.layer.masksToBounds = YES; - self.avatar.layer.cornerRadius = [TUIConfig defaultConfig].avatarCornerRadius; - } [self.contentView addSubview:_avatar]; // CGSize genderIconSize = CGSizeMake(20, 20); @@ -102,33 +94,92 @@ } else { self.accessoryType = UITableViewCellAccessoryNone; } + // tell constraints they need updating + [self setNeedsUpdateConstraints]; + + // update constraints now so we can animate the change + [self updateConstraintsIfNeeded]; + + [self layoutIfNeeded]; +} ++ (BOOL)requiresConstraintBasedLayout { + return YES; +} + +// this is Apple's recommended place for adding/updating constraints +- (void)updateConstraints { + + [super updateConstraints]; + self.backgroundColor = [UIColor redColor]; + CGSize headSize = CGSizeMake(kScale390(66), kScale390(66)); + + [self.avatar mas_remakeConstraints:^(MASConstraintMaker *make) { + make.size.mas_equalTo(headSize); + make.top.mas_equalTo(kScale390(10)); + make.leading.mas_equalTo(kScale390(16)); + }]; + + if ([TUIConfig defaultConfig].avatarType == TAvatarTypeRounded) { + self.avatar.layer.masksToBounds = YES; + self.avatar.layer.cornerRadius = headSize.height / 2; + } else if ([TUIConfig defaultConfig].avatarType == TAvatarTypeRadiusCorner) { + self.avatar.layer.masksToBounds = YES; + self.avatar.layer.cornerRadius = [TUIConfig defaultConfig].avatarCornerRadius; + } + + [self.name sizeToFit]; + [self.name mas_remakeConstraints:^(MASConstraintMaker *make) { + make.top.mas_equalTo(TPersonalCommonCell_Margin); + make.leading.mas_equalTo(self.avatar.mas_trailing).mas_offset(15); + make.width.mas_lessThanOrEqualTo(self.name.frame.size.width); + make.height.mas_greaterThanOrEqualTo(self.name.frame.size.height); + make.trailing.mas_lessThanOrEqualTo(self.genderIcon.mas_leading).mas_offset(- 1); + }]; + + [self.genderIcon mas_remakeConstraints:^(MASConstraintMaker *make) { + make.width.height.mas_equalTo(self.name.font.pointSize *0.9); + make.centerY.mas_equalTo(self.name); + make.leading.mas_equalTo(self.name.mas_trailing).mas_offset(1); + make.trailing.mas_lessThanOrEqualTo(self.contentView.mas_trailing).mas_offset(- 10); + }]; + + [self.identifier sizeToFit]; + [self.identifier mas_remakeConstraints:^(MASConstraintMaker *make) { + make.leading.mas_equalTo(self.name); + make.top.mas_equalTo(self.name.mas_bottom).mas_offset(5); + if(self.identifier.frame.size.width > 80) { + make.width.mas_greaterThanOrEqualTo(self.identifier.frame.size.width); + } + else { + make.width.mas_greaterThanOrEqualTo(@80); + } + make.height.mas_greaterThanOrEqualTo(self.identifier.frame.size.height); + make.trailing.mas_lessThanOrEqualTo(self.contentView.mas_trailing).mas_offset(-1); + }]; + + if (self.cardData.showSignature) { + [self.signature sizeToFit]; + [self.signature mas_remakeConstraints:^(MASConstraintMaker *make) { + make.leading.mas_equalTo(self.name); + make.top.mas_equalTo(self.identifier.mas_bottom).mas_offset(5); + if(self.signature.frame.size.width > 80) { + make.width.mas_greaterThanOrEqualTo(self.signature.frame.size.width); + } + else { + make.width.mas_greaterThanOrEqualTo(@80); + } + make.height.mas_greaterThanOrEqualTo(self.signature.frame.size.height); + make.trailing.mas_lessThanOrEqualTo(self.contentView.mas_trailing).mas_offset(-1); + }]; + + } else { + self.signature.frame = CGRectZero; + } + } - (void)layoutSubviews { [super layoutSubviews]; - CGFloat maxLabelWidth = self.contentView.mm_w - CGRectGetMaxX(_avatar.frame) - 30; - _name.mm_sizeToFitThan(0, _avatar.mm_h / 5).mm_top(_avatar.mm_y).mm_left(_avatar.mm_maxX + kScale390(8)); - if (CGRectGetMaxX(_name.frame) >= self.contentView.mm_w) { - _name.mm_w = maxLabelWidth; - } - - _identifier.mm_sizeToFitThan(80, _avatar.mm_h / 5).mm_left(_name.mm_x); - - if (self.cardData.showSignature) { - _identifier.mm_y = _name.mm_y + _name.mm_h + 5; - } else { - _identifier.mm_bottom(_avatar.mm_b); - } - - _signature.mm_sizeToFitThan(80, _avatar.mm_h / 3).mm_left(_name.mm_x); - _signature.mm_y = CGRectGetMaxY(_identifier.frame) + 5; - if (CGRectGetMaxX(_signature.frame) >= self.contentView.mm_w) { - _signature.mm_w = maxLabelWidth; - } - - _genderIcon.mm_sizeToFitThan(_name.font.pointSize * 0.9, _name.font.pointSize * 0.9) - .mm__centerY(_name.mm_centerY) - .mm_left(_name.mm_x + _name.mm_w + TPersonalCommonCell_Margin); } - (void)onTapAvatar { diff --git a/iOS/TUIKit/TUIContact/UI_Minimalist/Cell/CellUI/TUIFindContactCell_Minimalist.m b/iOS/TUIKit/TUIContact/UI_Minimalist/Cell/CellUI/TUIFindContactCell_Minimalist.m index a3721e5ec..1f0ddfeca 100644 --- a/iOS/TUIKit/TUIContact/UI_Minimalist/Cell/CellUI/TUIFindContactCell_Minimalist.m +++ b/iOS/TUIKit/TUIContact/UI_Minimalist/Cell/CellUI/TUIFindContactCell_Minimalist.m @@ -38,34 +38,62 @@ [self.avatarView sd_setImageWithURL:data.avatarUrl placeholderImage:data.avatar ?: placeHolder]; self.descLabel.hidden = (data.type == TUIFindContactTypeC2C_Minimalist); + + // tell constraints they need updating + [self setNeedsUpdateConstraints]; + + // update constraints now so we can animate the change + [self updateConstraintsIfNeeded]; + + [self layoutIfNeeded]; } -- (void)layoutSubviews { - [super layoutSubviews]; ++ (BOOL)requiresConstraintBasedLayout { + return YES; +} - self.avatarView.mm_left(16 * kScale).mm_top(10 * kScale).mm_width(43 * kScale).mm_height(43 * kScale); +// this is Apple's recommended place for adding/updating constraints +- (void)updateConstraints { + + [super updateConstraints]; + CGFloat imgWidth = kScale390(43); + [self.avatarView mas_remakeConstraints:^(MASConstraintMaker *make) { + make.width.height.mas_equalTo(imgWidth); + make.top.mas_equalTo(kScale390(10)); + make.leading.mas_equalTo(kScale390(16)); + }]; if ([TUIConfig defaultConfig].avatarType == TAvatarTypeRounded) { self.avatarView.layer.masksToBounds = YES; - self.avatarView.layer.cornerRadius = self.avatarView.frame.size.height / 2; + self.avatarView.layer.cornerRadius = imgWidth / 2; } else if ([TUIConfig defaultConfig].avatarType == TAvatarTypeRadiusCorner) { self.avatarView.layer.masksToBounds = YES; self.avatarView.layer.cornerRadius = [TUIConfig defaultConfig].avatarCornerRadius; } - - self.mainTitleLabel.mm_sizeToFit(); - self.mainTitleLabel.mm_x = CGRectGetMaxX(self.avatarView.frame) + 12 * kScale; - self.mainTitleLabel.mm_y = self.avatarView.mm_y; - self.mainTitleLabel.mm_flexToRight(12 * kScale); - - self.subTitleLabel.mm_sizeToFit(); - self.subTitleLabel.mm_x = self.mainTitleLabel.mm_x; - self.subTitleLabel.mm_y = CGRectGetMaxY(self.mainTitleLabel.frame) + kScale390(4); - self.subTitleLabel.mm_flexToRight(12 * kScale); - - self.descLabel.mm_sizeToFit(); - self.descLabel.mm_x = self.mainTitleLabel.mm_x; - self.descLabel.mm_y = CGRectGetMaxY(self.subTitleLabel.frame) + kScale390(4); - self.descLabel.mm_flexToRight(12 * kScale); + + [self.mainTitleLabel sizeToFit]; + [self.mainTitleLabel mas_remakeConstraints:^(MASConstraintMaker *make) { + make.top.mas_equalTo(self.avatarView.mas_top); + make.leading.mas_equalTo(self.avatarView.mas_trailing).mas_offset(12); + make.height.mas_equalTo(self.mainTitleLabel.frame.size.height); + make.trailing.mas_lessThanOrEqualTo(self.contentView.mas_trailing).mas_offset(- kScale390(12)); + }]; + [self.subTitleLabel sizeToFit]; + [self.subTitleLabel mas_remakeConstraints:^(MASConstraintMaker *make) { + make.top.mas_equalTo(self.mainTitleLabel.mas_bottom).mas_offset(kScale390(4)); + make.leading.mas_equalTo(self.mainTitleLabel.mas_leading); + make.height.mas_equalTo(self.subTitleLabel.frame.size.height); + make.trailing.mas_lessThanOrEqualTo(self.contentView.mas_trailing).mas_offset(- kScale390(12)); + }]; + [self.descLabel sizeToFit]; + [self.descLabel mas_remakeConstraints:^(MASConstraintMaker *make) { + make.top.mas_equalTo(self.subTitleLabel.mas_bottom).mas_offset(kScale390(4)); + make.leading.mas_equalTo(self.mainTitleLabel.mas_leading); + make.height.mas_equalTo(self.subTitleLabel.frame.size.height); + make.trailing.mas_lessThanOrEqualTo(self.contentView.mas_trailing).mas_offset(- kScale390(12)); + }]; +} +- (void)layoutSubviews { + [super layoutSubviews]; } - (UIImageView *)avatarView { diff --git a/iOS/TUIKit/TUIContact/UI_Minimalist/UI/TUIBlackListController_Minimalist.m b/iOS/TUIKit/TUIContact/UI_Minimalist/UI/TUIBlackListController_Minimalist.m index 83fff6d80..44585b939 100644 --- a/iOS/TUIKit/TUIContact/UI_Minimalist/UI/TUIBlackListController_Minimalist.m +++ b/iOS/TUIKit/TUIContact/UI_Minimalist/UI/TUIBlackListController_Minimalist.m @@ -9,7 +9,6 @@ #import "TUIBlackListController_Minimalist.h" #import #import -#import "ReactiveObjC.h" @interface TUIBlackListController_Minimalist () diff --git a/iOS/TUIKit/TUIContact/UI_Minimalist/UI/TUIContactController_Minimalist.m b/iOS/TUIKit/TUIContact/UI_Minimalist/UI/TUIContactController_Minimalist.m index 319371ea9..13035023a 100644 --- a/iOS/TUIKit/TUIContact/UI_Minimalist/UI/TUIContactController_Minimalist.m +++ b/iOS/TUIKit/TUIContact/UI_Minimalist/UI/TUIContactController_Minimalist.m @@ -134,7 +134,11 @@ CGFloat height = [TUIPopCell getHeight] * menus.count + TUIPopView_Arrow_Size.height; CGFloat orginY = StatusBar_Height + NavBar_Height; - TUIPopView *popView = [[TUIPopView alloc] initWithFrame:CGRectMake(Screen_Width - 140, orginY, 130, height)]; + CGFloat orginX = Screen_Width - 140; + if(isRTL()){ + orginX = 10; + } + TUIPopView *popView = [[TUIPopView alloc] initWithFrame:CGRectMake(orginX, orginY, 130, height)]; CGRect frameInNaviView = [self.navigationController.view convertRect:rightBarButton.frame fromView:rightBarButton.superview]; popView.arrowPoint = CGPointMake(frameInNaviView.origin.x + frameInNaviView.size.width * 0.5, orginY); popView.delegate = self; @@ -283,8 +287,12 @@ textLabel.tag = TEXT_TAG; textLabel.font = [UIFont systemFontOfSize:16]; textLabel.textColor = [UIColor tui_colorWithHex:@"#000000"]; + [textLabel setRtlAlignment:TUITextRTLAlignmentLeading]; [headerView addSubview:textLabel]; - textLabel.mm_fill().mm_left(12); + [textLabel mas_remakeConstraints:^(MASConstraintMaker *make) { + make.leading.mas_equalTo(headerView.mas_leading).mas_offset(12); + make.top.bottom.trailing.mas_equalTo(headerView); + }]; textLabel.autoresizingMask = UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth; } UILabel *label = [headerView viewWithTag:TEXT_TAG]; diff --git a/iOS/TUIKit/TUIContact/UI_Minimalist/UI/TUIContactSelectController_Minimalist.m b/iOS/TUIKit/TUIContact/UI_Minimalist/UI/TUIContactSelectController_Minimalist.m index 86973a113..6fc906bb0 100644 --- a/iOS/TUIKit/TUIContact/UI_Minimalist/UI/TUIContactSelectController_Minimalist.m +++ b/iOS/TUIKit/TUIContact/UI_Minimalist/UI/TUIContactSelectController_Minimalist.m @@ -205,8 +205,12 @@ textLabel.tag = TEXT_TAG; textLabel.font = [UIFont boldSystemFontOfSize:16]; textLabel.textColor = [UIColor tui_colorWithHex:@"#000000"]; + [textLabel setRtlAlignment:TUITextRTLAlignmentLeading]; [headerView addSubview:textLabel]; - textLabel.mm_fill().mm_left(12); + [textLabel mas_remakeConstraints:^(MASConstraintMaker *make) { + make.leading.mas_equalTo(headerView.mas_leading).mas_offset(12); + make.top.bottom.trailing.mas_equalTo(headerView); + }]; textLabel.autoresizingMask = UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth; } UILabel *label = [headerView viewWithTag:TEXT_TAG]; diff --git a/iOS/TUIKit/TUIContact/UI_Minimalist/UI/TUIContactUserPanelHeaderView_Minimalist.m b/iOS/TUIKit/TUIContact/UI_Minimalist/UI/TUIContactUserPanelHeaderView_Minimalist.m index 2a4eef81a..90840363f 100644 --- a/iOS/TUIKit/TUIContact/UI_Minimalist/UI/TUIContactUserPanelHeaderView_Minimalist.m +++ b/iOS/TUIKit/TUIContact/UI_Minimalist/UI/TUIContactUserPanelHeaderView_Minimalist.m @@ -91,7 +91,7 @@ - (UICollectionView *)userPanel { if (!_userPanel) { - UICollectionViewFlowLayout *layout = [[UICollectionViewFlowLayout alloc] init]; + UICollectionViewFlowLayout *layout = [[TUICollectionRTLFitFlowLayout alloc] init]; layout.scrollDirection = UICollectionViewScrollDirectionHorizontal; _userPanel = [[UICollectionView alloc] initWithFrame:CGRectZero collectionViewLayout:layout]; _userPanel.backgroundColor = [UIColor clearColor]; diff --git a/iOS/TUIKit/TUIContact/UI_Minimalist/UI/TUIFindContactViewController_Minimalist.m b/iOS/TUIKit/TUIContact/UI_Minimalist/UI/TUIFindContactViewController_Minimalist.m index a0e40ce12..2553cb116 100644 --- a/iOS/TUIKit/TUIContact/UI_Minimalist/UI/TUIFindContactViewController_Minimalist.m +++ b/iOS/TUIKit/TUIContact/UI_Minimalist/UI/TUIFindContactViewController_Minimalist.m @@ -158,6 +158,7 @@ self.type == TUIFindContactTypeC2C_Minimalist ? TIMCommonLocalizableString(TUIKitSearchUserID) : TIMCommonLocalizableString(TUIKitSearchGroupID); _searchBar.backgroundImage = [[UIImage alloc] init]; _searchBar.delegate = self; + _searchBar.searchTextField.textAlignment = isRTL()?NSTextAlignmentRight:NSTextAlignmentLeft; UITextField *searchField = [_searchBar valueForKey:@"searchField"]; if (searchField) { searchField.backgroundColor = [UIColor tui_colorWithHex:@"f9f9f9"]; diff --git a/iOS/TUIKit/TUIContact/UI_Minimalist/UI/TUIFriendProfileHeaderView_Minimalist.m b/iOS/TUIKit/TUIContact/UI_Minimalist/UI/TUIFriendProfileHeaderView_Minimalist.m index 487f0ca38..d2fe0a674 100644 --- a/iOS/TUIKit/TUIContact/UI_Minimalist/UI/TUIFriendProfileHeaderView_Minimalist.m +++ b/iOS/TUIKit/TUIContact/UI_Minimalist/UI/TUIFriendProfileHeaderView_Minimalist.m @@ -29,6 +29,7 @@ self.textLabel = [[UILabel alloc] init]; self.textLabel.font = [UIFont systemFontOfSize:kScale390(16)]; self.textLabel.textColor = [UIColor tui_colorWithHex:@"#000000"]; + self.textLabel.rtlAlignment = TUITextRTLAlignmentCenter; [self addSubview:self.textLabel]; self.textLabel.text = @"Message"; @@ -39,12 +40,31 @@ UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(click)]; [self addGestureRecognizer:tap]; } + ++ (BOOL)requiresConstraintBasedLayout { + return YES; +} + +// this is Apple's recommended place for adding/updating constraints +- (void)updateConstraints { + + [super updateConstraints]; + [self.iconView mas_remakeConstraints:^(MASConstraintMaker *make) { + make.width.height.mas_equalTo(kScale390(30)); + make.top.mas_equalTo(kScale390(19)); + make.centerX.mas_equalTo(self); + }]; + [self.textLabel sizeToFit]; + [self.textLabel mas_remakeConstraints:^(MASConstraintMaker *make) { + make.leading.trailing.mas_equalTo(self); + make.height.mas_equalTo(kScale390(19)); + make.top.mas_equalTo(self.iconView.mas_bottom).mas_offset(kScale390(11)); + make.centerX.mas_equalTo(self); + }]; +} - (void)layoutSubviews { [super layoutSubviews]; - self.iconView.frame = CGRectMake((self.bounds.size.width - kScale390(30)) * 0.5, kScale390(19), kScale390(30), kScale390(30)); - [self.textLabel sizeToFit]; - self.textLabel.frame = CGRectMake((self.bounds.size.width - self.textLabel.frame.size.width) * 0.5, - self.iconView.frame.origin.y + self.iconView.frame.size.height + kScale390(11), self.bounds.size.width, kScale390(19)); + } - (void)click { if (self.messageBtnClickBlock) { @@ -99,28 +119,61 @@ x = CGRectGetMaxX(itemView.frame) + space; } } + // tell constraints they need updating + [self setNeedsUpdateConstraints]; + + // update constraints now so we can animate the change + [self updateConstraintsIfNeeded]; + + [self layoutIfNeeded]; } -- (void)layoutSubviews { - [super layoutSubviews]; ++ (BOOL)requiresConstraintBasedLayout { + return YES; +} + +// this is Apple's recommended place for adding/updating constraints +- (void)updateConstraints { + + [super updateConstraints]; + CGFloat imgWidth = kScale390(94); + [self.headImg mas_remakeConstraints:^(MASConstraintMaker *make) { + make.width.height.mas_equalTo(imgWidth); + make.centerX.mas_equalTo(self.mas_centerX); + make.top.mas_equalTo(kScale390(42)); + }]; + + MASAttachKeys(self.headImg); - self.headImg.frame = CGRectMake((self.bounds.size.width - kScale390(94)) * 0.5, kScale390(42), kScale390(94), kScale390(94)); if ([TUIConfig defaultConfig].avatarType == TAvatarTypeRounded) { self.headImg.layer.masksToBounds = YES; - self.headImg.layer.cornerRadius = self.headImg.frame.size.height / 2.0; + self.headImg.layer.cornerRadius = imgWidth / 2; } else if ([TUIConfig defaultConfig].avatarType == TAvatarTypeRadiusCorner) { self.headImg.layer.masksToBounds = YES; self.headImg.layer.cornerRadius = [TUIConfig defaultConfig].avatarCornerRadius; } - + [self.descriptionLabel sizeToFit]; - self.descriptionLabel.frame = CGRectMake((self.bounds.size.width - self.descriptionLabel.frame.size.width) * 0.5, - self.headImg.frame.origin.y + self.headImg.frame.size.height + kScale390(10), - self.descriptionLabel.frame.size.width, self.descriptionLabel.frame.size.height); + [self.descriptionLabel mas_remakeConstraints:^(MASConstraintMaker *make) { + make.centerX.mas_equalTo(self.mas_centerX); + make.top.mas_equalTo(self.headImg.mas_bottom).mas_offset(kScale390(10)); + make.height.mas_equalTo(30); + make.width.mas_equalTo(self.descriptionLabel.frame.size.width); + make.width.mas_lessThanOrEqualTo(self).multipliedBy(0.5); + }]; + MASAttachKeys(self.descriptionLabel); if (self.functionListView.subviews.count > 0) { - self.functionListView.frame = CGRectMake(0, CGRectGetMaxY(self.descriptionLabel.frame) + kScale390(42), self.bounds.size.width, kScale390(95)); + [self.functionListView mas_remakeConstraints:^(MASConstraintMaker *make) { + make.leading.mas_equalTo(0); + make.width.mas_equalTo(self.bounds.size.width); + make.height.mas_equalTo(kScale390(95)); + make.top.mas_equalTo(self.descriptionLabel.mas_bottom).mas_offset(kScale390(18)); + }]; } } +- (void)layoutSubviews { + [super layoutSubviews]; +} @end diff --git a/iOS/TUIKit/TUIContact/UI_Minimalist/UI/TUIFriendRequestViewController_Minimalist.m b/iOS/TUIKit/TUIContact/UI_Minimalist/UI/TUIFriendRequestViewController_Minimalist.m index 925a60847..53a649803 100644 --- a/iOS/TUIKit/TUIContact/UI_Minimalist/UI/TUIFriendRequestViewController_Minimalist.m +++ b/iOS/TUIKit/TUIContact/UI_Minimalist/UI/TUIFriendRequestViewController_Minimalist.m @@ -14,7 +14,7 @@ #import "TUICommonContactSwitchCell.h" #import "TUIContactAvatarViewController_Minimalist.h" #import "TUIContactButtonCell_Minimalist.h" -#import "UIView+TUIToast.h" +#import @interface TUIFriendRequestViewController_Minimalist () @property UITableView *tableView; @@ -51,6 +51,13 @@ paragraphStyle.lineSpacing = 5; paragraphStyle.firstLineHeadIndent = kScale390(12.5); paragraphStyle.alignment = NSTextAlignmentLeft; + if (isRTL()) { + paragraphStyle.alignment = NSTextAlignmentRight; + } + else { + paragraphStyle.alignment = NSTextAlignmentLeft; + } + NSDictionary *attributes = @{NSFontAttributeName : [UIFont systemFontOfSize:kScale390(16)], NSParagraphStyleAttributeName : paragraphStyle}; NSString *selfUserID = [[V2TIMManager sharedInstance] getLoginUser]; [[V2TIMManager sharedInstance] getUsersInfo:@[ selfUserID ] @@ -70,7 +77,12 @@ }]; self.nickTextField = [[UITextField alloc] initWithFrame:CGRectZero]; - self.nickTextField.textAlignment = NSTextAlignmentRight; + if (isRTL()) { + self.nickTextField.textAlignment = NSTextAlignmentLeft; + } + else { + self.nickTextField.textAlignment = NSTextAlignmentRight; + } _titleView = [[TUINaviBarIndicatorView alloc] init]; [_titleView setTitle:TIMCommonLocalizableString(FriendRequestFillInfo)]; @@ -299,13 +311,24 @@ [msgView addSubview:descLabel]; descLabel.font = [UIFont systemFontOfSize:kScale390(14)]; descLabel.text = msgText; + descLabel.numberOfLines = 0; [descLabel sizeToFit]; - icon.frame = CGRectMake(kScale390(12), kScale390(10), kScale390(16), kScale390(16)); - descLabel.frame = CGRectMake(icon.frame.origin.x + icon.frame.size.width + kScale390(8), kScale390(8), descLabel.frame.size.width, kScale390(20)); - msgView.frame = CGRectMake(0, 0, descLabel.frame.origin.x + descLabel.frame.size.width + kScale390(12), kScale390(36)); - msgView.mm__centerX(hudView.mm_centerX); - msgView.mm__centerY(hudView.mm_centerY); + [icon mas_remakeConstraints:^(MASConstraintMaker *make) { + make.leading.mas_equalTo(kScale390(12)); + make.top.mas_equalTo(kScale390(10)); + make.width.height.mas_equalTo(kScale390(16)); + }]; + [descLabel mas_remakeConstraints:^(MASConstraintMaker *make) { + make.leading.mas_equalTo(icon.mas_trailing).mas_offset(kScale390(8)); + make.top.mas_equalTo(kScale390(10)); + make.bottom.mas_equalTo(msgView).mas_offset(-kScale390(10)); + make.trailing.mas_equalTo(msgView); + }]; + [msgView mas_remakeConstraints:^(MASConstraintMaker *make) { + make.center.mas_equalTo(hudView); + make.width.mas_lessThanOrEqualTo(hudView); + }]; [[UIApplication sharedApplication].keyWindow showToast:hudView duration:3.0 diff --git a/iOS/TUIKit/TUIContact/UI_Minimalist/UI/TUIGroupConversationListController_Minimalist.m b/iOS/TUIKit/TUIContact/UI_Minimalist/UI/TUIGroupConversationListController_Minimalist.m index 3d0bef47c..d7d6041c5 100644 --- a/iOS/TUIKit/TUIContact/UI_Minimalist/UI/TUIGroupConversationListController_Minimalist.m +++ b/iOS/TUIKit/TUIContact/UI_Minimalist/UI/TUIGroupConversationListController_Minimalist.m @@ -129,10 +129,12 @@ static NSString *gConversationCell_ReuseId = @"TConversationCell"; textLabel.tag = TEXT_TAG; textLabel.textColor = [UIColor tui_colorWithHex:@"#000000"]; textLabel.font = [UIFont systemFontOfSize:kScale390(14)]; + [textLabel setRtlAlignment:TUITextRTLAlignmentLeading]; [headerView.contentView addSubview:textLabel]; - textLabel.mm_fill().mm_left(kScale390(16)); - textLabel.autoresizingMask = UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth; - + [textLabel mas_remakeConstraints:^(MASConstraintMaker *make) { + make.leading.mas_equalTo(headerView.mas_leading).mas_offset(kScale390(16)); + make.top.bottom.trailing.mas_equalTo(headerView); + }]; UIView *clearBackgroundView = [[UIView alloc] init]; clearBackgroundView.mm_fill(); headerView.backgroundView = clearBackgroundView; diff --git a/iOS/TUIKit/TUIContact/UI_Minimalist/UI/TUIGroupCreateController_Minimalist.m b/iOS/TUIKit/TUIContact/UI_Minimalist/UI/TUIGroupCreateController_Minimalist.m index 7c15d937d..e1952d333 100644 --- a/iOS/TUIKit/TUIContact/UI_Minimalist/UI/TUIGroupCreateController_Minimalist.m +++ b/iOS/TUIKit/TUIContact/UI_Minimalist/UI/TUIGroupCreateController_Minimalist.m @@ -156,7 +156,7 @@ static NSString *const reuseIdentifier = @"TUISelectAvatarCollectionCell"; } - (void)initControl { - UICollectionViewFlowLayout *flowLayout = [[UICollectionViewFlowLayout alloc] init]; + UICollectionViewFlowLayout *flowLayout = [[TUICollectionRTLFitFlowLayout alloc] init]; [flowLayout setScrollDirection:UICollectionViewScrollDirectionHorizontal]; flowLayout.minimumLineSpacing = 20; flowLayout.minimumInteritemSpacing = 20; @@ -361,18 +361,18 @@ static NSString *const reuseIdentifier = @"TUISelectAvatarCollectionCell"; NSMutableParagraphStyle *paragraphPlaceholderStyle = [[NSMutableParagraphStyle alloc] init]; paragraphPlaceholderStyle.firstLineHeadIndent = 0; paragraphPlaceholderStyle.headIndent = 0; - paragraphPlaceholderStyle.alignment = NSTextAlignmentLeft; + paragraphPlaceholderStyle.alignment = isRTL()?NSTextAlignmentLeft:NSTextAlignmentRight; NSDictionary *attributesPlaceholder = @{NSFontAttributeName : [UIFont systemFontOfSize:kScale390(16)], NSParagraphStyleAttributeName : paragraphPlaceholderStyle}; NSMutableParagraphStyle *paragraphStyle = [[NSMutableParagraphStyle alloc] init]; paragraphStyle.firstLineHeadIndent = 0; - paragraphStyle.alignment = NSTextAlignmentLeft; + paragraphStyle.alignment = isRTL()?NSTextAlignmentRight:NSTextAlignmentLeft; NSDictionary *attributes = @{NSFontAttributeName : [UIFont boldSystemFontOfSize:kScale390(16)], NSParagraphStyleAttributeName : paragraphStyle}; self.groupNameTextField = [[UITextField alloc] initWithFrame:CGRectZero]; - self.groupNameTextField.textAlignment = NSTextAlignmentLeft; + self.groupNameTextField.textAlignment = isRTL()?NSTextAlignmentRight:NSTextAlignmentLeft; self.groupNameTextField.attributedText = [[NSAttributedString alloc] initWithString:@"" attributes:attributes]; self.groupNameTextField.attributedPlaceholder = [[NSAttributedString alloc] initWithString:TIMCommonLocalizableString(TUIKitCreatGroupNamed_Placeholder) attributes:attributesPlaceholder]; @@ -382,7 +382,7 @@ static NSString *const reuseIdentifier = @"TUISelectAvatarCollectionCell"; self.groupNameTextField.attributedText = [[NSAttributedString alloc] initWithString:self.createGroupInfo.groupName attributes:attributes]; } self.groupIDTextField = [[UITextField alloc] initWithFrame:CGRectZero]; - self.groupIDTextField.textAlignment = NSTextAlignmentLeft; + self.groupIDTextField.textAlignment = isRTL()?NSTextAlignmentRight:NSTextAlignmentLeft; self.groupIDTextField.keyboardType = UIKeyboardTypeDefault; self.groupIDTextField.attributedText = [[NSAttributedString alloc] initWithString:@"" attributes:attributes]; self.groupIDTextField.attributedPlaceholder = [[NSAttributedString alloc] initWithString:TIMCommonLocalizableString(TUIKitCreatGroupID_Placeholder) @@ -403,6 +403,7 @@ static NSString *const reuseIdentifier = @"TUISelectAvatarCollectionCell"; if (!_describeTextView) { _describeTextView = [[UITextView alloc] init]; _describeTextView.backgroundColor = [UIColor clearColor]; + _describeTextView.textAlignment = isRTL()?NSTextAlignmentRight:NSTextAlignmentLeft; _describeTextView.editable = NO; _describeTextView.scrollEnabled = NO; _describeTextView.textContainerInset = UIEdgeInsetsMake(0.f, 0.f, 0.f, 0.f); @@ -459,7 +460,7 @@ static NSString *const reuseIdentifier = @"TUISelectAvatarCollectionCell"; NSMutableParagraphStyle *paragraphStyle = [[NSMutableParagraphStyle alloc] init]; paragraphStyle.minimumLineHeight = 18; [paragraphStyle setLineBreakMode:NSLineBreakByWordWrapping]; - [paragraphStyle setAlignment:NSTextAlignmentLeft]; + [paragraphStyle setAlignment:isRTL()?NSTextAlignmentRight:NSTextAlignmentLeft]; NSDictionary *dictionary = @{ NSFontAttributeName : [UIFont systemFontOfSize:12], NSForegroundColorAttributeName : [UIColor tui_colorWithHex:@"#888888"], @@ -516,6 +517,7 @@ static NSString *const reuseIdentifier = @"TUISelectAvatarCollectionCell"; if (section == 2 || section == 3) { [view addSubview:sectionTitleLabel]; sectionTitleLabel.font = [UIFont boldSystemFontOfSize:kScale390(16)]; + sectionTitleLabel.rtlAlignment = TUITextRTLAlignmentLeading; if (section == 2) { sectionTitleLabel.text = TIMCommonLocalizableString(TUIKitCreatGroupAvatar); } else if (section == 3) { @@ -523,7 +525,11 @@ static NSString *const reuseIdentifier = @"TUISelectAvatarCollectionCell"; } [sectionTitleLabel sizeToFit]; - sectionTitleLabel.frame = CGRectMake(kScale390(16), kScale390(12), sectionTitleLabel.frame.size.width, sectionTitleLabel.frame.size.height); + [sectionTitleLabel mas_remakeConstraints:^(MASConstraintMaker *make) { + make.leading.mas_equalTo(kScale390(16)); + make.top.mas_equalTo(kScale390(12)); + make.size.mas_equalTo(sectionTitleLabel.frame.size); + }]; } return view; } @@ -552,13 +558,24 @@ static NSString *const reuseIdentifier = @"TUISelectAvatarCollectionCell"; UITableViewCell *cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"groupName"]; [cell.contentView addSubview:self.groupNameTextField]; cell.backgroundColor = TIMCommonDynamicColor(@"form_bg_color", @"#FFFFFF"); - self.groupNameTextField.mm_width(cell.contentView.mm_w).mm_height(cell.contentView.mm_h).mm_left(kScale390(16)); + [self.groupNameTextField mas_remakeConstraints:^(MASConstraintMaker *make) { + make.trailing.mas_equalTo(cell.contentView.mas_trailing); + make.leading.mas_equalTo(cell.contentView.mas_leading).mas_offset(10); + make.height.mas_equalTo(cell.contentView); + make.centerY.mas_equalTo(cell.contentView); + }]; return cell; } else { UITableViewCell *cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"groupID"]; cell.backgroundColor = TIMCommonDynamicColor(@"form_bg_color", @"#FFFFFF"); [cell.contentView addSubview:self.groupIDTextField]; - self.groupIDTextField.mm_width(cell.contentView.mm_w).mm_height(cell.contentView.mm_h).mm_left(kScale390(16)); + [self.groupIDTextField mas_remakeConstraints:^(MASConstraintMaker *make) { + make.trailing.mas_equalTo(cell.contentView.mas_trailing); + make.leading.mas_equalTo(cell.contentView.mas_leading).mas_offset(10); + make.height.mas_equalTo(cell.contentView); + make.width.mas_equalTo(cell.contentView); + make.centerY.mas_equalTo(cell.contentView); + }]; return cell; } } else if (indexPath.section == 1) { @@ -580,8 +597,13 @@ static NSString *const reuseIdentifier = @"TUISelectAvatarCollectionCell"; return cell; } else if (indexPath.section == 2) { UITableViewCell *cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"GroupChoose"]; - self.createPortraitView.mm_width(self.view.frame.size.width).mm_height(kScale390(144)).mm_left(kScale390(0)); [cell.contentView addSubview:self.createPortraitView]; + [self.createPortraitView mas_remakeConstraints:^(MASConstraintMaker *make) { + make.leading.mas_equalTo(cell.contentView); + make.height.mas_equalTo(kScale390(144)); + make.width.mas_equalTo(cell.contentView); + make.centerY.mas_equalTo(cell.contentView); + }]; @weakify(self); self.createPortraitView.onClick = ^(TUISelectAvatarCardItem *data) { @strongify(self); @@ -597,7 +619,12 @@ static NSString *const reuseIdentifier = @"TUISelectAvatarCollectionCell"; UITableViewCell *cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"UserPanel"]; self.userPanelHeaderView = [[TUIContactUserPanelHeaderView_Minimalist alloc] init]; [cell.contentView addSubview:self.userPanelHeaderView]; - self.userPanelHeaderView.mm_width(self.view.frame.size.width).mm_height(kScale390(57)).mm_left(kScale390(0)); + [self.userPanelHeaderView mas_remakeConstraints:^(MASConstraintMaker *make) { + make.trailing.mas_equalTo(cell.contentView); + make.height.mas_equalTo(kScale390(57)); + make.width.mas_equalTo(cell.contentView); + make.centerY.mas_equalTo(cell.contentView); + }]; self.userPanelHeaderView.selectedUsers = [NSMutableArray arrayWithArray:self.createContactArray]; @weakify(self); self.userPanelHeaderView.clickCallback = ^{ diff --git a/iOS/TUIKit/TUIContact/UI_Minimalist/UI/TUIGroupTypeListController_Minimalist.m b/iOS/TUIKit/TUIContact/UI_Minimalist/UI/TUIGroupTypeListController_Minimalist.m index 59d5586d3..e001ed307 100644 --- a/iOS/TUIKit/TUIContact/UI_Minimalist/UI/TUIGroupTypeListController_Minimalist.m +++ b/iOS/TUIKit/TUIContact/UI_Minimalist/UI/TUIGroupTypeListController_Minimalist.m @@ -95,24 +95,53 @@ [self.maskView addSubview:self.selectedView]; } ++ (BOOL)requiresConstraintBasedLayout { + return YES; +} + +// this is Apple's recommended place for adding/updating constraints +- (void)updateConstraints { + + [super updateConstraints]; + + [self.maskView mas_remakeConstraints:^(MASConstraintMaker *make) { + make.leading.mas_equalTo(kScale390(16)); + make.top.mas_equalTo(0); + make.trailing.mas_equalTo(self.mas_trailing).mas_offset(-kScale390(16)); + make.height.mas_equalTo(self); + }]; + + CGFloat x = 0; + if (!self.selectedView.isHidden) { + [self.selectedView mas_remakeConstraints:^(MASConstraintMaker *make) { + make.leading.mas_equalTo(kScale390(16)); + make.top.mas_equalTo(kScale390(15)); + make.width.height.mas_equalTo(kScale390(16)); + }]; + } + [self.title mas_remakeConstraints:^(MASConstraintMaker *make) { + if (self.selectedView.isHidden) { + make.leading.mas_equalTo(self.maskView).mas_offset(kScale390(16)); + } + else { + make.leading.mas_equalTo(self.selectedView.mas_trailing).mas_offset(10); + } + make.trailing.mas_equalTo(self.maskView.mas_trailing).mas_offset(- 10); + make.height.mas_equalTo(24); + make.top.mas_equalTo(kScale390(12)); + }]; + + [self.describeTextView mas_remakeConstraints:^(MASConstraintMaker *make) { + make.leading.mas_equalTo(self.contentView).mas_offset(16); + make.trailing.mas_equalTo(self.contentView).mas_offset(-16); + make.top.mas_equalTo(self.title.mas_bottom).mas_offset(kScale390(8)); + make.height.mas_equalTo(_describeTextViewRect.size.height); + }]; + +} + - (void)layoutSubviews { [super layoutSubviews]; - - [self updateCellView]; - - CGFloat x = 0; - - if (self.selectedView.isHidden) { - x = kScale390(16); - } else { - self.selectedView.frame = CGRectMake(kScale390(16), kScale390(15), kScale390(16), kScale390(16)); - x = self.selectedView.frame.origin.x + self.selectedView.frame.size.width + 10; - } - self.title.frame = CGRectMake(x, kScale390(12), self.maskView.frame.size.width - x - 10, 24); - self.describeTextView.mm_width(self.maskView.mm_w - 32) - .mm_height(_describeTextViewRect.size.height) - .mm_top(self.title.frame.origin.y + self.title.frame.size.height + kScale390(8)) - .mm_left(kScale390(16)); } - (void)setData:(TUIGroupTypeData_Minimalist *)data { @@ -120,14 +149,6 @@ _image.image = data.image; _title.text = data.title; [self updateRectAndTextForDescribeTextView:self.describeTextView groupType:data.groupType]; -} - -- (void)updateCellView { - [self updateSelectedUI]; - self.maskView.frame = CGRectMake(kScale390(16), 0, self.frame.size.width - kScale390(32), self.frame.size.height); -} - -- (void)updateSelectedUI { if (self.cellData.isSelect) { self.maskView.layer.borderColor = TIMCommonDynamicColor(@"", @"#006EFF").CGColor; self.selectedView.hidden = NO; @@ -135,11 +156,21 @@ self.maskView.layer.borderColor = [UIColor tui_colorWithHex:@"#DDDDDD"].CGColor; self.selectedView.hidden = YES; } + // tell constraints they need updating + [self setNeedsUpdateConstraints]; + + // update constraints now so we can animate the change + [self updateConstraintsIfNeeded]; + + [self layoutIfNeeded]; + } + - (UITextView *)describeTextView { if (!_describeTextView) { _describeTextView = [[UITextView alloc] init]; _describeTextView.backgroundColor = [UIColor clearColor]; + _describeTextView.textAlignment = isRTL()?NSTextAlignmentRight:NSTextAlignmentLeft; _describeTextView.editable = NO; _describeTextView.scrollEnabled = NO; _describeTextView.textContainerInset = UIEdgeInsetsMake(0.f, 0.f, 0.f, 0.f); @@ -162,7 +193,7 @@ if (@available(iOS 9.0, *)) { paragraphStyle.allowsDefaultTighteningForTruncation = YES; } - paragraphStyle.alignment = NSTextAlignmentJustified; + paragraphStyle.alignment = isRTL()?NSTextAlignmentRight: NSTextAlignmentLeft; NSDictionary *dictionary = @{ NSFontAttributeName : [UIFont systemFontOfSize:12], NSForegroundColorAttributeName : [UIColor tui_colorWithHex:@"#888888"], diff --git a/iOS/TUIKit/TUIContact/UI_Minimalist/UI/TUISettingController_Minimalist.m b/iOS/TUIKit/TUIContact/UI_Minimalist/UI/TUISettingController_Minimalist.m index 3096771ea..5647a956d 100644 --- a/iOS/TUIKit/TUIContact/UI_Minimalist/UI/TUISettingController_Minimalist.m +++ b/iOS/TUIKit/TUIContact/UI_Minimalist/UI/TUISettingController_Minimalist.m @@ -173,9 +173,14 @@ static NSString *const kKeyViews = @"views"; // Used to pass custom views from // Extension settings. if (dict[kKeyViews] && [dict[kKeyViews] isKindOfClass:NSArray.class]) { UIView *view = dict[kKeyViews][indexPath.row]; - UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"containerCell" forIndexPath:indexPath]; - [cell addSubview:view]; - return cell; + if ([view isKindOfClass:[UITableViewCell class]] ) { + return (id)view; + } + else { + UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"containerCell" forIndexPath:indexPath]; + [cell addSubview:view]; + return cell; + } } // Built-in settings. NSArray *array = dict[kKeyItems]; diff --git a/iOS/TUIKit/TUIConversation/BaseCell/CellUI/TUIConversationCell.m b/iOS/TUIKit/TUIConversation/BaseCell/CellUI/TUIConversationCell.m index 4c2fb3600..22eddd0b2 100644 --- a/iOS/TUIKit/TUIConversation/BaseCell/CellUI/TUIConversationCell.m +++ b/iOS/TUIKit/TUIConversation/BaseCell/CellUI/TUIConversationCell.m @@ -28,12 +28,14 @@ _timeLabel.font = [UIFont systemFontOfSize:12]; _timeLabel.textColor = TIMCommonDynamicColor(@"form_desc_color", @"#BBBBBB"); _timeLabel.layer.masksToBounds = YES; + [_timeLabel setRtlAlignment:TUITextRTLAlignmentLeading]; [self.contentView addSubview:_timeLabel]; _titleLabel = [[UILabel alloc] init]; _titleLabel.font = [UIFont systemFontOfSize:16]; _titleLabel.textColor = TIMCommonDynamicColor(@"form_title_color", @"#000000"); _titleLabel.layer.masksToBounds = YES; + [_titleLabel setRtlAlignment:TUITextRTLAlignmentLeading]; [self.contentView addSubview:_titleLabel]; _unReadView = [[TUIUnReadView alloc] init]; @@ -43,6 +45,7 @@ _subTitleLabel.layer.masksToBounds = YES; _subTitleLabel.font = [UIFont systemFontOfSize:14]; _subTitleLabel.textColor = TIMCommonDynamicColor(@"form_subtitle_color", @"#888888"); + [_subTitleLabel setRtlAlignment:TUITextRTLAlignmentLeading]; [self.contentView addSubview:_subTitleLabel]; _notDisturbRedDot = [[UIView alloc] init]; @@ -77,7 +80,11 @@ self.timeLabel.text = [TUITool convertDateToStr:convData.time]; self.subTitleLabel.attributedText = convData.subTitle; - + if (self.convData.showCheckBox) { + _selectedIcon.hidden = NO; + } else { + _selectedIcon.hidden = YES; + } [self configRedPoint:convData]; if (convData.isOnTop) { @@ -97,8 +104,15 @@ @weakify(self); [[[RACObserve(convData, title) takeUntil:self.rac_prepareForReuseSignal] distinctUntilChanged] subscribeNext:^(NSString *x) { - @strongify(self); - self.titleLabel.text = x; + @strongify(self); + self.titleLabel.text = x; + // tell constraints they need updating + [self setNeedsUpdateConstraints]; + + // update constraints now so we can animate the change + [self updateConstraintsIfNeeded]; + + [self layoutIfNeeded]; }]; /** @@ -117,7 +131,6 @@ avatar = [TUIGroupAvatar getCacheAvatarForGroup:convData.groupID number:(UInt32)member]; } convData.avatarImage = avatar ? avatar : DefaultGroupAvatarImageByGroupType(convData.groupType); - ; } [[RACObserve(convData, faceUrl) takeUntil:self.rac_prepareForReuseSignal] subscribeNext:^(NSString *faceUrl) { @@ -244,6 +257,15 @@ [self configOnlineStatusIcon:convData]; [self configDisplayLastMessageStatusImage:convData]; + + // tell constraints they need updating + [self setNeedsUpdateConstraints]; + + // update constraints now so we can animate the change + [self updateConstraintsIfNeeded]; + + [self layoutIfNeeded]; + } - (void)configDisplayLastMessageStatusImage:(TUIConversationCellData *)convData { @@ -319,27 +341,40 @@ self.notDisturbView.hidden = YES; } } -- (void)layoutSubviews { - [super layoutSubviews]; + ++ (BOOL)requiresConstraintBasedLayout { + return YES; +} + +// this is Apple's recommended place for adding/updating constraints +- (void)updateConstraints { + + [super updateConstraints]; CGFloat height = [self.convData heightOfWidth:self.mm_w]; self.mm_h = height; - CGFloat selectedIconSize = 20; - if (self.convData.showCheckBox) { - _selectedIcon.mm_width(selectedIconSize).mm_height(selectedIconSize); - _selectedIcon.mm_x = 10; - _selectedIcon.mm_centerY = self.headImageView.mm_centerY; - _selectedIcon.hidden = NO; - } else { - _selectedIcon.mm_width(0).mm_height(0); - _selectedIcon.mm_x = 0; - _selectedIcon.mm_y = 0; - _selectedIcon.hidden = YES; - } + [self.selectedIcon mas_remakeConstraints:^(MASConstraintMaker *make) { + if (self.convData.showCheckBox) { + make.width.height.mas_equalTo(selectedIconSize); + make.leading.mas_equalTo(self.contentView.mas_leading).mas_offset(10); + make.centerY.mas_equalTo(self.contentView.mas_centerY); + } + }]; + MASAttachKeys(self.selectedIcon); CGFloat imgHeight = height - 2 * (TConversationCell_Margin); - CGFloat margin = self.convData.showCheckBox ? _selectedIcon.mm_maxX : 0; - self.headImageView.mm_width(imgHeight).mm_height(imgHeight).mm_left(TConversationCell_Margin + 3 + margin).mm_top(TConversationCell_Margin); + [self.headImageView mas_remakeConstraints:^(MASConstraintMaker *make) { + make.size.mas_equalTo(imgHeight); + make.centerY.mas_equalTo(self.contentView.mas_centerY); + if (self.convData.showCheckBox) { + make.leading.mas_equalTo(self.selectedIcon.mas_trailing).mas_offset(TConversationCell_Margin + 3); + } + else { + make.leading.mas_equalTo(self.contentView.mas_leading).mas_offset(TConversationCell_Margin + 3); + } + }]; + MASAttachKeys(self.headImageView); + if ([TUIConfig defaultConfig].avatarType == TAvatarTypeRounded) { self.headImageView.layer.masksToBounds = YES; self.headImageView.layer.cornerRadius = imgHeight / 2; @@ -350,10 +385,14 @@ CGFloat titleLabelHeight = 30; if (self.convData.isLiteMode) { - self.titleLabel.mm_sizeToFitThan(120, titleLabelHeight) - .mm_top((height - titleLabelHeight) / 2) - .mm_left(self.headImageView.mm_maxX + TConversationCell_Margin) - .mm_flexToRight(2 * TConversationCell_Margin_Text); + [self.titleLabel sizeToFit]; + [self.titleLabel mas_remakeConstraints:^(MASConstraintMaker *make) { + make.width.mas_greaterThanOrEqualTo(120); + make.height.mas_greaterThanOrEqualTo(titleLabelHeight); + make.top.mas_equalTo((height - titleLabelHeight) / 2); + make.leading.mas_equalTo(self.headImageView.mas_trailing).mas_offset(TConversationCell_Margin); + make.trailing.mas_equalTo(self.contentView).mas_offset(- 2*TConversationCell_Margin_Text); + }]; self.timeLabel.hidden = YES; self.lastMessageStatusImageView.hidden = YES; self.subTitleLabel.hidden = YES; @@ -362,31 +401,80 @@ self.notDisturbView.hidden = YES; self.onlineStatusIcon.hidden = YES; } else { - self.timeLabel.mm_sizeToFit().mm_top(TConversationCell_Margin_Text).mm_right(TConversationCell_Margin + 4); - self.lastMessageStatusImageView.mm_width(kScale390(14)) - .mm_height(14) - .mm_bottom(kScale390(16)) - .mm_right(kScale390(1) + TConversationCell_Margin_Disturb + kScale390(8)); - self.titleLabel.mm_sizeToFitThan(120, titleLabelHeight) - .mm_top(TConversationCell_Margin_Text - 5) - .mm_left(self.headImageView.mm_maxX + TConversationCell_Margin) - .mm_flexToRight(self.timeLabel.mm_w + 2 * TConversationCell_Margin_Text); - self.subTitleLabel.mm_sizeToFit() - .mm_left(self.titleLabel.mm_x) - .mm_bottom(TConversationCell_Margin_Text) - .mm_flexToRight(2 * TConversationCell_Margin_Text); - self.unReadView.mm_right(self.headImageView.mm_r - 5).mm_top(self.headImageView.mm_y - 5); - self.notDisturbRedDot.mm_width(TConversationCell_Margin_Disturb_Dot) - .mm_height(TConversationCell_Margin_Disturb_Dot) - .mm_right(self.headImageView.mm_r - 3) - .mm_top(self.headImageView.mm_y - 3); - self.notDisturbView.mm_width(TConversationCell_Margin_Disturb).mm_height(TConversationCell_Margin_Disturb).mm_right(16).mm_bottom(15); + [self.timeLabel sizeToFit]; + [self.timeLabel mas_remakeConstraints:^(MASConstraintMaker *make) { + make.width.mas_equalTo(self.timeLabel); + make.height.mas_greaterThanOrEqualTo(self.timeLabel.font.lineHeight); + make.top.mas_equalTo(self.contentView.mas_top).mas_offset(TConversationCell_Margin_Text); + make.trailing.mas_equalTo(self.contentView.mas_trailing).mas_offset(- TConversationCell_Margin_Text); + }]; + MASAttachKeys(self.timeLabel); - self.onlineStatusIcon.mm_width(kScale * 15).mm_height(kScale * 15); - self.onlineStatusIcon.mm_x = CGRectGetMaxX(self.headImageView.frame) - 0.5 * self.onlineStatusIcon.mm_w - 3 * kScale; - self.onlineStatusIcon.mm_y = CGRectGetMaxY(self.headImageView.frame) - self.onlineStatusIcon.mm_w; - self.onlineStatusIcon.layer.cornerRadius = 0.5 * self.onlineStatusIcon.mm_w; + [self.lastMessageStatusImageView mas_remakeConstraints:^(MASConstraintMaker *make) { + make.width.mas_equalTo(kScale390(14)); + make.height.mas_equalTo(14); + make.trailing.mas_equalTo(self.contentView.mas_trailing).mas_offset(- (kScale390(1) + TConversationCell_Margin_Disturb + kScale390(8))); + make.bottom.mas_equalTo(self.contentView.mas_bottom).mas_offset(kScale390(16)); + }]; + MASAttachKeys(self.lastMessageStatusImageView); + + [self.titleLabel sizeToFit]; + [self.titleLabel mas_remakeConstraints:^(MASConstraintMaker *make) { + make.height.mas_greaterThanOrEqualTo(titleLabelHeight); + make.top.mas_equalTo(self.contentView.mas_top).mas_offset(TConversationCell_Margin_Text - 5); + make.leading.mas_equalTo(self.headImageView.mas_trailing).mas_offset(TConversationCell_Margin); + make.trailing.mas_lessThanOrEqualTo(self.timeLabel.mas_trailing).mas_offset(- 2*TConversationCell_Margin_Text); + }]; + MASAttachKeys(self.titleLabel); + [self.subTitleLabel sizeToFit]; + [self.subTitleLabel mas_remakeConstraints:^(MASConstraintMaker *make) { + make.height.mas_greaterThanOrEqualTo(self.subTitleLabel); + make.bottom.mas_equalTo(self.contentView).mas_offset(- TConversationCell_Margin_Text); + make.leading.mas_equalTo(self.titleLabel); + make.trailing.mas_equalTo(self.contentView).mas_offset(- 2*TConversationCell_Margin_Text); + }]; + MASAttachKeys(self.subTitleLabel); + + [self.unReadView.unReadLabel sizeToFit]; + [self.unReadView mas_remakeConstraints:^(MASConstraintMaker *make) { + make.trailing.mas_equalTo(self.headImageView.mas_trailing).mas_offset(kScale375(5)); + make.top.mas_equalTo(self.headImageView.mas_top).mas_offset(-kScale375(5)); + make.width.mas_equalTo(kScale375(20)); + make.height.mas_equalTo(kScale375(20)); + }]; + MASAttachKeys(self.unReadView); + + [self.unReadView.unReadLabel mas_remakeConstraints:^(MASConstraintMaker *make) { + make.center.mas_equalTo(self.unReadView); + make.size.mas_equalTo(self.unReadView.unReadLabel); + }]; + self.unReadView.layer.cornerRadius = kScale375(10); + [self.unReadView.layer masksToBounds]; + + [self.notDisturbRedDot mas_remakeConstraints:^(MASConstraintMaker *make) { + make.trailing.mas_equalTo(self.headImageView.mas_trailing).mas_offset(3); + make.top.mas_equalTo(self.headImageView.mas_top).mas_offset(1); + make.width.height.mas_equalTo(TConversationCell_Margin_Disturb_Dot); + }]; + MASAttachKeys(self.notDisturbRedDot); + + [self.notDisturbView mas_remakeConstraints:^(MASConstraintMaker *make) { + make.width.height.mas_equalTo(TConversationCell_Margin_Disturb); + make.trailing.mas_equalTo(self.timeLabel.mas_trailing); + make.bottom.mas_equalTo(self.contentView.mas_bottom).mas_offset(-15); + }]; + + [self.onlineStatusIcon mas_remakeConstraints:^(MASConstraintMaker *make) { + make.width.height.mas_equalTo(kScale375(15)); + make.leading.mas_equalTo(self.headImageView.mas_trailing).mas_offset(-kScale375(15)); + make.bottom.mas_equalTo(self.headImageView.mas_bottom).mas_offset(-kScale375(1)); + }]; + self.onlineStatusIcon.layer.cornerRadius = 0.5 * kScale375(15); } } +- (void)layoutSubviews { + [super layoutSubviews]; +} + @end diff --git a/iOS/TUIKit/TUIConversation/BaseDataProvider/TUIConversationListBaseDataProvider.m b/iOS/TUIKit/TUIConversation/BaseDataProvider/TUIConversationListBaseDataProvider.m index c12e518d6..94c918bdc 100644 --- a/iOS/TUIKit/TUIConversation/BaseDataProvider/TUIConversationListBaseDataProvider.m +++ b/iOS/TUIKit/TUIConversation/BaseDataProvider/TUIConversationListBaseDataProvider.m @@ -358,6 +358,9 @@ } for (TUIConversationCellData *item in conversationList) { + if (item.isLocalConversationFoldList){ + continue; + } NSNumber *position = [positionMaps objectForKey:item.conversationID]; NSAssert((position && [position isKindOfClass:NSNumber.class]), @"serius error, the self.conversationList maybe changed on the other thread"); if (position) { @@ -738,10 +741,10 @@ - (void)onRecvNewMessage:(V2TIMMessage *)msg { // 如果会话里是被隐藏的会话,则需要先清理被隐藏标记 // when a new message is received, if the conversation is a hidden conversation, you need to clear the hidden mark first - + // 如果会话里被标记未读,则需要清理标记 // when a new message is received, if the conversation is marked unread, you need to clear the mark - + NSString *userID = msg.userID; NSString *groupID = msg.groupID; NSString *conversationID = @""; @@ -756,22 +759,81 @@ if (IS_NOT_EMPTY_NSSTRING(groupID)) { conversationID = [NSString stringWithFormat:@"group_%@", groupID]; } - - [V2TIMManager.sharedInstance markConversation:@[ conversationID ] - markType:@(V2TIM_CONVERSATION_MARK_TYPE_HIDE) - enableMark:NO - succ:^(NSArray *result) { - [V2TIMManager.sharedInstance markConversation:@[ conversationID ] - markType:@(V2TIM_CONVERSATION_MARK_TYPE_UNREAD) - enableMark:NO - succ:nil - fail:^(int code, NSString *desc) { - kLog(@"[TUIConversation] %s code:%d, desc:%@", __func__, code, desc); - }]; + + TUIConversationCellData * targetCellData = nil; + for (TUIConversationCellData * cellData in self.conversationList) { + if ([cellData.conversationID isEqualToString:conversationID]) { + targetCellData = cellData; + break; } - fail:^(int code, NSString *desc) { - kLog(@"[TUIConversation] %s code:%d, desc:%@", __func__, code, desc); - }]; + } + if (targetCellData) { + BOOL existInHidelist = targetCellData.isMarkAsHide; + + BOOL existInUnreadlist = targetCellData.isMarkAsUnread; + + if (existInHidelist || existInUnreadlist) { + [self cancelHideAndUnreadMarkConversation:conversationID existInHidelist:existInHidelist existInUnreadlist:existInUnreadlist]; + } + } + else { + [V2TIMManager.sharedInstance getConversation:conversationID + succ:^(V2TIMConversation *conv) { + TUIConversationCellData *cellData = [self cellDataForConversation:conv]; + BOOL existInHidelist = cellData.isMarkAsHide; + + BOOL existInUnreadlist = cellData.isMarkAsUnread; + + if (existInHidelist || existInUnreadlist) { + [self cancelHideAndUnreadMarkConversation:conversationID existInHidelist:existInHidelist existInUnreadlist:existInUnreadlist]; + } + + } + fail:^(int code, NSString *desc) { + kLog(@"[TUIConversation] %s, code:%d, desc:%@", __func__, code, desc); + }]; + } + +} +- (void)cancelHideAndUnreadMarkConversation:(NSString *)conversationID existInHidelist:(BOOL)existInHidelist existInUnreadlist:(BOOL)existInUnreadlist { + if(existInHidelist && existInUnreadlist) { + [V2TIMManager.sharedInstance markConversation:@[ conversationID ] + markType:@(V2TIM_CONVERSATION_MARK_TYPE_HIDE) + enableMark:NO + succ:^(NSArray *result) { + [V2TIMManager.sharedInstance markConversation:@[ conversationID ] + markType:@(V2TIM_CONVERSATION_MARK_TYPE_UNREAD) + enableMark:NO + succ:nil + fail:^(int code, NSString *desc) { + kLog(@"[TUIConversation] %s code:%d, desc:%@", __func__, code, desc); + }]; + } + fail:^(int code, NSString *desc) { + kLog(@"[TUIConversation] %s code:%d, desc:%@", __func__, code, desc); + }]; + } + else if (existInHidelist) { + [V2TIMManager.sharedInstance markConversation:@[ conversationID ] + markType:@(V2TIM_CONVERSATION_MARK_TYPE_HIDE) + enableMark:NO + succ:nil + fail:^(int code, NSString *desc) { + kLog(@"[TUIConversation] %s code:%d, desc:%@", __func__, code, desc); + }]; + } + else if (existInUnreadlist) { + [V2TIMManager.sharedInstance markConversation:@[ conversationID ] + markType:@(V2TIM_CONVERSATION_MARK_TYPE_UNREAD) + enableMark:NO + succ:nil + fail:^(int code, NSString *desc) { + kLog(@"[TUIConversation] %s code:%d, desc:%@", __func__, code, desc); + }]; + } + else { + // noting to do + } } #pragma mark - SDK Data Process @@ -980,12 +1042,7 @@ * In some case, the time of unread conversation will be nil. * If this happens, directly mark the conversation as read. */ - if (conversation.userID.length > 0) { - [[V2TIMManager sharedInstance] markC2CMessageAsRead:conversation.userID succ:nil fail:nil]; - } - if (conversation.groupID.length > 0) { - [[V2TIMManager sharedInstance] markGroupMessageAsRead:conversation.groupID succ:nil fail:nil]; - } + [[V2TIMManager sharedInstance] cleanConversationUnreadMessageCount:conversation.conversationID cleanTimestamp:0 cleanSequence:0 succ:nil fail:nil]; } return YES; } @@ -999,12 +1056,7 @@ } - (void)markConversationAsRead:(TUIConversationCellData *)conv { - if (conv.userID.length > 0) { - [[V2TIMManager sharedInstance] markC2CMessageAsRead:conv.userID succ:nil fail:nil]; - } - if (conv.groupID.length > 0) { - [[V2TIMManager sharedInstance] markGroupMessageAsRead:conv.groupID succ:nil fail:nil]; - } + [[V2TIMManager sharedInstance] cleanConversationUnreadMessageCount:conv.conversationID cleanTimestamp:0 cleanSequence:0 succ:nil fail:nil]; [V2TIMManager.sharedInstance markConversation:@[ conv.conversationID ] markType:@(V2TIM_CONVERSATION_MARK_TYPE_UNREAD) enableMark:NO succ:nil fail:nil]; } diff --git a/iOS/TUIKit/TUIConversation/Resources/TUIConversation.bundle/message_not_disturb@2x.png b/iOS/TUIKit/TUIConversation/Resources/TUIConversation.bundle/message_not_disturb@2x.png index 6a19bd3d0..25135af52 100644 Binary files a/iOS/TUIKit/TUIConversation/Resources/TUIConversation.bundle/message_not_disturb@2x.png and b/iOS/TUIKit/TUIConversation/Resources/TUIConversation.bundle/message_not_disturb@2x.png differ diff --git a/iOS/TUIKit/TUIConversation/Resources/TUIConversation.bundle/msg_error_for_conv.png b/iOS/TUIKit/TUIConversation/Resources/TUIConversation.bundle/msg_error_for_conv.png index 5dc714be2..af496c134 100644 Binary files a/iOS/TUIKit/TUIConversation/Resources/TUIConversation.bundle/msg_error_for_conv.png and b/iOS/TUIKit/TUIConversation/Resources/TUIConversation.bundle/msg_error_for_conv.png differ diff --git a/iOS/TUIKit/TUIConversation/Resources/TUIConversation.bundle/msg_error_for_conv@2x.png b/iOS/TUIKit/TUIConversation/Resources/TUIConversation.bundle/msg_error_for_conv@2x.png index aa234de96..f25301a20 100644 Binary files a/iOS/TUIKit/TUIConversation/Resources/TUIConversation.bundle/msg_error_for_conv@2x.png and b/iOS/TUIKit/TUIConversation/Resources/TUIConversation.bundle/msg_error_for_conv@2x.png differ diff --git a/iOS/TUIKit/TUIConversation/Resources/TUIConversation.bundle/msg_error_for_conv@3x.png b/iOS/TUIKit/TUIConversation/Resources/TUIConversation.bundle/msg_error_for_conv@3x.png index cb0b5246e..ede352a8d 100644 Binary files a/iOS/TUIKit/TUIConversation/Resources/TUIConversation.bundle/msg_error_for_conv@3x.png and b/iOS/TUIKit/TUIConversation/Resources/TUIConversation.bundle/msg_error_for_conv@3x.png differ diff --git a/iOS/TUIKit/TUIConversation/Resources/TUIConversation.bundle/msg_sending_for_conv.png b/iOS/TUIKit/TUIConversation/Resources/TUIConversation.bundle/msg_sending_for_conv.png index 0edc0f6e3..0c94baf9e 100644 Binary files a/iOS/TUIKit/TUIConversation/Resources/TUIConversation.bundle/msg_sending_for_conv.png and b/iOS/TUIKit/TUIConversation/Resources/TUIConversation.bundle/msg_sending_for_conv.png differ diff --git a/iOS/TUIKit/TUIConversation/Resources/TUIConversation.bundle/msg_sending_for_conv@2x.png b/iOS/TUIKit/TUIConversation/Resources/TUIConversation.bundle/msg_sending_for_conv@2x.png index 40bb5314a..0b3321e6d 100644 Binary files a/iOS/TUIKit/TUIConversation/Resources/TUIConversation.bundle/msg_sending_for_conv@2x.png and b/iOS/TUIKit/TUIConversation/Resources/TUIConversation.bundle/msg_sending_for_conv@2x.png differ diff --git a/iOS/TUIKit/TUIConversation/Resources/TUIConversation.bundle/msg_sending_for_conv@3x.png b/iOS/TUIKit/TUIConversation/Resources/TUIConversation.bundle/msg_sending_for_conv@3x.png index 0f3366698..37366bec9 100644 Binary files a/iOS/TUIKit/TUIConversation/Resources/TUIConversation.bundle/msg_sending_for_conv@3x.png and b/iOS/TUIKit/TUIConversation/Resources/TUIConversation.bundle/msg_sending_for_conv@3x.png differ diff --git a/iOS/TUIKit/TUIConversation/Resources/TUIConversation.bundle/new_chat@3x.png b/iOS/TUIKit/TUIConversation/Resources/TUIConversation.bundle/new_chat@3x.png index cc2f2be41..035ed2b2f 100644 Binary files a/iOS/TUIKit/TUIConversation/Resources/TUIConversation.bundle/new_chat@3x.png and b/iOS/TUIKit/TUIConversation/Resources/TUIConversation.bundle/new_chat@3x.png differ diff --git a/iOS/TUIKit/TUIConversation/Resources/TUIConversation.bundle/new_groupchat@2x.png b/iOS/TUIKit/TUIConversation/Resources/TUIConversation.bundle/new_groupchat@2x.png index 22072cf96..4628703e3 100644 Binary files a/iOS/TUIKit/TUIConversation/Resources/TUIConversation.bundle/new_groupchat@2x.png and b/iOS/TUIKit/TUIConversation/Resources/TUIConversation.bundle/new_groupchat@2x.png differ diff --git a/iOS/TUIKit/TUIConversation/Resources/TUIConversation.bundle/no_conversation@3x.png b/iOS/TUIKit/TUIConversation/Resources/TUIConversation.bundle/no_conversation@3x.png index 61017c942..b28f6e9cd 100644 Binary files a/iOS/TUIKit/TUIConversation/Resources/TUIConversation.bundle/no_conversation@3x.png and b/iOS/TUIKit/TUIConversation/Resources/TUIConversation.bundle/no_conversation@3x.png differ diff --git a/iOS/TUIKit/TUIConversation/Resources/TUIConversationTheme.bundle/dark/resource/bg.png b/iOS/TUIKit/TUIConversation/Resources/TUIConversationTheme.bundle/dark/resource/bg.png index 7077009d5..a4d07d07a 100644 Binary files a/iOS/TUIKit/TUIConversation/Resources/TUIConversationTheme.bundle/dark/resource/bg.png and b/iOS/TUIKit/TUIConversation/Resources/TUIConversationTheme.bundle/dark/resource/bg.png differ diff --git a/iOS/TUIKit/TUIConversation/Resources/TUIConversationTheme.bundle/dark/resource/message_not_disturb@2x.png b/iOS/TUIKit/TUIConversation/Resources/TUIConversationTheme.bundle/dark/resource/message_not_disturb@2x.png index 81c614a27..ffde6e25a 100644 Binary files a/iOS/TUIKit/TUIConversation/Resources/TUIConversationTheme.bundle/dark/resource/message_not_disturb@2x.png and b/iOS/TUIKit/TUIConversation/Resources/TUIConversationTheme.bundle/dark/resource/message_not_disturb@2x.png differ diff --git a/iOS/TUIKit/TUIConversation/Resources/TUIConversationTheme.bundle/dark/resource/new_chat@3x.png b/iOS/TUIKit/TUIConversation/Resources/TUIConversationTheme.bundle/dark/resource/new_chat@3x.png index 441bd4090..6c56d5bbb 100644 Binary files a/iOS/TUIKit/TUIConversation/Resources/TUIConversationTheme.bundle/dark/resource/new_chat@3x.png and b/iOS/TUIKit/TUIConversation/Resources/TUIConversationTheme.bundle/dark/resource/new_chat@3x.png differ diff --git a/iOS/TUIKit/TUIConversation/Resources/TUIConversationTheme.bundle/dark/resource/new_groupchat@3x.png b/iOS/TUIKit/TUIConversation/Resources/TUIConversationTheme.bundle/dark/resource/new_groupchat@3x.png index 34a9bc5c5..027e168c9 100644 Binary files a/iOS/TUIKit/TUIConversation/Resources/TUIConversationTheme.bundle/dark/resource/new_groupchat@3x.png and b/iOS/TUIKit/TUIConversation/Resources/TUIConversationTheme.bundle/dark/resource/new_groupchat@3x.png differ diff --git a/iOS/TUIKit/TUIConversation/Resources/TUIConversationTheme.bundle/dark/resource/no_conversation@3x.png b/iOS/TUIKit/TUIConversation/Resources/TUIConversationTheme.bundle/dark/resource/no_conversation@3x.png index 331a8a4e7..b6caafaf6 100644 Binary files a/iOS/TUIKit/TUIConversation/Resources/TUIConversationTheme.bundle/dark/resource/no_conversation@3x.png and b/iOS/TUIKit/TUIConversation/Resources/TUIConversationTheme.bundle/dark/resource/no_conversation@3x.png differ diff --git a/iOS/TUIKit/TUIConversation/Resources/TUIConversationTheme.bundle/light/resource/bg.png b/iOS/TUIKit/TUIConversation/Resources/TUIConversationTheme.bundle/light/resource/bg.png index 87d7c51a0..292267063 100644 Binary files a/iOS/TUIKit/TUIConversation/Resources/TUIConversationTheme.bundle/light/resource/bg.png and b/iOS/TUIKit/TUIConversation/Resources/TUIConversationTheme.bundle/light/resource/bg.png differ diff --git a/iOS/TUIKit/TUIConversation/Resources/TUIConversationTheme.bundle/light/resource/new_groupchat@3x.png b/iOS/TUIKit/TUIConversation/Resources/TUIConversationTheme.bundle/light/resource/new_groupchat@3x.png index 2100ed866..44883c19e 100644 Binary files a/iOS/TUIKit/TUIConversation/Resources/TUIConversationTheme.bundle/light/resource/new_groupchat@3x.png and b/iOS/TUIKit/TUIConversation/Resources/TUIConversationTheme.bundle/light/resource/new_groupchat@3x.png differ diff --git a/iOS/TUIKit/TUIConversation/Resources/TUIConversationTheme.bundle/light/resource/no_conversation@3x.png b/iOS/TUIKit/TUIConversation/Resources/TUIConversationTheme.bundle/light/resource/no_conversation@3x.png index 61017c942..b28f6e9cd 100644 Binary files a/iOS/TUIKit/TUIConversation/Resources/TUIConversationTheme.bundle/light/resource/no_conversation@3x.png and b/iOS/TUIKit/TUIConversation/Resources/TUIConversationTheme.bundle/light/resource/no_conversation@3x.png differ diff --git a/iOS/TUIKit/TUIConversation/Resources/TUIConversationTheme.bundle/lively/resource/bg.png b/iOS/TUIKit/TUIConversation/Resources/TUIConversationTheme.bundle/lively/resource/bg.png index 62c1d746f..acfbbf52c 100644 Binary files a/iOS/TUIKit/TUIConversation/Resources/TUIConversationTheme.bundle/lively/resource/bg.png and b/iOS/TUIKit/TUIConversation/Resources/TUIConversationTheme.bundle/lively/resource/bg.png differ diff --git a/iOS/TUIKit/TUIConversation/Resources/TUIConversationTheme.bundle/lively/resource/no_conversation@3x.png b/iOS/TUIKit/TUIConversation/Resources/TUIConversationTheme.bundle/lively/resource/no_conversation@3x.png index 10d530f5a..c8a61e24e 100644 Binary files a/iOS/TUIKit/TUIConversation/Resources/TUIConversationTheme.bundle/lively/resource/no_conversation@3x.png and b/iOS/TUIKit/TUIConversation/Resources/TUIConversationTheme.bundle/lively/resource/no_conversation@3x.png differ diff --git a/iOS/TUIKit/TUIConversation/Resources/TUIConversationTheme.bundle/serious/resource/bg.png b/iOS/TUIKit/TUIConversation/Resources/TUIConversationTheme.bundle/serious/resource/bg.png index ccaf89e4a..0ad7159f3 100644 Binary files a/iOS/TUIKit/TUIConversation/Resources/TUIConversationTheme.bundle/serious/resource/bg.png and b/iOS/TUIKit/TUIConversation/Resources/TUIConversationTheme.bundle/serious/resource/bg.png differ diff --git a/iOS/TUIKit/TUIConversation/Resources/TUIConversationTheme.bundle/serious/resource/no_conversation@3x.png b/iOS/TUIKit/TUIConversation/Resources/TUIConversationTheme.bundle/serious/resource/no_conversation@3x.png index d62aa4a6f..619a35503 100644 Binary files a/iOS/TUIKit/TUIConversation/Resources/TUIConversationTheme.bundle/serious/resource/no_conversation@3x.png and b/iOS/TUIKit/TUIConversation/Resources/TUIConversationTheme.bundle/serious/resource/no_conversation@3x.png differ diff --git a/iOS/TUIKit/TUIConversation/Resources/TUIConversation_Minimalist.bundle/bottomLogo@3x.png b/iOS/TUIKit/TUIConversation/Resources/TUIConversation_Minimalist.bundle/bottomLogo@3x.png index de01f6fe1..14d735baf 100644 Binary files a/iOS/TUIKit/TUIConversation/Resources/TUIConversation_Minimalist.bundle/bottomLogo@3x.png and b/iOS/TUIKit/TUIConversation/Resources/TUIConversation_Minimalist.bundle/bottomLogo@3x.png differ diff --git a/iOS/TUIKit/TUIConversation/Resources/TUIConversation_Minimalist.bundle/icon_checkmark@3x.png b/iOS/TUIKit/TUIConversation/Resources/TUIConversation_Minimalist.bundle/icon_checkmark@3x.png index 8da7d83be..eb3ef4cc5 100644 Binary files a/iOS/TUIKit/TUIConversation/Resources/TUIConversation_Minimalist.bundle/icon_checkmark@3x.png and b/iOS/TUIKit/TUIConversation/Resources/TUIConversation_Minimalist.bundle/icon_checkmark@3x.png differ diff --git a/iOS/TUIKit/TUIConversation/Resources/TUIConversation_Minimalist.bundle/icon_conversation_swipe_more@3x.png b/iOS/TUIKit/TUIConversation/Resources/TUIConversation_Minimalist.bundle/icon_conversation_swipe_more@3x.png index 0cd395e1d..8eabb35dc 100644 Binary files a/iOS/TUIKit/TUIConversation/Resources/TUIConversation_Minimalist.bundle/icon_conversation_swipe_more@3x.png and b/iOS/TUIKit/TUIConversation/Resources/TUIConversation_Minimalist.bundle/icon_conversation_swipe_more@3x.png differ diff --git a/iOS/TUIKit/TUIConversation/Resources/TUIConversation_Minimalist.bundle/icon_conversation_swipe_more_ar.png b/iOS/TUIKit/TUIConversation/Resources/TUIConversation_Minimalist.bundle/icon_conversation_swipe_more_ar.png new file mode 100644 index 000000000..c934154b6 Binary files /dev/null and b/iOS/TUIKit/TUIConversation/Resources/TUIConversation_Minimalist.bundle/icon_conversation_swipe_more_ar.png differ diff --git a/iOS/TUIKit/TUIConversation/Resources/TUIConversation_Minimalist.bundle/icon_conversation_swipe_more_zh@3x.png b/iOS/TUIKit/TUIConversation/Resources/TUIConversation_Minimalist.bundle/icon_conversation_swipe_more_zh@3x.png index b585c602f..914d7ddde 100644 Binary files a/iOS/TUIKit/TUIConversation/Resources/TUIConversation_Minimalist.bundle/icon_conversation_swipe_more_zh@3x.png and b/iOS/TUIKit/TUIConversation/Resources/TUIConversation_Minimalist.bundle/icon_conversation_swipe_more_zh@3x.png differ diff --git a/iOS/TUIKit/TUIConversation/Resources/TUIConversation_Minimalist.bundle/icon_conversation_swipe_read@3x.png b/iOS/TUIKit/TUIConversation/Resources/TUIConversation_Minimalist.bundle/icon_conversation_swipe_read@3x.png index 36b688187..59a262afc 100644 Binary files a/iOS/TUIKit/TUIConversation/Resources/TUIConversation_Minimalist.bundle/icon_conversation_swipe_read@3x.png and b/iOS/TUIKit/TUIConversation/Resources/TUIConversation_Minimalist.bundle/icon_conversation_swipe_read@3x.png differ diff --git a/iOS/TUIKit/TUIConversation/Resources/TUIConversation_Minimalist.bundle/icon_conversation_swipe_read_ar.png b/iOS/TUIKit/TUIConversation/Resources/TUIConversation_Minimalist.bundle/icon_conversation_swipe_read_ar.png new file mode 100644 index 000000000..ee5c1ab27 Binary files /dev/null and b/iOS/TUIKit/TUIConversation/Resources/TUIConversation_Minimalist.bundle/icon_conversation_swipe_read_ar.png differ diff --git a/iOS/TUIKit/TUIConversation/Resources/TUIConversation_Minimalist.bundle/icon_conversation_swipe_read_zh@3x.png b/iOS/TUIKit/TUIConversation/Resources/TUIConversation_Minimalist.bundle/icon_conversation_swipe_read_zh@3x.png index a910692a5..65c90a540 100644 Binary files a/iOS/TUIKit/TUIConversation/Resources/TUIConversation_Minimalist.bundle/icon_conversation_swipe_read_zh@3x.png and b/iOS/TUIKit/TUIConversation/Resources/TUIConversation_Minimalist.bundle/icon_conversation_swipe_read_zh@3x.png differ diff --git a/iOS/TUIKit/TUIConversation/Resources/TUIConversation_Minimalist.bundle/icon_conversation_swipe_unread@3x.png b/iOS/TUIKit/TUIConversation/Resources/TUIConversation_Minimalist.bundle/icon_conversation_swipe_unread@3x.png index 6ce52d18f..59b143e50 100644 Binary files a/iOS/TUIKit/TUIConversation/Resources/TUIConversation_Minimalist.bundle/icon_conversation_swipe_unread@3x.png and b/iOS/TUIKit/TUIConversation/Resources/TUIConversation_Minimalist.bundle/icon_conversation_swipe_unread@3x.png differ diff --git a/iOS/TUIKit/TUIConversation/Resources/TUIConversation_Minimalist.bundle/icon_conversation_swipe_unread_ar.png b/iOS/TUIKit/TUIConversation/Resources/TUIConversation_Minimalist.bundle/icon_conversation_swipe_unread_ar.png new file mode 100644 index 000000000..9ca835e2a Binary files /dev/null and b/iOS/TUIKit/TUIConversation/Resources/TUIConversation_Minimalist.bundle/icon_conversation_swipe_unread_ar.png differ diff --git a/iOS/TUIKit/TUIConversation/Resources/TUIConversation_Minimalist.bundle/icon_conversation_swipe_unread_zh@3x.png b/iOS/TUIKit/TUIConversation/Resources/TUIConversation_Minimalist.bundle/icon_conversation_swipe_unread_zh@3x.png index 70dc3c5ef..220bd9b03 100644 Binary files a/iOS/TUIKit/TUIConversation/Resources/TUIConversation_Minimalist.bundle/icon_conversation_swipe_unread_zh@3x.png and b/iOS/TUIKit/TUIConversation/Resources/TUIConversation_Minimalist.bundle/icon_conversation_swipe_unread_zh@3x.png differ diff --git a/iOS/TUIKit/TUIConversation/Resources/TUIConversation_Minimalist.bundle/icon_online_status@3x.png b/iOS/TUIKit/TUIConversation/Resources/TUIConversation_Minimalist.bundle/icon_online_status@3x.png index 56503d340..c2fd8e6bc 100644 Binary files a/iOS/TUIKit/TUIConversation/Resources/TUIConversation_Minimalist.bundle/icon_online_status@3x.png and b/iOS/TUIKit/TUIConversation/Resources/TUIConversation_Minimalist.bundle/icon_online_status@3x.png differ diff --git a/iOS/TUIKit/TUIConversation/Resources/TUIConversation_Minimalist.bundle/icon_sendingmark@3x.png b/iOS/TUIKit/TUIConversation/Resources/TUIConversation_Minimalist.bundle/icon_sendingmark@3x.png index 0f3366698..37366bec9 100644 Binary files a/iOS/TUIKit/TUIConversation/Resources/TUIConversation_Minimalist.bundle/icon_sendingmark@3x.png and b/iOS/TUIKit/TUIConversation/Resources/TUIConversation_Minimalist.bundle/icon_sendingmark@3x.png differ diff --git a/iOS/TUIKit/TUIConversation/Resources/TUIConversation_Minimalist.bundle/message_not_disturb@3x.png b/iOS/TUIKit/TUIConversation/Resources/TUIConversation_Minimalist.bundle/message_not_disturb@3x.png index 283a60592..847e7ddb4 100644 Binary files a/iOS/TUIKit/TUIConversation/Resources/TUIConversation_Minimalist.bundle/message_not_disturb@3x.png and b/iOS/TUIKit/TUIConversation/Resources/TUIConversation_Minimalist.bundle/message_not_disturb@3x.png differ diff --git a/iOS/TUIKit/TUIConversation/Resources/TUIConversation_Minimalist.bundle/msg_error_for_conv@3x.png b/iOS/TUIKit/TUIConversation/Resources/TUIConversation_Minimalist.bundle/msg_error_for_conv@3x.png index cb0b5246e..ede352a8d 100644 Binary files a/iOS/TUIKit/TUIConversation/Resources/TUIConversation_Minimalist.bundle/msg_error_for_conv@3x.png and b/iOS/TUIKit/TUIConversation/Resources/TUIConversation_Minimalist.bundle/msg_error_for_conv@3x.png differ diff --git a/iOS/TUIKit/TUIConversation/Resources/TUIConversation_Minimalist.bundle/nav_add@2x.png b/iOS/TUIKit/TUIConversation/Resources/TUIConversation_Minimalist.bundle/nav_add@2x.png index 57e81830e..81371ffcd 100644 Binary files a/iOS/TUIKit/TUIConversation/Resources/TUIConversation_Minimalist.bundle/nav_add@2x.png and b/iOS/TUIKit/TUIConversation/Resources/TUIConversation_Minimalist.bundle/nav_add@2x.png differ diff --git a/iOS/TUIKit/TUIConversation/Resources/TUIConversation_Minimalist.bundle/nav_edit@2x.png b/iOS/TUIKit/TUIConversation/Resources/TUIConversation_Minimalist.bundle/nav_edit@2x.png index 93221cf05..3ba40e0c4 100644 Binary files a/iOS/TUIKit/TUIConversation/Resources/TUIConversation_Minimalist.bundle/nav_edit@2x.png and b/iOS/TUIKit/TUIConversation/Resources/TUIConversation_Minimalist.bundle/nav_edit@2x.png differ diff --git a/iOS/TUIKit/TUIConversation/TUIConversation.podspec b/iOS/TUIKit/TUIConversation/TUIConversation.podspec index bb4153b65..3670d2597 100644 --- a/iOS/TUIKit/TUIConversation/TUIConversation.podspec +++ b/iOS/TUIKit/TUIConversation/TUIConversation.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |spec| spec.name = 'TUIConversation' - spec.version = '7.4.4643' + spec.version = '7.5.4852' spec.platform = :ios spec.ios.deployment_target = '9.0' spec.license = { :type => 'Proprietary', diff --git a/iOS/TUIKit/TUIConversation/UI_Classic/DataProvider/TUIConversationListDataProvider.m b/iOS/TUIKit/TUIConversation/UI_Classic/DataProvider/TUIConversationListDataProvider.m index a489b5289..1d0d16b03 100644 --- a/iOS/TUIKit/TUIConversation/UI_Classic/DataProvider/TUIConversationListDataProvider.m +++ b/iOS/TUIKit/TUIConversation/UI_Classic/DataProvider/TUIConversationListDataProvider.m @@ -10,6 +10,7 @@ #import #import #import "TUIConversationCellData.h" +#import @implementation TUIConversationListDataProvider - (Class)getConversationCellClass { @@ -39,9 +40,12 @@ NSAttributedString *draft = [[NSAttributedString alloc] initWithString:TIMCommonLocalizableString(TUIKitMessageTypeDraftFormat) attributes:@{NSForegroundColorAttributeName : RGB(250, 81, 81)}]; [attributeString appendAttributedString:draft]; - - NSAttributedString *draftContent = [[NSAttributedString alloc] initWithString:[self getDraftContent:conv] + + NSString *draftContentStr = [self getDraftContent:conv]; + draftContentStr = [draftContentStr getLocalizableStringWithFaceContent]; + NSAttributedString *draftContent = [[NSAttributedString alloc] initWithString:draftContentStr attributes:@{NSForegroundColorAttributeName : [UIColor d_systemGrayColor]}]; + [attributeString appendAttributedString:draftContent]; } else { /** diff --git a/iOS/TUIKit/TUIConversation/UI_Classic/DataProvider/TUIFoldConversationListDataProvider.m b/iOS/TUIKit/TUIConversation/UI_Classic/DataProvider/TUIFoldConversationListDataProvider.m index a9079f03b..42a8aa604 100644 --- a/iOS/TUIKit/TUIConversation/UI_Classic/DataProvider/TUIFoldConversationListDataProvider.m +++ b/iOS/TUIKit/TUIConversation/UI_Classic/DataProvider/TUIFoldConversationListDataProvider.m @@ -10,6 +10,8 @@ #import #import #import "TUIConversationCellData.h" +#import + @implementation TUIFoldConversationListDataProvider - (Class)getConversationCellClass { @@ -40,8 +42,11 @@ attributes:@{NSForegroundColorAttributeName : RGB(250, 81, 81)}]; [attributeString appendAttributedString:draft]; - NSAttributedString *draftContent = [[NSAttributedString alloc] initWithString:[self getDraftContent:conv] - attributes:@{NSForegroundColorAttributeName : [UIColor d_systemGrayColor]}]; + NSString *draftContentStr = [self getDraftContent:conv]; + + NSMutableAttributedString *draftContent = [draftContentStr getAdvancedFormatEmojiStringWithFont:[UIFont systemFontOfSize:16.0] + textColor:TUIChatDynamicColor(@"chat_input_text_color", @"#000000") + emojiLocations:nil]; [attributeString appendAttributedString:draftContent]; } else { /** diff --git a/iOS/TUIKit/TUIConversation/UI_Classic/UI/TUIConversationListController.m b/iOS/TUIKit/TUIConversation/UI_Classic/UI/TUIConversationListController.m index b9d4e07d5..eca745ef0 100644 --- a/iOS/TUIKit/TUIConversation/UI_Classic/UI/TUIConversationListController.m +++ b/iOS/TUIKit/TUIConversation/UI_Classic/UI/TUIConversationListController.m @@ -111,7 +111,11 @@ CGFloat height = [TUIPopCell getHeight] * menus.count + TUIPopView_Arrow_Size.height; CGFloat orginY = StatusBar_Height + NavBar_Height; - TUIPopView *popView = [[TUIPopView alloc] initWithFrame:CGRectMake(Screen_Width - 155, orginY, 145, height)]; + CGFloat orginX = Screen_Width - 155; + if(isRTL()){ + orginX = 10; + } + TUIPopView *popView = [[TUIPopView alloc] initWithFrame:CGRectMake(orginX, orginY, 145, height)]; CGRect frameInNaviView = [self.navigationController.view convertRect:rightBarButton.frame fromView:rightBarButton.superview]; popView.arrowPoint = CGPointMake(frameInNaviView.origin.x + frameInNaviView.size.width * 0.5, orginY); popView.delegate = self; @@ -231,9 +235,12 @@ [TUICore raiseExtension:TUICore_TUIConversationExtension_ConversationGroupManagerContainer_ClassicExtensionID parentView:self.groupBtnContainer param:@{TUICore_TUIConversationExtension_ConversationGroupManagerContainer_ParentVCKey : self}]; - + CGFloat groupScrollViewWidth = self.groupBtnContainer.mm_x - kScale375(16) - kScale375(10); - self.groupScrollView = [[UIScrollView alloc] initWithFrame:CGRectMake(kScale375(16), 18, groupScrollViewWidth, GroupScrollViewHeight)]; + UIView *groupScrollBackgrounView = [[UIView alloc] init]; + [_groupView addSubview:groupScrollBackgrounView]; + groupScrollBackgrounView.frame = CGRectMake(kScale375(16), 18, groupScrollViewWidth, GroupScrollViewHeight); + self.groupScrollView = [[UIScrollView alloc] initWithFrame:CGRectMake(0, 0, groupScrollViewWidth, GroupScrollViewHeight)]; self.groupScrollView.backgroundColor = TUIConversationDynamicColor(@"conversation_group_bg_color", @"#EBECF0"); self.groupScrollView.showsHorizontalScrollIndicator = NO; self.groupScrollView.showsVerticalScrollIndicator = NO; @@ -241,11 +248,16 @@ self.groupScrollView.scrollEnabled = YES; self.groupScrollView.layer.cornerRadius = GroupScrollViewHeight / 2.0; self.groupScrollView.layer.masksToBounds = YES; - [_groupView addSubview:self.groupScrollView]; + [groupScrollBackgrounView addSubview:self.groupScrollView]; @weakify(self); [[[RACObserve(self.groupScrollView, contentSize) distinctUntilChanged] skip:1] subscribeNext:^(NSValue *contentSizeValue) { @strongify(self); - self.groupScrollView.mm_w = MIN(groupScrollViewWidth, [contentSizeValue CGSizeValue].width); + [self.groupScrollView mas_remakeConstraints:^(MASConstraintMaker *make) { + make.leading.mas_equalTo(groupScrollBackgrounView.mas_leading); + make.height.mas_equalTo(GroupScrollViewHeight); + make.width.mas_equalTo(MIN(groupScrollViewWidth, [contentSizeValue CGSizeValue].width)); + make.centerY.mas_equalTo(groupScrollBackgrounView); + }]; }]; self.groupAnimationView = [[UIView alloc] init]; @@ -255,6 +267,15 @@ self.groupAnimationView.layer.borderWidth = 1; self.groupAnimationView.layer.borderColor = [TUIConversationDynamicColor(@"conversation_group_bg_color", @"#EBECF0") CGColor]; [self.groupScrollView addSubview:self.groupAnimationView]; + if (isRTL()) { + [groupScrollBackgrounView resetFrameToFitRTL]; + [self.groupBtnContainer resetFrameToFitRTL]; + self.groupScrollView.transform = CGAffineTransformMakeRotation(M_PI); + NSArray *subViews = self.groupScrollView.subviews; + for (UIView *subView in subViews) { + subView.transform = CGAffineTransformMakeRotation(M_PI); + } + } } return _groupView; } @@ -272,13 +293,23 @@ groupBtn.mm_w = groupBtn.mm_w + GroupBtnSpace; groupBtn.mm_h = GroupScrollViewHeight; groupItem.groupBtn = groupBtn; + if (isRTL()) { + groupBtn.transform = CGAffineTransformMakeRotation(M_PI); + } + } - (void)updateGroupBtn:(TUIConversationGroupItem *)groupItem { [groupItem.groupBtn setAttributedTitle:[self getGroupBtnAttributedString:groupItem] forState:UIControlStateNormal]; - [groupItem.groupBtn sizeToFit]; - groupItem.groupBtn.mm_w = groupItem.groupBtn.mm_w + GroupBtnSpace; - groupItem.groupBtn.mm_h = GroupScrollViewHeight; + if(isRTL()) { + groupItem.groupBtn.mm_w = groupItem.groupBtn.mm_w ; + groupItem.groupBtn.mm_h = GroupScrollViewHeight; + } + else { + [groupItem.groupBtn sizeToFit]; + groupItem.groupBtn.mm_w = groupItem.groupBtn.mm_w + GroupBtnSpace; + groupItem.groupBtn.mm_h = GroupScrollViewHeight; + } } - (void)onGroupBtnClick:(UIButton *)btn { @@ -309,6 +340,12 @@ self.groupAnimationView.frame = groupItem.groupBtn.frame; } } + if (isRTL()) { + NSArray *subViews = self.groupScrollView.subviews; + for (UIView *subView in subViews) { + subView.transform = CGAffineTransformMakeRotation(M_PI); + } + } } - (void)addGroup:(TUIConversationGroupItem *)addGroup { @@ -438,32 +475,48 @@ } - (NSMutableAttributedString *)getGroupBtnAttributedString:(TUIConversationGroupItem *)groupItem { - NSMutableString *content = [NSMutableString stringWithString:groupItem.groupName]; + NSMutableString *content = [NSMutableString stringWithString:@""]; + NSMutableString *contentName = [NSMutableString stringWithString: groupItem.groupName]; + NSMutableString *contentNum = [NSMutableString stringWithString:@""]; + NSMutableAttributedString *attributeString = nil; NSInteger unreadCount = groupItem.unreadCount; if (unreadCount > 0) { + [contentNum appendString:(unreadCount > 99 ? @"99+" : [@(unreadCount) stringValue])]; + } + if (isRTL()){ + [content appendString:@"\u200E"]; + [content appendString:contentNum]; [content appendString:@" "]; - [content appendString:(unreadCount > 99 ? @"99+" : [@(unreadCount) stringValue])]; + [content appendString:@"\u202B"]; + [content appendString:contentName]; + attributeString = [[NSMutableAttributedString alloc] initWithString:content]; } - NSMutableAttributedString *attributeString = [[NSMutableAttributedString alloc] initWithString:content]; - if (groupItem.groupBtn.isSelected) { - [attributeString setAttributes:@{ - NSFontAttributeName : [UIFont systemFontOfSize:16], - NSForegroundColorAttributeName : TUIConversationDynamicColor(@"conversation_group_btn_select_color", @"#147AFF") - } - range:NSMakeRange(0, groupItem.groupName.length)]; - } else { - [attributeString setAttributes:@{ - NSFontAttributeName : [UIFont systemFontOfSize:16], - NSForegroundColorAttributeName : TUIConversationDynamicColor(@"conversation_group_btn_unselect_color", @"#666666") - } - range:NSMakeRange(0, groupItem.groupName.length)]; + else { + [content appendString:contentName]; + [content appendString:@" "]; + [content appendString:contentNum]; + attributeString = [[NSMutableAttributedString alloc] initWithString:content]; } + [attributeString setAttributes:@{ NSForegroundColorAttributeName : TUIConversationDynamicColor(@"conversation_group_btn_select_color", @"#147AFF"), NSFontAttributeName : [UIFont systemFontOfSize:12], NSBaselineOffsetAttributeName : @(1) } - range:NSMakeRange(groupItem.groupName.length, content.length - groupItem.groupName.length)]; + range:[content rangeOfString:contentNum]]; + if (groupItem.groupBtn.isSelected) { + [attributeString setAttributes:@{ + NSFontAttributeName : [UIFont systemFontOfSize:16], + NSForegroundColorAttributeName : TUIConversationDynamicColor(@"conversation_group_btn_select_color", @"#147AFF") + } + range:[content rangeOfString:contentName]]; + } else { + [attributeString setAttributes:@{ + NSFontAttributeName : [UIFont systemFontOfSize:16], + NSForegroundColorAttributeName : TUIConversationDynamicColor(@"conversation_group_btn_unselect_color", @"#666666") + } + range:[content rangeOfString:contentName]]; + } return attributeString; } @@ -477,7 +530,7 @@ if ([key isEqualToString:TUICore_TUIConversationGroupNotify]) { if ([param objectForKey:TUICore_TUIConversationGroupNotify_GroupListReloadKey]) { NSArray *groupItemList = [param objectForKey:TUICore_TUIConversationGroupNotify_GroupListReloadKey]; - if (groupItemList && groupItemList.count > 0) { + if (groupItemList) { [self reloadGroupList:groupItemList]; } } else if ([param objectForKey:TUICore_TUIConversationGroupNotify_GroupAddKey]) { diff --git a/iOS/TUIKit/TUIConversation/UI_Minimalist/Cell/CellUI/TUIConversationCell_Minimalist.m b/iOS/TUIKit/TUIConversation/UI_Minimalist/Cell/CellUI/TUIConversationCell_Minimalist.m index 3a2fe02c4..fb5462874 100644 --- a/iOS/TUIKit/TUIConversation/UI_Minimalist/Cell/CellUI/TUIConversationCell_Minimalist.m +++ b/iOS/TUIKit/TUIConversation/UI_Minimalist/Cell/CellUI/TUIConversationCell_Minimalist.m @@ -49,6 +49,14 @@ [self configOnlineStatusIcon:convData]; [self configDisplayLastMessageStatusImage:convData]; + + // tell constraints they need updating + [self setNeedsUpdateConstraints]; + + // update constraints now so we can animate the change + [self updateConstraintsIfNeeded]; + + [self layoutIfNeeded]; } - (void)configHeadImageView:(TUIConversationCellData *)convData { @@ -235,8 +243,7 @@ @strongify(self); if (convData.onlineStatus == TUIConversationOnlineStatusOnline && TUIConfig.defaultConfig.displayOnlineStatusIcon) { self.onlineStatusIcon.hidden = NO; - self.onlineStatusIcon.image = - TUIDynamicImage(@"", TUIThemeModuleConversation_Minimalist, [UIImage imageNamed:TUIConversationImagePath_Minimalist(@"icon_online_status")]); + self.onlineStatusIcon.image = TIMCommonDynamicImage(@"icon_online_status", [UIImage imageNamed:TIMCommonImagePath(@"icon_online_status")]); } else if (convData.onlineStatus == TUIConversationOnlineStatusOffline && TUIConfig.defaultConfig.displayOnlineStatusIcon) { self.onlineStatusIcon.hidden = YES; self.onlineStatusIcon.image = nil; @@ -264,27 +271,51 @@ return image; } -- (void)layoutSubviews { - [super layoutSubviews]; ++ (BOOL)requiresConstraintBasedLayout { + return YES; +} +// this is Apple's recommended place for adding/updating constraints +- (void)updateConstraints { + + [super updateConstraints]; + CGFloat height = [self.convData heightOfWidth:self.mm_w]; self.mm_h = height; CGFloat imgHeight = height - 2 * (kScale390(12)); + if (self.convData.isOnTop) { + self.contentView.backgroundColor = TUIConversationDynamicColor(@"conversation_cell_top_bg_color", @"#F4F4F4"); + } else { + self.contentView.backgroundColor = TUIConversationDynamicColor(@"conversation_cell_bg_color", @"#FFFFFF"); + } + + CGFloat selectedIconSize = 20; if (self.convData.showCheckBox) { - self.selectedIcon.mm_width(20).mm_height(20); - self.selectedIcon.mm_x = 10; - self.selectedIcon.mm_centerY = self.headImageView.mm_centerY; self.selectedIcon.hidden = NO; } else { - self.selectedIcon.mm_width(0).mm_height(0); - self.selectedIcon.mm_x = 0; - self.selectedIcon.mm_y = 0; self.selectedIcon.hidden = YES; } - - CGFloat margin = self.convData.showCheckBox ? self.selectedIcon.mm_maxX : 0; - self.headImageView.mm_width(imgHeight).mm_height(imgHeight).mm_left(kScale390(16) + margin).mm_top(kScale390(12)); + + [self.selectedIcon mas_remakeConstraints:^(MASConstraintMaker *make) { + if (self.convData.showCheckBox) { + make.width.height.mas_equalTo(selectedIconSize); + make.leading.mas_equalTo(self.contentView.mas_leading).mas_offset(10); + make.centerY.mas_equalTo(self.contentView.mas_centerY); + } + }]; + + [self.headImageView mas_remakeConstraints:^(MASConstraintMaker *make) { + make.size.mas_equalTo(imgHeight); + make.centerY.mas_equalTo(self.contentView.mas_centerY); + if (self.convData.showCheckBox) { + make.leading.mas_equalTo(self.selectedIcon.mas_trailing).mas_offset(kScale390(16)); + } + else { + make.leading.mas_equalTo(self.contentView.mas_leading).mas_offset(kScale390(16)); + } + }]; + if ([TUIConfig defaultConfig].avatarType == TAvatarTypeRounded) { self.headImageView.layer.masksToBounds = YES; self.headImageView.layer.cornerRadius = imgHeight / 2; @@ -292,35 +323,79 @@ self.headImageView.layer.masksToBounds = YES; self.headImageView.layer.cornerRadius = [TUIConfig defaultConfig].avatarCornerRadius; } + [self.timeLabel sizeToFit]; + [self.timeLabel mas_remakeConstraints:^(MASConstraintMaker *make) { + make.width.mas_equalTo(self.timeLabel.frame.size.width); + make.height.mas_greaterThanOrEqualTo(self.timeLabel.font.lineHeight); + make.top.mas_equalTo(self.subTitleLabel.mas_top); + make.trailing.mas_equalTo(self.contentView).mas_offset(- kScale390(8)); + }]; + MASAttachKeys(self.timeLabel); - self.unReadView.mm_right(self.mm_r + kScale390(8)).mm_top(kScale390(16.5)); - self.timeLabel.mm_sizeToFit().mm_top(self.unReadView.mm_maxY + kScale390(3)).mm_right(kScale390(8)); - self.lastMessageStatusImageView.mm_width(kScale390(14)) - .mm_height(14) - .mm_top(self.unReadView.mm_maxY + kScale390(3)) - .mm_right(kScale390(1) + self.timeLabel.mm_w + kScale390(8)); - self.titleLabel.mm_sizeToFit() - .mm_top(self.unReadView.mm_y) - .mm_left(self.headImageView.mm_maxX + kScale390(8)) - .mm_flexToRight(self.timeLabel.mm_w + 2 * kScale390(14)); - self.subTitleLabel.mm_sizeToFit().mm_left(self.titleLabel.mm_x).mm_top(self.titleLabel.mm_maxY + kScale390(3)).mm_flexToRight(2 * kScale390(28)); - self.notDisturbRedDot.mm_width(TConversationCell_Margin_Disturb_Dot) - .mm_height(TConversationCell_Margin_Disturb_Dot) - .mm_right(self.headImageView.mm_r - 3) - .mm_top(self.headImageView.mm_y - 3); - self.notDisturbView.mm_width(TConversationCell_Margin_Disturb).mm_height(TConversationCell_Margin_Disturb).mm_top(kScale390(16)).mm_right(kScale390(8)); + [self.lastMessageStatusImageView mas_remakeConstraints:^(MASConstraintMaker *make) { + make.width.mas_equalTo(kScale390(14)); + make.height.mas_equalTo(14); + make.trailing.mas_equalTo(self.timeLabel.mas_leading).mas_offset(- (kScale390(1) + kScale390(8))); + make.bottom.mas_equalTo(self.timeLabel.mas_bottom); + }]; + MASAttachKeys(self.lastMessageStatusImageView); + + [self.titleLabel mas_remakeConstraints:^(MASConstraintMaker *make) { + make.width.mas_greaterThanOrEqualTo(120); + make.height.mas_greaterThanOrEqualTo(self.titleLabel.font.lineHeight); + make.top.mas_equalTo(self.contentView.mas_top).mas_offset(kScale390(14)); + make.leading.mas_equalTo(self.headImageView.mas_trailing).mas_offset(kScale390(8)); + make.trailing.mas_equalTo(self.timeLabel.mas_leading).mas_offset(- 2*kScale390(14)); + }]; + MASAttachKeys(self.titleLabel); - self.onlineStatusIcon.mm_width(kScale390(10)).mm_height(kScale390(10)); - self.onlineStatusIcon.mm_x = CGRectGetMaxX(self.headImageView.frame) - 0.5 * self.onlineStatusIcon.mm_w - kScale390(3); - self.onlineStatusIcon.mm_y = CGRectGetMaxY(self.headImageView.frame) - self.onlineStatusIcon.mm_w; - self.onlineStatusIcon.layer.cornerRadius = 0.5 * self.onlineStatusIcon.mm_w; + - if (self.convData.isOnTop) { - self.contentView.backgroundColor = TUIConversationDynamicColor(@"conversation_cell_top_bg_color", @"#F4F4F4"); - } else { - self.contentView.backgroundColor = TUIConversationDynamicColor(@"conversation_cell_bg_color", @"#FFFFFF"); - ; - } + [self.subTitleLabel sizeToFit]; + [self.subTitleLabel mas_remakeConstraints:^(MASConstraintMaker *make) { + make.height.mas_greaterThanOrEqualTo(self.subTitleLabel); + make.bottom.mas_equalTo(self.contentView).mas_offset(- kScale390(14)); + make.leading.mas_equalTo(self.titleLabel.mas_leading); + make.trailing.mas_equalTo(self.timeLabel.mas_leading).mas_offset(-kScale390(8)); + }]; + MASAttachKeys(self.subTitleLabel); + + [self.unReadView.unReadLabel sizeToFit]; + [self.unReadView mas_remakeConstraints:^(MASConstraintMaker *make) { + make.trailing.mas_equalTo(self.timeLabel.mas_trailing); + make.top.mas_equalTo(self.titleLabel.mas_top); + make.width.mas_equalTo(kScale375(18)); + make.height.mas_equalTo(kScale375(18)); + }]; + [self.unReadView.unReadLabel mas_remakeConstraints:^(MASConstraintMaker *make) { + make.center.mas_equalTo(self.unReadView); + make.size.mas_equalTo(self.unReadView.unReadLabel); + }]; + self.unReadView.layer.cornerRadius = kScale375(18) * 0.5; + [self.unReadView.layer masksToBounds]; + + [self.notDisturbRedDot mas_remakeConstraints:^(MASConstraintMaker *make) { + make.trailing.mas_equalTo(self.headImageView.mas_trailing).mas_offset(3); + make.top.mas_equalTo(self.headImageView.mas_top).mas_offset(1); + make.width.height.mas_equalTo(TConversationCell_Margin_Disturb_Dot); + }]; + + [self.notDisturbView mas_remakeConstraints:^(MASConstraintMaker *make) { + make.width.height.mas_equalTo(TConversationCell_Margin_Disturb); + make.trailing.mas_equalTo(self.timeLabel.mas_trailing); + make.top.mas_equalTo(self.titleLabel.mas_top); + }]; + + [self.onlineStatusIcon mas_remakeConstraints:^(MASConstraintMaker *make) { + make.width.height.mas_equalTo(kScale375(15)); + make.leading.mas_equalTo(self.headImageView.mas_trailing).mas_offset(-kScale375(10)); + make.bottom.mas_equalTo(self.headImageView.mas_bottom).mas_offset(-kScale375(1)); + }]; + + self.onlineStatusIcon.layer.cornerRadius = 0.5 *kScale375(15); +} +- (void)layoutSubviews { + [super layoutSubviews]; } @end diff --git a/iOS/TUIKit/TUIConversation/UI_Minimalist/Cell/CellUI/TUIConversationForwardSelectCell_Minimalist.m b/iOS/TUIKit/TUIConversation/UI_Minimalist/Cell/CellUI/TUIConversationForwardSelectCell_Minimalist.m index ef439874e..a7bcc82a3 100644 --- a/iOS/TUIKit/TUIConversation/UI_Minimalist/Cell/CellUI/TUIConversationForwardSelectCell_Minimalist.m +++ b/iOS/TUIKit/TUIConversation/UI_Minimalist/Cell/CellUI/TUIConversationForwardSelectCell_Minimalist.m @@ -39,15 +39,47 @@ self.titleLabel.autoresizingMask = UIViewAutoresizingFlexibleTopMargin | UIViewAutoresizingFlexibleBottomMargin; - self.avatarView.mm_width(kScale390(40)).mm_height(kScale390(40)).mm__centerY(self.mm_centerY).mm_left(kScale390(16)); - self.selectButton.mm_sizeToFit().mm__centerY(self.mm_centerY).mm_right(kScale390(kScale390(42))); - self.titleLabel.mm_left(self.avatarView.mm_maxX + 12).mm_height(20).mm__centerY(self.avatarView.mm_centerY).mm_flexToRight(0); - self.selectionStyle = UITableViewCellSelectionStyleNone; } return self; } ++ (BOOL)requiresConstraintBasedLayout { + return YES; +} + +// this is Apple's recommended place for adding/updating constraints +- (void)updateConstraints { + + [super updateConstraints]; + CGFloat imgWidth = kScale390(40); + [self.avatarView mas_remakeConstraints:^(MASConstraintMaker *make) { + make.width.height.mas_equalTo(imgWidth); + make.centerY.mas_equalTo(self.contentView.mas_centerY); + make.leading.mas_equalTo(kScale390(16)); + }]; + if ([TUIConfig defaultConfig].avatarType == TAvatarTypeRounded) { + self.avatarView.layer.masksToBounds = YES; + self.avatarView.layer.cornerRadius = imgWidth / 2; + } else if ([TUIConfig defaultConfig].avatarType == TAvatarTypeRadiusCorner) { + self.avatarView.layer.masksToBounds = YES; + self.avatarView.layer.cornerRadius = [TUIConfig defaultConfig].avatarCornerRadius; + } + + [self.selectButton sizeToFit]; + [self.selectButton mas_remakeConstraints:^(MASConstraintMaker *make) { + make.centerY.mas_equalTo(self.contentView.mas_centerY); + make.trailing.mas_equalTo(self.contentView.mas_trailing).mas_offset(-kScale390(42)); + make.size.mas_equalTo(self.selectButton.frame.size); + }]; + [self.titleLabel mas_remakeConstraints:^(MASConstraintMaker *make) { + make.centerY.mas_equalTo(self.avatarView.mas_centerY); + make.leading.mas_equalTo(self.avatarView.mas_trailing).mas_offset(12); + make.height.mas_equalTo(20); + make.trailing.mas_greaterThanOrEqualTo(self.contentView.mas_trailing); + + }]; +} - (void)layoutSubviews { [super layoutSubviews]; } @@ -55,13 +87,6 @@ - (void)fillWithData:(TUIConversationCellData *)selectData { self.selectData = selectData; self.titleLabel.text = selectData.title; - if ([TUIConfig defaultConfig].avatarType == TAvatarTypeRounded) { - self.avatarView.layer.masksToBounds = YES; - self.avatarView.layer.cornerRadius = self.avatarView.frame.size.height / 2; - } else if ([TUIConfig defaultConfig].avatarType == TAvatarTypeRadiusCorner) { - self.avatarView.layer.masksToBounds = YES; - self.avatarView.layer.cornerRadius = [TUIConfig defaultConfig].avatarCornerRadius; - } [self configHeadImageView:selectData]; [self.selectButton setSelected:selectData.selected]; if (selectData.showCheckBox) { @@ -69,7 +94,14 @@ } else { self.selectButton.hidden = YES; } - // self.selectButton.enabled = selectData.enabled; + + // tell constraints they need updating + [self setNeedsUpdateConstraints]; + + // update constraints now so we can animate the change + [self updateConstraintsIfNeeded]; + + [self layoutIfNeeded]; } - (void)configHeadImageView:(TUIConversationCellData *)convData { diff --git a/iOS/TUIKit/TUIConversation/UI_Minimalist/DataProvider/TUIConversationListDataProvider_Minimalist.m b/iOS/TUIKit/TUIConversation/UI_Minimalist/DataProvider/TUIConversationListDataProvider_Minimalist.m index 0cc4638fa..43aaa4236 100644 --- a/iOS/TUIKit/TUIConversation/UI_Minimalist/DataProvider/TUIConversationListDataProvider_Minimalist.m +++ b/iOS/TUIKit/TUIConversation/UI_Minimalist/DataProvider/TUIConversationListDataProvider_Minimalist.m @@ -10,6 +10,7 @@ #import #import #import "TUIConversationCellData_Minimalist.h" +#import @implementation TUIConversationListDataProvider_Minimalist - (Class)getConversationCellClass { @@ -40,7 +41,9 @@ attributes:@{NSForegroundColorAttributeName : RGB(250, 81, 81)}]; [attributeString appendAttributedString:draft]; - NSAttributedString *draftContent = [[NSAttributedString alloc] initWithString:[self getDraftContent:conv] + NSString *draftContentStr = [self getDraftContent:conv]; + draftContentStr = [draftContentStr getLocalizableStringWithFaceContent]; + NSAttributedString *draftContent = [[NSAttributedString alloc] initWithString:draftContentStr attributes:@{NSForegroundColorAttributeName : [UIColor d_systemGrayColor]}]; [attributeString appendAttributedString:draftContent]; } else { diff --git a/iOS/TUIKit/TUIConversation/UI_Minimalist/DataProvider/TUIFoldConversationListDataProvider_Minimalist.m b/iOS/TUIKit/TUIConversation/UI_Minimalist/DataProvider/TUIFoldConversationListDataProvider_Minimalist.m index 1e41bff38..2591a374f 100644 --- a/iOS/TUIKit/TUIConversation/UI_Minimalist/DataProvider/TUIFoldConversationListDataProvider_Minimalist.m +++ b/iOS/TUIKit/TUIConversation/UI_Minimalist/DataProvider/TUIFoldConversationListDataProvider_Minimalist.m @@ -10,6 +10,7 @@ #import #import #import "TUIConversationCellData_Minimalist.h" +#import @implementation TUIFoldConversationListDataProvider_Minimalist @@ -40,7 +41,9 @@ attributes:@{NSForegroundColorAttributeName : RGB(250, 81, 81)}]; [attributeString appendAttributedString:draft]; - NSAttributedString *draftContent = [[NSAttributedString alloc] initWithString:[self getDraftContent:conv] + NSString *draftContentStr = [self getDraftContent:conv]; + draftContentStr = [draftContentStr getLocalizableStringWithFaceContent]; + NSAttributedString *draftContent = [[NSAttributedString alloc] initWithString:draftContentStr attributes:@{NSForegroundColorAttributeName : [UIColor d_systemGrayColor]}]; [attributeString appendAttributedString:draftContent]; } else { diff --git a/iOS/TUIKit/TUIConversation/UI_Minimalist/UI/TUIConversationListController_Minimalist.m b/iOS/TUIKit/TUIConversation/UI_Minimalist/UI/TUIConversationListController_Minimalist.m index a6104ad78..3a3d38f2f 100644 --- a/iOS/TUIKit/TUIConversation/UI_Minimalist/UI/TUIConversationListController_Minimalist.m +++ b/iOS/TUIKit/TUIConversation/UI_Minimalist/UI/TUIConversationListController_Minimalist.m @@ -195,7 +195,11 @@ static NSString *kConversationCell_Minimalist_ReuseId = @"kConversationCell_Mini CGFloat height = [TUIPopCell getHeight] * menus.count + TUIPopView_Arrow_Size.height; CGFloat orginY = StatusBar_Height + NavBar_Height; - TUIPopView *popView = [[TUIPopView alloc] initWithFrame:CGRectMake(Screen_Width - 155, orginY, 145, height)]; + CGFloat orginX = Screen_Width - 155; + if(isRTL()){ + orginX = 10; + } + TUIPopView *popView = [[TUIPopView alloc] initWithFrame:CGRectMake(orginX, orginY, 145, height)]; CGRect frameInNaviView = [self.navigationController.view convertRect:rightBarButton.frame fromView:rightBarButton.superview]; popView.arrowPoint = CGPointMake(frameInNaviView.origin.x + frameInNaviView.size.width * 0.5, orginY); popView.delegate = self; @@ -625,6 +629,9 @@ static NSString *kConversationCell_Minimalist_ReuseId = @"kConversationCell_Mini if ([language containsString:@"zh-"]) { markAsReadImageName = [markAsReadImageName stringByAppendingString:@"_zh"]; } + else if ([language containsString:@"ar"]) { + markAsReadImageName = [markAsReadImageName stringByAppendingString:@"_ar"]; + } markAsReadAction.image = TUIDynamicImage(@"", TUIThemeModuleConversation_Minimalist, [UIImage imageNamed:TUIConversationImagePath_Minimalist(markAsReadImageName)]); @@ -651,7 +658,13 @@ static NSString *kConversationCell_Minimalist_ReuseId = @"kConversationCell_Mini [weakSelf showMoreAction:cellData]; }]; moreAction.backgroundColor = RGB(0, 0, 0); - NSString *moreImageName = [language containsString:@"zh-"] ? @"icon_conversation_swipe_more_zh" : @"icon_conversation_swipe_more"; + NSString *moreImageName = @"icon_conversation_swipe_more"; + if ([language containsString:@"zh-"]) { + moreImageName = [moreImageName stringByAppendingString:@"_zh"]; + } + else if ([language containsString:@"ar"]) { + moreImageName = [moreImageName stringByAppendingString:@"_ar"]; + } moreAction.image = TUIDynamicImage(@"", TUIThemeModuleConversation_Minimalist, [UIImage imageNamed:TUIConversationImagePath_Minimalist(moreImageName)]); // config Actions diff --git a/iOS/TUIKit/TUIConversation/UI_Minimalist/UI/TUIConversationSelectController_Minimalist.m b/iOS/TUIKit/TUIConversation/UI_Minimalist/UI/TUIConversationSelectController_Minimalist.m index 2a51f83f4..a521fd49f 100644 --- a/iOS/TUIKit/TUIConversation/UI_Minimalist/UI/TUIConversationSelectController_Minimalist.m +++ b/iOS/TUIKit/TUIConversation/UI_Minimalist/UI/TUIConversationSelectController_Minimalist.m @@ -62,7 +62,7 @@ typedef void (^TUIConversationSelectCompletHandler)(BOOL); self.line = [[UIView alloc] init]; self.line.backgroundColor = [UIColor tui_colorWithHex:@"#000000" alpha:0.1]; [self addSubview:self.line]; - UICollectionViewFlowLayout *layout = [[UICollectionViewFlowLayout alloc] init]; + UICollectionViewFlowLayout *layout = [[TUICollectionRTLFitFlowLayout alloc] init]; layout.scrollDirection = UICollectionViewScrollDirectionHorizontal; layout.minimumLineSpacing = 0; layout.minimumInteritemSpacing = 0; diff --git a/iOS/TUIKit/TUICore/Resources/TUICore.bundle/default_c2c_head@2x.png b/iOS/TUIKit/TUICore/Resources/TUICore.bundle/default_c2c_head@2x.png index aca00ca22..09188487e 100644 Binary files a/iOS/TUIKit/TUICore/Resources/TUICore.bundle/default_c2c_head@2x.png and b/iOS/TUIKit/TUICore/Resources/TUICore.bundle/default_c2c_head@2x.png differ diff --git a/iOS/TUIKit/TUICore/Resources/TUICore.bundle/default_fold_group@2x.png b/iOS/TUIKit/TUICore/Resources/TUICore.bundle/default_fold_group@2x.png index 1e3c90570..0cce45aae 100644 Binary files a/iOS/TUIKit/TUICore/Resources/TUICore.bundle/default_fold_group@2x.png and b/iOS/TUIKit/TUICore/Resources/TUICore.bundle/default_fold_group@2x.png differ diff --git a/iOS/TUIKit/TUICore/Resources/TUICore.bundle/default_group_head@2x.png b/iOS/TUIKit/TUICore/Resources/TUICore.bundle/default_group_head@2x.png index 30d1732fb..1a9dbda07 100644 Binary files a/iOS/TUIKit/TUICore/Resources/TUICore.bundle/default_group_head@2x.png and b/iOS/TUIKit/TUICore/Resources/TUICore.bundle/default_group_head@2x.png differ diff --git a/iOS/TUIKit/TUICore/Resources/TUICore.bundle/default_group_head_avchatroom@2x.png b/iOS/TUIKit/TUICore/Resources/TUICore.bundle/default_group_head_avchatroom@2x.png index 015ce7aaf..e821e64bb 100644 Binary files a/iOS/TUIKit/TUICore/Resources/TUICore.bundle/default_group_head_avchatroom@2x.png and b/iOS/TUIKit/TUICore/Resources/TUICore.bundle/default_group_head_avchatroom@2x.png differ diff --git a/iOS/TUIKit/TUICore/Resources/TUICore.bundle/default_group_head_community@2x.png b/iOS/TUIKit/TUICore/Resources/TUICore.bundle/default_group_head_community@2x.png index ca5814336..92aceceeb 100644 Binary files a/iOS/TUIKit/TUICore/Resources/TUICore.bundle/default_group_head_community@2x.png and b/iOS/TUIKit/TUICore/Resources/TUICore.bundle/default_group_head_community@2x.png differ diff --git a/iOS/TUIKit/TUICore/Resources/TUICore.bundle/default_group_head_meeting@2x.png b/iOS/TUIKit/TUICore/Resources/TUICore.bundle/default_group_head_meeting@2x.png index e363ed6ef..dffcd1413 100644 Binary files a/iOS/TUIKit/TUICore/Resources/TUICore.bundle/default_group_head_meeting@2x.png and b/iOS/TUIKit/TUICore/Resources/TUICore.bundle/default_group_head_meeting@2x.png differ diff --git a/iOS/TUIKit/TUICore/Resources/TUICore.bundle/default_group_head_public@2x.png b/iOS/TUIKit/TUICore/Resources/TUICore.bundle/default_group_head_public@2x.png index 5484cddcb..2a275ca75 100644 Binary files a/iOS/TUIKit/TUICore/Resources/TUICore.bundle/default_group_head_public@2x.png and b/iOS/TUIKit/TUICore/Resources/TUICore.bundle/default_group_head_public@2x.png differ diff --git a/iOS/TUIKit/TUICore/Resources/TUICore.bundle/more@2x.png b/iOS/TUIKit/TUICore/Resources/TUICore.bundle/more@2x.png index b2890f402..134a61308 100644 Binary files a/iOS/TUIKit/TUICore/Resources/TUICore.bundle/more@2x.png and b/iOS/TUIKit/TUICore/Resources/TUICore.bundle/more@2x.png differ diff --git a/iOS/TUIKit/TUICore/Resources/TUICore.bundle/more_group_note@2x.png b/iOS/TUIKit/TUICore/Resources/TUICore.bundle/more_group_note@2x.png index 6e09e1e02..a8774392a 100644 Binary files a/iOS/TUIKit/TUICore/Resources/TUICore.bundle/more_group_note@2x.png and b/iOS/TUIKit/TUICore/Resources/TUICore.bundle/more_group_note@2x.png differ diff --git a/iOS/TUIKit/TUICore/Resources/TUICore.bundle/more_group_note@3x.png b/iOS/TUIKit/TUICore/Resources/TUICore.bundle/more_group_note@3x.png index acc41a783..8fb611a9e 100644 Binary files a/iOS/TUIKit/TUICore/Resources/TUICore.bundle/more_group_note@3x.png and b/iOS/TUIKit/TUICore/Resources/TUICore.bundle/more_group_note@3x.png differ diff --git a/iOS/TUIKit/TUICore/Resources/TUICore.bundle/more_poll@2x.png b/iOS/TUIKit/TUICore/Resources/TUICore.bundle/more_poll@2x.png index c90a74d45..cbe92506a 100644 Binary files a/iOS/TUIKit/TUICore/Resources/TUICore.bundle/more_poll@2x.png and b/iOS/TUIKit/TUICore/Resources/TUICore.bundle/more_poll@2x.png differ diff --git a/iOS/TUIKit/TUICore/Resources/TUICore.bundle/more_poll@3x.png b/iOS/TUIKit/TUICore/Resources/TUICore.bundle/more_poll@3x.png index be52e9a1b..addad7591 100644 Binary files a/iOS/TUIKit/TUICore/Resources/TUICore.bundle/more_poll@3x.png and b/iOS/TUIKit/TUICore/Resources/TUICore.bundle/more_poll@3x.png differ diff --git a/iOS/TUIKit/TUICore/Resources/TUICore.bundle/more_video_call@2x.png b/iOS/TUIKit/TUICore/Resources/TUICore.bundle/more_video_call@2x.png index f153cd288..6665734da 100644 Binary files a/iOS/TUIKit/TUICore/Resources/TUICore.bundle/more_video_call@2x.png and b/iOS/TUIKit/TUICore/Resources/TUICore.bundle/more_video_call@2x.png differ diff --git a/iOS/TUIKit/TUICore/Resources/TUICore.bundle/more_video_call@3x.png b/iOS/TUIKit/TUICore/Resources/TUICore.bundle/more_video_call@3x.png index 4d41ed8b2..f9714116a 100644 Binary files a/iOS/TUIKit/TUICore/Resources/TUICore.bundle/more_video_call@3x.png and b/iOS/TUIKit/TUICore/Resources/TUICore.bundle/more_video_call@3x.png differ diff --git a/iOS/TUIKit/TUICore/Resources/TUICore.bundle/more_voice_call@2x.png b/iOS/TUIKit/TUICore/Resources/TUICore.bundle/more_voice_call@2x.png index 0c9e81498..d847912eb 100644 Binary files a/iOS/TUIKit/TUICore/Resources/TUICore.bundle/more_voice_call@2x.png and b/iOS/TUIKit/TUICore/Resources/TUICore.bundle/more_voice_call@2x.png differ diff --git a/iOS/TUIKit/TUICore/Resources/TUICore.bundle/more_voice_call@3x.png b/iOS/TUIKit/TUICore/Resources/TUICore.bundle/more_voice_call@3x.png index 4c0455089..f333fe9ed 100644 Binary files a/iOS/TUIKit/TUICore/Resources/TUICore.bundle/more_voice_call@3x.png and b/iOS/TUIKit/TUICore/Resources/TUICore.bundle/more_voice_call@3x.png differ diff --git a/iOS/TUIKit/TUICore/Resources/TUICore.bundle/nav_back@3x.png b/iOS/TUIKit/TUICore/Resources/TUICore.bundle/nav_back@3x.png new file mode 100644 index 000000000..26bf81ead Binary files /dev/null and b/iOS/TUIKit/TUICore/Resources/TUICore.bundle/nav_back@3x.png differ diff --git a/iOS/TUIKit/TUICore/Resources/TUICoreTheme.bundle/dark/manifest.plist b/iOS/TUIKit/TUICore/Resources/TUICoreTheme.bundle/dark/manifest.plist index 748052f6c..951217548 100644 --- a/iOS/TUIKit/TUICore/Resources/TUICoreTheme.bundle/dark/manifest.plist +++ b/iOS/TUIKit/TUICore/Resources/TUICoreTheme.bundle/dark/manifest.plist @@ -36,5 +36,7 @@ service_more_video_call.png service_more_voice_call_img service_more_voice_call.png + nav_back_img + nav_back.png diff --git a/iOS/TUIKit/TUICore/Resources/TUICoreTheme.bundle/dark/resource/bg.png b/iOS/TUIKit/TUICore/Resources/TUICoreTheme.bundle/dark/resource/bg.png index 7077009d5..a4d07d07a 100644 Binary files a/iOS/TUIKit/TUICore/Resources/TUICoreTheme.bundle/dark/resource/bg.png and b/iOS/TUIKit/TUICore/Resources/TUICoreTheme.bundle/dark/resource/bg.png differ diff --git a/iOS/TUIKit/TUICore/Resources/TUICoreTheme.bundle/dark/resource/default_group_head@2x.png b/iOS/TUIKit/TUICore/Resources/TUICoreTheme.bundle/dark/resource/default_group_head@2x.png index 3af28307b..dfadf82bd 100644 Binary files a/iOS/TUIKit/TUICore/Resources/TUICoreTheme.bundle/dark/resource/default_group_head@2x.png and b/iOS/TUIKit/TUICore/Resources/TUICoreTheme.bundle/dark/resource/default_group_head@2x.png differ diff --git a/iOS/TUIKit/TUICore/Resources/TUICoreTheme.bundle/dark/resource/default_group_head_avchatroom@2x.png b/iOS/TUIKit/TUICore/Resources/TUICoreTheme.bundle/dark/resource/default_group_head_avchatroom@2x.png index 89c9f977e..b2f614ac6 100644 Binary files a/iOS/TUIKit/TUICore/Resources/TUICoreTheme.bundle/dark/resource/default_group_head_avchatroom@2x.png and b/iOS/TUIKit/TUICore/Resources/TUICoreTheme.bundle/dark/resource/default_group_head_avchatroom@2x.png differ diff --git a/iOS/TUIKit/TUICore/Resources/TUICoreTheme.bundle/dark/resource/default_group_head_community@2x.png b/iOS/TUIKit/TUICore/Resources/TUICoreTheme.bundle/dark/resource/default_group_head_community@2x.png index dc0277ffe..7f3c9bfd5 100644 Binary files a/iOS/TUIKit/TUICore/Resources/TUICoreTheme.bundle/dark/resource/default_group_head_community@2x.png and b/iOS/TUIKit/TUICore/Resources/TUICoreTheme.bundle/dark/resource/default_group_head_community@2x.png differ diff --git a/iOS/TUIKit/TUICore/Resources/TUICoreTheme.bundle/dark/resource/default_group_head_meeting@2x.png b/iOS/TUIKit/TUICore/Resources/TUICoreTheme.bundle/dark/resource/default_group_head_meeting@2x.png index 79c65c94b..b7b14c61a 100644 Binary files a/iOS/TUIKit/TUICore/Resources/TUICoreTheme.bundle/dark/resource/default_group_head_meeting@2x.png and b/iOS/TUIKit/TUICore/Resources/TUICoreTheme.bundle/dark/resource/default_group_head_meeting@2x.png differ diff --git a/iOS/TUIKit/TUICore/Resources/TUICoreTheme.bundle/dark/resource/default_group_head_public@2x.png b/iOS/TUIKit/TUICore/Resources/TUICoreTheme.bundle/dark/resource/default_group_head_public@2x.png index 631ad4923..309f128e9 100644 Binary files a/iOS/TUIKit/TUICore/Resources/TUICoreTheme.bundle/dark/resource/default_group_head_public@2x.png and b/iOS/TUIKit/TUICore/Resources/TUICoreTheme.bundle/dark/resource/default_group_head_public@2x.png differ diff --git a/iOS/TUIKit/TUICore/Resources/TUICoreTheme.bundle/dark/resource/nav_back@3x.png b/iOS/TUIKit/TUICore/Resources/TUICoreTheme.bundle/dark/resource/nav_back@3x.png index 20726344a..c1a03ce61 100644 Binary files a/iOS/TUIKit/TUICore/Resources/TUICoreTheme.bundle/dark/resource/nav_back@3x.png and b/iOS/TUIKit/TUICore/Resources/TUICoreTheme.bundle/dark/resource/nav_back@3x.png differ diff --git a/iOS/TUIKit/TUICore/Resources/TUICoreTheme.bundle/dark/resource/nav_more@3x.png b/iOS/TUIKit/TUICore/Resources/TUICoreTheme.bundle/dark/resource/nav_more@3x.png index 62557b2dc..42efcc5db 100644 Binary files a/iOS/TUIKit/TUICore/Resources/TUICoreTheme.bundle/dark/resource/nav_more@3x.png and b/iOS/TUIKit/TUICore/Resources/TUICoreTheme.bundle/dark/resource/nav_more@3x.png differ diff --git a/iOS/TUIKit/TUICore/Resources/TUICoreTheme.bundle/dark/resource/service_more_video_call@3x.png b/iOS/TUIKit/TUICore/Resources/TUICoreTheme.bundle/dark/resource/service_more_video_call@3x.png index 7e8124d3b..757c99e27 100644 Binary files a/iOS/TUIKit/TUICore/Resources/TUICoreTheme.bundle/dark/resource/service_more_video_call@3x.png and b/iOS/TUIKit/TUICore/Resources/TUICoreTheme.bundle/dark/resource/service_more_video_call@3x.png differ diff --git a/iOS/TUIKit/TUICore/Resources/TUICoreTheme.bundle/dark/resource/service_more_voice_call@3x.png b/iOS/TUIKit/TUICore/Resources/TUICoreTheme.bundle/dark/resource/service_more_voice_call@3x.png index 2277b5e78..10aed5f8e 100644 Binary files a/iOS/TUIKit/TUICore/Resources/TUICoreTheme.bundle/dark/resource/service_more_voice_call@3x.png and b/iOS/TUIKit/TUICore/Resources/TUICoreTheme.bundle/dark/resource/service_more_voice_call@3x.png differ diff --git a/iOS/TUIKit/TUICore/Resources/TUICoreTheme.bundle/light/manifest.plist b/iOS/TUIKit/TUICore/Resources/TUICoreTheme.bundle/light/manifest.plist index 4dabfe8df..5298454cd 100644 --- a/iOS/TUIKit/TUICore/Resources/TUICoreTheme.bundle/light/manifest.plist +++ b/iOS/TUIKit/TUICore/Resources/TUICoreTheme.bundle/light/manifest.plist @@ -38,5 +38,7 @@ service_more_video_call.png service_more_voice_call_img service_more_voice_call.png + nav_back_img + nav_back.png diff --git a/iOS/TUIKit/TUICore/Resources/TUICoreTheme.bundle/light/resource/bg.png b/iOS/TUIKit/TUICore/Resources/TUICoreTheme.bundle/light/resource/bg.png index 87d7c51a0..292267063 100644 Binary files a/iOS/TUIKit/TUICore/Resources/TUICoreTheme.bundle/light/resource/bg.png and b/iOS/TUIKit/TUICore/Resources/TUICoreTheme.bundle/light/resource/bg.png differ diff --git a/iOS/TUIKit/TUICore/Resources/TUICoreTheme.bundle/light/resource/default_group_head@2x.png b/iOS/TUIKit/TUICore/Resources/TUICoreTheme.bundle/light/resource/default_group_head@2x.png index 314f5c98b..d31242fc9 100644 Binary files a/iOS/TUIKit/TUICore/Resources/TUICoreTheme.bundle/light/resource/default_group_head@2x.png and b/iOS/TUIKit/TUICore/Resources/TUICoreTheme.bundle/light/resource/default_group_head@2x.png differ diff --git a/iOS/TUIKit/TUICore/Resources/TUICoreTheme.bundle/light/resource/default_group_head_avchatroom@2x.png b/iOS/TUIKit/TUICore/Resources/TUICoreTheme.bundle/light/resource/default_group_head_avchatroom@2x.png index 015ce7aaf..e821e64bb 100644 Binary files a/iOS/TUIKit/TUICore/Resources/TUICoreTheme.bundle/light/resource/default_group_head_avchatroom@2x.png and b/iOS/TUIKit/TUICore/Resources/TUICoreTheme.bundle/light/resource/default_group_head_avchatroom@2x.png differ diff --git a/iOS/TUIKit/TUICore/Resources/TUICoreTheme.bundle/light/resource/default_group_head_community@2x.png b/iOS/TUIKit/TUICore/Resources/TUICoreTheme.bundle/light/resource/default_group_head_community@2x.png index ca5814336..92aceceeb 100644 Binary files a/iOS/TUIKit/TUICore/Resources/TUICoreTheme.bundle/light/resource/default_group_head_community@2x.png and b/iOS/TUIKit/TUICore/Resources/TUICoreTheme.bundle/light/resource/default_group_head_community@2x.png differ diff --git a/iOS/TUIKit/TUICore/Resources/TUICoreTheme.bundle/light/resource/default_group_head_meeting@2x.png b/iOS/TUIKit/TUICore/Resources/TUICoreTheme.bundle/light/resource/default_group_head_meeting@2x.png index e363ed6ef..dffcd1413 100644 Binary files a/iOS/TUIKit/TUICore/Resources/TUICoreTheme.bundle/light/resource/default_group_head_meeting@2x.png and b/iOS/TUIKit/TUICore/Resources/TUICoreTheme.bundle/light/resource/default_group_head_meeting@2x.png differ diff --git a/iOS/TUIKit/TUICore/Resources/TUICoreTheme.bundle/light/resource/default_group_head_public@2x.png b/iOS/TUIKit/TUICore/Resources/TUICoreTheme.bundle/light/resource/default_group_head_public@2x.png index 5484cddcb..2a275ca75 100644 Binary files a/iOS/TUIKit/TUICore/Resources/TUICoreTheme.bundle/light/resource/default_group_head_public@2x.png and b/iOS/TUIKit/TUICore/Resources/TUICoreTheme.bundle/light/resource/default_group_head_public@2x.png differ diff --git a/iOS/TUIKit/TUICore/Resources/TUICoreTheme.bundle/light/resource/nav_back@3x.png b/iOS/TUIKit/TUICore/Resources/TUICoreTheme.bundle/light/resource/nav_back@3x.png index 3d8c99915..90f344af7 100644 Binary files a/iOS/TUIKit/TUICore/Resources/TUICoreTheme.bundle/light/resource/nav_back@3x.png and b/iOS/TUIKit/TUICore/Resources/TUICoreTheme.bundle/light/resource/nav_back@3x.png differ diff --git a/iOS/TUIKit/TUICore/Resources/TUICoreTheme.bundle/light/resource/nav_more@2x.png b/iOS/TUIKit/TUICore/Resources/TUICoreTheme.bundle/light/resource/nav_more@2x.png index b2890f402..134a61308 100644 Binary files a/iOS/TUIKit/TUICore/Resources/TUICoreTheme.bundle/light/resource/nav_more@2x.png and b/iOS/TUIKit/TUICore/Resources/TUICoreTheme.bundle/light/resource/nav_more@2x.png differ diff --git a/iOS/TUIKit/TUICore/Resources/TUICoreTheme.bundle/light/resource/service_more_video_call@3x.png b/iOS/TUIKit/TUICore/Resources/TUICoreTheme.bundle/light/resource/service_more_video_call@3x.png index cc3776137..7d89281fb 100644 Binary files a/iOS/TUIKit/TUICore/Resources/TUICoreTheme.bundle/light/resource/service_more_video_call@3x.png and b/iOS/TUIKit/TUICore/Resources/TUICoreTheme.bundle/light/resource/service_more_video_call@3x.png differ diff --git a/iOS/TUIKit/TUICore/Resources/TUICoreTheme.bundle/light/resource/service_more_voice_call@3x.png b/iOS/TUIKit/TUICore/Resources/TUICoreTheme.bundle/light/resource/service_more_voice_call@3x.png index 4c0455089..f333fe9ed 100644 Binary files a/iOS/TUIKit/TUICore/Resources/TUICoreTheme.bundle/light/resource/service_more_voice_call@3x.png and b/iOS/TUIKit/TUICore/Resources/TUICoreTheme.bundle/light/resource/service_more_voice_call@3x.png differ diff --git a/iOS/TUIKit/TUICore/Resources/TUICoreTheme.bundle/lively/manifest.plist b/iOS/TUIKit/TUICore/Resources/TUICoreTheme.bundle/lively/manifest.plist index d667812fb..db0141c57 100644 --- a/iOS/TUIKit/TUICore/Resources/TUICoreTheme.bundle/lively/manifest.plist +++ b/iOS/TUIKit/TUICore/Resources/TUICoreTheme.bundle/lively/manifest.plist @@ -38,5 +38,7 @@ service_more_video_call.png service_more_voice_call_img service_more_voice_call.png + nav_back_img + nav_back.png diff --git a/iOS/TUIKit/TUICore/Resources/TUICoreTheme.bundle/lively/resource/bg.png b/iOS/TUIKit/TUICore/Resources/TUICoreTheme.bundle/lively/resource/bg.png index 62c1d746f..acfbbf52c 100644 Binary files a/iOS/TUIKit/TUICore/Resources/TUICoreTheme.bundle/lively/resource/bg.png and b/iOS/TUIKit/TUICore/Resources/TUICoreTheme.bundle/lively/resource/bg.png differ diff --git a/iOS/TUIKit/TUICore/Resources/TUICoreTheme.bundle/lively/resource/default_group_head@2x.png b/iOS/TUIKit/TUICore/Resources/TUICoreTheme.bundle/lively/resource/default_group_head@2x.png index d94772e46..97f17ecb7 100644 Binary files a/iOS/TUIKit/TUICore/Resources/TUICoreTheme.bundle/lively/resource/default_group_head@2x.png and b/iOS/TUIKit/TUICore/Resources/TUICoreTheme.bundle/lively/resource/default_group_head@2x.png differ diff --git a/iOS/TUIKit/TUICore/Resources/TUICoreTheme.bundle/lively/resource/default_group_head_avchatroom@2x.png b/iOS/TUIKit/TUICore/Resources/TUICoreTheme.bundle/lively/resource/default_group_head_avchatroom@2x.png index 21b0cafab..2f7fd80d8 100644 Binary files a/iOS/TUIKit/TUICore/Resources/TUICoreTheme.bundle/lively/resource/default_group_head_avchatroom@2x.png and b/iOS/TUIKit/TUICore/Resources/TUICoreTheme.bundle/lively/resource/default_group_head_avchatroom@2x.png differ diff --git a/iOS/TUIKit/TUICore/Resources/TUICoreTheme.bundle/lively/resource/default_group_head_community@2x.png b/iOS/TUIKit/TUICore/Resources/TUICoreTheme.bundle/lively/resource/default_group_head_community@2x.png index d7dc620ff..f332607ec 100644 Binary files a/iOS/TUIKit/TUICore/Resources/TUICoreTheme.bundle/lively/resource/default_group_head_community@2x.png and b/iOS/TUIKit/TUICore/Resources/TUICoreTheme.bundle/lively/resource/default_group_head_community@2x.png differ diff --git a/iOS/TUIKit/TUICore/Resources/TUICoreTheme.bundle/lively/resource/default_group_head_meeting@2x.png b/iOS/TUIKit/TUICore/Resources/TUICoreTheme.bundle/lively/resource/default_group_head_meeting@2x.png index 85630caa7..0e1f87924 100644 Binary files a/iOS/TUIKit/TUICore/Resources/TUICoreTheme.bundle/lively/resource/default_group_head_meeting@2x.png and b/iOS/TUIKit/TUICore/Resources/TUICoreTheme.bundle/lively/resource/default_group_head_meeting@2x.png differ diff --git a/iOS/TUIKit/TUICore/Resources/TUICoreTheme.bundle/lively/resource/default_group_head_public@2x.png b/iOS/TUIKit/TUICore/Resources/TUICoreTheme.bundle/lively/resource/default_group_head_public@2x.png index f53088b7f..193bb68d8 100644 Binary files a/iOS/TUIKit/TUICore/Resources/TUICoreTheme.bundle/lively/resource/default_group_head_public@2x.png and b/iOS/TUIKit/TUICore/Resources/TUICoreTheme.bundle/lively/resource/default_group_head_public@2x.png differ diff --git a/iOS/TUIKit/TUICore/Resources/TUICoreTheme.bundle/lively/resource/nav_back@3x.png b/iOS/TUIKit/TUICore/Resources/TUICoreTheme.bundle/lively/resource/nav_back@3x.png index 20726344a..630dee187 100644 Binary files a/iOS/TUIKit/TUICore/Resources/TUICoreTheme.bundle/lively/resource/nav_back@3x.png and b/iOS/TUIKit/TUICore/Resources/TUICoreTheme.bundle/lively/resource/nav_back@3x.png differ diff --git a/iOS/TUIKit/TUICore/Resources/TUICoreTheme.bundle/lively/resource/nav_more@3x.png b/iOS/TUIKit/TUICore/Resources/TUICoreTheme.bundle/lively/resource/nav_more@3x.png index e44975b2c..b69d31e2f 100644 Binary files a/iOS/TUIKit/TUICore/Resources/TUICoreTheme.bundle/lively/resource/nav_more@3x.png and b/iOS/TUIKit/TUICore/Resources/TUICoreTheme.bundle/lively/resource/nav_more@3x.png differ diff --git a/iOS/TUIKit/TUICore/Resources/TUICoreTheme.bundle/lively/resource/service_more_video_call@3x.png b/iOS/TUIKit/TUICore/Resources/TUICoreTheme.bundle/lively/resource/service_more_video_call@3x.png index cc3776137..7d89281fb 100644 Binary files a/iOS/TUIKit/TUICore/Resources/TUICoreTheme.bundle/lively/resource/service_more_video_call@3x.png and b/iOS/TUIKit/TUICore/Resources/TUICoreTheme.bundle/lively/resource/service_more_video_call@3x.png differ diff --git a/iOS/TUIKit/TUICore/Resources/TUICoreTheme.bundle/lively/resource/service_more_voice_call@3x.png b/iOS/TUIKit/TUICore/Resources/TUICoreTheme.bundle/lively/resource/service_more_voice_call@3x.png index 4c0455089..f333fe9ed 100644 Binary files a/iOS/TUIKit/TUICore/Resources/TUICoreTheme.bundle/lively/resource/service_more_voice_call@3x.png and b/iOS/TUIKit/TUICore/Resources/TUICoreTheme.bundle/lively/resource/service_more_voice_call@3x.png differ diff --git a/iOS/TUIKit/TUICore/Resources/TUICoreTheme.bundle/serious/manifest.plist b/iOS/TUIKit/TUICore/Resources/TUICoreTheme.bundle/serious/manifest.plist index df285eda8..48a3ab56a 100644 --- a/iOS/TUIKit/TUICore/Resources/TUICoreTheme.bundle/serious/manifest.plist +++ b/iOS/TUIKit/TUICore/Resources/TUICoreTheme.bundle/serious/manifest.plist @@ -38,5 +38,7 @@ service_more_video_call.png service_more_voice_call_img service_more_voice_call.png + nav_back_img + nav_back.png diff --git a/iOS/TUIKit/TUICore/Resources/TUICoreTheme.bundle/serious/resource/bg.png b/iOS/TUIKit/TUICore/Resources/TUICoreTheme.bundle/serious/resource/bg.png index ccaf89e4a..0ad7159f3 100644 Binary files a/iOS/TUIKit/TUICore/Resources/TUICoreTheme.bundle/serious/resource/bg.png and b/iOS/TUIKit/TUICore/Resources/TUICoreTheme.bundle/serious/resource/bg.png differ diff --git a/iOS/TUIKit/TUICore/Resources/TUICoreTheme.bundle/serious/resource/default_group_head@2x.png b/iOS/TUIKit/TUICore/Resources/TUICoreTheme.bundle/serious/resource/default_group_head@2x.png index 64f95e26d..9178c8144 100644 Binary files a/iOS/TUIKit/TUICore/Resources/TUICoreTheme.bundle/serious/resource/default_group_head@2x.png and b/iOS/TUIKit/TUICore/Resources/TUICoreTheme.bundle/serious/resource/default_group_head@2x.png differ diff --git a/iOS/TUIKit/TUICore/Resources/TUICoreTheme.bundle/serious/resource/default_group_head_avchatroom@2x.png b/iOS/TUIKit/TUICore/Resources/TUICoreTheme.bundle/serious/resource/default_group_head_avchatroom@2x.png index a26280314..19d2cfcf8 100644 Binary files a/iOS/TUIKit/TUICore/Resources/TUICoreTheme.bundle/serious/resource/default_group_head_avchatroom@2x.png and b/iOS/TUIKit/TUICore/Resources/TUICoreTheme.bundle/serious/resource/default_group_head_avchatroom@2x.png differ diff --git a/iOS/TUIKit/TUICore/Resources/TUICoreTheme.bundle/serious/resource/default_group_head_community@2x.png b/iOS/TUIKit/TUICore/Resources/TUICoreTheme.bundle/serious/resource/default_group_head_community@2x.png index ca5814336..92aceceeb 100644 Binary files a/iOS/TUIKit/TUICore/Resources/TUICoreTheme.bundle/serious/resource/default_group_head_community@2x.png and b/iOS/TUIKit/TUICore/Resources/TUICoreTheme.bundle/serious/resource/default_group_head_community@2x.png differ diff --git a/iOS/TUIKit/TUICore/Resources/TUICoreTheme.bundle/serious/resource/default_group_head_meeting@2x.png b/iOS/TUIKit/TUICore/Resources/TUICoreTheme.bundle/serious/resource/default_group_head_meeting@2x.png index b4830e003..428541d3e 100644 Binary files a/iOS/TUIKit/TUICore/Resources/TUICoreTheme.bundle/serious/resource/default_group_head_meeting@2x.png and b/iOS/TUIKit/TUICore/Resources/TUICoreTheme.bundle/serious/resource/default_group_head_meeting@2x.png differ diff --git a/iOS/TUIKit/TUICore/Resources/TUICoreTheme.bundle/serious/resource/default_group_head_public@2x.png b/iOS/TUIKit/TUICore/Resources/TUICoreTheme.bundle/serious/resource/default_group_head_public@2x.png index 47e24ed90..dcd64e15c 100644 Binary files a/iOS/TUIKit/TUICore/Resources/TUICoreTheme.bundle/serious/resource/default_group_head_public@2x.png and b/iOS/TUIKit/TUICore/Resources/TUICoreTheme.bundle/serious/resource/default_group_head_public@2x.png differ diff --git a/iOS/TUIKit/TUICore/Resources/TUICoreTheme.bundle/serious/resource/nav_back@3x.png b/iOS/TUIKit/TUICore/Resources/TUICoreTheme.bundle/serious/resource/nav_back@3x.png index 20726344a..f0967a6e0 100644 Binary files a/iOS/TUIKit/TUICore/Resources/TUICoreTheme.bundle/serious/resource/nav_back@3x.png and b/iOS/TUIKit/TUICore/Resources/TUICoreTheme.bundle/serious/resource/nav_back@3x.png differ diff --git a/iOS/TUIKit/TUICore/Resources/TUICoreTheme.bundle/serious/resource/nav_more@3x.png b/iOS/TUIKit/TUICore/Resources/TUICoreTheme.bundle/serious/resource/nav_more@3x.png index e44975b2c..b69d31e2f 100644 Binary files a/iOS/TUIKit/TUICore/Resources/TUICoreTheme.bundle/serious/resource/nav_more@3x.png and b/iOS/TUIKit/TUICore/Resources/TUICoreTheme.bundle/serious/resource/nav_more@3x.png differ diff --git a/iOS/TUIKit/TUICore/Resources/TUICoreTheme.bundle/serious/resource/service_more_video_call@3x.png b/iOS/TUIKit/TUICore/Resources/TUICoreTheme.bundle/serious/resource/service_more_video_call@3x.png index cc3776137..7d89281fb 100644 Binary files a/iOS/TUIKit/TUICore/Resources/TUICoreTheme.bundle/serious/resource/service_more_video_call@3x.png and b/iOS/TUIKit/TUICore/Resources/TUICoreTheme.bundle/serious/resource/service_more_video_call@3x.png differ diff --git a/iOS/TUIKit/TUICore/Resources/TUICoreTheme.bundle/serious/resource/service_more_voice_call@3x.png b/iOS/TUIKit/TUICore/Resources/TUICoreTheme.bundle/serious/resource/service_more_voice_call@3x.png index 4c0455089..f333fe9ed 100644 Binary files a/iOS/TUIKit/TUICore/Resources/TUICoreTheme.bundle/serious/resource/service_more_voice_call@3x.png and b/iOS/TUIKit/TUICore/Resources/TUICoreTheme.bundle/serious/resource/service_more_voice_call@3x.png differ diff --git a/iOS/TUIKit/TUICore/Resources/TUIKitLocalizable.bundle/Localizable/ar.lproj/Localizable.strings b/iOS/TUIKit/TUICore/Resources/TUIKitLocalizable.bundle/Localizable/ar.lproj/Localizable.strings new file mode 100644 index 000000000..4252006e0 --- /dev/null +++ b/iOS/TUIKit/TUICore/Resources/TUIKitLocalizable.bundle/Localizable/ar.lproj/Localizable.strings @@ -0,0 +1,331 @@ +/* + Localizable.strings + Chinese Simplized + + Created by harvy on 2020/10/9. + +*/ + +/***************************** 日期格式化 Start *************************/ +"YesterdayDateFormat" = "aHH:mm"; +/***************************** 日期格式化 End *************************/ + +"TUIKitMoreVideoCall" = "مكالمة فيديو"; +"TUIKitMoreVoiceCall" = "مكالمة صوتية"; +"Make-a-call" = "إجراء مكالمة"; +"TUIKitNoSelfSignature" = "لا يوجد توقيع شخصي"; +"TUIKitSelfSignatureFormat" = "التوقيع الشخصي: %@"; +"TUIKitAllowTypeAcceptOne" = "السماح لأي مستخدم بإضافة صديق"; +"TUIKitAllowTypeNeedConfirm" = "يحتاج التحقق"; +"TUIKitAllowTypeDeclineAll" = "رفض أي شخص يريد إضافة صديق"; +"Male" = "ذكر"; +"Female" = "أنثى"; +"Unsetted" = "غير محدد"; + +"TUIKitErrorInProcess" = "جاري التنفيذ"; +"TUIKitErrorInvalidParameters" = "معلمات غير صالحة"; +"TUIKitErrorIOOperateFaild" = "فشل عملية الإدخال/الإخراج المحلية"; +"TUIKitErrorInvalidJson" = "تنسيق JSON غير صالح"; +"TUIKitErrorOutOfMemory" = "نفاد الذاكرة"; +"TUIKitErrorParseResponseFaild" = "فشل تحليل PB"; +"TUIKitErrorSerializeReqFaild" = "فشل تسلسل PB"; +"TUIKitErrorSDKNotInit" = "SDK IM غير مهيأ"; +"TUIKitErrorLoadMsgFailed" = "فشل تحميل عملية قاعدة البيانات المحلية"; +"TUIKitErrorDatabaseOperateFailed" = "فشل عملية قاعدة البيانات المحلية"; +"TUIKitErrorCrossThread" = "خطأ عبر الخيوط"; +"TUIKitErrorTinyIdEmpty" = "معلومات المستخدم فارغة"; +"TUIKitErrorInvalidIdentifier" = "معرف غير صالح"; +"TUIKitErrorFileNotFound" = "الملف غير موجود"; +"TUIKitErrorFileTooLarge" = "حجم الملف أكبر من الحد المسموح به"; +"TUIKitErrorEmptyFile" = "ملف فارغ"; +"TUIKitErrorFileOpenFailed" = "فشل فتح الملف"; +"TUIKitErrorNotLogin" = "لم يتم تسجيل الدخول إلى SDK IM"; +"TUIKitErrorNoPreviousLogin" = "لم يتم تسجيل الدخول بهذا المستخدم من قبل"; +"TUIKitErrorUserSigExpired" = "انتهت صلاحية UserSig"; +"TUIKitErrorLoginKickedOffByOther" = "تم تسجيل الدخول بواسطة جهاز آخر"; +"TUIKitErrorTLSSDKInit" = "فشل تهيئة SDK TLS"; +"TUIKitErrorTLSSDKUninit" = "SDK TLS غير مهيأ"; + +"TUIKitErrorTLSSDKTRANSPackageFormat" = "تنسيق حزمة TLS SDK TRANS غير صالح"; + + +"TUIKitErrorTLSDecrypt" = "فشل فك تشفير SDK TLS"; +"TUIKitErrorTLSSDKRequest" = "فشل طلب SDK TLS"; +"TUIKitErrorTLSSDKRequestTimeout" = "انتهت مهلة طلب SDK TLS"; +"TUIKitErrorInvalidConveration" = "المحادثة غير صالحة"; +"TUIKitErrorFileTransAuthFailed" = "فشل مصادقة نقل الملفات"; +"TUIKitErrorFileTransNoServer" = "فشل الحصول على قائمة الخوادم لنقل الملفات"; +"TUIKitErrorFileTransUploadFailed" = "فشل تحميل نقل الملفات، يرجى التحقق من اتصال الشبكة"; +"TUIKitErrorFileTransUploadFailedNotImage" = "فشل تحميل نقل الملفات، يرجى التحقق من قدرة فتح الصورة المراد تحميلها"; +"TUIKitErrorFileTransDownloadFailed" = "فشل تنزيل نقل الملفات، يرجى التحقق من الشبكة أو صلاحية الملف أو الصوت"; + +"TUIKitErrorHTTPRequestFailed" = "فشل طلب HTTP"; +"TUIKitErrorInvalidMsgElem" = "عنصر رسالة IM SDK غير صالح"; +"TUIKitErrorInvalidSDKObject" = "كائن غير صالح"; +"TUIKitSDKMsgBodySizeLimit" = "تجاوز حد طول الرسالة"; +"TUIKitErrorSDKMsgKeyReqDifferRsp" = "خطأ في مفتاح الرسالة"; +"TUIKitErrorSDKGroupInvalidID" = "معرف المجموعة غير صالح، يجب أن يكون معرف المجموعة المخصص قابلًا للطباعة ويتكون من أحرف ASCII (0x20-0x7e)، ويصل طوله إلى 48 بايتًا، ولا يمكن أن يبدأ بالبادئة @TGS#"; +"TUIKitErrorSDKGroupInvalidName" = "اسم المجموعة غير صالح، يصل طوله إلى 30 بايتًا"; +"TUIKitErrorSDKGroupInvalidIntroduction" = "مقدمة المجموعة غير صالحة، يصل طولها إلى 240 بايتًا"; +"TUIKitErrorSDKGroupInvalidNotification" = "إشعار المجموعة غير صالح، يصل طوله إلى 300 بايتًا"; +"TUIKitErrorSDKGroupInvalidFaceURL" ="عنوان URL للصورة الرمزية للمجموعة غير قانوني ، والحد الأقصى لطول عنوان URL للصورة الرمزية للمجموعة هو 100 بايت"; +"TUIKitErrorSDKGroupInvalidNameCard" = "بطاقة اسم المجموعة غير صالحة، يصل طولها إلى 50 بايتًا"; +"TUIKitErrorSDKGroupMemberCountLimit" = "تجاوز حد عدد أعضاء المجموعة"; + +"TUIKitErrorSDKGroupJoinPrivateGroupDeny" = "غير مسموح بطلب الانضمام إلى مجموعة خاصة"; +"TUIKitErrorSDKGroupInviteSuperDeny" = "غير مسموح بدعوة أعضاء يمتلكون دور المالك في المجموعة"; +"TUIKitErrorSDKGroupInviteNoMember" = "غير مسموح بدعوة أي أعضاء"; +"TUIKitErrorSDKFriendShipInvalidProfileKey" = "حقل الملف الشخصي غير صالح"; +"TUIKitErrorSDKFriendshipInvalidAddRemark" = "حقل الملاحظات غير صالح، يصل طوله إلى 96 بايتًا"; +"TUIKitErrorSDKFriendshipInvalidAddWording" = "حقل شرح طلب إضافة صديق غير صالح، يصل طوله إلى 120 بايتًا"; +"TUIKitErrorSDKFriendshipInvalidAddSource" = "حقل مصدر طلب إضافة صديق غير صالح، يجب أن يبدأ المصدر بالبادئة 'AddSource_Type_'"; +"TUIKitErrorSDKFriendshipFriendGroupEmpty" = "حقل مجموعة الأصدقاء غير صالح، يجب أن لا يكون فارغًا ويصل طول اسم كل مجموعة إلى 30 بايتًا"; +"TUIKitErrorSDKNetEncodeFailed" = "فشل تشفير الاتصال بالشبكة"; +"TUIKitErrorSDKNetDecodeFailed" = "فشل فك تشفير الاتصال بالشبكة"; +"TUIKitErrorSDKNetAuthInvalid" = "لم يتم استكمال التوثيق للاتصال بالشبكة"; +"TUIKitErrorSDKNetCompressFailed" = "فشل ضغط حزمة البيانات"; +"TUIKitErrorSDKNetUncompressFaile" = "فشل فك ضغط حزمة البيانات"; +"TUIKitErrorSDKNetFreqLimit" = "تم تحديد حد التردد، يمكن إجراء حد أقصى من 5 طلبات في الثانية الواحدة"; +"TUIKitErrorSDKnetReqCountLimit" = "تم تجاوز حد الطلبات المتزامنة، يمكن إجراء حد أقصى من 1000 طلب في نفس الوقت"; +"TUIKitErrorSDKNetDisconnect" = "تم فصل الاتصال بالشبكة، لم يتم إنشاء اتصال أو تم الكشف عن عدم وجود اتصال بالشبكة أثناء إنشاء اتصال socket"; +"TUIKitErrorSDKNetAllreadyConn" = "تم بالفعل إنشاء اتصال بالشبكة، لا يمكن إنشاء اتصال مكرر"; +"TUIKitErrorSDKNetConnTimeout" = "انتهت مهلة إنشاء اتصال الشبكة، يرجى المحاولة مرة أخرى بعد استعادة الاتصال بالشبكة."; +"TUIKitErrorSDKNetConnRefuse" = "تم رفض اتصال الشبكة، يتم رفض الطلب بسبب التكرار الزائد، يرفض الخادم الخدمة."; +"TUIKitErrorSDKNetNetUnreach" = "لا توجد طرق شبكة متاحة للوصول إلى الشبكة، يرجى المحاولة مرة أخرى بعد استعادة الاتصال بالشبكة."; +"TUIKitErrorSDKNetSocketNoBuff" = "لا توجد موارد مساحة تخزين مؤقت كافية في النظام لإكمال الاستدعاء، النظام مشغول جدًا، خطأ داخلي."; +"TUIKitERRORSDKNetResetByPeer" = "تم إعادة تعيين الاتصال بواسطة الطرف الآخر"; +"TUIKitErrorSDKNetSOcketInvalid" = "socket القابس غير صالح"; + +"TUIKitErrorSDKNetHostGetAddressFailed" = "IP العنوان فشل في الحصول على العنوان"; +"TUIKitErrorSDKNetConnectReset" = "تم إعادة تعيين اتصال الشبكة إلى العقدة الوسيطة أو الخادم"; +"TUIKitErrorSDKNetWaitInQueueTimeout" = "تجاوزت حزمة الطلبات المهلة الزمنية للانتظار في قائمة الانتظار للإرسال"; +"TUIKitErrorSDKNetWaitSendTimeout" = "الطلب قد دخل قائمة الانتظار للإرسال، في انتظار دخول البيانات في الـ buffer الشبكي في النظام وقد تجاوزت المهلة الزمنية"; +"TUIKitErrorSDKNetConnectReset" = "تم إعادة تعيين اتصال الشبكة إلى الـ server أو العقدة الوسيطة"; +"TUIKitErrorSDKNetWaitInQueueTimeout" = "تجاوزت حزمة الطلبات المهلة الزمنية للانتظار في قائمة الانتظار للإرسال"; +"TUIKitErrorSDKNetWaitAckTimeut" = "تجاوزت حزمة الطلبات المهلة الزمنية للانتظار في ذاكرة التخزين المؤقتة للشبكة في النظام، في انتظار استلام الرد من الـ server"; +"TUIKitErrorSDKSVRSSOConnectLimit" = "تجاوز عدد اتصالات الـ server الحد المسموح به، يرفض الـ server الخدمة"; +"TUIKitErrorSDKSVRSSOVCode" = "تجاوز مهلة إرسال رمز التحقق"; +"TUIKitErrorSVRSSOD2Expired" = "انتهت صلاحية الـ Key. الـ Key هو تذكرة داخلية تم إنشاؤها بناءً على UserSig، وصلاحية الـ Key أقل من أو تساوي صلاحية UserSig. يرجى استدعاء واجهة تسجيل الدخول TIMManager.getInstance().login مرة أخرى لتوليد Key جديد"; +"TUIKitErrorSVRA2UpInvalid" = "انتهت صلاحية الـ ticket. الـ ticket هي تذكرة داخلية تم إنشاؤها بناءً على UserSig، وصلاحية الـ ticket أقل من أو تساوي صلاحية UserSig. يرجى استدعاء واجهة تسجيل الدخول TIMManager.getInstance().login مرة أخرى لتوليد ticket جديدة"; +"TUIKitErrorSVRA2DownInvalid" = "فشل التحقق من الـ ticket أو تعرضت لهجوم أمان. يرجى استدعاء واجهة تسجيل الدخول TIMManager.getInstance().login مرة أخرى لتوليد ticket جديدة"; +"TUIKitErrorSVRSSOEmpeyKey" = "لا يُسمح بترك الـ Key فارغًا."; +"TUIKitErrorSVRSSOUinInvalid" = "حساب الـ Uin في الـ Key لا يتطابق مع حساب رأس الطلب."; +"TUIKitErrorSVRSSOVCodeTimeout" = "تجاوز مهلة إرسال رمز التحقق."; +"TUIKitErrorSVRSSONoImeiAndA2" = "الرجاء إرفاق الـ Key والـ Ticket."; +"TUIKitErrorSVRSSOCookieInvalid" = "فشل التحقق من تطابق الـ Cookie."; +"TUIKitErrorSVRSSODownTips" = "رسالة تلميح للتنزيل، انتهت صلاحية الـ Key."; +"TUIKitErrorSVRSSODisconnect" = "فصل الاتصال وقفل الشاشة."; +"TUIKitErrorSVRSSOIdentifierInvalid" = "هوية غير صالحة."; +"TUIKitErrorSVRSSOClientClose" = "إغلاق تلقائي للعميل."; +"TUIKitErrorSVRSSOMSFSDKQuit" = "إغلاق تلقائي لـ MSFSDK."; +"TUIKitErrorSVRSSOD2KeyWrong" = "فشل فك التشفير للمفتاح عدة مرات تجاوز الحد المسموح به، يُطلب إعادة تعيينه، يرجى استدعاء واجهة تسجيل الدخول TIMManager.getInstance().login مرة أخرى لتوليد مفتاح جديد."; +"TUIKitErrorSVRSSOUnsupport" = "غير مدعوم للتجميع، يتم إرجاع رمز خطأ موحد للعميل. يتوقف التجميع على العميل على هذه الاتصال الطويل للـ TCP."; +"TUIKitErrorSVRSSOPrepaidArrears" = "تأخير في الدفع المسبق."; +"TUIKitErrorSVRSSOPacketWrong" = "تنسيق حزمة الطلبات غير صحيح."; +"TUIKitErrorSVRSSOAppidBlackList" = "قائمة الـ SDKAppID السوداء."; +"TUIKitErrorSVRSSOCmdBlackList" = "قائمة الأوامر السوداء لـ service cmd في SDKAppID."; +"TUIKitErrorSVRSSOAppidWithoutUsing" = "SDKAppID متوقف عن الاستخدام."; +"TUIKitErrorSVRSSOFreqLimit" = "حد التردد (للمستخدم)، حد التردد هو الحد الذي يتم تعيينه لعدد الطلبات في الثانية لبروتوكول معين."; +"TUIKitErrorSVRSSOOverload" = "فائض الحمولة (النظام)، يتعامل الـ server المتصل بالاتصال بعدد كبير من الطلبات ولا يستطيع التعامل معها، ويتم رفض الخدمة."; +"TUIKitErrorSVRResNotFound" = "الملف المورد الذي يتم إرساله غير موجود."; +"TUIKitErrorSVRResAccessDeny" = "لا يُسمح بالوصول إلى الملف المورد الذي يتم إرساله."; +"TUIKitErrorSVRResSizeLimit"= "تجاوز حجم الملف الحد المسموح به."; +"TUIKitErrorSVRResSendCancel" = "تم إلغاء إرسال المستخدم، مثل تسجيل الخروج أثناء عملية الإرسال وما إلى ذلك."; +"TUIKitErrorSVRResReadFailed" = "فشل قراءة محتوى الملف."; +"TUIKitErrorSVRResTransferTimeout" = "انتهت مهلة نقل الملف المورد."; +"TUIKitErrorSVRResInvalidParameters" = "معلمات غير صالحة."; +"TUIKitErrorSVRResInvalidFileMd5" = "فشل التحقق من صحة MD5 للملف."; +"TUIKitErrorSVRResInvalidPartMd5" = "فشل التحقق من صحة MD5 للجزء المقسم."; +"TUIKitErrorSVRCommonInvalidHttpUrl" = "خطأ في تحليل عنوان URL للطلب HTTP، يرجى التحقق من تنسيق عنوان URL للطلب."; +"TUIKitErrorSVRCommomReqJsonParseFailed" = "فشل تحليل JSON للطلب HTTP، يرجى التحقق من تنسيق JSON."; +"TUIKitErrorSVRCommonInvalidAccount" = "خطأ في معرف أو UserSig في عنوان URI أو جسم JSON للطلب."; +"TUIKitErrorSVRCommonInvalidSdkappid" = "SDKAppID غير صالح، يرجى التحقق من صحة SDKAppID."; +"TUIKitErrorSVRCommonRestFreqLimit" = "تجاوز حد التردد لاستدعاء واجهة REST، يرجى تقليل تردد الطلبات."; +"TUIKitErrorSVRCommonRequestTimeout" = "انتهت مهلة الطلب أو يوجد خطأ في تنسيق الطلب HTTP، يرجى التحقق وإعادة المحاولة."; +"TUIKitErrorSVRCommonInvalidRes" = "خطأ في طلب المورد، يرجى التحقق من عنوان URL للطلب."; +"TUIKitErrorSVRCommonIDNotAdmin" = "يرجى استخدام حساب المسؤول في حقل المعرف في طلب واجهة REST."; +"TUIKitErrorSVRCommonSdkappidFreqLimit" = "تجاوز حد التردد لـ SDKAppID، يرجى تقليل تردد الطلبات."; +"TUIKitErrorSVRCommonSdkappidMiss" = "واجهة REST تحتاج إلى توفير SDKAppID، يرجى التحقق من وجود SDKAppID في عنوان URL للطلب."; +"TUIKitErrorSVRCommonRspJsonParseFailed" = "فشل تحليل JSON لحزمة الاستجابة HTTP."; +"TUIKitErrorSVRCommonExchangeAccountTimeout" = "انتهت مهلة تبديل الحساب."; +"TUIKitErrorSVRCommonInvalidIdFormat" = "نوع المعرف في جسم الطلب غير صحيح، يرجى التأكد من أن المعرف هو سلسلة نصية."; +"TUIKitErrorSVRCommonSDkappidForbidden" = "SDKAppID محظور."; +"TUIKitErrorSVRCommonReqForbidden" = "الطلب محظور."; +"TUIKitErrorSVRCommonReqFreqLimit" = "الطلب متكرر للغاية، يرجى المحاولة مرة أخرى لاحقًا."; +"TUIKitErrorSVRCommonInvalidService" = "انتهت صلاحية حزمة الاشتراك الخاصة بك وتم تعطيلها، يرجى تسجيل الدخول إلى صفحة شراء خدمة الدردشة الفورية IM وشراء حزمة جديدة. ستصبح الحزمة الجديدة نشطة بعد 5 دقائق."; +"TUIKitErrorSVRCommonSensitiveText" = "هجوم على النص الآمن، قد يحتوي النص على كلمات حساسة."; +"TUIKitErrorSVRCommonBodySizeLimit" = "حجم حزمة إرسال الرسالة طويل جدًا، يتم دعم حجم حزمة الرسالة حتى 12 كيلوبايت، يرجى تقليل حجم الحزمة وإعادة المحاولة."; +"TUIKitErrorSVRAccountUserSigExpired" = "انتهت صلاحية UserSig، يرجى إعادة توليد UserSig."; +"TUIKitErrorSVRAccountUserSigEmpty" = "طول UserSig يساوي 0."; +"TUIKitErrorSVRAccountUserSigCheckFailed" = "فشل التحقق من صحة UserSig."; +"TUIKitErrorSVRAccountUserSigMismatchPublicKey" = "فشل التحقق من صحة UserSig باستخدام المفتاح العام."; +"TUIKitErrorSVRAccountUserSigMismatchId" = "المعرف المطلوب في الطلب لا يتطابق مع المعرف المستخدم في إنشاء UserSig."; +"TUIKitErrorSVRAccountUserSigMismatchSdkAppid" = "SDKAppID المطلوب في الطلب لا يتطابق مع SDKAppID المستخدم في إنشاء UserSig."; +"TUIKitErrorSVRAccountUserSigPublicKeyNotFound" = "فشل العثور على المفتاح العام أثناء التحقق من صحة UserSig."; +"TUIKitErrorSVRAccountUserSigSdkAppidNotFount" = "لم يتم العثور على SDKAppID، يرجى التحقق من معلومات التطبيق في وحدة التحكم لـ IM الخاصة بالاتصال السحابي."; +"TUIKitErrorSVRAccountInvalidUserSig" = "انتهت صلاحية UserSig، يرجى إعادة توليد UserSig والمحاولة مرة أخرى."; +"TUIKitErrorSVRAccountNotFound" = "حساب المستخدم المطلوب غير موجود."; +"TUIKitErrorSVRAccountSecRstr" = "تم تقييد الوصول لأسباب أمان."; +"TUIKitErrorSVRAccountInternalTimeout" = "انتهت مهلة الخادم الداخلية، يرجى إعادة المحاولة."; +"TUIKitErrorSVRAccountInvalidCount" = "الكمية المجمعة في الطلب غير صالحة."; +"TUIkitErrorSVRAccountINvalidParameters" = "معلمات غير صالحة في الطلب، يرجى التحقق من ملء الحقول المطلوبة ومطابقة متطلبات البروتوكول."; +"TUIKitErrorSVRAccountAdminRequired" = "الطلب يتطلب صلاحيات المسؤول في التطبيق."; +"TUIKitErrorSVRAccountLowSDKVersion" = "إصدار SDK الخاص بك قديم جدًا، يرجى الترقية إلى أحدث إصدار."; +"TUIKitErrorSVRAccountFreqLimit" = "تم تقييد الطلب بسبب الفشل المتكرر وعدد محاولات إعادة المحاولة الكثيرة، يرجى الت"; + +"TUIKitErrorSVRAccountBlackList" = "تم إدراج الحساب في القائمة السوداء."; +"TUIKitErrorSVRAccountCountLimit" = "تجاوز الحد الأقصى لعدد الحسابات المسموح به في الإصدار التجريبي المجاني، يرجى الترقية إلى الإصدار المتخصص."; +"TUIKitErrorSVRAccountInternalError" = "خطأ داخلي في الخادم، يرجى إعادة المحاولة لاحقًا."; +"TUIKitErrorSVRProfileInvalidParameters" = "معلمات طلب غير صالحة، يرجى التحقق من صحة الطلب وفقًا لوصف الخطأ."; +"TUIKitErrorSVRProfileAccountMiss" = "معلمات الطلب غير صالحة، لم يتم تحديد حساب المستخدم الذي يجب جلب بياناته."; +"TUIKitErrorSVRProfileAccountNotFound" = "حساب المستخدم المطلوب غير موجود."; +"TUIKitErrorSVRProfileAdminRequired" = "الطلب يتطلب صلاحيات المسؤول في التطبيق."; +"TUIKitErrorSVRProfileSensitiveText" = "يحتوي حقل البيانات على كلمات حساسة."; +"TUIKitErrorSVRProfileInternalError" = "خطأ داخلي في الخادم، يرجى إعادة المحاولة لاحقًا."; +"TUIKitErrorSVRProfileReadWritePermissionRequired" = "لا يوجد إذن لقراءة حقل البيانات، يرجى الرجوع إلى وصف حقل البيانات."; +"TUIKitErrorSVRProfileTagNotFound" = "لا يوجد علامة لحقل البيانات."; +"TUIKitErrorSVRProfileSizeLimit" = "تجاوز طول قيمة حقل البيانات الحد الأقصى المسموح به والذي يبلغ 500 بايت."; +"TUIKitErrorSVRProfileValueError" = "قيمة حقل البيانات القياسية غير صحيحة، يرجى الرجوع إلى وصف حقل البيانات القياسية."; +"TUIKitErrorSVRProfileInvalidValueFormat" = "نوع قيمة حقل البيانات غير متطابق، يرجى الرجوع إلى وصف حقل البيانات القياسية."; +"TUIKitErrorSVRFriendshipInvalidParameters" = "معلمات الطلب غير صالحة، يرجى التحقق من صحة الطلب وفقًا لوصف الخطأ."; +"TUIKitErrorSVRFriendshipInvalidSdkAppid" = "SDKAppID غير متطابق."; +"TUIKitErrorSVRFriendshipAccountNotFound" = "حساب المستخدم المطلوب غير موجود."; +"TUIKitErrorSVRFriendshipAdminRequired" = "الطلب يتطلب صلاحيات المسؤول في التطبيق."; +"TUIKitErrorSVRFriendshipSensitiveText" = "يحتوي حقل علاقة الأصدقاء على كلمات حساسة."; +"TUIKitErrorSVRFriendshipNetTimeout" = "انتهت مهلة الشبكة، يرجى إعادة المحاولة لاحقًا."; +"TUIKitErrorSVRFriendshipWriteConflict" = "تعارض الكتابة المتزامنة يؤدي إلى تعارض الكتابة، يرجى استخدام الطريقة الدفعية."; +"TUIKitErrorSVRFriendshipAddFriendDeny" = "تم منع المستخدم من إرسال طلبات صداقة من الخلفية."; +"TUIkitErrorSVRFriendshipCountLimit" = "لقد وصلت إلى الحد الأقصى لعدد الأصدقاء في النظام."; +"TUIKitErrorSVRFriendshipGroupCountLimit" = "لقد وصلت إلى الحد الأقصى لعدد المجموعات في النظام."; +"TUIKitErrorSVRFriendshipPendencyLimit" = "لقد وصلت إلى الحد الأقصى لعدد الطلبات المعلقة في النظام."; +"TUIKitErrorSVRFriendshipBlacklistLimit" = "لقد وصلت إلى الحد الأقصى لعدد الأشخاص في القائمة السوداء في النظام."; +"TUIKitErrorSVRFriendshipPeerFriendLimit" = "لقد وصل الصديق الخاص بك إلى الحد الأقصى لعدد الأصدقاء في النظام."; +"TUIKitErrorSVRFriendshipInSelfBlacklist" = "الشخص الذي تحاول إضافته في القائمة السوداء الخاصة بك، لا يسمح بإضافته كصديق."; +"TUIKitErrorSVRFriendshipAllowTypeDenyAny" = "الشخص الذي تحاول إضافته كصديق، لا يسمح بإضافته كصديق لأي شخص."; +"TUIKitErrorSVRFriendshipInPeerBlackList" = "أنت في القائمة السوداء الخاصة بالشخص الذي تحاول إضافته كصديق، لا يسمح بإضافته كصديق."; +"TUIKitErrorSVRFriendshipAllowTypeNeedConfirm" = "تم إرسال الطلب ويتم انتظار الموافقة من الشخص الآخر."; +"TUIKitErrorSVRFriendshipAddFriendSecRstr" = "تم منع طلب الصداقة بسبب سياسة الأمان، يرجى عدم إرسال طلبات صداقة بشكل متكرر."; +"TUIKitErrorSVRFriendshipPendencyNotFound" = "الطلب المعلق المطلوب غير موجود."; +"TUIKitErrorSVRFriendshipDelFriendSecRstr" = "تم منع طلب حذف الصديق بسبب سياسة الأمان، يرجى عدم إرسال طلبات حذف الصديق بشكل متكرر."; + +"TUIKirErrorSVRFriendAccountNotFoundEx" = "حساب المستخدم المطلوب غير موجود."; +"TUIKitErrorSVRMsgPkgParseFailed" = "فشل تحليل حزمة الطلب."; +"TUIKitErrorSVRMsgInternalAuthFailed" = "فشل المصادقة الداخلية."; +"TUIKitErrorSVRMsgInvalidId" = "معرف غير صالح."; +"TUIKitErrorSVRMsgNetError" = "خطأ في الشبكة، يرجى إعادة المحاولة."; +"TUIKitErrorSVRMsgPushDeny" = "تم منع إرسال رسالة الدردشة الفردية قبل تنفيذها، تطبيق الخلفية يمنع إرسال هذه الرسالة."; +"TUIKitErrorSVRMsgInPeerBlackList" = "تم حظر إرسال رسالة الدردشة الفردية بواسطة الشخص الآخر، يمنع إرسالها."; +"TUIKitErrorSVRMsgBothNotFriend" = "الشخصين اللذين يحاولان إرسال رسالة الدردشة الفردية ليسا صديقين، يمنع إرسالها."; +"TUIKitErrorSVRMsgNotPeerFriend" = "تم إرسال رسالة الدردشة الفردية وأنت لست صديق الشخص الآخر (علاقة من جانب واحد)، يمنع إرسالها."; +"TUIkitErrorSVRMsgNotSelfFriend" = "تم إرسال رسالة الدردشة الفردية والشخص الآخر ليس صديقك (علاقة من جانب واحد)، يمنع إرسالها."; +"TUIKitErrorSVRMsgShutupDeny" = "تم منع إرسال الرسائل بسبب الحظر عن الكلام."; +"TUIKitErrorSVRMsgRevokeTimeLimit" = "تم تجاوز الحد الزمني لسحب الرسالة (الافتراضي 2 دقيقة)."; +"TUIKitErrorSVRMsgDelRambleInternalError" = "خطأ داخلي في حذف الرسائل المتجولة."; +"TUIKitErrorSVRMsgJsonParseFailed" = "فشل تحليل تنسيق JSON، يرجى التحقق من صحة حزمة الطلب وفقًا لوصف JSON."; +"TUIKitErrorSVRMsgInvalidJsonBodyFormat" = "تنسيق حزمة الطلب JSON غير صحيح، يرجى التحقق من صحة حقل MsgBody وفقًا لوصف تنسيق الرسالة."; +"TUIKitErrorSVRMsgInvalidToAccount" = "حقل To_Account مفقود أو ليس من نوع Integer في حزمة الطلب بتنسيق JSON."; +"TUIKitErrorSVRMsgInvalidRand" = "حقل MsgRandom مفقود أو ليس من نوع Integer في حزمة الطلب بتنسيق JSON."; +"TUIKitErrorSVRMsgInvalidTimestamp" = "حقل MsgTimeStamp مفقود أو ليس من نوع Integer في حزمة الطلب بتنسيق JSON."; +"TUIKitErrorSVRMsgBodyNotArray" = "نوع حقل MsgBody في حزمة الطلب بتنسيق JSON ليس من نوع Array."; +"TUIKitErrorSVRMsgInvalidJsonFormat" = "حزمة الطلب بتنسيق JSON لا تتوافق مع وصف تنسيق الرسالة."; +"TUIKitErrorSVRMsgToAccountCountLimit" = "عدد حسابات الوجهة في إرسال الرسائل الجماعية تجاوز الحد الأقصى (500)."; +"TUIKitErrorSVRMsgToAccountNotFound" = "حساب To_Account غير مسجل أو غير موجود."; +"TUIKitErrorSVRMsgTimeLimit" = "خطأ في وقت تخزين الرسالة غير المتصلة (لا يمكن أن يتجاوز 7 أيام)."; +"TUIKitErrorSVRMsgInvalidSyncOtherMachine" = "حقل SyncOtherMachine في حزمة الطلب بتنسيق JSON ليس من نوع Integer."; +"TUIkitErrorSVRMsgInvalidMsgLifeTime" = "حقل MsgLifeTime في حزمة الطلب بتنسيق JSON ليس من نوع Integer."; +"TUIKitErrorSVRMsgBodySizeLimit" = "حزمة بيانات JSON طويلة جدًا، يرجى عدم تجاوز حجم حزمة الرسالة 12 كيلوبايت."; +"TUIKitErrorSVRmsgLongPollingCountLimit" = "تم طرد الاستعلام الطويل على الويب (تم تجاوز الحد الأقصى لعدد الجلسات المتصلة في الويب)."; +"TUIKitErrorSVRGroupApiNameError" = "اسم الواجهة في الطلب غير صحيح."; +"TUIKitErrorSVRGroupAccountCountLimit" = "عدد الحسابات المرفقة في حزمة الطلب كثير جدًا."; +"TUIkitErrorSVRGroupFreqLimit" = "تم تقييد تكرار العملية، يرجى محاولة تقليل تكرار الاستدعاء."; +"TUIKitErrorSVRGroupPermissionDeny" = "ليس لديك صلاحيات كافية للقيام بالعملية."; +"TUIKitErrorSVRGroupInvalidReq" = "طلب غير صالح."; +"TUIKitErrorSVRGroupSuperNotAllowQuit" = "لا يُسمح لمالك المجموعة بالخروج من المجموعة بنفسه."; +"TUIKitErrorSVRGroupNotFound" = "المجموعة غير موجودة."; +"TUIKitErrorSVRGroupJsonParseFailed" = "فشل تحليل حزمة JSON، يرجى التحقق من تنسيق الحزمة."; +"TUIKitErrorSVRGroupInvalidId" = "معرف المستخدم الذي يقوم بالعملية غير صالح، يرجى التحقق من صحة معرف المستخدم الذي يقوم بالعملية."; +"TUIKitErrorSVRGroupAllreadyMember" = "المستخدم الذي تمت دعوته للانضمام إلى المجموعة هو بالفعل عضو في المجموعة."; +"TUIKitErrorSVRGroupFullMemberCount" = "المجموعة مكتملة العدد، لا يمكن إضافة المستخدمين المحددين في الطلب إلى المجموعة."; +"TUIKitErrorSVRGroupInvalidGroupId" = "معرف المجموعة غير صالح، يرجى التحقق من صحة معرف المجموعة."; +"TUIKitErrorSVRGroupRejectFromThirdParty" = "تم رفض العملية من قبل خلفية التطبيق من خلال رد فعل طرف ثالث."; +"TUIKitErrorSVRGroupShutDeny" = "لا يمكن إرسال الرسائل بسبب الحظر عن الكلام، يرجى التحقق مما إذا كان المرسل محظورًا عن الكلام."; +"TUIKitErrorSVRGroupRspSizeLimit" = "تجاوز طول حزمة الاستجابة الحد الأقصى."; +"TUIKitErrorSVRGroupAccountNotFound" = "حساب المستخدم المطلوب غير موجود."; +"TUIKitErrorSVRGroupGroupIdInUse" = "معرف المجموعة قيد الاستخدام، يرجى اختيار معرف مجموعة آخر."; +"TUIKitErrorSVRGroupSendMsgFreqLimit" = "تجاوز تكرار إرسال الرسائل، يرجى زيادة الفاصل الزمني بين إرسال الرسائل."; +"TUIKitErrorSVRGroupReqAllreadyBeenProcessed" = "تم معالجة طلب الدعوة أو الطلب هذا بالفعل."; +"TUIKitErrorSVRGroupGroupIdUserdForSuper" = "معرف المجموعة قيد الاستخدام والمستخدم هو المالك، يمكن استخدامه مباشرة."; +"TUIKitErrorSVRGroupSDkAppidDeny" = "تم تعطيل كلمة الأمر المطلوبة من قبل SDKAppID المطلوب."; +"TUIKitErrorSVRGroupRevokeMsgNotFound" = "الرسالة المطلوبة للإلغاء غير موجودة."; +"TUIKitErrorSVRGroupRevokeMsgTimeLimit" = "تجاوز الوقت المحدد لإلغاء الرسالة (الافتراضي 2 دقيقة)."; +"TUIKitErrorSVRGroupRevokeMsgDeny" = "الرسالة المطلوبة للإلغاء لا تدعم عملية الإلغاء."; +"TUIKitErrorSVRGroupNotAllowRevokeMsg" = "نوع المجموعة لا يدعم عملية إلغاء الرسالة."; +"TUIKitErrorSVRGroupRemoveMsgDeny" = "نوع الرسالة غير مدعوم لعملية الحذف."; +"TUIKitErrorSVRGroupNotAllowRemoveMsg" = "غرفة الدردشة الصوتية والفيديو والبث الكبير للأعضاء المتصلين لا تدعم حذف الرسائل."; +"TUIKitErrorSVRGroupAvchatRoomCountLimit" = "تجاوز الحد الأقصى لعدد غرف الدردشة الصوتية والفيديو المنشأة."; +"TUIKitErrorSVRGroupCountLimit" = "تجاوز الحد الأقصى لعدد المجموعات التي يمكن للمستخدم الفردي إنشاؤها والانضمام إليها."; +"TUIKitErrorSVRGroupMemberCountLimit" = "تجاوز الحد الأقصى لعدد أعضاء المجموعة."; +"TUIKitErrorSVRNoSuccessResult" = "لا توجد نتائج ناجحة للعملية المجمعة."; +"TUIKitErrorSVRToUserInvalid" = "IM: المستلم غير صالح."; +"TUIKitErrorSVRRequestTimeout" = "انتهت مهلة الطلب."; +"TUIKitErrorSVRInitCoreFail" = "فشل في تهيئة وحدة INIT CORE."; +"TUIKitErrorSVRConvGroupNameLengthLimit" = "تجاوز طول اسم مجموعة الدردشة الجماعية الحد الأقصى."; +"TUIKitErrorExpiredSessionNode" = "SessionNode غير موجود."; +"TUIKitErrorLoggedOutBeforeLoginFinished" = "تم تسجيل الخروج قبل انتهاء عملية تسجيل الدخول (تم الرد عند تسجيل الدخول)."; +"TUIKitErrorTLSSDKNotInitialized" = "لم يتم تهيئة tlssdk بعد."; +"TUIKitErrorTLSSDKUserNotFound" = "لم يتم العثور على معلومات المستخدم المطلوبة في TLSSDK."; +"TUIKitErrorBindFaildRegTimeout" = "انتهت مهلة التسجيل."; +"TUIKitErrorBindFaildIsBinding" = "جاري عملية الربط حاليًا."; +"TUIKitErrorPacketFailUnknown" = "خطأ غير معروف في إرسال الحزمة."; +"TUIKitErrorPacketFailReqNoNet" = "لا يوجد اتصال بالشبكة أثناء إرسال حزمة الطلب، يتم تحويلها إلى حالة ERR_REQ_NO_NET_ON_REQ عند المعالجة."; +"TUIKitErrorPacketFailRespNoNet" = "لا يوجد اتصال بالشبكة أثناء إرسال حزمة الرد، يتم تحويلها إلى حالة ERR_REQ_NO_NET_ON_RSP عند المعالجة."; +"TUIKitErrorPacketFailReqNoAuth" = "لا يوجد صلاحيات أثناء إرسال حزمة الطلب."; +"TUIKitErrorPacketFailSSOErr" = "خطأ في SSO."; +"TUIKitErrorPacketFailRespTimeout" = "انتهت مهلة الرد."; +"TUIKitErrorFriendshipProxySyncing" = "لم يكتمل تزامن بيانات proxy_manager مع الخادم."; +"TUIKitErrorFriendshipProxySyncedFail" = "فشل في تزامن بيانات proxy_manager."; +"TUIKitErrorFriendshipProxyLocalCheckErr" = "معلمات طلب proxy_manager غير صالحة في التحقق المحلي."; +"TUIKitErrorGroupInvalidField" = "تحتوي حقل غير محدد في طلب مساعد المجموعة"; +"TUIKitErrorGroupStoreageDisabled" = "تم تعطيل تخزين معلومات المجموعة المحلي لمساعد المجموعة"; +"TUIKitErrorLoadGrpInfoFailed" = "فشل تحميل معلومات المجموعة من التخزين"; +"TUIKitErrorReqNoNetOnReq" = "لا يوجد اتصال بالشبكة أثناء الطلب."; +"TUIKitErrorReqNoNetOnResp" = "لا يوجد اتصال بالشبكة أثناء الاستجابة."; +"TUIKitErrorServiceNotReady" = "خدمة QALSDK غير جاهزة بعد."; +"TUIKitErrorLoginAuthFailed" = "فشلت عملية المصادقة على الحساب (فشل في الحصول على معلومات المستخدم)."; +"TUIKitErrorNeverConnectAfterLaunch" = "لم يتم محاولة الاتصال بالإنترنت بعد تشغيل التطبيق."; +"TUIKitErrorReqFailed" = "فشل تنفيذ الطلب في QAL."; +"TUIKitErrorReqInvaidReq" = "طلب غير صالح، toMsgService غير صالح."; +"TUIKitErrorReqOnverLoaded" = "طابور الطلبات مكتظ."; +"TUIKitErrorReqKickOff" = "تم تسجيل الخروج من جهاز آخر."; +"TUIKitErrorReqServiceSuspend" = "تم إيقاف الخدمة مؤقتًا."; +"TUIKitErrorReqInvalidSign" = "توقيع SSO غير صالح."; +"TUIKitErrorReqInvalidCookie" = "ملف تعريف الارتباط SSO غير صالح."; +"TUIKitErrorLoginTlsRspParseFailed" = "فشل في التحقق من صحة حزمة الاستجابة TLS أثناء تسجيل الدخول، طول البيانات غير صحيح."; +"TUIKitErrorLoginOpenMsgTimeout" = "انتهت مهلة تقرير حالة OPENSTATSVC إلى OPENMSG أثناء تسجيل الدخول."; +"TUIKitErrorLoginOpenMsgRspParseFailed" = "فشل في تحليل حزمة الاستجابة أثناء تقرير حالة OPENSTATSVC إلى OPENMSG أثناء تسجيل الدخول."; +"TUIKitErrorLoginTslDecryptFailed" = "فشل في فك تشفير TLS أثناء تسجيل الدخول."; +"TUIKitErrorWifiNeedAuth" = "يتطلب wifi المصادقة"; +"TUIKitErrorUserCanceled" = "ألغى المستخدم"; +"TUIkitErrorRevokeTimeLimitExceed" = "تجاوزت إعادة الرسالة الحد الزمني (الافتراضي 2 دقيقة)"; +"TUIKitErrorLackUGExt" = "يفتقر إلى حزمة UGC الموسعة"; +"TUIKitErrorAutoLoginNeedUserSig" = "تسجيل الدخول التلقائي، انتهت صلاحية التذكرة المحلية، يتطلب تسجيل الدخول اليدوي باستخدام userSig"; +"TUIKitErrorQALNoShortConneAvailable" = "لا يوجد اتصال قصير SSO متاح"; +"TUIKitErrorReqContentAttach" = "ضربة أمنية لمحتوى الرسالة"; +"TUIKitErrorLoginSigExpire" = "انتهت صلاحية التذكرة المحلية عند تسجيل الدخول"; +"TUIKitErrorSDKHadInit" = "تم تهيئة SDK بالفعل ولا يلزم إعادة التهيئة"; +"TUIKitErrorOpenBDHBase" = "خطأ في openbdh"; +"TUIKitErrorRequestNoNetOnReq" = "لا يوجد اتصال بالشبكة أثناء الطلب، يرجى المحاولة مرة أخرى بعد استعادة الاتصال بالشبكة"; +"TUIKitErrorRequestNoNetOnRsp" = "لا يوجد اتصال بالشبكة أثناء الاستجابة، يرجى المحاولة مرة أخرى بعد استعادة الاتصال بالشبكة"; +"TUIKitErrorRequestOnverLoaded" = "طابور الطلبات ممتلئ"; +"TUIKitErrorUnsupporInterface" = "هذه الميزة متاحة فقط في الإصدار الرئيسي، يرجى الترقية إلى الإصدار الرئيسي."; +"TUIKitErrorUnsupporInterfaceSuffix" = "هذه الميزة متاحة فقط في الإصدار الرئيسي، يرجى الترقية إلى الإصدار الرئيسي."; +"TUIKitErrorUnsupportIntefaceSearch" = "البحث"; +"TUIKitErrorUnsupportIntefaceMessageRead" = "إيصال قراءة الرسالة"; +"TUIKitErrorUnsupportIntefaceCommunity" = "المجتمع"; +"TUIKitErrorUnsupportIntefaceDesc" = "هذه الميزة متاحة فقط في الإصدار الرئيسي لـ IM، يمكن استخدامها بعد شراء حزمة الإصدار الرئيسي، يرجى الرجوع إلى تفاصيل الأسعار."; +"TUIKitErrorValueAddedUnsupportIntefaceDesc" = "هذه الميزة هي ميزة دفع إضافية وتقع حاليًا في مرحلة الاختبار الداخلي، يرجى الاتصال بفريق الأعمال في Tencent Cloud لتفعيلها واستخدامها."; +"TUIKitErrorUnsupportIntefaceCommunityDesc" = "\nملاحظة: يمكن أن يستوعب المجتمع ملايين الأعضاء ويمكن تقسيمه إلى مجموعات ومواضيع، وهو مناسب لتبادل الاهتمامات والتواصل الاجتماعي في الألعاب وإدارة المعجبين وإدارة المنظمات وما إلى ذلك."; +"TUIKitErrorUnsupportIntefaceGuidelines" = "تفاصيل الأسعار"; +"TUIKitErrorUnsupportIntefaceTitle" = "تنبيه"; +"TUIKitErrorUnsupportIntefaceIGotIt" = "فهمت"; +"TUIKitErrorUnsupportIntefaceNoMoreAlert" = "لا تذكرني مرة أخرى"; diff --git a/iOS/TUIKit/TUICore/TUICommonModel.m b/iOS/TUIKit/TUICore/TUICommonModel.m index b954db967..23610d286 100644 --- a/iOS/TUIKit/TUICore/TUICommonModel.m +++ b/iOS/TUIKit/TUICore/TUICommonModel.m @@ -659,7 +659,7 @@ static void *gScrollViewBoundsChangeNotificationContext = &gScrollViewBoundsChan - (UIImage *)navigationItemBackArrowImage { if (!_navigationItemBackArrowImage) { - _navigationItemBackArrowImage = TUICoreDynamicImage(@"nav_back_img", [UIImage imageNamed:@"ic_back_white"]); + _navigationItemBackArrowImage = TUICoreDynamicImage(@"nav_back_img", [UIImage imageNamed:TUICoreImagePath(@"nav_back")]); } return _navigationItemBackArrowImage; } diff --git a/iOS/TUIKit/TUICore/TUICore.podspec b/iOS/TUIKit/TUICore/TUICore.podspec index cb79f3996..8ed0e3643 100644 --- a/iOS/TUIKit/TUICore/TUICore.podspec +++ b/iOS/TUIKit/TUICore/TUICore.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |spec| spec.name = 'TUICore' - spec.version = '7.4.4643' + spec.version = '7.5.4852' spec.platform = :ios spec.ios.deployment_target = '9.0' spec.license = { :type => 'Proprietary', diff --git a/iOS/TUIKit/TUICore/TUIDefine.h b/iOS/TUIKit/TUICore/TUIDefine.h index 6e0fd68a6..fae9e4eb3 100644 --- a/iOS/TUIKit/TUICore/TUIDefine.h +++ b/iOS/TUIKit/TUICore/TUIDefine.h @@ -139,6 +139,7 @@ #define TUIGroupNoteBundle @"TUIGroupNote" #define TIMCommonBundle @"TIMCommon" #define TUITranslationBundle @"TUITranslation" +#define TUIVoiceToTextBundle @"TUIVoiceToText" #define TUIKitLocalizableBundle @"TUIKitLocalizable" #define TUICoreLocalizableBundle TUIKitLocalizableBundle @@ -164,6 +165,7 @@ #define TUIGroupNoteBundle_Key_Class @"TUIGroupNoteService" #define TIMCommonBundle_Key_Class @"TIMConfig" #define TUITranslationBundle_Key_Class @"TUITranslationService" +#define TUIVoiceToTextBundle_Key_Class @"TUIVoiceToTextService" #define TUIKitLocalizableBundle_Key_Class @"TUICore" #define TUIChatLocalizableBundle_Key_Class @"TUIChatService" #define TIMCommonLocalizableBundle_Key_Class @"TIMConfig" @@ -206,6 +208,9 @@ static inline NSString *getTUIFrameWorkName(NSString *bundleKeyClass) { if ([bundleKeyClass isEqualToString:TUITranslationBundle_Key_Class]) { return @"TUITranslationPlugin"; } + if ([bundleKeyClass isEqualToString:TUIVoiceToTextBundle_Key_Class]) { + return @"TUIVoiceToTextPlugin"; + } return @""; } @@ -250,6 +255,7 @@ static inline NSString *getTUIGetBundlePath(NSString *bundleName, NSString *bund #define TUIGroupNoteThemePath TUIBundlePath(@"TUIGroupNoteTheme", TUIGroupNoteBundle_Key_Class) #define TIMCommonThemePath TUIBundlePath(@"TIMCommonTheme", TIMCommonBundle_Key_Class) #define TUITranslationThemePath TUIBundlePath(@"TUITranslationTheme", TUITranslationBundle_Key_Class) +#define TUIVoiceToTextThemePath TUIBundlePath(@"TUIVoiceToTextTheme", TUIVoiceToTextBundle_Key_Class) #define TUICallKitThemePath TUIBundlePath(@"TUICallKitTheme", TUICallKitBundle_Key_Class) static inline NSBundle *getTUIGetLocalizable(NSString *bundleName) { @@ -279,6 +285,7 @@ static inline NSBundle *getTUIGetLocalizable(NSString *bundleName) { #define TUIGroupNoteImagePath(imageName) [TUIBundlePath(TUIGroupNoteBundle, TUIGroupNoteBundle_Key_Class) stringByAppendingPathComponent:imageName] #define TIMCommonImagePath(imageName) [TUIBundlePath(TIMCommonBundle, TIMCommonBundle_Key_Class) stringByAppendingPathComponent:imageName] #define TUITranslationImagePath(imageName) [TUIBundlePath(TUITranslationBundle, TUITranslationBundle_Key_Class) stringByAppendingPathComponent:imageName] +#define TUIVoiceToTextImagePath(imageName) [TUIBundlePath(TUIVoiceToTextBundle, TUIVoiceToTextBundle_Key_Class) stringByAppendingPathComponent:imageName] //-----Minimalist------- #define TUIDemoBundle_Minimalist @"TUIDemo_Minimalist" @@ -292,6 +299,7 @@ static inline NSBundle *getTUIGetLocalizable(NSString *bundleName) { #define TUIPollBundle_Minimalist @"TUIPoll_Minimalist" #define TUIGroupNoteBundle_Minimalist @"TUIGroupNote_Minimalist" #define TUITranslationBundle_Minimalist @"TUITranslation_Minimalist" +#define TUIVoiceToTextBundle_Minimalist @"TUIVoiceToText_Minimalist" // #define TUIKitLocalizableBundle @"TUIKitLocalizable" // #define TUIKitLocalizable(bundleName) [NSBundle bundleWithPath:TUIBundlePath(bundleName, TUIKitLocalizableBundle_Key_Class)] @@ -312,6 +320,8 @@ static inline NSBundle *getTUIGetLocalizable(NSString *bundleName) { [TUIBundlePath(TUIGroupNoteBundle_Minimalist, TUIGroupNoteBundle_Key_Class) stringByAppendingPathComponent:imageName] #define TUITranslationImagePath_Minimalist(imageName) \ [TUIBundlePath(TUITranslationBundle_Minimalist, TUITranslationBundle_Key_Class) stringByAppendingPathComponent:imageName] +#define TUIVoiceToTextImagePath_Minimalist(imageName) \ + [TUIBundlePath(TUIVoiceToTextBundle_Minimalist, TUIVoiceToTextBundle_Key_Class) stringByAppendingPathComponent:imageName] //----- ///////////////////////////////////////////////////////////////////////////////// @@ -700,6 +710,7 @@ static inline NSBundle *getTUIGetLocalizable(NSString *bundleName) { #define TUICore_TUIChatExtension_InputViewMoreItem_GroupID @"TUICore_TUIChatExtension_InputViewMoreItem_GroupID" #define TUICore_TUIChatExtension_InputViewMoreItem_FilterVideoCall @"TUICore_TUIChatExtension_InputViewMoreItem_FilterVideoCall" #define TUICore_TUIChatExtension_InputViewMoreItem_FilterAudioCall @"TUICore_TUIChatExtension_InputViewMoreItem_FilterAudioCall" +#define TUICore_TUIChatExtension_InputViewMoreItem_FilterRoom @"TUICore_TUIChatExtension_InputViewMoreItem_FilterRoom" #define TUICore_TUIChatExtension_InputViewMoreItem_ItemSize @"TUICore_TUIChatExtension_InputViewMoreItem_ItemSize" #define TUICore_TUIChatExtension_InputViewMoreItem_ItemImage @"TUICore_TUIChatExtension_InputViewMoreItem_ItemImage" #define TUICore_TUIChatExtension_InputViewMoreItem_ItemTitle @"TUICore_TUIChatExtension_InputViewMoreItem_ItemTitle" @@ -736,6 +747,9 @@ static inline NSBundle *getTUIGetLocalizable(NSString *bundleName) { #define TUICore_TUIChatObjectFactory_ChatViewController_LocateMessage @"TUICore_TUIChatObjectFactory_ChatViewController_LocateMessage" #define TUICore_TUIChatObjectFactory_ChatViewController_AtMsgSeqs @"TUICore_TUIChatObjectFactory_ChatViewController_AtMsgSeqs" #define TUICore_TUIChatObjectFactory_ChatViewController_Draft @"TUICore_TUIChatObjectFactory_ChatViewController_Draft" +#define TUICore_TUIChatObjectFactory_ChatViewController_Enable_Video_Call @"TUICore_TUIChatObjectFactory_ChatViewController_Enable_Video_Call" +#define TUICore_TUIChatObjectFactory_ChatViewController_Enable_Audio_Call @"TUICore_TUIChatObjectFactory_ChatViewController_Enable_Audio_Call" +#define TUICore_TUIChatObjectFactory_ChatViewController_Enable_Room @"TUICore_TUIChatObjectFactory_ChatViewController_Enable_Room" #pragma mark - TUICore_TUIConversation_Service #define TUICore_TUIConversationService @"TUICore_TUIConversationService" @@ -1014,15 +1028,12 @@ static inline NSBundle *getTUIGetLocalizable(NSString *bundleName) { #define TUICore_TUIPluginNotify_PluginViewSizeChangedSubKey @"TUICore_TUIPluginNotify_PluginViewSizeChangedSubKey" #define TUICore_TUIPluginNotify_PluginViewSizeChangedSubKey_Message @"TUICore_TUIPluginNotify_PluginViewSizeChangedSubKey_Message" -#pragma mark - TUICore_TUITranslation_Notify -#define TUICore_TUITranslationNotify @"TUICore_TUITranslationNotify" +#define TUICore_TUIPluginNotify_DidChangePluginViewSubKey @"TUICore_TUIPluginNotify_DidChangePluginViewSubKey" +#define TUICore_TUIPluginNotify_DidChangePluginViewSubKey_Data @"TUICore_TUIPluginNotify_DidChangePluginViewSubKey_Data" +#define TUICore_TUIPluginNotify_DidChangePluginViewSubKey_VC @"TUICore_TUIPluginNotify_DidChangePluginViewSubKey_VC" -#define TUICore_TUITranslationNotify_DidChangeTranslationSubKey @"TUICore_TUITranslationNotify_DidChangeTranslationSubKey" -#define TUICore_TUITranslationNotify_DidChangeTranslationSubKey_Data @"TUICore_TUITranslationNotify_DidChangeTranslationSubKey_Data" -#define TUICore_TUITranslationNotify_DidChangeTranslationSubKey_VC @"TUICore_TUITranslationNotify_DidChangeTranslationSubKey_VC" - -#define TUICore_TUITranslationNotify_WillForwardTranslationSubKey @"TUICore_TUITranslationNotify_WillForwardTranslationSubKey" -#define TUICore_TUITranslationNotify_WillForwardTranslationSubKey_Text @"TUICore_TUITranslationNotify_WillForwardTranslationSubKey_Text" +#define TUICore_TUIPluginNotify_WillForwardTextSubKey @"TUICore_TUIPluginNotify_WillForwardTextSubKey" +#define TUICore_TUIPluginNotify_WillForwardTextSubKey_Text @"TUICore_TUIPluginNotify_WillForwardTextSubKey_Text" // 初始化录制成功,录制成功 #define TUICore_RecordAudioMessageNotifyError_None 0 @@ -1120,6 +1131,13 @@ static inline NSBundle *getTUIGetLocalizable(NSString *bundleName) { #define TUICore_TUIRoomImAccessFactory_GetRoomMessageViewMethod @"TUICore_TUIRoomImAccessFactory_GetRoomMessageViewMethod" #define TUICore_TUIRoomImAccessFactory_GetRoomMessageViewMethod_Message @"TUICore_TUIRoomImAccessFactory_GetRoomMessageViewMethod_Message" +#pragma mark - TUICore_PrivacyService_ScreenShareAntifraudReminderService +#define TUICore_PrivacyService @"TUICore_PrivacyService" +#define TUICore_PrivacyService_ScreenShareAntifraudReminderMethod @"TUICore_PrivacyService_ScreenShareAntifraudReminderMethod" +#define TUICore_PrivacyService_EnableScreenShareAntifraudReminderMethod_Cancel -1 +#define TUICore_PrivacyService_EnableScreenShareAntifraudReminderMethod_Continue 0 + + ///////////////////////////////////////////////////////////////////////////////// // // TUIOfflinePush @@ -1157,10 +1175,3 @@ static inline NSBundle *getTUIGetLocalizable(NSString *bundleName) { #endif /* THeader_h */ - -#pragma mark - TUICore_TUIDebugService -#define TUICore_TUIDebugService @"TUICore_TUIDebugService" -#define TUICore_TUIDebugService_ShowDebugView @"TUICore_TUIDebugService_ShowDebugView" - -#define TUICore_TUIDebugService_PrepareSetting @"TUICore_TUIDebugService_PrepareSetting" -#define TUICore_TUIDebugService_PrepareSettingView @"TUICore_TUIDebugService_PrepareSettingView" diff --git a/iOS/TUIKit/TUICore/TUIGlobalization.h b/iOS/TUIKit/TUICore/TUIGlobalization.h index 363440451..87707427a 100644 --- a/iOS/TUIKit/TUICore/TUIGlobalization.h +++ b/iOS/TUIKit/TUICore/TUIGlobalization.h @@ -29,6 +29,8 @@ #define TIMCommonLocalizableString(key) [TUIGlobalization getLocalizedStringForKey:@"" #key "" bundle:TIMCommonLocalizableBundle] +#define isRTL() [TUIGlobalization getRTLOption] + #define TUICustomLanguageKey @"TUICustomLanguageKey" #define TUIChangeLanguageNotification @"TUIChangeLanguageNotification" @@ -58,6 +60,10 @@ */ + (void)ignoreTraditionChinese:(BOOL)ignore; ++ (void)setRTLOption:(BOOL)op; + ++ (BOOL)getRTLOption; + #pragma mark - Deprecated + (NSString *)g_localizedStringForKey:(NSString *)key bundle:(NSString *)bundleName __attribute__((deprecated("use getLocalizedStringForKey:bundle:"))); + (NSString *)tk_localizableLanguageKey __attribute__((deprecated("use getPreferredLanguage"))); diff --git a/iOS/TUIKit/TUICore/TUIGlobalization.m b/iOS/TUIKit/TUICore/TUIGlobalization.m index 484c47907..ae7caaa92 100644 --- a/iOS/TUIKit/TUICore/TUIGlobalization.m +++ b/iOS/TUIKit/TUICore/TUIGlobalization.m @@ -12,8 +12,19 @@ @implementation TUIGlobalization ++ (void)load { + NSString *language = [TUIGlobalization getPreferredLanguage]; + if([language hasPrefix:@"ar"]) { + [TUIGlobalization setRTLOption:YES]; + } + else { + [TUIGlobalization setRTLOption:NO]; + } +} + static NSString *gCustomLanguage = nil; static BOOL gIgnoreTraditionChinese = YES; +static BOOL gRTLOption = NO; + (NSString *)getLocalizedStringForKey:(NSString *)key bundle:(NSString *)bundleName { return [self getLocalizedStringForKey:key value:nil bundle:bundleName]; @@ -66,7 +77,10 @@ static BOOL gIgnoreTraditionChinese = YES; language = @"ru"; } else if ([language hasPrefix:@"uk"]) { language = @"uk"; - } else { + } else if ([language hasPrefix:@"ar"]) { + language = @"ar"; + } + else { language = @"en"; } @@ -92,6 +106,18 @@ static BOOL gIgnoreTraditionChinese = YES; gIgnoreTraditionChinese = ignore; } ++ (void)setRTLOption:(BOOL)op { + gRTLOption = op; + [UIView appearance].semanticContentAttribute = op?UISemanticContentAttributeForceRightToLeft:UISemanticContentAttributeForceLeftToRight; + [UISearchBar appearance].semanticContentAttribute = op?UISemanticContentAttributeForceRightToLeft:UISemanticContentAttributeForceLeftToRight; + [UICollectionView appearance].semanticContentAttribute = op?UISemanticContentAttributeForceRightToLeft:UISemanticContentAttributeForceLeftToRight; + [UISwitch appearance].semanticContentAttribute = op?UISemanticContentAttributeForceRightToLeft:UISemanticContentAttributeForceLeftToRight; +} + ++ (BOOL)getRTLOption { + return gRTLOption; +} + #pragma mark - Deprecated + (NSString *)g_localizedStringForKey:(NSString *)key bundle:(nonnull NSString *)bundleName { return [self getLocalizedStringForKey:key value:nil bundle:bundleName]; diff --git a/iOS/TUIKit/TUICore/TUIThemeManager.h b/iOS/TUIKit/TUICore/TUIThemeManager.h index cedb64077..ab503d31d 100644 --- a/iOS/TUIKit/TUICore/TUIThemeManager.h +++ b/iOS/TUIKit/TUICore/TUIThemeManager.h @@ -87,6 +87,7 @@ NS_ASSUME_NONNULL_BEGIN #define TUIGroupNoteDynamicColor(colorKey, defaultHex) TUIDynamicColor(colorKey, TUIThemeModuleGroupNote, defaultHex) #define TIMCommonDynamicColor(colorKey, defaultHex) TUIDynamicColor(colorKey, TUIThemeModuleTIMCommon, defaultHex) #define TUITranslationDynamicColor(colorKey, defaultHex) TUIDynamicColor(colorKey, TUIThemeModuleTranslation, defaultHex) +#define TUIVoiceToTextDynamicColor(colorKey, defaultHex) TUIDynamicColor(colorKey, TUIThemeModuleVoiceToText, defaultHex) /** * 动态获取图片 @@ -104,6 +105,7 @@ NS_ASSUME_NONNULL_BEGIN #define TUIGroupNoteBundleThemeImage(imageKey, defaultImageName) TUIGroupNoteDynamicImage(imageKey, TUIGroupNoteCommonBundleImage(defaultImageName)) #define TIMCommonBundleThemeImage(imageKey, defaultImageName) TIMCommonDynamicImage(imageKey, TIMCommonBundleImage(defaultImageName)) #define TUITranslationBundleThemeImage(imageKey, defaultImageName) TUITranslationDynamicImage(imageKey, TUITranslationCommonBundleImage(defaultImageName)) +#define TUIVoiceToTextBundleThemeImage(imageKey, defaultImageName) TUIVoiceToTextDynamicImage(imageKey, TUIVoiceToTextCommonBundleImage(defaultImageName)) #define TUIDynamicImage(imageKey, themeModule, defaultImg) [TUITheme dynamicImage:imageKey module:themeModule defaultImage:defaultImg] #define TUIDemoDynamicImage(imageKey, defaultImg) TUIDynamicImage(imageKey, TUIThemeModuleDemo, defaultImg) @@ -119,6 +121,7 @@ NS_ASSUME_NONNULL_BEGIN #define TUIGroupNoteDynamicImage(imageKey, defaultImg) TUIDynamicImage(imageKey, TUIThemeModuleGroupNote, defaultImg) #define TIMCommonDynamicImage(imageKey, defaultImg) TUIDynamicImage(imageKey, TUIThemeModuleTIMCommon, defaultImg) #define TUITranslationDynamicImage(imageKey, defaultImg) TUIDynamicImage(imageKey, TUIThemeModuleTranslation, defaultImg) +#define TUIVoiceToTextDynamicImage(imageKey, defaultImg) TUIDynamicImage(imageKey, TUIThemeModuleVoiceToText, defaultImg) #define __TUIDefaultBundleImage(imageBundlePath) [UIImage imageWithContentsOfFile:imageBundlePath] #define TUIDemoCommonBundleImage(imageName) __TUIDefaultBundleImage(TUIDemoImagePath(imageName)) @@ -133,6 +136,7 @@ NS_ASSUME_NONNULL_BEGIN #define TUIGroupNoteCommonBundleImage(imageName) __TUIDefaultBundleImage(TUIGroupNoteImagePath(imageName)) #define TIMCommonBundleImage(imageName) __TUIDefaultBundleImage(TIMCommonImagePath(imageName)) #define TUITranslationCommonBundleImage(imageName) __TUIDefaultBundleImage(TUITranslationImagePath(imageName)) +#define TUIVoiceToTextCommonBundleImage(imageName) __TUIDefaultBundleImage(TUIVoiceToTextImagePath(imageName)) /** * 主题模块 @@ -164,6 +168,7 @@ typedef NS_ENUM(NSInteger, TUIThemeModule) { TUIThemeModuleTIMCommon = 0x1 << 18, TUIThemeModuleTranslation = 0x1 << 19, TUIThemeModuleConversationGroup = 0x1 << 20, + TUIThemeModuleVoiceToText = 0x1 << 21, }; @interface TUITheme : NSObject diff --git a/iOS/TUIKit/TUICore/TUITool.h b/iOS/TUIKit/TUICore/TUITool.h index 10d04c571..867c19ff8 100644 --- a/iOS/TUIKit/TUICore/TUITool.h +++ b/iOS/TUIKit/TUICore/TUITool.h @@ -33,6 +33,7 @@ typedef void (^TAsyncImageComplete)(NSString *path, UIImage *image); // msg code convert + (NSString *)convertIMError:(NSInteger)code msg:(NSString *)msg; ++ (void)configIMErrorMap; + (NSString *)genImageName:(NSString *)uuid; + (NSString *)genSnapshotName:(NSString *)uuid; diff --git a/iOS/TUIKit/TUICore/TUITool.m b/iOS/TUIKit/TUICore/TUITool.m index 0d209ae2e..a53779cfb 100644 --- a/iOS/TUIKit/TUICore/TUITool.m +++ b/iOS/TUIKit/TUICore/TUITool.m @@ -7,9 +7,10 @@ // #import -#import "TUIDefine.h" -#import "TUIGlobalization.h" #import "TUILogin.h" +#import "TUIGlobalization.h" +#import "TUIWeakProxy.h" +#import "TUIDefine.h" #import "UIView+TUIToast.h" @import ImSDK_Plus; @@ -21,6 +22,9 @@ static NSMutableDictionary * gIMErrorMsgMap = nil; + (void)initialize { [self setupIMErrorMap]; } ++ (void)configIMErrorMap { + [self.class setupIMErrorMap]; +} + (void)setupIMErrorMap { NSMutableDictionary *map = [NSMutableDictionary dictionary]; gIMErrorMsgMap = map; @@ -549,8 +553,7 @@ static NSMutableDictionary * gIMErrorMsgMap = nil; if (dateFmt == nil) { dateFmt = [[NSDateFormatter alloc] init]; } - NSString *identifer = [TUIGlobalization tk_localizableLanguageKey]; - dateFmt.locale = [NSLocale localeWithLocaleIdentifier:identifer]; + dateFmt.locale = nil; NSCalendar *calendar = [NSCalendar currentCalendar]; calendar.firstWeekday = 7; @@ -571,6 +574,8 @@ static NSMutableDictionary * gIMErrorMsgMap = nil; } else { // Not same day dateFmt.dateFormat = @"EEEE"; + NSString *identifer = [TUIGlobalization getPreferredLanguage]; + dateFmt.locale = [NSLocale localeWithLocaleIdentifier:identifer]; } } else { // Not same weeek @@ -726,7 +731,7 @@ static NSMutableDictionary * gIMErrorMsgMap = nil; if (!enable) { return; } - + TUIWeakProxy *weakVC = [TUIWeakProxy proxyWithTarget:vc]; [[NSNotificationCenter defaultCenter] addObserverForName:TUIKitNotification_onReceivedUnsupportInterfaceError object:nil queue:nil @@ -734,7 +739,9 @@ static NSMutableDictionary * gIMErrorMsgMap = nil; NSDictionary *userInfo = note.userInfo; NSString *service = [userInfo objectForKey:@"service"]; NSString *serviceDesc = [userInfo objectForKey:@"serviceDesc"]; - [TUITool showUnsupportAlertOfService:service serviceDesc:serviceDesc onVC:vc]; + if (weakVC.target) { + [TUITool showUnsupportAlertOfService:service serviceDesc:serviceDesc onVC:weakVC.target]; + } }]; } diff --git a/iOS/TUIKit/TUIGroup/BaseCell/CellData/TUIAddCellData.h b/iOS/TUIKit/TUIGroup/BaseCell/CellData/TUIAddCellData.h deleted file mode 100644 index 6699b136a..000000000 --- a/iOS/TUIKit/TUIGroup/BaseCell/CellData/TUIAddCellData.h +++ /dev/null @@ -1,26 +0,0 @@ -// -// TUIAddCellData.h -// TXIMSDK_TUIKit_iOS -// -// Created by xiangzhang on 2021/6/25. -// Copyright © 2023 Tencent. All rights reserved. -// - -#import - -NS_ASSUME_NONNULL_BEGIN - -typedef NS_ENUM(NSUInteger, TUIAddCellState) { - TAddCell_State_UnSelect, - TAddCell_State_Selected, - TAddCell_State_Solid, -}; - -@interface TUIAddCellData : NSObject -@property(nonatomic, strong) NSString *identifier; -@property(nonatomic, strong) NSString *head; -@property(nonatomic, strong) NSString *name; -@property(nonatomic, assign) TUIAddCellState state; -@end - -NS_ASSUME_NONNULL_END diff --git a/iOS/TUIKit/TUIGroup/BaseCell/CellData/TUIAddCellData.m b/iOS/TUIKit/TUIGroup/BaseCell/CellData/TUIAddCellData.m deleted file mode 100644 index eba776e40..000000000 --- a/iOS/TUIKit/TUIGroup/BaseCell/CellData/TUIAddCellData.m +++ /dev/null @@ -1,13 +0,0 @@ -// -// TUIAddCellData.m -// TXIMSDK_TUIKit_iOS -// -// Created by xiangzhang on 2021/6/25. -// Copyright © 2023 Tencent. All rights reserved. -// - -#import "TUIAddCellData.h" - -@implementation TUIAddCellData - -@end diff --git a/iOS/TUIKit/TUIGroup/BaseCell/CellUI/TUIAddCell.h b/iOS/TUIKit/TUIGroup/BaseCell/CellUI/TUIAddCell.h deleted file mode 100644 index 1946fdeb1..000000000 --- a/iOS/TUIKit/TUIGroup/BaseCell/CellUI/TUIAddCell.h +++ /dev/null @@ -1,18 +0,0 @@ -// -// TAddCell.h -// TUIKit -// -// Created by kennethmiao on 2018/10/15. -// Copyright © 2018年 Tencent. All rights reserved. -// - -#import -#import "TUIAddCellData.h" - -@interface TUIAddCell : UITableViewCell -@property(nonatomic, strong) UIImageView *selectImageView; -@property(nonatomic, strong) UIImageView *headImageView; -@property(nonatomic, strong) UILabel *nameLabel; -+ (CGFloat)getHeight; -- (void)setData:(TUIAddCellData *)data; -@end diff --git a/iOS/TUIKit/TUIGroup/BaseCell/CellUI/TUIAddCell.m b/iOS/TUIKit/TUIGroup/BaseCell/CellUI/TUIAddCell.m deleted file mode 100644 index 508112b9f..000000000 --- a/iOS/TUIKit/TUIGroup/BaseCell/CellUI/TUIAddCell.m +++ /dev/null @@ -1,60 +0,0 @@ -// -// TAddCell.m -// TUIKit -// -// Created by kennethmiao on 2018/10/15. -// Copyright © 2018年 Tencent. All rights reserved. -// - -#import "TUIAddCell.h" -#import - -@implementation TUIAddCell - -- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier { - self = [super initWithStyle:style reuseIdentifier:reuseIdentifier]; - if (self) { - [self setupViews]; - } - return self; -} - -- (void)setupViews { - [self setSeparatorInset:UIEdgeInsetsMake(0, TAddCell_Margin, 0, 0)]; - - CGSize selectSize = TAddCell_Select_Size; - _selectImageView = - [[UIImageView alloc] initWithFrame:CGRectMake(TAddCell_Margin, (TAddCell_Height - selectSize.height) * 0.5, selectSize.width, selectSize.height)]; - _selectImageView.contentMode = UIViewContentModeScaleAspectFit; - [self addSubview:_selectImageView]; - - CGSize headSize = TAddCell_Head_Size; - _headImageView = [[UIImageView alloc] initWithFrame:CGRectMake(_selectImageView.frame.origin.x + _selectImageView.frame.size.width + 2 * TAddCell_Margin, - (TAddCell_Height - headSize.height) * 0.5, headSize.width, headSize.height)]; - _headImageView.contentMode = UIViewContentModeScaleAspectFit; - [self addSubview:_headImageView]; - - CGFloat width = self.frame.size.width - _headImageView.frame.size.width - _headImageView.frame.origin.x - 2 * TAddCell_Margin; - _nameLabel = [[UILabel alloc] - initWithFrame:CGRectMake(_headImageView.frame.origin.x + _headImageView.frame.size.width + TAddCell_Margin, 0, width, TAddCell_Height)]; - _nameLabel.font = [UIFont systemFontOfSize:15]; - _nameLabel.textColor = [UIColor blackColor]; - [self addSubview:_nameLabel]; -} - -+ (CGFloat)getHeight { - return TAddCell_Height; -} - -- (void)setData:(TUIAddCellData *)data { - _headImageView.image = [UIImage imageNamed:data.head]; - _nameLabel.text = data.name; - if (data.state == TAddCell_State_Selected) { - _selectImageView.image = [UIImage imageNamed:TUIGroupImagePath(@"add_selected")]; - } else if (data.state == TAddCell_State_UnSelect) { - _selectImageView.image = [UIImage imageNamed:TUIGroupImagePath(@"add_unselect")]; - } else if (data.state == TAddCell_State_Solid) { - _selectImageView.image = [UIImage imageNamed:TUIGroupImagePath(@"add_solid")]; - } -} -@end diff --git a/iOS/TUIKit/TUIGroup/BaseCell/CellUI/TUIGroupMemberCell.m b/iOS/TUIKit/TUIGroup/BaseCell/CellUI/TUIGroupMemberCell.m index 6dc3d35b5..45d454f0d 100644 --- a/iOS/TUIKit/TUIGroup/BaseCell/CellUI/TUIGroupMemberCell.m +++ b/iOS/TUIKit/TUIGroup/BaseCell/CellUI/TUIGroupMemberCell.m @@ -13,7 +13,6 @@ self = [super initWithFrame:frame]; if (self) { [self setupViews]; - [self defaultLayout]; } return self; } @@ -31,22 +30,9 @@ [self.contentView addSubview:_name]; } -- (void)defaultLayout { - CGSize headSize = [[self class] getSize]; - _head.frame = CGRectMake(0, 0, headSize.width, headSize.width); - _name.frame = CGRectMake(0, _head.frame.origin.y + _head.frame.size.height + TGroupMemberCell_Margin, _head.frame.size.width, TGroupMemberCell_Name_Height); - if ([TUIConfig defaultConfig].avatarType == TAvatarTypeRounded) { - _head.layer.masksToBounds = YES; - _head.layer.cornerRadius = _head.frame.size.height / 2; - } else if ([TUIConfig defaultConfig].avatarType == TAvatarTypeRadiusCorner) { - _head.layer.masksToBounds = YES; - _head.layer.cornerRadius = [TUIConfig defaultConfig].avatarCornerRadius; - } -} - - (void)setData:(TUIGroupMemberCellData *)data { _data = data; - + if (data.avatarUrl) { [self.head sd_setImageWithURL:[NSURL URLWithString:data.avatarUrl] placeholderImage:data.avatarImage ?: DefaultAvatarImage]; } else { @@ -61,9 +47,45 @@ } else { self.name.text = data.identifier; } - [self defaultLayout]; + + // tell constraints they need updating + [self setNeedsUpdateConstraints]; + + // update constraints now so we can animate the change + [self updateConstraintsIfNeeded]; + + [self layoutIfNeeded]; + +} ++ (BOOL)requiresConstraintBasedLayout { + return YES; } +// this is Apple's recommended place for adding/updating constraints +- (void)updateConstraints { + + [super updateConstraints]; + CGSize headSize = [[self class] getSize]; + [_head mas_remakeConstraints:^(MASConstraintMaker *make) { + make.leading.top.mas_equalTo(self.contentView); + make.width.mas_equalTo(headSize.width); + make.height.mas_equalTo(headSize.width); + }]; + [_name mas_remakeConstraints:^(MASConstraintMaker *make) { + make.leading.mas_equalTo(self.head); + make.top.mas_equalTo(self.head.mas_bottom).mas_offset(TGroupMemberCell_Margin); + make.width.mas_equalTo(headSize.width); + make.height.mas_equalTo(TGroupMemberCell_Name_Height); + }]; + if ([TUIConfig defaultConfig].avatarType == TAvatarTypeRounded) { + _head.layer.masksToBounds = YES; + _head.layer.cornerRadius = _head.frame.size.height / 2; + } else if ([TUIConfig defaultConfig].avatarType == TAvatarTypeRadiusCorner) { + _head.layer.masksToBounds = YES; + _head.layer.cornerRadius = [TUIConfig defaultConfig].avatarCornerRadius; + } + +} + (CGSize)getSize { CGSize headSize = TGroupMemberCell_Head_Size; if (headSize.width * TGroupMembersCell_Column_Count + TGroupMembersCell_Margin * (TGroupMembersCell_Column_Count + 1) > Screen_Width) { diff --git a/iOS/TUIKit/TUIGroup/BaseCell/CellUI/TUIGroupNoticeCell.m b/iOS/TUIKit/TUIGroup/BaseCell/CellUI/TUIGroupNoticeCell.m index ff0977a62..6983380f2 100644 --- a/iOS/TUIKit/TUIGroup/BaseCell/CellUI/TUIGroupNoticeCell.m +++ b/iOS/TUIKit/TUIGroup/BaseCell/CellUI/TUIGroupNoticeCell.m @@ -8,6 +8,7 @@ #import "TUIGroupNoticeCell.h" #import +#import @implementation TUIGroupNoticeCell @@ -48,20 +49,41 @@ self.nameLabel.text = cellData.name; self.descLabel.text = cellData.desc; + // tell constraints they need updating + [self setNeedsUpdateConstraints]; + + // update constraints now so we can animate the change + [self updateConstraintsIfNeeded]; + + [self layoutIfNeeded]; } ++ (BOOL)requiresConstraintBasedLayout { + return YES; +} + +// this is Apple's recommended place for adding/updating constraints +- (void)updateConstraints { + + [super updateConstraints]; + + [self.nameLabel sizeToFit]; + [self.nameLabel mas_remakeConstraints:^(MASConstraintMaker *make) { + make.leading.mas_equalTo(20); + make.top.mas_equalTo(12); + make.trailing.mas_lessThanOrEqualTo(self.contentView).mas_offset(-20); + make.size.mas_equalTo(self.nameLabel.frame.size); + }]; + [self.descLabel sizeToFit]; + [self.descLabel mas_remakeConstraints:^(MASConstraintMaker *make) { + make.leading.mas_equalTo(self.nameLabel); + make.top.mas_equalTo(self.nameLabel.mas_bottom).mas_offset(4); + make.trailing.mas_lessThanOrEqualTo(self.contentView).mas_offset(-30); + make.size.mas_equalTo(self.descLabel.frame.size); + }]; +} - (void)layoutSubviews { [super layoutSubviews]; - - [self.nameLabel sizeToFit]; - self.nameLabel.mm_x = 20.0; - self.nameLabel.mm_y = 12.0; - self.nameLabel.mm_flexToRight(20); - - [self.descLabel sizeToFit]; - self.descLabel.mm_y = CGRectGetMaxY(self.nameLabel.frame) + 4; - self.descLabel.mm_x = self.nameLabel.mm_x; - self.descLabel.mm_flexToRight(30); } - (UILabel *)nameLabel { diff --git a/iOS/TUIKit/TUIGroup/BaseCell/CellUI/TUIMemberInfoCell.m b/iOS/TUIKit/TUIGroup/BaseCell/CellUI/TUIMemberInfoCell.m index d95d6dfa2..cee641e43 100644 --- a/iOS/TUIKit/TUIGroup/BaseCell/CellUI/TUIMemberInfoCell.m +++ b/iOS/TUIKit/TUIGroup/BaseCell/CellUI/TUIMemberInfoCell.m @@ -66,7 +66,7 @@ - (void)setData:(TUIMemberInfoCellData *)data { _data = data; - + UIImage *defaultImage = DefaultAvatarImage; [self.avatarImageView sd_setImageWithURL:[NSURL URLWithString:data.avatarUrl] placeholderImage:data.avatar ?: defaultImage]; self.nameLabel.text = data.name; @@ -79,25 +79,47 @@ self.tagView.tagname.text = @""; self.tagView.hidden = YES; } - + if (data.showAccessory) { - self.accessoryType = UITableViewCellAccessoryDisclosureIndicator; - + self.accessoryType = UITableViewCellAccessoryDisclosureIndicator; } else { self.accessoryType = UITableViewCellAccessoryNone; } - [self updateUI]; + + // tell constraints they need updating + [self setNeedsUpdateConstraints]; + + // update constraints now so we can animate the change + [self updateConstraintsIfNeeded]; + + [self layoutIfNeeded]; + } -- (void)updateUI { ++ (BOOL)requiresConstraintBasedLayout { + return YES; +} + +// this is Apple's recommended place for adding/updating constraints +- (void)updateConstraints { + + [super updateConstraints]; + if (self.data.style == TUIMemberInfoCellStyleAdd) { - self.avatarImageView.mm_width(20.0 * kScale).mm_height(20.0 * kScale); - self.avatarImageView.mm_left(18.0 * kScale); + + [self.avatarImageView mas_remakeConstraints:^(MASConstraintMaker *make) { + make.leading.mas_equalTo(self.contentView.mas_leading).mas_offset(18.0 * kScale); + make.centerY.mas_equalTo(self.contentView); + make.width.height.mas_equalTo(20.0 * kScale); + }]; self.nameLabel.font = [UIFont systemFontOfSize:16.0 * kScale]; self.nameLabel.textColor = TIMCommonDynamicColor(@"form_value_text_color", @"#000000"); } else { - self.avatarImageView.mm_width(34.0 * kScale).mm_height(34.0 * kScale); - self.avatarImageView.mm_left(16.0 * kScale); + [self.avatarImageView mas_remakeConstraints:^(MASConstraintMaker *make) { + make.leading.mas_equalTo(self.contentView.mas_leading).mas_offset(16.0 * kScale); + make.centerY.mas_equalTo(self.contentView); + make.width.height.mas_equalTo(34.0 * kScale); + }]; self.nameLabel.font = [UIFont systemFontOfSize:16.0 * kScale]; self.nameLabel.textColor = TIMCommonDynamicColor(@"form_value_text_color", @"#000000"); } @@ -109,14 +131,27 @@ self.avatarImageView.layer.masksToBounds = YES; self.avatarImageView.layer.cornerRadius = [TUIConfig defaultConfig].avatarCornerRadius; } - - self.avatarImageView.mm_centerY = self.contentView.mm_centerY; [self.nameLabel sizeToFit]; - self.nameLabel.mm_height(self.contentView.mm_h).mm_left(CGRectGetMaxX(self.avatarImageView.frame) + 14); + [self.nameLabel mas_remakeConstraints:^(MASConstraintMaker *make) { + make.leading.mas_equalTo(self.avatarImageView.mas_trailing).mas_offset(14); + make.centerY.mas_equalTo(self.contentView); + make.size.mas_equalTo(self.nameLabel.frame.size); + if (self.tagView.tagname.text.length > 0) { + make.trailing.mas_lessThanOrEqualTo(self.tagView.mas_trailing).mas_offset(- 2.0 * kScale); + } + else { + make.trailing.mas_lessThanOrEqualTo(self.contentView.mas_trailing).mas_offset(- 2.0 * kScale); + } + }]; [self.tagView.tagname sizeToFit]; - self.tagView.frame = CGRectMake(self.nameLabel.frame.origin.x + self.nameLabel.frame.size.width + kScale390(10), 0, - self.tagView.tagname.frame.size.width + kScale390(16), kScale390(15)); - self.tagView.mm_centerY = self.contentView.mm_centerY; + [self.tagView mas_remakeConstraints:^(MASConstraintMaker *make) { + make.leading.mas_equalTo(self.nameLabel.mas_trailing).mas_offset(kScale390(10)); + make.width.mas_equalTo(self.tagView.tagname.frame.size.width + kScale390(16)); + make.height.mas_equalTo(kScale390(15)); + make.centerY.mas_equalTo(self.contentView.mas_centerY); + make.trailing.mas_lessThanOrEqualTo(self.contentView.mas_trailing).mas_offset(- 2.0 * kScale); + + }]; } - (UIImageView *)avatarImageView { diff --git a/iOS/TUIKit/TUIGroup/BaseCell/CellUI/TUISelectGroupMemberCell.m b/iOS/TUIKit/TUIGroup/BaseCell/CellUI/TUISelectGroupMemberCell.m index 7048c8dad..3177e0837 100644 --- a/iOS/TUIKit/TUIGroup/BaseCell/CellUI/TUISelectGroupMemberCell.m +++ b/iOS/TUIKit/TUIGroup/BaseCell/CellUI/TUISelectGroupMemberCell.m @@ -27,6 +27,7 @@ _userImg = [[UIImageView alloc] initWithFrame:CGRectZero]; [self addSubview:_userImg]; _nameLabel = [[UILabel alloc] initWithFrame:CGRectZero]; + _nameLabel.textAlignment = isRTL()?NSTextAlignmentRight:NSTextAlignmentLeft; [self addSubview:_nameLabel]; self.selectionStyle = UITableViewCellSelectionStyleNone; } @@ -38,12 +39,45 @@ _selectedMark.image = isSelect ? [UIImage imageNamed:TUIGroupImagePath(@"ic_selected")] : [UIImage imageNamed:TUIGroupImagePath(@"ic_unselect")]; [_userImg sd_setImageWithURL:[NSURL URLWithString:model.avatar] placeholderImage:DefaultAvatarImage]; _nameLabel.text = model.name; + // tell constraints they need updating + [self setNeedsUpdateConstraints]; + + // update constraints now so we can animate the change + [self updateConstraintsIfNeeded]; + + [self layoutIfNeeded]; + } ++ (BOOL)requiresConstraintBasedLayout { + return YES; +} + +// this is Apple's recommended place for adding/updating constraints +- (void)updateConstraints { + + [super updateConstraints]; + + [_selectedMark mas_remakeConstraints:^(MASConstraintMaker *make) { + make.width.height.mas_equalTo(20); + make.leading.mas_equalTo(self.contentView).mas_offset(12); + make.centerY.mas_equalTo(self.contentView); + }]; + + [_userImg mas_remakeConstraints:^(MASConstraintMaker *make) { + make.width.height.mas_equalTo(32); + make.leading.mas_equalTo(_selectedMark.mas_trailing).mas_offset(12); + make.centerY.mas_equalTo(self.contentView); + }]; + [_nameLabel sizeToFit]; + [_nameLabel mas_remakeConstraints:^(MASConstraintMaker *make) { + make.leading.mas_equalTo(_userImg.mas_trailing).mas_offset(12); + make.trailing.mas_equalTo(self.contentView.mas_trailing); + make.height.mas_equalTo(self.contentView); + make.centerY.mas_equalTo(self.contentView); + }]; +} - (void)layoutSubviews { [super layoutSubviews]; - _selectedMark.mm_width(12).mm_height(12).mm_left(12).mm__centerY(self.mm_h / 2); - _userImg.mm_width(32).mm_height(32).mm_left(_selectedMark.mm_maxX + 12).mm__centerY(self.mm_h / 2); - _nameLabel.mm_height(self.mm_h).mm_left(_userImg.mm_maxX + 12).mm_flexToRight(0); } @end diff --git a/iOS/TUIKit/TUIGroup/BaseDataProvider/TUIGroupInfoDataProvider.m b/iOS/TUIKit/TUIGroup/BaseDataProvider/TUIGroupInfoDataProvider.m index e24c04258..8faae1096 100644 --- a/iOS/TUIKit/TUIGroup/BaseDataProvider/TUIGroupInfoDataProvider.m +++ b/iOS/TUIKit/TUIGroup/BaseDataProvider/TUIGroupInfoDataProvider.m @@ -5,7 +5,6 @@ #import #import #import "TIMGroupInfo+TUIDataProvider.h" -#import "TUIAddCellData.h" #import "TUIGroupInfoDataProvider.h" #import "TUIGroupMemberCellData.h" #import "TUIGroupMembersCellData.h" diff --git a/iOS/TUIKit/TUIGroup/BaseDataProvider/TUIGroupManageDataProvider.m b/iOS/TUIKit/TUIGroup/BaseDataProvider/TUIGroupManageDataProvider.m index e70eca980..3953cb1c3 100644 --- a/iOS/TUIKit/TUIGroup/BaseDataProvider/TUIGroupManageDataProvider.m +++ b/iOS/TUIKit/TUIGroup/BaseDataProvider/TUIGroupManageDataProvider.m @@ -9,7 +9,6 @@ #import "TUIGroupManageDataProvider.h" #import #import -#import "TUIAddCellData.h" #import "TUIMemberInfoCellData.h" #import "TUISelectGroupMemberCell.h" diff --git a/iOS/TUIKit/TUIGroup/Resources/TUIGroup.bundle/add_selected@2x.png b/iOS/TUIKit/TUIGroup/Resources/TUIGroup.bundle/add_selected@2x.png index 2b7c1ca62..892a9a71c 100644 Binary files a/iOS/TUIKit/TUIGroup/Resources/TUIGroup.bundle/add_selected@2x.png and b/iOS/TUIKit/TUIGroup/Resources/TUIGroup.bundle/add_selected@2x.png differ diff --git a/iOS/TUIKit/TUIGroup/Resources/TUIGroup.bundle/add_selected@3x.png b/iOS/TUIKit/TUIGroup/Resources/TUIGroup.bundle/add_selected@3x.png index ca0f6c3c7..f491e70ed 100644 Binary files a/iOS/TUIKit/TUIGroup/Resources/TUIGroup.bundle/add_selected@3x.png and b/iOS/TUIKit/TUIGroup/Resources/TUIGroup.bundle/add_selected@3x.png differ diff --git a/iOS/TUIKit/TUIGroup/Resources/TUIGroup.bundle/add_solid@2x.png b/iOS/TUIKit/TUIGroup/Resources/TUIGroup.bundle/add_solid@2x.png index c3bb6e0a3..b53e0c79d 100644 Binary files a/iOS/TUIKit/TUIGroup/Resources/TUIGroup.bundle/add_solid@2x.png and b/iOS/TUIKit/TUIGroup/Resources/TUIGroup.bundle/add_solid@2x.png differ diff --git a/iOS/TUIKit/TUIGroup/Resources/TUIGroup.bundle/add_solid@3x.png b/iOS/TUIKit/TUIGroup/Resources/TUIGroup.bundle/add_solid@3x.png index c1a94329e..7f203456b 100644 Binary files a/iOS/TUIKit/TUIGroup/Resources/TUIGroup.bundle/add_solid@3x.png and b/iOS/TUIKit/TUIGroup/Resources/TUIGroup.bundle/add_solid@3x.png differ diff --git a/iOS/TUIKit/TUIGroup/Resources/TUIGroup.bundle/add_unselect@2x.png b/iOS/TUIKit/TUIGroup/Resources/TUIGroup.bundle/add_unselect@2x.png index c061a1641..47ce633b9 100644 Binary files a/iOS/TUIKit/TUIGroup/Resources/TUIGroup.bundle/add_unselect@2x.png and b/iOS/TUIKit/TUIGroup/Resources/TUIGroup.bundle/add_unselect@2x.png differ diff --git a/iOS/TUIKit/TUIGroup/Resources/TUIGroup.bundle/add_unselect@3x.png b/iOS/TUIKit/TUIGroup/Resources/TUIGroup.bundle/add_unselect@3x.png index 394c16d83..50c11b492 100644 Binary files a/iOS/TUIKit/TUIGroup/Resources/TUIGroup.bundle/add_unselect@3x.png and b/iOS/TUIKit/TUIGroup/Resources/TUIGroup.bundle/add_unselect@3x.png differ diff --git a/iOS/TUIKit/TUIGroup/Resources/TUIGroup.bundle/back@3x.png b/iOS/TUIKit/TUIGroup/Resources/TUIGroup.bundle/back@3x.png index 069f4b13d..feed5cbeb 100644 Binary files a/iOS/TUIKit/TUIGroup/Resources/TUIGroup.bundle/back@3x.png and b/iOS/TUIKit/TUIGroup/Resources/TUIGroup.bundle/back@3x.png differ diff --git a/iOS/TUIKit/TUIGroup/Resources/TUIGroup.bundle/chat_nav_more_menu@3x.png b/iOS/TUIKit/TUIGroup/Resources/TUIGroup.bundle/chat_nav_more_menu@3x.png index 84b00e342..3dabae0da 100644 Binary files a/iOS/TUIKit/TUIGroup/Resources/TUIGroup.bundle/chat_nav_more_menu@3x.png and b/iOS/TUIKit/TUIGroup/Resources/TUIGroup.bundle/chat_nav_more_menu@3x.png differ diff --git a/iOS/TUIKit/TUIGroup/Resources/TUIGroup.bundle/female.png b/iOS/TUIKit/TUIGroup/Resources/TUIGroup.bundle/female.png index 0dc10a4c3..1c15d169a 100755 Binary files a/iOS/TUIKit/TUIGroup/Resources/TUIGroup.bundle/female.png and b/iOS/TUIKit/TUIGroup/Resources/TUIGroup.bundle/female.png differ diff --git a/iOS/TUIKit/TUIGroup/Resources/TUIGroup.bundle/female@2x.png b/iOS/TUIKit/TUIGroup/Resources/TUIGroup.bundle/female@2x.png index 6a463da41..2ecaaa1b7 100755 Binary files a/iOS/TUIKit/TUIGroup/Resources/TUIGroup.bundle/female@2x.png and b/iOS/TUIKit/TUIGroup/Resources/TUIGroup.bundle/female@2x.png differ diff --git a/iOS/TUIKit/TUIGroup/Resources/TUIGroup.bundle/female@3x.png b/iOS/TUIKit/TUIGroup/Resources/TUIGroup.bundle/female@3x.png index 4527e07bc..e3cb5e977 100755 Binary files a/iOS/TUIKit/TUIGroup/Resources/TUIGroup.bundle/female@3x.png and b/iOS/TUIKit/TUIGroup/Resources/TUIGroup.bundle/female@3x.png differ diff --git a/iOS/TUIKit/TUIGroup/Resources/TUIGroup.bundle/ic_close_poppings@2x.png b/iOS/TUIKit/TUIGroup/Resources/TUIGroup.bundle/ic_close_poppings@2x.png index 93ab6fba4..4b06587cb 100644 Binary files a/iOS/TUIKit/TUIGroup/Resources/TUIGroup.bundle/ic_close_poppings@2x.png and b/iOS/TUIKit/TUIGroup/Resources/TUIGroup.bundle/ic_close_poppings@2x.png differ diff --git a/iOS/TUIKit/TUIGroup/Resources/TUIGroup.bundle/ic_selected@2x.png b/iOS/TUIKit/TUIGroup/Resources/TUIGroup.bundle/ic_selected@2x.png index c9dfae173..7660ff18a 100644 Binary files a/iOS/TUIKit/TUIGroup/Resources/TUIGroup.bundle/ic_selected@2x.png and b/iOS/TUIKit/TUIGroup/Resources/TUIGroup.bundle/ic_selected@2x.png differ diff --git a/iOS/TUIKit/TUIGroup/Resources/TUIGroup.bundle/ic_selected@3x.png b/iOS/TUIKit/TUIGroup/Resources/TUIGroup.bundle/ic_selected@3x.png index d6f659cae..77686dfa2 100644 Binary files a/iOS/TUIKit/TUIGroup/Resources/TUIGroup.bundle/ic_selected@3x.png and b/iOS/TUIKit/TUIGroup/Resources/TUIGroup.bundle/ic_selected@3x.png differ diff --git a/iOS/TUIKit/TUIGroup/Resources/TUIGroup.bundle/ic_unselect@2x.png b/iOS/TUIKit/TUIGroup/Resources/TUIGroup.bundle/ic_unselect@2x.png index ec55ba2ab..c83ad1eb4 100644 Binary files a/iOS/TUIKit/TUIGroup/Resources/TUIGroup.bundle/ic_unselect@2x.png and b/iOS/TUIKit/TUIGroup/Resources/TUIGroup.bundle/ic_unselect@2x.png differ diff --git a/iOS/TUIKit/TUIGroup/Resources/TUIGroup.bundle/ic_unselect@3x.png b/iOS/TUIKit/TUIGroup/Resources/TUIGroup.bundle/ic_unselect@3x.png index d346d948f..343de3fef 100644 Binary files a/iOS/TUIKit/TUIGroup/Resources/TUIGroup.bundle/ic_unselect@3x.png and b/iOS/TUIKit/TUIGroup/Resources/TUIGroup.bundle/ic_unselect@3x.png differ diff --git a/iOS/TUIKit/TUIGroup/Resources/TUIGroup.bundle/icon_add@2x.png b/iOS/TUIKit/TUIGroup/Resources/TUIGroup.bundle/icon_add@2x.png index f57174bf7..ac6f48f92 100644 Binary files a/iOS/TUIKit/TUIGroup/Resources/TUIGroup.bundle/icon_add@2x.png and b/iOS/TUIKit/TUIGroup/Resources/TUIGroup.bundle/icon_add@2x.png differ diff --git a/iOS/TUIKit/TUIGroup/Resources/TUIGroup.bundle/icon_add@3x.png b/iOS/TUIKit/TUIGroup/Resources/TUIGroup.bundle/icon_add@3x.png index 676d97a97..015ebec96 100644 Binary files a/iOS/TUIKit/TUIGroup/Resources/TUIGroup.bundle/icon_add@3x.png and b/iOS/TUIKit/TUIGroup/Resources/TUIGroup.bundle/icon_add@3x.png differ diff --git a/iOS/TUIKit/TUIGroup/Resources/TUIGroup.bundle/icon_group_Add@3x.png b/iOS/TUIKit/TUIGroup/Resources/TUIGroup.bundle/icon_group_Add@3x.png index 6dfb26db1..b46e6666e 100644 Binary files a/iOS/TUIKit/TUIGroup/Resources/TUIGroup.bundle/icon_group_Add@3x.png and b/iOS/TUIKit/TUIGroup/Resources/TUIGroup.bundle/icon_group_Add@3x.png differ diff --git a/iOS/TUIKit/TUIGroup/Resources/TUIGroup.bundle/icon_group_edit@2x.png b/iOS/TUIKit/TUIGroup/Resources/TUIGroup.bundle/icon_group_edit@2x.png index 4302350df..0e31ab269 100644 Binary files a/iOS/TUIKit/TUIGroup/Resources/TUIGroup.bundle/icon_group_edit@2x.png and b/iOS/TUIKit/TUIGroup/Resources/TUIGroup.bundle/icon_group_edit@2x.png differ diff --git a/iOS/TUIKit/TUIGroup/Resources/TUIGroup.bundle/male.png b/iOS/TUIKit/TUIGroup/Resources/TUIGroup.bundle/male.png index be4ec3f04..602fa404e 100644 Binary files a/iOS/TUIKit/TUIGroup/Resources/TUIGroup.bundle/male.png and b/iOS/TUIKit/TUIGroup/Resources/TUIGroup.bundle/male.png differ diff --git a/iOS/TUIKit/TUIGroup/Resources/TUIGroup.bundle/male@2x.png b/iOS/TUIKit/TUIGroup/Resources/TUIGroup.bundle/male@2x.png index 081fb92a1..8750cb006 100644 Binary files a/iOS/TUIKit/TUIGroup/Resources/TUIGroup.bundle/male@2x.png and b/iOS/TUIKit/TUIGroup/Resources/TUIGroup.bundle/male@2x.png differ diff --git a/iOS/TUIKit/TUIGroup/Resources/TUIGroup.bundle/male@3x.png b/iOS/TUIKit/TUIGroup/Resources/TUIGroup.bundle/male@3x.png index fe4258af3..bb7b4c502 100644 Binary files a/iOS/TUIKit/TUIGroup/Resources/TUIGroup.bundle/male@3x.png and b/iOS/TUIKit/TUIGroup/Resources/TUIGroup.bundle/male@3x.png differ diff --git a/iOS/TUIKit/TUIGroup/Resources/TUIGroupTheme.bundle/dark/resource/bg.png b/iOS/TUIKit/TUIGroup/Resources/TUIGroupTheme.bundle/dark/resource/bg.png index 7077009d5..a4d07d07a 100644 Binary files a/iOS/TUIKit/TUIGroup/Resources/TUIGroupTheme.bundle/dark/resource/bg.png and b/iOS/TUIKit/TUIGroup/Resources/TUIGroupTheme.bundle/dark/resource/bg.png differ diff --git a/iOS/TUIKit/TUIGroup/Resources/TUIGroupTheme.bundle/dark/resource/chat_nav_more_menu@3x.png b/iOS/TUIKit/TUIGroup/Resources/TUIGroupTheme.bundle/dark/resource/chat_nav_more_menu@3x.png index cbc3fef2a..62f791715 100644 Binary files a/iOS/TUIKit/TUIGroup/Resources/TUIGroupTheme.bundle/dark/resource/chat_nav_more_menu@3x.png and b/iOS/TUIKit/TUIGroup/Resources/TUIGroupTheme.bundle/dark/resource/chat_nav_more_menu@3x.png differ diff --git a/iOS/TUIKit/TUIGroup/Resources/TUIGroupTheme.bundle/dark/resource/nav_back@3x.png b/iOS/TUIKit/TUIGroup/Resources/TUIGroupTheme.bundle/dark/resource/nav_back@3x.png index 68ced6688..3e9caefc9 100644 Binary files a/iOS/TUIKit/TUIGroup/Resources/TUIGroupTheme.bundle/dark/resource/nav_back@3x.png and b/iOS/TUIKit/TUIGroup/Resources/TUIGroupTheme.bundle/dark/resource/nav_back@3x.png differ diff --git a/iOS/TUIKit/TUIGroup/Resources/TUIGroupTheme.bundle/light/resource/bg.png b/iOS/TUIKit/TUIGroup/Resources/TUIGroupTheme.bundle/light/resource/bg.png index 87d7c51a0..292267063 100644 Binary files a/iOS/TUIKit/TUIGroup/Resources/TUIGroupTheme.bundle/light/resource/bg.png and b/iOS/TUIKit/TUIGroup/Resources/TUIGroupTheme.bundle/light/resource/bg.png differ diff --git a/iOS/TUIKit/TUIGroup/Resources/TUIGroupTheme.bundle/light/resource/chat_nav_more_menu@3x.png b/iOS/TUIKit/TUIGroup/Resources/TUIGroupTheme.bundle/light/resource/chat_nav_more_menu@3x.png index 84b00e342..3dabae0da 100644 Binary files a/iOS/TUIKit/TUIGroup/Resources/TUIGroupTheme.bundle/light/resource/chat_nav_more_menu@3x.png and b/iOS/TUIKit/TUIGroup/Resources/TUIGroupTheme.bundle/light/resource/chat_nav_more_menu@3x.png differ diff --git a/iOS/TUIKit/TUIGroup/Resources/TUIGroupTheme.bundle/light/resource/nav_back@3x.png b/iOS/TUIKit/TUIGroup/Resources/TUIGroupTheme.bundle/light/resource/nav_back@3x.png index 3d8c99915..64874680e 100644 Binary files a/iOS/TUIKit/TUIGroup/Resources/TUIGroupTheme.bundle/light/resource/nav_back@3x.png and b/iOS/TUIKit/TUIGroup/Resources/TUIGroupTheme.bundle/light/resource/nav_back@3x.png differ diff --git a/iOS/TUIKit/TUIGroup/Resources/TUIGroupTheme.bundle/lively/resource/bg.png b/iOS/TUIKit/TUIGroup/Resources/TUIGroupTheme.bundle/lively/resource/bg.png index 62c1d746f..acfbbf52c 100644 Binary files a/iOS/TUIKit/TUIGroup/Resources/TUIGroupTheme.bundle/lively/resource/bg.png and b/iOS/TUIKit/TUIGroup/Resources/TUIGroupTheme.bundle/lively/resource/bg.png differ diff --git a/iOS/TUIKit/TUIGroup/Resources/TUIGroupTheme.bundle/lively/resource/chat_nav_more_menu@3x.png b/iOS/TUIKit/TUIGroup/Resources/TUIGroupTheme.bundle/lively/resource/chat_nav_more_menu@3x.png index cbc3fef2a..bb7a7f278 100644 Binary files a/iOS/TUIKit/TUIGroup/Resources/TUIGroupTheme.bundle/lively/resource/chat_nav_more_menu@3x.png and b/iOS/TUIKit/TUIGroup/Resources/TUIGroupTheme.bundle/lively/resource/chat_nav_more_menu@3x.png differ diff --git a/iOS/TUIKit/TUIGroup/Resources/TUIGroupTheme.bundle/lively/resource/nav_back@3x.png b/iOS/TUIKit/TUIGroup/Resources/TUIGroupTheme.bundle/lively/resource/nav_back@3x.png index 20726344a..1410968a0 100644 Binary files a/iOS/TUIKit/TUIGroup/Resources/TUIGroupTheme.bundle/lively/resource/nav_back@3x.png and b/iOS/TUIKit/TUIGroup/Resources/TUIGroupTheme.bundle/lively/resource/nav_back@3x.png differ diff --git a/iOS/TUIKit/TUIGroup/Resources/TUIGroupTheme.bundle/serious/resource/bg.png b/iOS/TUIKit/TUIGroup/Resources/TUIGroupTheme.bundle/serious/resource/bg.png index ccaf89e4a..0ad7159f3 100644 Binary files a/iOS/TUIKit/TUIGroup/Resources/TUIGroupTheme.bundle/serious/resource/bg.png and b/iOS/TUIKit/TUIGroup/Resources/TUIGroupTheme.bundle/serious/resource/bg.png differ diff --git a/iOS/TUIKit/TUIGroup/Resources/TUIGroupTheme.bundle/serious/resource/chat_nav_more_menu@3x.png b/iOS/TUIKit/TUIGroup/Resources/TUIGroupTheme.bundle/serious/resource/chat_nav_more_menu@3x.png index cbc3fef2a..97445f14f 100644 Binary files a/iOS/TUIKit/TUIGroup/Resources/TUIGroupTheme.bundle/serious/resource/chat_nav_more_menu@3x.png and b/iOS/TUIKit/TUIGroup/Resources/TUIGroupTheme.bundle/serious/resource/chat_nav_more_menu@3x.png differ diff --git a/iOS/TUIKit/TUIGroup/Resources/TUIGroupTheme.bundle/serious/resource/nav_back@3x.png b/iOS/TUIKit/TUIGroup/Resources/TUIGroupTheme.bundle/serious/resource/nav_back@3x.png index 20726344a..1410968a0 100644 Binary files a/iOS/TUIKit/TUIGroup/Resources/TUIGroupTheme.bundle/serious/resource/nav_back@3x.png and b/iOS/TUIKit/TUIGroup/Resources/TUIGroupTheme.bundle/serious/resource/nav_back@3x.png differ diff --git a/iOS/TUIKit/TUIGroup/TUIGroup.podspec b/iOS/TUIKit/TUIGroup/TUIGroup.podspec index c9386376e..1266841af 100644 --- a/iOS/TUIKit/TUIGroup/TUIGroup.podspec +++ b/iOS/TUIKit/TUIGroup/TUIGroup.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |spec| spec.name = 'TUIGroup' - spec.version = '7.4.4643' + spec.version = '7.5.4852' spec.platform = :ios spec.ios.deployment_target = '9.0' spec.license = { :type => 'Proprietary', diff --git a/iOS/TUIKit/TUIGroup/UI_Classic/UI/TUIGroupInfoController.m b/iOS/TUIKit/TUIGroup/UI_Classic/UI/TUIGroupInfoController.m index 3c991b60c..edda24fb1 100644 --- a/iOS/TUIKit/TUIGroup/UI_Classic/UI/TUIGroupInfoController.m +++ b/iOS/TUIKit/TUIGroup/UI_Classic/UI/TUIGroupInfoController.m @@ -7,7 +7,6 @@ #import #import #import "TIMGroupInfo+TUIDataProvider.h" -#import "TUIAddCell.h" #import "TUIGroupInfoDataProvider.h" #import "TUIGroupManageController.h" #import "TUIGroupMemberCell.h" diff --git a/iOS/TUIKit/TUIGroup/UI_Classic/UI/TUIGroupManageController.m b/iOS/TUIKit/TUIGroup/UI_Classic/UI/TUIGroupManageController.m index b9b96a3dd..a240a32dc 100644 --- a/iOS/TUIKit/TUIGroup/UI_Classic/UI/TUIGroupManageController.m +++ b/iOS/TUIKit/TUIGroup/UI_Classic/UI/TUIGroupManageController.m @@ -9,8 +9,6 @@ #import "TUIGroupManageController.h" #import #import -#import "TUIAddCell.h" -#import "TUIAddCellData.h" #import "TUIGroupManageDataProvider.h" #import "TUIMemberInfoCell.h" #import "TUIMemberInfoCellData.h" @@ -143,9 +141,6 @@ } else if ([data isKindOfClass:TUICommonSwitchCellData.class]) { cell = [[TUICommonSwitchCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:NSStringFromClass(TUICommonSwitchCell.class)]; [(TUICommonSwitchCell *)cell fillWithData:(TUICommonSwitchCellData *)data]; - } else if ([data isKindOfClass:TUIAddCellData.class]) { - cell = [[TUIAddCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:NSStringFromClass(TUIAddCell.class)]; - [(TUIAddCell *)cell setData:(TUIAddCellData *)data]; } else if ([data isKindOfClass:TUIMemberInfoCellData.class]) { cell = [[TUIMemberInfoCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:NSStringFromClass(TUIMemberInfoCell.class)]; [(TUIMemberInfoCell *)cell setData:(TUIMemberInfoCellData *)data]; diff --git a/iOS/TUIKit/TUIGroup/UI_Classic/UI/TUIGroupMemberController.m b/iOS/TUIKit/TUIGroup/UI_Classic/UI/TUIGroupMemberController.m index 82552f733..346ac7a45 100644 --- a/iOS/TUIKit/TUIGroup/UI_Classic/UI/TUIGroupMemberController.m +++ b/iOS/TUIKit/TUIGroup/UI_Classic/UI/TUIGroupMemberController.m @@ -10,7 +10,6 @@ #import #import #import "TIMGroupInfo+TUIDataProvider.h" -#import "TUIAddCell.h" #import "TUIGroupMemberCell.h" #import "TUIGroupMemberDataProvider.h" @@ -55,6 +54,7 @@ // left UIImage *image = TUIGroupDynamicImage(@"group_nav_back_img", [UIImage imageNamed:TUIGroupImagePath(@"back")]); + image = [image rtl_imageFlippedForRightToLeftLayoutDirection]; UIButton *leftButton = [[UIButton alloc] initWithFrame:CGRectMake(0, 0, 30, 30)]; [leftButton addTarget:self action:@selector(leftBarButtonClick) forControlEvents:UIControlEventTouchUpInside]; [leftButton setImage:image forState:UIControlStateNormal]; diff --git a/iOS/TUIKit/TUIGroup/UI_Classic/UI/TUIGroupNoticeController.m b/iOS/TUIKit/TUIGroup/UI_Classic/UI/TUIGroupNoticeController.m index 3560fb2aa..1fb420044 100644 --- a/iOS/TUIKit/TUIGroup/UI_Classic/UI/TUIGroupNoticeController.m +++ b/iOS/TUIKit/TUIGroup/UI_Classic/UI/TUIGroupNoticeController.m @@ -96,6 +96,7 @@ - (UITextView *)textView { if (_textView == nil) { _textView = [[UITextView alloc] init]; + _textView.textAlignment = isRTL()?NSTextAlignmentRight:NSTextAlignmentLeft; _textView.backgroundColor = TIMCommonDynamicColor(@"controller_bg_color", @"#F2F3F5"); _textView.textColor = TIMCommonDynamicColor(@"form_title_color", @"#000000"); _textView.font = [UIFont systemFontOfSize:17]; diff --git a/iOS/TUIKit/TUIGroup/UI_Classic/UI/TUIGroupRequestViewController.m b/iOS/TUIKit/TUIGroup/UI_Classic/UI/TUIGroupRequestViewController.m index 85d3c6bef..09d48c17a 100644 --- a/iOS/TUIKit/TUIGroup/UI_Classic/UI/TUIGroupRequestViewController.m +++ b/iOS/TUIKit/TUIGroup/UI_Classic/UI/TUIGroupRequestViewController.m @@ -27,6 +27,7 @@ self.addMsgTextView = [[UITextView alloc] initWithFrame:CGRectZero]; self.addMsgTextView.font = [UIFont systemFontOfSize:14]; + self.addMsgTextView.textAlignment = isRTL()?NSTextAlignmentRight:NSTextAlignmentLeft; NSString *loginUser = [[V2TIMManager sharedInstance] getLoginUser]; [[V2TIMManager sharedInstance] getUsersInfo:@[ loginUser ] succ:^(NSArray *infoList) { diff --git a/iOS/TUIKit/TUIGroup/UI_Minimalist/Cell/CellUI/TUIGroupButtonCell_Minimalist.m b/iOS/TUIKit/TUIGroup/UI_Minimalist/Cell/CellUI/TUIGroupButtonCell_Minimalist.m index f7ad861f5..23b25217f 100644 --- a/iOS/TUIKit/TUIGroup/UI_Minimalist/Cell/CellUI/TUIGroupButtonCell_Minimalist.m +++ b/iOS/TUIKit/TUIGroup/UI_Minimalist/Cell/CellUI/TUIGroupButtonCell_Minimalist.m @@ -47,7 +47,12 @@ [super fillWithData:data]; self.buttonData = data; [_button setTitle:data.title forState:UIControlStateNormal]; - _button.contentHorizontalAlignment = UIControlContentHorizontalAlignmentLeft; + if(isRTL()) { + _button.contentHorizontalAlignment = UIControlContentHorizontalAlignmentRight; + } + else { + _button.contentHorizontalAlignment = UIControlContentHorizontalAlignmentLeft; + } _button.titleEdgeInsets = UIEdgeInsetsMake(0, 0, 0, 0); switch (data.style) { case ButtonGreen: { @@ -88,13 +93,43 @@ } _line.hidden = data.hideSeparatorLine; + + // tell constraints they need updating + [self setNeedsUpdateConstraints]; + + // update constraints now so we can animate the change + [self updateConstraintsIfNeeded]; + + [self layoutIfNeeded]; + +} + ++ (BOOL)requiresConstraintBasedLayout { + return YES; +} + +// this is Apple's recommended place for adding/updating constraints +- (void)updateConstraints { + + [super updateConstraints]; + [self.button mas_remakeConstraints:^(MASConstraintMaker *make) { + make.leading.mas_equalTo(self.contentView.mas_leading).mas_offset(kScale390(20)); + make.trailing.mas_equalTo(self.contentView.mas_trailing).mas_offset(- kScale390(20)); + make.top.mas_equalTo(self.contentView); + make.bottom.mas_equalTo(self.contentView); + }]; + + [_line mas_remakeConstraints:^(MASConstraintMaker *make) { + make.leading.mas_equalTo(self.contentView.mas_leading).mas_offset(20); + make.trailing.mas_equalTo(self.contentView.mas_trailing); + make.height.mas_equalTo(0.2); + make.bottom.mas_equalTo(self.contentView); + }]; } - (void)layoutSubviews { [super layoutSubviews]; - _button.mm_width(Screen_Width - 2 * kScale390(20)).mm_height(self.mm_h - TButtonCell_Margin).mm_left(kScale390(20)); - _line.mm_width(Screen_Width).mm_height(0.2).mm_left(0).mm_bottom(0); } - (void)onClick:(UIButton *)sender { diff --git a/iOS/TUIKit/TUIGroup/UI_Minimalist/Cell/CellUI/TUIGroupMemberTableViewCell_Minimalist.m b/iOS/TUIKit/TUIGroup/UI_Minimalist/Cell/CellUI/TUIGroupMemberTableViewCell_Minimalist.m index 05f6b5f72..75e39f05d 100644 --- a/iOS/TUIKit/TUIGroup/UI_Minimalist/Cell/CellUI/TUIGroupMemberTableViewCell_Minimalist.m +++ b/iOS/TUIKit/TUIGroup/UI_Minimalist/Cell/CellUI/TUIGroupMemberTableViewCell_Minimalist.m @@ -54,26 +54,55 @@ self.accessoryType = UITableViewCellAccessoryNone; self.userInteractionEnabled = NO; } + // tell constraints they need updating + [self setNeedsUpdateConstraints]; + + // update constraints now so we can animate the change + [self updateConstraintsIfNeeded]; + + [self layoutIfNeeded]; +} ++ (BOOL)requiresConstraintBasedLayout { + return YES; } -- (void)layoutSubviews { - [super layoutSubviews]; - self.avatarView.frame = CGRectMake(kScale390(16), (self.bounds.size.height - kScale390(40)) * 0.5, kScale390(40), kScale390(40)); +// this is Apple's recommended place for adding/updating constraints +- (void)updateConstraints { + + [super updateConstraints]; + + CGFloat imgWidth = kScale390(40); + + [self.avatarView mas_remakeConstraints:^(MASConstraintMaker *make) { + make.width.height.mas_equalTo(imgWidth); + make.centerY.mas_equalTo(self.contentView.mas_centerY); + make.leading.mas_equalTo(kScale390(16)); + }]; if ([TUIConfig defaultConfig].avatarType == TAvatarTypeRounded) { self.avatarView.layer.masksToBounds = YES; - self.avatarView.layer.cornerRadius = self.avatarView.frame.size.height / 2; + self.avatarView.layer.cornerRadius = imgWidth / 2; } else if ([TUIConfig defaultConfig].avatarType == TAvatarTypeRadiusCorner) { self.avatarView.layer.masksToBounds = YES; self.avatarView.layer.cornerRadius = [TUIConfig defaultConfig].avatarCornerRadius; } + + [self.titleLabel sizeToFit]; + [self.titleLabel mas_remakeConstraints:^(MASConstraintMaker *make) { + make.centerY.mas_equalTo(self.avatarView.mas_centerY); + make.leading.mas_equalTo(self.avatarView.mas_trailing).mas_offset(12); + make.height.mas_equalTo(20); + make.trailing.mas_lessThanOrEqualTo(self.contentView.mas_trailing).mas_offset(1); + }]; - self.titleLabel.mm_left(self.avatarView.mm_maxX + 12).mm_height(20).mm__centerY(self.avatarView.mm_centerY).mm_flexToRight(0); + [self.detailLabel sizeToFit]; + [self.detailLabel mas_remakeConstraints:^(MASConstraintMaker *make) { + make.centerY.mas_equalTo(self.avatarView.mas_centerY); + make.height.mas_equalTo(self.detailLabel.frame.size.height); + make.trailing.mas_lessThanOrEqualTo(self.contentView.mas_trailing).mas_offset(- kScale390(16)); + }]; +} +- (void)layoutSubviews { + [super layoutSubviews]; - self.detailLabel.mm_sizeToFit(); - self.detailLabel.mm_right(kScale390(16)); - self.detailLabel.mm_height(20); - self.detailLabel.mm__centerY(self.avatarView.mm_centerY); - self.detailLabel.mm_flexToRight(kScale390(16)); - // self.separtorView.frame = CGRectMake(self.avatarView.mm_maxX, self.contentView.mm_h - 1, self.contentView.mm_w, 1); } @end diff --git a/iOS/TUIKit/TUIGroup/UI_Minimalist/Cell/CellUI/TUIGroupProfileCardViewCell_Minimalist.m b/iOS/TUIKit/TUIGroup/UI_Minimalist/Cell/CellUI/TUIGroupProfileCardViewCell_Minimalist.m index 19d73905e..fb50d4d79 100644 --- a/iOS/TUIKit/TUIGroup/UI_Minimalist/Cell/CellUI/TUIGroupProfileCardViewCell_Minimalist.m +++ b/iOS/TUIKit/TUIGroup/UI_Minimalist/Cell/CellUI/TUIGroupProfileCardViewCell_Minimalist.m @@ -29,6 +29,7 @@ self.textLabel = [[UILabel alloc] init]; self.textLabel.font = [UIFont systemFontOfSize:kScale390(16)]; + self.textLabel.rtlAlignment = TUITextRTLAlignmentCenter; self.textLabel.textColor = [UIColor tui_colorWithHex:@"#000000"]; self.textLabel.userInteractionEnabled = YES; [self addSubview:self.textLabel]; @@ -41,12 +42,30 @@ UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(click)]; [self addGestureRecognizer:tap]; } ++ (BOOL)requiresConstraintBasedLayout { + return YES; +} + +// this is Apple's recommended place for adding/updating constraints +- (void)updateConstraints { + + [super updateConstraints]; + [self.iconView mas_remakeConstraints:^(MASConstraintMaker *make) { + make.width.height.mas_equalTo(kScale390(30)); + make.top.mas_equalTo(kScale390(19)); + make.centerX.mas_equalTo(self); + }]; + [self.textLabel sizeToFit]; + [self.textLabel mas_remakeConstraints:^(MASConstraintMaker *make) { + make.leading.trailing.mas_equalTo(self); + make.height.mas_equalTo(kScale390(19)); + make.top.mas_equalTo(self.iconView.mas_bottom).mas_offset(kScale390(11)); + make.centerX.mas_equalTo(self); + }]; +} - (void)layoutSubviews { [super layoutSubviews]; - self.iconView.frame = CGRectMake((self.bounds.size.width - kScale390(30)) * 0.5, kScale390(19), kScale390(30), kScale390(30)); - [self.textLabel sizeToFit]; - self.textLabel.frame = CGRectMake((self.bounds.size.width - self.textLabel.frame.size.width) * 0.5, - self.iconView.frame.origin.y + self.iconView.frame.size.height + kScale390(11), self.bounds.size.width, kScale390(19)); + } - (void)click { if (self.messageBtnClickBlock) { @@ -105,14 +124,21 @@ [self.headImg sd_setImageWithURL:[NSURL URLWithString:self.groupInfo.faceURL] placeholderImage:DefaultGroupAvatarImageByGroupType(self.groupInfo.groupType)]; [self configHeadImageView:groupInfo]; - + self.descriptionLabel.text = groupInfo.groupName; - [self.descriptionLabel sizeToFit]; self.idLabel.text = self.groupInfo.groupID; if ([self.class isMeSuper:groupInfo]) { self.editButton.hidden = NO; } - [self setNeedsLayout]; + + // tell constraints they need updating + [self setNeedsUpdateConstraints]; + + // update constraints now so we can animate the change + [self updateConstraintsIfNeeded]; + + [self layoutIfNeeded]; + } - (void)configHeadImageView:(V2TIMGroupInfo *)groupInfo { /** @@ -162,33 +188,69 @@ } } } ++ (BOOL)requiresConstraintBasedLayout { + return YES; +} -- (void)layoutSubviews { - [super layoutSubviews]; +// this is Apple's recommended place for adding/updating constraints +- (void)updateConstraints { + + [super updateConstraints]; + CGFloat imgWidth = kScale390(94); + [self.headImg mas_remakeConstraints:^(MASConstraintMaker *make) { + make.width.height.mas_equalTo(imgWidth); + make.centerX.mas_equalTo(self.mas_centerX); + make.top.mas_equalTo(kScale390(42)); + }]; + + MASAttachKeys(self.headImg); - self.headImg.frame = CGRectMake((self.bounds.size.width - kScale390(94)) * 0.5, kScale390(42), kScale390(94), kScale390(94)); if ([TUIConfig defaultConfig].avatarType == TAvatarTypeRounded) { self.headImg.layer.masksToBounds = YES; - self.headImg.layer.cornerRadius = self.headImg.frame.size.height / 2.0; + self.headImg.layer.cornerRadius = imgWidth / 2; } else if ([TUIConfig defaultConfig].avatarType == TAvatarTypeRadiusCorner) { self.headImg.layer.masksToBounds = YES; self.headImg.layer.cornerRadius = [TUIConfig defaultConfig].avatarCornerRadius; } - + [self.descriptionLabel sizeToFit]; - CGFloat descriptionLabelWidth = MIN(self.descriptionLabel.frame.size.width, self.bounds.size.width * 0.5); - self.descriptionLabel.frame = CGRectMake((self.bounds.size.width - descriptionLabelWidth) * 0.5, - self.headImg.frame.origin.y + self.headImg.frame.size.height + kScale390(10), descriptionLabelWidth, 30); - self.editButton.frame = CGRectMake(self.descriptionLabel.frame.origin.x + self.descriptionLabel.frame.size.width + kScale390(3), - self.descriptionLabel.frame.origin.y, kScale390(30), kScale390(30)); - self.idLabel.frame = - CGRectMake(0, self.descriptionLabel.frame.origin.y + self.descriptionLabel.frame.size.height + kScale390(8), self.bounds.size.width, 30); + [self.descriptionLabel mas_remakeConstraints:^(MASConstraintMaker *make) { + make.centerX.mas_equalTo(self.mas_centerX); + make.top.mas_equalTo(self.headImg.mas_bottom).mas_offset(kScale390(10)); + make.height.mas_equalTo(30); + make.width.mas_equalTo(self.descriptionLabel.frame.size.width); + make.width.mas_lessThanOrEqualTo(self).multipliedBy(0.5); + }]; + MASAttachKeys(self.descriptionLabel); + [self.editButton mas_remakeConstraints:^(MASConstraintMaker *make) { + make.leading.mas_equalTo(self.descriptionLabel.mas_trailing).mas_equalTo(kScale390(3)); + make.top.mas_equalTo(self.descriptionLabel.mas_top); + make.height.mas_equalTo(30); + make.width.mas_equalTo(30); + }]; + MASAttachKeys(self.editButton); + + [self.idLabel mas_remakeConstraints:^(MASConstraintMaker *make) { + make.leading.mas_equalTo(self.mas_leading); + make.top.mas_equalTo(self.descriptionLabel.mas_bottom).mas_offset(kScale390(8)); + make.height.mas_equalTo(30); + make.width.mas_equalTo(self.frame.size.width); + }]; if (self.functionListView.subviews.count > 0) { - self.functionListView.frame = CGRectMake(0, CGRectGetMaxY(self.idLabel.frame) + kScale390(18), self.bounds.size.width, kScale390(95)); + [self.functionListView mas_remakeConstraints:^(MASConstraintMaker *make) { + make.leading.mas_equalTo(0); + make.width.mas_equalTo(self.bounds.size.width); + make.height.mas_equalTo(kScale390(95)); + make.top.mas_equalTo(self.idLabel.mas_bottom).mas_offset(kScale390(18)); + }]; } } +- (void)layoutSubviews { + [super layoutSubviews]; +} + - (void)headImageClick { if (self.headImgClickBlock && [self.class isMeSuper:self.groupInfo]) { self.headImgClickBlock(); diff --git a/iOS/TUIKit/TUIGroup/UI_Minimalist/Cell/CellUI/TUIMemberInfoCell_Minimalist.m b/iOS/TUIKit/TUIGroup/UI_Minimalist/Cell/CellUI/TUIMemberInfoCell_Minimalist.m index b6e4e18c3..dfd5e28ec 100644 --- a/iOS/TUIKit/TUIGroup/UI_Minimalist/Cell/CellUI/TUIMemberInfoCell_Minimalist.m +++ b/iOS/TUIKit/TUIGroup/UI_Minimalist/Cell/CellUI/TUIMemberInfoCell_Minimalist.m @@ -36,32 +36,61 @@ [self.avatarImageView sd_setImageWithURL:[NSURL URLWithString:data.avatarUrl] placeholderImage:data.avatar ?: defaultImage]; self.nameLabel.text = data.name; - [self updateUI]; + // tell constraints they need updating + [self setNeedsUpdateConstraints]; + + // update constraints now so we can animate the change + [self updateConstraintsIfNeeded]; + + [self layoutIfNeeded]; } -- (void)updateUI { ++ (BOOL)requiresConstraintBasedLayout { + return YES; +} + +// this is Apple's recommended place for adding/updating constraints +- (void)updateConstraints { + + [super updateConstraints]; + CGFloat imgWidth = kScale390(20); if (self.data.style == TUIMemberInfoCellStyleAdd) { - self.avatarImageView.mm_width(20.0 * kScale).mm_height(20.0 * kScale); - self.avatarImageView.mm_left(18.0 * kScale); + imgWidth = 20.0 * kScale; + [self.avatarImageView mas_remakeConstraints:^(MASConstraintMaker *make) { + make.width.height.mas_equalTo(20.0 * kScale); + make.leading.mas_equalTo(kScale390(18)); + make.centerY.mas_equalTo(self.contentView.mas_centerY); + }]; self.nameLabel.font = [UIFont systemFontOfSize:16.0 * kScale]; self.nameLabel.textColor = [UIColor tui_colorWithHex:@"#147AFF"]; } else { - self.avatarImageView.mm_width(34.0 * kScale).mm_height(34.0 * kScale); - self.avatarImageView.mm_left(16.0 * kScale); + imgWidth = 34.0 * kScale; + [self.avatarImageView mas_remakeConstraints:^(MASConstraintMaker *make) { + make.width.height.mas_equalTo(34.0 * kScale); + make.leading.mas_equalTo(kScale390(16)); + make.centerY.mas_equalTo(self.contentView.mas_centerY); + }]; self.nameLabel.font = [UIFont systemFontOfSize:16.0 * kScale]; self.nameLabel.textColor = TIMCommonDynamicColor(@"form_value_text_color", @"#000000"); } if ([TUIConfig defaultConfig].avatarType == TAvatarTypeRounded) { self.avatarImageView.layer.masksToBounds = YES; - self.avatarImageView.layer.cornerRadius = self.avatarImageView.frame.size.height / 2; + self.avatarImageView.layer.cornerRadius = imgWidth / 2; } else if ([TUIConfig defaultConfig].avatarType == TAvatarTypeRadiusCorner) { self.avatarImageView.layer.masksToBounds = YES; self.avatarImageView.layer.cornerRadius = [TUIConfig defaultConfig].avatarCornerRadius; } - self.avatarImageView.mm_centerY = self.contentView.mm_centerY; - self.nameLabel.mm_height(self.contentView.mm_h).mm_left(CGRectGetMaxX(self.avatarImageView.frame) + 14).mm_flexToRight(16 * kScale); + [self.nameLabel sizeToFit]; + [self.nameLabel mas_remakeConstraints:^(MASConstraintMaker *make) { + make.leading.mas_equalTo(self.avatarImageView.mas_trailing).mas_offset(14); + make.centerY.mas_equalTo(self.contentView); + make.size.mas_equalTo(self.nameLabel.frame.size); + make.trailing.mas_lessThanOrEqualTo(self.contentView.mas_trailing).mas_offset(- 2.0 * kScale); + }]; + + } - (UIImageView *)avatarImageView { diff --git a/iOS/TUIKit/TUIGroup/UI_Minimalist/Cell/CellUI/TUIProfileCardCell_Minimalist.m b/iOS/TUIKit/TUIGroup/UI_Minimalist/Cell/CellUI/TUIProfileCardCell_Minimalist.m index c030575df..0c44dbe10 100644 --- a/iOS/TUIKit/TUIGroup/UI_Minimalist/Cell/CellUI/TUIProfileCardCell_Minimalist.m +++ b/iOS/TUIKit/TUIGroup/UI_Minimalist/Cell/CellUI/TUIProfileCardCell_Minimalist.m @@ -102,33 +102,89 @@ } else { self.accessoryType = UITableViewCellAccessoryNone; } + + // tell constraints they need updating + [self setNeedsUpdateConstraints]; + + // update constraints now so we can animate the change + [self updateConstraintsIfNeeded]; + + [self layoutIfNeeded]; } -- (void)layoutSubviews { - [super layoutSubviews]; - CGFloat maxLabelWidth = self.contentView.mm_w - CGRectGetMaxX(_avatar.frame) - 30; - _name.mm_sizeToFitThan(0, _avatar.mm_h / 5).mm_top(_avatar.mm_y).mm_left(_avatar.mm_maxX + kScale390(8)); - if (CGRectGetMaxX(_name.frame) >= self.contentView.mm_w) { - _name.mm_w = maxLabelWidth; ++ (BOOL)requiresConstraintBasedLayout { + return YES; +} + +// this is Apple's recommended place for adding/updating constraints +- (void)updateConstraints { + + [super updateConstraints]; + CGSize headSize = CGSizeMake(kScale390(66), kScale390(66)); + + [self.avatar mas_remakeConstraints:^(MASConstraintMaker *make) { + make.size.mas_equalTo(headSize); + make.top.mas_equalTo(kScale390(10)); + make.leading.mas_equalTo(kScale390(16)); + }]; + + if ([TUIConfig defaultConfig].avatarType == TAvatarTypeRounded) { + self.avatar.layer.masksToBounds = YES; + self.avatar.layer.cornerRadius = headSize.height / 2; + } else if ([TUIConfig defaultConfig].avatarType == TAvatarTypeRadiusCorner) { + self.avatar.layer.masksToBounds = YES; + self.avatar.layer.cornerRadius = [TUIConfig defaultConfig].avatarCornerRadius; } - _identifier.mm_sizeToFitThan(80, _avatar.mm_h / 5).mm_left(_name.mm_x); + [self.name sizeToFit]; + [self.name mas_remakeConstraints:^(MASConstraintMaker *make) { + make.top.mas_equalTo(TPersonalCommonCell_Margin); + make.leading.mas_equalTo(self.avatar.mas_trailing).mas_offset(15); + make.width.mas_lessThanOrEqualTo(self.name.frame.size.width); + make.height.mas_greaterThanOrEqualTo(self.name.frame.size.height); + make.trailing.mas_lessThanOrEqualTo(self.genderIcon.mas_leading).mas_offset(- 1); + }]; + + [self.genderIcon mas_remakeConstraints:^(MASConstraintMaker *make) { + make.width.height.mas_equalTo(self.name.font.pointSize *0.9); + make.centerY.mas_equalTo(self.name); + make.leading.mas_equalTo(self.name.mas_trailing).mas_offset(1); + make.trailing.mas_lessThanOrEqualTo(self.contentView.mas_trailing).mas_offset(- 10); + }]; + + [self.identifier sizeToFit]; + [self.identifier mas_remakeConstraints:^(MASConstraintMaker *make) { + make.leading.mas_equalTo(self.name); + make.top.mas_equalTo(self.name.mas_bottom).mas_offset(5); + if(self.identifier.frame.size.width > 80) { + make.width.mas_greaterThanOrEqualTo(self.identifier.frame.size.width); + } + else { + make.width.mas_greaterThanOrEqualTo(@80); + } + make.height.mas_greaterThanOrEqualTo(self.identifier.frame.size.height); + make.trailing.mas_lessThanOrEqualTo(self.contentView.mas_trailing).mas_offset(-1); + }]; if (self.cardData.showSignature) { - _identifier.mm_y = _name.mm_y + _name.mm_h + 5; + [self.signature sizeToFit]; + [self.signature mas_remakeConstraints:^(MASConstraintMaker *make) { + make.leading.mas_equalTo(self.name); + make.top.mas_equalTo(self.identifier.mas_bottom).mas_offset(5); + if(self.signature.frame.size.width > 80) { + make.width.mas_greaterThanOrEqualTo(self.signature.frame.size.width); + } + else { + make.width.mas_greaterThanOrEqualTo(@80); + } + make.height.mas_greaterThanOrEqualTo(self.signature.frame.size.height); + make.trailing.mas_lessThanOrEqualTo(self.contentView.mas_trailing).mas_offset(-1); + }]; + } else { - _identifier.mm_bottom(_avatar.mm_b); + self.signature.frame = CGRectZero; } - _signature.mm_sizeToFitThan(80, _avatar.mm_h / 3).mm_left(_name.mm_x); - _signature.mm_y = CGRectGetMaxY(_identifier.frame) + 5; - if (CGRectGetMaxX(_signature.frame) >= self.contentView.mm_w) { - _signature.mm_w = maxLabelWidth; - } - - _genderIcon.mm_sizeToFitThan(_name.font.pointSize * 0.9, _name.font.pointSize * 0.9) - .mm__centerY(_name.mm_centerY) - .mm_left(_name.mm_x + _name.mm_w + TPersonalCommonCell_Margin); } - (void)onTapAvatar { diff --git a/iOS/TUIKit/TUIGroup/UI_Minimalist/DataProvider/TUIGroupInfoDataProvider_Minimalist.m b/iOS/TUIKit/TUIGroup/UI_Minimalist/DataProvider/TUIGroupInfoDataProvider_Minimalist.m index dbcc37379..41196acb0 100644 --- a/iOS/TUIKit/TUIGroup/UI_Minimalist/DataProvider/TUIGroupInfoDataProvider_Minimalist.m +++ b/iOS/TUIKit/TUIGroup/UI_Minimalist/DataProvider/TUIGroupInfoDataProvider_Minimalist.m @@ -11,7 +11,6 @@ #import #import #import "TIMGroupInfo+TUIDataProvider.h" -#import "TUIAddCellData.h" #import "TUIGroupButtonCell_Minimalist.h" #import "TUIGroupMemberCellData.h" #import "TUIGroupMemberCellData_Minimalist.h" @@ -259,8 +258,6 @@ self.inviteOptionData = inviteOptionData; [dataList addObject:groupInfoArray]; - [dataList addObject:groupInfoArray]; - // personal info TUICommonTextCellData *nickData = [[TUICommonTextCellData alloc] init]; nickData.key = TIMCommonLocalizableString(TUIKitGroupProfileAlias); diff --git a/iOS/TUIKit/TUIGroup/UI_Minimalist/DataProvider/TUIGroupManageDataProvider_Minimalist.m b/iOS/TUIKit/TUIGroup/UI_Minimalist/DataProvider/TUIGroupManageDataProvider_Minimalist.m index 652bc3eed..d3017fb50 100644 --- a/iOS/TUIKit/TUIGroup/UI_Minimalist/DataProvider/TUIGroupManageDataProvider_Minimalist.m +++ b/iOS/TUIKit/TUIGroup/UI_Minimalist/DataProvider/TUIGroupManageDataProvider_Minimalist.m @@ -10,7 +10,6 @@ #import #import #import -#import "TUIAddCellData.h" #import "TUIMemberInfoCellData_Minimalist.h" #import "TUISelectGroupMemberCell.h" diff --git a/iOS/TUIKit/TUIGroup/UI_Minimalist/UI/TUIGroupInfoController_Minimalist.m b/iOS/TUIKit/TUIGroup/UI_Minimalist/UI/TUIGroupInfoController_Minimalist.m index 3fd20d1ff..11c92c33b 100644 --- a/iOS/TUIKit/TUIGroup/UI_Minimalist/UI/TUIGroupInfoController_Minimalist.m +++ b/iOS/TUIKit/TUIGroup/UI_Minimalist/UI/TUIGroupInfoController_Minimalist.m @@ -8,7 +8,6 @@ #import #import #import "TIMGroupInfo+TUIDataProvider.h" -#import "TUIAddCell.h" #import "TUIGroupButtonCell_Minimalist.h" #import "TUIGroupInfoDataProvider_Minimalist.h" #import "TUIGroupManageController_Minimalist.h" diff --git a/iOS/TUIKit/TUIGroup/UI_Minimalist/UI/TUIGroupManageController_Minimalist.m b/iOS/TUIKit/TUIGroup/UI_Minimalist/UI/TUIGroupManageController_Minimalist.m index 2b410d8d0..d6766e481 100644 --- a/iOS/TUIKit/TUIGroup/UI_Minimalist/UI/TUIGroupManageController_Minimalist.m +++ b/iOS/TUIKit/TUIGroup/UI_Minimalist/UI/TUIGroupManageController_Minimalist.m @@ -10,8 +10,6 @@ #import #import #import -#import "TUIAddCell.h" -#import "TUIAddCellData.h" #import "TUIGroupManageDataProvider_Minimalist.h" #import "TUIMemberInfoCellData_Minimalist.h" #import "TUIMemberInfoCell_Minimalist.h" @@ -144,9 +142,6 @@ } else if ([data isKindOfClass:TUICommonSwitchCellData.class]) { cell = [[TUICommonSwitchCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:NSStringFromClass(TUICommonSwitchCell.class)]; [(TUICommonSwitchCell *)cell fillWithData:(TUICommonSwitchCellData *)data]; - } else if ([data isKindOfClass:TUIAddCellData.class]) { - cell = [[TUIAddCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:NSStringFromClass(TUIAddCell.class)]; - [(TUIAddCell *)cell setData:(TUIAddCellData *)data]; } else if ([data isKindOfClass:TUIMemberInfoCellData_Minimalist.class]) { cell = [[TUIMemberInfoCell_Minimalist alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:NSStringFromClass(TUIMemberInfoCell_Minimalist.class)]; diff --git a/iOS/TUIKit/TUIGroup/UI_Minimalist/UI/TUIGroupMemberController_Minimalist.m b/iOS/TUIKit/TUIGroup/UI_Minimalist/UI/TUIGroupMemberController_Minimalist.m index fafc1f03c..07d86e92e 100644 --- a/iOS/TUIKit/TUIGroup/UI_Minimalist/UI/TUIGroupMemberController_Minimalist.m +++ b/iOS/TUIKit/TUIGroup/UI_Minimalist/UI/TUIGroupMemberController_Minimalist.m @@ -10,7 +10,6 @@ #import #import #import "TIMGroupInfo+TUIDataProvider.h" -#import "TUIAddCell.h" #import "TUIGroupMemberCell.h" #import "TUIGroupMemberDataProvider.h" @@ -63,6 +62,7 @@ // left UIImage *image = TUIGroupDynamicImage(@"group_nav_back_img", [UIImage imageNamed:TUIGroupImagePath(@"back")]); + image = [image rtl_imageFlippedForRightToLeftLayoutDirection]; UIButton *leftButton = [[UIButton alloc] initWithFrame:CGRectMake(0, 0, 30, 30)]; [leftButton addTarget:self action:@selector(leftBarButtonClick) forControlEvents:UIControlEventTouchUpInside]; [leftButton setImage:image forState:UIControlStateNormal]; diff --git a/iOS/TUIKit/TUIGroup/UI_Minimalist/UI/TUIGroupNoticeController_Minimalist.m b/iOS/TUIKit/TUIGroup/UI_Minimalist/UI/TUIGroupNoticeController_Minimalist.m index 2d3db16bb..9cb2c25ee 100644 --- a/iOS/TUIKit/TUIGroup/UI_Minimalist/UI/TUIGroupNoticeController_Minimalist.m +++ b/iOS/TUIKit/TUIGroup/UI_Minimalist/UI/TUIGroupNoticeController_Minimalist.m @@ -96,6 +96,7 @@ - (UITextView *)textView { if (_textView == nil) { _textView = [[UITextView alloc] init]; + _textView.textAlignment = isRTL()?NSTextAlignmentRight:NSTextAlignmentLeft; _textView.backgroundColor = TIMCommonDynamicColor(@"controller_bg_color", @"#F2F3F5"); _textView.textColor = TIMCommonDynamicColor(@"form_title_color", @"#000000"); _textView.font = [UIFont systemFontOfSize:17]; diff --git a/iOS/TUIKit/TUIGroup/UI_Minimalist/UI/TUIGroupRequestViewController_Minimalist.m b/iOS/TUIKit/TUIGroup/UI_Minimalist/UI/TUIGroupRequestViewController_Minimalist.m index 6b55e85ad..e7bf68a3f 100644 --- a/iOS/TUIKit/TUIGroup/UI_Minimalist/UI/TUIGroupRequestViewController_Minimalist.m +++ b/iOS/TUIKit/TUIGroup/UI_Minimalist/UI/TUIGroupRequestViewController_Minimalist.m @@ -31,6 +31,7 @@ self.addMsgTextView = [[UITextView alloc] initWithFrame:CGRectZero]; self.addMsgTextView.font = [UIFont systemFontOfSize:14]; + self.addMsgTextView.textAlignment = isRTL()?NSTextAlignmentRight:NSTextAlignmentLeft; self.addMsgTextView.backgroundColor = [UIColor tui_colorWithHex:@"f9f9f9"]; NSMutableParagraphStyle *paragraphStyle = [[NSMutableParagraphStyle alloc] init]; paragraphStyle.lineSpacing = 5; diff --git a/iOS/TUIKit/TUIOfflinePush/TUIOfflinePush.podspec b/iOS/TUIKit/TUIOfflinePush/TUIOfflinePush.podspec index 3da3144f5..5d8dcdc9a 100644 --- a/iOS/TUIKit/TUIOfflinePush/TUIOfflinePush.podspec +++ b/iOS/TUIKit/TUIOfflinePush/TUIOfflinePush.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |spec| spec.name = 'TUIOfflinePush' - spec.version = '7.4.4643' + spec.version = '7.5.4852' spec.platform = :ios spec.ios.deployment_target = '9.0' spec.license = { :type => 'Proprietary', diff --git a/iOS/TUIKit/TUISearch/BaseCell/CellUI/TUISearchResultCell.m b/iOS/TUIKit/TUISearch/BaseCell/CellUI/TUISearchResultCell.m index 20323ca67..b3b2daf84 100644 --- a/iOS/TUIKit/TUISearch/BaseCell/CellUI/TUISearchResultCell.m +++ b/iOS/TUIKit/TUISearch/BaseCell/CellUI/TUISearchResultCell.m @@ -37,12 +37,14 @@ _title_label.text = @""; _title_label.textColor = TIMCommonDynamicColor(@"form_title_color", @"#000000"); _title_label.font = [UIFont systemFontOfSize:14.0]; + _title_label.rtlAlignment = TUITextRTLAlignmentLeading; [self.contentView addSubview:_title_label]; _detail_title = [[UILabel alloc] init]; _detail_title.text = @""; _detail_title.textColor = TIMCommonDynamicColor(@"form_subtitle_color", @"#888888"); _detail_title.font = [UIFont systemFontOfSize:12.0]; + _detail_title.rtlAlignment = TUITextRTLAlignmentLeading; [self.contentView addSubview:_detail_title]; _separtorView = [[UIView alloc] init]; @@ -54,38 +56,6 @@ - (void)layoutSubviews { [super layoutSubviews]; - self.avatarView.mm_x = 10; - self.avatarView.mm_w = 40; - self.avatarView.mm_h = 40; - self.avatarView.mm_centerY = self.contentView.mm_centerY; - if (self.cellModel.avatarType == TAvatarTypeRadiusCorner) { - self.avatarView.layer.cornerRadius = self.avatarView.mm_h / 2; - self.avatarView.layer.masksToBounds = YES; - } - - self.title_label.mm_x = self.avatarView.mm_maxX + 10; - self.detail_title.mm_x = self.avatarView.mm_maxX + 10; - - [self.title_label sizeToFit]; - [self.detail_title sizeToFit]; - - self.separtorView.frame = CGRectMake(self.avatarView.mm_maxX, self.contentView.mm_h - 1, self.contentView.mm_w, 1); - - NSString *title = self.title_label.text; - if (title.length == 0) { - title = self.title_label.attributedText.string; - } - NSString *detail = self.detail_title.text; - if (detail.length == 0) { - detail = self.detail_title.attributedText.string; - } - if (title.length && self.detail_title.text.length) { - self.title_label.mm_y = self.avatarView.mm_y; - self.detail_title.mm_b = self.avatarView.mm_b; - } else { - self.title_label.mm_centerY = self.avatarView.mm_centerY; - self.detail_title.mm_centerY = self.avatarView.mm_centerY; - } } - (void)fillWithData:(TUISearchResultCellModel *)cellModel { @@ -232,6 +202,86 @@ [self.avatarView sd_setImageWithURL:[NSURL URLWithString:faceUrl] placeholderImage:self.cellModel.avatarImage]; } }]; + + // tell constraints they need updating + [self setNeedsUpdateConstraints]; + + // update constraints now so we can animate the change + [self updateConstraintsIfNeeded]; + + [self layoutIfNeeded]; +} ++ (BOOL)requiresConstraintBasedLayout { + return YES; +} + +// this is Apple's recommended place for adding/updating constraints +- (void)updateConstraints { + + [super updateConstraints]; + + CGSize headSize = CGSizeMake(kScale390(40), kScale390(40)); + + [self.avatarView mas_remakeConstraints:^(MASConstraintMaker *make) { + make.size.mas_equalTo(headSize); + make.centerY.mas_equalTo(self.contentView.mas_centerY); + make.leading.mas_equalTo(kScale390(10)); + }]; + + if ([TUIConfig defaultConfig].avatarType == TAvatarTypeRounded) { + self.avatarView.layer.masksToBounds = YES; + self.avatarView.layer.cornerRadius = headSize.height / 2; + } else if ([TUIConfig defaultConfig].avatarType == TAvatarTypeRadiusCorner) { + self.avatarView.layer.masksToBounds = YES; + self.avatarView.layer.cornerRadius = [TUIConfig defaultConfig].avatarCornerRadius; + } + + NSString *title = self.title_label.text; + if (title.length == 0) { + title = self.title_label.attributedText.string; + } + NSString *detail = self.detail_title.text; + if (detail.length == 0) { + detail = self.detail_title.attributedText.string; + } + [self.title_label sizeToFit]; + [self.detail_title sizeToFit]; + if (title.length && self.detail_title.text.length) { + [self.title_label mas_remakeConstraints:^(MASConstraintMaker *make) { + make.top.mas_equalTo(self.avatarView.mas_top); + make.leading.mas_equalTo(self.avatarView.mas_trailing).mas_offset(10); + make.trailing.mas_equalTo(self.contentView.mas_trailing).mas_offset(-10); + make.height.mas_greaterThanOrEqualTo(self.title_label.frame.size.height); + }]; + + [self.detail_title mas_remakeConstraints:^(MASConstraintMaker *make) { + make.bottom.mas_equalTo(self.avatarView.mas_bottom); + make.leading.mas_equalTo(self.avatarView.mas_trailing).mas_offset(10); + make.trailing.mas_equalTo(self.contentView.mas_trailing).mas_offset(-10); + make.height.mas_greaterThanOrEqualTo(self.detail_title.frame.size.height); + }]; + } else { + [self.title_label mas_remakeConstraints:^(MASConstraintMaker *make) { + make.centerY.mas_equalTo(self.avatarView.mas_centerY); + make.leading.mas_equalTo(self.avatarView.mas_trailing).mas_offset(10); + make.trailing.mas_equalTo(self.contentView.mas_trailing).mas_offset(-10); + make.height.mas_greaterThanOrEqualTo(self.title_label.frame.size.height); + }]; + + [self.detail_title mas_remakeConstraints:^(MASConstraintMaker *make) { + make.centerY.mas_equalTo(self.avatarView.mas_centerY); + make.leading.mas_equalTo(self.avatarView.mas_trailing).mas_offset(10); + make.trailing.mas_equalTo(self.contentView.mas_trailing).mas_offset(-10); + make.height.mas_greaterThanOrEqualTo(self.detail_title.frame.size.height); + }]; + } + [self.separtorView mas_remakeConstraints:^(MASConstraintMaker *make) { + make.leading.mas_equalTo(self.avatarView.mas_trailing); + make.bottom.mas_equalTo(self.contentView.mas_bottom).mas_offset(-1); + make.width.mas_equalTo(self.contentView); + make.height.mas_equalTo(1); + }]; + } @end diff --git a/iOS/TUIKit/TUISearch/Resources/TUISearch.bundle/right@2x.png b/iOS/TUIKit/TUISearch/Resources/TUISearch.bundle/right@2x.png index b4fd76e70..a3ea33a4d 100644 Binary files a/iOS/TUIKit/TUISearch/Resources/TUISearch.bundle/right@2x.png and b/iOS/TUIKit/TUISearch/Resources/TUISearch.bundle/right@2x.png differ diff --git a/iOS/TUIKit/TUISearch/Resources/TUISearch.bundle/search.png b/iOS/TUIKit/TUISearch/Resources/TUISearch.bundle/search.png index b403aca49..6a2cf1fba 100644 Binary files a/iOS/TUIKit/TUISearch/Resources/TUISearch.bundle/search.png and b/iOS/TUIKit/TUISearch/Resources/TUISearch.bundle/search.png differ diff --git a/iOS/TUIKit/TUISearch/Resources/TUISearch.bundle/search_not_found_icon@3x.png b/iOS/TUIKit/TUISearch/Resources/TUISearch.bundle/search_not_found_icon@3x.png index e3394494c..eb858ca20 100644 Binary files a/iOS/TUIKit/TUISearch/Resources/TUISearch.bundle/search_not_found_icon@3x.png and b/iOS/TUIKit/TUISearch/Resources/TUISearch.bundle/search_not_found_icon@3x.png differ diff --git a/iOS/TUIKit/TUISearch/Resources/TUISearchTheme.bundle/dark/resource/bg.png b/iOS/TUIKit/TUISearch/Resources/TUISearchTheme.bundle/dark/resource/bg.png index 7077009d5..a4d07d07a 100644 Binary files a/iOS/TUIKit/TUISearch/Resources/TUISearchTheme.bundle/dark/resource/bg.png and b/iOS/TUIKit/TUISearch/Resources/TUISearchTheme.bundle/dark/resource/bg.png differ diff --git a/iOS/TUIKit/TUISearch/Resources/TUISearchTheme.bundle/light/resource/bg.png b/iOS/TUIKit/TUISearch/Resources/TUISearchTheme.bundle/light/resource/bg.png index 87d7c51a0..292267063 100644 Binary files a/iOS/TUIKit/TUISearch/Resources/TUISearchTheme.bundle/light/resource/bg.png and b/iOS/TUIKit/TUISearch/Resources/TUISearchTheme.bundle/light/resource/bg.png differ diff --git a/iOS/TUIKit/TUISearch/Resources/TUISearchTheme.bundle/lively/resource/bg.png b/iOS/TUIKit/TUISearch/Resources/TUISearchTheme.bundle/lively/resource/bg.png index 62c1d746f..acfbbf52c 100644 Binary files a/iOS/TUIKit/TUISearch/Resources/TUISearchTheme.bundle/lively/resource/bg.png and b/iOS/TUIKit/TUISearch/Resources/TUISearchTheme.bundle/lively/resource/bg.png differ diff --git a/iOS/TUIKit/TUISearch/Resources/TUISearchTheme.bundle/serious/resource/bg.png b/iOS/TUIKit/TUISearch/Resources/TUISearchTheme.bundle/serious/resource/bg.png index ccaf89e4a..0ad7159f3 100644 Binary files a/iOS/TUIKit/TUISearch/Resources/TUISearchTheme.bundle/serious/resource/bg.png and b/iOS/TUIKit/TUISearch/Resources/TUISearchTheme.bundle/serious/resource/bg.png differ diff --git a/iOS/TUIKit/TUISearch/TUISearch.podspec b/iOS/TUIKit/TUISearch/TUISearch.podspec index 7e31916fd..671225a73 100644 --- a/iOS/TUIKit/TUISearch/TUISearch.podspec +++ b/iOS/TUIKit/TUISearch/TUISearch.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |spec| spec.name = 'TUISearch' - spec.version = '7.4.4643' + spec.version = '7.5.4852' spec.platform = :ios spec.ios.deployment_target = '9.0' spec.license = { :type => 'Proprietary', diff --git a/iOS/TUIKit/TUISearch/UI_Classic/UI/TUISearchBar.m b/iOS/TUIKit/TUISearch/UI_Classic/UI/TUISearchBar.m index 76a2fb5d6..9df54280f 100644 --- a/iOS/TUIKit/TUISearch/UI_Classic/UI/TUISearchBar.m +++ b/iOS/TUIKit/TUISearch/UI_Classic/UI/TUISearchBar.m @@ -41,6 +41,7 @@ _searchBar.showsCancelButton = NO; _searchBar.delegate = self; _searchBar.showsCancelButton = !self.isEntrance; + _searchBar.searchTextField.textAlignment = isRTL()?NSTextAlignmentRight:NSTextAlignmentLeft; if (@available(iOS 13.0, *)) { _searchBar.searchTextField.backgroundColor = TIMCommonDynamicColor(@"search_textfield_bg_color", @"#FEFEFE"); } @@ -125,7 +126,7 @@ } cancelBtn.enabled = YES; cancelBtn.userInteractionEnabled = YES; - + [cancelBtn setTitleColor:[UIColor systemBlueColor] forState:UIControlStateNormal]; [UIBarButtonItem appearanceWhenContainedInInstancesOfClasses:@[ [UISearchBar class] ]].title = TIMCommonLocalizableString(TUIKitSearchItemCancel); ; }); diff --git a/iOS/TUIKit/TUISearch/UI_Classic/UI/TUISearchResultHeaderFooterView.m b/iOS/TUIKit/TUISearch/UI_Classic/UI/TUISearchResultHeaderFooterView.m index 3f7edff52..e70aee175 100644 --- a/iOS/TUIKit/TUISearch/UI_Classic/UI/TUISearchResultHeaderFooterView.m +++ b/iOS/TUIKit/TUISearch/UI_Classic/UI/TUISearchResultHeaderFooterView.m @@ -38,10 +38,11 @@ _titleLabel = [[UILabel alloc] init]; _titleLabel.text = @""; _titleLabel.font = [UIFont systemFontOfSize:12.0]; + _titleLabel.rtlAlignment = TUITextRTLAlignmentLeading; [self.contentView addSubview:_titleLabel]; _accessoryView = [[UIImageView alloc] init]; - _accessoryView.image = [UIImage imageNamed:TUISearchImagePath(@"right")]; + _accessoryView.image = [[UIImage imageNamed:TUISearchImagePath(@"right")] rtl_imageFlippedForRightToLeftLayoutDirection]; [self.contentView addSubview:_accessoryView]; _separtorView = [[UIView alloc] init]; @@ -63,33 +64,99 @@ self.accessoryView.hidden = !self.isFooter; UIColor *footerColor = TIMCommonDynamicColor(@"primary_theme_color", @"#147AFF"); self.titleLabel.textColor = self.isFooter ? footerColor : [UIColor darkGrayColor]; + + // tell constraints they need updating + [self setNeedsUpdateConstraints]; + + // update constraints now so we can animate the change + [self updateConstraintsIfNeeded]; + + [self layoutIfNeeded]; + } - (void)setTitle:(NSString *)title { _title = title; self.titleLabel.text = title; + + // tell constraints they need updating + [self setNeedsUpdateConstraints]; + + // update constraints now so we can animate the change + [self updateConstraintsIfNeeded]; + + [self layoutIfNeeded]; +} + ++ (BOOL)requiresConstraintBasedLayout { + return YES; +} + +// this is Apple's recommended place for adding/updating constraints +- (void)updateConstraints { + + [super updateConstraints]; + if (self.isFooter) { + [self.iconView mas_remakeConstraints:^(MASConstraintMaker *make) { + make.centerY.mas_equalTo(self.contentView); + make.height.width.mas_equalTo(20); + if(isRTL()){ + make.right.mas_equalTo(self.contentView.mas_right).mas_offset(-10); + } + else { + make.left.mas_equalTo(self.contentView.mas_left).mas_offset(10); + } + }]; + [self.titleLabel sizeToFit]; + [self.titleLabel mas_remakeConstraints:^(MASConstraintMaker *make) { + if(isRTL()) { + make.right.mas_equalTo(self.iconView.mas_left).mas_offset(-10); + } + else{ + make.left.mas_equalTo(self.iconView.mas_right).mas_offset(10); + } + make.leading.mas_equalTo(self.iconView.mas_trailing).mas_offset(10); + make.centerY.mas_equalTo(self.contentView); + make.width.mas_equalTo(self.titleLabel.frame.size.width); + make.height.mas_equalTo(self.titleLabel.font.lineHeight); + }]; + + [self.accessoryView mas_remakeConstraints:^(MASConstraintMaker *make) { + make.height.width.mas_equalTo(10); + make.centerY.mas_equalTo(self.contentView); + if(isRTL()) { + make.left.mas_equalTo(self.contentView.mas_left).mas_offset(10); + }else { + make.right.mas_equalTo(self.contentView.mas_right).mas_offset(-10); + } + }]; + [self.separtorView mas_remakeConstraints:^(MASConstraintMaker *make) { + make.leading.mas_equalTo(10); + make.bottom.mas_equalTo(self.contentView); + make.width.mas_equalTo(self.contentView); + make.height.mas_equalTo(1); + }]; + + MASAttachKeys(self.iconView,self.titleLabel,self.accessoryView,self.separtorView); + } else { + [self.titleLabel mas_remakeConstraints:^(MASConstraintMaker *make) { + make.leading.mas_equalTo(self.contentView.mas_leading).mas_offset(10); + make.centerY.mas_equalTo(self.contentView); + make.trailing.mas_equalTo(self.contentView.mas_trailing).mas_offset(-10); + make.height.mas_equalTo(self.titleLabel.font.lineHeight); + }]; + [self.separtorView mas_remakeConstraints:^(MASConstraintMaker *make) { + make.leading.mas_equalTo(10); + make.bottom.mas_equalTo(self.contentView).mas_offset(-1); + make.width.mas_equalTo(self.contentView); + make.height.mas_equalTo(1); + }]; + MASAttachKeys(self.titleLabel,self.separtorView); + } } - (void)layoutSubviews { [super layoutSubviews]; - - if (self.isFooter) { - self.iconView.mm_height(20).mm_width(20); - self.iconView.mm_centerY = self.contentView.mm_centerY; - self.iconView.mm_x = 10; - [self.titleLabel sizeToFit]; - self.titleLabel.mm_centerY = self.contentView.mm_centerY; - self.titleLabel.mm_x = self.iconView.mm_maxX + 10; - self.accessoryView.mm_height(10).mm_width(10); - self.accessoryView.mm_centerY = self.contentView.mm_centerY; - self.accessoryView.mm_r = 10; - self.separtorView.frame = CGRectMake(10, 0, self.contentView.mm_w, 1); - } else { - [self.titleLabel sizeToFit]; - self.titleLabel.mm_centerY = self.contentView.mm_centerY; - self.titleLabel.mm_x = 10; - self.separtorView.frame = CGRectMake(10, self.contentView.mm_h - 1, self.contentView.mm_w, 1); - } } - (void)setFrame:(CGRect)frame { diff --git a/iOS/TUIKit/TUISearch/UI_Classic/UI/TUISearchResultListController.m b/iOS/TUIKit/TUISearch/UI_Classic/UI/TUISearchResultListController.m index c8a5bb100..636ae90e6 100644 --- a/iOS/TUIKit/TUISearch/UI_Classic/UI/TUISearchResultListController.m +++ b/iOS/TUIKit/TUISearch/UI_Classic/UI/TUISearchResultListController.m @@ -61,8 +61,9 @@ static NSString *const HFId = @"HFId"; self.navigationController.navigationBar.shadowImage = [UIImage new]; self.view.backgroundColor = [UIColor groupTableViewBackgroundColor]; - UIImage *image = [UIImage imageNamed:@"ic_back_white"]; + UIImage *image = [UIImage imageNamed:TIMCommonImagePath(@"nav_back")]; image = [image imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal]; + image = [image rtl_imageFlippedForRightToLeftLayoutDirection]; UIBarButtonItem *back = [[UIBarButtonItem alloc] initWithImage:image style:UIBarButtonItemStylePlain target:self action:@selector(back)]; self.navigationItem.leftBarButtonItems = @[ back ]; self.navigationItem.leftItemsSupplementBackButton = NO; diff --git a/iOS/TUIKit/TUISearch/UI_Minimalist/Cell/CellUI/TUISearchResultCell_Minimalist.m b/iOS/TUIKit/TUISearch/UI_Minimalist/Cell/CellUI/TUISearchResultCell_Minimalist.m index cdbdcb6ac..f7c55a4f0 100644 --- a/iOS/TUIKit/TUISearch/UI_Minimalist/Cell/CellUI/TUISearchResultCell_Minimalist.m +++ b/iOS/TUIKit/TUISearch/UI_Minimalist/Cell/CellUI/TUISearchResultCell_Minimalist.m @@ -38,12 +38,15 @@ _title_label.text = @""; _title_label.textColor = TIMCommonDynamicColor(@"form_title_color", @"#000000"); _title_label.font = [UIFont boldSystemFontOfSize:14.0]; + _title_label.textAlignment = isRTL()?NSTextAlignmentRight:NSTextAlignmentLeft; [self.contentView addSubview:_title_label]; _detail_title = [[UILabel alloc] init]; _detail_title.text = @""; _detail_title.textColor = TIMCommonDynamicColor(@"form_subtitle_color", @"#888888"); _detail_title.font = [UIFont systemFontOfSize:12.0]; + _detail_title.textAlignment = isRTL()?NSTextAlignmentRight:NSTextAlignmentLeft; + [self.contentView addSubview:_detail_title]; _rowAccessoryView = [[UIImageView alloc] init]; @@ -61,42 +64,6 @@ - (void)layoutSubviews { [super layoutSubviews]; - self.avatarView.mm_x = kScale390(16); - self.avatarView.mm_w = kScale390(40); - self.avatarView.mm_h = kScale390(40); - self.avatarView.mm_centerY = self.contentView.mm_centerY; - if (self.cellModel.avatarType == TAvatarTypeRadiusCorner) { - self.avatarView.layer.cornerRadius = self.avatarView.mm_h / 2; - self.avatarView.layer.masksToBounds = YES; - } - - self.title_label.mm_x = self.avatarView.mm_maxX + 10; - self.detail_title.mm_x = self.avatarView.mm_maxX + 10; - - [self.title_label sizeToFit]; - [self.detail_title sizeToFit]; - - self.rowAccessoryView.mm_height(10).mm_width(10); - self.rowAccessoryView.mm_centerY = self.contentView.mm_centerY; - self.rowAccessoryView.mm_r = 10; - - self.separtorView.frame = CGRectMake(self.detail_title.mm_x, self.contentView.mm_h - 1, self.contentView.mm_w - self.detail_title.mm_x - kScale390(10), 1); - - NSString *title = self.title_label.text; - if (title.length == 0) { - title = self.title_label.attributedText.string; - } - NSString *detail = self.detail_title.text; - if (detail.length == 0) { - detail = self.detail_title.attributedText.string; - } - if (title.length && self.detail_title.text.length) { - self.title_label.mm_y = self.avatarView.mm_y; - self.detail_title.mm_b = self.avatarView.mm_b; - } else { - self.title_label.mm_centerY = self.avatarView.mm_centerY; - self.detail_title.mm_centerY = self.avatarView.mm_centerY; - } } - (void)fillWithData:(TUISearchResultCellModel *)cellModel { @@ -243,6 +210,95 @@ [self.avatarView sd_setImageWithURL:[NSURL URLWithString:faceUrl] placeholderImage:self.cellModel.avatarImage]; } }]; + + // tell constraints they need updating + [self setNeedsUpdateConstraints]; + + // update constraints now so we can animate the change + [self updateConstraintsIfNeeded]; + + [self layoutIfNeeded]; } ++ (BOOL)requiresConstraintBasedLayout { + return YES; +} + +// this is Apple's recommended place for adding/updating constraints +- (void)updateConstraints { + + [super updateConstraints]; + + CGSize headSize = CGSizeMake(kScale390(40), kScale390(40)); + + [self.avatarView mas_remakeConstraints:^(MASConstraintMaker *make) { + make.size.mas_equalTo(headSize); + make.centerY.mas_equalTo(self.contentView.mas_centerY); + make.leading.mas_equalTo(kScale390(16)); + }]; + + if ([TUIConfig defaultConfig].avatarType == TAvatarTypeRounded) { + self.avatarView.layer.masksToBounds = YES; + self.avatarView.layer.cornerRadius = headSize.height / 2; + } else if ([TUIConfig defaultConfig].avatarType == TAvatarTypeRadiusCorner) { + self.avatarView.layer.masksToBounds = YES; + self.avatarView.layer.cornerRadius = [TUIConfig defaultConfig].avatarCornerRadius; + } + + NSString *title = self.title_label.text; + if (title.length == 0) { + title = self.title_label.attributedText.string; + } + NSString *detail = self.detail_title.text; + if (detail.length == 0) { + detail = self.detail_title.attributedText.string; + } + + [self.title_label sizeToFit]; + + [self.detail_title sizeToFit]; + + if (title.length && self.detail_title.text.length) { + [self.title_label mas_remakeConstraints:^(MASConstraintMaker *make) { + make.top.mas_equalTo(self.avatarView.mas_top); + make.leading.mas_equalTo(self.avatarView.mas_trailing).mas_offset(10); + make.trailing.mas_equalTo(self.contentView.mas_trailing).mas_offset(-10); + make.height.mas_greaterThanOrEqualTo(self.title_label.frame.size.height); + }]; + + [self.detail_title mas_remakeConstraints:^(MASConstraintMaker *make) { + make.bottom.mas_equalTo(self.avatarView.mas_bottom); + make.leading.mas_equalTo(self.avatarView.mas_trailing).mas_offset(10); + make.trailing.mas_equalTo(self.contentView.mas_trailing).mas_offset(-10); + make.height.mas_greaterThanOrEqualTo(self.detail_title.frame.size.height); + }]; + } else { + + [self.title_label mas_remakeConstraints:^(MASConstraintMaker *make) { + make.centerY.mas_equalTo(self.avatarView.mas_centerY); + make.leading.mas_equalTo(self.avatarView.mas_trailing).mas_offset(10); + make.trailing.mas_equalTo(self.contentView.mas_trailing).mas_offset(-10); + make.height.mas_greaterThanOrEqualTo(self.title_label.frame.size.height); + }]; + [self.detail_title mas_remakeConstraints:^(MASConstraintMaker *make) { + make.centerY.mas_equalTo(self.avatarView.mas_centerY); + make.leading.mas_equalTo(self.avatarView.mas_trailing).mas_offset(10); + make.trailing.mas_equalTo(self.contentView.mas_trailing).mas_offset(-10); + make.height.mas_greaterThanOrEqualTo(self.title_label.frame.size.height); + }]; + } + + [self.rowAccessoryView mas_remakeConstraints:^(MASConstraintMaker *make) { + make.height.width.mas_equalTo(10); + make.centerY.mas_equalTo(self.contentView); + make.trailing.mas_equalTo(self.contentView.mas_trailing).mas_offset(- 10); + }]; + [self.separtorView mas_remakeConstraints:^(MASConstraintMaker *make) { + make.leading.mas_equalTo(self.detail_title.mas_trailing); + make.bottom.mas_equalTo(self.contentView.mas_bottom).mas_offset(-1); + make.width.mas_equalTo(self.contentView); + make.height.mas_equalTo(1); + }]; + +} @end diff --git a/iOS/TUIKit/TUISearch/UI_Minimalist/UI/TUISearchBar_Minimalist.m b/iOS/TUIKit/TUISearch/UI_Minimalist/UI/TUISearchBar_Minimalist.m index 7150d8526..03836189d 100644 --- a/iOS/TUIKit/TUISearch/UI_Minimalist/UI/TUISearchBar_Minimalist.m +++ b/iOS/TUIKit/TUISearch/UI_Minimalist/UI/TUISearchBar_Minimalist.m @@ -39,6 +39,7 @@ _searchBar.backgroundImage = [UIImage new]; _searchBar.barTintColor = UIColor.redColor; _searchBar.showsCancelButton = NO; + _searchBar.searchTextField.textAlignment = isRTL()?NSTextAlignmentRight:NSTextAlignmentLeft; _searchBar.delegate = self; _searchBar.showsCancelButton = !self.isEntrance; if (@available(iOS 13.0, *)) { @@ -124,6 +125,7 @@ } cancelBtn.enabled = YES; cancelBtn.userInteractionEnabled = YES; + [cancelBtn setTitleColor:[UIColor systemBlueColor] forState:UIControlStateNormal]; [UIBarButtonItem appearanceWhenContainedInInstancesOfClasses:@[ [UISearchBar class] ]].title = TIMCommonLocalizableString(TUIKitSearchItemCancel); ; diff --git a/iOS/TUIKit/TUISearch/UI_Minimalist/UI/TUISearchResultHeaderFooterView_Minimalist.m b/iOS/TUIKit/TUISearch/UI_Minimalist/UI/TUISearchResultHeaderFooterView_Minimalist.m index cf094596c..2163823b3 100644 --- a/iOS/TUIKit/TUISearch/UI_Minimalist/UI/TUISearchResultHeaderFooterView_Minimalist.m +++ b/iOS/TUIKit/TUISearch/UI_Minimalist/UI/TUISearchResultHeaderFooterView_Minimalist.m @@ -72,25 +72,73 @@ self.titleLabel.text = title; } ++ (BOOL)requiresConstraintBasedLayout { + return YES; +} + +// this is Apple's recommended place for adding/updating constraints +- (void)updateConstraints { + + [super updateConstraints]; + if (self.isFooter) { + [self.iconView mas_remakeConstraints:^(MASConstraintMaker *make) { + make.centerY.mas_equalTo(self.contentView); + make.height.width.mas_equalTo(20); + if(isRTL()){ + make.right.mas_equalTo(self.contentView.mas_right).mas_offset(-10); + } + else { + make.left.mas_equalTo(self.contentView.mas_left).mas_offset(10); + } + }]; + [self.titleLabel sizeToFit]; + [self.titleLabel mas_remakeConstraints:^(MASConstraintMaker *make) { + if(isRTL()) { + make.right.mas_equalTo(self.iconView.mas_left).mas_offset(-10); + } + else{ + make.left.mas_equalTo(self.iconView.mas_right).mas_offset(10); + } + make.centerY.mas_equalTo(self.contentView); + make.width.mas_equalTo(self.titleLabel.frame.size.width); + make.height.mas_equalTo(self.titleLabel.font.lineHeight); + }]; + + MASAttachKeys(self.iconView,self.titleLabel); + } else { + [self.titleLabel mas_remakeConstraints:^(MASConstraintMaker *make) { + if(isRTL()) { + make.left.mas_equalTo(self.moreBtn.mas_right).mas_offset(kScale390(16)); + make.right.mas_equalTo(self.contentView.mas_right).mas_offset(-kScale390(16)); + } + else{ + make.left.mas_equalTo(self.contentView.mas_left).mas_offset(kScale390(16)); + make.right.mas_equalTo(self.moreBtn.mas_left).mas_offset(-kScale390(16)); + + } +// make.leading.mas_equalTo(self.contentView.mas_leading).mas_offset(kScale390(16)); + make.centerY.mas_equalTo(self.contentView); +// make.trailing.mas_equalTo(self.contentView.mas_trailing).mas_offset(-10); + make.height.mas_equalTo(self.titleLabel.font.lineHeight); + }]; + [self.moreBtn sizeToFit]; + [self.moreBtn mas_remakeConstraints:^(MASConstraintMaker *make) { + if(isRTL()) { + make.left.mas_equalTo(self.contentView).mas_offset(kScale390(10)); + } + else{ + make.right.mas_equalTo(self.contentView).mas_offset(-kScale390(10)); + } + make.centerY.mas_equalTo(self.contentView.mas_centerY); + make.width.mas_equalTo(self.moreBtn.frame.size.width); + make.height.mas_equalTo(self.moreBtn.frame.size.height); + }]; + + MASAttachKeys(self.titleLabel,self.moreBtn); + } +} - (void)layoutSubviews { [super layoutSubviews]; - - if (self.isFooter) { - self.iconView.mm_height(20).mm_width(20); - self.iconView.mm_centerY = self.contentView.mm_centerY; - self.iconView.mm_x = 10; - [self.titleLabel sizeToFit]; - self.titleLabel.mm_centerY = self.contentView.mm_centerY; - self.titleLabel.mm_x = self.iconView.mm_maxX + 10; - } else { - [self.titleLabel sizeToFit]; - self.titleLabel.mm_centerY = self.contentView.mm_centerY; - self.titleLabel.mm_x = kScale390(16); - [self.moreBtn sizeToFit]; - self.moreBtn.frame = CGRectMake(self.contentView.frame.size.width - self.moreBtn.frame.size.width - kScale390(20), - (self.contentView.frame.size.height - self.moreBtn.frame.size.height) * 0.5, self.moreBtn.frame.size.width, - self.moreBtn.frame.size.height); - } } - (void)setFrame:(CGRect)frame { @@ -131,7 +179,7 @@ [self.contentView addSubview:_titleLabel]; _rowAccessoryView = [[UIImageView alloc] init]; - _rowAccessoryView.image = [UIImage imageNamed:TUISearchImagePath(@"right")]; + _rowAccessoryView.image = [[UIImage imageNamed:TUISearchImagePath(@"right")] rtl_imageFlippedForRightToLeftLayoutDirection]; [self.contentView addSubview:_rowAccessoryView]; _separtorView = [[UIView alloc] init]; @@ -142,6 +190,13 @@ - (void)configPlaceHolderImage:(UIImage *)img imgUrl:(NSString *)imgurl Text:(NSString *)text { [_iconView sd_setImageWithURL:[NSURL URLWithString:imgurl] placeholderImage:img]; _titleLabel.text = text; + // tell constraints they need updating + [self setNeedsUpdateConstraints]; + + // update constraints now so we can animate the change + [self updateConstraintsIfNeeded]; + + [self layoutIfNeeded]; } - (void)tap:(UITapGestureRecognizer *)tap { if (self.onTap) { @@ -154,30 +209,65 @@ self.titleLabel.text = title; } -- (void)layoutSubviews { - [super layoutSubviews]; - - self.iconView.mm_height(kScale390(40)).mm_width(kScale390(40)); - self.iconView.mm_centerY = self.contentView.mm_centerY; - self.iconView.mm_x = kScale390(16); +// this is Apple's recommended place for adding/updating constraints +- (void)updateConstraints { + + [super updateConstraints]; + CGFloat imgWitdh = kScale390(40); + [self.iconView mas_remakeConstraints:^(MASConstraintMaker *make) { + make.centerY.mas_equalTo(self.contentView); + make.height.width.mas_equalTo(kScale390(40)); + if(isRTL()){ + make.right.mas_equalTo(self.contentView.mas_right).mas_offset(-kScale390(16)); + } + else { + make.left.mas_equalTo(self.contentView.mas_left).mas_offset(kScale390(16)); + } + }]; if ([TUIConfig defaultConfig].avatarType == TAvatarTypeRounded) { self.iconView.layer.masksToBounds = YES; - self.iconView.layer.cornerRadius = self.iconView.frame.size.height / 2.0; + self.iconView.layer.cornerRadius = imgWitdh / 2.0; } else if ([TUIConfig defaultConfig].avatarType == TAvatarTypeRadiusCorner) { self.iconView.layer.masksToBounds = YES; self.iconView.layer.cornerRadius = [TUIConfig defaultConfig].avatarCornerRadius; } [self.titleLabel sizeToFit]; - self.titleLabel.mm_centerY = self.contentView.mm_centerY; - self.titleLabel.mm_x = self.iconView.mm_maxX + kScale390(8); - - self.rowAccessoryView.mm_height(10).mm_width(10); - self.rowAccessoryView.mm_centerY = self.contentView.mm_centerY; - self.rowAccessoryView.mm_r = 10; - - self.separtorView.frame = CGRectMake(kScale390(16), self.contentView.mm_h - 1, self.contentView.mm_w, 1); + [self.titleLabel mas_remakeConstraints:^(MASConstraintMaker *make) { + if(isRTL()){ + make.right.mas_equalTo(self.iconView.mas_left).mas_offset(-kScale390(8)); + } + else { + make.left.mas_equalTo(self.iconView.mas_right).mas_offset(kScale390(8)); + } + make.centerY.mas_equalTo(self.contentView); + make.width.mas_equalTo(self.titleLabel.frame.size.width); + make.height.mas_equalTo(self.titleLabel.frame.size.height); + }]; + + [self.rowAccessoryView mas_remakeConstraints:^(MASConstraintMaker *make) { + make.height.width.mas_equalTo(10); + make.centerY.mas_equalTo(self.contentView); + + if(isRTL()){ + make.left.mas_equalTo(self.contentView.mas_left).mas_offset(10); + } + else { + make.right.mas_equalTo(self.contentView.mas_right).mas_offset(-10); + } +// make.trailing.mas_equalTo(self.contentView).mas_offset(-10); + }]; + + [self.separtorView mas_remakeConstraints:^(MASConstraintMaker *make) { + make.leading.mas_equalTo(10); + make.bottom.mas_equalTo(self.contentView).mas_offset(-1); + make.width.mas_equalTo(self.contentView); + make.height.mas_equalTo(1); + }]; +} +- (void)layoutSubviews { + [super layoutSubviews]; } @end diff --git a/iOS/TUIKit/TUISearch/UI_Minimalist/UI/TUISearchResultListController_Minimalist.m b/iOS/TUIKit/TUISearch/UI_Minimalist/UI/TUISearchResultListController_Minimalist.m index 54e104ce4..ee0eb2f5f 100644 --- a/iOS/TUIKit/TUISearch/UI_Minimalist/UI/TUISearchResultListController_Minimalist.m +++ b/iOS/TUIKit/TUISearch/UI_Minimalist/UI/TUISearchResultListController_Minimalist.m @@ -63,8 +63,9 @@ static NSString *const HistoryHFId = @"HistoryHFId"; self.navigationController.navigationBar.shadowImage = [UIImage new]; self.view.backgroundColor = [UIColor whiteColor]; - UIImage *image = [UIImage imageNamed:@"ic_back_white"]; + UIImage *image = [UIImage imageNamed:TIMCommonImagePath(@"nav_back")]; image = [image imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal]; + image = [image rtl_imageFlippedForRightToLeftLayoutDirection]; UIBarButtonItem *back = [[UIBarButtonItem alloc] initWithImage:image style:UIBarButtonItemStylePlain target:self action:@selector(back)]; self.navigationItem.leftBarButtonItems = @[ back ]; self.navigationItem.leftItemsSupplementBackButton = NO;