Commit 4308636e by suolong

修复bug

parent 0d5eb2b5
Showing with 329 additions and 207 deletions
......@@ -102,7 +102,7 @@
/* End PBXFileReference section */
/* Begin PBXFileSystemSynchronizedBuildFileExceptionSet section */
00E501FF2E0543A800579DB0 /* Exceptions for "NotificationService" folder in "NotificationService" target */ = {
00E501FF2E0543A800579DB0 /* PBXFileSystemSynchronizedBuildFileExceptionSet */ = {
isa = PBXFileSystemSynchronizedBuildFileExceptionSet;
membershipExceptions = (
"NotificationService-Info.plist",
......@@ -112,18 +112,7 @@
/* End PBXFileSystemSynchronizedBuildFileExceptionSet section */
/* Begin PBXFileSystemSynchronizedRootGroup section */
00E501F42E0543A800579DB0 /* NotificationService */ = {
isa = PBXFileSystemSynchronizedRootGroup;
exceptions = (
00E501FF2E0543A800579DB0 /* Exceptions for "NotificationService" folder in "NotificationService" target */,
);
explicitFileTypes = {
};
explicitFolders = (
);
path = NotificationService;
sourceTree = "<group>";
};
00E501F42E0543A800579DB0 /* NotificationService */ = {isa = PBXFileSystemSynchronizedRootGroup; exceptions = (00E501FF2E0543A800579DB0 /* PBXFileSystemSynchronizedBuildFileExceptionSet */, ); explicitFileTypes = {}; explicitFolders = (); path = NotificationService; sourceTree = "<group>"; };
/* End PBXFileSystemSynchronizedRootGroup section */
/* Begin PBXFrameworksBuildPhase section */
......@@ -444,10 +433,14 @@
inputFileListPaths = (
"${PODS_ROOT}/Target Support Files/Pods-FuSiLive/Pods-FuSiLive-frameworks-${CONFIGURATION}-input-files.xcfilelist",
);
inputPaths = (
);
name = "[CP] Embed Pods Frameworks";
outputFileListPaths = (
"${PODS_ROOT}/Target Support Files/Pods-FuSiLive/Pods-FuSiLive-frameworks-${CONFIGURATION}-output-files.xcfilelist",
);
outputPaths = (
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-FuSiLive/Pods-FuSiLive-frameworks.sh\"\n";
......@@ -461,10 +454,14 @@
inputFileListPaths = (
"${PODS_ROOT}/Target Support Files/Pods-FuSiLive/Pods-FuSiLive-resources-${CONFIGURATION}-input-files.xcfilelist",
);
inputPaths = (
);
name = "[CP] Copy Pods Resources";
outputFileListPaths = (
"${PODS_ROOT}/Target Support Files/Pods-FuSiLive/Pods-FuSiLive-resources-${CONFIGURATION}-output-files.xcfilelist",
);
outputPaths = (
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-FuSiLive/Pods-FuSiLive-resources.sh\"\n";
......@@ -694,7 +691,7 @@
CLANG_CXX_LANGUAGE_STANDARD = "gnu++17";
CODE_SIGN_ENTITLEMENTS = FuSiLive/FuSiLive.entitlements;
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 202506260047;
CURRENT_PROJECT_VERSION = 202506260048;
DEFINES_MODULE = YES;
DEVELOPMENT_TEAM = 6GG26BHUMC;
ENABLE_ON_DEMAND_RESOURCES = NO;
......@@ -959,7 +956,7 @@
CLANG_CXX_LANGUAGE_STANDARD = "gnu++17";
CODE_SIGN_ENTITLEMENTS = FuSiLive/FuSiLive.entitlements;
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 202506260047;
CURRENT_PROJECT_VERSION = 202506260048;
DEFINES_MODULE = YES;
DEVELOPMENT_TEAM = 6GG26BHUMC;
ENABLE_ON_DEMAND_RESOURCES = NO;
......
......@@ -70,8 +70,8 @@
self.roomTypeTagView.backgroundColor = UIColor.clearColor;
[self.contentView addSubview:self.roomTypeTagView];
[self.roomTypeTagView mas_makeConstraints:^(MASConstraintMaker *make) {
make.left.top.inset(6);
make.size.mas_equalTo(CGSizeMake(52.5, 22));
make.left.top.offset(0);
make.size.mas_equalTo(CGSizeMake(60, 22));
}];
self.roomTypeBgImageView = [[UIImageView alloc] init];
......@@ -100,7 +100,7 @@
self.roomTypeTextLabel = [[UILabel alloc] init];
self.roomTypeTextLabel.font = [UIFont fus_themeMediumFont:10];
self.roomTypeTextLabel.textColor = [UIColor fus_textColorVeryLight];
self.roomTypeTextLabel.textColor = [UIColor colorWithHex:@"#111111"];
[self.roomTypeTagView addSubview:self.roomTypeTextLabel];
[self.roomTypeTextLabel mas_makeConstraints:^(MASConstraintMaker *make) {
make.left.equalTo(self.roomTypeIconImageView.mas_right).offset(4);
......@@ -342,7 +342,7 @@
[self.roomTypeTextLabel mas_updateConstraints:^(MASConstraintMaker *make) {
make.left.equalTo(self.roomTypeIconImageView.mas_right).offset(4);
}];
} else if (model.type == 5) {
} else if (model.type == 5 || model.type == 4) {
icon = [FUSShowRoomCenterBunble imageNamed:@"home_list_ticket"];
[self.roomTypeIconImageView mas_updateConstraints:^(MASConstraintMaker *make) {
make.size.mas_equalTo(CGSizeMake(18.5, 10));
......
......@@ -414,7 +414,7 @@
if (gift.giftNumList.count > 0) {
self.countOptions = gift.giftNumList;
} else {
self.countOptions = @[@1, @10, @66, @99, @188, @520, @1314, @3344, @5200];
self.countOptions = @[@(1)];
}
[self fus_applyCountIndex:0];
}
......
......@@ -10,7 +10,7 @@
#import "FUSLiveHelper.h"
#import "FUSLiveHttpHelper.h"
static NSInteger const FUSLiveGiftInteractMaxItemCount = 6;
static NSInteger const FUSLiveGiftInteractMaxItemCount = 20;
@interface FUSLiveGiftInteractSettingViewController () <UITableViewDataSource, UITableViewDelegate>
......
......@@ -17,6 +17,8 @@ NS_ASSUME_NONNULL_BEGIN
@property (nonatomic, copy) NSString *giftName;
/// 礼物数量集合
@property (nonatomic, copy) NSArray<NSNumber *> *giftNumList;
/// 礼物价格
@property (nonatomic, assign) NSInteger giftPrice;
@end
......
......@@ -7,4 +7,14 @@
@implementation FUSLiveGiftInteractOptionModel
- (BOOL)modelCustomTransformFromDictionary:(NSDictionary *)dic {
if ([self.giftName isKindOfClass:[NSString class]] && self.giftName.length > 0) {
NSString *decodedName = [self.giftName stringByRemovingPercentEncoding];
if (decodedName) {
self.giftName = decodedName;
}
}
return YES;
}
@end
......@@ -73,7 +73,10 @@
NSString *name = model.giftName.length ? model.giftName : [NSString fus_localString:@"礼物"];
self.nameLabel.text = name;
[self.giftImageView setWebImageWithSubURLString:model.giftIcon];
self.priceButton.hidden = YES;
self.priceButton.hidden = NO;
[self.priceButton setTitle:[NSString stringWithFormat:@" %zd", model.giftPrice] forState:UIControlStateNormal];
self.selectedBackgroundView.hidden = !selected;
}
......
......@@ -29,7 +29,6 @@
#import "FUSPayRoomEntryMainView.h"
#import "FUSPayRoomFrostedGlassDataModel.h"
#import "FUSPayRoomCompanionDataModel.h"
#import "FUSPayRoomCompanionPopView.h"
#import "FUSRechargeViewController.h"
#import "FUSLiveShowTimeAudienceEntryMainView.h"
......@@ -51,9 +50,7 @@ static NSString *const KLiveDataCenter_store_liveRTCData = @"LiveDataCenter_stor
@property (nonatomic, strong) NSTimer *pushStreamSwitchTimer;
/// 付费屋 /payRoom/payViewing 接口返回的陪伴信息缓存(用于进房后弹窗展示)
@property (nonatomic, strong) FUSPayRoomCompanionDataModel *payRoomCompanionDataModel;
@property (nonatomic, assign) NSInteger payRoomUnitPricePerMinute;
@property (nonatomic, assign) NSInteger payRoomBillingTimeMinutes;
@property (nonatomic, strong) FUSPayRoomFrostedGlassDataModel *payRoomCompanionPayloadModel;
// 直播间 Controller,弱引用
@property (nonatomic, strong) FUSLiveMainViewController *liveVC;
......@@ -77,6 +74,10 @@ static NSString *const KLiveDataCenter_store_liveRTCData = @"LiveDataCenter_stor
@property (nonatomic, strong) UIButton *payRoomPreviewCountdownButton;
/// 付费房试看剩余秒数(用于驱动按钮文案与自动结束)
@property (nonatomic, assign) NSInteger payRoomPreviewCountdownSeconds;
/// 付费房试看的 channelId(结束时回传)
@property (nonatomic, copy) NSString *payRoomPreviewChannelId;
/// 付费房试看的 roundId(结束时回传)
@property (nonatomic, copy) NSString *payRoomPreviewRoundId;
@property (nonatomic, strong) dispatch_source_t payRoomRenewalCountdownTimer;
@property (nonatomic, assign) NSInteger payRoomRenewalCountdownSeconds;
......@@ -1177,6 +1178,17 @@ static NSString *const KLiveDataCenter_store_liveRTCData = @"LiveDataCenter_stor
NSDictionary *payload = ([dataDict[@"data"] isKindOfClass:NSDictionary.class] ? dataDict[@"data"] : dataDict);
FUSPayRoomFrostedGlassDataModel *dataModel = [FUSPayRoomFrostedGlassDataModel fus_modelWithDict:(payload ?: @{})];
if (strongSelf.roomInfoModel) {
NSString *newChannelId = [dataModel.roomData.channelId description];
NSString *newRoundId = [dataModel.roomData.roundId description];
if (![NSString isNull:newChannelId]) {
strongSelf.roomInfoModel.channelId = newChannelId;
}
if (![NSString isNull:newRoundId]) {
strongSelf.roomInfoModel.roundId = newRoundId;
}
}
FUSPayRoomEntryMainViewModel *viewModel = [[FUSPayRoomEntryMainViewModel alloc] init];
NSString *introduce = [dataModel.roomData.introduce description];
NSString *nick = [dataModel.roomData.nickName description];
......@@ -1199,14 +1211,12 @@ static NSString *const KLiveDataCenter_store_liveRTCData = @"LiveDataCenter_stor
viewModel.accompanyUserFacePaths = facePaths.copy;
NSInteger pricePerMinute = dataModel.payRoomConfigData.payUnitPrice;
NSInteger billingTime = dataModel.payRoomConfigData.billingTime;
NSInteger canCompanionTime = dataModel.userData.canCompanionTime;
NSInteger previewTime = dataModel.payRoomConfigData.previewTime;
BOOL diamondEnough = (dataModel.userData.isDiamondEnough > 0);
viewModel.primaryButtonTitle = (diamondEnough ? [NSString fus_localString:@"进入陪伴"] : [NSString fus_localString:@"马上储值进入陪伴"]);
strongSelf.payRoomUnitPricePerMinute = MAX(0, pricePerMinute);
strongSelf.payRoomBillingTimeMinutes = MAX(0, billingTime);
strongSelf.payRoomCompanionPayloadModel = nil;
viewModel.trialButtonHidden = (previewTime <= 0);
if (previewTime > 0) {
......@@ -1258,6 +1268,13 @@ static NSString *const KLiveDataCenter_store_liveRTCData = @"LiveDataCenter_stor
*/
- (void)fus_endPayRoomPreviewWithRoomId:(NSString *)roomId
{
NSString *uid = [[FUSCacheDataShare shareStore].userVerifyInfo.uid description] ?: @"";
NSString *channelId = self.payRoomPreviewChannelId ?: (self.roomInfoModel.channelId ?: @"");
NSString *roundId = self.payRoomPreviewRoundId ?: (self.roomInfoModel.roundId ?: @"");
// 通知服务端结束试看
[FUSLiveHttpHelper fus_requestPayRoomPreviewWithUid:uid RoomId:(roomId ?: @"") previewType:@"0" channelId:channelId roundId:roundId succeed:nil failure:nil];
dispatch_async(dispatch_get_main_queue(), ^{
[self fus_stopPayRoomPreviewCountdown];
[self.liveVC fus_showLiveLoadingViewWithType:liveLoadingDismiss];
......@@ -1315,11 +1332,14 @@ static NSString *const KLiveDataCenter_store_liveRTCData = @"LiveDataCenter_stor
}
- (void)fus_requestPayRoomPreviewWithUid:(NSString *)uid
roomId:(NSString *)roomId
channelId:(NSString *)channelId
roundId:(NSString *)roundId
entryView:(FUSPayRoomEntryMainView *)entryView
roomId:(NSString *)roomId
channelId:(NSString *)channelId
roundId:(NSString *)roundId
entryView:(FUSPayRoomEntryMainView *)entryView
{
self.payRoomPreviewChannelId = channelId;
self.payRoomPreviewRoundId = roundId;
/**
付费房试看:请求 /payRoom/preview,拿到 pullUrl 后切换到“纯播放”模式。
......@@ -1369,12 +1389,8 @@ static NSString *const KLiveDataCenter_store_liveRTCData = @"LiveDataCenter_stor
return;
}
NSDictionary *companionData = [FUSHttpHelper fus_parseJSONDictionaryLayerByLayerWithObject:dataDict[@"companionData"]];
if (![NSDictionary isNull:companionData]) {
strongSelf.payRoomCompanionDataModel = [FUSPayRoomCompanionDataModel fus_modelWithDict:companionData];
} else {
strongSelf.payRoomCompanionDataModel = nil;
}
NSDictionary *payload = ([dataDict[@"data"] isKindOfClass:NSDictionary.class] ? dataDict[@"data"] : dataDict);
strongSelf.payRoomCompanionPayloadModel = [FUSPayRoomFrostedGlassDataModel fus_modelWithDict:(payload ?: @{})];
dispatch_async(dispatch_get_main_queue(), ^{
[weakEntryView fus_dismissAnimated:YES];
......@@ -1408,15 +1424,11 @@ static NSString *const KLiveDataCenter_store_liveRTCData = @"LiveDataCenter_stor
return;
}
/// 如果接口未返回数据,也给一个空模型兜底,保证 UI 可展示
FUSPayRoomCompanionDataModel *dataModel = self.payRoomCompanionDataModel;
if (!dataModel) {
dataModel = [[FUSPayRoomCompanionDataModel alloc] init];
FUSPayRoomFrostedGlassDataModel *payRoomDataModel = self.payRoomCompanionPayloadModel;
if (!payRoomDataModel) {
payRoomDataModel = [[FUSPayRoomFrostedGlassDataModel alloc] init];
}
FUSPayRoomCompanionPopView *popView = [FUSPayRoomCompanionPopView fus_showWithRootView:rootView companionData:dataModel];
popView.unitPricePerMinute = self.payRoomUnitPricePerMinute;
popView.billingTimeMinutes = self.payRoomBillingTimeMinutes;
FUSPayRoomCompanionPopView *popView = [FUSPayRoomCompanionPopView fus_showWithRootView:rootView payRoomData:payRoomDataModel];
__weak typeof(self) weakSelf = self;
popView.rechargeHandler = ^{
/// 去充值:复用全局充值页入口
......@@ -1424,7 +1436,7 @@ static NSString *const KLiveDataCenter_store_liveRTCData = @"LiveDataCenter_stor
if (topVC) {
[FUSRechargeViewController fus_showRechargeViewControllerForRootVC:topVC];
}
weakSelf.payRoomCompanionDataModel = nil;
weakSelf.payRoomCompanionPayloadModel = nil;
};
[self fus_startPayRoomRenewalCountdownWithRoomId:(roomId ?: @"")];
......@@ -1555,6 +1567,8 @@ static NSString *const KLiveDataCenter_store_liveRTCData = @"LiveDataCenter_stor
self.payRoomPreviewCountdownButton = nil;
self.payRoomPreviewCountdownSeconds = 0;
self.payRoomPreviewChannelId = nil;
self.payRoomPreviewRoundId = nil;
}
/// 获取当前展示中的“陪伴弹窗”(仅付费房场景存在,存在则用于进度与数据刷新)
......@@ -1674,17 +1688,14 @@ static NSString *const KLiveDataCenter_store_liveRTCData = @"LiveDataCenter_stor
return;
}
NSDictionary *companionData = [FUSHttpHelper fus_parseJSONDictionaryLayerByLayerWithObject:dataDict[@"companionData"]];
if ([NSDictionary isNull:companionData]) {
return;
}
FUSPayRoomCompanionDataModel *model = [FUSPayRoomCompanionDataModel fus_modelWithDict:companionData];
strongSelf.payRoomCompanionDataModel = model;
NSDictionary *payload = ([dataDict[@"data"] isKindOfClass:NSDictionary.class] ? dataDict[@"data"] : dataDict);
FUSPayRoomFrostedGlassDataModel *model = [FUSPayRoomFrostedGlassDataModel fus_modelWithDict:(payload ?: @{})];
strongSelf.payRoomCompanionPayloadModel = model;
dispatch_async(dispatch_get_main_queue(), ^{
FUSPayRoomCompanionPopView *popView = [strongSelf fus_currentPayRoomCompanionPopView];
if (popView) {
[popView fus_updateWithCompanionData:model];
[popView fus_updateWithPayRoomData:model];
}
});
} failure:^(NSString *msg, NSInteger code) {
......
......@@ -457,6 +457,23 @@
NSDictionary *payload = jsonDict;
NSInteger dataType = [payload[@"dataType"] integerValue];
if (dataType == 5) {
dispatch_async(dispatch_get_main_queue(), ^{
NSString *showTheme = [NSString stringWithObject:payload[@"showTheme"]];
if ([NSString isNull:showTheme]) {
showTheme = @"";
} else {
NSString *decodedTheme = [showTheme stringByRemovingPercentEncoding];
if (![NSString isNull:decodedTheme]) {
showTheme = decodedTheme;
}
}
FUSLiveHelper.shareInstance.roomInfoModel.introduce = showTheme;
[[FUSLiveHelper shareInstance].currentFunctionView fus_refreshLiveTopicWindow];
[self.showTimeFrostedView fus_updateThemeText:showTheme];
});
return;
}
if (dataType == 9999) {
dispatch_async(dispatch_get_main_queue(), ^{
[self fus_destroyShowTimeFrostedIfNeeded];
......@@ -513,8 +530,8 @@
if (FUSLiveHelper.shareInstance.liveType == FUSLiveTypeAudience && dataType == 2) {
return;
}
// 主播端只处理 dataType=4 的推送
if (FUSLiveHelper.shareInstance.liveType == FUSLiveTypeAnchor && dataType != 4) {
// 主播端只处理 dataType=4 和 dataType=3 的推送
if (FUSLiveHelper.shareInstance.liveType == FUSLiveTypeAnchor && dataType != 4 && dataType != 3) {
return;
}
......@@ -759,7 +776,7 @@
NSInteger remaining = MAX(0, target - finalNum);
CGFloat progress = (target > 0 ? ((CGFloat)finalNum / (CGFloat)target) : 0);
NSString *remainingText = nil;
if (stageStatus == 2 || stageStatus == 1) {
if (stageStatus == 2) {
remainingText = [NSString stringWithFormat:[NSString fus_localString:@"已集票数 %zd 张!"], (NSInteger)finalNum];
progress = 1.0;
} else {
......@@ -806,11 +823,14 @@
// MVP 用户信息用于右侧头像展示(无则不展示)
FUSOnlineUserModel *mvpUser = model.mvpInfo.mvpUserInfo;
NSInteger remainMs = (model.stageData ? model.stageData.remaintime : model.remaintime);
// 只拿 remaintime 作为剩余时间,总时间直接传 -1 让内部兜底或仅依赖 remaintime 计算
NSInteger totalSeconds = -1;
NSInteger remainSeconds = (remainMs > 0 ? (NSInteger)llround(((NSTimeInterval)remainMs) / 1000.0) : -1);
if (bar.displayMode == FUSLiveShowTimeCollectFrostedDisplayModeAudience) {
NSInteger durationMs = (model.stageData ? model.stageData.showStatusTime : model.showStatusTime);
NSInteger remainMs = (model.stageData ? model.stageData.remaintime : model.remaintime);
NSInteger totalSeconds = (durationMs > 0 ? (NSInteger)llround(((NSTimeInterval)durationMs) / 1000.0) : -1);
NSInteger remainSeconds = (remainMs >= 0 ? (NSInteger)llround(((NSTimeInterval)remainMs) / 1000.0) : -1);
self.showTimeCountdownRemainSeconds = remainSeconds;
[bar fus_updateAudienceWithState:showState
themeText:themeText
......@@ -821,6 +841,9 @@
newTicketCount:newTicketCount
giftUserModel:giftUser
mvpUserModel:mvpUser];
if (dataType == 3 || stageStatus == 0) {
[bar fus_syncCountdownTotalSeconds:totalSeconds countdownRemainingSeconds:remainSeconds];
}
} else {
[bar fus_updateWithState:showState
themeText:themeText
......@@ -829,11 +852,10 @@
newTicketCount:newTicketCount
giftUserModel:giftUser
mvpUserModel:mvpUser];
if (stageStatus == 2) {
NSInteger durationMs = (model.stageData ? model.stageData.showStatusTime : model.showStatusTime);
NSInteger remainMs = (model.stageData ? model.stageData.remaintime : model.remaintime);
NSInteger totalSeconds = (durationMs > 0 ? (NSInteger)llround(((NSTimeInterval)durationMs) / 1000.0) : -1);
NSInteger remainSeconds = (remainMs >= 0 ? (NSInteger)llround(((NSTimeInterval)remainMs) / 1000.0) : -1);
// 主播端无论是 11038 推送还是发起集票,只要有时间数据就同步
if (remainSeconds > 0) {
[bar fus_syncCountdownTotalSeconds:totalSeconds countdownRemainingSeconds:remainSeconds];
} else if (stageStatus == 2 || dataType == 3) {
[bar fus_syncCountdownTotalSeconds:totalSeconds countdownRemainingSeconds:remainSeconds];
}
}
......@@ -1378,12 +1400,21 @@
FUSLiveHelper.shareInstance.roomInfoModel.introduce = updateTheme;
}
NSInteger remainMs = (model.stageData ? model.stageData.remaintime : model.remaintime);
NSInteger totalSeconds = -1;
NSInteger remainSeconds = (remainMs > 0 ? (NSInteger)llround(((NSTimeInterval)remainMs) / 1000.0) : -1);
[bar fus_updateWithState:FUSLiveShowTimeCollectFrostedStateStarted
themeText:updateTheme
progress:progress
remainingText:remainingText
newTicketCount:0
userModel:nil];
giftUserModel:nil
mvpUserModel:model.mvpInfo.mvpUserInfo];
if (remainSeconds > 0) {
[bar fus_syncCountdownTotalSeconds:totalSeconds countdownRemainingSeconds:remainSeconds];
}
});
} failure:^(NSString * _Nonnull msg, NSInteger code) {
dispatch_async(dispatch_get_main_queue(), ^{
......@@ -1800,7 +1831,7 @@
NSInteger remaining = MAX(0, target - finalNum);
CGFloat progress = MIN(1.0, MAX(0.0, (CGFloat)finalNum / (CGFloat)target));
NSString *remainingText = nil;
if (stageStatus == 2 || stageStatus == 1) {
if (stageStatus == 2) {
remainingText = [NSString stringWithFormat:[NSString fus_localString:@"已集票数 %zd 张!"], (NSInteger)finalNum];
progress = 1.0;
} else {
......@@ -1819,13 +1850,9 @@
currentBar.stageStatus = stageStatus;
currentBar.actionTitle = ([NSString stringWithObject:model.mvpInfo.mvpUserId].length > 0 ? [NSString fus_localString:@"抢当MVP"] : [NSString fus_localString:@"购票支持"]);
NSInteger durationMs = (model.stageData ? model.stageData.showStatusTime : model.showStatusTime);
NSInteger remainMs = (model.stageData ? model.stageData.remaintime : model.remaintime);
NSInteger totalSeconds = (durationMs > 0 ? (NSInteger)llround(((NSTimeInterval)durationMs) / 1000.0) : -1);
NSInteger remainSeconds = -1;
if (durationMs > 0 && remainMs >= 0 && remainMs <= durationMs) {
remainSeconds = (NSInteger)llround(((NSTimeInterval)remainMs) / 1000.0);
}
NSInteger totalSeconds = -1;
NSInteger remainSeconds = (remainMs > 0 ? (NSInteger)llround(((NSTimeInterval)remainMs) / 1000.0) : -1);
strongSelf.showTimeCountdownRemainSeconds = remainSeconds;
FUSLiveShowTimeCollectFrostedState showState = FUSLiveShowTimeCollectFrostedStateStarted;
......@@ -1862,9 +1889,9 @@
NSString *resolvedRoomId = (model.stageData.roomId.length > 0 ? model.stageData.roomId : (model.roomId.length > 0 ? model.roomId : roomInfoModel.roomId));
NSString *resolvedChannelId = (model.stageData.channelId.length > 0 ? model.stageData.channelId : (model.channelId.length > 0 ? model.channelId : roomInfoModel.channelId));
NSString *resolvedRoundId = self.showTimeRoundId;
NSString *resolvedRoundId = (model.stageData.roundId.length > 0 ? model.stageData.roundId : model.roundId);
if ([NSString isNull:resolvedRoundId]) {
resolvedRoundId = (model.stageData.roundId.length > 0 ? model.stageData.roundId : model.roundId);
resolvedRoundId = self.showTimeRoundId;
}
if ([NSString isNull:resolvedRoomId] || [NSString isNull:resolvedChannelId] || [NSString isNull:resolvedRoundId]) {
......@@ -1919,7 +1946,7 @@
NSInteger remaining = MAX(0, target - finalNum);
CGFloat progress = MIN(1.0, MAX(0.0, (CGFloat)finalNum / (CGFloat)target));
NSString *remainingText = nil;
if (stageStatus == 2 || stageStatus == 1) {
if (stageStatus == 2) {
remainingText = [NSString stringWithFormat:[NSString fus_localString:@"已集票数 %zd 张!"], (NSInteger)finalNum];
progress = 1.0;
} else {
......@@ -1965,6 +1992,9 @@
newTicketCount:0
giftUserModel:startModel.buyUser
mvpUserModel:startModel.mvpInfo.mvpUserInfo];
if (stageStatus == 2) {
[bar fus_syncCountdownTotalSeconds:totalSeconds countdownRemainingSeconds:remainSeconds];
}
}
}
}
......
......@@ -86,6 +86,10 @@ typedef NS_ENUM(NSInteger, FUSLiveShowTimeCollectFrostedAvatarTapType) {
- (void)fus_updateTopTicketInfoWithGiftUserModel:(FUSOnlineUserModel * _Nullable)giftUserModel
newTicketCount:(NSInteger)newTicketCount;
/// 仅更新磨砂条标题文案(例如 11038 dataType=5 的 showTheme 变更)
/// @param themeText 最新主题文案,支持 URL 编码字符串
- (void)fus_updateThemeText:(NSString *)themeText;
/// 取消按钮点击回调(预留服务端入口)
@property (nonatomic, copy, nullable) void (^cancelHandler)(void);
......
......@@ -98,6 +98,8 @@ static const NSInteger kFUSShowTimeCollectSeconds = 60 * 10;
@property (nonatomic, assign) NSInteger countdownStageStatus;
/// 当前阶段倒计时总时长(秒)
@property (nonatomic, assign) NSInteger countdownTotalSeconds;
/// 距离结束剩余秒数
@property (nonatomic, assign) NSInteger countdownRemainingSeconds;
/// 倒计时刷新计时器
@property (nonatomic, strong) dispatch_source_t countdownTimer;
......@@ -193,7 +195,7 @@ static const NSInteger kFUSShowTimeCollectSeconds = 60 * 10;
self.showTimeNewTicketLabel = [[UILabel alloc] init];
self.showTimeNewTicketLabel.font = [UIFont fus_themeBoldFont:12];
self.showTimeNewTicketLabel.textColor = [UIColor colorWithWhite:1 alpha:0.9];
self.showTimeNewTicketLabel.textColor = [UIColor colorWithHex:@"#52DDE2"];
self.showTimeNewTicketLabel.hidden = YES;
[self.topTicketInfoContainerView addSubview:self.showTimeNewTicketLabel];
self.lastNewTicketCount = 0;
......@@ -257,7 +259,7 @@ static const NSInteger kFUSShowTimeCollectSeconds = 60 * 10;
self.countdownLabel = [[UILabel alloc] init];
self.countdownLabel.font = [UIFont fus_themeFont:12];
self.countdownLabel.textColor = [UIColor colorWithWhite:1 alpha:0.85];
self.countdownLabel.textAlignment = NSTextAlignmentRight;
self.countdownLabel.textAlignment = NSTextAlignmentLeft;
self.countdownLabel.text = @"";
[self.blurView.contentView addSubview:self.countdownLabel];
......@@ -485,7 +487,11 @@ static const NSInteger kFUSShowTimeCollectSeconds = 60 * 10;
self.progressLabel.text = [NSString stringWithFormat:@"%zd%%", (NSInteger)llround(clamped * 100)];
}
self.remainingLabel.text = (remainingText.length > 0 ? remainingText : @"");
[self fus_updateRemainingLabelWithText:(remainingText.length > 0 ? remainingText : @"")];
if (self.stageStatus == 2) {
[self fus_updateRemainingLabelWithText:[NSString fus_localString:@"表演结束倒数"]];
}
if (state == FUSLiveShowTimeCollectFrostedStateCompleted) {
self.startTimestamp = 0;
self.countdownStageStatus = -1;
......@@ -506,7 +512,7 @@ static const NSInteger kFUSShowTimeCollectSeconds = 60 * 10;
}
if (state == FUSLiveShowTimeCollectFrostedStateCompleted) {
self.remainingLabel.text = [NSString fus_localString:@"已集票满 50 张!"];
[self fus_updateRemainingLabelWithText:[NSString fus_localString:@"已集票满 50 张!"]];
self.progressLayer.strokeEnd = 1.0;
self.progressLabel.text = @"100%";
self.countdownLabel.text = @"00:00";
......@@ -590,6 +596,38 @@ static const NSInteger kFUSShowTimeCollectSeconds = 60 * 10;
self.lastGiftUserUid = (candidateUid ?: @"");
}
/// 只改标题,不改进度/倒计时/顶部上票信息,避免主题更新影响当前集票状态
- (void)fus_updateThemeText:(NSString *)themeText {
NSString *decodedThemeText = nil;
if (themeText.length > 0) {
decodedThemeText = themeText.stringByRemovingPercentEncoding ?: themeText;
}
NSString *finalThemeText = (decodedThemeText.length > 0 ? decodedThemeText : [NSString fus_localString:@"限时表演"]);
if (![self.themeLabel.text isEqualToString:finalThemeText]) {
[self.themeLabel setText:finalThemeText refreshLabels:YES];
}
}
- (void)fus_updateRemainingLabelWithText:(NSString *)text {
NSString *displayText = (text.length > 0 ? text : @"");
NSDictionary *baseAttributes = @{
NSForegroundColorAttributeName: [UIColor colorWithWhite:1 alpha:0.85]
};
NSMutableAttributedString *attributedText = [[NSMutableAttributedString alloc] initWithString:displayText attributes:baseAttributes];
[displayText enumerateSubstringsInRange:NSMakeRange(0, displayText.length)
options:NSStringEnumerationByComposedCharacterSequences
usingBlock:^(NSString * _Nullable substring, NSRange substringRange, NSRange enclosingRange, BOOL * _Nonnull stop) {
if (substring.length == 0) {
return;
}
unichar c = [substring characterAtIndex:0];
if ([[NSCharacterSet decimalDigitCharacterSet] characterIsMember:c]) {
[attributedText addAttribute:NSForegroundColorAttributeName value:[UIColor colorWithHex:@"#52DDE2"] range:substringRange];
}
}];
self.remainingLabel.attributedText = attributedText;
}
/// 新用户到来时,顶部上票信息从右侧滑入并渐显
- (void)fus_playTopTicketInfoContainerEnterAnimation {
[self.topTicketInfoContainerView.layer removeAllAnimations];
......@@ -633,6 +671,7 @@ static const NSInteger kFUSShowTimeCollectSeconds = 60 * 10;
- (void)fus_syncCountdownTotalSeconds:(NSInteger)countdownTotalSeconds
countdownRemainingSeconds:(NSInteger)countdownRemainingSeconds {
self.countdownRemainingSeconds = countdownRemainingSeconds;
if (countdownRemainingSeconds < 0) {
return;
}
......@@ -640,18 +679,9 @@ static const NSInteger kFUSShowTimeCollectSeconds = 60 * 10;
[self fus_stopCountdownTimer];
}
NSInteger totalSeconds = countdownTotalSeconds;
if (totalSeconds <= 0) {
totalSeconds = MAX(kFUSShowTimeCollectSeconds, countdownRemainingSeconds);
} else {
totalSeconds = MAX(totalSeconds, countdownRemainingSeconds);
}
self.countdownTotalSeconds = totalSeconds;
NSInteger remainSeconds = MAX(0, MIN(totalSeconds, countdownRemainingSeconds));
// 直接以当前时间为基准,倒计时只看 countdownRemainingSeconds
NSTimeInterval nowSec = [[NSDate date] timeIntervalSince1970];
NSTimeInterval base = nowSec - MAX(0, (NSTimeInterval)totalSeconds - (NSTimeInterval)remainSeconds);
self.startTimestamp = base;
self.startTimestamp = nowSec;
self.countdownStageStatus = self.stageStatus;
[self fus_startCountdownTimerIfNeeded];
}
......@@ -739,8 +769,16 @@ static const NSInteger kFUSShowTimeCollectSeconds = 60 * 10;
NSTimeInterval now = [[NSDate date] timeIntervalSince1970];
NSTimeInterval elapsed = MAX(0, now - self.startTimestamp);
NSInteger totalSeconds = (self.countdownTotalSeconds > 0 ? self.countdownTotalSeconds : kFUSShowTimeCollectSeconds);
NSInteger remain = (NSInteger)llround(MAX(0, (NSTimeInterval)totalSeconds - elapsed));
NSInteger remain = -1;
if (self.countdownRemainingSeconds > 0) {
// 如果后端下发了剩余时间,以此为准扣减流逝时间
remain = (NSInteger)llround(MAX(0, (NSTimeInterval)self.countdownRemainingSeconds - elapsed));
} else {
// 兜底 10 分钟
remain = (NSInteger)llround(MAX(0, 600.0 - elapsed));
}
if (remain <= 0) {
self.countdownLabel.text = @"00:00";
[self fus_stopCountdownTimer];
......
......@@ -29,7 +29,7 @@ static const NSInteger kFUSShowTimeTicketMax = 50;
/// 减号按钮
@property (nonatomic, strong) UIButton *subBtn;
/// 数量展示
@property (nonatomic, strong) UILabel *countLabel;
@property (nonatomic, strong) UITextField *countTextField;
/// 加号按钮
@property (nonatomic, strong) UIButton *addBtn;
......@@ -140,25 +140,25 @@ static const NSInteger kFUSShowTimeTicketMax = 50;
[self.subBtn addTarget:self action:@selector(fus_onClickSub) forControlEvents:UIControlEventTouchUpInside];
[self.contentView addSubview:self.subBtn];
self.countLabel = [[UILabel alloc] initWithFrame:CGRectMake(self.subBtn.right + space, 0, countW, controlH)];
self.countLabel.textAlignment = NSTextAlignmentCenter;
self.countLabel.font = [UIFont fus_themeBoldFont:16];
self.countLabel.textColor = [UIColor colorWithHex:@"#333333"];
self.countLabel.centerY = self.subBtn.centerY;
self.countLabel.userInteractionEnabled = YES;
UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(fus_onTapCount)];
[self.countLabel addGestureRecognizer:tap];
[self.contentView addSubview:self.countLabel];
self.countTextField = [[UITextField alloc] initWithFrame:CGRectMake(self.subBtn.right + space, 0, countW, controlH)];
self.countTextField.textAlignment = NSTextAlignmentCenter;
self.countTextField.font = [UIFont fus_themeBoldFont:16];
self.countTextField.textColor = [UIColor colorWithHex:@"#333333"];
self.countTextField.keyboardType = UIKeyboardTypeNumberPad;
self.countTextField.centerY = self.subBtn.centerY;
[self.countTextField addTarget:self action:@selector(fus_textFieldDidChange:) forControlEvents:UIControlEventEditingChanged];
[self.countTextField addTarget:self action:@selector(fus_textFieldDidEndEditing:) forControlEvents:UIControlEventEditingDidEnd];
[self.contentView addSubview:self.countTextField];
[self fus_refreshCountUI];
self.addBtn = [UIButton buttonWithType:UIButtonTypeCustom];
self.addBtn.frame = CGRectMake(self.countLabel.right + space, 0, btnSize, btnSize);
self.addBtn.frame = CGRectMake(self.countTextField.right + space, 0, btnSize, btnSize);
self.addBtn.centerY = self.subBtn.centerY;
[self.addBtn setImage:[FUSShowRoomCenterBunble imageNamed:@"Live_bottom_add"] forState:UIControlStateNormal];
[self.addBtn addTarget:self action:@selector(fus_onClickAdd) forControlEvents:UIControlEventTouchUpInside];
[self.contentView addSubview:self.addBtn];
self.tipLabel = [[UILabel alloc] initWithFrame:CGRectMake(24, self.countLabel.bottom + 12, self.contentView.width - 48, 18)];
self.tipLabel = [[UILabel alloc] initWithFrame:CGRectMake(24, self.countTextField.bottom + 12, self.contentView.width - 48, 18)];
self.tipLabel.textAlignment = NSTextAlignmentCenter;
self.tipLabel.font = [UIFont fus_themeFont:12];
self.tipLabel.textColor = [UIColor colorWithHex:@"#9AA0A6"];
......@@ -262,7 +262,7 @@ static const NSInteger kFUSShowTimeTicketMax = 50;
/// 刷新数量与按钮可用态
- (void)fus_refreshCountUI {
self.countLabel.text = [NSString stringWithFormat:@"%zd", self.ticketCount];
self.countTextField.text = [NSString stringWithFormat:@"%zd", self.ticketCount];
self.subBtn.enabled = YES;
}
......@@ -295,32 +295,14 @@ static const NSInteger kFUSShowTimeTicketMax = 50;
}
}
/// 点击中间数字:弹出输入框填写具体票数
- (void)fus_onTapCount {
UIViewController *topVC = [UIViewController fus_topViewController];
if (!topVC) {
return;
}
UIAlertController *alert = [UIAlertController alertControllerWithTitle:[NSString fus_localString:@"填写票数"]
message:nil
preferredStyle:UIAlertControllerStyleAlert];
__weak typeof(self) weakSelf = self;
[alert addTextFieldWithConfigurationHandler:^(UITextField * _Nonnull textField) {
textField.keyboardType = UIKeyboardTypeNumberPad;
textField.text = [NSString stringWithFormat:@"%zd", weakSelf.ticketCount];
}];
[alert addAction:[UIAlertAction actionWithTitle:[NSString fus_localString:@"取消"]
style:UIAlertActionStyleCancel
handler:nil]];
[alert addAction:[UIAlertAction actionWithTitle:[NSString fus_localString:@"确定"]
style:UIAlertActionStyleDefault
handler:^(UIAlertAction * _Nonnull action) {
NSString *text = alert.textFields.firstObject.text ?: @"";
NSInteger value = text.integerValue;
[weakSelf fus_setTicketCount:value showTipIfOutOfRange:YES];
}]];
[topVC presentViewController:alert animated:YES completion:nil];
- (void)fus_textFieldDidChange:(UITextField *)textField {
// 可以在这里实时限制输入长度或去除非数字字符
// 注意:不要在这里直接修改 self.ticketCount 导致触发 UI 刷新,影响输入体验
}
- (void)fus_textFieldDidEndEditing:(UITextField *)textField {
NSInteger value = textField.text.integerValue;
[self fus_setTicketCount:value showTipIfOutOfRange:YES];
}
/// 尝试按步长调整票数,超过边界时提示并保持在边界值
......
......@@ -118,23 +118,22 @@
make.width.height.mas_equalTo(40);
}];
[_ticketIconView mas_makeConstraints:^(MASConstraintMaker *make) {
[_countLabel mas_makeConstraints:^(MASConstraintMaker *make) {
make.right.equalTo(self.contentView).offset(-16);
make.centerY.equalTo(self.contentView);
make.width.mas_equalTo(30);
make.height.mas_equalTo(16);
}];
[_countLabel mas_makeConstraints:^(MASConstraintMaker *make) {
make.right.equalTo(_ticketIconView.mas_left).offset(-6);
[_ticketIconView mas_makeConstraints:^(MASConstraintMaker *make) {
make.right.equalTo(_countLabel.mas_left).offset(-6);
make.centerY.equalTo(self.contentView);
make.width.mas_greaterThanOrEqualTo(40);
make.width.mas_equalTo(30);
make.height.mas_equalTo(16);
}];
[_nicknameLabel mas_makeConstraints:^(MASConstraintMaker *make) {
make.left.equalTo(_faceImageView.mas_right).offset(10);
make.top.equalTo(self.contentView).offset(12);
make.right.lessThanOrEqualTo(_countLabel.mas_left).offset(-10);
make.right.lessThanOrEqualTo(_ticketIconView.mas_left).offset(-10);
}];
[_onlineLabel mas_makeConstraints:^(MASConstraintMaker *make) {
......@@ -142,21 +141,21 @@
make.centerY.equalTo(_nicknameLabel.mas_centerY);
make.height.mas_equalTo(14);
make.width.mas_greaterThanOrEqualTo(20);
make.right.lessThanOrEqualTo(_countLabel.mas_left).offset(-10);
make.right.lessThanOrEqualTo(_ticketIconView.mas_left).offset(-10);
}];
[_vipImageView mas_makeConstraints:^(MASConstraintMaker *make) {
make.left.equalTo(_onlineLabel.mas_right).offset(4);
make.centerY.equalTo(_nicknameLabel.mas_centerY);
make.width.height.mas_equalTo(14);
make.right.lessThanOrEqualTo(_countLabel.mas_left).offset(-10);
make.right.lessThanOrEqualTo(_ticketIconView.mas_left).offset(-10);
}];
[_newImageView mas_makeConstraints:^(MASConstraintMaker *make) {
make.left.equalTo(_vipImageView.mas_right).offset(4);
make.centerY.equalTo(_nicknameLabel.mas_centerY);
make.width.height.mas_equalTo(0);
make.right.lessThanOrEqualTo(_countLabel.mas_left).offset(-10);
make.right.lessThanOrEqualTo(_ticketIconView.mas_left).offset(-10);
}];
[_firstLoveImageView mas_makeConstraints:^(MASConstraintMaker *make) {
......@@ -164,7 +163,7 @@
make.centerY.equalTo(_nicknameLabel.mas_centerY);
make.width.mas_equalTo(32);
make.height.mas_equalTo(11);
make.right.lessThanOrEqualTo(_countLabel.mas_left).offset(-10);
make.right.lessThanOrEqualTo(_ticketIconView.mas_left).offset(-10);
}];
[_mvpImageView mas_makeConstraints:^(MASConstraintMaker *make) {
......@@ -270,13 +269,13 @@
make.centerY.equalTo(_nicknameLabel.mas_centerY);
make.height.mas_equalTo(14);
make.width.mas_greaterThanOrEqualTo(20);
make.right.lessThanOrEqualTo(_countLabel.mas_left).offset(-10);
make.right.lessThanOrEqualTo(_ticketIconView.mas_left).offset(-10);
}];
[_vipImageView mas_remakeConstraints:^(MASConstraintMaker *make) {
make.left.equalTo(_onlineLabel.mas_right).offset(4);
make.centerY.equalTo(_nicknameLabel.mas_centerY);
make.right.lessThanOrEqualTo(_countLabel.mas_left).offset(-10);
make.right.lessThanOrEqualTo(_ticketIconView.mas_left).offset(-10);
if (!showVip) {
make.width.height.mas_equalTo(0);
return;
......@@ -289,7 +288,7 @@
UIView *leftView = (showVip ? _vipImageView : _onlineLabel);
make.left.equalTo(leftView.mas_right).offset(4);
make.centerY.equalTo(_nicknameLabel.mas_centerY);
make.right.lessThanOrEqualTo(_countLabel.mas_left).offset(-10);
make.right.lessThanOrEqualTo(_ticketIconView.mas_left).offset(-10);
if (showNew) {
make.width.height.mas_equalTo(20);
} else {
......@@ -303,7 +302,7 @@
make.centerY.equalTo(_nicknameLabel.mas_centerY);
make.width.mas_equalTo(isFirstCharge ? 32 : 0);
make.height.mas_equalTo(isFirstCharge ? 11 : 0);
make.right.lessThanOrEqualTo(_countLabel.mas_left).offset(-10);
make.right.lessThanOrEqualTo(_ticketIconView.mas_left).offset(-10);
}];
// MVP Icon remains below avatar, no need to remake horizontal constraints
......
......@@ -253,8 +253,6 @@ NSString * const FUSLiveShowTimeAudienceEntryTicketOptionTagTextKey = @"tagText"
@interface FUSLiveShowTimeAudienceEntryMainView ()
/// 背景遮罩按钮(用于拦截触摸并支持点击关闭)
@property (nonatomic, strong) UIButton *bgBtn;
/// 右上角关闭按钮
@property (nonatomic, strong) UIButton *closeBtn;
/// 白色内容卡片容器(承载所有展示内容)
......@@ -471,11 +469,7 @@ NSString * const FUSLiveShowTimeAudienceEntryTicketOptionTagTextKey = @"tagText"
- (void)fus_buildUI {
self.alpha = 0;
self.backgroundColor = UIColor.clearColor;
self.bgBtn = [UIButton buttonWithType:UIButtonTypeCustom];
self.bgBtn.backgroundColor = [UIColor colorWithWhite:0 alpha:0.55];
[self addSubview:self.bgBtn];
self.backgroundColor = [UIColor colorWithWhite:0 alpha:0.4];
self.closeBtn = [UIButton buttonWithType:UIButtonTypeCustom];
[self.closeBtn setImage:[FUSShowRoomCenterBunble imageNamed:@"Live_room_close"] forState:UIControlStateNormal];
......@@ -483,7 +477,7 @@ NSString * const FUSLiveShowTimeAudienceEntryTicketOptionTagTextKey = @"tagText"
self.cardView = [[UIView alloc] initWithFrame:CGRectZero];
self.cardView.backgroundColor = UIColor.whiteColor;
self.cardView.layer.cornerRadius = 16;
self.cardView.layer.cornerRadius = 24;
self.cardView.layer.masksToBounds = YES;
[self addSubview:self.cardView];
......@@ -533,10 +527,6 @@ NSString * const FUSLiveShowTimeAudienceEntryTicketOptionTagTextKey = @"tagText"
self.noticeButton = [UIButton buttonWithType:UIButtonTypeCustom];
[self.cardView addSubview:self.noticeButton];
[self.bgBtn mas_makeConstraints:^(MASConstraintMaker *make) {
make.edges.equalTo(self);
}];
[self.closeBtn mas_makeConstraints:^(MASConstraintMaker *make) {
make.top.equalTo(self.mas_safeAreaLayoutGuideTop).offset(6);
make.right.equalTo(self).offset(-8);
......@@ -598,10 +588,11 @@ NSString * const FUSLiveShowTimeAudienceEntryTicketOptionTagTextKey = @"tagText"
}
- (void)fus_bindActions {
__weak typeof(self) weakSelf = self;
[self.closeBtn addTarget:self action:@selector(fus_onTapClose) forControlEvents:UIControlEventTouchUpInside];
[self.enterButton addTarget:self action:@selector(fus_onTapEnter) forControlEvents:UIControlEventTouchUpInside];
[self.noticeButton addTarget:self action:@selector(fus_onTapNotice) forControlEvents:UIControlEventTouchUpInside];
__weak typeof(self) weakSelf = self;
self.optionGroupView.selectHandler = ^(NSInteger index) {
__strong typeof(weakSelf) strongSelf = weakSelf;
......
......@@ -3586,6 +3586,17 @@ BDAlphaPlayerMetalViewDelegate
if (!self.giftInteractAudiencePanelView) {
self.giftInteractAudiencePanelView = [[FUSLiveGiftInteractAudiencePanelView alloc] initWithFrame:CGRectZero];
[[self fus_viewWithLayer:FUSLiveFunctionLayerManualPopView] addSubview:self.giftInteractAudiencePanelView];
__weak typeof(self) weakSelf = self;
self.giftInteractAudiencePanelView.onItemClickBlock = ^(FUSLiveGiftInteractSettingItemModel * _Nonnull item) {
UIView *superView = [weakSelf fus_viewWithLayer:FUSLiveFunctionLayerManualPopView];
if ([FUSLiveHelper shareInstance].liveType == FUSLiveTypeAudience) {
[[FUSLiveGiftView shareGiftView] fus_giftViewShowOnView:superView currentVC:[weakSelf getViewController] animation:YES toUid:[FUSLiveHelper shareInstance].roomInfoModel.roomId liveType:FUSGiftViewTypeAudience micLinkingUsers:weakSelf.linkMicroView.micListArr];
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
[[FUSLiveGiftView shareGiftView] fus_jumpToGiftPageWithGCId:nil GiftId:item.giftId];
});
}
};
}
[self.giftInteractAudiencePanelView fus_updateWithItems:@[]];
......
......@@ -9,6 +9,9 @@ NS_ASSUME_NONNULL_BEGIN
/// 刷新展示条目(支持展示礼物图标与数量)
- (void)fus_updateWithItems:(NSArray<FUSLiveGiftInteractSettingItemModel *> *)items;
/// 点击某个礼物条目的回调
@property (nonatomic, copy) void (^onItemClickBlock)(FUSLiveGiftInteractSettingItemModel *item);
@end
NS_ASSUME_NONNULL_END
......@@ -17,6 +17,8 @@
@property (nonatomic, strong) NSMutableArray<UIImageView *> *giftIconViews;
/// 礼物数量 label 列表(按 items 数量动态增减)
@property (nonatomic, strong) NSMutableArray<CBAutoScrollLabel *> *giftCountLabels;
/// 点击按钮列表
@property (nonatomic, strong) NSMutableArray<UIButton *> *itemButtons;
/// 当前展示的条目数组
@property (nonatomic, copy) NSArray<FUSLiveGiftInteractSettingItemModel *> *items;
@end
......@@ -60,6 +62,7 @@ static NSString *fus_substringComposedToLength(NSString *text, NSUInteger maxLen
self.textLabels = [NSMutableArray array];
self.giftIconViews = [NSMutableArray array];
self.giftCountLabels = [NSMutableArray array];
self.itemButtons = [NSMutableArray array];
self.emptyLabel = [[UILabel alloc] initWithFrame:CGRectZero];
self.emptyLabel.text = [NSString fus_localString:@"暂无"];
......@@ -91,6 +94,11 @@ static NSString *fus_substringComposedToLength(NSString *text, NSUInteger maxLen
[label removeFromSuperview];
[self.giftCountLabels removeLastObject];
}
while (self.itemButtons.count > targetCount) {
UIButton *btn = self.itemButtons.lastObject;
[btn removeFromSuperview];
[self.itemButtons removeLastObject];
}
while (self.textLabels.count < targetCount) {
UILabel *label = [[UILabel alloc] initWithFrame:CGRectZero];
......@@ -117,6 +125,12 @@ static NSString *fus_substringComposedToLength(NSString *text, NSUInteger maxLen
[self addSubview:label];
[self.giftCountLabels addObject:label];
}
while (self.itemButtons.count < targetCount) {
UIButton *btn = [UIButton buttonWithType:UIButtonTypeCustom];
[btn addTarget:self action:@selector(fus_onItemButtonClick:) forControlEvents:UIControlEventTouchUpInside];
[self addSubview:btn];
[self.itemButtons addObject:btn];
}
UIImage *placeholder = [FUSShowRoomCenterBunble imageNamed:@"icon_gift_placehold"];
for (NSInteger i = 0; i < targetCount; i++) {
......@@ -198,6 +212,20 @@ static NSString *fus_substringComposedToLength(NSString *text, NSUInteger maxLen
CBAutoScrollLabel *countLabel = self.giftCountLabels[i];
countLabel.frame = CGRectMake(giftCountX, y, countW, rowHeight);
UIButton *btn = self.itemButtons[i];
btn.frame = CGRectMake(0, y, CGRectGetWidth(self.bounds), rowHeight);
btn.tag = i;
}
}
- (void)fus_onItemButtonClick:(UIButton *)btn {
NSInteger index = btn.tag;
if (index >= 0 && index < self.items.count) {
FUSLiveGiftInteractSettingItemModel *item = self.items[index];
if (self.onItemClickBlock) {
self.onItemClickBlock(item);
}
}
}
......
......@@ -13,7 +13,8 @@ NS_ASSUME_NONNULL_BEGIN
/// 陪伴单价(单位:宝石/分钟)
@property (nonatomic, assign) NSInteger payUnitPrice;
/// 当前这分钟剩余可观看时长(毫秒)
@property (nonatomic, assign) NSInteger remaintime;
@end
NS_ASSUME_NONNULL_END
......@@ -2,22 +2,19 @@
NS_ASSUME_NONNULL_BEGIN
@class FUSPayRoomCompanionDataModel;
@class FUSPayRoomFrostedGlassDataModel;
@interface FUSPayRoomCompanionPopView : UIView
/// 点击“去充值”的回调(由外部决定跳转逻辑)
@property (nonatomic, copy, nullable) void (^rechargeHandler)(void);
@property (nonatomic, assign) NSInteger unitPricePerMinute;
@property (nonatomic, assign) NSInteger billingTimeMinutes;
/// 展示弹窗(如果已存在同类弹窗则复用并刷新数据)
+ (FUSPayRoomCompanionPopView *)fus_showWithRootView:(UIView *)rootView
companionData:(FUSPayRoomCompanionDataModel *)companionData;
payRoomData:(FUSPayRoomFrostedGlassDataModel *)payRoomData;
/// 刷新展示内容(已陪伴/可继续陪伴/是否不足提示/进度条)
- (void)fus_updateWithCompanionData:(FUSPayRoomCompanionDataModel *)companionData;
- (void)fus_updateWithPayRoomData:(FUSPayRoomFrostedGlassDataModel *)payRoomData;
/// 刷新“下次计费”进度(用于 60s 轮询续费时每秒更新进度条)
- (void)fus_updateBillingCountdownWithRemainingSeconds:(NSInteger)remainingSeconds totalSeconds:(NSInteger)totalSeconds;
......
......@@ -4,6 +4,7 @@
#import <FUSCommon/FUSCommon.h>
#import "FUSPayRoomCompanionDataModel.h"
#import "FUSPayRoomFrostedGlassDataModel.h"
#import "FUSShowRoomCenterBunble.h"
#import "FUSPayRoomCompanionProgressView.h"
......@@ -59,25 +60,30 @@
@implementation FUSPayRoomCompanionPopView
+ (FUSPayRoomCompanionPopView *)fus_showWithRootView:(UIView *)rootView
companionData:(FUSPayRoomCompanionDataModel *)companionData
payRoomData:(FUSPayRoomFrostedGlassDataModel *)payRoomData
{
if (!rootView) {
return nil;
}
FUSPayRoomCompanionDataModel *displayCompanionData = payRoomData.companionData;
if (!displayCompanionData) {
displayCompanionData = [[FUSPayRoomCompanionDataModel alloc] init];
}
UIView *existView = [rootView viewWithTag:90917001];
if ([existView isKindOfClass:FUSPayRoomCompanionPopView.class]) {
[existView removeFromSuperview];
}
CGFloat viewW = 120;
CGFloat viewH = (companionData.isEnough == 1 ? 160 : 123);
CGFloat viewH = (displayCompanionData.isEnough == 0 ? 160 : 123);
CGFloat viewX = 10;
CGFloat viewY = UIView.fus_SafeTop + 205;
FUSPayRoomCompanionPopView *popView = [[FUSPayRoomCompanionPopView alloc] initWithFrame:CGRectMake(viewX, viewY, viewW, viewH)];
popView.tag = 90917001;
[rootView addSubview:popView];
[popView fus_updateWithCompanionData:companionData];
[popView fus_updateWithPayRoomData:payRoomData];
return popView;
}
......@@ -201,17 +207,28 @@
return self;
}
- (void)fus_updateWithCompanionData:(FUSPayRoomCompanionDataModel *)companionData {
- (void)fus_applyCompanionData:(FUSPayRoomCompanionDataModel *)companionData {
self.lastCompanionData = companionData;
NSInteger companionTime = companionData.companionTime;
NSInteger canCompanionTime = companionData.canCompanionTime;
self.companionLabel.text = [NSString stringWithFormat:[NSString fus_localString:@"已陪伴:%ld 分钟"], (long)MAX(0, companionTime)];
self.continueLabel.text = [NSString stringWithFormat:[NSString fus_localString:@"您可继续陪伴 %ld 分钟"], (long)MAX(0, canCompanionTime)];
NSString *continueText = [NSString stringWithFormat:[NSString fus_localString:@"您可继续陪伴 %ld 分钟"], (long)MAX(0, canCompanionTime)];
NSMutableAttributedString *continueAttr = [[NSMutableAttributedString alloc] initWithString:continueText attributes:@{
NSFontAttributeName: self.continueLabel.font ?: [UIFont fus_themeFont:8],
NSForegroundColorAttributeName: [UIColor colorWithWhite:1 alpha:0.9]
}];
NSString *timeValueText = [NSString stringWithFormat:@"%ld", (long)MAX(0, canCompanionTime)];
NSRange timeValueRange = [continueText rangeOfString:timeValueText];
if (timeValueRange.location != NSNotFound && companionData.isEnough == 0) {
[continueAttr addAttribute:NSForegroundColorAttributeName value:[UIColor colorWithHex:@"#FF0000"] range:timeValueRange];
}
self.continueLabel.attributedText = continueAttr;
self.rechargeBtn.hidden = (companionData.isEnough != 1);
BOOL shouldShowRecharge = (companionData.isEnough == 0);
self.rechargeBtn.hidden = !shouldShowRecharge;
CGFloat targetHeight = (companionData.isEnough == 1 ? self.rechargeHeight : self.normalHeight);
CGFloat targetHeight = (shouldShowRecharge ? self.rechargeHeight : self.normalHeight);
self.originalHeight = targetHeight;
if (self.arrowBtn.isSelected == NO && CGAffineTransformIsIdentity(self.transform)) {
self.height = targetHeight;
......@@ -221,9 +238,6 @@
}
NSInteger unitPrice = MAX(0, companionData.payUnitPrice);
if (unitPrice <= 0) {
unitPrice = MAX(0, self.unitPricePerMinute);
}
NSString *priceText = [NSString stringWithFormat:@"%ld /%@", (long)unitPrice,[NSString fus_localString:@"分钟"]];
NSMutableAttributedString *priceAttr = [[NSMutableAttributedString alloc] initWithString:priceText attributes:@{
NSFontAttributeName: self.priceLabel.font ?: [UIFont boldSystemFontOfSize:8],
......@@ -252,6 +266,18 @@
self.dashLine2Layer.path = path2.CGPath;
}
- (void)fus_updateWithPayRoomData:(FUSPayRoomFrostedGlassDataModel *)payRoomData
{
FUSPayRoomCompanionDataModel *displayCompanionData = payRoomData.companionData;
if (!displayCompanionData) {
displayCompanionData = [[FUSPayRoomCompanionDataModel alloc] init];
}
if (displayCompanionData.payUnitPrice <= 0) {
displayCompanionData.payUnitPrice = MAX(0, payRoomData.payRoomConfigData.payUnitPrice);
}
[self fus_applyCompanionData:displayCompanionData];
}
/// 付费房续看轮询:将“剩余秒数”换算为 1~0 的进度值,用于每秒刷新进度条
- (void)fus_updateBillingCountdownWithRemainingSeconds:(NSInteger)remainingSeconds totalSeconds:(NSInteger)totalSeconds
{
......@@ -324,7 +350,7 @@
self.dashLine2Layer.hidden = NO;
if (self.lastCompanionData) {
[self fus_updateWithCompanionData:self.lastCompanionData];
[self fus_applyCompanionData:self.lastCompanionData];
}
}];
}
......
......@@ -45,7 +45,6 @@
@interface FUSPayRoomEntryMainView ()
@property (nonatomic, strong) UIButton *backgroundButton;
@property (nonatomic, strong) UIButton *closeBtn;
@property (nonatomic, strong) UIView *cardView;
......@@ -160,11 +159,7 @@
- (void)fus_buildUI {
self.alpha = 1;
self.backgroundColor = UIColor.clearColor;
self.backgroundButton = [UIButton buttonWithType:UIButtonTypeCustom];
self.backgroundButton.backgroundColor = UIColor.clearColor;
[self addSubview:self.backgroundButton];
self.backgroundColor = [UIColor colorWithWhite:0 alpha:0.4];
self.closeBtn = [UIButton buttonWithType:UIButtonTypeCustom];
[self.closeBtn setImage:[FUSShowRoomCenterBunble imageNamed:@"Live_room_close"] forState:UIControlStateNormal];
......@@ -244,10 +239,6 @@
self.bottomTipLabel.numberOfLines = 2;
[self.cardView addSubview:self.bottomTipLabel];
[self.backgroundButton mas_makeConstraints:^(MASConstraintMaker *make) {
make.edges.equalTo(self);
}];
[self.closeBtn mas_makeConstraints:^(MASConstraintMaker *make) {
make.top.equalTo(self.mas_safeAreaLayoutGuideTop).offset(6);
make.right.equalTo(self).offset(-8);
......@@ -331,7 +322,6 @@
}
- (void)fus_bindActions {
[self.backgroundButton addTarget:self action:@selector(fus_onTapClose) forControlEvents:UIControlEventTouchUpInside];
[self.closeBtn addTarget:self action:@selector(fus_onTapClose) forControlEvents:UIControlEventTouchUpInside];
[self.primaryButton addTarget:self action:@selector(fus_onTapPrimary) forControlEvents:UIControlEventTouchUpInside];
[self.trialButton addTarget:self action:@selector(fus_onTapTrial) forControlEvents:UIControlEventTouchUpInside];
......@@ -440,8 +430,8 @@
} else {
[imageView setLiveFaceWebImageWithSubURLString:facePath placeholder:UIImage.fus_defaultIcon];
}
// 为了实现错位层叠效果,后添加的视图在最上面
[self.accompanyAvatarContainerView bringSubviewToFront:imageView];
// 为了实现错位层叠效果,左边的头像在上面
[self.accompanyAvatarContainerView sendSubviewToBack:imageView];
// 为了和设计图保持一致,给头像加一层白边,让层叠时边界更清晰
imageView.layer.borderWidth = 1.0;
......
#import <Foundation/Foundation.h>
#import <FUSFoundation/FUSFoundation.h>
#import "FUSOnlineUserModel.h"
#import "FUSPayRoomCompanionDataModel.h"
/// 主播数据(roomData)
/// 说明:该模型字段严格对应接口字段,不做别名映射与额外推导
......@@ -56,4 +57,6 @@
@property (nonatomic, strong) FUSPayRoomFrostedGlassUserDataModel *userData;
/// 付费房配置数据
@property (nonatomic, strong) FUSPayRoomFrostedGlassConfigDataModel *payRoomConfigData;
/// 陪伴数据
@property (nonatomic, strong) FUSPayRoomCompanionDataModel *companionData;
@end
......@@ -24,7 +24,8 @@
return @{
@"roomData": [FUSPayRoomFrostedGlassRoomDataModel class],
@"userData": [FUSPayRoomFrostedGlassUserDataModel class],
@"payRoomConfigData": [FUSPayRoomFrostedGlassConfigDataModel class]
@"payRoomConfigData": [FUSPayRoomFrostedGlassConfigDataModel class],
@"companionData": [FUSPayRoomCompanionDataModel class]
};
}
......
......@@ -146,6 +146,13 @@
self.titleLabel.text = [NSString fus_localString:@"付费屋"];
[self.titleContainerView addSubview:self.titleLabel];
UIButton *headerTapBtn = [UIButton buttonWithType:UIButtonTypeCustom];
headerTapBtn.frame = CGRectMake(0, 0, self.contentView.width, 33);
headerTapBtn.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
[headerTapBtn addTarget:self action:@selector(fus_clickArrowBtnAction:) forControlEvents:UIControlEventTouchUpInside];
[self.headerView addSubview:headerTapBtn];
[self.headerView bringSubviewToFront:headerTapBtn];
CGFloat statsY = self.headerView.bottom;
CGFloat statsW = self.contentView.width;
CGFloat statsH = self.contentView.height - statsY;
......@@ -246,20 +253,8 @@
}
- (void)fus_clickStatsAction:(UIButton *)sender forEvent:(UIEvent *)event {
UITouch *touch = event.allTouches.anyObject;
if (!touch) {
return;
}
CGPoint point = [touch locationInView:self.statsBackgroundView];
CGFloat itemH = self.statsBackgroundView.height / 3.0;
NSInteger startIndex = 0;
if (point.y >= itemH && point.y < itemH * 2.0) {
startIndex = 1;
}
UIView *rootView = [[FUSLiveHelper shareInstance].currentFunctionView fus_viewWithLayer:FUSLiveFunctionLayerManualPopView];
[FUSPayRoomViewerPopView fus_showWithRootView:rootView startIndex:startIndex];
[FUSPayRoomViewerPopView fus_showWithRootView:rootView startIndex:0];
}
- (void)fus_requestPayRoomDataIfNeeded {
......
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