From a24b1d7dce406eeae5eeb84d537b01d21bd53742 Mon Sep 17 00:00:00 2001 From: fengshuo <963787902@qq.com> Date: Wed, 5 Jan 2022 21:48:21 +0800 Subject: [PATCH] =?UTF-8?q?=E7=9B=B8=E4=BA=B2=E5=8A=A8=E7=94=BB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- xplan-ios.xcodeproj/project.pbxproj | 12 + xplan-ios/Main/IM/Model/AttachmentModel.h | 16 + xplan-ios/Main/Room/Model/DatingInfoModel.h | 49 +++ xplan-ios/Main/Room/Model/DatingInfoModel.m | 12 + xplan-ios/Main/Room/Model/RoomInfoModel.h | 2 + .../View/AnimationView/XPRoomAnimationView.m | 70 ++++ .../AnimationView/XPRoomDatingAnimationView.h | 16 + .../AnimationView/XPRoomDatingAnimationView.m | 365 ++++++++++++++++++ .../Tool/XPRoomMessageParser.m | 51 ++- .../XPRoomMessageContainerView.m | 32 +- .../Main/Room/View/XPRoomViewController.m | 13 +- 11 files changed, 628 insertions(+), 10 deletions(-) create mode 100644 xplan-ios/Main/Room/Model/DatingInfoModel.h create mode 100644 xplan-ios/Main/Room/Model/DatingInfoModel.m create mode 100644 xplan-ios/Main/Room/View/AnimationView/XPRoomDatingAnimationView.h create mode 100644 xplan-ios/Main/Room/View/AnimationView/XPRoomDatingAnimationView.m diff --git a/xplan-ios.xcodeproj/project.pbxproj b/xplan-ios.xcodeproj/project.pbxproj index 294d25e0..64b0eb9d 100644 --- a/xplan-ios.xcodeproj/project.pbxproj +++ b/xplan-ios.xcodeproj/project.pbxproj @@ -260,6 +260,8 @@ E884C36F2743AAC800E1EBED /* AttachmentModel.m in Sources */ = {isa = PBXBuildFile; fileRef = E884C36E2743AAC800E1EBED /* AttachmentModel.m */; }; E884C3722743AEDE00E1EBED /* CustomAttachmentDecoder.m in Sources */ = {isa = PBXBuildFile; fileRef = E884C3712743AEDE00E1EBED /* CustomAttachmentDecoder.m */; }; E8899C7F27853B6A007944BE /* DatingMicroView.m in Sources */ = {isa = PBXBuildFile; fileRef = E8899C7E27853B6A007944BE /* DatingMicroView.m */; }; + E8899C822785A694007944BE /* DatingInfoModel.m in Sources */ = {isa = PBXBuildFile; fileRef = E8899C812785A694007944BE /* DatingInfoModel.m */; }; + E8899C852785CC69007944BE /* XPRoomDatingAnimationView.m in Sources */ = {isa = PBXBuildFile; fileRef = E8899C842785CC69007944BE /* XPRoomDatingAnimationView.m */; }; E88B5CA526FB088600DA9178 /* XPMineTeenagerViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = E88B5CA426FB088600DA9178 /* XPMineTeenagerViewController.m */; }; E88B5CA826FB089C00DA9178 /* XPMineTeenagePwdViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = E88B5CA726FB089C00DA9178 /* XPMineTeenagePwdViewController.m */; }; E88B5CAD26FB16A800DA9178 /* XPMineTeenagerDesView.m in Sources */ = {isa = PBXBuildFile; fileRef = E88B5CAC26FB16A800DA9178 /* XPMineTeenagerDesView.m */; }; @@ -933,6 +935,10 @@ E884C3712743AEDE00E1EBED /* CustomAttachmentDecoder.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = CustomAttachmentDecoder.m; sourceTree = ""; }; E8899C7D27853B6A007944BE /* DatingMicroView.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = DatingMicroView.h; sourceTree = ""; }; E8899C7E27853B6A007944BE /* DatingMicroView.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = DatingMicroView.m; sourceTree = ""; }; + E8899C802785A694007944BE /* DatingInfoModel.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = DatingInfoModel.h; sourceTree = ""; }; + E8899C812785A694007944BE /* DatingInfoModel.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = DatingInfoModel.m; sourceTree = ""; }; + E8899C832785CC69007944BE /* XPRoomDatingAnimationView.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = XPRoomDatingAnimationView.h; sourceTree = ""; }; + E8899C842785CC69007944BE /* XPRoomDatingAnimationView.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = XPRoomDatingAnimationView.m; sourceTree = ""; }; E88B5CA326FB088600DA9178 /* XPMineTeenagerViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = XPMineTeenagerViewController.h; sourceTree = ""; }; E88B5CA426FB088600DA9178 /* XPMineTeenagerViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = XPMineTeenagerViewController.m; sourceTree = ""; }; E88B5CA626FB089C00DA9178 /* XPMineTeenagePwdViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = XPMineTeenagePwdViewController.h; sourceTree = ""; }; @@ -1940,6 +1946,8 @@ E89D60C0271D64B9001F8895 /* RoomInfoModel.m */, E8252FEC27687DF1002B3164 /* ActivityInfoModel.h */, E8252FED27687DF1002B3164 /* ActivityInfoModel.m */, + E8899C802785A694007944BE /* DatingInfoModel.h */, + E8899C812785A694007944BE /* DatingInfoModel.m */, ); path = Model; sourceTree = ""; @@ -2217,6 +2225,8 @@ E83DB4832746661800D8CBD1 /* XPRoomGiftBroadcastView.m */, E8A03DFD27635F960098D9EA /* XPRoomCandyGiftView.h */, E8A03DFE27635F960098D9EA /* XPRoomCandyGiftView.m */, + E8899C832785CC69007944BE /* XPRoomDatingAnimationView.h */, + E8899C842785CC69007944BE /* XPRoomDatingAnimationView.m */, E838D99E275E1BF60079E0B5 /* XPRoomAnimationView.h */, E838D99F275E1BF60079E0B5 /* XPRoomAnimationView.m */, ); @@ -3673,12 +3683,14 @@ E8B846BF26FD827900A777FE /* XPMineUserInfoAlbumViewController.m in Sources */, E824545C26F5EEBA00BE8163 /* XPMineVerifIdentityPresenter.m in Sources */, E8A1E44E2761F98600B294CA /* XPCandyTreeViewController.m in Sources */, + E8899C852785CC69007944BE /* XPRoomDatingAnimationView.m in Sources */, E84BF7D4277C383700EF8877 /* XPRoomSettingInputView.m in Sources */, E8AC723726F49982007D6E91 /* XPMineNotificaProtocol.h in Sources */, E896EFAC2771AEFE00AD2CC1 /* XPMineFriendTableViewCell.m in Sources */, E8412FA22779BE8F006E1101 /* XPRoomSettingViewController.m in Sources */, E89D60BD271D647A001F8895 /* XPRoomPresenter.m in Sources */, E80DE4072775665000BE5BCB /* XPFirstRechargeCollectionViewCell.m in Sources */, + E8899C822785A694007944BE /* DatingInfoModel.m in Sources */, E8C6FFD72754BC61004DC9F0 /* XPHomeNavView.m in Sources */, E8AC723226F49710007D6E91 /* XPMineNotificationTableViewCell.m in Sources */, E8AC722926F488DA007D6E91 /* XPMineFeedbackProtocol.h in Sources */, diff --git a/xplan-ios/Main/IM/Model/AttachmentModel.h b/xplan-ios/Main/IM/Model/AttachmentModel.h index 6ff2a157..6db202bb 100644 --- a/xplan-ios/Main/IM/Model/AttachmentModel.h +++ b/xplan-ios/Main/IM/Model/AttachmentModel.h @@ -38,8 +38,11 @@ typedef NS_ENUM(NSUInteger, CustomMessageType) { CustomMessageType_Collection_Room = 59, ///福袋消息 CustomMessageType_LuckyBag = 61, + ///相亲 + CustomMessageType_RoomPlay_Dating = 72, ///首充奖励 CustomMessageType_First_Recharge_Reward = 76, + }; @@ -181,6 +184,19 @@ typedef NS_ENUM(NSUInteger, CustomMessageSubLuckyBag) { Custom_Message_Sub_Collect_Room_Remind_User = 592, }; + +///CustomMessageType_RoomPlay_Dating +typedef NS_ENUM(NSUInteger, CustomMessageSubRoomPlayDating){ + ///选择心动用户 + Custom_Message_Sub_Room_Play_Dating_Pick_Heart= 721, + ///公布结果 + Custom_Message_Sub_Room_Play_Dating_Public_Result = 722, + ///选择了对象 但不是互选 客户端收到结果之后自动加到 公屏上 + Custom_Message_Sub_Room_Play_Dating_Result_Not_Mutual = 723, + ///互选的 客户端收到结果之后自动加到 公屏上 + Custom_Message_Sub_Room_Play_Dating_Result_Mutual = 724, +}; + ///first = CustomMessageType_First_Recharge_Reward typedef NS_ENUM(NSUInteger, CustomMessageSubFirstRecharge) { /// 首充完成 diff --git a/xplan-ios/Main/Room/Model/DatingInfoModel.h b/xplan-ios/Main/Room/Model/DatingInfoModel.h new file mode 100644 index 00000000..e6c9f19e --- /dev/null +++ b/xplan-ios/Main/Room/Model/DatingInfoModel.h @@ -0,0 +1,49 @@ +// +// DatingInfoModel.h +// xplan-ios +// +// Created by 冯硕 on 2022/1/5. +// + +#import +#import "XPEnum.h" +NS_ASSUME_NONNULL_BEGIN + +@interface DatingInfoModel : NSObject +///头像 +@property (nonatomic,strong) NSString *avatar; +///操作用户uid +@property (nonatomic,assign) NSInteger uid; +///操作用户昵称 +@property (nonatomic,strong) NSString *nickname; +///当前操作的坑位 +@property (nonatomic,assign) int position; +///目标用户uid +@property (nonatomic,assign) NSInteger targetUid; +///目标用户昵称 +@property (nonatomic,strong) NSString *targetNickname; +///目标的头像 +@property (nonatomic,strong) NSString *targetAvatar; +///操作用户麦位 +@property (nonatomic,assign) int targetPosition; +///相亲步骤变更提示文案 +@property (nonatomic,strong) NSString *content; +///是否有互选对象 +@property (nonatomic,assign) BOOL hasHeart; +///是否有选择的对象 +@property (nonatomic,assign) BOOL hasSelectUser; +/// 1 男性, 2 女性。 +@property (nonatomic, assign) GenderType gender; +///目标用户的性别 +@property (nonatomic,assign) GenderType targetGender; +///互选的时候动画 +@property (nonatomic,strong) NSString *svgaUrl; +///SVGA的时长 +@property (nonatomic,assign) int svgaSecond; +///起始地址的 +@property (nonatomic,assign) CGPoint originPoint; +///目标地址的坐标 +@property (nonatomic,assign) CGPoint targetPoint; +@end + +NS_ASSUME_NONNULL_END diff --git a/xplan-ios/Main/Room/Model/DatingInfoModel.m b/xplan-ios/Main/Room/Model/DatingInfoModel.m new file mode 100644 index 00000000..e669dcdd --- /dev/null +++ b/xplan-ios/Main/Room/Model/DatingInfoModel.m @@ -0,0 +1,12 @@ +// +// DatingInfoModel.m +// xplan-ios +// +// Created by 冯硕 on 2022/1/5. +// + +#import "DatingInfoModel.h" + +@implementation DatingInfoModel + +@end diff --git a/xplan-ios/Main/Room/Model/RoomInfoModel.h b/xplan-ios/Main/Room/Model/RoomInfoModel.h index f708c797..e7b12680 100644 --- a/xplan-ios/Main/Room/Model/RoomInfoModel.h +++ b/xplan-ios/Main/Room/Model/RoomInfoModel.h @@ -101,6 +101,8 @@ typedef NS_ENUM(NSInteger, RoomPlayDateingType) { @property(nonatomic, assign) BOOL isRoomFans; ///当前相亲所进行到什么模式 @property (nonatomic,assign) RoomPlayDateingType blindDateState; +///本地字段 判断是否开启了 相亲模式 +@property (nonatomic,assign) BOOL isOpenRoomDating; @end NS_ASSUME_NONNULL_END diff --git a/xplan-ios/Main/Room/View/AnimationView/XPRoomAnimationView.m b/xplan-ios/Main/Room/View/AnimationView/XPRoomAnimationView.m index c662425d..e125a3bc 100644 --- a/xplan-ios/Main/Room/View/AnimationView/XPRoomAnimationView.m +++ b/xplan-ios/Main/Room/View/AnimationView/XPRoomAnimationView.m @@ -28,10 +28,12 @@ #import "XPGiftBannerUserInfoModel.h" #import "XPRoomGiftBroadCastModel.h" #import "XPMessageRemoteExtModel.h" +#import "DatingInfoModel.h" ///View #import "XPRoomGiftBannerView.h" #import "XPRoomGiftBroadcastView.h" #import "XPRoomCandyGiftView.h" +#import "XPRoomDatingAnimationView.h" @interface XPRoomAnimationView () @@ -81,6 +83,9 @@ #pragma mark - 进房动画的 @property (nonatomic, strong) NSMutableArray *enterEffectQueue; @property (nonatomic,strong) SVGAImageView *enterEffectView; +#pragma mark - 相亲动画的 +@property (nonatomic, strong) NSMutableArray *datingEffectQueue; +@property (nonatomic,strong) SVGAImageView *datingEffectView; @end @implementation XPRoomAnimationView @@ -155,6 +160,8 @@ [self receiveCandyTreeGiftHighLevle:attachment]; } else if (attachment.first == CustomMessageType_Car_Notify && attachment.second == Custom_Message_Sub_Car_EnterRoom ) {//座驾进房 [self receiveDriveCarEnterRoom:attachment]; + } else if(attachment.first == CustomMessageType_RoomPlay_Dating && attachment.second == Custom_Message_Sub_Room_Play_Dating_Public_Result) { + [self roomDatingPublicResult:attachment]; } } } @@ -169,6 +176,53 @@ [self userEnterRoom:content ext:extModel]; } } +#pragma mark - 相亲 动画 +- (void)roomDatingPublicResult:(AttachmentModel *)attachment { + self.datingEffectQueue = [NSMutableArray array]; + ///心动结果公布的话 结果是一个数组 + NSArray * results = [DatingInfoModel modelsWithArray:attachment.data[@"list"]]; + [self.datingEffectQueue addObjectsFromArray:results]; + if (self.datingEffectQueue.count > 0) { + [self startDatingAnimation:self.datingEffectQueue.firstObject]; + } +} + +- (void)startDatingAnimation:(DatingInfoModel *)datingModel { + [[NSNotificationCenter defaultCenter] postNotificationName:@"message" object:[self createRoomDatingResultMessage:datingModel]]; + NSString * targetUid= [NSString stringWithFormat:@"%ld", datingModel.targetUid]; + NSString * uid= [NSString stringWithFormat:@"%ld", datingModel.uid]; + if (datingModel.hasHeart || datingModel.hasSelectUser) { + datingModel.originPoint = [self.delegate centerForUserAtUid:uid]; + datingModel.targetPoint = [self.delegate centerForUserAtUid:targetUid]; + } + XPRoomDatingAnimationView * datingView = [[XPRoomDatingAnimationView alloc] init]; + [self.highLevleView addSubview:datingView]; + [datingView startAnimationWithModel:datingModel finishBlock:^(BOOL finish) { + [self.datingEffectQueue removeObject:datingModel]; + if (self.datingEffectQueue > 0) { + DatingInfoModel * datingModel = [self.datingEffectQueue firstObject]; + [self startDatingAnimation:datingModel]; + } + }]; +} + +- (NIMMessage *)createRoomDatingResultMessage:(DatingInfoModel *)datingModel { + NIMMessage * message = [[NIMMessage alloc] init]; + NIMSession * session = [NIMSession session:[NSString stringWithFormat:@"%ld", self.delegate.getRoomInfo.roomId] type:NIMSessionTypeChatroom]; + [message setValue:session forKey:@"session"]; + AttachmentModel * attach = [[AttachmentModel alloc] init]; + attach.first = CustomMessageType_RoomPlay_Dating; + if (datingModel.hasHeart) {///如果是互选的话 + attach.second = Custom_Message_Sub_Room_Play_Dating_Result_Mutual; + } else { + attach.second = Custom_Message_Sub_Room_Play_Dating_Result_Not_Mutual; + } + attach.data = [datingModel model2dictionary]; + NIMCustomObject * object = [[NIMCustomObject alloc] init]; + object.attachment = attach; + message.messageObject = object; + return message; +} #pragma mark - 进房动画 XXX来了 - (void)userEnterRoom:(NIMChatroomNotificationContent *)content ext:(XPMessageRemoteExtModel *)extModel { @@ -1033,4 +1087,20 @@ return _enterEffectView; } + +- (SVGAImageView *)datingEffectView { + if (_datingEffectView == nil) { + _datingEffectView = [[SVGAImageView alloc]init]; + _datingEffectView.delegate = self; + _datingEffectView.contentMode = UIViewContentModeScaleAspectFit; + _datingEffectView.frame = CGRectMake(0, 0, KScreenWidth, KScreenHeight); + _datingEffectView.backgroundColor = [UIColor clearColor]; + _datingEffectView.alpha = 0; + _datingEffectView.userInteractionEnabled = NO; + } + return _datingEffectView; +} + + + @end diff --git a/xplan-ios/Main/Room/View/AnimationView/XPRoomDatingAnimationView.h b/xplan-ios/Main/Room/View/AnimationView/XPRoomDatingAnimationView.h new file mode 100644 index 00000000..d58cd8e6 --- /dev/null +++ b/xplan-ios/Main/Room/View/AnimationView/XPRoomDatingAnimationView.h @@ -0,0 +1,16 @@ +// +// XPRoomDatingAnimationView.h +// xplan-ios +// +// Created by 冯硕 on 2022/1/5. +// + +#import + +NS_ASSUME_NONNULL_BEGIN +@class DatingInfoModel; +@interface XPRoomDatingAnimationView : UIView +- (void)startAnimationWithModel:(DatingInfoModel *)model finishBlock:(void (^)(BOOL))finishBlock; +@end + +NS_ASSUME_NONNULL_END diff --git a/xplan-ios/Main/Room/View/AnimationView/XPRoomDatingAnimationView.m b/xplan-ios/Main/Room/View/AnimationView/XPRoomDatingAnimationView.m new file mode 100644 index 00000000..880a97ed --- /dev/null +++ b/xplan-ios/Main/Room/View/AnimationView/XPRoomDatingAnimationView.m @@ -0,0 +1,365 @@ +// +// XPRoomDatingAnimationView.m +// xplan-ios +// +// Created by 冯硕 on 2022/1/5. +// + +#import "XPRoomDatingAnimationView.h" +///Third +#import +#import +#import +///Model +#import "XPMacro.h" +#import "ThemeColor.h" +#import "UIButton+EnlargeTouchArea.h" +///Model +#import "DatingInfoModel.h" + +@interface XPRoomDatingAnimationView () +///背景 +@property (nonatomic,strong) UIView *backView; +///动画管理类 +@property (strong, nonatomic) SVGAParser *parser; +///播放相亲结果的SVGA +@property (nonatomic, strong) SVGAImageView *datingSvgaImageView; +///倒计时的背景 +@property (nonatomic,strong) UIView *cutTimeBackView; +///倒计时 +@property (nonatomic,strong) UILabel *timeLabel; +///分割线 +@property (nonatomic,strong) UIView *lineView; +///关闭的按钮 +@property (nonatomic,strong) UIButton *closeButton; +///❤的动画 +@property (nonatomic,strong) UIImageView *heartImageView; +/// +@property (nonatomic,copy) void(^FinishBlock)(BOOL result); +/// 定时器 +@property (nonatomic,strong) id timer; +@end + +@implementation XPRoomDatingAnimationView + +- (instancetype)initWithFrame:(CGRect)frame { + if (self = [super initWithFrame:frame]) { + [self addSubview:self.backView]; + [self addSubview:self.datingSvgaImageView]; + [self addSubview:self.cutTimeBackView]; + [self addSubview:self.heartImageView]; + [self.cutTimeBackView addSubview:self.timeLabel]; + [self.cutTimeBackView addSubview:self.lineView]; + [self.cutTimeBackView addSubview:self.closeButton]; + [self initContrations]; + } + return self; +} +#pragma mark - Resonse +- (void)closetButtonAction:(UIButton *)sender { + if (self.FinishBlock) { + [NSObject cancelPreviousPerformRequestsWithTarget:self]; + self.FinishBlock(YES); + } +} + +#pragma mark - Pirvate Method +- (void)initContrations { + [self mas_makeConstraints:^(MASConstraintMaker *make) { + make.width.mas_equalTo(KScreenWidth); + make.height.mas_equalTo(KScreenHeight); + }]; + + [self.backView mas_makeConstraints:^(MASConstraintMaker *make) { + make.edges.mas_equalTo(self); + }]; + + [self.cutTimeBackView mas_makeConstraints:^(MASConstraintMaker *make) { + make.size.mas_equalTo(CGSizeMake(70, 25)); + make.right.mas_equalTo(self).offset(-12); + make.top.mas_equalTo(self).offset(41 + kSafeAreaTopHeight); + }]; + + [self.timeLabel mas_makeConstraints:^(MASConstraintMaker *make) { + make.left.mas_equalTo(self.cutTimeBackView).offset(13); + make.centerY.mas_equalTo(self.cutTimeBackView); + }]; + + [self.lineView mas_makeConstraints:^(MASConstraintMaker *make) { + make.center.mas_equalTo(self.cutTimeBackView); + make.size.mas_equalTo(CGSizeMake(0.5, 13)); + }]; + + [self.closeButton mas_makeConstraints:^(MASConstraintMaker *make) { + make.size.mas_equalTo(CGSizeMake(14, 14)); + make.centerY.mas_equalTo(self.cutTimeBackView); + make.left.mas_equalTo(self.lineView.mas_right).offset(8); + }]; +} + +- (void)stopAnimation { + if (self.FinishBlock) { + [NSObject cancelPreviousPerformRequestsWithTarget:self]; + self.FinishBlock(YES); + } +} + +- (UIImage *)setCornerWithRadius:(CGFloat)radius andSize:(CGSize)size image:(UIImage *)image { + //开启图形上下文 + UIGraphicsBeginImageContext(size); + //绘制圆角矩形 + CGRect rect = CGRectMake(0, 0, size.width, size.height); + UIBezierPath *path = [UIBezierPath bezierPathWithRoundedRect:rect byRoundingCorners:UIRectCornerAllCorners cornerRadii:CGSizeMake(radius, radius)]; + //将Path添加到上下文中 + CGContextAddPath(UIGraphicsGetCurrentContext(), path.CGPath); + //裁剪上下文 + CGContextClip(UIGraphicsGetCurrentContext()); + //将图片绘制到上下文中 + [image drawInRect:rect]; + //设置绘制模式 + CGContextDrawPath(UIGraphicsGetCurrentContext(), kCGPathStroke); + //获取图片 + UIImage *output = UIGraphicsGetImageFromCurrentImageContext(); + //关闭上下文 + UIGraphicsEndImageContext(); + //返回裁剪好的图片 + return output; +} + +- (CAAnimationGroup *)createRoomDatingPickAnimatioOriginPoint:(CGPoint)orginPoint destinationPoint:(CGPoint)destinationPoint { + ///刚出来的时候 进行慢慢放大的效果 + CAKeyframeAnimation * scaleAnimation = [CAKeyframeAnimation animationWithKeyPath:@"transform.scale"]; + scaleAnimation.duration = 0.5; + scaleAnimation.repeatCount = 1; + scaleAnimation.values = @[@(0),@(0.2),@(0.4), @(0.6), @(0.8), @(0.9), @(1)]; + scaleAnimation.calculationMode = kCAAnimationCubic; + scaleAnimation.removedOnCompletion = NO; + scaleAnimation.fillMode = kCAFillModeForwards; + /// + CAKeyframeAnimation * transformAnimation = [CAKeyframeAnimation animationWithKeyPath:@"position"]; + transformAnimation.beginTime = 0.5; + transformAnimation.duration = 1; + transformAnimation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseOut];; + transformAnimation.values = @[[NSValue valueWithCGPoint:orginPoint],[NSValue valueWithCGPoint:destinationPoint]]; + transformAnimation.repeatCount = 1; + transformAnimation.removedOnCompletion = NO; + transformAnimation.fillMode = kCAFillModeForwards; + + CAKeyframeAnimation * desScaleformAnimation = [CAKeyframeAnimation animationWithKeyPath:@"transform.scale"]; + desScaleformAnimation.beginTime = 1.5; + desScaleformAnimation.duration = 0.5; + desScaleformAnimation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseOut];; + desScaleformAnimation.values = @[@(1), @(1.2), @(1.4), @(1.6)]; + desScaleformAnimation.repeatCount = 1; + desScaleformAnimation.removedOnCompletion = NO; + desScaleformAnimation.fillMode = kCAFillModeForwards; + + + CAKeyframeAnimation * opacityAnimation = [CAKeyframeAnimation animationWithKeyPath:@"opacity"]; + opacityAnimation.beginTime = 1.5; + opacityAnimation.duration = 0.5; + opacityAnimation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseOut];; + opacityAnimation.values = @[@(1),@(0.8),@(0.6),@(0)]; + opacityAnimation.repeatCount = 1; + opacityAnimation.removedOnCompletion = NO; + opacityAnimation.fillMode = kCAFillModeForwards; + + + CAAnimationGroup * group = [CAAnimationGroup animation]; + group.animations = @[scaleAnimation, transformAnimation, desScaleformAnimation, opacityAnimation]; + group.duration = 2; + group.removedOnCompletion = NO; + group.fillMode = kCAFillModeForwards; + return group;; +} + +- (void)startBeginCutCountWithTotalTime:(int)time { + __block int totalTime = time; + dispatch_source_t times = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, dispatch_get_global_queue(0, 0)); + _timer = times; + dispatch_source_set_timer(times, DISPATCH_TIME_NOW, 1* NSEC_PER_SEC, 0 * NSEC_PER_SEC); + dispatch_source_set_event_handler(times, ^{ + dispatch_async(dispatch_get_main_queue(), ^{ + if (totalTime <= 5 && totalTime >= 0) { + ///开始显示倒计时 + self.cutTimeBackView.hidden = NO; + self.timeLabel.text = [NSString stringWithFormat:@"%ds", totalTime]; + } + if (totalTime <= 0) { + dispatch_source_cancel(times); + self.cutTimeBackView.hidden = YES; + } + totalTime--; + }); + }); + dispatch_resume(times); +} + +- (void)startPickHeartPersonAnimationOriginPoint:(CGPoint)originPoint targetPoint:(CGPoint)targetPoint { + if (originPoint.x > 0 && targetPoint.x > 0) { + self.heartImageView.frame = CGRectMake(0, 0, 55, 55); + self.heartImageView.hidden = YES; + self.backView.hidden = YES; + self.heartImageView.hidden = NO; + self.heartImageView.center = originPoint; + CAAnimationGroup * group = [self createRoomDatingPickAnimatioOriginPoint:originPoint destinationPoint:targetPoint]; + [self.heartImageView.layer addAnimation:group forKey:nil]; + [self performSelector:@selector(aniationDidFinish:) withObject:self.heartImageView afterDelay:(2)]; + } +} + +- (void)aniationDidFinish:(UIImageView *)giftImageView{ + [giftImageView.layer removeAllAnimations]; + giftImageView.hidden = YES; +} + +#pragma mark - Public Method + +- (void)startAnimationWithModel:(DatingInfoModel *)model finishBlock:(void (^)(BOOL))finishBlock { + self.FinishBlock = finishBlock; + if (model.hasHeart) { + if (model.svgaUrl) { + [self startPalySVGAWithUrl:model]; + } else { + ///如果是心动选人的话 但是没有SVGA的话 直接结束 + ///播完之后直接结束这次 + if (self.FinishBlock) { + self.FinishBlock(YES); + } + } + } else { + ///不是心动选人的话 那就不用播两次 爱心的动画 + [self startPickHeartPersonAnimationOriginPoint:model.originPoint targetPoint:model.targetPoint]; + dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ + ///心动结束了 直接结束此次 + if (self.FinishBlock) { + self.FinishBlock(YES); + } + }); + } + +} + +///播放SVGA的时候 需要先播放选人的动画 +- (void)startPalySVGAWithUrl:(DatingInfoModel *)model { + if (model.svgaUrl) { + self.backView.hidden = NO; + [[SDWebImageManager sharedManager] loadImageWithURL:[NSURL URLWithString:model.avatar] options:SDWebImageRetryFailed progress:nil completed:^(UIImage * _Nullable image, NSData * _Nullable data, NSError * _Nullable error, SDImageCacheType cacheType, BOOL finished, NSURL * _Nullable imageURL) { + if (image) { + image = [self setCornerWithRadius:200 andSize:CGSizeMake(400, 400) image:image]; + [self.datingSvgaImageView setImage:image forKey:@"z_tx"]; + } + }]; + + NSString * title = model.nickname ? model.nickname : @""; + if (title.length >= 5) { + title = [NSString stringWithFormat:@"%@…", [title substringToIndex:5]]; + } + NSMutableAttributedString * rightAttribut = [[NSMutableAttributedString alloc] initWithString:title]; + [rightAttribut addAttributes:@{NSFontAttributeName:[UIFont systemFontOfSize:28], NSForegroundColorAttributeName:[UIColor whiteColor]} range:NSMakeRange(0, title.length)]; + [self.datingSvgaImageView setAttributedText:rightAttribut forKey:@"z_yhname"]; + + [[SDWebImageManager sharedManager] loadImageWithURL:[NSURL URLWithString:model.targetAvatar] options:SDWebImageRetryFailed progress:nil completed:^(UIImage * _Nullable image, NSData * _Nullable data, NSError * _Nullable error, SDImageCacheType cacheType, BOOL finished, NSURL * _Nullable imageURL) { + if (image) { + image = [self setCornerWithRadius:200 andSize:CGSizeMake(400, 400) image:image]; + [self.datingSvgaImageView setImage:image forKey:@"y_tx"]; + } + }]; + NSString * leftTitle = model.targetNickname ? model.targetNickname : @""; + if (leftTitle.length >= 5) { + leftTitle = [NSString stringWithFormat:@"%@…", [leftTitle substringToIndex:5]]; + } + NSMutableAttributedString * leftAttribut = [[NSMutableAttributedString alloc] initWithString:leftTitle]; + [leftAttribut addAttributes:@{NSFontAttributeName:[UIFont systemFontOfSize:28], NSForegroundColorAttributeName:[UIColor whiteColor]} range:NSMakeRange(0, leftTitle.length)]; + [self.datingSvgaImageView setAttributedText:leftAttribut forKey:@"y_yhname"]; + @kWeakify(self); + [self.parser parseWithURL:[NSURL URLWithString:model.svgaUrl] completionBlock:^(SVGAVideoEntity * _Nonnull videoItem) { + @kStrongify(self); + self.datingSvgaImageView.hidden = NO; + self.datingSvgaImageView.videoItem = videoItem; + self.datingSvgaImageView.loops = 1; + self.datingSvgaImageView.clearsAfterStop = YES; + [ self.datingSvgaImageView startAnimation]; + [self startBeginCutCountWithTotalTime:model.svgaSecond]; + } failureBlock:^(NSError * _Nonnull error) { + + }]; + [self performSelector:@selector(stopAnimation) withObject:nil afterDelay:model.svgaSecond]; + } +} + +- (UIImageView *)heartImageView { + if (!_heartImageView) { + _heartImageView = [[UIImageView alloc] init]; + _heartImageView.image = [UIImage imageNamed:@"room_dating_pick_heart"]; + _heartImageView.hidden = YES; + } + return _heartImageView; +} + +- (UIView *)backView { + if (!_backView) { + _backView = [[UIView alloc] init]; + _backView.backgroundColor = UIColorRGBAlpha(0x000000, 0.3); + _backView.hidden = YES; + } + return _backView; +} + +- (UILabel *)timeLabel { + if (!_timeLabel) { + _timeLabel = [[UILabel alloc] init]; + _timeLabel.text = @"5S"; + _timeLabel.font = [UIFont systemFontOfSize:15]; + _timeLabel.textColor = UIColorFromRGB(0xFFFEFE); + } + return _timeLabel; +} + +- (UIView *)cutTimeBackView { + if (!_cutTimeBackView) { + _cutTimeBackView = [[UIView alloc] init]; + _cutTimeBackView.backgroundColor = UIColorRGBAlpha(0x000000, 0.3); + _cutTimeBackView.layer.masksToBounds = YES; + _cutTimeBackView.layer.cornerRadius = 25/2; + _cutTimeBackView.hidden = YES; + } + return _cutTimeBackView; +} + +- (UIButton *)closeButton { + if (!_closeButton) { + _closeButton = [UIButton buttonWithType: UIButtonTypeCustom]; + [_closeButton setImage:[UIImage imageNamed:@"common_close_white_icon"] forState:UIControlStateNormal]; + [_closeButton addTarget:self action:@selector(closetButtonAction:) forControlEvents:UIControlEventTouchUpInside]; + [_closeButton setEnlargeEdgeWithTop:10 right:10 bottom:10 left:10]; + } + return _closeButton; +} + +- (UIView *)lineView { + if (!_lineView) { + _lineView = [[UIView alloc] init]; + _lineView.backgroundColor = UIColor.whiteColor; + } + return _lineView; +} + +- (SVGAParser *)parser { + if (!_parser) { + _parser = [[SVGAParser alloc]init]; + } + return _parser; +} + +- (SVGAImageView *)datingSvgaImageView { + if (!_datingSvgaImageView) { + _datingSvgaImageView = [[SVGAImageView alloc]init]; + _datingSvgaImageView.backgroundColor = [UIColor clearColor]; + _datingSvgaImageView.frame = self.bounds; + _datingSvgaImageView.userInteractionEnabled = YES; + } + return _datingSvgaImageView; +} + +@end diff --git a/xplan-ios/Main/Room/View/MessageContainerView/Tool/XPRoomMessageParser.m b/xplan-ios/Main/Room/View/MessageContainerView/Tool/XPRoomMessageParser.m index 784b7d8d..fdd5253f 100644 --- a/xplan-ios/Main/Room/View/MessageContainerView/Tool/XPRoomMessageParser.m +++ b/xplan-ios/Main/Room/View/MessageContainerView/Tool/XPRoomMessageParser.m @@ -24,6 +24,7 @@ #import "UserInfoModel.h" #import "MicroStateModel.h" #import "RoomInfoModel.h" +#import "DatingInfoModel.h" #import "NetImageView.h" @@ -74,6 +75,8 @@ return [self createRoomInfoUpdateAttribute:attachment]; } else if(first == CustomMessageType_Collection_Room) { return [self createCollectRoomAttribute:attachment]; + } else if(first == CustomMessageType_RoomPlay_Dating) { + return [self createRoomDatingAttribute:attachment]; } return nil; } @@ -108,7 +111,7 @@ /// 房间tips消息 /// @param message 消息的实体 - (NSAttributedString*)makeTipsAttribute:(NIMMessage *)message { - return [self createTextAttribute:message.text color:[ThemeColor messageDefaultTextColor] font:kRoomMessageDefalutFont]; + return [self createTextAttribute:message.text color:UIColorFromRGB(0xFE5D7F) font:kRoomMessageDefalutFont]; } /// 房间通知类消息 @@ -142,9 +145,18 @@ return attribute; } break; + case NIMChatroomEventTypeInfoUpdated:{ + NSMutableAttributedString * attribute = [[NSMutableAttributedString alloc] init]; + if (self.hostDelegate.getRoomInfo.isOpenRoomDating) { + [attribute appendAttributedString:[self createTextAttribute:@"相亲玩法已开启,请点击主持人麦位选择主持人" color:[ThemeColor messageDefaultTextColor] font:kRoomMessageDefalutFont]]; + return attribute; + } + } + break; default: return nil; } + return nil; } #pragma mark - 收藏房间 @@ -188,6 +200,43 @@ return nil; } +#pragma mark - 相亲 +- (NSAttributedString *)createRoomDatingAttribute:(AttachmentModel *)attachment { + NSMutableAttributedString * attribute = [[NSMutableAttributedString alloc] init]; + if(attachment.second == Custom_Message_Sub_Room_Play_Dating_Pick_Heart) { + DatingInfoModel * datingModel = [DatingInfoModel modelWithDictionary:attachment.data]; + NSString * targetGender = datingModel.targetGender == GenderType_Male ? @"男" : @"女"; + NSString * pickString = [NSString stringWithFormat:@"%d号%@嘉宾:", (datingModel.targetPosition + 1), targetGender]; + [attribute appendAttributedString:[self createTextAttribute:@"本轮你选择了" color:[ThemeColor messageTextColor] font:kRoomMessageDefalutFont]]; + [attribute appendAttributedString:[self createTextAttribute:pickString color:[ThemeColor messageTextColor] font:kRoomMessageDefalutFont]]; + NSString * targetNick = datingModel.targetNickname ? datingModel.targetNickname : @""; + [attribute appendAttributedString:[self createNickAtrribute:targetNick uid:datingModel.targetUid]]; + NSString * heartContent = @"作为你的心动对象"; + [attribute appendAttributedString:[self createTextAttribute:heartContent color:[ThemeColor messageTextColor] font:kRoomMessageDefalutFont]]; + } else if(attachment.second == Custom_Message_Sub_Room_Play_Dating_Result_Mutual) {///互选 + DatingInfoModel * datingModel = [DatingInfoModel modelWithDictionary:attachment.data]; + [attribute appendAttributedString:[self createTextAttribute:@"恭喜" color:[ThemeColor messageTextColor] font:kRoomMessageDefalutFont]]; + NSString * nick = datingModel.nickname ? datingModel.nickname : @""; + [attribute appendAttributedString:[self createNickAtrribute:nick uid:datingModel.uid]]; + [attribute appendAttributedString:[self createTextAttribute:@"和" color:[ThemeColor messageTextColor] font:kRoomMessageDefalutFont]]; + NSString * targetNick = datingModel.targetNickname ? datingModel.targetNickname : @""; + [attribute appendAttributedString:[self createNickAtrribute:targetNick uid:datingModel.targetUid]]; + [attribute appendAttributedString:[self createTextAttribute:@"牵手成功,让我们见证他们幸福的开端" color:UIColorFromRGB(0xF84C95) font:kRoomMessageDefalutFont]]; + } else if (attachment.second == Custom_Message_Sub_Room_Play_Dating_Result_Not_Mutual) {///不是互选 + DatingInfoModel * datingModel = [DatingInfoModel modelWithDictionary:attachment.data]; + NSString * nick = datingModel.nickname ? datingModel.nickname : @""; + [attribute appendAttributedString:[self createNickAtrribute:nick uid:datingModel.uid]]; + if (datingModel.hasSelectUser) {//选择的有人 + [attribute appendAttributedString:[self createTextAttribute:@"的心动对象是" color:[ThemeColor messageTextColor] font:kRoomMessageDefalutFont]]; + NSString * targetNick = datingModel.targetNickname ? datingModel.targetNickname : @""; + [attribute appendAttributedString:[self createNickAtrribute:targetNick uid:datingModel.targetUid]]; + } else {///没有选择人 + [attribute appendAttributedString:[self createTextAttribute:@"未选择心动对象" color:[ThemeColor messageTextColor] font:kRoomMessageDefalutFont]]; + } + } + return attribute; +} + #pragma mark - 排麦 - (NSAttributedString *)createArrangeMicAttribute:(AttachmentModel *)attachment { NSMutableAttributedString * attribute = [[NSMutableAttributedString alloc] init]; diff --git a/xplan-ios/Main/Room/View/MessageContainerView/XPRoomMessageContainerView.m b/xplan-ios/Main/Room/View/MessageContainerView/XPRoomMessageContainerView.m index 3c579caa..5642149b 100644 --- a/xplan-ios/Main/Room/View/MessageContainerView/XPRoomMessageContainerView.m +++ b/xplan-ios/Main/Room/View/MessageContainerView/XPRoomMessageContainerView.m @@ -49,6 +49,10 @@ @implementation XPRoomMessageContainerView +- (void)dealloc { + [[NSNotificationCenter defaultCenter] removeObserver:self]; +} + - (instancetype)initWithDelegate:(id)delegate { self = [super init]; if (self) { @@ -68,6 +72,7 @@ #pragma mark - Private Method - (void)initSubViews { + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(addCustomMessage:) name:@"message" object:nil]; [self addSubview:self.messageTableView]; [self addSubview:self.messageTipsBtn]; self.messageTableView.tableHeaderView = self.headerView; @@ -203,9 +208,21 @@ [NSSet setWithObjects: @(Custom_Message_Sub_Collect_Room_Tips), nil], + @(CustomMessageType_RoomPlay_Dating): + [NSSet setWithObjects: + @(Custom_Message_Sub_Room_Play_Dating_Pick_Heart), + @(Custom_Message_Sub_Room_Play_Dating_Result_Mutual), + @(Custom_Message_Sub_Room_Play_Dating_Result_Not_Mutual), + nil], }; } +- (void)addCustomMessage:(NSNotification *)notification { + if (self.hostDelegate.getRoomInfo.isCloseScreen) {return;} + NIMMessage * message = notification.object; + [self addRoomMessage:message]; +} + #pragma mark - RoomGuestDelegate - (void)handleNIMCustomMessage:(NIMMessage *)message { NIMCustomObject *obj = (NIMCustomObject *)message.messageObject; @@ -229,8 +246,9 @@ - (void)handleNIMNotificationMessage:(NIMMessage *)message { NIMNotificationObject *notiMsg = (NIMNotificationObject *)message.messageObject; NIMChatroomNotificationContent *content = (NIMChatroomNotificationContent *)notiMsg.content; + RoomInfoModel * roomInfo = self.hostDelegate.getRoomInfo; if (content.eventType == NIMChatroomEventTypeEnter) { - if (self.hostDelegate.getRoomInfo.isCloseScreen) { + if (roomInfo.isCloseScreen) { AttachmentModel *attachement = [[AttachmentModel alloc]init]; attachement.first = CustomMessageType_Update_RoomInfo; attachement.second = Custom_Message_Sub_Update_RoomInfo_MessageState; @@ -245,18 +263,21 @@ [self addRoomMessage:message]; NIMChatroomNotificationMember *member = content.targets[0]; if (member.userId.integerValue == [AccountInfoStorage instance].getUid.integerValue) { - if (!self.hostDelegate.getRoomInfo.hasAnimationEffect) { + if (!roomInfo.hasAnimationEffect) { [self roomInfoNoGiftAnimationMessage:message]; } } } + } else if(content.eventType == NIMChatroomEventTypeInfoUpdated) { + if (roomInfo.isCloseScreen) {return;} + if (roomInfo.isOpenRoomDating) { + [self addRoomMessage:message]; + } } } - (void)handleNIMTextMessage:(NIMMessage *)message { - if (self.hostDelegate.getRoomInfo.isCloseScreen) { - return; - } + if (self.hostDelegate.getRoomInfo.isCloseScreen) {return;} [self addRoomMessage:message]; } @@ -270,7 +291,6 @@ tempMessage.messageObject = customObject; [self addRoomMessage:tempMessage]; } - #pragma mark - ScrollViewDelegate - (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView { // 手动拖拽开始 diff --git a/xplan-ios/Main/Room/View/XPRoomViewController.m b/xplan-ios/Main/Room/View/XPRoomViewController.m index 34e03b4d..e8f14393 100644 --- a/xplan-ios/Main/Room/View/XPRoomViewController.m +++ b/xplan-ios/Main/Room/View/XPRoomViewController.m @@ -386,9 +386,14 @@ UIKIT_EXTERN NSString * const kRoomMiniNotificationKey; { NSMutableDictionary *lastRoomInfoDic = [NSMutableDictionary dictionaryWithDictionary:[self.roomInfo model2dictionary]]; [lastRoomInfoDic addEntriesFromDictionary: ((NSString *)data[@"roomInfo"]).toJSONObject]; - RoomInfoModel * lastRoomInfo = [RoomInfoModel modelWithJSON:lastRoomInfoDic]; - lastRoomInfo.hasAnimationEffect = self.hasAnimationEffect; - self.roomInfo= lastRoomInfo; + RoomInfoModel *newRoomInfo = [RoomInfoModel modelWithJSON:lastRoomInfoDic]; + newRoomInfo.hasAnimationEffect = self.hasAnimationEffect; + if (newRoomInfo.roomModeType == RoomModeType_Open_Blind && self.roomInfo.roomModeType != RoomModeType_Open_Blind) { + self.roomInfo.isOpenRoomDating = YES; + } else { + self.roomInfo.isOpenRoomDating = YES; + } + self.roomInfo = newRoomInfo; [self changeStageViewOnRoomUpdate]; [self.stageView onRoomUpdate]; [self.menuContainerView onRoomUpdate]; @@ -443,6 +448,8 @@ UIKIT_EXTERN NSString * const kRoomMiniNotificationKey; } } else if(message.messageType == NIMMessageTypeText) { [self.messageContainerView handleNIMTextMessage:message]; + } else if(message.messageType == NIMMessageTypeTip) { + [self.messageContainerView handleNIMTextMessage:message]; } } }