2025-04-21 13:52:13 +08:00
|
|
|
|
#import "BravoGiftBannerView.h"
|
2025-04-02 11:04:07 +08:00
|
|
|
|
#import "UserInfoModel.h"
|
|
|
|
|
#import "AttachmentModel.h"
|
|
|
|
|
#import <POP.h>
|
|
|
|
|
#import <SVGA.h>
|
2025-04-10 18:01:01 +08:00
|
|
|
|
#import "XPRoomViewController.h"
|
|
|
|
|
#import "XCCurrentVCStackManager.h"
|
2025-04-02 11:04:07 +08:00
|
|
|
|
|
|
|
|
|
//{"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}
|
|
|
|
|
|
2025-04-21 13:52:13 +08:00
|
|
|
|
@interface BravoGiftBannerViewModel : PIBaseModel
|
2025-04-02 11:04:07 +08:00
|
|
|
|
|
|
|
|
|
@property (nonatomic, assign, readonly) CGFloat times;
|
|
|
|
|
@property (nonatomic, assign, readonly) CGFloat coins;
|
|
|
|
|
@property (nonatomic, copy, readonly) NSString *giftPic;
|
|
|
|
|
@property (nonatomic, copy, readonly) NSDictionary *giftNameMap;
|
2025-04-10 18:01:01 +08:00
|
|
|
|
@property (nonatomic, copy) NSNumber *roomUid;
|
2025-04-02 11:04:07 +08:00
|
|
|
|
@property (nonatomic, strong, readonly) UserInfoModel *sender;
|
|
|
|
|
|
|
|
|
|
@end
|
|
|
|
|
|
2025-04-21 13:52:13 +08:00
|
|
|
|
@implementation BravoGiftBannerViewModel
|
2025-04-02 11:04:07 +08:00
|
|
|
|
|
|
|
|
|
@end
|
|
|
|
|
|
|
|
|
|
|
2025-04-21 13:52:13 +08:00
|
|
|
|
@interface BravoGiftBannerView ()
|
|
|
|
|
@property (nonatomic, strong) BravoGiftBannerViewModel *model;
|
2025-04-02 11:04:07 +08:00
|
|
|
|
@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;
|
2025-04-10 18:01:01 +08:00
|
|
|
|
@property (nonatomic, assign) NSInteger currentRoomUid;
|
2025-04-02 11:04:07 +08:00
|
|
|
|
@property (nonatomic, copy) void(^completeDisplay)(void);
|
2025-04-10 18:01:01 +08:00
|
|
|
|
@property (nonatomic, copy) void(^exitCurrentRoom)(void);
|
2025-04-02 11:04:07 +08:00
|
|
|
|
@end
|
|
|
|
|
|
2025-04-21 13:52:13 +08:00
|
|
|
|
@implementation BravoGiftBannerView
|
2025-04-02 11:04:07 +08:00
|
|
|
|
|
2025-04-10 18:01:01 +08:00
|
|
|
|
+ (void)display:(UIView *)superView
|
|
|
|
|
inRoomUid:(NSInteger)roomUid
|
|
|
|
|
with:(AttachmentModel *)attachment
|
|
|
|
|
complete:(void (^)(void))complete
|
|
|
|
|
exitCurrentRoom:(void(^)(void))exit {
|
2025-04-21 13:52:13 +08:00
|
|
|
|
BravoGiftBannerViewModel *model = [BravoGiftBannerViewModel modelWithDictionary:attachment.data];
|
2025-04-02 11:04:07 +08:00
|
|
|
|
CGRect frame = CGRectMake(KScreenWidth, 0, KScreenWidth, kGetScaleWidth(90));
|
2025-04-21 13:52:13 +08:00
|
|
|
|
BravoGiftBannerView *banner = [[BravoGiftBannerView alloc] initWithFrame:frame];
|
2025-04-02 11:04:07 +08:00
|
|
|
|
banner.model = model;
|
2025-04-28 14:52:00 +08:00
|
|
|
|
banner.currentRoomUid = roomUid;
|
2025-04-02 11:04:07 +08:00
|
|
|
|
banner.completeDisplay = complete;
|
2025-04-10 18:01:01 +08:00
|
|
|
|
banner.exitCurrentRoom = exit;
|
2025-04-02 11:04:07 +08:00
|
|
|
|
[banner addNotification];
|
|
|
|
|
[superView addSubview:banner];
|
|
|
|
|
|
2025-06-09 15:52:34 +08:00
|
|
|
|
NSInteger time = 3;
|
|
|
|
|
|
2025-04-02 11:04:07 +08:00
|
|
|
|
@kWeakify(banner);
|
|
|
|
|
[banner popEnterAnimation:^(BOOL finished) {
|
2025-06-09 15:52:34 +08:00
|
|
|
|
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(time * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
|
2025-04-02 11:04:07 +08:00
|
|
|
|
@kStrongify(banner);
|
|
|
|
|
[banner popLeaveAnimation:^(bool finished) {
|
|
|
|
|
if (banner.completeDisplay) {
|
|
|
|
|
banner.completeDisplay();
|
|
|
|
|
}
|
|
|
|
|
[banner removeFromSuperview];
|
|
|
|
|
}];
|
|
|
|
|
});
|
|
|
|
|
}];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
- (void)addNotification {
|
|
|
|
|
@kWeakify(self);
|
|
|
|
|
[[NSNotificationCenter defaultCenter] addObserverForName:@"SwipeOutBanner"
|
|
|
|
|
object:nil
|
|
|
|
|
queue:[NSOperationQueue mainQueue]
|
|
|
|
|
usingBlock:^(NSNotification * _Nonnull notification) {
|
|
|
|
|
@kStrongify(self);
|
|
|
|
|
[self dismissBanner];
|
|
|
|
|
}];
|
|
|
|
|
}
|
|
|
|
|
|
2025-04-21 13:52:13 +08:00
|
|
|
|
- (void)setModel:(BravoGiftBannerViewModel *)model {
|
2025-04-28 14:52:00 +08:00
|
|
|
|
_model = model;
|
2025-04-02 11:04:07 +08:00
|
|
|
|
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 {
|
|
|
|
|
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];
|
2025-06-09 15:52:34 +08:00
|
|
|
|
self.userInteractionEnabled = NO;
|
2025-08-14 18:36:23 +08:00
|
|
|
|
UIButton *b = [UIButton buttonWithType:UIButtonTypeCustom];
|
|
|
|
|
[self addSubview:b];
|
|
|
|
|
[b mas_remakeConstraints:^(MASConstraintMaker *make) {
|
|
|
|
|
make.edges.mas_equalTo(self);
|
|
|
|
|
}];
|
|
|
|
|
[b addTarget:self action:@selector(handelTap) forControlEvents:UIControlEventTouchUpInside];
|
2025-04-02 11:04:07 +08:00
|
|
|
|
}
|
|
|
|
|
return self;
|
|
|
|
|
}
|
|
|
|
|
|
2025-04-10 18:01:01 +08:00
|
|
|
|
- (void)handelTap {
|
|
|
|
|
if (self.model.roomUid.integerValue == self.currentRoomUid) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2025-08-14 18:04:38 +08:00
|
|
|
|
// 在弹框显示前保存必要数据,避免依赖banner对象
|
|
|
|
|
NSNumber *targetRoomUid = self.model.roomUid;
|
|
|
|
|
void(^exitCurrentRoomBlock)(void) = self.exitCurrentRoom;
|
|
|
|
|
|
2025-04-10 18:01:01 +08:00
|
|
|
|
@kWeakify(self);
|
|
|
|
|
[TTPopup alertWithMessage:YMLocalizedString(@"Combo_10") confirmHandler:^{
|
|
|
|
|
@kStrongify(self);
|
2025-08-14 18:04:38 +08:00
|
|
|
|
|
|
|
|
|
// 检查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还存在,正常执行
|
2025-04-10 18:01:01 +08:00
|
|
|
|
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:^{}];
|
|
|
|
|
}
|
|
|
|
|
|
2025-04-02 11:04:07 +08:00
|
|
|
|
- (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
|