Files
peko-ios/YuMi/Modules/YMRoom/View/AnimationView/RoomAnimationView.m

3827 lines
150 KiB
Mathematica
Raw Normal View History

2025-01-14 14:29:14 +08:00
//
// RoomAnimationView.m
// YuMi
//
// Created by P on 2025/1/13.
//
//banner
2025-01-14 14:29:14 +08:00
#import "RoomAnimationView.h"
2025-01-15 19:02:58 +08:00
#import <POP.h>
#import <SVGA.h>
#import <libpag/libpag.h>
#import <NIMSDK/NIMSDK.h>
2025-01-16 16:00:12 +08:00
#import <UIImageView+WebCache.h>
2025-01-15 19:02:58 +08:00
#import "UIView+VAP.h"
#import "ClientConfig.h"
#import "XPGiftStorage.h"
#import "UserInfoModel.h"
#import "RoomInfoModel.h"
#import "MicroQueueModel.h"
#import "AttachmentModel.h"
#import "QGVAPConfigModel.h"
#import "ActivityInfoModel.h"
#import "GiftReceiveInfoModel.h"
#import "XPRoomEnterHideTipView.h"
#import "XPMessageRemoteExtModel.h"
#import "PIBaseAnimationViewModel.h"
#import "XPRoomGiftAnimationParser.h"
#import "GiftComboManager.h"
#import "GiftAnimationManager.h"
#import "BannerScheduler.h"
#import "TouchAreaCacheManager.h"
#import "GestureOptimizer.h"
2025-01-15 19:02:58 +08:00
#import "MSRoomGameWebVC.h"
#import "XPRoomViewController.h"
#import "PIUniversalBannerView.h"
#import "PIUniversalBannerModel.h"
#import "CPGiftBanner.h"
#import "CPLevelUpAnimation.h"
#import "CPBindingAnimation.h"
#import "GameUniversalBannerView.h"
#import "LuckyGiftWinningFlagView.h"
#import "LuckyGiftWinningBannerView.h"
#import "RoomHighValueGiftBannerAnimation.h"
2025-02-28 19:04:09 +08:00
#import "LuckyPackageBannerView.h"
2025-04-21 13:52:13 +08:00
#import "BravoGiftBannerView.h"
2025-01-16 16:00:12 +08:00
#import "XCCurrentVCStackManager.h"
2025-04-21 13:52:13 +08:00
#import "BravoGiftWinningFlagView.h"
2025-02-28 19:04:09 +08:00
#import "RoomEnterModel.h"
2025-01-16 16:00:12 +08:00
// Old Methods
#import "DatingInfoModel.h"
#import "XPWebViewController.h"
#import "XPRoomCandyGiftView.h"
#import "XPSailingAnimationView.h"
#import "AcrossRoomPKPrizeModel.h"
#import "XPRoomNobleLevelUpView.h"
2025-01-16 16:00:12 +08:00
#import "XPRoomGiftCompoundView.h"
#import "XPRoomGiftBroadcastView.h"
#import "XPRoomLuckyBigPrizeView.h"
#import "XPTreasureFairyGiftView.h"
#import "XPAcrossRoomPKPrizeView.h"
#import "PIRoomGiftBroadcastWindow.h"
#import "XPRoomDatingAnimationView.h"
#import "XPRoomAnchorRankBannerView.h"
2025-01-16 16:00:12 +08:00
#import "XPRoomGraffitiGiftAnimationView.h"
#import "XPRoomFunctionContainerView.h"
#import "XPRoomRankEntranceView.h"
#import "XPRoomAnchorRankEnterView.h"
#import "MSRoomOnLineView.h"
2025-01-16 16:00:12 +08:00
#import "BannerScheduler.h"
2025-01-15 19:02:58 +08:00
static const CGFloat kTipViewStayDuration = 3.0;
//static const CGFloat kTipViewMoveDuration = 0.5;
2025-01-15 19:02:58 +08:00
@interface RoomAnimationView () <
PAGViewListener,
SVGAPlayerDelegate,
HWDMP4PlayDelegate,
GiftAnimationDelegate,
2025-01-16 16:00:12 +08:00
NIMBroadcastManagerDelegate,
PIUniversalBannerViewDelegate,
XPRoomGiftBroadcastViewDelegate,
XPRoomLuckyBigPrizeViewDelegate,
PIRoomGiftBroadcastWindowDelegate,
XPRoomAnchorRankBannerViewDelegate,
XPRoomGraffitiGiftAnimationViewDelegate,
UIGestureRecognizerDelegate,
BannerSchedulerDelegate
2025-01-15 19:02:58 +08:00
>
@property (nonatomic, weak) id<RoomHostDelegate>hostDelegate;
///
@property (nonatomic, strong) XPRoomAnimationHitView *bottomContainer;
///
@property (nonatomic, strong) XPRoomAnimationHitView *middleContainer;
///
@property (nonatomic, strong) XPRoomAnimationHitView *topContainer;
@property (nonatomic, strong) XPRoomAnimationHitView *bannerContainer;
@property (nonatomic, strong) UIView *bannerSwipeGestureContainer;
@property (nonatomic, strong) UIView *bannerLeftTapGestureContainer;
@property (nonatomic, strong) UIView *bannerRightTapGestureContainer;
2025-01-15 19:02:58 +08:00
/// ---
/// "队列" FIFO
2025-01-15 19:02:58 +08:00
@property (nonatomic, strong) NSMutableArray<NSDictionary *> *enterRoomAnimationQueue;
///
@property (nonatomic, assign) BOOL isEnterRoomAnimating;
@property (nonatomic, strong) SVGAImageView *enterEffectView;
/// ---
@property(nonatomic, strong) PAGView *pagGiftEffectView;
@property(nonatomic, strong) SVGAParser *vggParser;
@property(nonatomic, assign) BOOL isPlayingGiftEffect;
@property(nonatomic, strong) NSMutableArray *svgaQueue;
@property(nonatomic, strong) VAPView *vapGiftEffectView;
2025-01-16 16:00:12 +08:00
@property(nonatomic, strong) SVGAImageView *vggGiftEffectView;
2025-01-15 19:02:58 +08:00
@property(nonatomic, strong) NSMutableArray *mp4AvatarLoaders;
@property(nonatomic, copy) NSString *GiftDynamicEffectListPath;
@property(nonatomic, strong) dispatch_source_t giftEffectTimer;
@property(nonatomic, strong) dispatch_queue_t giftEffectsQueue;
@property(nonatomic, strong) XPRoomGiftAnimationParser *vapParser;
@property(nonatomic, strong) GiftAnimationManager *giftAnimationManager;
@property(nonatomic, strong) GiftReceiveInfoModel *mp4TempReceiveInfoModel;
/// ---
@property (nonatomic, strong) NSMutableArray *roomBannertModelsQueueV2; // banner CP banner CP
@property (nonatomic, assign) BOOL isRoomBannerV2Displaying;
@property (nonatomic, strong) BannerScheduler *bannerScheduler; // Banner
2025-01-15 19:02:58 +08:00
2025-04-02 11:04:07 +08:00
// --- Brove
@property (nonatomic, strong) SVGAVideoEntity *broveSVGAEntity_lv_1;
@property (nonatomic, strong) SVGAVideoEntity *broveSVGAEntity_lv_2;
@property (nonatomic, strong) SVGAVideoEntity *broveSVGAEntity_lv_3;
@property (nonatomic, strong) NSMutableArray *broveSVGAQueue;
@property (nonatomic, assign) BOOL isBroveSVGAPlaying;
@property (nonatomic, assign) NSInteger viewIndex;
2025-01-15 19:02:58 +08:00
/// ---
///pag
@property(nonatomic, strong) PAGView *carPagEffectView;
///VAP
@property(nonatomic, strong) VAPView *carVapEffectView;
@property(nonatomic, strong) SVGAImageView *carSVGAEffectView;
@property(nonatomic, strong) NSMutableArray<NSDictionary *> *carEffectQueue;
2025-01-16 16:00:12 +08:00
/// ---
@property(nonatomic, assign) BOOL isPlayOfB;
@property(nonatomic, strong) NSMutableArray<PIBaseAnimationViewModel *> *animationListB; //
@property(nonatomic, assign) CGFloat broadCastHieght;
@property (nonatomic, strong) NetImageView *imageLoader;
@property (nonatomic, strong) SVGAImageView *datingEffectView;
@property (nonatomic, strong) NSMutableArray<AttachmentModel *> *sailingQueue;
@property (nonatomic, strong) NSMutableArray<DatingInfoModel *> *datingEffectQueue;
@property (nonatomic, strong) NSMutableArray<AttachmentModel *> *graffitiGiftQueue;
@property (nonatomic, strong) NSMutableArray<AcrossRoomPKPrizeModel *> *acrossRoomPKQueue;
@property (nonatomic,strong) SVGAImageView *luckyGiftEffectView; ///
@property (nonatomic, strong) VAPView *luckyVapGiftEffectView; ///VAP
2025-03-24 16:09:48 +08:00
@property(nonatomic, strong) NSMutableArray <PIUniversalBannerView *>* universalBannerViewCaches;
// Banner
@property(nonatomic, assign) CGPoint savedTapPoint;
@property(nonatomic, assign) BOOL hasSavedTapPoint;
2025-01-15 19:02:58 +08:00
@end
2025-01-14 14:29:14 +08:00
@implementation RoomAnimationView
2025-02-28 19:04:09 +08:00
- (void)setIsPlayOfB:(BOOL)isPlayOfB {
_isPlayOfB = isPlayOfB;
}
2025-01-15 19:02:58 +08:00
- (void)dealloc
{
NSLog(@" RoomAnimationView: dealloc 开始");
[self removeItSelf];
NSLog(@" RoomAnimationView: dealloc 完成");
}
- (void)removeItSelf {
NSLog(@"<22><> RoomAnimationView: 开始销毁");
// 🔧
[self cancelAllAnimations];
// 广
2025-01-22 21:22:58 +08:00
[[NIMSDK sharedSDK].broadcastManager removeDelegate:self];
//
[NSObject cancelPreviousPerformRequestsWithTarget:self];
// POP
[self pop_removeAllAnimations];
//
if (_giftEffectTimer && !dispatch_source_testcancel(_giftEffectTimer)) {
dispatch_source_cancel(_giftEffectTimer);
_giftEffectTimer = nil;
}
//
if (_giftEffectsQueue) {
self.giftEffectsQueue = NULL;
}
// <EFBFBD><EFBFBD> banner block
[self cleanupAllSubviews];
// 🔧 BannerScheduler
if (self.bannerScheduler) {
NSLog(@"<22><> 清理 BannerScheduler");
[self.bannerScheduler clearQueue];
[self.bannerScheduler pause];
self.bannerScheduler = nil;
}
//
[self cleanupGestureRecognizers];
//
[self cleanupCacheManagers];
//
[self removeNotificationObservers];
NSLog(@"<22><> RoomAnimationView: 销毁完成");
}
- (void)cancelAllAnimations {
NSLog(@" 取消所有动画");
2025-01-22 21:22:58 +08:00
// POP
2025-01-22 21:22:58 +08:00
[self pop_removeAllAnimations];
// POP
NSArray *containers = @[self.bannerContainer, self.topContainer, self.middleContainer, self.bottomContainer];
for (UIView *container in containers) {
if (!container) continue;
for (UIView *subview in container.subviews) {
[subview pop_removeAllAnimations];
}
2025-01-15 19:02:58 +08:00
}
2025-03-24 16:09:48 +08:00
// UIView
[UIView setAnimationsEnabled:NO];
NSLog(@"🔄 所有动画取消完成");
}
- (void)cleanupAllSubviews {
NSLog(@" 清理所有子视图");
//
NSArray *containers = @[self.bannerContainer, self.topContainer, self.middleContainer, self.bottomContainer];
for (UIView *container in containers) {
if (!container) continue;
NSMutableArray *viewsToRemove = [NSMutableArray array];
for (UIView *subview in container.subviews) {
[viewsToRemove addObject:subview];
NSLog(@" 标记移除视图: %@ (从容器: %@)", NSStringFromClass([subview class]), NSStringFromClass([container class]));
}
for (UIView *view in viewsToRemove) {
//
[view pop_removeAllAnimations];
//
if (view.gestureRecognizers.count > 0) {
NSLog(@" 清理视图 %@ 上的 %lu 个手势识别器", NSStringFromClass([view class]), (unsigned long)view.gestureRecognizers.count);
for (UIGestureRecognizer *gesture in view.gestureRecognizers.copy) {
[view removeGestureRecognizer:gesture];
}
}
//
[view removeFromSuperview];
}
2025-01-15 19:02:58 +08:00
}
NSLog(@"🔄 所有子视图清理完成");
}
- (void)__cleanupAllBannerViews {
NSLog(@"<22><> 清理所有 Banner 视图");
// bannerContainer
NSMutableArray *viewsToRemove = [NSMutableArray array];
for (UIView *subview in self.bannerContainer.subviews) {
[viewsToRemove addObject:subview];
NSLog(@"🔄 标记移除 banner: %@", NSStringFromClass([subview class]));
}
for (UIView *view in viewsToRemove) {
[view removeFromSuperview];
}
// topContainer CP banner
viewsToRemove = [NSMutableArray array];
for (UIView *subview in self.topContainer.subviews) {
if ([subview isKindOfClass:[CPBindingAnimation class]] ||
[subview isKindOfClass:[CPLevelUpAnimation class]]) {
[viewsToRemove addObject:subview];
NSLog(@"<22><> 标记移除 CP banner: %@", NSStringFromClass([subview class]));
}
}
for (UIView *view in viewsToRemove) {
[view removeFromSuperview];
}
NSLog(@"🔄 Banner 视图清理完成");
2025-01-15 19:02:58 +08:00
}
-(void)resumeTimer{
if(self.giftEffectTimer != nil){
dispatch_source_cancel(self.giftEffectTimer);
self.giftEffectTimer = nil;
}
[self.pagGiftEffectView removeListener:self];
self.hostDelegate = nil;
[[GiftComboManager sharedManager] removeComboFlag];
}
- (instancetype)initWithHostDelegate:(id<RoomHostDelegate>)hDelegate {
if (self = [super init]) {
self.hostDelegate = hDelegate;
[[NIMSDK sharedSDK].broadcastManager addDelegate:self];
// RoomAnimationView
self.userInteractionEnabled = YES;
2025-01-15 19:02:58 +08:00
[self setup];
}
return self;
}
#pragma mark - SETUP
- (void)setup {
[self setupUI];
[self setupEnterRoom];
[self setupGiftEffects];
[self setupBanner];
[self setupCar];
2025-01-16 16:00:12 +08:00
[self setupOldMethods];
[self addBnnerContainGesture];
2025-01-15 19:02:58 +08:00
}
- (void)setupUI {
[self addSubview:self.bottomContainer];
[self insertSubview:self.middleContainer aboveSubview:self.bottomContainer];
[self insertSubview:self.topContainer aboveSubview:self.middleContainer];
[self insertSubview:self.bannerContainer aboveSubview:self.topContainer];
[self.bottomContainer mas_makeConstraints:^(MASConstraintMaker *make) {
make.edges.mas_equalTo(self);
}];
[self.middleContainer mas_makeConstraints:^(MASConstraintMaker *make) {
make.edges.mas_equalTo(self);
}];
[self.topContainer mas_makeConstraints:^(MASConstraintMaker *make) {
make.edges.mas_equalTo(self);
}];
[self.bannerContainer mas_makeConstraints:^(MASConstraintMaker *make) {
make.top.mas_equalTo(self).offset(kNavigationHeight);
make.leading.trailing.mas_equalTo(self);
make.height.mas_equalTo(80);
2025-01-15 19:02:58 +08:00
}];
}
- (void)setupEnterRoom {
self.enterRoomAnimationQueue = [NSMutableArray array];
}
- (void)setupGiftEffects {
self.GiftDynamicEffectListPath = [[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) xpSafeObjectAtIndex:0] stringByAppendingPathComponent:@"GiftDynamicEffectList"];
self.giftAnimationManager = [[GiftAnimationManager alloc] initWithContainerView:self.bottomContainer];
self.giftAnimationManager.delegate = self;
_giftEffectsQueue = dispatch_queue_create("com.RoomGiftEffects.queue", DISPATCH_QUEUE_SERIAL);
}
- (void)setupBanner {
_roomBannertModelsQueueV2 = [NSMutableArray array];
// Banner
self.bannerScheduler = [[BannerScheduler alloc] initWithDelegate:self];
}
#pragma mark - Legacy Support
2025-01-15 19:02:58 +08:00
- (void)setupCar {
_carEffectQueue = [NSMutableArray array];
}
2025-01-16 16:00:12 +08:00
- (void)setupOldMethods {
_broadCastHieght = 190 - 150 + kGetScaleWidth(69);
_sailingQueue = @[].mutableCopy;
_datingEffectQueue = @[].mutableCopy;
_graffitiGiftQueue = @[].mutableCopy;
_acrossRoomPKQueue = @[].mutableCopy;
_animationListB = @[].mutableCopy;
}
2025-01-15 19:02:58 +08:00
#pragma mark - Method: Enter Roooooom
- (void)enterRoom:(NIMMessage *)message content:(NIMChatroomNotificationContent *)content {
NIMMessageChatroomExtension *messageExt = (NIMMessageChatroomExtension *)message.messageExt;
NSDictionary * dic = [(NSDictionary *)messageExt.roomExt.toJSONObject objectForKey:message.from];
XPMessageRemoteExtModel *extModel = [XPMessageRemoteExtModel modelWithJSON:dic];
2025-01-22 21:22:58 +08:00
if (extModel.platformRole == 1) {
return;
}
2025-01-15 19:02:58 +08:00
if (extModel.enterHide) {
//
if ([message.from isEqualToString:[AccountInfoStorage instance].getUid]) {
[self createEnterHideAnimation];
}
} else {
[self userEnterRoom:content ext:extModel];
}
}
///
- (void)createEnterHideAnimation {
NSDictionary * dic= @{@"title":@"隐身进房",
@"isMe":@"",
2025-01-15 19:02:58 +08:00
@"experLevelSeq":@"",
@"effectPath" : @""};
[self.enterRoomAnimationQueue addObject:dic];
[self tryDequeueAnimation];
}
- (void)userEnterRoom:(NIMChatroomNotificationContent *)content ext:(XPMessageRemoteExtModel *)extModel {
NSString *userName = [self _resolveUserNameFromContent:content extModel:extModel];
NSString *title = [NSString stringWithFormat:YMLocalizedString(@"XPRoomAnimationView0"), userName];
NSDictionary * dic= @{@"title":title,
@"experLevelSeq":[NSString stringWithFormat:@"%ld", extModel.experLevelSeq],
@"effectPath" : extModel.enterRoomEffects.length ? extModel.enterRoomEffects : @""};
[self.enterRoomAnimationQueue addObject:dic];
[self tryDequeueAnimation];
}
- (void)tryDequeueAnimation {
// return
if (self.isEnterRoomAnimating || self.enterRoomAnimationQueue.count == 0) {
return;
}
self.isEnterRoomAnimating = YES;
//
NSDictionary *dic = [self.enterRoomAnimationQueue firstObject];
if (self.enterRoomAnimationQueue.count > 0) {
[self.enterRoomAnimationQueue xpSafeRemoveObjectAtIndex:0];
}
2025-01-15 19:02:58 +08:00
NSString *title = [dic objectForKey:@"title"];
if ([title isEqualToString:@"隐身进房"]) {
[self playHideEnterRoomAnimation];
} else {
//
[self playUserEnterRoomAnimation:[dic objectForKey:@"title"]
experLevelSeq:[dic objectForKey:@"experLevelSeq"]
2025-02-28 19:04:09 +08:00
effectPath:[dic objectForKey:@"effectPath"]
isCPEnter:[[dic objectForKey:@"isCP"] boolValue]];
2025-01-15 19:02:58 +08:00
}
}
- (void)playHideEnterRoomAnimation {
XPRoomEnterHideTipView *enterHideTipView = [[XPRoomEnterHideTipView alloc] initWithFrame:CGRectMake(KScreenWidth,
(KScreenHeight - 48) * 0.5,
KScreenWidth,
48)];
[self.bottomContainer addSubview:enterHideTipView];
@kWeakify(self);
[self enterRoomAnimationFor:enterHideTipView
startFrom:enterHideTipView.center
startTo:CGPointMake(enterHideTipView.frame.size.width / 2, enterHideTipView.center.y)
endFrom:CGPointMake(0, enterHideTipView.center.y)
endTo:CGPointMake(-KScreenWidth / 2, enterHideTipView.center.y)
duration:CACurrentMediaTime() + kTipViewStayDuration
completion:^(BOOL finished) {
@kStrongify(self);
[self endAnimationEnterEffect];
}];
}
- (void)playUserEnterRoomAnimation:(NSString *)title
experLevelSeq:(NSString *)experLevelSeq
2025-02-28 19:04:09 +08:00
effectPath:(NSString *)effectPath
isCPEnter:(BOOL)isCP {
2025-01-15 19:02:58 +08:00
NSDictionary *attributes = @{
NSFontAttributeName:kFontRegular(26),
NSForegroundColorAttributeName:[UIColor whiteColor]
};
NSMutableAttributedString *attributeString = [[NSMutableAttributedString alloc] initWithString:title
attributes:attributes];
[attributeString setYy_alignment:NSTextAlignmentLeft];
BOOL hasEffectPath = ![NSString isEmpty:effectPath];
[self addEnterEffectView: hasEffectPath];
2025-02-28 19:04:09 +08:00
if (isCP) {
[self playCPPPPEnterRoomSvgaWith:attributeString];
} else if (hasEffectPath) {
2025-01-15 19:02:58 +08:00
[self playEnterRoomSvga:effectPath
content:attributeString
needMoveAnimation:YES];
} else {
[self playEnterRoomSvgaWith:experLevelSeq
content:attributeString];
}
}
- (void)addEnterEffectView:(BOOL)hasEffectPath {
if (self.enterEffectView.superview == nil) {
[self.bottomContainer addSubview:self.enterEffectView];
}
self.enterEffectView.loops = hasEffectPath ? 0 : 1;
self.enterEffectView.frame = CGRectMake(hasEffectPath ? KScreenWidth : 0,
340 + kSafeAreaTopHeight,
KScreenWidth,
hasEffectPath ? 75 : 50);
}
- (void)playEnterRoomSvga:(NSString *)path
content:(NSAttributedString *)content
needMoveAnimation:(BOOL)isNeed {
@kWeakify(self);
SVGAParser *parser = [[SVGAParser alloc] init];
[parser parseWithURL:[NSURL URLWithString:path]
completionBlock:^(SVGAVideoEntity * _Nullable videoItem) {
@kStrongify(self);
self.enterEffectView.alpha = 1;
2025-02-28 19:04:09 +08:00
self.enterEffectView.hidden = NO;
2025-01-15 19:02:58 +08:00
self.enterEffectView.videoItem = videoItem;
[self.enterEffectView setAttributedText:content forKey:@"room_text"];
[self.enterEffectView startAnimation];
if (isNeed) {
[self popAnimationEnterEffect];
}
} failureBlock:^(NSError * _Nullable error) {
@kStrongify(self);
[self endAnimationEnterEffect];
}];
}
- (void)playEnterRoomSvgaWith:(NSString *)seq
content:(NSAttributedString *)content {
NSInteger seqNum = [NSString isEmpty:seq] ? 0 : [seq integerValue];
NSString *path = [self _mapExperLevelSeqToLocalKey:seqNum];
if ([NSString isEmpty:path]) {
[self endAnimationEnterEffect];
return;
}
NSString *targetPath = [NSString stringWithFormat:@"%@/%@.svga", @"https://image.molistar.xyz", path];
[self playEnterRoomSvga:targetPath content:content needMoveAnimation:NO];
}
2025-02-28 19:04:09 +08:00
- (void)playCPPPPEnterRoomSvgaWith:(NSAttributedString *)content {
if ([NSString isEmpty:content.string]) {
[self endAnimationEnterEffect];
return;
}
NSString *path = @"CP进场";
@kWeakify(self);
SVGAParser *parser = [[SVGAParser alloc] init];
[parser parseWithNamed:path inBundle:[NSBundle mainBundle] completionBlock:^(SVGAVideoEntity * _Nonnull videoItem) {
@kStrongify(self);
self.enterEffectView.loops = 0;
self.enterEffectView.alpha = 1;
self.enterEffectView.hidden = NO;
self.enterEffectView.videoItem = videoItem;
[self.enterEffectView setAttributedText:content forKey:@"room_text"];
[self.enterEffectView startAnimation];
[self popAnimationEnterEffect];
} failureBlock:^(NSError * _Nonnull error) {
@kStrongify(self);
[self endAnimationEnterEffect];
}];
}
2025-01-15 19:02:58 +08:00
- (void)popAnimationEnterEffect {
@kWeakify(self);
[self enterRoomAnimationFor:self.enterEffectView
startFrom:self.enterEffectView.center
startTo:CGPointMake(self.enterEffectView.frame.size.width / 2, self.enterEffectView.center.y)
endFrom:CGPointMake(0, self.enterEffectView.center.y)
endTo:CGPointMake(-KScreenWidth / 2, self.enterEffectView.center.y)
duration:CACurrentMediaTime() + kTipViewStayDuration
completion:^(BOOL finished) {
@kStrongify(self);
[self endAnimationEnterEffect];
}];
}
- (void)endAnimationEnterEffect {
self.isEnterRoomAnimating = NO;
2025-01-22 21:22:58 +08:00
[self.enterEffectView stopAnimation];
self.enterEffectView.hidden = YES;
[self.enterEffectView removeFromSuperview];
2025-01-15 19:02:58 +08:00
[self tryDequeueAnimation];
}
#pragma mark - Method: Banner
- (void)inserBannerModelToQueue:(AttachmentModel *)obj {
//
if (!obj || ![obj isKindOfClass:[AttachmentModel class]]) {
NSLog(@"⚠️ 警告: inserBannerModelToQueue 接收到无效参数: %@", obj);
return;
}
#if 0
// DEBUGbanner
BOOL enableBannerCopy = obj.second == Custom_Message_Sub_Super_Gift_Banner;// YES; // NO
NSInteger copyCount = 10; //
if (enableBannerCopy) {
NSLog(@"🧪 DEBUG环境收到banner数据复制%ld份用于测试", (long)copyCount);
NSLog(@"🧪 原始banner类型: %@", NSStringFromClass([obj class]));
//
[self.bannerScheduler enqueueBanner:obj];
//
for (int i = 1; i < copyCount; i++) {
AttachmentModel *copiedObj = [[AttachmentModel alloc] init];
// data
if ([obj.data respondsToSelector:@selector(mutableCopy)]) {
copiedObj.data = [obj.data mutableCopy];
} else if ([obj.data respondsToSelector:@selector(copy)]) {
copiedObj.data = [obj.data copy];
} else {
copiedObj.data = obj.data; //
}
copiedObj.first = obj.first;
copiedObj.second = obj.second;
copiedObj.isBroadcast = obj.isBroadcast;
copiedObj.seq = obj.seq;
NSLog(@"🧪 复制第%d份banner数据", i + 1);
[self.bannerScheduler enqueueBanner:copiedObj];
}
NSLog(@"🧪 队列中banner总数: %ld", (long)self.bannerScheduler.queueCount);
// banner
NSLog(@"🧪 队列状态: %@", [self.bannerScheduler queueStatusDescription]);
} else {
//
NSLog(@"🧪 DEBUG环境复制功能已禁用正常添加banner");
[self.bannerScheduler enqueueBanner:obj];
}
#else
//
[self.bannerScheduler enqueueBanner:obj];
#endif
2025-03-24 16:09:48 +08:00
}
- (void)sortBannerQueue {
// FIFO
//
NSLog(@"🔄 RoomAnimationView: 使用先进先出策略,保持队列原有顺序");
2025-03-24 16:09:48 +08:00
}
2025-01-15 19:02:58 +08:00
- (void)processNextRoomEffectAttachment {
NSLog(@"🔄 processNextRoomEffectAttachment 被调用 - 当前状态: isRoomBannerV2Displaying=%@, 队列数量: %ld",
self.isRoomBannerV2Displaying ? @"YES" : @"NO", (long)self.roomBannertModelsQueueV2.count);
2025-01-15 19:02:58 +08:00
//
if (self.roomBannertModelsQueueV2.count == 0) {
//
self.isRoomBannerV2Displaying = NO;
NSLog(@"🔄 队列为空,停止处理");
2025-01-15 19:02:58 +08:00
return;
}
2025-02-28 19:04:09 +08:00
if (self.isRoomBannerV2Displaying) {
NSLog(@"🔄 已有banner正在显示跳过处理");
2025-02-28 19:04:09 +08:00
return;
}
2025-03-24 16:09:48 +08:00
[self sortBannerQueue];
2025-01-15 19:02:58 +08:00
//
AttachmentModel *nextAttachment = [self.roomBannertModelsQueueV2 firstObject];
if (self.roomBannertModelsQueueV2.count > 0) {
[self.roomBannertModelsQueueV2 xpSafeRemoveObjectAtIndex:0];
}
2025-01-15 19:02:58 +08:00
//
self.isRoomBannerV2Displaying = YES;
NSLog(@"🔄 设置状态为正在显示: %@", NSStringFromClass([nextAttachment class]));
// bannerbannerdebug
NSMutableArray *viewsToRemove = [NSMutableArray array];
for (UIView *subview in self.bannerContainer.subviews) {
[viewsToRemove addObject:subview];
NSLog(@"🔄 标记移除banner: %@", NSStringFromClass([subview class]));
}
for (UIView *view in viewsToRemove) {
[view removeFromSuperview];
}
2025-01-15 19:02:58 +08:00
switch (nextAttachment.second) {
case Custom_Message_Sub_General_Floating_Screen_One_Room:
case Custom_Message_Sub_General_Floating_Screen_All_Room:
//
[self playGameBanner:nextAttachment];
break;
case Custom_Message_Sub_Super_Gift_Winning_Coins_ALL_Room:
[self playLuckyWinningBanner:nextAttachment];
break;
case Custom_Message_Sub_CP_Gift:
[self playCPGiftBanner:nextAttachment];
break;
case Custom_Message_Sub_CP_Upgrade:
[self playCPLevelUp:nextAttachment];
break;
case Custom_Message_Sub_CP_Binding:
[self playCPBinding:nextAttachment];
break;
case Custom_Message_Sub_Gift_ChannelNotify:
[self playRoomGiftBanner:nextAttachment];
break;
2025-02-28 19:04:09 +08:00
case Custom_Message_Sub_LuckyPackage:
[self playLuckyPackageBanner:nextAttachment];
break;
2025-04-02 11:04:07 +08:00
case Custom_Message_Sub_Super_Gift_Banner:
[self playBroveBanner:nextAttachment];
break;
2025-01-15 19:02:58 +08:00
default:
break;
}
}
2025-04-02 11:04:07 +08:00
- (void)playBroveBanner:(AttachmentModel *)obj {
if (!obj.data) {
self.isRoomBannerV2Displaying = NO;
[self.bannerScheduler markBannerFinished];
return;
}
self.isRoomBannerV2Displaying = YES;
@kWeakify(self);
RoomInfoModel *roomInfo = self.hostDelegate.getRoomInfo;
// <EFBFBD><EFBFBD>
if (!self || !self.superview) {
NSLog(@"⚠️ RoomAnimationView 正在销毁,跳过 banner 播放");
return;
}
[BravoGiftBannerView display:self.bannerContainer
inRoomUid:roomInfo.uid
with:obj
complete:^{
@kStrongify(self);
if (!self || !self.superview) {
NSLog(@"⚠️ RoomAnimationView 已被释放,跳过 complete 回调");
return;
}
NSLog(@"🔄 BravoGiftBannerView complete 回调被调用");
self.isRoomBannerV2Displaying = NO;
[self.bannerScheduler markBannerFinished];
} exitCurrentRoom:^{
@kStrongify(self);
if (!self || !self.superview) {
NSLog(@"⚠️ RoomAnimationView 已被释放,跳过 exitCurrentRoom 回调");
return;
}
[self.hostDelegate exitRoom];
}];
2025-04-02 11:04:07 +08:00
}
2025-02-28 19:04:09 +08:00
- (void)playLuckyPackageBanner:(AttachmentModel *)obj {
if (!obj.data) {
self.isRoomBannerV2Displaying = NO;
[self.bannerScheduler markBannerFinished];
2025-02-28 19:04:09 +08:00
return;
}
2025-04-02 11:04:07 +08:00
self.isRoomBannerV2Displaying = YES;
2025-02-28 19:04:09 +08:00
@kWeakify(self);
RoomInfoModel *roomInfo = self.hostDelegate.getRoomInfo;
[LuckyPackageBannerView display:self.bannerContainer
inRoomUid:roomInfo.uid
with:obj
complete:^{
@kStrongify(self);
NSLog(@"🔄 LuckyPackageBannerView complete 回调被调用");
2025-02-28 19:04:09 +08:00
self.isRoomBannerV2Displaying = NO;
[self.bannerScheduler markBannerFinished];
2025-02-28 19:04:09 +08:00
} exitCurrentRoom:^{
@kStrongify(self);
[self.hostDelegate exitRoom];
}];
}
2025-01-15 19:02:58 +08:00
- (void)receiveRoomGiftBanner:(AttachmentModel *)obj {
2025-03-24 16:09:48 +08:00
[self inserBannerModelToQueue:obj];
2025-01-15 19:02:58 +08:00
}
- (void)playRoomGiftBanner:(AttachmentModel *)obj {
2025-01-22 21:22:58 +08:00
if (!obj.data) {
2025-02-28 19:04:09 +08:00
self.isRoomBannerV2Displaying = NO;
[self.bannerScheduler markBannerFinished];
2025-01-22 21:22:58 +08:00
return;
}
2025-04-02 11:04:07 +08:00
self.isRoomBannerV2Displaying = YES;
2025-01-15 19:02:58 +08:00
@kWeakify(self);
[RoomHighValueGiftBannerAnimation display:self.bannerContainer
with:obj
complete:^{
@kStrongify(self);
NSLog(@"🔄 RoomHighValueGiftBannerAnimation complete 回调被调用");
2025-02-28 19:04:09 +08:00
self.isRoomBannerV2Displaying = NO;
[self.bannerScheduler markBannerFinished];
2025-01-15 19:02:58 +08:00
}];
}
- (void)receiveCPEvent:(AttachmentModel *)attachment {
2025-03-24 16:09:48 +08:00
[self inserBannerModelToQueue:attachment];
2025-01-15 19:02:58 +08:00
}
- (void)playCPBinding:(AttachmentModel *)attachment {
@kWeakify(self);
[CPBindingAnimation display:self.topContainer
with:attachment
complete:^{
@kStrongify(self);
2025-02-28 19:04:09 +08:00
self.isRoomBannerV2Displaying = NO;
[self.bannerScheduler markBannerFinished];
2025-01-15 19:02:58 +08:00
}];
}
- (void)playCPGiftBanner:(AttachmentModel *)attachMent {
@kWeakify(self);
[CPGiftBanner display:self.bannerContainer
with:attachMent
complete:^{
@kStrongify(self);
NSLog(@"🔄 CPGiftBanner complete 回调被调用");
2025-02-28 19:04:09 +08:00
self.isRoomBannerV2Displaying = NO;
[self.bannerScheduler markBannerFinished];
2025-01-15 19:02:58 +08:00
}];
}
- (void)playCPLevelUp:(AttachmentModel *)attachMent {
@kWeakify(self);
[CPLevelUpAnimation display:self.topContainer
with:attachMent
complete:^{
@kStrongify(self);
2025-02-28 19:04:09 +08:00
self.isRoomBannerV2Displaying = NO;
[self.bannerScheduler markBannerFinished];
2025-01-15 19:02:58 +08:00
}];
}
- (void)receiveLuckGiftWinning:(AttachmentModel *)attachment {
RoomInfoModel *roomInfo = self.hostDelegate.getRoomInfo;
[LuckyGiftWinningFlagView display:self.topContainer
with:attachment
roomID:roomInfo.roomId
uID:[AccountInfoStorage instance].getUid];
}
2025-04-21 13:52:13 +08:00
- (void)receiveBravoGiftWinning:(AttachmentModel *)attachment {
2025-04-02 11:04:07 +08:00
RoomInfoModel *roomInfo = self.hostDelegate.getRoomInfo;
2025-04-21 13:52:13 +08:00
BravoGiftWinningFlagViewModel *flagModel = [BravoGiftWinningFlagView display:self.topContainer
with:attachment
roomID:roomInfo.roomId
uID:[AccountInfoStorage instance].getUid];
2025-04-02 11:04:07 +08:00
if (flagModel.roomId != roomInfo.roomId || flagModel.uid != [AccountInfoStorage instance].getUid.integerValue) {
return;
}
if ([flagModel.receiverUidList containsObject:@([AccountInfoStorage instance].getUid.integerValue)]) {
// combo
[[NSNotificationCenter defaultCenter] postNotificationName:@"receiveLuckGiftWinning" object:[NSString stringByRemovingRedundantZeros:@(flagModel.receiverProfit).stringValue]];
}
2025-04-21 13:52:13 +08:00
2025-04-02 11:04:07 +08:00
if (!self.hostDelegate.getRoomInfo.hasAnimationEffect) {
return;
}
NSDictionary *tip = [attachment.data objectForKey:@"tip"];
if (tip) {
NSNumber *level = [tip objectForKey:@"level"];
NSNumber *coins = [tip objectForKey:@"coins"];
if (level) {
[self loadBroveSVGAVideoItem:level.integerValue];
}
if (coins) {
[[NSNotificationCenter defaultCenter] postNotificationName:@"receiveLuckGiftWinning" object:[NSString stringByRemovingRedundantZeros:coins.stringValue]];
2025-04-02 11:04:07 +08:00
}
}
}
- (void)loadBroveSVGAVideoItem:(NSInteger)level {
2025-04-10 18:01:01 +08:00
if (level < 3) {
return;
}
2025-04-02 11:04:07 +08:00
NSString *svgaItemName = @"";
SVGAVideoEntity *entity;
svgaItemName = @"大";
entity = self.broveSVGAEntity_lv_3;
/*
2025-04-02 11:04:07 +08:00
switch (level) {
case 1:
svgaItemName = @"小";
entity = self.broveSVGAEntity_lv_1;
break;
case 2:
svgaItemName = @"中";
entity = self.broveSVGAEntity_lv_2;
break;
2025-04-02 11:04:07 +08:00
case 3:
svgaItemName = @"大";
entity = self.broveSVGAEntity_lv_3;
break;
default:
break;
}
*/
2025-04-02 11:04:07 +08:00
if ([NSString isEmpty:svgaItemName]) {
return;
}
if (self.broveSVGAQueue.count >=3) {
return;
}
SVGAImageView *svgaView = [[SVGAImageView alloc] initWithFrame:CGRectMake(0, 0, KScreenWidth, KScreenHeight)];
svgaView.backgroundColor = [UIColor clearColor];
svgaView.contentMode = UIViewContentModeScaleAspectFill;
svgaView.userInteractionEnabled = NO;
if (!entity) {
@kWeakify(self);
SVGAParser *parser = [[SVGAParser alloc] init];
[parser parseWithNamed:svgaItemName
inBundle:[NSBundle mainBundle]
completionBlock:^(SVGAVideoEntity * _Nonnull videoItem) {
@kStrongify(self);
self.broveSVGAEntity_lv_3 = videoItem;
/*
2025-04-02 11:04:07 +08:00
switch (level) {
case 1:
self.broveSVGAEntity_lv_1 = videoItem;
break;
case 2:
self.broveSVGAEntity_lv_2 = videoItem;
break;
2025-04-02 11:04:07 +08:00
case 3:
self.broveSVGAEntity_lv_3 = videoItem;
break;
default:
break;
}
*/
2025-04-02 11:04:07 +08:00
[self startPlayBroveSVGA:svgaView level:level];
} failureBlock:^(NSError * _Nonnull error) {
}];
} else {
[self startPlayBroveSVGA:svgaView level:level];
}
}
- (void)startPlayBroveSVGA:(SVGAImageView *)svgaView level:(NSInteger)level {
if (!_broveSVGAQueue) {
_broveSVGAQueue = [[NSMutableArray alloc] init];
self.viewIndex = 0;
}
if (![self.broveSVGAQueue containsObject:svgaView]) {
[self.broveSVGAQueue addObject:svgaView];
}
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)((0.3 + (self.viewIndex * 0.1)) * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
SVGAVideoEntity *entity;
switch (level) {
case 1:
entity = self.broveSVGAEntity_lv_1;
break;
case 2:
entity = self.broveSVGAEntity_lv_2;
break;
case 3:
entity = self.broveSVGAEntity_lv_3;
break;
default:
break;
}
// [self insertSubview:svgaView atIndex:self.viewIndex];
[self _addSubviewToMiddleContainer:svgaView];
svgaView.tag = 913;
svgaView.delegate = self;
svgaView.videoItem = entity;
svgaView.loops = 1;
[svgaView startAnimation];
self.viewIndex += 1;
});
}
2025-01-15 19:02:58 +08:00
- (void)receiveLuckGiftBanner:(AttachmentModel *)attachment {
2025-03-24 16:09:48 +08:00
[self inserBannerModelToQueue:attachment];
2025-01-15 19:02:58 +08:00
}
- (void)playLuckyWinningBanner:(AttachmentModel *)nextAttachment {
RoomInfoModel *roomInfo = self.hostDelegate.getRoomInfo;
@kWeakify(self);
[LuckyGiftWinningBannerView display:self.bannerContainer
inRoomUid:roomInfo.uid
with:nextAttachment
complete:^{
@kStrongify(self);
NSLog(@"🔄 LuckyGiftWinningBannerView complete 回调被调用");
2025-02-28 19:04:09 +08:00
self.isRoomBannerV2Displaying = NO;
[self.bannerScheduler markBannerFinished];
2025-01-15 19:02:58 +08:00
} exitCurrentRoom:^{
@kStrongify(self);
[self.hostDelegate exitRoom];
}];
}
-(void)receiveRoomGeneralFloatingScreen:(AttachmentModel *)attachment{
PIBaseAnimationViewModel *roomGraffiti = [PIBaseAnimationViewModel new];
roomGraffiti.data = attachment.data;
roomGraffiti.type = GiftBannerType_General_Floating_Screen;
roomGraffiti.first = attachment.first;
roomGraffiti.second = attachment.second;
PIUniversalBannerModel *model = [PIUniversalBannerModel modelWithDictionary:attachment.data];
if (model.skipType == 7 &&
(attachment.second == Custom_Message_Sub_General_Floating_Screen_One_Room ||
attachment.second == Custom_Message_Sub_General_Floating_Screen_All_Room)) {
[self receiveGameBanner:attachment];
} else {
2025-01-16 16:00:12 +08:00
if(self.animationListB.count == 0 && self.isPlayOfB == NO){
[self createGeneralFloatingScreenAnimation:roomGraffiti bannerModel:model];
}
[self.animationListB addObject:roomGraffiti];
2025-01-15 19:02:58 +08:00
}
}
- (void)receiveGameBanner:(AttachmentModel *)attachment {
2025-03-24 16:09:48 +08:00
[self inserBannerModelToQueue:attachment];
2025-01-15 19:02:58 +08:00
}
- (void)playGameBanner:(AttachmentModel *)attachment {
@kWeakify(self);
[GameUniversalBannerView display:self.bannerContainer
with:attachment
complete:^{
@kStrongify(self);
NSLog(@"🔄 GameUniversalBannerView complete 回调被调用");
2025-02-28 19:04:09 +08:00
self.isRoomBannerV2Displaying = NO;
[self.bannerScheduler markBannerFinished];
2025-01-15 19:02:58 +08:00
} goToGame:^(NSInteger gameID) {
@kStrongify(self);
NSArray *baishunList = [self.hostDelegate getPlayList];
for (ActivityInfoModel *model in baishunList) {
if (model.id == gameID) {
MSRoomGameWebVC *vc = [[MSRoomGameWebVC alloc]initWithDelegate:self.hostDelegate
gameModel:model];
vc.view.frame = CGRectMake(0, 0, KScreenWidth, KScreenHeight);
XPRoomViewController *roomVC = (XPRoomViewController *)self.hostDelegate;
[roomVC addChildViewController:vc];
2025-01-22 21:22:58 +08:00
RoomAnimationView *animationView;
2025-01-15 19:02:58 +08:00
for (id obj in self.hostDelegate.getSuperView.subviews) {
2025-01-22 21:22:58 +08:00
if ([obj isKindOfClass:[RoomAnimationView class]]){
2025-01-15 19:02:58 +08:00
animationView = obj;
break;
}
}
[self.hostDelegate.getSuperView addSubview:vc.view];
vc.view.tag = 913;
2025-02-28 19:04:09 +08:00
break;
2025-01-15 19:02:58 +08:00
}
}
}];
}
#pragma mark - Method: Car
- (void)handleCarEnter:(AttachmentModel *)attachment {
if (attachment.second == Custom_Message_Sub_Car_EnterRoom) {
if (self.isPlayingGiftEffect) {
return;
}
if ([self _isInSudGame]) {
return;
}
if (!self.hostDelegate.getRoomInfo.hasAnimationEffect) {
return;
}
2025-01-22 21:22:58 +08:00
if (self.hostDelegate.getUserInfo.platformRole == 1) {
return;
}
2025-01-15 19:02:58 +08:00
NSInteger otherViewType = [attachment.data[@"otherViewType"] integerValue];
NSString *viewUrl = attachment.data[@"viewUrl"];
NSString *effect = attachment.data[@"effect"];
NSDictionary *dic = nil;
if (![NSString isEmpty:viewUrl]) {
dic = @{@"otherViewType":@(otherViewType), @"viewUrl":viewUrl};
} else if(![NSString isEmpty:effect]) {
dic = @{@"effect":effect};
}
[self starHandleCarEffect:dic];
}
}
- (void)starHandleCarEffect:(NSDictionary *)dic {
if (!dic) {
return;
}
[self.carEffectQueue addObject:dic];
[self playCarEffect:dic];
}
- (void)nextCarEffect {
if (self.carEffectQueue.count > 0) {
if (self.carEffectQueue.count > 0) {
[self.carEffectQueue xpSafeRemoveObjectAtIndex:0];
}
2025-01-15 19:02:58 +08:00
}
if (self.carEffectQueue.count > 0) {
[self playCarEffect:self.carEffectQueue.firstObject];
}
}
- (void)playCarEffect:(NSDictionary *)effectDict {
NSString *viewUrl = [effectDict objectForKey:@"viewUrl"];
NSString *carEffect = [effectDict objectForKey:@"effect"];
@kWeakify(self);
if (![NSString isEmpty:viewUrl]) {
[self.vapParser parseWithURL:viewUrl completionBlock:^(NSString * _Nullable videoUrl) {
@kStrongify(self);
if (![NSString isEmpty:videoUrl]) {
if([videoUrl.lowercaseString containsString:@".pag"]){
self.carPagEffectView.hidden = NO;
[self _addSubviewToMiddleContainer:self.carPagEffectView];
[self.carPagEffectView setPath:videoUrl];
[self.carPagEffectView play];
} else {
self.carVapEffectView.hidden = NO;
[self _addSubviewToMiddleContainer:self.carVapEffectView];
[self.carVapEffectView setMute:NO];
[self.carVapEffectView playHWDMP4:videoUrl repeatCount:1 delegate:self];
}
}
} failureBlock:^(NSError * _Nullable error) {
@kStrongify(self);
[self nextCarEffect];
}];
} else if (![NSString isEmpty:carEffect]) {
[self.vggParser parseWithURL:[NSURL URLWithString:carEffect]
completionBlock:^(SVGAVideoEntity * _Nullable videoItem) {
@kStrongify(self);
if (videoItem) {
[self _addSubviewToMiddleContainer:self.carSVGAEffectView];
[self _updateGiftEffectContentMode:self.carSVGAEffectView
size:videoItem.videoSize];
self.carSVGAEffectView.videoItem = videoItem;
[self.carSVGAEffectView startAnimation];
}
} failureBlock:^(NSError * _Nullable error) {
@kStrongify(self);
[self nextCarEffect];
}];
}
}
#pragma mark - Method: Send Gifts
- (void)receiveGiftHandleSendGiftAnimationWith:(GiftReceiveInfoModel *)receiveInfo attachment:(AttachmentModel *)attachment {
if (!self.hostDelegate.getRoomInfo.hasAnimationEffect) {
return;
}
GiftInfoModel *giftInfo = receiveInfo.gift;
if (attachment.second == Custom_Message_Sub_AllMicroLuckySend ||
attachment.second == Custom_Message_Sub_AllBatchMicroLuckySend ||
attachment.second == Custom_Message_Sub_Gift_LuckySend) {
NSString * giftId = [NSString stringWithFormat:@"%ld", receiveInfo.luckyGiftList.giftList.firstObject.giftId];
2025-04-21 13:52:13 +08:00
NSString *roomUid = receiveInfo.roomUid == 0 ? receiveInfo.uid : @(receiveInfo.roomUid).stringValue;
giftInfo = [[XPGiftStorage shareStorage] findGiftInfo:giftId inRoom:roomUid];
2025-01-15 19:02:58 +08:00
}
if (giftInfo == nil) {
2025-03-06 15:26:44 +08:00
giftInfo = [[XPGiftStorage shareStorage] findGiftInfo:receiveInfo.giftId inRoom:@(receiveInfo.roomUid).stringValue];
2025-01-15 19:02:58 +08:00
}
2025-02-28 19:04:09 +08:00
if (giftInfo == nil) {
giftInfo = [receiveInfo.displayGift xpSafeObjectAtIndex:0];
}
2025-01-15 19:02:58 +08:00
receiveInfo.gift = giftInfo;
RoomInfoModel * roomInfo = [self.hostDelegate getRoomInfo];
if ((giftInfo.otherViewType == GiftOtherViewTypeMp4 ||
giftInfo.otherViewType == GiftOtherViewTypePag) &&
giftInfo.viewUrl.length > 0 && roomInfo.hasAnimationEffect) {
receiveInfo.mp4Url = giftInfo.viewUrl;
} else if (giftInfo.hasVggPic &&
giftInfo.vggUrl.length > 0
&& roomInfo.hasAnimationEffect) {///SVGA
receiveInfo.vggUrl = giftInfo.vggUrl;
}
2025-01-16 16:00:12 +08:00
if (attachment.second != Custom_Message_Sub_Gift_EmbeddedStyle) {
// Custom_Message_Sub_Gift_EmbeddedStyle
[self.giftAnimationManager enqueueGift:receiveInfo];
}
2025-01-15 19:02:58 +08:00
}
- (void)receiveGift:(GiftReceiveInfoModel *)receiveInfo {
if (receiveInfo.isHomeShow) {
return;
}
2025-01-16 16:00:12 +08:00
// combo
2025-01-15 19:02:58 +08:00
[[GiftComboManager sharedManager] receiveGiftInfoForDisplayComboFlags:receiveInfo
container:self];
if (receiveInfo.isLuckyBagGift) {
2025-01-16 16:00:12 +08:00
if (receiveInfo.isShowAnimation) {
[self handleLuckyBagGifts:receiveInfo];
}
2025-01-15 19:02:58 +08:00
} else {
if (![NSString isEmpty:receiveInfo.mp4Url] || ![NSString isEmpty:receiveInfo.vggUrl]) {
2025-03-24 16:09:48 +08:00
[self addToSvgaQueue:receiveInfo];
2025-01-15 19:02:58 +08:00
}
}
dispatch_async(self.giftEffectsQueue, ^{
if (self.giftEffectTimer == nil &&
self.svgaQueue.count > 0) {
[self startHandleGiftEffectTimer];
}
});
2025-01-15 19:02:58 +08:00
}
2025-01-16 16:00:12 +08:00
- (void)handleLuckyBagGifts:(GiftReceiveInfoModel *)receiveInfo {
// SVGA
// MARK: XPRoomAnimationView copy
RoomInfoModel * roomInfo = [self.hostDelegate getRoomInfo];
if (receiveInfo.displayGift.count > 0) {
[receiveInfo.displayGift enumerateObjectsUsingBlock:^(GiftInfoModel * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
if ((obj.otherViewType == GiftOtherViewTypeMp4 || obj.otherViewType == GiftOtherViewTypePag) && obj.viewUrl && obj.viewUrl.length > 0 && roomInfo.hasAnimationEffect) {
GiftReceiveInfoModel * model = [[GiftReceiveInfoModel alloc] init];
model.mp4Url = obj.viewUrl;
model.avatar = receiveInfo.sendUserAvatar;
model.gift = obj;
model.giftNum = [obj.giftNum integerValue];;
model.nick = receiveInfo.nick;
model.targetUids = receiveInfo.targetUids;
model.isBatch = receiveInfo.isBatch;
model.targetAvatar = receiveInfo.targetAvatar;
model.targetNick = receiveInfo.targetNick;
2025-03-24 16:09:48 +08:00
[self addToSvgaQueue:model];
2025-01-16 16:00:12 +08:00
} else if (obj.hasVggPic && roomInfo.hasAnimationEffect) {
GiftReceiveInfoModel * model = [[GiftReceiveInfoModel alloc] init];
model.mp4Url = obj.viewUrl;
model.avatar = receiveInfo.sendUserAvatar;
model.gift = obj;
model.giftNum = [obj.giftNum integerValue];;
model.nick = receiveInfo.nick;
model.targetUids = receiveInfo.targetUids;
model.isBatch = receiveInfo.isBatch;
model.targetAvatar = receiveInfo.targetAvatar;
model.targetNick = receiveInfo.targetNick;
2025-03-24 16:09:48 +08:00
[self addToSvgaQueue:model];
2025-01-16 16:00:12 +08:00
}
}];
}
}
2025-01-15 19:02:58 +08:00
- (void)startHandleGiftEffectTimer {
NSTimeInterval period = 2.0;
dispatch_queue_t queue = dispatch_get_global_queue(0, 0);
dispatch_source_t timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, queue);
dispatch_source_set_timer(timer, dispatch_walltime(NULL, 0), period * NSEC_PER_SEC, 0); //
@kWeakify(self);
dispatch_source_set_event_handler(timer, ^{
@kStrongify(self)
if (!self) {
return;
}
dispatch_async(self.giftEffectsQueue, ^{
NSLog(@"******************* 当前队列个数: %@image loader 个数: %@", @(self.svgaQueue.count), @(self.mp4AvatarLoaders.count));
2025-01-15 19:02:58 +08:00
if (self.svgaQueue.count == 0) {
dispatch_source_cancel(timer);
dispatch_async(dispatch_get_main_queue(), ^{
self.giftEffectTimer = nil;
});
} else {
if (self.isPlayingGiftEffect == NO) {
self.isPlayingGiftEffect = YES;
GiftReceiveInfoModel *receiveModel = [self.svgaQueue xpSafeObjectAtIndex:0];
if ([receiveModel isKindOfClass:[GiftReceiveInfoModel class]]) {
dispatch_async(dispatch_get_main_queue(), ^{
[self createGiftSvgaAnimation:receiveModel];
});
}else {
2025-03-24 16:09:48 +08:00
[self removeFromSvgaQueueAtIndex:0];
2025-01-15 19:02:58 +08:00
self.isPlayingGiftEffect = NO;
}
}
}
});
});
self.giftEffectTimer = timer;
dispatch_resume(timer);
}
-(void)createGiftSvgaAnimation:(GiftReceiveInfoModel *)receiveInfo {
GiftInfoModel *giftInfo = receiveInfo.gift;
NSString *targetURL = @"";
if (receiveInfo.isLuckyBagGift) {
//
if (![NSString isEmpty:receiveInfo.mp4Url]) {
[self stopCarEffect:giftInfo.goldPrice];
targetURL = receiveInfo.mp4Url;
2025-01-16 16:00:12 +08:00
[self playLuckyGiftEffectWithVapUrl:receiveInfo.mp4Url];
2025-01-15 19:02:58 +08:00
} else if (![NSString isEmpty:receiveInfo.luckyGiftSvgaUrl]) {
[self stopCarEffect:giftInfo.goldPrice];
targetURL = receiveInfo.luckyGiftSvgaUrl;
[self playGiftEffectWithVapUrl:receiveInfo.luckyGiftSvgaUrl];
} else if (![NSString isEmpty:giftInfo.luckyGiftSvgaUrl]) {
[self stopCarEffect:giftInfo.goldPrice];
targetURL = giftInfo.luckyGiftSvgaUrl;
[self playGiftEffectWithVapUrl:giftInfo.luckyGiftSvgaUrl];
}
} else {
2025-02-28 19:04:09 +08:00
[self stopCarEffect:giftInfo.goldPrice];
2025-01-15 19:02:58 +08:00
if (giftInfo.otherViewType == GiftOtherViewTypePag ||
giftInfo.otherViewType == GiftOtherViewTypeMp4) {
2025-02-28 19:04:09 +08:00
if (giftInfo.otherViewType == GiftOtherViewTypePag) {
2025-01-15 19:02:58 +08:00
[self playGiftEffectWithPagUrl:giftInfo.viewUrl];
targetURL = giftInfo.viewUrl;
2025-02-28 19:04:09 +08:00
} else {
2025-01-15 19:02:58 +08:00
self.mp4TempReceiveInfoModel = receiveInfo;
[self playGiftEffectWithVapUrl:giftInfo.viewUrl];
targetURL = giftInfo.viewUrl;
2025-02-28 19:04:09 +08:00
}
}
// svga
if ([NSString isEmpty:targetURL] && giftInfo.hasVggPic && giftInfo.vggUrl.length > 0) {
[self playGiftEffectWithVggUrl:giftInfo.vggUrl];
targetURL = giftInfo.vggUrl;
}
2025-01-15 19:02:58 +08:00
}
2025-04-02 11:04:07 +08:00
// NSLog(@"******************* 执行播放, 是否MP4:%@URL: %@, self.svgaQueue num: %@", @(giftInfo.otherViewType), targetURL, @(self.svgaQueue.count));
2025-01-15 19:02:58 +08:00
[[NSNotificationCenter defaultCenter] postNotificationName:@"kExchangeRoomAnimationViewAndGameViewIndex"
object:nil];
@kWeakify(self);
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.25 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
@kStrongify(self);
2025-03-24 16:09:48 +08:00
[self removeFromSvgaQueueAtIndex:0];
2025-01-15 19:02:58 +08:00
});
}
- (void)stopCarEffect:(double)goldPrice {
if ([ClientConfig shareConfig].configInfo.hideCarEffectGiftPrice <= goldPrice) {
[self.carEffectQueue removeAllObjects];
[self.carSVGAEffectView stopAnimation];
[self.carVapEffectView stopHWDMP4];
[self.carPagEffectView stop];
}
}
- (void)playGiftEffectWithPagUrl:(NSString *)pagUrl {
@kWeakify(self);
[self.vapParser parseWithURL:pagUrl
completionBlock:^(NSString * _Nullable videoUrl) {
@kStrongify(self);
if ([NSString isEmpty:videoUrl]) {
[self playPAGFailure];
} else {
[self _addSubviewToMiddleContainer:self.pagGiftEffectView];
[self.pagGiftEffectView setPath:videoUrl];
[self.pagGiftEffectView play];
}
} failureBlock:^(NSError * _Nullable error) {
@kStrongify(self);
[self playPAGFailure];
}];
}
- (void)playGiftEffectWithVapUrl:(NSString *)vapUrl {
NSString *encodingUrl = [vapUrl pureURLString];
NSString *fullPath = [self _findFullPath:vapUrl];
self.mp4AvatarLoaders = @[].mutableCopy;
if ([[NSFileManager defaultManager] fileExistsAtPath:fullPath]){
[self playVAG:fullPath];
}else {
@kWeakify(self);
[self.vapParser parseWithURL:encodingUrl
completionBlock:^(NSString * _Nullable videoUrl) {
@kStrongify(self);
if ([NSString isEmpty:videoUrl]) {
[self playVAGFailure];
} else {
[self playVAG:videoUrl];
}
} failureBlock:^(NSError * _Nullable error) {
@kStrongify(self);
[self playVAGFailure];
}];
}
}
- (void)playGiftEffectWithVggUrl:(NSString *)vggUrl {
NSString *encodingUrl = [vggUrl pureURLString];
NSString *fullPath = [self _findFullPath:vggUrl];
2025-04-02 11:04:07 +08:00
// NSLog(@"******************* 解释 SVGA : %@ | %@", encodingUrl, fullPath);
2025-01-15 19:02:58 +08:00
if (![NSString isEmpty:fullPath] && [[NSFileManager defaultManager] fileExistsAtPath:fullPath]) {
NSData *data = [NSData dataWithContentsOfFile:fullPath options:0 error:NULL];
NSString *fileName = [[encodingUrl componentsSeparatedByString:@"/"] lastObject];
@kWeakify(self);
[self.vggParser parseWithData:data
cacheKey:fileName
completionBlock:^(SVGAVideoEntity * _Nonnull videoItem) {
@kStrongify(self);
if (videoItem) {
[self playVGG:videoItem];
} else {
[self playVGGFailure];
}
} failureBlock:^(NSError * _Nonnull error) {
@kStrongify(self);
[self playVGGFailure];
}];
} else {
@kWeakify(self);
[self.vggParser parseWithURL:[NSURL URLWithString:encodingUrl]
completionBlock:^(SVGAVideoEntity * _Nullable videoItem) {
@kStrongify(self);
2025-04-02 11:04:07 +08:00
// NSLog(@"******************* 解释 SVGA 成功");
2025-01-15 19:02:58 +08:00
if (videoItem) {
[self playVGG:videoItem];
} else {
[self playVGGFailure];
}
} failureBlock:^(NSError * _Nullable error) {
@kStrongify(self);
2025-04-02 11:04:07 +08:00
// NSLog(@"******************* 解释 SVGA 失败:%@", error);
2025-01-15 19:02:58 +08:00
[self playVGGFailure];
}];
}
}
- (void)playVGG:(SVGAVideoEntity *)videoItem {
2025-02-28 19:04:09 +08:00
[self.vggGiftEffectView stopAnimation];
2025-01-15 19:02:58 +08:00
[self _addSubviewToMiddleContainer:self.vggGiftEffectView];
[self _updateGiftEffectContentMode:self.vggGiftEffectView
size:videoItem.videoSize];
self.vggGiftEffectView.videoItem = videoItem;
[self.vggGiftEffectView startAnimation];
}
- (void)playVGGFailure {
[self playVGGEnd];
}
- (void)playVGGEnd {
self.isPlayingGiftEffect = NO;
self.vggGiftEffectView.hidden = YES;
}
- (void)playVAG:(NSString *)url {
@kWeakify(self);
dispatch_async(dispatch_get_main_queue(), ^{
@kStrongify(self);
[self _addSubviewToMiddleContainer:self.vapGiftEffectView];
[self.vapGiftEffectView setMute:NO];
[self.vapGiftEffectView playHWDMP4:url
repeatCount:1
delegate:self];
});
}
- (void)playVAGFailure {
[self playVAGEnd];
}
- (void)playVAGEnd {
self.isPlayingGiftEffect = NO;
self.vapGiftEffectView.hidden = YES;
[self.vapGiftEffectView setMute:YES];
[self.vapGiftEffectView stopHWDMP4];
2025-03-24 16:09:48 +08:00
[self.vapGiftEffectView removeFromSuperview];
self.vapGiftEffectView = nil;
2025-01-15 19:02:58 +08:00
}
- (void)playPAGFailure {
self.isPlayingGiftEffect = NO;
self.pagGiftEffectView.hidden = YES;
}
#pragma mark - Delegates
#pragma mark - SVGA delegate
- (void)svgaPlayerDidFinishedAnimation:(SVGAPlayer *)player {
2025-04-02 11:04:07 +08:00
if (player.tag == 913) {
[player clear];
player.delegate = nil;
[player removeFromSuperview];
self.viewIndex -= 1;
if ([self.broveSVGAQueue containsObject:player]) {
[self.broveSVGAQueue removeObject:player];
}
return;
}
2025-01-15 19:02:58 +08:00
if (player == self.enterEffectView && player.loops == 1) {
[self endAnimationEnterEffect];
}
else if (player == self.vggGiftEffectView) {
[self playVGGEnd];
}
else if (player == self.carSVGAEffectView) {
self.carSVGAEffectView.hidden = YES;
[self.carSVGAEffectView removeFromSuperview];
[self nextCarEffect];
}
}
#pragma mark - HWDMP4PlayDelegate
- (BOOL)shouldStartPlayMP4:(VAPView *)container config:(QGVAPConfigModel *)config {
CGFloat width = config.info.size.width;
CGFloat height = config.info.size.height;
container.center = self.center;
[container mas_updateConstraints:^(MASConstraintMaker *make) {
make.width.mas_equalTo(KScreenWidth);
make.height.mas_equalTo(KScreenWidth * height / width);
}];
return YES;
}
- (void)viewDidFinishPlayMP4:(NSInteger)totalFrameCount view:(VAPView *)container {
dispatch_async(dispatch_get_main_queue(), ^{
container.hidden = YES;
if (container == self.carVapEffectView) {
[self.carVapEffectView removeFromSuperview];
self.carVapEffectView = nil;
[self nextCarEffect];
}
else if (container == self.vapGiftEffectView) {
[self playVAGEnd];
}
2025-01-16 16:00:12 +08:00
else if(container == self.luckyVapGiftEffectView) {
[self.luckyVapGiftEffectView removeFromSuperview];
self.luckyVapGiftEffectView = nil;
}
2025-01-15 19:02:58 +08:00
});
}
- (void)viewDidStopPlayMP4:(NSInteger)lastFrameIndex view:(VAPView *)container {
dispatch_async(dispatch_get_main_queue(), ^{
container.hidden = YES;
if (container == self.carVapEffectView) {
[self.carVapEffectView removeFromSuperview];
[self nextCarEffect];
}
else if (container == self.vapGiftEffectView) {
[self playVAGEnd];
}
2025-01-16 16:00:12 +08:00
else if(container == self.luckyVapGiftEffectView) {
[self.luckyVapGiftEffectView removeFromSuperview];
self.luckyVapGiftEffectView = nil;
}
2025-01-15 19:02:58 +08:00
});
}
- (void)viewDidFailPlayMP4:(NSError *)error{
[self playVAGFailure];
}
- (void)loadVapImageWithURL:(NSString *)urlStr
context:(NSDictionary *)context
completion:(VAPImageCompletionBlock)completionBlock {
if (self.mp4TempReceiveInfoModel) {
dispatch_async(dispatch_get_main_queue(), ^{
QGVAPSourceInfo *info = (QGVAPSourceInfo *)context[@"resource"];
2025-04-02 11:04:07 +08:00
// NSLog(@" MP4 的 key - info.contentTag : %@", info.contentTag);
2025-01-15 19:02:58 +08:00
[self _loadMP4AvatarURL:urlStr
info:info
completion:completionBlock];
});
}
}
- (void)_loadMP4AvatarURL:(NSString *)urlStr
info:(QGVAPSourceInfo *)info
completion:(VAPImageCompletionBlock)completionBlock {
NSString *path = @"";
switch (self.mp4TempReceiveInfoModel.gift.showAvatarType) {
case 1: // 使 avatar
case 3:
path = self.mp4TempReceiveInfoModel.avatar;
if ([NSString isEmpty:path]) {
path = self.mp4TempReceiveInfoModel.sendUserAvatar;
}
break;
case 2: // 使 target avatar
path = self.mp4TempReceiveInfoModel.targetAvatar;
if ([NSString isEmpty:path]) {
path = self.mp4TempReceiveInfoModel.recvUserAvatar;
}
break;
default:
break;
}
if ([NSString isEmpty:path]) {
completionBlock(kImage(@"common_avatar"), nil, @"dafeult image");
} else {
NetImageView *avatar_Loader = [[NetImageView alloc] init];
[avatar_Loader loadImageWithUrl:path
completion:^(UIImage * _Nullable image, NSURL * _Nonnull url) {
completionBlock(image, nil, urlStr);
}];
[self.mp4AvatarLoaders addObject:avatar_Loader];
}
}
#pragma mark - PAGViewListener
- (void)onAnimationEnd:(PAGView*)pagView{
dispatch_async(dispatch_get_main_queue(), ^{
pagView.hidden = YES;
if (pagView == self.pagGiftEffectView) {
self.isPlayingGiftEffect = NO;
}
else if(pagView == self.carPagEffectView){
[self.carPagEffectView removeFromSuperview];
self.carPagEffectView = nil;
[self nextCarEffect];
}
});
}
- (void)onAnimationCancel:(PAGView*)pagView{
dispatch_async(dispatch_get_main_queue(), ^{
pagView.hidden = YES;
if (pagView == self.pagGiftEffectView) {
self.isPlayingGiftEffect = NO;
}
});
}
#pragma mark - RoomHostDelegate
#pragma mark - RoomGuestDelegate: NIMCustomMessage
- (void)handleNIMCustomMessage:(NIMMessage *)message {
if (![message.messageObject isKindOfClass:[NIMCustomObject class]]) {
return;
}
NIMCustomObject *obj = (NIMCustomObject *)message.messageObject;
if (obj.attachment == nil || ![obj.attachment isKindOfClass:[AttachmentModel class]]) {
return;
}
AttachmentModel *attachment = (AttachmentModel *)obj.attachment;
{
// first/secondpayload size线
NSData *payloadJSON = nil;
@try { payloadJSON = [NSJSONSerialization dataWithJSONObject:attachment.data ?: @{} options:0 error:nil]; } @catch (__unused NSException *e) {}
NSLog(@"[Combo effect][Anim] 🎞 handleNIMCustomMessage | first=%ld second=%ld | payload=%lub | main=%@ | ts=%.3f",
(long)attachment.first, (long)attachment.second,
(unsigned long)payloadJSON.length,
[NSThread isMainThread] ? @"YES" : @"NO",
[[NSDate date] timeIntervalSince1970]);
}
2025-01-15 19:02:58 +08:00
switch (attachment.first) {
2025-02-28 19:04:09 +08:00
case CustomMessageType_User_Enter_Room:
[self _handleEnterRoomMessage:message];
break;
case CustomMessageType_RedPacket:
[self _handleLuckyPackageMessage:attachment];
break;
2025-01-15 19:02:58 +08:00
case CustomMessageType_Gift:
[self _handleGiftMessage:attachment];
break;
case CustomMessageType_AllMicroSend:
[self _handleGiftMessage:attachment];
break;
case CustomMessageType_Car_Notify:
[self handleCarEnter:attachment];
break;
case CustomMessageType_CP:
[self receiveCPEvent:attachment];
break;
case CustomMessageType_Super_Gift:
[self _handleSuperGift:attachment];
break;
case CustomMessageType_General_Floating_Screen:
[self _handleCommonBanner:attachment];
break;
case CustomMessageType_LuckyBag:
2025-01-16 16:00:12 +08:00
[self handleLuckyBag:attachment];
2025-01-15 19:02:58 +08:00
break;
case CustomMessageType_Look_Love:
2025-01-16 16:00:12 +08:00
[self handle98:attachment];
2025-01-15 19:02:58 +08:00
break;
case CustomMessageType_RoomPlay_Dating:
2025-01-16 16:00:12 +08:00
[self handleDating:attachment];
2025-01-15 19:02:58 +08:00
break;
case CustomMessageType_Across_Room_PK:
2025-01-16 16:00:12 +08:00
[self handleAcrossRoomPK:attachment];
2025-01-15 19:02:58 +08:00
break;
case CustomMessageType_Anchor_FansTeam:
2025-01-16 16:00:12 +08:00
[self handleAnchorFansTeam:attachment];
2025-01-15 19:02:58 +08:00
break;
case CustomMessageType_Anchor_Hour_Rank:
2025-01-16 16:00:12 +08:00
[self handleAnchorHourRank:attachment];
2025-01-15 19:02:58 +08:00
break;
case CustomMessageType_License_Hour_Rank:
2025-01-16 16:00:12 +08:00
[self handleLicenseHourRank:attachment];
2025-01-15 19:02:58 +08:00
break;
case CustomMessageType_Gift_Compound:
2025-01-16 16:00:12 +08:00
[self handle93:attachment];
2025-01-15 19:02:58 +08:00
break;
case CustomMessageType_Room_Sailing:
2025-01-16 16:00:12 +08:00
[self handle81:attachment];
2025-01-15 19:02:58 +08:00
break;
2025-01-16 16:00:12 +08:00
case CustomMessageType_Graffiti_Gift: {
[self receiveRoomGraffitiGift:attachment];
}
2025-01-15 19:02:58 +08:00
break;
case CustomMessageType_Graffiti_Star_Kitchen:
2025-01-16 16:00:12 +08:00
[self handle104:attachment];
2025-01-15 19:02:58 +08:00
break;
case CustomMessageType_Treasure_Fairy:
2025-01-16 16:00:12 +08:00
[self handleFairy:attachment];
2025-01-15 19:02:58 +08:00
break;
case CustomMessageType_Tarot:
2025-01-16 16:00:12 +08:00
[self handleTarot:attachment];
2025-01-15 19:02:58 +08:00
break;
case CustomMessageType_Common_H5:
2025-01-16 16:00:12 +08:00
[self handleCommonH5:attachment];
2025-01-15 19:02:58 +08:00
break;
default:
break;
}
}
2025-02-28 19:04:09 +08:00
- (void)_handleEnterRoomMessage:(NIMMessage *)message {
NIMCustomObject *obj = (NIMCustomObject *)message.messageObject;
if (obj.attachment == nil || ![obj.attachment isKindOfClass:[AttachmentModel class]]) {
return;
}
AttachmentModel *attachment = (AttachmentModel *)obj.attachment;
switch (attachment.second) {
case Custom_Message_Sub_User_Enter_Room: {
RoomEnterModel *model = [RoomEnterModel modelWithJSON:attachment.data];
if (model.platformRole == 1) {
return;
}
if (model.enterHide) {
//
if (model.uid == [AccountInfoStorage instance].getUid.integerValue) {
2025-02-28 19:04:09 +08:00
[self createEnterHideAnimation];
}
} else {
NSString *userName = model.nick;
if (model.cpList.count > 0 && model.screenType < 3) {
2025-03-06 15:26:44 +08:00
NSString *title = [NSString stringWithFormat:YMLocalizedString(@"XPRoomAnimationView0"), userName];
NSDictionary * dic= @{@"title":title,
@"experLevelSeq":[NSString stringWithFormat:@"%ld", model.experLevelSeq],
@"effectPath" : @"",
@"isCP":@(YES)
};
[self.enterRoomAnimationQueue addObject:dic];
2025-02-28 19:04:09 +08:00
} else {
NSString *title = [NSString stringWithFormat:YMLocalizedString(@"XPRoomAnimationView0"), userName];
NSDictionary * dic= @{@"title":title,
@"experLevelSeq":[NSString stringWithFormat:@"%ld", model.experLevelSeq],
@"effectPath" : model.enterRoomEffects.length ? model.enterRoomEffects : @""};
[self.enterRoomAnimationQueue addObject:dic];
}
[self tryDequeueAnimation];
}
}
break;
default:
break;
}
}
- (void)_handleLuckyPackageMessage:(AttachmentModel *)attachment {
if ([self _isInSudGame]) {
return;
}
switch (attachment.second) {
case Custom_Message_Sub_LuckyPackage:
[self receiveLuckGiftBanner:attachment];
break;
default:
return;
break;
}
}
2025-01-15 19:02:58 +08:00
- (void)_handleGiftMessage:(AttachmentModel *)attachment {
if ([self _isInSudGame]) {
return;
}
NSLog(@"[Combo effect] 📨 收到礼物消息 - second: %ld", (long)attachment.second);
2025-01-15 19:02:58 +08:00
GiftReceiveInfoModel * receiveInfo = [GiftReceiveInfoModel modelWithJSON:attachment.data];
[receiveInfo giftDataAlignment];
//
if (receiveInfo.comboCount < 1) {
NSLog(@"[Combo effect] 🚨 收到云信消息中连击计数异常 - comboCount: %ld", (long)receiveInfo.comboCount);
// attachment.data
NSNumber *dataComboCount = attachment.data[@"comboCount"];
if (dataComboCount && [dataComboCount integerValue] >= 1) {
NSLog(@"[Combo effect] 🔧 从 attachment.data 修复连击计数 - 修复为: %@", dataComboCount);
receiveInfo.comboCount = [dataComboCount integerValue];
} else {
NSLog(@"[Combo effect] 🔧 设置默认连击计数为 1");
receiveInfo.comboCount = 1;
}
}
NSLog(@"[Combo effect] 📨 礼物消息解析完成 - giftId: %ld, combo: %ld, uid: %@", (long)receiveInfo.gift.giftId, (long)receiveInfo.comboCount, receiveInfo.uid);
2025-02-28 19:04:09 +08:00
receiveInfo.isLuckyBagGift = (attachment.second == Custom_Message_Sub_Gift_LuckySend ||
attachment.second == Custom_Message_Sub_AllMicroLuckySend ||
attachment.second == Custom_Message_Sub_AllBatchMicroLuckySend);
2025-01-15 19:02:58 +08:00
receiveInfo.isBatch = (attachment.second == Custom_Message_Sub_AllBatchSend ||
attachment.second == Custom_Message_Sub_AllBatchMicroLuckySend);
receiveInfo.isComboBatch = (attachment.second == Custom_Message_Sub_AllMicroSend);
switch (attachment.second) {
case Custom_Message_Sub_Gift_Send:
[self _handleGift:receiveInfo attachment:attachment];
break;
case Custom_Message_Sub_AllMicroSend:
2025-01-22 21:22:58 +08:00
case Custom_Message_Sub_AllBatchSend:
2025-01-15 19:02:58 +08:00
[self _handleGift:receiveInfo attachment:attachment];
break;
case Custom_Message_Sub_Gift_ChannelNotify:
//广 banner
[self receiveRoomGiftBanner:attachment];
return;
break;
case Custom_Message_Sub_Gift_EmbeddedStyle:
[self _handleGiftEmbeddedStyle:receiveInfo attachment:attachment];
break;
2025-02-28 19:04:09 +08:00
case 607:
[self receiveLuckGiftBanner:attachment];
break;
case Custom_Message_Sub_Gift_LuckySend:
case Custom_Message_Sub_AllMicroLuckySend:
case Custom_Message_Sub_AllBatchMicroLuckySend:
{
[self _handleGift:receiveInfo attachment:attachment];
// if (receiveInfo.mp4Url.length > 0) {
// [self playLuckyGiftEffectWithVapUrl:receiveInfo.mp4Url];
// } else {
// NSString * svgaString = receiveInfo.luckyGiftSvgaUrl.length > 0 ? receiveInfo.luckyGiftSvgaUrl : receiveInfo.gift.luckyGiftSvgaUrl;
// NSURL * luckyGiftSvgaUrl = [NSURL URLWithString:svgaString];
// if (luckyGiftSvgaUrl.absoluteString.length > 0) {
// [self play:luckyGiftSvgaUrl];
// }
// }
// dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.5 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
// [self receiveGift:receiveInfo];
// });
}
break;
2025-01-15 19:02:58 +08:00
default:
break;
}
if (receiveInfo.isLuckyBagGift) {
NSLog(@"[Combo effect] 🎁 处理福袋礼物");
2025-01-15 19:02:58 +08:00
[self receiveGiftHandleSendGiftAnimationWith:receiveInfo
attachment:attachment];
[self _handleBagGift:receiveInfo];
} else {
if (receiveInfo.gift.notifyFull == 1 &&
attachment.second == Custom_Message_Sub_Gift_Send) {
//
NSLog(@"[Combo effect] 🎁 全服礼物由自己发送,跳过播放");
2025-01-15 19:02:58 +08:00
return;
}
2025-02-28 19:04:09 +08:00
//
NSLog(@"[Combo effect] 🎁 处理普通礼物动画");
2025-01-15 19:02:58 +08:00
[self receiveGiftHandleSendGiftAnimationWith:receiveInfo
attachment:attachment];
2025-02-28 19:04:09 +08:00
// svga/mp4
2025-01-15 19:02:58 +08:00
[self receiveGift:receiveInfo];
}
}
- (void)_handleBagGift:(GiftReceiveInfoModel *)receiveInfo {
if (!self.hostDelegate.getRoomInfo.hasAnimationEffect) {
return;
}
[self receiveGift:receiveInfo];
}
- (void)_handleGift:(GiftReceiveInfoModel *)receiveInfo
attachment:(AttachmentModel *)attachment {
// uid
if (receiveInfo.targetUsers.count == 0) {
GiftReceiveUserInfoModel *model = [[GiftReceiveUserInfoModel alloc] init];
model.nick = receiveInfo.targetNick;
model.avatar = receiveInfo.targetAvatar;
model.uid = receiveInfo.uid.integerValue;
receiveInfo.targetUsers = @[model];
}
// uid
if (receiveInfo.targetUsers.count > 0 && receiveInfo.targetUids.count <= 0) {
receiveInfo.targetUids = [receiveInfo.targetUsers valueForKeyPath:@"uid"];
2025-01-15 19:02:58 +08:00
}
}
- (void)_handleGiftEmbeddedStyle:(GiftReceiveInfoModel *)receiveInfo
attachment:(AttachmentModel *)attachment {
//
receiveInfo.targetUid = [[attachment.data objectForKey:@"recvUserUid"] stringValue];
receiveInfo.targetNick = [attachment.data objectForKey:@"recvUserNick"];
receiveInfo.targetAvatar = [attachment.data objectForKey:@"recvUserAvatar"];
receiveInfo.avatar = [attachment.data objectForKey:@"sendUserAvatar"];
receiveInfo.nick = [attachment.data objectForKey:@"sendUserNick"];
receiveInfo.uid = [[attachment.data objectForKey:@"sendUserUid"] stringValue];
// uid
if (receiveInfo.targetUsers.count > 0 && receiveInfo.targetUids.count <= 0) {
receiveInfo.targetUids = [receiveInfo.targetUsers valueForKeyPath:@"uid"];
}
}
- (void)_handleSuperGift:(AttachmentModel *)attachment {
switch (attachment.second) {
case Custom_Message_Sub_Super_Gift_Winning_Coins:
[self receiveLuckGiftWinning:attachment];
break;
case Custom_Message_Sub_Super_Gift_Winning_Coins_ALL_Room:
[self receiveLuckGiftBanner:attachment];
break;
2025-04-02 11:04:07 +08:00
case Custom_Message_Sub_Super_Gift_Banner:
[self handleBroveGiftBanner:attachment];
break;
case Custom_Message_Sub_Super_Gift_UI_Rffect:
2025-04-21 13:52:13 +08:00
[self receiveBravoGiftWinning:attachment];
2025-01-15 19:02:58 +08:00
default:
break;
}
}
- (void)_handleCommonBanner:(AttachmentModel *)attachment {
switch (attachment.second) {
case Custom_Message_Sub_General_Floating_Screen_One_Room:
case Custom_Message_Sub_General_Floating_Screen_All_Room:
[self receiveRoomGeneralFloatingScreen:attachment];
break;
default:
break;
}
}
- (NSString *)_findFullPath:(NSString *)url {
NSString *encodingUrl = [url pureURLString];
NSString *fileName = [[encodingUrl componentsSeparatedByString:@"/"] lastObject];
NSString *fullPath = [self.GiftDynamicEffectListPath stringByAppendingPathComponent:fileName];
return fullPath;
}
- (void)_updateGiftEffectContentMode:(UIView *)view
size:(CGSize)size {
CGFloat width = size.width;
CGFloat height = size.height;
if (width > height) {
view.contentMode = UIViewContentModeScaleAspectFit;
} else {//
CGFloat resizeH = KScreenWidth * height / width;//
if (resizeH > KScreenHeight) {//
view.contentMode = UIViewContentModeScaleAspectFill;
} else {//
view.contentMode = UIViewContentModeScaleAspectFit;
}
}
}
2025-01-16 16:00:12 +08:00
- (void)handleCommonH5:(AttachmentModel *)attachment {
if (!attachment) {
return;
}
switch (attachment.second) {
2025-01-16 16:00:12 +08:00
default:
break;
}
}
- (void)handleTarot:(AttachmentModel *)attachment {
if (!attachment) {
return;
}
switch (attachment.second) {
2025-01-16 16:00:12 +08:00
default:
break;
}
}
- (void)handleFairy:(AttachmentModel *)attachment {
if (!attachment) {
return;
}
switch (attachment.second) {
case Custom_Message_Sub_Treasure_Fairy_Draw_Gift_L4:
case Custom_Message_Sub_Treasure_Fairy_Draw_Gift_L5:
case Custom_Message_Sub_Treasure_Fairy_Convert_L1:
case Custom_Message_Sub_Treasure_Fairy_Convert_L2:
case Custom_Message_Sub_Treasure_Fairy_Convert_L3:
[self receiveTreasureFairyGiftHighLevel:attachment];
break;
default:
break;
}
}
- (void)handle98:(AttachmentModel *)attachment {
if (!attachment) {
return;
}
switch (attachment.second) {
case Custom_Message_Sub_Look_Love_InRoom_NeedAllMicSend:
[self receiveCandyTreeGiftHighLevle:attachment];
break;
default:
break;
}
}
- (void)handle104:(AttachmentModel *)attachment {
if (!attachment) {
return;
}
switch (attachment.second) {
2025-01-16 16:00:12 +08:00
default:
break;
}
}
- (void)handleLuckyBag:(AttachmentModel *)attachment {
if (!attachment) {
return;
}
switch (attachment.second) {
case Custom_Message_Sub_Room_Gift_LuckBag_FullScree:
2025-02-28 19:04:09 +08:00
case Custom_Message_Sub_Room_Gift_LuckBag_Server:
2025-01-16 16:00:12 +08:00
[self receiveLuckyGiftBigPrize:attachment];
break;
default:
break;
}
}
- (void)handleVIPLevelUp:(AttachmentModel *)attachment {
if (!attachment) {
return;
}
switch (attachment.second) {
case Custom_Message_Sub_Room_Noble_LevelUp_Suspend:
[self receiveNobleLevelUp:attachment];
break;
default:
break;
}
}
- (void)handleDating:(AttachmentModel *)attachment {
if (!attachment) {
return;
}
switch (attachment.second) {
case Custom_Message_Sub_Room_Play_Dating_Public_Result:
[self roomDatingPublicResult:attachment];
break;
default:
break;
}
}
- (void)handleAcrossRoomPK:(AttachmentModel *)attachment {
if (!attachment) {
return;
}
switch (attachment.second) {
case Custom_Message_Sub_AcrossRoomPK_Result:
[self acrossRoomPKBannerAnimation:attachment];
break;
default:
break;
}
}
- (void)handleAnchorFansTeam:(AttachmentModel *)attachment {
if (!attachment) {
return;
}
switch (attachment.second) {
case Custom_Message_Sub_FansTeam_Join_Success: {
GiftReceiveInfoModel *receiveInfo = [[GiftReceiveInfoModel alloc] init];
GiftInfoModel *giftInfo = [GiftInfoModel modelWithJSON:attachment.data[@"giftVo"]];
receiveInfo.gift = giftInfo;
receiveInfo.giftInfo = giftInfo;
[self receiveFansTeamGiftHandleSendGiftAnimation:attachment];
[self receiveGift:receiveInfo];
}
break;
default:
break;
}
}
- (void)handleAnchorHourRank:(AttachmentModel *)attachment {
if (!attachment) {
return;
}
switch (attachment.second) {
case Custom_Message_Sub_Anchor_Hour_Rank:
[self receiveAnchorHourRank:attachment];
break;
default:
break;
}
}
- (void)handleLicenseHourRank:(AttachmentModel *)attachment {
if (!attachment) {
return;
}
switch (attachment.second) {
case Custom_Message_Sub_License_Hour_Rank:
[self receiveAnchorHourRank:attachment];
break;
default:
break;
}
}
- (void)handle93:(AttachmentModel *)attachment {
if (!attachment) {
return;
}
switch (attachment.second) {
case Custom_Message_Sub_Gift_Compound:
[self receiveGiftCompound:attachment];
break;
default:
break;
}
}
- (void)handle81:(AttachmentModel *)attachment {
if (!attachment) {
return;
}
switch (attachment.second) {
case Custom_Message_Sub_Sailing_AllRoom_Notify:
case Custom_Message_Sub_Sailing_InRoom_NeedAllMicSend:
[self receiveRoomSailing:attachment];
break;
default:
break;
}
}
2025-04-02 11:04:07 +08:00
- (void)handleBroveGiftBanner:(AttachmentModel *)attachment {
[self inserBannerModelToQueue:attachment];
}
2025-01-15 19:02:58 +08:00
#pragma mark - RoomGuestDelegate: NIMNotificationMessageDelegate
- (void)handleNIMNotificationMessage:(NIMMessage *)message {
2025-02-28 19:04:09 +08:00
return;
// NIMNotificationObject *notiMsg = (NIMNotificationObject *)message.messageObject;
// NIMChatroomNotificationContent *content = (NIMChatroomNotificationContent *)notiMsg.content;
// if (!content) {
// return;
// }
//
// switch (content.eventType) {
// case NIMChatroomEventTypeEnter:
// [self enterRoom:message content:content];
// break;
//
// default:
// break;
// }
2025-01-15 19:02:58 +08:00
}
#pragma mark - NIMBroadcastManagerDelegate
- (void)onReceiveBroadcastMessage:(NIMBroadcastMessage *)broadcastMessage {
if (broadcastMessage.content) {
NSDictionary *msgDictionary = [broadcastMessage.content toJSONObject];
AttachmentModel *attachment = [AttachmentModel modelWithJSON:msgDictionary[@"body"]];
NSString *partitionId = [NSString stringWithFormat:@"%@",attachment.data[@"partitionId"]];
if(![partitionId isEqualToString:self.hostDelegate.getUserInfo.partitionId]){
return;
}
switch (attachment.first) {
case CustomMessageType_General_Floating_Screen:
[self _handleCommonBanner:attachment];
break;
2025-01-16 16:00:12 +08:00
case CustomMessageType_Noble_VIP:
[self handleVIPLevelUp:attachment];
break;
case CustomMessageType_LuckyBag:
[self handleLuckyBag:attachment];
break;
case CustomMessageType_Graffiti_Star_Kitchen:
[self handle104:attachment];
break;
case CustomMessageType_Look_Love:
[self handle98:attachment];
break;
case CustomMessageType_Treasure_Fairy:
[self handleFairy:attachment];
break;
case CustomMessageType_Tarot:
[self handleTarot:attachment];
break;
case CustomMessageType_Common_H5:
[self handleCommonH5:attachment];
break;
2025-01-15 19:02:58 +08:00
default:
break;
}
}
}
#pragma mark - GiftAnimationManagerDelegate
- (CGPoint)animationPointAtStageViewByUid:(NSString *)uid {
return [self.hostDelegate animationPointAtStageViewByUid:uid];
}
#pragma mark - Gesture
- (void)addBnnerContainGesture {
[self insertSubview:self.bannerSwipeGestureContainer aboveSubview:self.bannerContainer];
[self insertSubview:self.bannerLeftTapGestureContainer aboveSubview:self.bannerContainer];
[self insertSubview:self.bannerRightTapGestureContainer aboveSubview:self.bannerContainer];
// tag
self.bannerSwipeGestureContainer.tag = 1001; //
self.bannerLeftTapGestureContainer.tag = 1002; //
self.bannerRightTapGestureContainer.tag = 1003; //
[self.bannerSwipeGestureContainer mas_makeConstraints:^(MASConstraintMaker *make) {
make.center.mas_equalTo(self.bannerContainer);
make.top.bottom.mas_equalTo(self.bannerContainer);
make.width.mas_equalTo(self.bannerContainer.mas_width).multipliedBy(2.0/3.0);
}];
[self.bannerLeftTapGestureContainer mas_makeConstraints:^(MASConstraintMaker *make) {
make.top.leading.bottom.mas_equalTo(self.bannerContainer);
make.trailing.mas_equalTo(self.bannerSwipeGestureContainer.mas_leading);
}];
[self.bannerRightTapGestureContainer mas_makeConstraints:^(MASConstraintMaker *make) {
make.top.trailing.bottom.mas_equalTo(self.bannerContainer);
make.leading.mas_equalTo(self.bannerSwipeGestureContainer.mas_trailing);
}];
// swipe 2/3
2025-01-15 19:02:58 +08:00
UISwipeGestureRecognizer *swipe = [[UISwipeGestureRecognizer alloc] initWithTarget:self
action:@selector(handleSwipe)];
2025-01-22 21:22:58 +08:00
if (isMSRTL()) {
swipe.direction = UISwipeGestureRecognizerDirectionRight;
} else {
swipe.direction = UISwipeGestureRecognizerDirectionLeft;
}
swipe.delegate = self;
// tap 2/3
UITapGestureRecognizer *centerTap = [[UITapGestureRecognizer alloc] initWithTarget:self
action:@selector(handleBannerTap:)];
centerTap.delegate = self;
// tap 1/6
UITapGestureRecognizer *leftTap = [[UITapGestureRecognizer alloc] initWithTarget:self
action:@selector(handleBannerTap:)];
leftTap.delegate = self;
// tap 1/6
UITapGestureRecognizer *rightTap = [[UITapGestureRecognizer alloc] initWithTarget:self
action:@selector(handleBannerTap:)];
rightTap.delegate = self;
2025-01-22 21:22:58 +08:00
// swipe tap
[centerTap requireGestureRecognizerToFail:swipe];
//
[self.bannerSwipeGestureContainer addGestureRecognizer:swipe];
[self.bannerSwipeGestureContainer addGestureRecognizer:centerTap];
[self.bannerLeftTapGestureContainer addGestureRecognizer:leftTap];
[self.bannerRightTapGestureContainer addGestureRecognizer:rightTap];
NSLog(@"🎯 手势识别器设置完成 - 中央容器: %@, 左侧容器: %@, 右侧容器: %@",
NSStringFromClass([self.bannerSwipeGestureContainer class]),
NSStringFromClass([self.bannerLeftTapGestureContainer class]),
NSStringFromClass([self.bannerRightTapGestureContainer class]));
2025-01-15 19:02:58 +08:00
}
- (void)handleSwipe {
// banner swipe
// bannerContainer banner
UIView *currentVisibleBanner = nil;
for (UIView *subview in self.bannerContainer.subviews) {
if (!subview.hidden && subview.alpha > 0.01) {
currentVisibleBanner = subview;
break;
}
}
if (currentVisibleBanner) {
NSLog(@"🎯 检测到 swipe 手势,当前有可见 banner: %@,发送 SwipeOutBanner 通知", NSStringFromClass([currentVisibleBanner class]));
// banner banner swipe
[[NSNotificationCenter defaultCenter] postNotificationName:@"SwipeOutBanner"
object:currentVisibleBanner];
} else {
NSLog(@"🎯 检测到 swipe 手势,但当前没有可见 banner忽略此手势");
}
2025-01-15 19:02:58 +08:00
}
- (void)handleBannerTap:(UITapGestureRecognizer *)tapGesture {
CGPoint tapPoint = [tapGesture locationInView:self.bannerContainer];
// banner tap
if ([self isPointInBannerInteractiveArea:tapPoint]) {
// banner banner
NSLog(@"🎯 Banner tap 位置在可交互区域banner 将处理此事件");
[[NSNotificationCenter defaultCenter] postNotificationName:@"TapBanner"
object:nil
userInfo:@{@"point": [NSValue valueWithCGPoint:tapPoint]}];
} else {
// banner tap
self.savedTapPoint = tapPoint;
self.hasSavedTapPoint = YES;
NSLog(@"💾 Banner tap 位置不在可交互区域,已保存位置: %@", NSStringFromCGPoint(tapPoint));
// bannerContainer
CGPoint screenPoint = [self.bannerContainer convertPoint:tapPoint toView:nil];
// UIView *tappedView = tapGesture.view;
[[NSNotificationCenter defaultCenter] postNotificationName:@"BannerTapToFunctionContainer"
object:nil
userInfo:@{@"point": [NSValue valueWithCGPoint:screenPoint]}];
}
}
- (BOOL)isPointInBannerInteractiveArea:(CGPoint)point {
// 使
TouchAreaCacheManager *cacheManager = [TouchAreaCacheManager sharedManager];
// 使
if ([cacheManager isPointInInteractiveArea:point]) {
NSLog(@"🎯 isPointInBannerInteractiveArea: 缓存命中 - 点 %@ 在可交互区域内", NSStringFromCGPoint(point));
return YES;
}
// 使
NSLog(@"🎯 isPointInBannerInteractiveArea: 缓存未命中,使用传统方法检查");
for (UIView *subview in self.bannerContainer.subviews) {
if (subview.hidden || subview.alpha <= 0.01) {
continue;
}
//
if (CGRectContainsPoint(subview.bounds, point)) {
//
if (subview.userInteractionEnabled) {
//
CGPoint subviewPoint = [subview convertPoint:point fromView:self.bannerContainer];
UIView *hitView = [subview hitTest:subviewPoint withEvent:nil];
if (hitView && hitView.userInteractionEnabled) {
//
CGRect bannerBounds = subview.bounds;
CGRect interactiveBounds = [self calculateInteractiveBoundsForView:subview];
[cacheManager updateBannerBounds:bannerBounds
interactiveBounds:interactiveBounds
forBanner:subview];
NSLog(@"🎯 isPointInBannerInteractiveArea: 传统方法命中,已更新缓存");
return YES;
}
}
}
}
NSLog(@"🎯 isPointInBannerInteractiveArea: 点 %@ 不在可交互区域内", NSStringFromCGPoint(point));
return NO;
}
#pragma mark - UIGestureRecognizerDelegate
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer {
//
return YES;
}
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch {
CGPoint touchPoint = [touch locationInView:self.bannerContainer];
CGFloat containerWidth = self.bannerContainer.bounds.size.width;
// 使
GestureOptimizer *optimizer = [GestureOptimizer sharedOptimizer];
BOOL shouldReceive = [optimizer shouldGestureRecognizer:gestureRecognizer
receiveTouchAtPoint:touchPoint
containerWidth:containerWidth];
//
if (shouldReceive) {
[optimizer debugGestureAreaForPoint:touchPoint containerWidth:containerWidth];
}
return shouldReceive;
}
2025-01-15 19:02:58 +08:00
#pragma mark - Animations
- (void)enterRoomAnimationFor:(UIView *)targetView
startFrom:(CGPoint)sfPoint
startTo:(CGPoint)stPoint
endFrom:(CGPoint)efPoint
endTo:(CGPoint)etPoint
duration:(CFTimeInterval)duration
completion:(void (^)(BOOL finished))completion {
@kWeakify(self);
[self enterRoomMoveInAnimationFor:targetView
fromValue:sfPoint
toValue:stPoint
completion:^(BOOL finished) {
if (finished) {
@kStrongify(self);
@kWeakify(self);
[self enterRoomMoveOutAnimationFor:targetView
fromValue:efPoint
toValue:etPoint
beginTime:duration
completion:^(BOOL finished) {
if (finished) {
@kStrongify(self);
[self cleanupAnimationsForView:targetView];
if (completion) {
completion(finished);
}
}
}];
}
}];
}
- (void)enterRoomMoveInAnimationFor:(UIView *)view
fromValue:(CGPoint)fromValue
toValue:(CGPoint)toValue
completion:(void (^)(BOOL finished))completion {
POPSpringAnimation *springAnimation = [POPSpringAnimation animationWithPropertyNamed:kPOPViewCenter];
springAnimation.springSpeed = 12;
springAnimation.springBounciness = 10.f;
springAnimation.fromValue = [NSValue valueWithCGPoint:fromValue];
springAnimation.toValue = [NSValue valueWithCGPoint:toValue];
[springAnimation setCompletionBlock:^(POPAnimation *anim, BOOL finished) {
if (completion) completion(finished);
}];
[view pop_addAnimation:springAnimation forKey:@"amationSpringIn"];
}
- (void)enterRoomMoveOutAnimationFor:(UIView *)view
fromValue:(CGPoint)fromValue
toValue:(CGPoint)toValue
beginTime:(CFTimeInterval)beginTime
completion:(void (^)(BOOL finished))completion {
POPSpringAnimation *moveAnimation = [POPSpringAnimation animationWithPropertyNamed:kPOPViewCenter];
moveAnimation.fromValue = [NSValue valueWithCGPoint:fromValue];
moveAnimation.toValue = [NSValue valueWithCGPoint:toValue];
moveAnimation.beginTime = beginTime;
moveAnimation.springSpeed = 8;
moveAnimation.springBounciness = 15.f;
[moveAnimation setCompletionBlock:^(POPAnimation *anim, BOOL finished) {
if (completion) completion(finished);
}];
[view pop_addAnimation:moveAnimation forKey:@"animetionMoveOut"];
}
- (void)cleanupAnimationsForView:(UIView *)view {
[view pop_removeAllAnimations];
[view removeFromSuperview];
}
#pragma mark - Common methods
- (NSString *)_resolveUserNameFromContent:(NIMChatroomNotificationContent *)content
extModel:(XPMessageRemoteExtModel *)extModel {
// 1) extModel.nick
if (![NSString isEmpty:extModel.nick]) {
return extModel.nick;
}
// 2) extModel.nick content.source.nick
if (![NSString isEmpty:content.source.nick]) {
return content.source.nick;
}
// 3) nick
if (content.source.userId.intValue == self.hostDelegate.getUserInfo.uid &&
![NSString isEmpty:self.hostDelegate.getUserInfo.nick]) {
return self.hostDelegate.getUserInfo.nick;
}
// 4)
return @"";
}
- (NSString *)_mapExperLevelSeqToLocalKey:(NSInteger)seq {
if (seq >= 30 && seq <= 39) {
return @"experience_entre_effect_30";
} else if (seq >= 40 && seq <= 49) {
return @"experience_entre_effect_40";
} else if (seq >= 50 && seq <= 59) {
return @"experience_entre_effect_50";
} else if (seq >= 60 && seq <= 69) {
return @"experience_entre_effect_60";
} else if (seq >= 70 && seq <= 79) {
return @"experience_entre_effect_70";
} else if (seq >= 80 && seq <= 89) {
return @"experience_entre_effect_80";
} else if (seq >= 90) {
return @"experience_entre_effect_90";
}
return @"";
}
- (BOOL)_isInSudGame {
BOOL isGamePlaying = NO;
if (self.hostDelegate.getRoomInfo.type == RoomType_MiniGame) {
NSInteger micCount = self.hostDelegate.getRoomInfo.mgMicNum;
for (int i = -1; i<micCount; i++) {
NSMutableDictionary * micQueue = self.hostDelegate.getMicroQueue;
MicroQueueModel *micSequence = [micQueue objectForKey:[NSString stringWithFormat:@"%d", i]];
if (micSequence == nil || micSequence.userInfo == nil) {
continue;
}
if (micSequence.userInfo.uid == [AccountInfoStorage instance].getUid.integerValue &&
micSequence.userInfo.gameStatus == LittleGamePlayStatus_Plying) {
isGamePlaying = YES;
break;
}
}
}
return isGamePlaying;
}
- (void)_addSubviewToMiddleContainer:(UIView *)view {
if (view.superview == nil) {
[self.middleContainer addSubview:view];
[view mas_makeConstraints:^(MASConstraintMaker *make) {
make.center.mas_equalTo(self.middleContainer);
make.width.mas_equalTo(KScreenWidth);
make.height.mas_equalTo(KScreenHeight);
}];
}
view.hidden = NO;
}
#pragma mark - Lazy init
- (XPRoomAnimationHitView *)bottomContainer {
if (!_bottomContainer) {
_bottomContainer = [[XPRoomAnimationHitView alloc] init];
}
return _bottomContainer;
}
- (XPRoomAnimationHitView *)middleContainer {
if (!_middleContainer) {
_middleContainer = [[XPRoomAnimationHitView alloc] init];
}
return _middleContainer;
}
- (XPRoomAnimationHitView *)topContainer {
if (!_topContainer) {
_topContainer = [[XPRoomAnimationHitView alloc] init];
}
return _topContainer;
}
- (XPRoomAnimationHitView *)bannerContainer {
if (!_bannerContainer) {
_bannerContainer = [[XPRoomAnimationHitView alloc] init];
}
return _bannerContainer;
}
- (UIView *)bannerSwipeGestureContainer {
if (!_bannerSwipeGestureContainer) {
_bannerSwipeGestureContainer = [[UIView alloc] init];
_bannerSwipeGestureContainer.userInteractionEnabled = YES;
}
return _bannerSwipeGestureContainer;
}
- (UIView *)bannerLeftTapGestureContainer {
if (!_bannerLeftTapGestureContainer) {
_bannerLeftTapGestureContainer = [[UIView alloc] init];
_bannerLeftTapGestureContainer.userInteractionEnabled = YES;
}
return _bannerLeftTapGestureContainer;
}
- (UIView *)bannerRightTapGestureContainer {
if (!_bannerRightTapGestureContainer) {
_bannerRightTapGestureContainer = [[UIView alloc] init];
_bannerRightTapGestureContainer.userInteractionEnabled = YES;
}
return _bannerRightTapGestureContainer;
}
2025-01-15 19:02:58 +08:00
- (SVGAImageView *)enterEffectView {
if (_enterEffectView == nil) {
_enterEffectView = [[SVGAImageView alloc]init];
_enterEffectView.delegate = self;
2025-02-28 19:04:09 +08:00
_enterEffectView.contentMode = UIViewContentModeScaleAspectFill;
2025-01-15 19:02:58 +08:00
_enterEffectView.frame = CGRectMake(0, 0, KScreenWidth, 50);
_enterEffectView.backgroundColor = [UIColor clearColor];
_enterEffectView.alpha = 0;
_enterEffectView.userInteractionEnabled = NO;
}
return _enterEffectView;
}
- (NSMutableArray *)svgaQueue{
if(!_svgaQueue){
_svgaQueue = [NSMutableArray array];
}
return _svgaQueue;
}
2025-03-24 16:09:48 +08:00
- (void)addToSvgaQueue:(GiftReceiveInfoModel *)model {
dispatch_async(self.giftEffectsQueue, ^{
[self.svgaQueue addObject:model];
});
}
- (void)removeFromSvgaQueueAtIndex:(NSInteger)index {
dispatch_async(self.giftEffectsQueue, ^{
if (index < self.svgaQueue.count) {
if (index < self.svgaQueue.count) {
[self.svgaQueue xpSafeRemoveObjectAtIndex:index];
}
2025-03-24 16:09:48 +08:00
}
});
}
2025-01-15 19:02:58 +08:00
- (XPRoomGiftAnimationParser *)vapParser {
if (!_vapParser) {
_vapParser = [[XPRoomGiftAnimationParser alloc] init];
}
return _vapParser;
}
- (PAGView *)pagGiftEffectView{
if(!_pagGiftEffectView){
_pagGiftEffectView = [[PAGView alloc]init];
[_pagGiftEffectView addListener:self];
_pagGiftEffectView.backgroundColor = [UIColor clearColor];
_pagGiftEffectView.userInteractionEnabled = NO;
_pagGiftEffectView.repeatCount = 1;
_pagGiftEffectView.scaleMode = PAGScaleModeStretch;
}
return _pagGiftEffectView;
}
- (VAPView *)vapGiftEffectView {
if (!_vapGiftEffectView) {
_vapGiftEffectView = [[VAPView alloc] initWithFrame:CGRectMake(0, 0, KScreenWidth, KScreenHeight)];
_vapGiftEffectView.backgroundColor = [UIColor colorWithWhite:0 alpha:0.5];
_vapGiftEffectView.contentMode = UIViewContentModeScaleAspectFill;
_vapGiftEffectView.hidden = YES;
_vapGiftEffectView.userInteractionEnabled = NO;
}
return _vapGiftEffectView;
}
- (SVGAParser *)vggParser {
if (!_vggParser) {
_vggParser = [[SVGAParser alloc] init];
}
return _vggParser;
}
- (SVGAImageView *)vggGiftEffectView {
if (!_vggGiftEffectView) {
_vggGiftEffectView = [[SVGAImageView alloc]init];
_vggGiftEffectView.backgroundColor = [UIColor colorWithWhite:0 alpha:0.5];
_vggGiftEffectView.userInteractionEnabled = NO;
_vggGiftEffectView.delegate = self;
_vggGiftEffectView.hidden = YES;
_vggGiftEffectView.loops = 1;
_vggGiftEffectView.clearsAfterStop = YES;
}
return _vggGiftEffectView;
}
- (VAPView *)carVapEffectView {
if (!_carVapEffectView) {
_carVapEffectView = [[VAPView alloc] initWithFrame:CGRectMake(0, 0, KScreenWidth, KScreenHeight)];
_carVapEffectView.backgroundColor = [UIColor colorWithWhite:0 alpha:0.3];
_carVapEffectView.contentMode = UIViewContentModeScaleAspectFill;
_carVapEffectView.hidden = YES;
}
return _carVapEffectView;
}
- (SVGAImageView *)carSVGAEffectView {
if (_carSVGAEffectView == nil) {
_carSVGAEffectView = [[SVGAImageView alloc]init];
_carSVGAEffectView.delegate = self;
_carSVGAEffectView.contentMode = UIViewContentModeScaleAspectFit;
_carSVGAEffectView.frame = CGRectMake(0, 0, KScreenWidth, KScreenHeight);
_carSVGAEffectView.backgroundColor = [UIColor colorWithRed:0 green:0 blue:0 alpha:0.3];
_carSVGAEffectView.hidden = YES;
_carSVGAEffectView.userInteractionEnabled = NO;
_carSVGAEffectView.loops = 1;
_carSVGAEffectView.clearsAfterStop = YES;
}
return _carSVGAEffectView;
}
- (PAGView *)carPagEffectView{
if(!_carPagEffectView){
_carPagEffectView = [[PAGView alloc]init];
[_carPagEffectView addListener:self];
_carPagEffectView.backgroundColor = [UIColor clearColor];
_carPagEffectView.userInteractionEnabled = NO;
_carPagEffectView.repeatCount = 1;
_carPagEffectView.scaleMode = PAGScaleModeStretch;
}
return _carPagEffectView;
2025-01-14 14:29:14 +08:00
}
2025-01-16 16:00:12 +08:00
#pragma mark - OLD METHODs
2025-01-16 16:00:12 +08:00
- (void)receiveLuckyGiftBigPrize:(AttachmentModel *)attachment {
if ([self _isInSudGame]) {return;}
PIBaseAnimationViewModel * prizeModel = [PIBaseAnimationViewModel modelWithDictionary:attachment.data];
prizeModel.type = GiftBannerType_Lucky;
prizeModel.isInRoomVisable = attachment.second == Custom_Message_Sub_Room_Gift_LuckBag;
if(self.animationListB.count == 0 && self.isPlayOfB == NO){
[self createBigPrizeAnimation:prizeModel];
}
[self.animationListB addObject:prizeModel];
}
- (void)createBigPrizeAnimation:(PIBaseAnimationViewModel *)prizeModel {
self.isPlayOfB = YES;
CGFloat top = (kNavigationHeight + 15);
XPRoomLuckyBigPrizeView * luckyGiftEffectView = [[XPRoomLuckyBigPrizeView alloc] initWithFrame:CGRectMake(KScreenWidth, top, 375, 71)];
luckyGiftEffectView.delegate = self;
[self.topContainer addSubview:luckyGiftEffectView];
luckyGiftEffectView.giftInfo = prizeModel;
POPSpringAnimation *springAnimation = [POPSpringAnimation animationWithPropertyNamed:kPOPViewCenter];
springAnimation.springSpeed = 12;
springAnimation.springBounciness = 10.f;
springAnimation.fromValue = [NSValue valueWithCGPoint:luckyGiftEffectView.center];
springAnimation.toValue = [NSValue valueWithCGPoint:CGPointMake(KScreenWidth / 2, luckyGiftEffectView.center.y)];
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 7 * NSEC_PER_SEC), dispatch_get_main_queue(), ^{
POPBasicAnimation *moveAnimation = [POPBasicAnimation animationWithPropertyNamed:kPOPViewCenter];
moveAnimation.fromValue = [NSValue valueWithCGPoint:CGPointMake(0, luckyGiftEffectView.center.y)];
moveAnimation.toValue = [NSValue valueWithCGPoint:CGPointMake(-KScreenWidth/2, luckyGiftEffectView.center.y)];
moveAnimation.beginTime = CACurrentMediaTime();
moveAnimation.duration = 0.5;
moveAnimation.repeatCount = 1;
moveAnimation.removedOnCompletion = YES;
@kWeakify(self);
[moveAnimation setCompletionBlock:^(POPAnimation *anim, BOOL finished) {
@kStrongify(self);
if (finished) {
[luckyGiftEffectView removeFromSuperview];
if (self.animationListB.count > 0) {
[self.animationListB xpSafeRemoveObjectAtIndex:0];
2025-01-16 16:00:12 +08:00
}
self.isPlayOfB = NO;
[self playAnimationWithModel];
}
}];
[luckyGiftEffectView pop_addAnimation:moveAnimation forKey:@"moveOutAnimation"];
});
[luckyGiftEffectView pop_addAnimation:springAnimation forKey:@"nobleLevelUpspingOutAnimation"];
}
- (void)receiveCandyTreeGiftHighLevle:(AttachmentModel *)attatchment {
if ([self _isInSudGame]) {return;}
PIBaseAnimationViewModel *giftModel = [PIBaseAnimationViewModel new];
giftModel.data = attatchment.data;
giftModel.second = attatchment.second;
giftModel.first = attatchment.first;
giftModel.type = GiftBannerType_Love;
if (self.animationListB.count == 0 && self.isPlayOfB == NO) {
[self createCandyTreeBannerAnimation:giftModel];
}
[self.animationListB addObject:giftModel];
}
- (void)createCandyTreeBannerAnimation:(PIBaseAnimationViewModel *)attatchment {
CGFloat kscale = (CGFloat)60 / (CGFloat)375;
self.isPlayOfB = YES;
CGFloat top = (kNavigationHeight + 15);
XPRoomCandyGiftView *candyTreeView = [[XPRoomCandyGiftView alloc] initWithFrame:CGRectMake(KScreenWidth, top, KScreenWidth , KScreenWidth * kscale)];
candyTreeView.isMaxLargeGift = attatchment.second == Custom_Message_Sub_Look_Love_InRoom_NeedAllMicSend;
candyTreeView.candyInfo = attatchment.data;
[self.middleContainer addSubview:candyTreeView];
POPSpringAnimation *springAnimation = [POPSpringAnimation animationWithPropertyNamed:kPOPViewCenter];
springAnimation.springSpeed = 12;
springAnimation.springBounciness = 10.f;
springAnimation.fromValue = [NSValue valueWithCGPoint:candyTreeView.center];
springAnimation.toValue = [NSValue valueWithCGPoint:CGPointMake(candyTreeView.frame.size.width / 2, candyTreeView.center.y)];
@kWeakify(self);
[springAnimation setCompletionBlock:^(POPAnimation *anim, BOOL finished) {
@kStrongify(self);
if (finished) {
POPBasicAnimation *moveAnimation = [POPBasicAnimation animationWithPropertyNamed:kPOPViewCenter];
moveAnimation.fromValue = [NSValue valueWithCGPoint:CGPointMake(0, candyTreeView.center.y)];
moveAnimation.toValue = [NSValue valueWithCGPoint:CGPointMake(-KScreenWidth/2, candyTreeView.center.y)];
moveAnimation.beginTime = CACurrentMediaTime() + 3;
moveAnimation.duration = 0.5;
moveAnimation.repeatCount = 1;
moveAnimation.removedOnCompletion = YES;
@kWeakify(self);
[moveAnimation setCompletionBlock:^(POPAnimation *anim, BOOL finished) {
@kStrongify(self);
if (finished) {
[candyTreeView removeFromSuperview];
self.isPlayOfB = NO;
if (self.animationListB.count > 0) {
[self.animationListB xpSafeRemoveObjectAtIndex:0];
2025-01-16 16:00:12 +08:00
}
[self playAnimationWithModel];
}
}];
[candyTreeView pop_addAnimation:moveAnimation forKey:@"moveOutAnimation"];
}
}];
[candyTreeView pop_addAnimation:springAnimation forKey:@"candyTreespingOutAnimation"];
}
- (void)receiveNobleLevelUp:(AttachmentModel *)attachment {
@kWeakify(self);
[[NetImageView new]loadImageWithUrl:attachment.data[@"avatar"] completion:^(UIImage * _Nonnull image, NSURL * _Nonnull url) {
@kStrongify(self);
PIBaseAnimationViewModel *nobleModel = [PIBaseAnimationViewModel new];
nobleModel.data = attachment.data;
nobleModel.type = GiftBannerType_Nobleman;
if (self.animationListB.count == 0 && self.isPlayOfB == NO) {
[self createNobleLevelUpBannerAnimation:nobleModel];
}
[self.animationListB addObject:nobleModel];
}];
}
- (void)createNobleLevelUpBannerAnimation:(PIBaseAnimationViewModel *)model {
self.isPlayOfB = YES;
CGFloat top = (kNavigationHeight + 15);
XPRoomNobleLevelUpView *nobleLevelUpView = [[XPRoomNobleLevelUpView alloc] initWithFrame:CGRectMake(KScreenWidth, top, KScreenWidth, 90)];
nobleLevelUpView.nobleInfo = model.data;
[self.topContainer addSubview:nobleLevelUpView];
@kWeakify(self);
@kWeakify(nobleLevelUpView);
nobleLevelUpView.completionBlock = ^{
@kStrongify(self);
@kStrongify(nobleLevelUpView);
POPSpringAnimation *springAnimation = [POPSpringAnimation animationWithPropertyNamed:kPOPViewCenter];
springAnimation.springSpeed = 12;
springAnimation.springBounciness = 10.f;
springAnimation.fromValue = [NSValue valueWithCGPoint:nobleLevelUpView.center];
springAnimation.toValue = [NSValue valueWithCGPoint:CGPointMake(nobleLevelUpView.frame.size.width / 2, nobleLevelUpView.center.y)];
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(6.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
POPBasicAnimation *moveAnimation = [POPBasicAnimation animationWithPropertyNamed:kPOPViewCenter];
moveAnimation.fromValue = [NSValue valueWithCGPoint:CGPointMake(0, nobleLevelUpView.center.y)];
moveAnimation.toValue = [NSValue valueWithCGPoint:CGPointMake(-KScreenWidth/2, nobleLevelUpView.center.y)];
moveAnimation.beginTime = CACurrentMediaTime() + 3;
moveAnimation.duration = 0.5;
moveAnimation.repeatCount = 1;
moveAnimation.removedOnCompletion = YES;
@kWeakify(self);
[moveAnimation setCompletionBlock:^(POPAnimation *anim, BOOL finished) {
@kStrongify(self);
if (finished) {
self.isPlayOfB = NO;
[nobleLevelUpView removeFromSuperview];
if (self.animationListB.count > 0) {
[self.animationListB xpSafeRemoveObjectAtIndex:0];
2025-01-16 16:00:12 +08:00
}
[self playAnimationWithModel];
}
}];
[nobleLevelUpView pop_addAnimation:moveAnimation forKey:@"moveOutAnimation"];
});
[nobleLevelUpView pop_addAnimation:springAnimation forKey:@"nobleLevelUpspingOutAnimation"];
};
}
- (void)createAnchorHourRankAnimation:(PIBaseAnimationViewModel *)attachment {
self.isPlayOfB = YES;
CGFloat top = (kNavigationHeight + 15);
XPRoomAnchorRankBannerView *anchorRankView = [[XPRoomAnchorRankBannerView alloc] initWithFrame:CGRectMake(KScreenWidth,top, KScreenWidth, kGetScaleWidth(55))];
anchorRankView.anchorRankInfo = [RoomHalfHourRankModel modelWithDictionary:attachment.data];
anchorRankView.delegate = self;
UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(gotoTopRankAnchorRoom:)];
[anchorRankView addGestureRecognizer:tap];
[self.topContainer addSubview:anchorRankView];
POPSpringAnimation *springAnimation = [POPSpringAnimation animationWithPropertyNamed:kPOPViewCenter];
springAnimation.springSpeed = 12;
springAnimation.springBounciness = 10.f;
springAnimation.fromValue = [NSValue valueWithCGPoint:anchorRankView.center];
springAnimation.toValue = [NSValue valueWithCGPoint:CGPointMake(anchorRankView.frame.size.width / 2, anchorRankView.center.y)];
[springAnimation setCompletionBlock:^(POPAnimation *anim, BOOL finished) {
if (finished) {
POPBasicAnimation *moveAnimation = [POPBasicAnimation animationWithPropertyNamed:kPOPViewCenter];
moveAnimation.fromValue = [NSValue valueWithCGPoint:CGPointMake(0, anchorRankView.center.y)];
moveAnimation.toValue = [NSValue valueWithCGPoint:CGPointMake(-KScreenWidth/2, anchorRankView.center.y)];
moveAnimation.beginTime = CACurrentMediaTime() + 3;
moveAnimation.duration = 0.5;
moveAnimation.repeatCount = 1;
moveAnimation.removedOnCompletion = YES;
[moveAnimation setCompletionBlock:^(POPAnimation *anim, BOOL finished) {
[anchorRankView removeFromSuperview];
self.isPlayOfB = NO;
if(self.animationListB.count > 0){
[self.animationListB xpSafeRemoveObjectAtIndex:0];
2025-01-16 16:00:12 +08:00
[self playAnimationWithModel];
}
}];
[anchorRankView pop_addAnimation:moveAnimation forKey:@"moveOutAnimation"];
}
}];
[anchorRankView pop_addAnimation:springAnimation forKey:@"nobleLevelUpspingOutAnimation"];
}
- (void)gotoTopRankAnchorRoom:(UITapGestureRecognizer *)tap {
XPRoomAnchorRankBannerView * view = (XPRoomAnchorRankBannerView *)tap.view;
if (view.anchorRankInfo.uid.integerValue > 0) {
[self.hostDelegate exitRoom];
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
[XPRoomViewController openRoom:view.anchorRankInfo.uid viewController:[XCCurrentVCStackManager shareManager].getCurrentVC];
});
}
}
- (void)receiveTreasureFairyGiftHighLevel:(AttachmentModel *)attatchment {
if ([self _isInSudGame]) {return;}
PIBaseAnimationViewModel *giftModel = [PIBaseAnimationViewModel new];
giftModel.data = attatchment.data;
giftModel.second = attatchment.second;
giftModel.first = attatchment.first;
giftModel.type = GiftBannerType_Fairy;
if (self.animationListB.count == 0 && self.isPlayOfB == NO) {
[self createTreasureFairyBannerAnimation:giftModel];
}
[self.animationListB addObject:giftModel];
}
- (void)createTreasureFairyBannerAnimation:(PIBaseAnimationViewModel *)attatchment {
self.isPlayOfB = YES;
CGFloat kscale = (CGFloat)60 / (CGFloat)375;
CGFloat top = (kNavigationHeight + 15);
XPTreasureFairyGiftView *treasureView = [[XPTreasureFairyGiftView alloc] initWithFrame:CGRectMake(KScreenWidth, top, KScreenWidth , KScreenWidth * kscale)];
//
if ((attatchment.second == Custom_Message_Sub_Treasure_Fairy_Draw_Gift_L5) || (attatchment.second == Custom_Message_Sub_Treasure_Fairy_Convert_L3)) {
treasureView.isMaxLargeGift = YES;
}else{
treasureView.isMaxLargeGift = NO;
}
if ((attatchment.second == Custom_Message_Sub_Treasure_Fairy_Draw_Gift_L4) || (attatchment.second == Custom_Message_Sub_Treasure_Fairy_Draw_Gift_L5)) {
treasureView.isDrawGift = YES; //
}else{
treasureView.isDrawGift = NO; //
}
treasureView.treasureInfo = attatchment.data;
[self.middleContainer addSubview:treasureView];
POPSpringAnimation *springAnimation = [POPSpringAnimation animationWithPropertyNamed:kPOPViewCenter];
springAnimation.springSpeed = 12;
springAnimation.springBounciness = 10.f;
springAnimation.fromValue = [NSValue valueWithCGPoint:treasureView.center];
springAnimation.toValue = [NSValue valueWithCGPoint:CGPointMake(treasureView.frame.size.width / 2, treasureView.center.y)];
[springAnimation setCompletionBlock:^(POPAnimation *anim, BOOL finished) {
if (finished) {
POPBasicAnimation *moveAnimation = [POPBasicAnimation animationWithPropertyNamed:kPOPViewCenter];
moveAnimation.fromValue = [NSValue valueWithCGPoint:CGPointMake(0, treasureView.center.y)];
moveAnimation.toValue = [NSValue valueWithCGPoint:CGPointMake(-KScreenWidth/2, treasureView.center.y)];
moveAnimation.beginTime = CACurrentMediaTime() + 3;
moveAnimation.duration = 0.5;
moveAnimation.repeatCount = 1;
moveAnimation.removedOnCompletion = YES;
@kWeakify(self);
[moveAnimation setCompletionBlock:^(POPAnimation *anim, BOOL finished) {
@kStrongify(self);
if (finished) {
[treasureView removeFromSuperview];
self.isPlayOfB = NO;
if (self.animationListB.count > 0) {
[self.animationListB xpSafeRemoveObjectAtIndex:0];
2025-01-16 16:00:12 +08:00
}
[self playAnimationWithModel];
}
}];
[treasureView pop_addAnimation:moveAnimation forKey:@"moveOutAnimation"];
}
}];
[treasureView pop_addAnimation:springAnimation forKey:@"candyTreespingOutAnimation"];
}
2025-01-16 16:00:12 +08:00
- (void)createGiftCompoundBannerAnimation:(PIBaseAnimationViewModel *)attachment {
self.isPlayOfB = YES;
XPRoomGiftCompoundView *compoundGiftView = [[XPRoomGiftCompoundView alloc] initWithFrame:CGRectMake(KScreenWidth, kNavigationHeight + 15, KScreenWidth, 45)];
compoundGiftView.compoundGiftInfo = attachment.data;
[self.middleContainer addSubview:compoundGiftView];
POPSpringAnimation *springAnimation = [POPSpringAnimation animationWithPropertyNamed:kPOPViewCenter];
springAnimation.springSpeed = 12;
springAnimation.springBounciness = 10.f;
springAnimation.fromValue = [NSValue valueWithCGPoint:compoundGiftView.center];
springAnimation.toValue = [NSValue valueWithCGPoint:CGPointMake(compoundGiftView.frame.size.width / 2, compoundGiftView.center.y)];
[springAnimation setCompletionBlock:^(POPAnimation *anim, BOOL finished) {
if (finished) {
POPBasicAnimation *moveAnimation = [POPBasicAnimation animationWithPropertyNamed:kPOPViewCenter];
moveAnimation.fromValue = [NSValue valueWithCGPoint:CGPointMake(0, compoundGiftView.center.y)];
moveAnimation.toValue = [NSValue valueWithCGPoint:CGPointMake(-KScreenWidth/2, compoundGiftView.center.y)];
moveAnimation.beginTime = CACurrentMediaTime() + 3;
moveAnimation.duration = 0.5;
moveAnimation.repeatCount = 1;
moveAnimation.removedOnCompletion = YES;
@kWeakify(self);
[moveAnimation setCompletionBlock:^(POPAnimation *anim, BOOL finished) {
@kStrongify(self);
if (finished) {
[compoundGiftView removeFromSuperview];
self.isPlayOfB = NO;
if(self.animationListB.count > 0){
[self.animationListB xpSafeRemoveObjectAtIndex:0];
2025-01-16 16:00:12 +08:00
}
[self playAnimationWithModel];
}
}];
[compoundGiftView pop_addAnimation:moveAnimation forKey:@"moveOutAnimation"];
}
}];
[compoundGiftView pop_addAnimation:springAnimation forKey:@"compoundGiftSpingOutAnimation"];
}
- (void)createGeneralFloatingScreenAnimation:(PIBaseAnimationViewModel *)attachment bannerModel:(PIUniversalBannerModel *)model {
self.isPlayOfB = YES;
CGFloat top = (kNavigationHeight + 15);
if (!model) {
model = [PIUniversalBannerModel modelWithDictionary:attachment.data];
}
BOOL isSvga = [model.resourceType.uppercaseString isEqualToString:@"SVGA"];
__block PIUniversalBannerView *bannerView;
@kWeakify(self);
if (isSvga == YES) {
SVGAParser *parser = [SVGAParser new];
[parser parseWithURL:[NSURL URLWithString:model.resourceContent] completionBlock:^(SVGAVideoEntity * _Nonnull videoItem) {
@kStrongify(self);
model.videoItem = videoItem;
CGFloat height = kGetScaleWidth(60);
if(videoItem.videoSize.width > 0){
height = KScreenWidth * videoItem.videoSize.height / videoItem.videoSize.width;
}
bannerView = [[PIUniversalBannerView alloc]initWithFrame:CGRectMake(KScreenWidth, top, KScreenWidth, height)];
[self showGeneralFloatingScreenView:bannerView model:model];
} failureBlock:^(NSError * _Nonnull error) {
@kStrongify(self);
[bannerView removeFromSuperview];
self.isPlayOfB = NO;
if(self.animationListB.count > 0){
[self.animationListB xpSafeRemoveObjectAtIndex:0];
2025-01-16 16:00:12 +08:00
}
[self playAnimationWithModel];
}];
}else{
if (!_imageLoader) {
_imageLoader = [[NetImageView alloc] init];
}
[self.imageLoader loadImageWithUrl:model.resourceContent
completion:^(UIImage * _Nonnull image, NSURL * _Nonnull url) {
@kStrongify(self);
model.image = image;
CGFloat width = image.size.width <= 0 ? kGetScaleWidth(60) : image.size.width;
CGFloat height = image.size.height ;
CGFloat getHeight = KScreenWidth * height / width;
if (getHeight > 100) {
getHeight = 100;
}
bannerView = [[PIUniversalBannerView alloc]initWithFrame:CGRectMake(KScreenWidth, top, KScreenWidth, getHeight) ];
[self showGeneralFloatingScreenView:bannerView model:model];
}
fail:^(NSError * _Nonnull error) {
@kStrongify(self);
[bannerView removeFromSuperview];
self.isPlayOfB = NO;
if(self.animationListB.count > 0){
[self.animationListB xpSafeRemoveObjectAtIndex:0];
2025-01-16 16:00:12 +08:00
}
[self playAnimationWithModel];
}];
}
}
-(void)showGeneralFloatingScreenView:(PIUniversalBannerView *)bannerView model:(PIUniversalBannerModel *)model{
BOOL isSvga = [model.resourceType isEqualToString:@"SVGA"];
bannerView.isSvga = isSvga;
bannerView.delegate = self;
2025-03-24 16:09:48 +08:00
if (!_universalBannerViewCaches) {
_universalBannerViewCaches = @[].mutableCopy;
}
[self.universalBannerViewCaches addObject:bannerView];
2025-02-28 19:04:09 +08:00
@kWeakify(bannerView);
2025-01-16 16:00:12 +08:00
@kWeakify(self);
2025-02-28 19:04:09 +08:00
[bannerView setAllowToPlay:^{
@kStrongify(self);
@kStrongify(bannerView);
[self.topContainer addSubview:bannerView];
POPSpringAnimation *springAnimation = [POPSpringAnimation animationWithPropertyNamed:kPOPViewCenter];
springAnimation.springSpeed = 12;
springAnimation.springBounciness = 10.f;
springAnimation.fromValue = [NSValue valueWithCGPoint:bannerView.center];
springAnimation.toValue = [NSValue valueWithCGPoint:CGPointMake(bannerView.frame.size.width / 2, bannerView.center.y)];
@kWeakify(self);
[springAnimation setCompletionBlock:^(POPAnimation *anim, BOOL finished) {
if (finished) {
POPBasicAnimation *moveAnimation = [POPBasicAnimation animationWithPropertyNamed:kPOPViewCenter];
moveAnimation.fromValue = [NSValue valueWithCGPoint:CGPointMake(0, bannerView.center.y)];
moveAnimation.toValue = [NSValue valueWithCGPoint:CGPointMake(-KScreenWidth/2, bannerView.center.y)];
moveAnimation.beginTime = CACurrentMediaTime() + 5;
moveAnimation.duration = 0.5;
moveAnimation.repeatCount = 1;
moveAnimation.removedOnCompletion = YES;
[moveAnimation setCompletionBlock:^(POPAnimation *anim, BOOL finished) {
@kStrongify(self);
if (finished) {
[bannerView removeFromSuperview];
2025-03-24 16:09:48 +08:00
[self.universalBannerViewCaches removeObject:bannerView];
2025-02-28 19:04:09 +08:00
self.isPlayOfB = NO;
if(self.animationListB.count > 0){
[self.animationListB xpSafeRemoveObjectAtIndex:0];
2025-02-28 19:04:09 +08:00
}
[self playAnimationWithModel];
2025-01-16 16:00:12 +08:00
}
2025-02-28 19:04:09 +08:00
}];
[bannerView pop_addAnimation:moveAnimation forKey:@"moveOutAnimation"];
}
}];
[bannerView pop_addAnimation:springAnimation forKey:@"starKitchenOutAnimation"];
2025-01-16 16:00:12 +08:00
}];
2025-02-28 19:04:09 +08:00
bannerView.model = model;
2025-01-16 16:00:12 +08:00
}
- (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.hostDelegate animationPointAtStageViewByUid:uid];
datingModel.targetPoint = [self.hostDelegate animationPointAtStageViewByUid:targetUid];
}
XPRoomDatingAnimationView *datingView = [[XPRoomDatingAnimationView alloc] init];
[self.topContainer addSubview:datingView];
[datingView startAnimationWithModel:datingModel finishBlock:^(BOOL finish) {
[datingView removeFromSuperview];
[self.datingEffectQueue removeObject:datingModel];
if (self.datingEffectQueue.count > 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.hostDelegate.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;
}
- (void)acrossRoomPKBannerAnimation:(AttachmentModel *)attacment {
AcrossRoomPKPrizeModel * prizeModel = [AcrossRoomPKPrizeModel modelWithJSON:attacment.data];
if (attacment.second == Custom_Message_Sub_AnchorPK_Result) {
prizeModel.pkType = 1;
} else {
prizeModel.pkType = 0;
}
[self.acrossRoomPKQueue addObject:prizeModel];
if (self.acrossRoomPKQueue.count == 1 ) {//1
[self startAcrossRoomPKAnimation:self.acrossRoomPKQueue.firstObject];
}
}
- (void)startAcrossRoomPKAnimation:(AcrossRoomPKPrizeModel *)model {
XPAcrossRoomPKPrizeView *wishEffectView = [[XPAcrossRoomPKPrizeView alloc] initWithFrame:CGRectMake(KScreenWidth, kNavigationHeight+40, KScreenWidth, 87)];
wishEffectView.data = model;
UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(gotoPkWinRoom:)];
[wishEffectView addGestureRecognizer:tap];
[self.topContainer addSubview:wishEffectView];
[UIView animateWithDuration:0.5 animations:^{
wishEffectView.frame = CGRectMake(0, kNavigationHeight+40, KScreenWidth, 87);
} 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:^{
wishEffectView.hidden = YES;
} completion:^(BOOL finished) {
[wishEffectView removeFromSuperview];
[self.acrossRoomPKQueue removeObject:model];
if (self.acrossRoomPKQueue.count > 0) {
[self startAcrossRoomPKAnimation:self.acrossRoomPKQueue.firstObject];
}
}];
});
}];
}
- (void)gotoPkWinRoom:(UITapGestureRecognizer *)tap {
XPAcrossRoomPKPrizeView * view = (XPAcrossRoomPKPrizeView *)tap.view;
if (view.data.winUid.length > 0) {
[self.hostDelegate exitRoom];
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
[XPRoomViewController openRoom:view.data.winUid viewController:[XCCurrentVCStackManager shareManager].getCurrentVC];
});
}
}
- (void)receiveFansTeamGiftHandleSendGiftAnimation:(AttachmentModel *)attachment {
if ([self _isInSudGame]) {return;}
if (!self.hostDelegate.getRoomInfo.hasAnimationEffect) {return;}
GiftReceiveInfoModel *receiveInfo = [[GiftReceiveInfoModel alloc] init];
GiftInfoModel *gift = [GiftInfoModel modelWithJSON:attachment.data[@"giftVo"]];
receiveInfo.gift = gift;
receiveInfo.giftInfo = gift;
receiveInfo.targetUid = [NSString stringWithFormat:@"%ld", self.hostDelegate.getRoomInfo.uid];
GiftInfoModel * giftInfo = receiveInfo.gift ? receiveInfo.gift : receiveInfo.giftInfo;
if (attachment.second == Custom_Message_Sub_AllMicroLuckySend || attachment.second == Custom_Message_Sub_AllBatchMicroLuckySend || attachment.second == Custom_Message_Sub_Gift_LuckySend) {
NSString * giftId = [NSString stringWithFormat:@"%ld", receiveInfo.luckyGiftList.giftList.firstObject.giftId];
2025-03-06 15:26:44 +08:00
giftInfo = [[XPGiftStorage shareStorage] findGiftInfo:giftId inRoom:@(receiveInfo.roomUid).stringValue];
2025-01-16 16:00:12 +08:00
}
if (giftInfo == nil) {
2025-03-06 15:26:44 +08:00
giftInfo = [[XPGiftStorage shareStorage] findGiftInfo:receiveInfo.giftId inRoom:@(receiveInfo.roomUid).stringValue];
2025-01-16 16:00:12 +08:00
}
/// 使
receiveInfo.gift = giftInfo;
receiveInfo.isLuckyBagGift = (attachment.second == Custom_Message_Sub_AllMicroLuckySend || attachment.second == Custom_Message_Sub_AllBatchMicroLuckySend || attachment.second == Custom_Message_Sub_Gift_LuckySend);
[self.giftAnimationManager enqueueGift:receiveInfo];
}
- (void)receiveAnchorHourRank:(AttachmentModel *)attachment {
PIBaseAnimationViewModel *anchorModel =[PIBaseAnimationViewModel new];
anchorModel.data = attachment.data;
anchorModel.type = GiftBannerType_AnchorHour;
if(self.animationListB.count == 0 && self.isPlayOfB == NO){
[self createAnchorHourRankAnimation:anchorModel];
}
[self.animationListB addObject:anchorModel];
}
- (void)receiveGiftCompound:(AttachmentModel *)attachment {
if ([self _isInSudGame]) {return;}
PIBaseAnimationViewModel *magicModel =[PIBaseAnimationViewModel new];
magicModel.data = attachment.data;
magicModel.type = GiftBannerType_Magic_House;
if(self.animationListB.count == 0 && self.isPlayOfB == NO){
[self createGiftCompoundBannerAnimation:magicModel];
}
[self.animationListB addObject:magicModel];
}
- (void)receiveRoomSailing:(AttachmentModel *)attachment {
if ([self _isInSudGame]) {return;}
if (self.sailingQueue.count == 0) {
[self createSailingBannerAnimation:attachment];
}
[self.sailingQueue addObject:attachment];
}
- (void)createSailingBannerAnimation:(AttachmentModel *)attatchment {
CGFloat kscale = (CGFloat)60 / (CGFloat)375;
XPSailingAnimationView *sailingView = [[XPSailingAnimationView alloc] initWithFrame:CGRectMake(KScreenWidth, kNavigationHeight + 15, KScreenWidth, KScreenWidth * kscale)];
sailingView.prizeInfo = attatchment.data;
[self.middleContainer addSubview:sailingView];
POPSpringAnimation *springAnimation = [POPSpringAnimation animationWithPropertyNamed:kPOPViewCenter];
springAnimation.springSpeed = 12;
springAnimation.springBounciness = 10.f;
springAnimation.fromValue = [NSValue valueWithCGPoint:sailingView.center];
springAnimation.toValue = [NSValue valueWithCGPoint:CGPointMake(sailingView.frame.size.width / 2, sailingView.center.y)];
[springAnimation setCompletionBlock:^(POPAnimation *anim, BOOL finished) {
if (finished) {
POPBasicAnimation *moveAnimation = [POPBasicAnimation animationWithPropertyNamed:kPOPViewCenter];
moveAnimation.fromValue = [NSValue valueWithCGPoint:CGPointMake(0, sailingView.center.y)];
moveAnimation.toValue = [NSValue valueWithCGPoint:CGPointMake(-KScreenWidth/2, sailingView.center.y)];
moveAnimation.beginTime = CACurrentMediaTime() + 3;
moveAnimation.duration = 0.5;
moveAnimation.repeatCount = 1;
moveAnimation.removedOnCompletion = YES;
@kWeakify(self);
[moveAnimation setCompletionBlock:^(POPAnimation *anim, BOOL finished) {
@kStrongify(self);
if (finished) {
[sailingView removeFromSuperview];
if (self.sailingQueue.count > 0) {
[self.sailingQueue xpSafeRemoveObjectAtIndex:0];
2025-01-16 16:00:12 +08:00
}
if (self.sailingQueue.count > 0) {
[self createSailingBannerAnimation:self.sailingQueue.firstObject];
}
}
}];
[sailingView pop_addAnimation:moveAnimation forKey:@"moveOutAnimation"];
}
}];
[sailingView pop_addAnimation:springAnimation forKey:@"candyTreespingOutAnimation"];
}
- (void)receiveRoomGraffitiGift:(AttachmentModel *)attachment {
if (self.graffitiGiftQueue.count == 0) {
[self startGraffitiGiftAnimation:attachment];
}
[self.graffitiGiftQueue addObject:attachment];
}
- (void)startGraffitiGiftAnimation:(AttachmentModel *)model {
NSDictionary * dic = model.data;
NSNumber * giftId = dic[@"giftId"];
2025-03-06 15:26:44 +08:00
GiftInfoModel * giftInfo = [[XPGiftStorage shareStorage] findGiftInfo:giftId.stringValue inRoom:@""];
2025-01-16 16:00:12 +08:00
NSArray * array = dic[@"drawFixedArray"];
if (giftInfo.giftUrl.length > 0 && array.count > 0) {
[[SDWebImageManager sharedManager] loadImageWithURL:[NSURL URLWithString:giftInfo.giftUrl] options:SDWebImageProgressiveLoad progress:nil completed:^(UIImage * _Nullable image, NSData * _Nullable data, NSError * _Nullable error, SDImageCacheType cacheType, BOOL finished, NSURL * _Nullable imageURL) {
if (error == nil && image) {
XPRoomGraffitiGiftAnimationView *graffitiView = [[XPRoomGraffitiGiftAnimationView alloc] initWithFrame:CGRectMake(0, 0, KScreenWidth, KScreenHeight)];
graffitiView.giftImage = image;
graffitiView.delegate = self;
graffitiView.model = model;
graffitiView.pointArray = array;
[graffitiView beginDrawAnimation];
[self.topContainer addSubview:graffitiView];
} else {
[self.graffitiGiftQueue removeObject:model];
if (self.graffitiGiftQueue.count > 0) {
[self startGraffitiGiftAnimation:self.graffitiGiftQueue.firstObject];
}
}
}];
} else {
[self.graffitiGiftQueue removeObject:model];
if (self.graffitiGiftQueue.count > 0) {
[self startGraffitiGiftAnimation:self.graffitiGiftQueue.firstObject];
}
}
}
- (void)playLuckyGiftEffectWithVapUrl:(NSString *)vapUrl {
NSString *encodingUrl = [vapUrl pureURLString];
encodingUrl = [encodingUrl stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLQueryAllowedCharacterSet]];
NSString *fileName = [[encodingUrl componentsSeparatedByString:@"/"] lastObject];
NSString *fullPath = [self.GiftDynamicEffectListPath stringByAppendingPathComponent:fileName];
if ([[NSFileManager defaultManager] fileExistsAtPath:fullPath]){
vapUrl = fullPath;
[self _addSubviewToMiddleContainer:self.luckyVapGiftEffectView];
[self.luckyVapGiftEffectView setMute:NO];
[self.luckyVapGiftEffectView playHWDMP4:vapUrl repeatCount:1 delegate:self];
} else {
@kWeakify(self);
[self.vapParser parseWithURL:encodingUrl completionBlock:^(NSString * _Nullable videoUrl) {
@kStrongify(self);
if (videoUrl.length) {
[self _addSubviewToMiddleContainer:self.luckyVapGiftEffectView];
[self.luckyVapGiftEffectView setMute:NO];
[self.luckyVapGiftEffectView playHWDMP4:videoUrl repeatCount:1 delegate:self];
}
} failureBlock:^(NSError * _Nullable error) {
self.luckyVapGiftEffectView.hidden = YES;
}];
}
}
-(void)playAnimationWithModel{
if(self.animationListB.count <= 0){
return;
}
if(self.isPlayOfB == YES) {
return;
}
PIBaseAnimationViewModel *model = self.animationListB.firstObject;
switch (model.type) {
case GiftBannerType_Lucky:
[self createBigPrizeAnimation:model];
break;
case GiftBannerType_Love:
[self createCandyTreeBannerAnimation:model];
break;
case GiftBannerType_Nobleman:
[self createNobleLevelUpBannerAnimation:model];
break;
case GiftBannerType_AnchorHour:
[self createAnchorHourRankAnimation:model];
break;
case GiftBannerType_LicneseHour:
[self createAnchorHourRankAnimation:model];
break;
case GiftBannerType_Fairy:
[self createTreasureFairyBannerAnimation:model];
break;
case GiftBannerType_Magic_House:
[self createGiftCompoundBannerAnimation:model];
break;
case GiftBannerType_General_Floating_Screen:
[self createGeneralFloatingScreenAnimation:model bannerModel:nil];
break;
default:
//
// GiftBannerType_Unknown, GiftBannerType_Normal,
// GiftBannerType_Special, GiftBannerType_Event
break;
2025-01-16 16:00:12 +08:00
}
}
- (SVGAImageView *)luckyGiftEffectView {
if (!_luckyGiftEffectView) {
_luckyGiftEffectView = [[SVGAImageView alloc]init];
_luckyGiftEffectView.backgroundColor = [UIColor colorWithWhite:0 alpha:0.5];
_luckyGiftEffectView.userInteractionEnabled = NO;
_luckyGiftEffectView.delegate = self;
_luckyGiftEffectView.hidden = YES;
}
return _luckyGiftEffectView;
}
- (VAPView *)luckyVapGiftEffectView {
if (!_luckyVapGiftEffectView) {
_luckyVapGiftEffectView = [[VAPView alloc] initWithFrame:CGRectMake(0, 0, KScreenWidth, KScreenHeight)];
_luckyVapGiftEffectView.backgroundColor = [UIColor colorWithWhite:0 alpha:0.5];
_luckyVapGiftEffectView.contentMode = UIViewContentModeScaleAspectFill;
_luckyVapGiftEffectView.hidden = YES;
}
return _luckyVapGiftEffectView;
}
#pragma mark - Old Methods Delegate: XPRoomGiftBroadcastViewDelegate
- (void)xPRoomGiftBroadcastView:(XPRoomGiftBroadcastView *)view enterRoom:(NSString *)roomUid roomName:(NSString *)roomName{
id isShowBroadcastView = [[NSUserDefaults standardUserDefaults]valueForKey:@"kSaveBrooadcastSelectState"];
if(isShowBroadcastView == nil){
PIRoomGiftBroadcastWindow *broadcastView = [[PIRoomGiftBroadcastWindow alloc] initWithFrame:CGRectMake(0, 0, KScreenWidth, KScreenHeight)];
broadcastView.roodUid = roomUid;
broadcastView.roomName = roomName;
broadcastView.delegate = self;
[kWindow addSubview:broadcastView];
return;
}
if (roomUid.length > 0 && self.hostDelegate.getRoomInfo.uid != roomUid.integerValue) {
[self.hostDelegate exitRoom];
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.7 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
[XPRoomViewController openRoom:roomUid viewController:[XCCurrentVCStackManager shareManager].getCurrentVC];
});
}
}
- (void)xPRoomLuckyBigPrizeView:(XPRoomLuckyBigPrizeView *)view luckyGiftInfo:(PIBaseAnimationViewModel *)giftInfo {
id isShowBroadcastView = [[NSUserDefaults standardUserDefaults]valueForKey:@"kSaveLuckSelectState"];
if(isShowBroadcastView == nil){
PIRoomGiftBroadcastWindow *broadcastView = [[PIRoomGiftBroadcastWindow alloc] initWithFrame:CGRectMake(0, 0, KScreenWidth, KScreenHeight)];
broadcastView.isLuck = YES;
broadcastView.roodUid = giftInfo.roomUid;
broadcastView.roomName = giftInfo.roomTitle;
broadcastView.delegate = self;
[kWindow addSubview:broadcastView];
return;
}
if (!giftInfo.isInRoomVisable && giftInfo.roomUid.length > 0 && giftInfo.roomUid.integerValue != self.hostDelegate.getRoomInfo.uid) {
[self.hostDelegate 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];
});
}
}
2025-01-16 16:00:12 +08:00
- (void)xPRoomAnchorRankBannerView:(XPRoomAnchorRankBannerView *)view rankInfo:(RoomHalfHourRankModel *)rankInfo{
if (rankInfo.uid.integerValue > 0 && self.hostDelegate.getRoomInfo.uid != rankInfo.uid.integerValue) {
[self.hostDelegate exitRoom];
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
[XPRoomViewController openRoom:rankInfo.uid viewController:[XCCurrentVCStackManager shareManager].getCurrentVC];
});
}
}
-(void)confirmLeaveForTheRoom:(NSString *_Nonnull)roomUid{
if (roomUid.length > 0 && self.hostDelegate.getRoomInfo.uid != roomUid.integerValue) {
[self.hostDelegate exitRoom];
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.7 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
[XPRoomViewController openRoom:roomUid viewController:[XCCurrentVCStackManager shareManager].getCurrentVC];
});
}
}
- (void)pIUniversalBannerView:(PIUniversalBannerView *)view didClick:(PIUniversalBannerModel *)model{
if (model.skipType == 2){
[self.hostDelegate exitRoom];
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
[XPRoomViewController openRoom:model.skipContent viewController:[XCCurrentVCStackManager shareManager].getCurrentVC];
});
}else if (model.skipType == 3){
XPWebViewController * webVC = [[XPWebViewController alloc] initWithRoomUID:nil];
webVC.isPush = YES;
webVC.url = model.skipContent;
[self.hostDelegate.getCurrentNav pushViewController:webVC animated:YES];
}
}
- (void)xPRoomGraffitiGiftAnimationViewCompletion:(XPRoomGraffitiGiftAnimationView *)view attachment:(nonnull AttachmentModel *)attachment{
[view removeFromSuperview];
if ([self.graffitiGiftQueue containsObject:attachment]) {
[self.graffitiGiftQueue removeObject:attachment];
}
if (self.graffitiGiftQueue.count > 0) {
[self startGraffitiGiftAnimation:self.graffitiGiftQueue.firstObject];
}
}
#pragma mark - Touch Event Handling
// pointInside
#pragma mark - Public Methods
- (CGPoint)getSavedTapPoint {
return self.savedTapPoint;
}
- (BOOL)hasSavedTapPointAvailable {
return self.hasSavedTapPoint;
}
- (void)clearSavedTapPoint {
self.hasSavedTapPoint = NO;
self.savedTapPoint = CGPointZero;
}
- (CGRect)calculateInteractiveBoundsForView:(UIView *)view {
//
// Banner
CGRect bounds = view.bounds;
// Banner
//
if ([view isKindOfClass:[PIUniversalBannerView class]]) {
//
// 使
return bounds;
}
// 使
return bounds;
}
#pragma mark - Cleanup Methods
- (void)cleanupGestureRecognizers {
NSLog(@"🔄 清理手势识别器");
//
if (self.bannerSwipeGestureContainer) {
for (UIGestureRecognizer *gesture in self.bannerSwipeGestureContainer.gestureRecognizers.copy) {
[self.bannerSwipeGestureContainer removeGestureRecognizer:gesture];
}
}
//
if (self.bannerLeftTapGestureContainer) {
for (UIGestureRecognizer *gesture in self.bannerLeftTapGestureContainer.gestureRecognizers.copy) {
[self.bannerLeftTapGestureContainer removeGestureRecognizer:gesture];
}
}
//
if (self.bannerRightTapGestureContainer) {
for (UIGestureRecognizer *gesture in self.bannerRightTapGestureContainer.gestureRecognizers.copy) {
[self.bannerRightTapGestureContainer removeGestureRecognizer:gesture];
}
}
NSLog(@"🔄 手势识别器清理完成");
}
- (void)cleanupCacheManagers {
NSLog(@"🔄 清理缓存管理器");
// BannerScheduler
[self cleanupBannerScheduler];
//
TouchAreaCacheManager *touchCacheManager = [TouchAreaCacheManager sharedManager];
[touchCacheManager clearCache];
//
GestureOptimizer *gestureOptimizer = [GestureOptimizer sharedOptimizer];
[gestureOptimizer clearCache];
NSLog(@"🔄 缓存管理器清理完成");
}
- (void)cleanupBannerScheduler {
if (self.bannerScheduler) {
NSLog(@"<22><> 清理 BannerScheduler");
[self.bannerScheduler clearQueue];
[self.bannerScheduler pause];
self.bannerScheduler = nil;
}
}
- (void)removeNotificationObservers {
NSLog(@"🔄 移除通知监听");
//
[[NSNotificationCenter defaultCenter] removeObserver:self name:@"SwipeOutBanner" object:nil];
[[NSNotificationCenter defaultCenter] removeObserver:self name:@"TapBanner" object:nil];
[[NSNotificationCenter defaultCenter] removeObserver:self name:@"BannerTapToFunctionContainer" object:nil];
//
[[NSNotificationCenter defaultCenter] removeObserver:self];
NSLog(@"🔄 通知监听移除完成");
}
#pragma mark - BannerSchedulerDelegate
- (void)bannerScheduler:(BannerScheduler *)scheduler shouldPlayBanner:(id)banner {
NSLog(@"🎯 BannerSchedulerDelegate: 收到播放 Banner 请求");
NSLog(@"🎯 Banner 类型: %@", [banner class]);
// Banner AttachmentModel
if ([banner isKindOfClass:[AttachmentModel class]]) {
AttachmentModel *attachment = (AttachmentModel *)banner;
NSLog(@"🎯 AttachmentModel 类型: %ld", (long)attachment.second);
NSLog(@"🎯 AttachmentModel 数据: %@", attachment.data);
[self _playBannerWithAttachment:attachment];
} else {
NSLog(@"⚠️ BannerSchedulerDelegate: Banner 不是 AttachmentModel 类型");
}
}
- (void)bannerSchedulerDidFinishPlaying:(BannerScheduler *)scheduler {
// Banner
NSLog(@"🔄 BannerScheduler: Banner 播放完成");
}
- (void)bannerScheduler:(BannerScheduler *)scheduler didStartPlayingBanner:(id)banner {
// Banner
NSLog(@"🔄 BannerScheduler: Banner 开始播放 - 类型: %@", [banner class]);
}
#pragma mark - Private Methods
- (void)_playBannerWithAttachment:(AttachmentModel *)attachment {
NSLog(@"🎯 _playBannerWithAttachment: 开始处理 Banner - 类型: %ld", (long)attachment.second);
// bannerbanner
NSMutableArray *viewsToRemove = [NSMutableArray array];
for (UIView *subview in self.bannerContainer.subviews) {
[viewsToRemove addObject:subview];
NSLog(@"🔄 标记移除banner: %@", NSStringFromClass([subview class]));
// Banner
TouchAreaCacheManager *cacheManager = [TouchAreaCacheManager sharedManager];
[cacheManager removeBannerFromCache:subview];
}
for (UIView *view in viewsToRemove) {
[view removeFromSuperview];
}
// Banner
switch (attachment.second) {
case Custom_Message_Sub_General_Floating_Screen_One_Room:
case Custom_Message_Sub_General_Floating_Screen_All_Room:
NSLog(@"🎯 分发到 playGameBanner");
[self playGameBanner:attachment];
break;
case Custom_Message_Sub_Super_Gift_Winning_Coins_ALL_Room:
NSLog(@"🎯 分发到 playLuckyWinningBanner");
[self playLuckyWinningBanner:attachment];
break;
case Custom_Message_Sub_CP_Gift:
NSLog(@"🎯 分发到 playCPGiftBanner");
[self playCPGiftBanner:attachment];
break;
case Custom_Message_Sub_CP_Upgrade:
NSLog(@"🎯 分发到 playCPLevelUp");
[self playCPLevelUp:attachment];
break;
case Custom_Message_Sub_CP_Binding:
NSLog(@"🎯 分发到 playCPBinding");
[self playCPBinding:attachment];
break;
case Custom_Message_Sub_Gift_ChannelNotify:
NSLog(@"🎯 分发到 playRoomGiftBanner");
[self playRoomGiftBanner:attachment];
break;
case Custom_Message_Sub_LuckyPackage:
NSLog(@"🎯 分发到 playLuckyPackageBanner");
[self playLuckyPackageBanner:attachment];
break;
case Custom_Message_Sub_Super_Gift_Banner:
NSLog(@"🎯 分发到 playBroveBanner");
[self playBroveBanner:attachment];
break;
default:
NSLog(@"⚠️ 未知的 Banner 类型: %ld", (long)attachment.second);
//
[self.bannerScheduler markBannerFinished];
break;
}
}
2025-01-14 14:29:14 +08:00
@end