diff --git a/xplan-ios.xcodeproj/project.pbxproj b/xplan-ios.xcodeproj/project.pbxproj index a4203509..03068c2d 100644 --- a/xplan-ios.xcodeproj/project.pbxproj +++ b/xplan-ios.xcodeproj/project.pbxproj @@ -588,6 +588,9 @@ E896EFAC2771AEFE00AD2CC1 /* XPMineFriendTableViewCell.m in Sources */ = {isa = PBXBuildFile; fileRef = E896EFAB2771AEFE00AD2CC1 /* XPMineFriendTableViewCell.m */; }; E896EFAF2771AF0F00AD2CC1 /* XPMineFriendEmptyTableViewCell.m in Sources */ = {isa = PBXBuildFile; fileRef = E896EFAE2771AF0F00AD2CC1 /* XPMineFriendEmptyTableViewCell.m */; }; E896EFB22771C93B00AD2CC1 /* XPMineFriendNumberView.m in Sources */ = {isa = PBXBuildFile; fileRef = E896EFB12771C93B00AD2CC1 /* XPMineFriendNumberView.m */; }; + E8998D7A2859784200C68558 /* XPSVGAPlayer.m in Sources */ = {isa = PBXBuildFile; fileRef = E8998D792859784200C68558 /* XPSVGAPlayer.m */; }; + E8998D8028597B0300C68558 /* XPRoomLuckyBigPrizeView.m in Sources */ = {isa = PBXBuildFile; fileRef = E8998D7F28597B0300C68558 /* XPRoomLuckyBigPrizeView.m */; }; + E8998D82285982EE00C68558 /* lucky_gift_streamer.svga in Resources */ = {isa = PBXBuildFile; fileRef = E8998D81285982EE00C68558 /* lucky_gift_streamer.svga */; }; E899C68927508F4E00E189E5 /* XPUserCardInfoModel.m in Sources */ = {isa = PBXBuildFile; fileRef = E899C68827508F4E00E189E5 /* XPUserCardInfoModel.m */; }; E899C68C275093B800E189E5 /* XPUserCardMicroItemModel.m in Sources */ = {isa = PBXBuildFile; fileRef = E899C68B275093B800E189E5 /* XPUserCardMicroItemModel.m */; }; E89BD7D4277D471100E31B19 /* XPRoomOnlineTableViewCell.m in Sources */ = {isa = PBXBuildFile; fileRef = E89BD7D3277D471100E31B19 /* XPRoomOnlineTableViewCell.m */; }; @@ -2026,6 +2029,11 @@ E896EFAE2771AF0F00AD2CC1 /* XPMineFriendEmptyTableViewCell.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = XPMineFriendEmptyTableViewCell.m; sourceTree = ""; }; E896EFB02771C93B00AD2CC1 /* XPMineFriendNumberView.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = XPMineFriendNumberView.h; sourceTree = ""; }; E896EFB12771C93B00AD2CC1 /* XPMineFriendNumberView.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = XPMineFriendNumberView.m; sourceTree = ""; }; + E8998D782859784200C68558 /* XPSVGAPlayer.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = XPSVGAPlayer.h; sourceTree = ""; }; + E8998D792859784200C68558 /* XPSVGAPlayer.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = XPSVGAPlayer.m; sourceTree = ""; }; + E8998D7E28597B0300C68558 /* XPRoomLuckyBigPrizeView.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = XPRoomLuckyBigPrizeView.h; sourceTree = ""; }; + E8998D7F28597B0300C68558 /* XPRoomLuckyBigPrizeView.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = XPRoomLuckyBigPrizeView.m; sourceTree = ""; }; + E8998D81285982EE00C68558 /* lucky_gift_streamer.svga */ = {isa = PBXFileReference; lastKnownFileType = file; path = lucky_gift_streamer.svga; sourceTree = ""; }; E899C68727508F4E00E189E5 /* XPUserCardInfoModel.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = XPUserCardInfoModel.h; sourceTree = ""; }; E899C68827508F4E00E189E5 /* XPUserCardInfoModel.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = XPUserCardInfoModel.m; sourceTree = ""; }; E899C68A275093B700E189E5 /* XPUserCardMicroItemModel.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = XPUserCardMicroItemModel.h; sourceTree = ""; }; @@ -2904,6 +2912,7 @@ 189DD56C26DF5B5400AB55B1 /* UI */ = { isa = PBXGroup; children = ( + E8998D772859782C00C68558 /* SVGA */, E8659640270160F200846EBD /* VagueImageView */, E8AC720A26F435AF007D6E91 /* UIImageView */, E81366F926F0D27A0076364C /* UIButton */, @@ -4634,6 +4643,8 @@ E86A16CD28574844004228B8 /* XPRoomLicneseHourRankView.m */, 9B86D8782817DD8400494FCD /* XPRoomEnterHideTipView.h */, 9B86D8792817DD8400494FCD /* XPRoomEnterHideTipView.m */, + E8998D7E28597B0300C68558 /* XPRoomLuckyBigPrizeView.h */, + E8998D7F28597B0300C68558 /* XPRoomLuckyBigPrizeView.m */, E838D99E275E1BF60079E0B5 /* XPRoomAnimationView.h */, E838D99F275E1BF60079E0B5 /* XPRoomAnimationView.m */, 9BC9DAED27E33B3F009EE409 /* XPRoomGiftAnimationParser.h */, @@ -5428,6 +5439,15 @@ path = Friend; sourceTree = ""; }; + E8998D772859782C00C68558 /* SVGA */ = { + isa = PBXGroup; + children = ( + E8998D782859784200C68558 /* XPSVGAPlayer.h */, + E8998D792859784200C68558 /* XPSVGAPlayer.m */, + ); + path = SVGA; + sourceTree = ""; + }; E899C68D2750DA3C00E189E5 /* CustomMessage */ = { isa = PBXGroup; children = ( @@ -5546,6 +5566,7 @@ E8A1E45C276220B100B294CA /* Sources */ = { isa = PBXGroup; children = ( + E8998D81285982EE00C68558 /* lucky_gift_streamer.svga */, 9B5F1502280FF02600C3C2B1 /* anchorPk_crossPking.svga */, 9B0AABDD280D4CD20025269D /* anchorPK_vs.svga */, E88863C2278E7BCC004BCFAB /* crossRoomPk_progress.svga */, @@ -6964,6 +6985,7 @@ 9BE29A6B27D1BFF700446AB5 /* anchor_room_speak.svga in Resources */, 9BE29A6D27D210A500446AB5 /* anchor_room_bg.svga in Resources */, E8937AC8276C3EDE00B2C7E1 /* svga_member_in_lv70.svga in Resources */, + E8998D82285982EE00C68558 /* lucky_gift_streamer.svga in Resources */, E8DEC98B27637EA50078CB70 /* candyTree_open.svga in Resources */, E8A1E460276220DA00B294CA /* candyTree_banner.svga in Resources */, E8E859E428264D8800EE4857 /* index.html in Resources */, @@ -7178,6 +7200,7 @@ E8E859C828264C2300EE4857 /* HTTPMessage.m in Sources */, 9B7D80502753AA9D003DAC0C /* UITableView+NIMScrollToBottom.m in Sources */, 9BEE3D0E27853BD000C83219 /* ThemeColor+NobleCenter.m in Sources */, + E8998D7A2859784200C68558 /* XPSVGAPlayer.m in Sources */, 18E7B22626E8CDCF0064BC9B /* XplanFlutterBoostDelegate.m in Sources */, 9BD9A18427A0F128004186FE /* XPMineVisitorItemModel.m in Sources */, E80B0712280D0A6700A79F63 /* FansInfoModel.m in Sources */, @@ -7403,6 +7426,7 @@ E8C1671228067F6C00ECB15C /* XPGuildChooseManagerRoomTableViewCell.m in Sources */, E878893C273A54C300BF1D57 /* Api+Gift.m in Sources */, E81C279026EB314D0031E639 /* LoginForgetEditView.m in Sources */, + E8998D8028597B0300C68558 /* XPRoomLuckyBigPrizeView.m in Sources */, 9BA8A48027C65098000365A3 /* XPSkillCardVoiceView.m in Sources */, E8DEC9A82764A68B0078CB70 /* Api+MoreMenu.m in Sources */, E8A6C28F27CF43D600AC7442 /* XPHomeAttentionTableViewCell.m in Sources */, diff --git a/xplan-ios/Base/UI/SVGA/XPSVGAPlayer.h b/xplan-ios/Base/UI/SVGA/XPSVGAPlayer.h new file mode 100644 index 00000000..b8798acf --- /dev/null +++ b/xplan-ios/Base/UI/SVGA/XPSVGAPlayer.h @@ -0,0 +1,16 @@ +// +// XPSVGAPlayer.h +// xplan-ios +// +// Created by 冯硕 on 2022/6/15. +// + +#import "SVGAImageView.h" + +NS_ASSUME_NONNULL_BEGIN + +@interface XPSVGAPlayer : SVGAImageView + +@end + +NS_ASSUME_NONNULL_END diff --git a/xplan-ios/Base/UI/SVGA/XPSVGAPlayer.m b/xplan-ios/Base/UI/SVGA/XPSVGAPlayer.m new file mode 100644 index 00000000..9c82e83d --- /dev/null +++ b/xplan-ios/Base/UI/SVGA/XPSVGAPlayer.m @@ -0,0 +1,528 @@ +// +// XPSVGAPlayer.m +// xplan-ios +// +// Created by 冯硕 on 2022/6/15. +// + +#import "XPSVGAPlayer.h" +#import "SVGAVideoEntity.h" +#import "SVGAVideoSpriteEntity.h" +#import "SVGAVideoSpriteFrameEntity.h" +#import "SVGAContentLayer.h" +#import "SVGABitmapLayer.h" +#import "SVGAVectorLayer.h" +#import "SVGAAudioLayer.h" +#import "SVGAAudioEntity.h" +#import "YYText.h" + +@interface XPSVGAPlayer () + +@property (nonatomic, strong) CALayer *drawLayer; +@property (nonatomic, strong) NSArray *audioLayers; +@property (nonatomic, strong) CADisplayLink *displayLink; +@property (nonatomic, assign) NSInteger currentFrame; +@property (nonatomic, copy) NSArray *contentLayers; +@property (nonatomic, copy) NSDictionary *dynamicObjects; +@property (nonatomic, copy) NSDictionary *dynamicTexts; +@property (nonatomic, copy) NSDictionary *dynamicDrawings; +@property (nonatomic, copy) NSDictionary *dynamicHiddens; +@property (nonatomic, assign) int loopCount; +@property (nonatomic, assign) NSRange currentRange; +@property (nonatomic, assign) BOOL forwardAnimating; +@property (nonatomic, assign) BOOL reversing; +@property (nonatomic, assign) BOOL audioPlaying; + +@end + + + +@implementation XPSVGAPlayer +@synthesize videoItem = _videoItem; + + +- (instancetype)init { + if (self = [super init]) { + [self initPlayer]; + } + return self; +} + +- (instancetype)initWithFrame:(CGRect)frame { + if (self = [super initWithFrame:frame]) { + [self initPlayer]; + } + return self; +} + +- (instancetype)initWithCoder:(NSCoder *)aDecoder { + if (self = [super initWithCoder:aDecoder]) { + [self initPlayer]; + } + return self; +} + +- (void)initPlayer { + self.contentMode = UIViewContentModeTop; + self.clearsAfterStop = YES; +} + +- (void)willMoveToSuperview:(UIView *)newSuperview { + [super willMoveToSuperview:newSuperview]; + if (newSuperview == nil) { + [self stopAnimation:YES]; + } +} + +- (void)startAnimation { + if (self.videoItem == nil) { + NSLog(@"videoItem could not be nil!"); + return; + } else if (self.drawLayer == nil) { + self.videoItem = _videoItem; + } + [self stopAnimation:NO]; + self.loopCount = 0; + self.displayLink = [CADisplayLink displayLinkWithTarget:self selector:@selector(next)]; + + self.displayLink.frameInterval = 60 / self.videoItem.FPS; + [self.displayLink addToRunLoop:[NSRunLoop mainRunLoop] forMode:NSRunLoopCommonModes]; + self.forwardAnimating = !self.reversing; +} + +- (void)startAnimationWithRange:(NSRange)range reverse:(BOOL)reverse { + self.currentRange = range; + self.reversing = reverse; + if (reverse) { + self.currentFrame = MIN(self.videoItem.frames - 1, range.location + range.length - 1); + } + else { + self.currentFrame = MAX(0, range.location); + } + [self startAnimation]; +} + +- (void)pauseAnimation { + [self stopAnimation:NO]; +} + +- (void)stopAnimation { + [self stopAnimation:self.clearsAfterStop]; +} + +- (void)stopAnimation:(BOOL)clear { + self.forwardAnimating = NO; + if (self.displayLink != nil) { + [self.displayLink invalidate]; + } + if (clear) { + [self clear]; + } + [self clearAudios]; + self.displayLink = nil; +} + +- (void)clear { + self.contentLayers = nil; + [self.drawLayer removeFromSuperlayer]; + self.drawLayer = nil; +} + +- (void)clearAudios { + if (!self.audioPlaying) { + return; + } + for (SVGAAudioLayer *layer in self.audioLayers) { + [layer.audioPlayer stop]; + } + self.audioPlaying = NO; +} + +- (void)stepToFrame:(NSInteger)frame andPlay:(BOOL)andPlay { + if (self.videoItem == nil) { + NSLog(@"videoItem could not be nil!"); + return; + } else if (self.drawLayer == nil) { + self.videoItem = _videoItem; + } + if (frame >= self.videoItem.frames || frame < 0) { + return; + } + [self pauseAnimation]; + self.currentFrame = frame; + [self update]; + if (andPlay) { + self.forwardAnimating = YES; + self.displayLink = [CADisplayLink displayLinkWithTarget:self selector:@selector(next)]; + self.displayLink.frameInterval = 60 / self.videoItem.FPS; + [self.displayLink addToRunLoop:[NSRunLoop mainRunLoop] forMode:NSRunLoopCommonModes]; + } +} + +- (void)stepToPercentage:(CGFloat)percentage andPlay:(BOOL)andPlay { + NSInteger frame = (NSInteger)(self.videoItem.frames * percentage); + if (frame >= self.videoItem.frames && frame > 0) { + frame = self.videoItem.frames - 1; + } + [self stepToFrame:frame andPlay:andPlay]; +} + +- (void)draw { + self.drawLayer = [[CALayer alloc] init]; + self.drawLayer.frame = CGRectMake(0, 0, self.videoItem.videoSize.width, self.videoItem.videoSize.height); + self.drawLayer.masksToBounds = true; + NSMutableDictionary *tempHostLayers = [NSMutableDictionary dictionary]; + NSMutableArray *tempContentLayers = [NSMutableArray array]; + + [self.videoItem.sprites enumerateObjectsUsingBlock:^(SVGAVideoSpriteEntity * _Nonnull sprite, NSUInteger idx, BOOL * _Nonnull stop) { + UIImage *bitmap; + if (sprite.imageKey != nil) { + NSString *bitmapKey = [sprite.imageKey stringByDeletingPathExtension]; + if (self.dynamicObjects[bitmapKey] != nil) { + bitmap = self.dynamicObjects[bitmapKey]; + } + else { + bitmap = self.videoItem.images[bitmapKey]; + } + } + SVGAContentLayer *contentLayer = [sprite requestLayerWithBitmap:bitmap]; + contentLayer.imageKey = sprite.imageKey; + [tempContentLayers addObject:contentLayer]; + if ([sprite.imageKey hasSuffix:@".matte"]) { + CALayer *hostLayer = [[CALayer alloc] init]; + hostLayer.mask = contentLayer; + tempHostLayers[sprite.imageKey] = hostLayer; + } else { + if (sprite.matteKey && sprite.matteKey.length > 0) { + CALayer *hostLayer = tempHostLayers[sprite.matteKey]; + [hostLayer addSublayer:contentLayer]; + if (![sprite.matteKey isEqualToString:self.videoItem.sprites[idx - 1].matteKey]) { + [self.drawLayer addSublayer:hostLayer]; + } + } else { + [self.drawLayer addSublayer:contentLayer]; + } + } + if (sprite.imageKey != nil) { + if (self.dynamicTexts[sprite.imageKey] != nil) { + NSAttributedString *text = self.dynamicTexts[sprite.imageKey]; + CGSize bitmapSize = CGSizeMake(self.videoItem.images[sprite.imageKey].size.width * self.videoItem.images[sprite.imageKey].scale, self.videoItem.images[sprite.imageKey].size.height * self.videoItem.images[sprite.imageKey].scale); + + + CATextLayer *textLayer = [CATextLayer layer]; + textLayer.contentsScale = [[UIScreen mainScreen] scale]; + [textLayer setString:self.dynamicTexts[sprite.imageKey]]; + CGSize size = [text boundingRectWithSize:CGSizeMake(bitmapSize.width, CGFLOAT_MAX) + options:NSStringDrawingUsesLineFragmentOrigin + context:NULL].size; + textLayer.frame = CGRectMake(0, 0, size.width, size.height); + [contentLayer addSublayer:textLayer]; + contentLayer.textLayer = textLayer; + [contentLayer resetTextLayerProperties:text]; + } + if (self.dynamicHiddens[sprite.imageKey] != nil && + [self.dynamicHiddens[sprite.imageKey] boolValue] == YES) { + contentLayer.dynamicHidden = YES; + } + if (self.dynamicDrawings[sprite.imageKey] != nil) { + contentLayer.dynamicDrawingBlock = self.dynamicDrawings[sprite.imageKey]; + } + } + }]; + self.contentLayers = tempContentLayers; + + [self.layer addSublayer:self.drawLayer]; + NSMutableArray *audioLayers = [NSMutableArray array]; + [self.videoItem.audios enumerateObjectsUsingBlock:^(SVGAAudioEntity * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) { + SVGAAudioLayer *audioLayer = [[SVGAAudioLayer alloc] initWithAudioItem:obj videoItem:self.videoItem]; + [audioLayers addObject:audioLayer]; + }]; + self.audioLayers = audioLayers; + [self update]; + [self resize]; +} + +- (void)resize { + if (self.contentMode == UIViewContentModeScaleAspectFit) { + CGFloat videoRatio = self.videoItem.videoSize.width / self.videoItem.videoSize.height; + CGFloat layerRatio = self.bounds.size.width / self.bounds.size.height; + if (videoRatio > layerRatio) { + CGFloat ratio = self.bounds.size.width / self.videoItem.videoSize.width; + CGPoint offset = CGPointMake( + (1.0 - ratio) / 2.0 * self.videoItem.videoSize.width, + (1.0 - ratio) / 2.0 * self.videoItem.videoSize.height + - (self.bounds.size.height - self.videoItem.videoSize.height * ratio) / 2.0 + ); + self.drawLayer.transform = CATransform3DMakeAffineTransform(CGAffineTransformMake(ratio, 0, 0, ratio, -offset.x, -offset.y)); + } + else { + CGFloat ratio = self.bounds.size.height / self.videoItem.videoSize.height; + CGPoint offset = CGPointMake( + (1.0 - ratio) / 2.0 * self.videoItem.videoSize.width - (self.bounds.size.width - self.videoItem.videoSize.width * ratio) / 2.0, + (1.0 - ratio) / 2.0 * self.videoItem.videoSize.height); + self.drawLayer.transform = CATransform3DMakeAffineTransform(CGAffineTransformMake(ratio, 0, 0, ratio, -offset.x, -offset.y)); + } + } + else if (self.contentMode == UIViewContentModeScaleAspectFill) { + CGFloat videoRatio = self.videoItem.videoSize.width / self.videoItem.videoSize.height; + CGFloat layerRatio = self.bounds.size.width / self.bounds.size.height; + if (videoRatio < layerRatio) { + CGFloat ratio = self.bounds.size.width / self.videoItem.videoSize.width; + CGPoint offset = CGPointMake( + (1.0 - ratio) / 2.0 * self.videoItem.videoSize.width, + (1.0 - ratio) / 2.0 * self.videoItem.videoSize.height + - (self.bounds.size.height - self.videoItem.videoSize.height * ratio) / 2.0 + ); + self.drawLayer.transform = CATransform3DMakeAffineTransform(CGAffineTransformMake(ratio, 0, 0, ratio, -offset.x, -offset.y)); + } + else { + CGFloat ratio = self.bounds.size.height / self.videoItem.videoSize.height; + CGPoint offset = CGPointMake( + (1.0 - ratio) / 2.0 * self.videoItem.videoSize.width - (self.bounds.size.width - self.videoItem.videoSize.width * ratio) / 2.0, + (1.0 - ratio) / 2.0 * self.videoItem.videoSize.height); + self.drawLayer.transform = CATransform3DMakeAffineTransform(CGAffineTransformMake(ratio, 0, 0, ratio, -offset.x, -offset.y)); + } + } + else if (self.contentMode == UIViewContentModeTop) { + CGFloat scaleX = self.frame.size.width / self.videoItem.videoSize.width; + CGPoint offset = CGPointMake((1.0 - scaleX) / 2.0 * self.videoItem.videoSize.width, (1 - scaleX) / 2.0 * self.videoItem.videoSize.height); + self.drawLayer.transform = CATransform3DMakeAffineTransform(CGAffineTransformMake(scaleX, 0, 0, scaleX, -offset.x, -offset.y)); + } + else if (self.contentMode == UIViewContentModeBottom) { + CGFloat scaleX = self.frame.size.width / self.videoItem.videoSize.width; + CGPoint offset = CGPointMake( + (1.0 - scaleX) / 2.0 * self.videoItem.videoSize.width, + (1.0 - scaleX) / 2.0 * self.videoItem.videoSize.height); + self.drawLayer.transform = CATransform3DMakeAffineTransform(CGAffineTransformMake(scaleX, 0, 0, scaleX, -offset.x, -offset.y + self.frame.size.height - self.videoItem.videoSize.height * scaleX)); + } + else if (self.contentMode == UIViewContentModeLeft) { + CGFloat scaleY = self.frame.size.height / self.videoItem.videoSize.height; + CGPoint offset = CGPointMake((1.0 - scaleY) / 2.0 * self.videoItem.videoSize.width, (1 - scaleY) / 2.0 * self.videoItem.videoSize.height); + self.drawLayer.transform = CATransform3DMakeAffineTransform(CGAffineTransformMake(scaleY, 0, 0, scaleY, -offset.x, -offset.y)); + } + else if (self.contentMode == UIViewContentModeRight) { + CGFloat scaleY = self.frame.size.height / self.videoItem.videoSize.height; + CGPoint offset = CGPointMake( + (1.0 - scaleY) / 2.0 * self.videoItem.videoSize.width, + (1.0 - scaleY) / 2.0 * self.videoItem.videoSize.height); + self.drawLayer.transform = CATransform3DMakeAffineTransform(CGAffineTransformMake(scaleY, 0, 0, scaleY, -offset.x + self.frame.size.width - self.videoItem.videoSize.width * scaleY, -offset.y)); + } + else { + CGFloat scaleX = self.frame.size.width / self.videoItem.videoSize.width; + CGFloat scaleY = self.frame.size.height / self.videoItem.videoSize.height; + CGPoint offset = CGPointMake((1.0 - scaleX) / 2.0 * self.videoItem.videoSize.width, (1 - scaleY) / 2.0 * self.videoItem.videoSize.height); + self.drawLayer.transform = CATransform3DMakeAffineTransform(CGAffineTransformMake(scaleX, 0, 0, scaleY, -offset.x, -offset.y)); + } +} + +- (void)layoutSubviews { + [super layoutSubviews]; + [self resize]; +} + +- (void)update { + [CATransaction setDisableActions:YES]; + for (SVGAContentLayer *layer in self.contentLayers) { + if ([layer isKindOfClass:[SVGAContentLayer class]]) { + [layer stepToFrame:self.currentFrame]; + } + } + [CATransaction setDisableActions:NO]; + if (self.forwardAnimating && self.audioLayers.count > 0) { + for (SVGAAudioLayer *layer in self.audioLayers) { + if (!self.audioPlaying && layer.audioItem.startFrame >= self.currentFrame) { + [layer.audioPlayer setCurrentTime:(NSTimeInterval)(layer.audioItem.startTime / 1000)]; + [layer.audioPlayer play]; + self.audioPlaying = YES; + } + if (self.audioPlaying && layer.audioItem.endFrame <= self.currentFrame) { + [layer.audioPlayer stop]; + self.audioPlaying = NO; + } + } + } +} + +- (void)next { + if (self.reversing) { + self.currentFrame--; + if (self.currentFrame < (NSInteger)MAX(0, self.currentRange.location)) { + self.currentFrame = MIN(self.videoItem.frames - 1, self.currentRange.location + self.currentRange.length - 1); + self.loopCount++; + } + } + else { + self.currentFrame++; + if (self.currentFrame >= MIN(self.videoItem.frames, self.currentRange.location + self.currentRange.length)) { + self.currentFrame = MAX(0, self.currentRange.location); + [self clearAudios]; + self.loopCount++; + } + } + if (self.loops > 0 && self.loopCount >= self.loops) { + [self stopAnimation]; + if (!self.clearsAfterStop && [self.fillMode isEqualToString:@"Backward"]) { + [self stepToFrame:MAX(0, self.currentRange.location) andPlay:NO]; + } + else if (!self.clearsAfterStop && [self.fillMode isEqualToString:@"Forward"]) { + [self stepToFrame:MIN(self.videoItem.frames - 1, self.currentRange.location + self.currentRange.length - 1) andPlay:NO]; + } + id delegate = self.delegate; + if (delegate != nil && [delegate respondsToSelector:@selector(svgaPlayerDidFinishedAnimation:)]) { + [delegate svgaPlayerDidFinishedAnimation:self]; + } + return; + } + [self update]; + id delegate = self.delegate; + if (delegate != nil && [delegate respondsToSelector:@selector(svgaPlayerDidAnimatedToFrame:)]) { + [delegate svgaPlayerDidAnimatedToFrame:self.currentFrame]; + } + if (delegate != nil && [delegate respondsToSelector:@selector(svgaPlayerDidAnimatedToPercentage:)] && self.videoItem.frames > 0) { + [delegate svgaPlayerDidAnimatedToPercentage:(CGFloat)(self.currentFrame + 1) / (CGFloat)self.videoItem.frames]; + } +} + +- (void)setVideoItem:(SVGAVideoEntity *)videoItem { + _videoItem = videoItem; + _currentRange = NSMakeRange(0, videoItem.frames); + _reversing = NO; + _currentFrame = 0; + _loopCount = 0; + [[NSOperationQueue mainQueue] addOperationWithBlock:^{ + [self clear]; + [self draw]; + }]; +} + +#pragma mark - Dynamic Object + +- (void)setImage:(UIImage *)image forKey:(NSString *)aKey { + if (image == nil) { + return; + } + NSMutableDictionary *mutableDynamicObjects = [self.dynamicObjects mutableCopy]; + [mutableDynamicObjects setObject:image forKey:aKey]; + self.dynamicObjects = mutableDynamicObjects; + if (self.contentLayers.count > 0) { + for (SVGAContentLayer *layer in self.contentLayers) { + if ([layer isKindOfClass:[SVGAContentLayer class]] && [layer.imageKey isEqualToString:aKey]) { + layer.bitmapLayer.contents = (__bridge id _Nullable)([image CGImage]); + } + } + } +} + +- (void)setImageWithURL:(NSURL *)URL forKey:(NSString *)aKey { + [[[NSURLSession sharedSession] dataTaskWithURL:URL completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) { + if (error == nil && data != nil) { + UIImage *image = [UIImage imageWithData:data]; + if (image != nil) { + [[NSOperationQueue mainQueue] addOperationWithBlock:^{ + [self setImage:image forKey:aKey]; + }]; + } + } + }] resume]; +} + +- (void)setImage:(UIImage *)image forKey:(NSString *)aKey referenceLayer:(CALayer *)referenceLayer { + [self setImage:image forKey:aKey]; +} + +- (void)setAttributedText:(NSAttributedString *)attributedText forKey:(NSString *)aKey { + if (attributedText == nil) { + return; + } + NSMutableDictionary *mutableDynamicTexts = [self.dynamicTexts mutableCopy]; + [mutableDynamicTexts setObject:attributedText forKey:aKey]; + self.dynamicTexts = mutableDynamicTexts; + if (self.contentLayers.count > 0) { + CGSize bitmapSize = CGSizeMake(self.videoItem.images[aKey].size.width * self.videoItem.images[aKey].scale, self.videoItem.images[aKey].size.height * self.videoItem.images[aKey].scale); + CGSize size = [attributedText boundingRectWithSize:bitmapSize + options:NSStringDrawingUsesLineFragmentOrigin context:NULL].size; + CATextLayer *textLayer; + for (SVGAContentLayer *layer in self.contentLayers) { + if ([layer isKindOfClass:[SVGAContentLayer class]] && [layer.imageKey isEqualToString:aKey]) { + textLayer = layer.textLayer; + if (textLayer == nil) { + textLayer = [CATextLayer layer]; + [layer addSublayer:textLayer]; + layer.textLayer = textLayer; + [layer resetTextLayerProperties:attributedText]; + } + } + } + if (textLayer != nil) { + textLayer.contentsScale = [[UIScreen mainScreen] scale]; + [textLayer setString:attributedText]; + textLayer.frame = CGRectMake(0, 0, size.width, size.height); + } + } +} + +- (void)setDrawingBlock:(SVGAPlayerDynamicDrawingBlock)drawingBlock forKey:(NSString *)aKey { + NSMutableDictionary *mutableDynamicDrawings = [self.dynamicDrawings mutableCopy]; + [mutableDynamicDrawings setObject:drawingBlock forKey:aKey]; + self.dynamicDrawings = mutableDynamicDrawings; + if (self.contentLayers.count > 0) { + for (SVGAContentLayer *layer in self.contentLayers) { + if ([layer isKindOfClass:[SVGAContentLayer class]] && + [layer.imageKey isEqualToString:aKey]) { + layer.dynamicDrawingBlock = drawingBlock; + } + } + } +} + +- (void)setHidden:(BOOL)hidden forKey:(NSString *)aKey { + NSMutableDictionary *mutableDynamicHiddens = [self.dynamicHiddens mutableCopy]; + [mutableDynamicHiddens setObject:@(hidden) forKey:aKey]; + self.dynamicHiddens = mutableDynamicHiddens; + if (self.contentLayers.count > 0) { + for (SVGAContentLayer *layer in self.contentLayers) { + if ([layer isKindOfClass:[SVGAContentLayer class]] && + [layer.imageKey isEqualToString:aKey]) { + layer.dynamicHidden = hidden; + } + } + } +} + +- (void)clearDynamicObjects { + self.dynamicObjects = nil; + self.dynamicTexts = nil; + self.dynamicHiddens = nil; + self.dynamicDrawings = nil; +} + +- (NSDictionary *)dynamicObjects { + if (_dynamicObjects == nil) { + _dynamicObjects = @{}; + } + return _dynamicObjects; +} + +- (NSDictionary *)dynamicTexts { + if (_dynamicTexts == nil) { + _dynamicTexts = @{}; + } + return _dynamicTexts; +} + +- (NSDictionary *)dynamicHiddens { + if (_dynamicHiddens == nil) { + _dynamicHiddens = @{}; + } + return _dynamicHiddens; +} + +- (NSDictionary *)dynamicDrawings { + if (_dynamicDrawings == nil) { + _dynamicDrawings = @{}; + } + return _dynamicDrawings; +} + +@end + diff --git a/xplan-ios/Main/Room/View/AnimationView/Model/XPGiftBigPrizeModel.h b/xplan-ios/Main/Room/View/AnimationView/Model/XPGiftBigPrizeModel.h index 015c853c..4c304b14 100644 --- a/xplan-ios/Main/Room/View/AnimationView/Model/XPGiftBigPrizeModel.h +++ b/xplan-ios/Main/Room/View/AnimationView/Model/XPGiftBigPrizeModel.h @@ -16,6 +16,16 @@ NS_ASSUME_NONNULL_BEGIN @property(nonatomic, copy)NSString *giftName; ///幸运的礼物 @property (nonatomic,copy) NSString *luckyBagName; +///房间名称 +@property (nonatomic,copy) NSString *roomTitle; +///yoghurtuid +@property (nonatomic,copy) NSString *uid; +///房主的uid +@property (nonatomic,copy) NSString *roomUid; +///礼物的价值 +@property (nonatomic,copy) NSString *goldPrice; +///是否仅自己房间可见 +@property (nonatomic,assign) BOOL isInRoomVisiable; @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 12045ea5..c62cb4a3 100644 --- a/xplan-ios/Main/Room/View/AnimationView/XPRoomAnimationView.m +++ b/xplan-ios/Main/Room/View/AnimationView/XPRoomAnimationView.m @@ -49,8 +49,9 @@ #import "XPRoomAnchorRankBannerView.h" #import "XPRoomEnterHideTipView.h" #import "XPRoomLicneseHourRankView.h" +#import "XPRoomLuckyBigPrizeView.h" -@interface XPRoomAnimationView () +@interface XPRoomAnimationView () ///展示的不同层级 ///最底层的 @property (nonatomic,strong) XPRoomAnimationHitView * lowLevelView; @@ -110,7 +111,8 @@ @property (nonatomic,strong) SVGAImageView *datingEffectView; #pragma mark - 跨房PK @property (nonatomic, strong) NSMutableArray *acrossRoomPKQueue; - +///幸运礼物动画是否在播放 +@property (nonatomic,assign) BOOL isLuckyGiftAnimation; @end @implementation XPRoomAnimationView @@ -971,10 +973,8 @@ - (void)receiveLuckyGiftBigPrize:(AttachmentModel *)attachment { if ([self isInSudGame]) {return;} if (attachment.second == Custom_Message_Sub_Room_Gift_LuckBag || attachment.second == Custom_Message_Sub_Room_Gift_LuckBag_Server) { - XPGiftBigPrizeModel * prizeModel = [[XPGiftBigPrizeModel alloc] init]; - prizeModel.giftName = attachment.data[@"giftName"]; - prizeModel.luckyBagName = attachment.data[@"luckyBagName"]; - prizeModel.nick = attachment.data[@"nick"]; + XPGiftBigPrizeModel * prizeModel = [XPGiftBigPrizeModel modelWithDictionary:attachment.data]; + prizeModel.isInRoomVisiable = attachment.second == Custom_Message_Sub_Room_Gift_LuckBag; [self.bigPrizeGiftQueue addObject:prizeModel]; if (self.luckyprizeTimer == nil) { [self startHandleBigPrizeGiftTimer]; @@ -992,6 +992,9 @@ @kStrongify(self) if (self.bigPrizeGiftQueue.count > 0) { dispatch_sync(dispatch_get_main_queue(), ^{ + if (self.isLuckyGiftAnimation) { + return; + } XPGiftBigPrizeModel * prizeModel = [self.bigPrizeGiftQueue firstObject]; [self createBigPrizeAnimation:prizeModel]; [self.bigPrizeGiftQueue removeObject:prizeModel]; @@ -1006,66 +1009,33 @@ } - (void)createBigPrizeAnimation:(XPGiftBigPrizeModel *)prizeModel { - NSAttributedString *text = [self createBigPrizeAttribute:prizeModel]; - UIImageView *luckyBgView = [[UIImageView alloc] initWithFrame:CGRectMake(KScreenWidth, kNavigationHeight + 15, KScreenWidth, 45)]; - luckyBgView.contentMode = UIViewContentModeScaleAspectFill; - luckyBgView.image= [UIImage imageNamed:@"room_lucky_gift_big_prize_bg"]; - UILabel *contentLabel = [[UILabel alloc] initWithFrame:CGRectMake(90, 0, KScreenWidth - 160, 45)]; - contentLabel.attributedText = text; - contentLabel.textAlignment = NSTextAlignmentCenter; - contentLabel.numberOfLines = 2; - [luckyBgView addSubview:contentLabel]; - [self.lowLevelView addSubview:luckyBgView]; - [UIView animateWithDuration:0.5 animations:^{ - luckyBgView.frame = CGRectMake(0, kNavigationHeight + 15, KScreenWidth, 45); - } completion:^(BOOL finished) { - dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(3.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ - [UIView animateWithDuration:0.5 animations:^{ - luckyBgView.hidden = YES; - } completion:^(BOOL finished) { - [luckyBgView removeFromSuperview]; - }]; - }); + self.isLuckyGiftAnimation = YES; + XPRoomLuckyBigPrizeView * luckyGiftEffectView = [[XPRoomLuckyBigPrizeView alloc] init]; + luckyGiftEffectView.delegate = self; + [self.highLevleView addSubview:luckyGiftEffectView]; + [luckyGiftEffectView mas_makeConstraints:^(MASConstraintMaker *make) { + make.centerX.mas_equalTo(self); + make.top.mas_equalTo(self).offset(kNavigationHeight + 15); + make.size.mas_equalTo(CGSizeMake(375, 60)); }]; + luckyGiftEffectView.giftInfo = prizeModel; + [self performSelector:@selector(LuckyBigPrizeAnimationFinish:) withObject:luckyGiftEffectView afterDelay:6]; } -- (NSAttributedString *)createBigPrizeAttribute:(XPGiftBigPrizeModel *)prizModel { - NSMutableAttributedString *attributedString = [[NSMutableAttributedString alloc] init]; - [attributedString appendAttributedString: - [self createTextAttribute:@"哇偶 ! " - color:[ThemeColor messageViewTipColor] font:12]]; - [attributedString appendAttributedString: - [self createTextAttribute:prizModel.nick - color:[ThemeColor messageNickColor] font:12]]; - - [attributedString appendAttributedString: - [self createTextAttribute:@"通过" - color:[ThemeColor messageViewTipColor] font:12]]; - - [attributedString appendAttributedString: - [self createTextAttribute:prizModel.luckyBagName - color:[ThemeColor messageNickColor] font:12]]; - - [attributedString appendAttributedString: - [self createTextAttribute:@"开出了" - color:[ThemeColor messageNickColor] font:12]]; - - [attributedString appendAttributedString: - [self createTextAttribute:prizModel.giftName color:[ThemeColor messageNickColor] font:12]]; - return attributedString; +- (void)LuckyBigPrizeAnimationFinish:(XPRoomLuckyBigPrizeView *)player { + [player removeFromSuperview]; + player.hidden = YES; + self.isLuckyGiftAnimation = NO; } -/// 生成一个富文本 -/// @param text 富文本的文字 -/// @param color 文字的颜色 -/// @param font 文字的大小 -- (NSMutableAttributedString *)createTextAttribute:(NSString *)text color:(UIColor *)color font:(CGFloat)font { - if (text == nil || text.length <= 0) { - text = @""; +#pragma mark - XPRoomLuckyBigPrizeViewDelegate +- (void)xPRoomLuckyBigPrizeView:(XPRoomLuckyBigPrizeView *)view luckyGiftInfo:(XPGiftBigPrizeModel *)giftInfo { + if (!giftInfo.isInRoomVisiable && giftInfo.roomUid.length > 0 && giftInfo.roomUid.integerValue != self.delegate.getRoomInfo.uid) { + [self.delegate exitRoom]; + dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ + [XPRoomViewController openRoom:giftInfo.roomUid viewController:[XCCurrentVCStackManager shareManager].getCurrentVC]; + }); } - NSDictionary * dic = @{NSFontAttributeName:[UIFont systemFontOfSize:12], NSForegroundColorAttributeName:color}; - NSMutableAttributedString *attribute = [[NSMutableAttributedString alloc] initWithString:text attributes:dic]; - return attribute; } #pragma mark - 普通礼物 diff --git a/xplan-ios/Main/Room/View/AnimationView/XPRoomLuckyBigPrizeView.h b/xplan-ios/Main/Room/View/AnimationView/XPRoomLuckyBigPrizeView.h new file mode 100644 index 00000000..a2c69a26 --- /dev/null +++ b/xplan-ios/Main/Room/View/AnimationView/XPRoomLuckyBigPrizeView.h @@ -0,0 +1,25 @@ +// +// XPRoomLuckyBigPrizeView.h +// xplan-ios +// +// Created by 冯硕 on 2022/6/15. +// + +#import + +NS_ASSUME_NONNULL_BEGIN +@class XPGiftBigPrizeModel, XPRoomLuckyBigPrizeView; +@protocol XPRoomLuckyBigPrizeViewDelegate + +- (void)xPRoomLuckyBigPrizeView:(XPRoomLuckyBigPrizeView *)view luckyGiftInfo:(XPGiftBigPrizeModel *)giftInfo; + +@end + +@interface XPRoomLuckyBigPrizeView : UIView +///礼物信息 +@property (nonatomic,strong) XPGiftBigPrizeModel *giftInfo; +///代理 +@property (nonatomic,weak) id delegate; +@end + +NS_ASSUME_NONNULL_END diff --git a/xplan-ios/Main/Room/View/AnimationView/XPRoomLuckyBigPrizeView.m b/xplan-ios/Main/Room/View/AnimationView/XPRoomLuckyBigPrizeView.m new file mode 100644 index 00000000..a2d20dfe --- /dev/null +++ b/xplan-ios/Main/Room/View/AnimationView/XPRoomLuckyBigPrizeView.m @@ -0,0 +1,125 @@ +// +// XPRoomLuckyBigPrizeView.m +// xplan-ios +// +// Created by 冯硕 on 2022/6/15. +// + +#import "XPRoomLuckyBigPrizeView.h" +///Third +#import +#import "SVGAParser.h" +#import "SVGA.h" +///Tool +#import "ThemeColor.h" +#import "XPMacro.h" +///Model +#import "XPGiftBigPrizeModel.h" +///View +#import "XPSVGAPlayer.h" + + +@interface XPRoomLuckyBigPrizeView () +///动画管理类 +@property (strong, nonatomic) SVGAParser *parser; +@property (nonatomic, strong) XPSVGAPlayer *giftImageView; +@end + +@implementation XPRoomLuckyBigPrizeView + +- (instancetype)initWithFrame:(CGRect)frame { + self = [super initWithFrame:frame]; + if (self) { + [self initSubViews]; + [self initSubViewConstraints]; + } + return self; +} + +#pragma mark - Private Method +- (void)initSubViews { + [self addSubview:self.giftImageView]; + UITapGestureRecognizer * tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(tapRecognizer:)]; + [self addGestureRecognizer:tap]; +} + +- (void)initSubViewConstraints { + [self.giftImageView mas_makeConstraints:^(MASConstraintMaker *make) { + make.edges.mas_equalTo(self); + }]; +} + +#pragma mark - Event Response +- (void)tapRecognizer:(UITapGestureRecognizer *)tap { + if (self.delegate && [self.delegate respondsToSelector:@selector(xPRoomLuckyBigPrizeView:luckyGiftInfo:)]) { + [self.delegate xPRoomLuckyBigPrizeView:self luckyGiftInfo:self.giftInfo]; + } +} + +#pragma mark - Getters And Setters +- (void)setGiftInfo:(XPGiftBigPrizeModel *)giftInfo { + _giftInfo = giftInfo; + if (_giftInfo) { + NSString * nick = _giftInfo.nick; + if (nick.length > 6) { + nick = [nick substringToIndex:6]; + } + CGFloat fontSize = 22; + NSDictionary * dic = @{NSFontAttributeName:[UIFont systemFontOfSize:fontSize], NSForegroundColorAttributeName:[UIColor whiteColor]}; + NSDictionary * mainDic = @{NSFontAttributeName:[UIFont systemFontOfSize:fontSize], NSForegroundColorAttributeName:[ThemeColor appMainColor]}; + NSMutableAttributedString *attributedString = [[NSMutableAttributedString alloc] init]; + [attributedString appendAttributedString:[[NSMutableAttributedString alloc] initWithString:@"恭喜 " attributes:dic]]; + if (nick) { + [attributedString appendAttributedString:[[NSMutableAttributedString alloc] initWithString:nick attributes:mainDic]]; + } + + [attributedString appendAttributedString:[[NSMutableAttributedString alloc] initWithString:[NSString stringWithFormat:@"在%@幸运礼物中欧气爆棚开出了价值",_giftInfo.luckyBagName] attributes:dic]]; + if (giftInfo.goldPrice) { + [attributedString appendAttributedString:[[NSMutableAttributedString alloc] initWithString:giftInfo.goldPrice attributes:mainDic]]; + } + [attributedString appendAttributedString:[[NSMutableAttributedString alloc] initWithString:giftInfo.giftName attributes:mainDic]]; + NSMutableParagraphStyle *paragraphStyle = [NSMutableParagraphStyle new]; + paragraphStyle.lineBreakMode = NSLineBreakByCharWrapping; + paragraphStyle.alignment = NSTextAlignmentLeft; + paragraphStyle.lineSpacing = 4.0f;//行间距 + // 强制排版(从左到右) + paragraphStyle.alignment = NSTextAlignmentLeft; + paragraphStyle.baseWritingDirection = NSWritingDirectionLeftToRight; + [attributedString addAttribute:NSParagraphStyleAttributeName value:paragraphStyle range:NSMakeRange(0, attributedString.length)]; + if (_giftInfo.isInRoomVisiable) { + [self.giftImageView setHidden:YES forKey:@"img_206"]; + } else { + [self.giftImageView setHidden:NO forKey:@"img_206"]; + } + @kWeakify(self); + [self.giftImageView setAttributedText:attributedString forKey:@"fdpp_copywriting"]; + [self.parser parseWithNamed:@"lucky_gift_streamer" inBundle:[NSBundle mainBundle] completionBlock:^(SVGAVideoEntity * _Nonnull videoItem) { + @kStrongify(self); + self.hidden = NO; + self.giftImageView.hidden = NO; + self.giftImageView.videoItem = videoItem; + self.giftImageView.loops = 1; + self.giftImageView.clearsAfterStop = YES; + [self.giftImageView startAnimation]; + } failureBlock:^(NSError * _Nonnull error) { + + }]; + } +} + +- (XPSVGAPlayer *)giftImageView { + if (!_giftImageView) { + _giftImageView = [[XPSVGAPlayer alloc]init]; + _giftImageView.backgroundColor = [UIColor clearColor]; + _giftImageView.userInteractionEnabled = NO; + } + return _giftImageView; +} + +- (SVGAParser *)parser { + if (!_parser) { + _parser = [[SVGAParser alloc]init]; + } + return _parser; +} +@end diff --git a/xplan-ios/Main/Room/View/MessageContainerView/Tool/XPRoomMessageParser.m b/xplan-ios/Main/Room/View/MessageContainerView/Tool/XPRoomMessageParser.m index 47896740..5d983f3b 100644 --- a/xplan-ios/Main/Room/View/MessageContainerView/Tool/XPRoomMessageParser.m +++ b/xplan-ios/Main/Room/View/MessageContainerView/Tool/XPRoomMessageParser.m @@ -33,6 +33,7 @@ #import "RoomPKChooseUserModel.h" #import "RoomPKInfoModel.h" #import "CandyTreeResultModel.h" +#import "XPGiftBigPrizeModel.h" #import "NetImageView.h" @@ -105,6 +106,8 @@ return [self createKickUserAttribute:attachment info:kickModel]; } else if (first == CustomMessageType_Room_PK) {///房内PK return [self createRoomPKAttribute:attachment]; + } else if (first == CustomMessageType_LuckyBag) {///幸运礼物 + return [self createRoomLuckyBigPrizeAttribute:attachment]; } return nil; } @@ -261,6 +264,19 @@ return nil; } +#pragma mark - 房间内幸运礼物 大价值 +- (NSAttributedString *)createRoomLuckyBigPrizeAttribute:(AttachmentModel *)attachment { + XPGiftBigPrizeModel * info= [XPGiftBigPrizeModel modelWithDictionary:attachment.data]; + NSMutableAttributedString * attribute = [[NSMutableAttributedString alloc] init]; + [attribute appendAttributedString:[self createTextAttribute:@"恭喜" color:[ThemeColor messageTextColor] font:kRoomMessageDefalutFont]]; + [attribute appendAttributedString:[self createTextAttribute:info.nick color:[ThemeColor messageNickColor] font:kRoomMessageDefalutFont]]; + [attribute appendAttributedString:[self createTextAttribute:@"在" color:[ThemeColor messageTextColor] font:kRoomMessageDefalutFont]]; + [attribute appendAttributedString:[self createTextAttribute:info.roomTitle color:[ThemeColor messageTextColor] font:kRoomMessageDefalutFont]]; + [attribute appendAttributedString:[self createTextAttribute:[NSString stringWithFormat:@"通过%@", info.luckyBagName] color:[ThemeColor messageTextColor] font:kRoomMessageDefalutFont]]; + [attribute appendAttributedString:[self createTextAttribute:[NSString stringWithFormat:@",开出%@", info.giftName] color:[ThemeColor messageTextColor] font:kRoomMessageDefalutFont]]; + return attribute; +} + #pragma mark - 房间内PK - (NSAttributedString *)createRoomPKAttribute:(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 39b928bf..643ff717 100644 --- a/xplan-ios/Main/Room/View/MessageContainerView/XPRoomMessageContainerView.m +++ b/xplan-ios/Main/Room/View/MessageContainerView/XPRoomMessageContainerView.m @@ -459,6 +459,10 @@ NSString * const kRoomShowTopicKey = @"kRoomShowTopicKey"; @(Custom_Message_Sub_Room_PK_Start), @(Custom_Message_Sub_Room_PK_Re_Start), nil], + @(CustomMessageType_LuckyBag): + [NSSet setWithObjects: + @(Custom_Message_Sub_Room_Gift_LuckBag_Server), + nil] }; } diff --git a/xplan-ios/Main/Room/View/XPMiniRoomView.m b/xplan-ios/Main/Room/View/XPMiniRoomView.m index b74f9908..ae214976 100644 --- a/xplan-ios/Main/Room/View/XPMiniRoomView.m +++ b/xplan-ios/Main/Room/View/XPMiniRoomView.m @@ -310,6 +310,30 @@ UIKIT_EXTERN NSString * kRoomBackMusicPlayMusicOrderKey; [NSSet setWithObjects: @(Custom_Message_Sub_Face_Send), nil], + @(CustomMessageType_Anchor_FansTeam): + [NSSet setWithObjects: + @(Custom_Message_Sub_FansTeam_Open_Success), + @(Custom_Message_Sub_FansTeam_Open_Fail), + @(Custom_Message_Sub_FansTeam_Join_Success), + @(Custom_Message_Sub_FansTeam_Out_Success), + nil], + @(CustomMessageType_Hall_Super_Admin): + [NSSet setWithObjects: + @(Custom_Message_Sub_Hall_Super_Admin_Kick_Manager_Out_Room), + nil], + @(CustomMessageType_Room_PK): + [NSSet setWithObjects: + @(Custom_Message_Sub_Room_PK_Manager_Up_Mic), + @(Custom_Message_Sub_Room_PK_Mode_Close), + @(Custom_Message_Sub_Room_PK_Result), + @(Custom_Message_Sub_Room_PK_Mode_Open), + @(Custom_Message_Sub_Room_PK_Start), + @(Custom_Message_Sub_Room_PK_Re_Start), + nil], + @(CustomMessageType_LuckyBag): + [NSSet setWithObjects: + @(Custom_Message_Sub_Room_Gift_LuckBag_Server), + nil] }; } diff --git a/xplan-ios/Sources/lucky_gift_streamer.svga b/xplan-ios/Sources/lucky_gift_streamer.svga new file mode 100644 index 00000000..2b9d5a57 Binary files /dev/null and b/xplan-ios/Sources/lucky_gift_streamer.svga differ