Files
peko-ios/YuMi/Modules/YMRoom/View/Common/BravoGiftBannerView.m

325 lines
12 KiB
Objective-C
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#import "BravoGiftBannerView.h"
#import "UserInfoModel.h"
#import "AttachmentModel.h"
#import <POP.h>
#import <SVGA.h>
#import "XPRoomViewController.h"
#import "XCCurrentVCStackManager.h"
//{"data":"{\"times\":\"1.65\",\"sender\":{\"avatar\":\"https://image.pekolive.com/14a8039a-df7f-4a4b-a6b9-99c6d3f9918e.gif\",\"erbanNo\":6228657,\"gender\":1,\"nick\":\"Molistar\",\"uid\":3224},\"coins\":\"1650.0\",\"giftPic\":\"https://image.pekolive.com/1000.png\",\"giftNameMap\":{\"ar\":\"lucky1000\",\"en\":\"lucky1000\",\"zh\":\"lucky1000\",\"tr\":\"lucky1000\"},\"roomUid\":3224}","first":106,"second":1066}
@interface BravoGiftBannerViewModel : PIBaseModel
@property (nonatomic, assign, readonly) CGFloat times;
@property (nonatomic, assign, readonly) CGFloat coins;
@property (nonatomic, copy, readonly) NSString *giftPic;
@property (nonatomic, copy, readonly) NSDictionary *giftNameMap;
@property (nonatomic, copy) NSNumber *roomUid;
@property (nonatomic, strong, readonly) UserInfoModel *sender;
@end
@implementation BravoGiftBannerViewModel
@end
@interface BravoGiftBannerView ()
@property (nonatomic, strong) BravoGiftBannerViewModel *model;
@property (nonatomic, strong) NetImageView *sendAvatarImageView;
@property (nonatomic, strong) NetImageView *giftImageView;
@property (nonatomic, strong) UILabel *goldNumLabel;
//@property (nonatomic, strong) UIImageView *backgroundImageView;
@property (nonatomic, strong) UIImageView *moneyIconImageView;
@property(nonatomic, strong) SVGAImageView *svgaView;
@property (nonatomic, assign) NSInteger currentRoomUid;
@property (nonatomic, copy) void(^completeDisplay)(void);
@property (nonatomic, copy) void(^exitCurrentRoom)(void);
@property (nonatomic, assign) BOOL isLeaveAnimating;
@end
@implementation BravoGiftBannerView
+ (void)display:(UIView *)superView
inRoomUid:(NSInteger)roomUid
with:(AttachmentModel *)attachment
complete:(void (^)(void))complete
exitCurrentRoom:(void(^)(void))exit {
BravoGiftBannerViewModel *model = [BravoGiftBannerViewModel modelWithDictionary:attachment.data];
CGRect frame = CGRectMake(KScreenWidth, 0, KScreenWidth, kGetScaleWidth(90));
BravoGiftBannerView *banner = [[BravoGiftBannerView alloc] initWithFrame:frame];
banner.model = model;
banner.currentRoomUid = roomUid;
banner.completeDisplay = complete;
banner.exitCurrentRoom = exit;
[superView addSubview:banner];
NSInteger time = 3;
@kWeakify(banner);
[banner popEnterAnimation:^(BOOL finished) {
@kStrongify(banner);
if (finished) {
[banner addNotification];
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(time * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
[banner removeNotification];
[banner popLeaveAnimation:^(bool finished) {
if (banner.completeDisplay) {
banner.completeDisplay();
}
[banner removeFromSuperview];
}];
});
}
}];
}
- (void)handleSwipeNotification {
NSLog(@"🎯 BravoGiftBannerView: 响应 swipe 手势,开始移除动画");
[self dismissBanner];
}
- (void)handleTapNotification:(NSNotification *)note {
NSValue *value = note.userInfo[@"point"];
CGPoint point = [value CGPointValue];
// 计算中央 2/3 区域
CGFloat totalW = KScreenWidth;
CGFloat regionW = totalW * 2.0 / 3.0;
CGFloat originX = (totalW - regionW) / 2.0;
CGRect centerRegion = CGRectMake(originX,
0, // 高度不做限制就填 0
regionW,
self.bounds.size.height);
if (CGRectContainsPoint(centerRegion, point)) {
NSLog(@" Banner tap 点落在中央 2/3 区域");
[self handleTap];
} else {
NSLog(@" Banner tap 点不落在中央 2/3 区域");
// 将 banner 中的点转换为屏幕坐标系
CGPoint screenPoint = [self convertPoint:point toView:nil];
// 发送通知给 FunctionContainer 处理,传递屏幕坐标
[[NSNotificationCenter defaultCenter] postNotificationName:@"BannerTapToFunctionContainer"
object:nil
userInfo:@{@"point": [NSValue valueWithCGPoint:screenPoint]}];
}
}
- (void)addNotification {
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(handleSwipeNotification)
name:@"SwipeOutBanner"
object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(handleTapNotification:)
name:@"TapBanner"
object:nil];
}
- (void)removeNotification {
[[NSNotificationCenter defaultCenter] removeObserver:self];
}
- (void)setModel:(BravoGiftBannerViewModel *)model {
_model = model;
self.sendAvatarImageView.imageUrl = model.sender.avatar;
self.giftImageView.imageUrl = model.giftPic;
self.goldNumLabel.text = [NSString stringByRemovingRedundantZeros:@(model.coins).stringValue];
}
- (void)dismissBanner {
[self pop_removeAllAnimations]; // 停止所有动画
[self popLeaveAnimation:^(bool finished) {
if (self.completeDisplay) {
self.completeDisplay();
}
[self removeFromSuperview];
}];
}
- (void)popEnterAnimation:(void(^)(BOOL finished))finish {
POPSpringAnimation *enterAnimation = [POPSpringAnimation animationWithPropertyNamed:kPOPViewFrame];
enterAnimation.toValue = [NSValue valueWithCGRect:CGRectMake(0, 0, KScreenWidth, kGetScaleWidth(100))];
enterAnimation.springBounciness = 10; // 弹性系数
enterAnimation.springSpeed = 12; // 动画速度
enterAnimation.completionBlock = ^(POPAnimation *anim, BOOL finished) {
if (finish) {
finish(finished);
}
};
[self pop_addAnimation:enterAnimation forKey:@"enterAnimation"];
}
- (void)popLeaveAnimation:(void(^)(bool finished))finish {
if (self.isLeaveAnimating) {
return;
}
self.isLeaveAnimating = YES;
POPBasicAnimation *exitAnimation = [POPBasicAnimation animationWithPropertyNamed:kPOPViewFrame];
exitAnimation.toValue = [NSValue valueWithCGRect:CGRectMake(-KScreenWidth, 0, KScreenWidth, kGetScaleWidth(100))];
exitAnimation.duration = 0.25; // 动画持续时间
exitAnimation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
exitAnimation.completionBlock = ^(POPAnimation *anim, BOOL finished) {
if (finish) {
finish(finished);
}
};
[self pop_addAnimation:exitAnimation forKey:@"exitAnimation"];
}
- (instancetype)initWithFrame:(CGRect)frame {
self = [super initWithFrame:frame];
if (self) {
[self setupUI];
self.userInteractionEnabled = YES;
UIButton *b = [UIButton buttonWithType:UIButtonTypeCustom];
[self addSubview:b];
[b mas_remakeConstraints:^(MASConstraintMaker *make) {
make.edges.mas_equalTo(self);
}];
// [b addTarget:self action:@selector(handleTap) forControlEvents:UIControlEventTouchUpInside];
}
return self;
}
- (void)handleTap {
if (self.model.roomUid.integerValue == self.currentRoomUid) {
return;
}
// 在弹框显示前保存必要数据避免依赖banner对象
NSNumber *targetRoomUid = self.model.roomUid;
void(^exitCurrentRoomBlock)(void) = self.exitCurrentRoom;
@kWeakify(self);
[TTPopup alertWithMessage:YMLocalizedString(@"Combo_10") confirmHandler:^{
@kStrongify(self);
// 检查banner是否还存在
if (!self) {
NSLog(@"⚠️ BravoGiftBannerView: banner已被移除但弹框回调仍在执行");
// 即使banner被移除仍然执行跳转逻辑
if (exitCurrentRoomBlock) {
exitCurrentRoomBlock();
}
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
[XPRoomViewController openRoom:targetRoomUid.stringValue
viewController:[XCCurrentVCStackManager shareManager].getCurrentVC];
});
return;
}
// banner还存在正常执行
if (self.exitCurrentRoom) {
self.exitCurrentRoom();
}
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
[XPRoomViewController openRoom:targetRoomUid.stringValue
viewController:[XCCurrentVCStackManager shareManager].getCurrentVC];
});
} cancelHandler:^{}];
}
- (void)setupUI {
// 设置背景图
self.svgaView = [[SVGAImageView alloc] init];
self.svgaView.loops = 0;
self.svgaView.clearsAfterStop = YES;
[self addSubview:self.svgaView];
[self.svgaView mas_makeConstraints:^(MASConstraintMaker *make) {
make.edges.equalTo(self);
}];
SVGAParser *p = [[SVGAParser alloc] init];
@kWeakify(self);
[p parseWithNamed:@"brove_gift" inBundle:[NSBundle mainBundle] completionBlock:^(SVGAVideoEntity * _Nonnull videoItem) {
@kStrongify(self);
if (videoItem) {
self.svgaView.videoItem = videoItem;
[self.svgaView startAnimation];
}
} failureBlock:^(NSError * _Nonnull error) {
@kStrongify(self);
if (self.completeDisplay) {
self.completeDisplay();
}
}];
UILabel *sendLabel = [self sendLabel];
UILabel *winLabel = [self winLabel];
// 发送者头像
NetImageConfig * config = [[NetImageConfig alloc]init];
config.imageType = ImageTypeUserIcon;
config.placeHolder = [UIImageConstant defaultAvatarPlaceholder];
self.sendAvatarImageView = [[NetImageView alloc] initWithConfig:config];
[self.sendAvatarImageView setCornerRadius:kGetScaleWidth(15)];
// 礼物头像
self.giftImageView = [[NetImageView alloc] initWithConfig:config];
[self.giftImageView setCornerRadius:2];
// 金币数量
self.goldNumLabel = [[UILabel alloc] init];
self.goldNumLabel.font = kFontSemibold(18);
self.goldNumLabel.textColor = UIColorFromRGB(0xffec6f);
// 金币图标
self.moneyIconImageView = [[UIImageView alloc] init];
self.moneyIconImageView.image = kImage(@"moli_money_icon");
UIStackView *stackView = [[UIStackView alloc] initWithArrangedSubviews:@[
self.sendAvatarImageView,
sendLabel,
self.giftImageView,
winLabel,
self.goldNumLabel,
self.moneyIconImageView
]];
stackView.spacing = 4;
stackView.alignment = UIStackViewAlignmentCenter;
[self addSubview:stackView];
[stackView mas_makeConstraints:^(MASConstraintMaker *make) {
make.centerX.mas_equalTo(self);
make.top.mas_equalTo(self).offset(kGetScaleWidth(28));
}];
[sendLabel mas_makeConstraints:^(MASConstraintMaker *make) {
make.height.mas_equalTo(24);
}];
[winLabel mas_makeConstraints:^(MASConstraintMaker *make) {
make.height.mas_equalTo(24);
}];
[self.sendAvatarImageView mas_makeConstraints:^(MASConstraintMaker *make) {
make.width.height.mas_equalTo(kGetScaleWidth(30));
}];
[self.giftImageView mas_makeConstraints:^(MASConstraintMaker *make) {
make.width.height.mas_equalTo(kGetScaleWidth(32));
}];
[self.moneyIconImageView mas_makeConstraints:^(MASConstraintMaker *make) {
make.width.height.mas_equalTo(kGetScaleWidth(24));
}];
}
- (UILabel *)sendLabel {
return [UILabel labelInitWithText:YMLocalizedString(@"Combo_0")
font:kFontRegular(14)
textColor:[UIColor whiteColor]];
}
- (UILabel *)winLabel {
return [UILabel labelInitWithText:YMLocalizedString(@"Combo_4")
font:kFontRegular(14)
textColor:[UIColor whiteColor]];
}
@end