Commit 365c58d3 by suolong

添加部分限时表演 主播

parent c4be54a1
Showing with 690 additions and 5 deletions
......@@ -1435,6 +1435,8 @@
BED658F42C5B745E00668116 /* FUSLiveBottomToolSubView.m in Sources */ = {isa = PBXBuildFile; fileRef = BED655F12C5B745D00668116 /* FUSLiveBottomToolSubView.m */; };
BEF6C0A72F0A1B2C0033D4E5 /* FUSLiveShowTimePopView.h in Headers */ = {isa = PBXBuildFile; fileRef = BEF6C0A52F0A1B2C0033D4E5 /* FUSLiveShowTimePopView.h */; };
BEF6C0A82F0A1B2C0033D4E5 /* FUSLiveShowTimePopView.m in Sources */ = {isa = PBXBuildFile; fileRef = BEF6C0A62F0A1B2C0033D4E5 /* FUSLiveShowTimePopView.m */; };
BEF6C0BB2F0A1D3A0033D4E5 /* FUSLiveShowTimeCollectFrostedView.h in Headers */ = {isa = PBXBuildFile; fileRef = BEF6C0B92F0A1D3A0033D4E5 /* FUSLiveShowTimeCollectFrostedView.h */; };
BEF6C0BC2F0A1D3A0033D4E5 /* FUSLiveShowTimeCollectFrostedView.m in Sources */ = {isa = PBXBuildFile; fileRef = BEF6C0BA2F0A1D3A0033D4E5 /* FUSLiveShowTimeCollectFrostedView.m */; };
BED658F52C5B745E00668116 /* FUSLiveBottomToolView.h in Headers */ = {isa = PBXBuildFile; fileRef = BED655F22C5B745D00668116 /* FUSLiveBottomToolView.h */; };
BED658F62C5B745E00668116 /* FUSLiveBottomToolView.m in Sources */ = {isa = PBXBuildFile; fileRef = BED655F32C5B745D00668116 /* FUSLiveBottomToolView.m */; };
BED658F72C5B745E00668116 /* FUSLiveChatFastInputCell.h in Headers */ = {isa = PBXBuildFile; fileRef = BED655F42C5B745D00668116 /* FUSLiveChatFastInputCell.h */; };
......@@ -3818,6 +3820,8 @@
BED655F12C5B745D00668116 /* FUSLiveBottomToolSubView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FUSLiveBottomToolSubView.m; sourceTree = "<group>"; };
BEF6C0A52F0A1B2C0033D4E5 /* FUSLiveShowTimePopView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FUSLiveShowTimePopView.h; sourceTree = "<group>"; };
BEF6C0A62F0A1B2C0033D4E5 /* FUSLiveShowTimePopView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FUSLiveShowTimePopView.m; sourceTree = "<group>"; };
BEF6C0B92F0A1D3A0033D4E5 /* FUSLiveShowTimeCollectFrostedView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FUSLiveShowTimeCollectFrostedView.h; sourceTree = "<group>"; };
BEF6C0BA2F0A1D3A0033D4E5 /* FUSLiveShowTimeCollectFrostedView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FUSLiveShowTimeCollectFrostedView.m; sourceTree = "<group>"; };
BED655F22C5B745D00668116 /* FUSLiveBottomToolView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FUSLiveBottomToolView.h; sourceTree = "<group>"; };
BED655F32C5B745D00668116 /* FUSLiveBottomToolView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FUSLiveBottomToolView.m; sourceTree = "<group>"; };
BED655F42C5B745D00668116 /* FUSLiveChatFastInputCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FUSLiveChatFastInputCell.h; sourceTree = "<group>"; };
......@@ -6768,6 +6772,8 @@
BED655F12C5B745D00668116 /* FUSLiveBottomToolSubView.m */,
BEF6C0A52F0A1B2C0033D4E5 /* FUSLiveShowTimePopView.h */,
BEF6C0A62F0A1B2C0033D4E5 /* FUSLiveShowTimePopView.m */,
BEF6C0B92F0A1D3A0033D4E5 /* FUSLiveShowTimeCollectFrostedView.h */,
BEF6C0BA2F0A1D3A0033D4E5 /* FUSLiveShowTimeCollectFrostedView.m */,
BED655F22C5B745D00668116 /* FUSLiveBottomToolView.h */,
BED655F32C5B745D00668116 /* FUSLiveBottomToolView.m */,
BED655F42C5B745D00668116 /* FUSLiveChatFastInputCell.h */,
......@@ -8613,6 +8619,7 @@
BED65B0A2C5B746000668116 /* FUSOpenScreenPushHelp.h in Headers */,
BED658F32C5B745E00668116 /* FUSLiveBottomToolSubView.h in Headers */,
BEF6C0A72F0A1B2C0033D4E5 /* FUSLiveShowTimePopView.h in Headers */,
BEF6C0BB2F0A1D3A0033D4E5 /* FUSLiveShowTimeCollectFrostedView.h in Headers */,
00B28CBA2D2FC4E10008476B /* FUSLiveEndLiveAssesModel.h in Headers */,
BE189DDF2C733B460008418B /* FSRRoomManagerViewController.h in Headers */,
BED65A442C5B745F00668116 /* FUSLiveBoxDetailSettingView.h in Headers */,
......@@ -10681,6 +10688,7 @@
BE189DBC2C733B460008418B /* FSRSettingRoomGuarderOnlineModel.m in Sources */,
BED658F42C5B745E00668116 /* FUSLiveBottomToolSubView.m in Sources */,
BEF6C0A82F0A1B2C0033D4E5 /* FUSLiveShowTimePopView.m in Sources */,
BEF6C0BC2F0A1D3A0033D4E5 /* FUSLiveShowTimeCollectFrostedView.m in Sources */,
BED6599E2C5B745F00668116 /* FUSLinkMicItemView.m in Sources */,
BED658802C5B745E00668116 /* FUSLivePropsModel.m in Sources */,
BE189DB82C733B460008418B /* FSRRoomManagerShowRoomModel.m in Sources */,
{
"images" : [
{
"filename" : "Live_bottom_countdown.png",
"idiom" : "universal",
"scale" : "1x"
},
{
"filename" : "Live_bottom_countdown@2x.png",
"idiom" : "universal",
"scale" : "2x"
},
{
"filename" : "Live_bottom_countdown@3x.png",
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}
{
"images" : [
{
"filename" : "Live_bottom_mvp.png",
"idiom" : "universal",
"scale" : "1x"
},
{
"filename" : "Live_bottom_mvp@2x.png",
"idiom" : "universal",
"scale" : "2x"
},
{
"filename" : "Live_bottom_mvp@3x.png",
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}
{
"images" : [
{
"filename" : "Live_bottom_ticket.png",
"idiom" : "universal",
"scale" : "1x"
},
{
"filename" : "Live_bottom_ticket@2x.png",
"idiom" : "universal",
"scale" : "2x"
},
{
"filename" : "Live_bottom_ticket@3x.png",
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}
......@@ -43,6 +43,12 @@ NS_ASSUME_NONNULL_BEGIN
*/
- (void)fus_bottomSubViewDidClickPKBtn:(FUSLiveBottomToolSubView *)bottomSubView livePkBtnState:(FUSLiveChatToolPKBtnState)livePkBtnState;
/// 点击“限时表演”工具按钮(交由外部决定如何展示弹窗/后续逻辑)
/// - Parameters:
/// - bottomSubView: 当前工具子视图
/// - containerView: 建议承载弹窗的父视图
- (void)fus_bottomSubView:(FUSLiveBottomToolSubView *)bottomSubView didClickShowTimeOnView:(UIView *)containerView;
@end
@interface FUSLiveBottomToolSubView : UIView
......
......@@ -21,8 +21,6 @@
#import "FUSShowRoomModule/FUSShowRoomModule-Swift.h"
#import "FUSLiveShowTimePopView.h"
//#import "UIImageView+FUSTestImgeView.h"
@interface FUSLiveBottomToolSubView () <FUSLiveChatInputTextViewDelegate>
......@@ -172,7 +170,10 @@
break;
case FUSLiveBottomToolTypeShowTime:
{
[FUSLiveShowTimePopView fus_showOnView:bgView];
if ([self.delegate respondsToSelector:@selector(fus_bottomSubView:didClickShowTimeOnView:)]) {
UIView *container = bgView ?: self.bgView ?: [UIViewController fus_topViewController].view;
[self.delegate fus_bottomSubView:self didClickShowTimeOnView:container];
}
}
break;
case FUSLiveBottomToolTypeExchange:
......
......@@ -111,6 +111,12 @@ typedef NS_ENUM(NSUInteger, FUSLiveChatToolBeautyType) { //美颜工具按钮
- (void)fus_bottomToolViewDidBeautySetting:(FUSLiveBottomToolView *)bottomToolView
beautyType:(FUSLiveChatToolBeautyType)type;
/// 点击“限时表演”工具按钮(交由外部决定如何展示弹窗/后续逻辑)
/// - Parameters:
/// - bottomToolView: 当前工具栏
/// - containerView: 建议承载弹窗的父视图
- (void)fus_bottomToolView:(FUSLiveBottomToolView *)bottomToolView didClickShowTimeOnView:(UIView *)containerView;
@end
@interface FUSLiveBottomToolView : UIView
......
......@@ -1339,6 +1339,12 @@
}
}
- (void)fus_bottomSubView:(FUSLiveBottomToolSubView *)bottomSubView didClickShowTimeOnView:(UIView *)containerView {
if (self.delegate && [self.delegate respondsToSelector:@selector(fus_bottomToolView:didClickShowTimeOnView:)]) {
[self.delegate fus_bottomToolView:self didClickShowTimeOnView:containerView];
}
}
- (void)fus_bottomSubViewDidBeautySetting:(FUSLiveBottomToolSubView *)bottomToolView beautyType:(FUSLiveChatToolBeautyType)type{
if (_delegate && [_delegate respondsToSelector:@selector(fus_bottomToolViewDidBeautySetting:beautyType:)]) {
......
......@@ -54,4 +54,7 @@
// 取消未执行的任务并置空定时器
- (void)cancelTimerTaskAndDeleteTimer;
/// 销毁限时表演集票磨砂条(确认结束直播后调用)
- (void)fus_destroyShowTimeFrostedIfNeeded;
@end
......@@ -25,6 +25,10 @@
#import "FUSBottomOptionalView.h"
#import "FUSLiveShareToChatView.h"
#import "FUSLiveShowTimePopView.h"
#import "FUSLiveShowTimeCollectFrostedView.h"
#import "FUSLiveFunctionLayerView.h"
#import <FUSFoundation/FUSFoundation-Swift.h>
#import <FUSCommon/FUSCommon-Swift.h>
......@@ -40,6 +44,9 @@
@property (nonatomic, assign) BOOL isUpdating; // 是否正在更新礼物数据
// 限时表演集票磨砂条:由工具栏点击触发创建,用于后续 socket 刷新进度/新票
@property (nonatomic, strong) FUSLiveShowTimeCollectFrostedView *showTimeFrostedView;
@end
@implementation FUSLiveChatInputHelper
......@@ -419,6 +426,47 @@
FUSLogDebug(@"");
}
- (void)fus_bottomToolView:(FUSLiveBottomToolView *)bottomToolView didClickShowTimeOnView:(UIView *)containerView {
UIView *popContainer = (containerView ?: [UIViewController fus_topViewController].view);
__weak typeof(self) weakSelf = self;
FUSLiveShowTimePopView *popView = [FUSLiveShowTimePopView fus_showOnView:popContainer];
popView.startCollectHandler = ^(NSString * _Nonnull themeText, NSInteger ticketCount) {
__strong typeof(weakSelf) strongSelf = weakSelf;
if (!strongSelf) {
return;
}
UIView *onView = [[FUSLiveHelper shareInstance].currentFunctionView fus_viewWithLayer:FUSLiveFunctionLayerFunctionButtons];
if (!onView) {
onView = [FUSLiveHelper shareInstance].currentLiveVCView ?: popContainer;
}
if (!onView) {
onView = [UIViewController fus_topViewController].view;
}
if (strongSelf.showTimeFrostedView.superview) {
[strongSelf.showTimeFrostedView removeFromSuperview];
}
FUSLiveShowTimeCollectFrostedView *bar = [FUSLiveShowTimeCollectFrostedView fus_showOnView:onView];
strongSelf.showTimeFrostedView = bar;
bar.cancelHandler = ^{
__strong typeof(weakSelf) innerSelf = weakSelf;
innerSelf.showTimeFrostedView = nil;
};
NSString *finalTheme = (themeText.length > 0 ? themeText : [NSString fus_localString:@"我是表演主题表演主题"]);
NSString *remainingText = [NSString stringWithFormat:[NSString fus_localString:@"还差 %zd 张!"], (NSInteger)ticketCount];
[bar fus_updateWithState:FUSLiveShowTimeCollectFrostedStateStarted
themeText:finalTheme
progress:ticketCount
remainingText:remainingText
startTimestamp:[[NSDate date] timeIntervalSince1970]
newTicketCount:0
userModel:nil];
};
}
- (void)fus_bottomToolViewDidClickPKBtn:(FUSLiveBottomToolView *)bottomToolView livePkBtnState:(FUSLiveChatToolPKBtnState)livePkBtnState{
// switch (livePkBtnState) {
......@@ -673,4 +721,12 @@
[self closeTimer:self.giftTimer];
}
#pragma mark - 限时表演磨砂条
- (void)fus_destroyShowTimeFrostedIfNeeded {
if (self.showTimeFrostedView) {
[self.showTimeFrostedView fus_dismiss];
self.showTimeFrostedView = nil;
}
}
@end
#import <UIKit/UIKit.h>
NS_ASSUME_NONNULL_BEGIN
@class FUSOnlineUserModel;
/// 集票磨砂条状态
typedef NS_ENUM(NSInteger, FUSLiveShowTimeCollectFrostedState) {
/// 刚开启
FUSLiveShowTimeCollectFrostedStateStarted = 0,
/// 有新票(展示 +N 提示)
FUSLiveShowTimeCollectFrostedStateNewTicket,
/// 集票完成
FUSLiveShowTimeCollectFrostedStateCompleted,
};
/// 限时表演集票磨砂条:展示集票进度/倒计时/取消入口
@interface FUSLiveShowTimeCollectFrostedView : UIView
/// 在指定视图底部展示磨砂条
/// @param onView 父视图
+ (instancetype)fus_showOnView:(UIView *)onView;
/// 更新展示内容(跟服务端对接时从这里刷新)
/// @param state 当前状态
/// @param themeText 表演主题
/// @param progress 0~1 进度
/// @param remainingText 剩余票提示,如“还差 49 张!”
/// @param startTimestamp 集票开始时间戳(秒)
/// @param newTicketCount 新票数(state=NewTicket 时使用)
/// @param userModel 新票贡献用户信息(nil 时不展示标题栏用户信息)
- (void)fus_updateWithState:(FUSLiveShowTimeCollectFrostedState)state
themeText:(NSString *)themeText
progress:(CGFloat)progress
remainingText:(NSString *)remainingText
startTimestamp:(NSTimeInterval)startTimestamp
newTicketCount:(NSInteger)newTicketCount
userModel:(FUSOnlineUserModel * _Nullable)userModel;
/// 取消按钮点击回调(预留服务端入口)
@property (nonatomic, copy, nullable) void (^cancelHandler)(void);
/// 移除磨砂条
- (void)fus_dismiss;
@end
NS_ASSUME_NONNULL_END
#import "FUSLiveShowTimeCollectFrostedView.h"
#import <FUSCommon/FUSCommon.h>
#import <FUSFoundation/FUSFoundation.h>
#import <Masonry/Masonry.h>
#import "FUSShowRoomCenterBunble.h"
#import "FUSLiveBottomToolView.h"
#import "FUSOnlineUserModel.h"
static const CGFloat kFUSShowTimeFrostedHeight = 120.0;
static const NSInteger kFUSShowTimeCollectSeconds = 10 * 60;
@interface FUSLiveShowTimeCollectFrostedView ()
/// 磨砂容器(承载毛玻璃效果)
@property (nonatomic, strong) UIVisualEffectView *blurView;
/// 左侧进度圈容器
@property (nonatomic, strong) UIView *progressContainer;
/// 进度圈底轨
@property (nonatomic, strong) CAShapeLayer *progressTrackLayer;
/// 进度圈进度层
@property (nonatomic, strong) CAShapeLayer *progressLayer;
/// 进度百分比文本
@property (nonatomic, strong) UILabel *progressLabel;
/// 记录上一次进度圈尺寸,避免重复计算 path
@property (nonatomic, assign) CGFloat lastProgressCircleSize;
/// 顶部用户头像
@property (nonatomic, strong) UIImageView *avatarView;
/// 顶部昵称
@property (nonatomic, strong) UILabel *topTitleLabel;
/// 新票图标
@property (nonatomic, strong) UIImageView *ticketIconView;
/// 新票数提示(+N)
@property (nonatomic, strong) UILabel *showTimeNewTicketLabel;
/// 分割线以下内容容器(用于垂直居中进度圈)
@property (nonatomic, strong) UIView *bottomContentView;
/// 表演主题
@property (nonatomic, strong) UILabel *themeLabel;
/// 倒计时图标
@property (nonatomic, strong) UIImageView *countdownIconView;
/// 还差票数提示
@property (nonatomic, strong) UILabel *remainingLabel;
/// 倒计时文本
@property (nonatomic, strong) UILabel *countdownLabel;
/// 顶部操作区下方分割线
@property (nonatomic, strong) UIView *topDividerView;
/// 右侧 MVP 标识
@property (nonatomic, strong) UIImageView *mvpIconView;
/// 取消集票按钮
@property (nonatomic, strong) UIButton *cancelBtn;
/// 集票开始时间戳(秒)
@property (nonatomic, assign) NSTimeInterval startTimestamp;
/// 倒计时刷新计时器
@property (nonatomic, strong) dispatch_source_t countdownTimer;
@end
@implementation FUSLiveShowTimeCollectFrostedView
+ (instancetype)fus_showOnView:(UIView *)onView {
FUSLiveShowTimeCollectFrostedView *existView = [onView viewWithTag:8817201];
if ([existView isKindOfClass:FUSLiveShowTimeCollectFrostedView.class]) {
return existView;
}
CGFloat safeBottom = UIView.fus_SafeBottom;
CGFloat bottomToolH = LIVE_ROOM_BOTTOM_VIEW_HEIGHT;
CGFloat y = onView.height - safeBottom - bottomToolH - kFUSShowTimeFrostedHeight;
if (y < 0) {
y = 0;
}
FUSLiveShowTimeCollectFrostedView *view = [[FUSLiveShowTimeCollectFrostedView alloc] initWithFrame:CGRectMake(0, y, onView.width, kFUSShowTimeFrostedHeight)];
view.tag = 8817201;
[onView addSubview:view];
return view;
}
- (instancetype)initWithFrame:(CGRect)frame {
self = [super initWithFrame:frame];
if (self) {
self.backgroundColor = UIColor.clearColor;
UIBlurEffect *effect = [UIBlurEffect effectWithStyle:UIBlurEffectStyleDark];
self.blurView = [[UIVisualEffectView alloc] initWithEffect:effect];
[self addSubview:self.blurView];
self.progressContainer = [[UIView alloc] init];
[self.blurView.contentView addSubview:self.progressContainer];
[self fus_setupProgressLayers];
self.avatarView = [[UIImageView alloc] init];
self.avatarView.layer.cornerRadius = 11;
self.avatarView.layer.masksToBounds = YES;
self.avatarView.backgroundColor = [UIColor colorWithWhite:1 alpha:0.2];
[self.blurView.contentView addSubview:self.avatarView];
self.topTitleLabel = [[UILabel alloc] init];
self.topTitleLabel.font = [UIFont fus_themeFont:12];
self.topTitleLabel.textColor = [UIColor colorWithWhite:1 alpha:0.85];
self.topTitleLabel.text = [NSString fus_localString:@"我是昵称"];
[self.blurView.contentView addSubview:self.topTitleLabel];
self.ticketIconView = [[UIImageView alloc] init];
self.ticketIconView.image = [FUSShowRoomCenterBunble imageNamed:@"Live_bottom_ticket"];
self.ticketIconView.hidden = YES;
[self.blurView.contentView addSubview:self.ticketIconView];
self.showTimeNewTicketLabel = [[UILabel alloc] init];
self.showTimeNewTicketLabel.font = [UIFont fus_themeBoldFont:12];
self.showTimeNewTicketLabel.textColor = [UIColor colorWithWhite:1 alpha:0.9];
self.showTimeNewTicketLabel.hidden = YES;
[self.blurView.contentView addSubview:self.showTimeNewTicketLabel];
self.cancelBtn = [UIButton buttonWithType:UIButtonTypeCustom];
self.cancelBtn.layer.cornerRadius = 13;
self.cancelBtn.layer.masksToBounds = YES;
self.cancelBtn.backgroundColor = [UIColor colorWithHex:@"#52DDE2"];
[self.cancelBtn setTitle:[NSString fus_localString:@"取消集票"] forState:UIControlStateNormal];
[self.cancelBtn setTitleColor:UIColor.blackColor forState:UIControlStateNormal];
self.cancelBtn.titleLabel.font = [UIFont fus_themeBoldFont:12];
[self.cancelBtn addTarget:self action:@selector(fus_onClickCancel) forControlEvents:UIControlEventTouchUpInside];
[self.blurView.contentView addSubview:self.cancelBtn];
self.topDividerView = [[UIView alloc] init];
self.topDividerView.backgroundColor = [UIColor colorWithWhite:1 alpha:0.15];
[self.blurView.contentView addSubview:self.topDividerView];
self.bottomContentView = [[UIView alloc] init];
[self.blurView.contentView addSubview:self.bottomContentView];
self.themeLabel = [[UILabel alloc] init];
self.themeLabel.font = [UIFont fus_themeBoldFont:16];
self.themeLabel.textColor = UIColor.whiteColor;
self.themeLabel.text = [NSString fus_localString:@"我是表演主题表演主题"];
[self.blurView.contentView addSubview:self.themeLabel];
self.remainingLabel = [[UILabel alloc] init];
self.remainingLabel.font = [UIFont fus_themeFont:12];
self.remainingLabel.textColor = [UIColor colorWithWhite:1 alpha:0.85];
self.remainingLabel.text = [NSString fus_localString:@"还差 49 张!"];
[self.blurView.contentView addSubview:self.remainingLabel];
self.countdownIconView = [[UIImageView alloc] init];
self.countdownIconView.image = [FUSShowRoomCenterBunble imageNamed:@"Live_bottom_countdown"];
[self.blurView.contentView addSubview:self.countdownIconView];
self.countdownLabel = [[UILabel alloc] init];
self.countdownLabel.font = [UIFont fus_themeFont:12];
self.countdownLabel.textColor = [UIColor colorWithWhite:1 alpha:0.85];
self.countdownLabel.text = @"";
[self.blurView.contentView addSubview:self.countdownLabel];
self.mvpIconView = [[UIImageView alloc] init];
self.mvpIconView.image = [FUSShowRoomCenterBunble imageNamed:@"Live_bottom_mvp"];
[self.blurView.contentView addSubview:self.mvpIconView];
[self.blurView mas_makeConstraints:^(MASConstraintMaker *make) {
make.edges.equalTo(self);
}];
[self.cancelBtn mas_makeConstraints:^(MASConstraintMaker *make) {
make.top.equalTo(self.blurView.contentView).offset(10);
make.right.equalTo(self.blurView.contentView).offset(-12);
make.size.mas_equalTo(CGSizeMake(76, 26));
}];
[self.topDividerView mas_makeConstraints:^(MASConstraintMaker *make) {
make.left.right.equalTo(self.blurView.contentView);
make.top.equalTo(self.cancelBtn.mas_bottom).offset(8);
make.height.mas_equalTo(0.5);
}];
[self.bottomContentView mas_makeConstraints:^(MASConstraintMaker *make) {
make.left.right.bottom.equalTo(self.blurView.contentView);
make.top.equalTo(self.topDividerView.mas_bottom);
}];
[self.themeLabel mas_makeConstraints:^(MASConstraintMaker *make) {
make.left.equalTo(self.progressContainer.mas_right).offset(12);
make.top.equalTo(self.bottomContentView).offset(8);
make.height.mas_equalTo(22);
}];
[self.remainingLabel mas_makeConstraints:^(MASConstraintMaker *make) {
make.left.equalTo(self.themeLabel);
make.top.equalTo(self.themeLabel.mas_bottom).offset(6);
make.height.mas_equalTo(18);
}];
[self.remainingLabel setContentCompressionResistancePriority:UILayoutPriorityRequired forAxis:UILayoutConstraintAxisHorizontal];
[self.remainingLabel setContentHuggingPriority:UILayoutPriorityRequired forAxis:UILayoutConstraintAxisHorizontal];
[self.mvpIconView mas_makeConstraints:^(MASConstraintMaker *make) {
make.right.equalTo(self.blurView.contentView).offset(-12);
make.centerY.equalTo(self.remainingLabel);
make.size.mas_equalTo(CGSizeMake(44, 20));
}];
[self.themeLabel mas_makeConstraints:^(MASConstraintMaker *make) {
make.right.lessThanOrEqualTo(self.mvpIconView.mas_left).offset(-12);
}];
[self.progressContainer mas_makeConstraints:^(MASConstraintMaker *make) {
make.left.equalTo(self.blurView.contentView).offset(14);
make.centerY.equalTo(self.bottomContentView);
make.size.mas_equalTo(CGSizeMake(52, 52));
make.top.greaterThanOrEqualTo(self.bottomContentView).offset(8);
}];
[self.avatarView mas_makeConstraints:^(MASConstraintMaker *make) {
make.left.equalTo(self.progressContainer.mas_right).offset(12);
make.top.equalTo(self.blurView.contentView).offset(10);
make.size.mas_equalTo(CGSizeMake(22, 22));
}];
[self.topTitleLabel mas_makeConstraints:^(MASConstraintMaker *make) {
make.left.equalTo(self.avatarView.mas_right).offset(6);
make.centerY.equalTo(self.avatarView);
make.height.mas_equalTo(18);
make.right.lessThanOrEqualTo(self.cancelBtn.mas_left).offset(-8);
}];
[self.ticketIconView mas_makeConstraints:^(MASConstraintMaker *make) {
make.left.equalTo(self.topTitleLabel.mas_right).offset(6);
make.centerY.equalTo(self.topTitleLabel);
make.size.mas_equalTo(CGSizeMake(28, 16));
make.right.lessThanOrEqualTo(self.cancelBtn.mas_left).offset(-4);
}];
[self.showTimeNewTicketLabel mas_makeConstraints:^(MASConstraintMaker *make) {
make.left.equalTo(self.ticketIconView.mas_right).offset(4);
make.centerY.equalTo(self.topTitleLabel);
make.height.mas_equalTo(18);
make.right.lessThanOrEqualTo(self.cancelBtn.mas_left).offset(-8);
}];
[self.countdownIconView mas_makeConstraints:^(MASConstraintMaker *make) {
make.left.equalTo(self.remainingLabel.mas_right).offset(8);
make.centerY.equalTo(self.remainingLabel);
make.size.mas_equalTo(CGSizeMake(16, 16));
}];
[self.countdownLabel mas_makeConstraints:^(MASConstraintMaker *make) {
make.left.equalTo(self.countdownIconView.mas_right).offset(4);
make.centerY.equalTo(self.remainingLabel);
make.height.mas_equalTo(18);
make.right.lessThanOrEqualTo(self.mvpIconView.mas_left).offset(-8);
}];
[self.countdownLabel setContentCompressionResistancePriority:UILayoutPriorityRequired forAxis:UILayoutConstraintAxisHorizontal];
[self.countdownLabel setContentHuggingPriority:UILayoutPriorityRequired forAxis:UILayoutConstraintAxisHorizontal];
[self fus_updateWithState:FUSLiveShowTimeCollectFrostedStateStarted
themeText:self.themeLabel.text
progress:0.05
remainingText:self.remainingLabel.text
startTimestamp:[[NSDate date] timeIntervalSince1970]
newTicketCount:0
userModel:nil];
[self setNeedsLayout];
[self layoutIfNeeded];
[self.progressContainer layoutIfNeeded];
[self fus_setupProgressLayers];
}
return self;
}
- (void)layoutSubviews {
[super layoutSubviews];
[self fus_setupProgressLayers];
}
/// 配置左侧进度圈(用于展示集票进度)
- (void)fus_setupProgressLayers {
CGFloat size = MIN(CGRectGetWidth(self.progressContainer.bounds), CGRectGetHeight(self.progressContainer.bounds));
CGFloat lineW = 4.0;
if (!self.progressTrackLayer) {
self.progressTrackLayer = [CAShapeLayer layer];
self.progressTrackLayer.strokeColor = [UIColor colorWithWhite:1 alpha:0.18].CGColor;
self.progressTrackLayer.fillColor = UIColor.clearColor.CGColor;
self.progressTrackLayer.lineWidth = lineW;
self.progressTrackLayer.lineCap = kCALineCapRound;
[self.progressContainer.layer addSublayer:self.progressTrackLayer];
}
if (!self.progressLayer) {
self.progressLayer = [CAShapeLayer layer];
self.progressLayer.strokeColor = [UIColor colorWithHex:@"#52DDE2"].CGColor;
self.progressLayer.fillColor = UIColor.clearColor.CGColor;
self.progressLayer.lineWidth = lineW;
self.progressLayer.lineCap = kCALineCapRound;
self.progressLayer.strokeEnd = 0;
[self.progressContainer.layer addSublayer:self.progressLayer];
}
if (!self.progressLabel) {
self.progressLabel = [[UILabel alloc] init];
self.progressLabel.textAlignment = NSTextAlignmentCenter;
self.progressLabel.font = [UIFont fus_themeBoldFont:12];
self.progressLabel.textColor = UIColor.whiteColor;
self.progressLabel.text = @"0%";
[self.progressContainer addSubview:self.progressLabel];
[self.progressLabel mas_makeConstraints:^(MASConstraintMaker *make) {
make.edges.equalTo(self.progressContainer);
}];
}
if (size <= 0) {
return;
}
if (!CGRectEqualToRect(self.progressTrackLayer.frame, self.progressContainer.bounds)) {
self.progressTrackLayer.frame = self.progressContainer.bounds;
}
if (!CGRectEqualToRect(self.progressLayer.frame, self.progressContainer.bounds)) {
self.progressLayer.frame = self.progressContainer.bounds;
}
if (fabs(self.lastProgressCircleSize - size) < 0.5 && self.progressLayer.path && self.progressTrackLayer.path) {
return;
}
self.lastProgressCircleSize = size;
CGFloat radius = (size - lineW) / 2.0;
CGPoint center = CGPointMake(size / 2.0, size / 2.0);
UIBezierPath *path = [UIBezierPath bezierPathWithArcCenter:center
radius:radius
startAngle:-M_PI_2
endAngle:(M_PI * 2 - M_PI_2)
clockwise:YES];
self.progressTrackLayer.path = path.CGPath;
self.progressLayer.path = path.CGPath;
}
- (void)fus_updateWithState:(FUSLiveShowTimeCollectFrostedState)state
themeText:(NSString *)themeText
progress:(CGFloat)progress
remainingText:(NSString *)remainingText
startTimestamp:(NSTimeInterval)startTimestamp
newTicketCount:(NSInteger)newTicketCount
userModel:(FUSOnlineUserModel *)userModel {
self.themeLabel.text = (themeText.length > 0 ? themeText : [NSString fus_localString:@"限时表演"]);
if (userModel) {
self.avatarView.hidden = NO;
self.topTitleLabel.hidden = NO;
self.mvpIconView.hidden = NO;
NSString *nickname = (userModel.nickname.length > 0 ? userModel.nickname : userModel.uid);
self.topTitleLabel.text = (nickname.length > 0 ? nickname : [NSString fus_localString:@""]);
if (userModel.face.length > 0) {
[self.avatarView setWebImageWithSubURLString:userModel.face placeholder:nil];
}
} else {
self.avatarView.hidden = YES;
self.topTitleLabel.hidden = YES;
self.ticketIconView.hidden = YES;
self.showTimeNewTicketLabel.hidden = YES;
self.mvpIconView.hidden = YES;
}
CGFloat clamped = MIN(1.0, MAX(0.0, progress));
self.progressLayer.strokeEnd = clamped;
self.progressLabel.text = [NSString stringWithFormat:@"%zd%%", (NSInteger)llround(clamped * 100)];
self.remainingLabel.text = (remainingText.length > 0 ? remainingText : @"");
self.startTimestamp = startTimestamp;
if (state == FUSLiveShowTimeCollectFrostedStateCompleted) {
[self fus_stopCountdownTimer];
} else {
[self fus_startCountdownTimerIfNeeded];
}
if (userModel && state == FUSLiveShowTimeCollectFrostedStateNewTicket && newTicketCount > 0) {
self.ticketIconView.hidden = NO;
self.showTimeNewTicketLabel.hidden = NO;
self.showTimeNewTicketLabel.text = [NSString stringWithFormat:@"+%zd", (NSInteger)newTicketCount];
} else {
self.ticketIconView.hidden = YES;
self.showTimeNewTicketLabel.hidden = YES;
}
if (state == FUSLiveShowTimeCollectFrostedStateCompleted) {
self.remainingLabel.text = [NSString fus_localString:@"已集票满 50 张!"];
self.progressLayer.strokeEnd = 1.0;
self.progressLabel.text = @"100%";
self.countdownLabel.text = @"00:00";
}
}
/// 开始倒计时刷新(每秒刷新显示,触底自动停止)
- (void)fus_startCountdownTimerIfNeeded {
if (self.startTimestamp <= 0) {
[self fus_stopCountdownTimer];
self.countdownLabel.text = @"";
return;
}
if (self.countdownTimer) {
[self fus_refreshCountdownText];
return;
}
__weak typeof(self) weakSelf = self;
dispatch_queue_t queue = dispatch_get_main_queue();
dispatch_source_t timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, queue);
self.countdownTimer = timer;
dispatch_source_set_timer(timer, DISPATCH_TIME_NOW, (uint64_t)(1.0 * NSEC_PER_SEC), (uint64_t)(0.05 * NSEC_PER_SEC));
dispatch_source_set_event_handler(timer, ^{
[weakSelf fus_refreshCountdownText];
});
dispatch_resume(timer);
[self fus_refreshCountdownText];
}
/// 停止倒计时刷新
- (void)fus_stopCountdownTimer {
if (self.countdownTimer) {
dispatch_source_cancel(self.countdownTimer);
self.countdownTimer = nil;
}
}
/// 刷新倒计时显示
- (void)fus_refreshCountdownText {
if (self.startTimestamp <= 0) {
self.countdownLabel.text = @"";
[self fus_stopCountdownTimer];
return;
}
NSTimeInterval now = [[NSDate date] timeIntervalSince1970];
NSTimeInterval elapsed = MAX(0, now - self.startTimestamp);
NSInteger remain = (NSInteger)llround(MAX(0, (NSTimeInterval)kFUSShowTimeCollectSeconds - elapsed));
if (remain <= 0) {
self.countdownLabel.text = @"00:00";
[self fus_stopCountdownTimer];
return;
}
NSInteger minutes = remain / 60;
NSInteger seconds = remain % 60;
self.countdownLabel.text = [NSString stringWithFormat:@"%02zd:%02zd", (NSInteger)minutes, (NSInteger)seconds];
}
/// 点击取消:预留给服务端取消接口
- (void)fus_onClickCancel {
if (self.cancelHandler) {
self.cancelHandler();
return;
}
[FUSDialogView fus_showDialog:[NSString fus_localString:@"功能开发中"]];
[self fus_dismiss];
}
- (void)fus_dismiss {
[self fus_stopCountdownTimer];
[self removeFromSuperview];
}
- (void)dealloc {
[self fus_stopCountdownTimer];
}
@end
......@@ -2,6 +2,9 @@
NS_ASSUME_NONNULL_BEGIN
/// 开启集票点击回调
typedef void(^FUSLiveShowTimeStartCollectHandler)(NSString *themeText, NSInteger ticketCount);
/// “限时表演”底部弹窗(集票数量配置)
@interface FUSLiveShowTimePopView : UIView
......@@ -9,6 +12,9 @@ NS_ASSUME_NONNULL_BEGIN
/// - Parameter onView: 承载弹窗的父视图
+ (instancetype)fus_showOnView:(UIView *)onView;
/// 点击“开启集票”后的回调(外部决定怎么展示集票磨砂条/调用接口)
@property (nonatomic, copy, nullable) FUSLiveShowTimeStartCollectHandler startCollectHandler;
@end
NS_ASSUME_NONNULL_END
......@@ -222,8 +222,10 @@ static const NSInteger kFUSShowTimeTicketMax = 50;
/// 点击主按钮:后续接入真实“开始集票/开启表演”逻辑
- (void)fus_onClickStart {
// 跟服务器相关逻辑先保留入口:后续接入接口时在这里提交 themeTextField/ticketCount
[FUSDialogView fus_showDialog:[NSString fus_localString:@"功能开发中"]];
if (self.startCollectHandler) {
NSString *themeText = (self.themeTextField.text.length > 0 ? self.themeTextField.text : @"");
self.startCollectHandler(themeText, self.ticketCount);
}
[self fus_dismiss];
}
......
......@@ -5813,6 +5813,9 @@ BDAlphaPlayerMetalViewDelegate
[[NSNotificationCenter defaultCenter] postNotificationName:FUSLiveNotificationKeys.fus_LIVE_ROOM_FUNCTION_VIEW_CLEAN_NOTIFICATION object:nil];
[_bottomToolView fus_cleanBottomToolView];
if (self.chatInputHelper) {
[self.chatInputHelper fus_destroyShowTimeFrostedIfNeeded];
}
[FUSLivePunishmentManager fus_removePunishData];
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or sign in to comment