From 16c88699619ee062db6cc0b5ab7b13c9e28251e9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=90=AF=E6=98=9F?= Date: Sat, 6 Dec 2025 16:55:26 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E8=81=8A=E5=A4=A9=E9=97=AA?= =?UTF-8?q?=E9=80=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- QXLive/Dynamic(语圈)/View/QXSendGiftView.m | 10 +- .../Controlller/QXRankHomeSubVC.h | 2 +- .../Controlller/QXRankHomeSubVC.m | 21 ++- .../HomePage(声播)/Controlller/QXRankHomeVC.m | 2 +- QXLive/HomePage(声播)/Model/QXRankModel.h | 3 + .../View/首页/排行榜/QXRankCPListCell.m | 3 +- .../View/首页/排行榜/QXRankCPTopThreeView.m | 8 +- QXLive/Manager/QXHapticManager.h | 32 ++++ QXLive/Manager/QXHapticManager.m | 172 ++++++++++++++++++ QXLive/Mine(音域)/View/QXMainHeaderView.m | 1 + .../View/歌手认证/QXAudioRecorderView.m | 13 +- .../UI/TUIConversationListController.m | 36 +++- 12 files changed, 288 insertions(+), 15 deletions(-) create mode 100644 QXLive/Manager/QXHapticManager.h create mode 100644 QXLive/Manager/QXHapticManager.m diff --git a/QXLive/Dynamic(语圈)/View/QXSendGiftView.m b/QXLive/Dynamic(语圈)/View/QXSendGiftView.m index 459bee0..714de21 100644 --- a/QXLive/Dynamic(语圈)/View/QXSendGiftView.m +++ b/QXLive/Dynamic(语圈)/View/QXSendGiftView.m @@ -563,8 +563,14 @@ [weakSelf.categoryView setDefaultSelectedIndex:1]; [weakSelf.categoryView reloadData]; }else{ - for (QXGiftLabelModel*md in weakSelf.titles) { - [arr addObject:md.name]; + /// 在发现打赏时 不需要趣味 循环中剔除 + for (QXGiftLabelModel*md in list) { + if ([md.id isEqualToString:@"2"]) { + [weakSelf.titles removeObject:md]; + continue; + }else{ + [arr addObject:md.name]; + } } weakSelf.categoryView.titles = arr; [weakSelf.categoryView setDefaultSelectedIndex:0]; diff --git a/QXLive/HomePage(声播)/Controlller/QXRankHomeSubVC.h b/QXLive/HomePage(声播)/Controlller/QXRankHomeSubVC.h index 893890c..1afad2a 100644 --- a/QXLive/HomePage(声播)/Controlller/QXRankHomeSubVC.h +++ b/QXLive/HomePage(声播)/Controlller/QXRankHomeSubVC.h @@ -10,7 +10,7 @@ NS_ASSUME_NONNULL_BEGIN -@interface QXRankHomeSubVC : QXBaseViewController +@interface QXRankHomeSubVC : UIViewController @property (nonatomic,strong)NSString *roomId; /// 1日 2 周 3月 @property (nonatomic,strong)NSString *dataType; diff --git a/QXLive/HomePage(声播)/Controlller/QXRankHomeSubVC.m b/QXLive/HomePage(声播)/Controlller/QXRankHomeSubVC.m index 132d090..0fd6cfd 100644 --- a/QXLive/HomePage(声播)/Controlller/QXRankHomeSubVC.m +++ b/QXLive/HomePage(声播)/Controlller/QXRankHomeSubVC.m @@ -24,6 +24,8 @@ @property (nonatomic, strong) QXRankCPTopThreeView *cpHeaderView; @property (nonatomic, strong) QXMyRankView *myRankView; @property (nonatomic, strong) NSMutableArray *topDataArray; +@property (nonatomic, strong) NSMutableArray *dataArray; +@property (nonatomic, assign) NSInteger page; @end @implementation QXRankHomeSubVC @@ -37,19 +39,25 @@ } -(void)viewDidLayoutSubviews{ [super viewDidLayoutSubviews]; - self.myRankView.frame = CGRectMake(0, self.view.height-ScaleWidth(74)-kSafeAreaTop-kSafeAreaBottom, SCREEN_WIDTH, ScaleWidth(74)); - self.tableView.frame = CGRectMake(0, self.rankTypeView.bottom+10, SCREEN_WIDTH, self.view.height - self.rankTypeView.height-20-self.myRankView.height-kSafeAreaTop-kSafeAreaBottom); + if (self.rankType == 4) { + self.tableView.frame = CGRectMake(0,kSafeAreaTop , SCREEN_WIDTH, self.view.height - kSafeAreaTop-10-self.myRankView.height); + }else{ + self.myRankView.frame = CGRectMake(0, self.view.height-ScaleWidth(74)-kSafeAreaTop-kSafeAreaBottom, SCREEN_WIDTH, ScaleWidth(74)); + self.tableView.frame = CGRectMake(0, self.rankTypeView.bottom+10, SCREEN_WIDTH, self.view.height - self.rankTypeView.height-20-self.myRankView.height-kSafeAreaTop-kSafeAreaBottom); + } } -(void)initSubViews{ - self.bgImageHidden = YES; + self.page = 1; self.dataType = @"1"; self.view.backgroundColor = [UIColor clearColor]; [self.view addSubview:self.rankTypeView]; [self.view addSubview:self.myRankView]; if (self.rankType == 4) { + self.rankTypeView.hidden = YES; self.tableView.tableHeaderView = self.cpHeaderView; self.myRankView.isCP = YES; }else{ + self.rankTypeView.hidden = NO; self.myRankView.isCP = NO; self.tableView.tableHeaderView = self.headerView; } @@ -266,4 +274,11 @@ } return _topDataArray; } +-(NSMutableArray *)dataArray{ + if (!_dataArray) { + _dataArray = [NSMutableArray array]; + } + return _dataArray; + +} @end diff --git a/QXLive/HomePage(声播)/Controlller/QXRankHomeVC.m b/QXLive/HomePage(声播)/Controlller/QXRankHomeVC.m index 4a012e7..97b790d 100644 --- a/QXLive/HomePage(声播)/Controlller/QXRankHomeVC.m +++ b/QXLive/HomePage(声播)/Controlller/QXRankHomeVC.m @@ -44,7 +44,7 @@ self.view.backgroundColor = [UIColor clearColor]; // self.titles = @[@"房间榜", @"财富榜", @"魅力榜",@"公会榜",@"真爱榜"]; - self.titles = @[@"房间榜", @"财富榜", @"魅力榜",@"真爱榜"]; + self.titles = @[@"房间榜", @"财富榜", @"魅力榜",@"心动榜"]; self.listVCArray = [NSMutableArray array]; self.categoryView = [[JXCategoryTitleView alloc] init]; self.categoryView.frame = CGRectMake(0, 0, SCREEN_WIDTH-100, 44); diff --git a/QXLive/HomePage(声播)/Model/QXRankModel.h b/QXLive/HomePage(声播)/Model/QXRankModel.h index 6eb1406..4943ffb 100644 --- a/QXLive/HomePage(声播)/Model/QXRankModel.h +++ b/QXLive/HomePage(声播)/Model/QXRankModel.h @@ -44,6 +44,9 @@ NS_ASSUME_NONNULL_BEGIN @property (nonatomic,strong)NSString* user_avatar; @property (nonatomic,strong)NSString* user_avatar1; + +@property (nonatomic,strong)NSString* exp; +@property (nonatomic,strong)NSString* level; @end diff --git a/QXLive/HomePage(声播)/View/首页/排行榜/QXRankCPListCell.m b/QXLive/HomePage(声播)/View/首页/排行榜/QXRankCPListCell.m index be659fc..e78dd5f 100644 --- a/QXLive/HomePage(声播)/View/首页/排行榜/QXRankCPListCell.m +++ b/QXLive/HomePage(声播)/View/首页/排行榜/QXRankCPListCell.m @@ -22,7 +22,8 @@ [self.headerImageView1 sd_setImageWithURL:[NSURL URLWithString:model.user_avatar] placeholderImage:[UIImage imageNamed:@"user_header_placehoulder"]]; [self.headerImageView2 sd_setImageWithURL:[NSURL URLWithString:model.user_avatar1] placeholderImage:[UIImage imageNamed:@"user_header_placehoulder"]]; self.nameLabel.text = [NSString stringWithFormat:@"%@\n%@",model.nickname,model.nickname1]; - self.valueLabel.text = [NSString qx_showHotCountNum:model.total.longLongValue]; +// self.valueLabel.text = [NSString qx_showHotCountNum:model.total.longLongValue]; + self.valueLabel.text = [NSString stringWithFormat:@"Lv %@",model.total]; self.numberLabel.text = model.rank; } - (void)awakeFromNib { diff --git a/QXLive/HomePage(声播)/View/首页/排行榜/QXRankCPTopThreeView.m b/QXLive/HomePage(声播)/View/首页/排行榜/QXRankCPTopThreeView.m index 32a38bd..2d2f808 100644 --- a/QXLive/HomePage(声播)/View/首页/排行榜/QXRankCPTopThreeView.m +++ b/QXLive/HomePage(声播)/View/首页/排行榜/QXRankCPTopThreeView.m @@ -55,7 +55,7 @@ [self.firstHeaderImage2 sd_setImageWithURL:[NSURL URLWithString:firstModel.user_avatar1] placeholderImage:[UIImage imageNamed:@"user_header_placehoulder"]]; self.firstNameLabel.text = firstModel.nickname; self.firstIDLabel.text = firstModel.nickname1; - self.firstRankValueLabel.text = firstModel.total; + self.firstRankValueLabel.text = [NSString stringWithFormat:@"Lv %@",firstModel.total]; } if (secondModel) { @@ -63,7 +63,8 @@ [self.secondHeaderImage2 sd_setImageWithURL:[NSURL URLWithString:secondModel.user_avatar1] placeholderImage:[UIImage imageNamed:@"user_header_placehoulder"]]; self.secondNameLabel.text = secondModel.nickname; self.secondIDLabel.text = secondModel.nickname1; - self.secondRankValueLabel.text = secondModel.total; +// self.secondRankValueLabel.text = secondModel.total; + self.secondRankValueLabel.text = [NSString stringWithFormat:@"Lv %@",secondModel.total]; } if (thirdModel) { @@ -71,7 +72,8 @@ [self.thirdHeaderImage2 sd_setImageWithURL:[NSURL URLWithString:thirdModel.user_avatar1] placeholderImage:[UIImage imageNamed:@"user_header_placehoulder"]]; self.thirdNameLabel.text = thirdModel.nickname; self.thirdIDLabel.text = thirdModel.nickname1; - self.thirdRankValueLabel.text = thirdModel.total; +// self.thirdRankValueLabel.text = thirdModel.total; + self.thirdRankValueLabel.text = [NSString stringWithFormat:@"Lv %@",thirdModel.total]; } } diff --git a/QXLive/Manager/QXHapticManager.h b/QXLive/Manager/QXHapticManager.h new file mode 100644 index 0000000..71fb147 --- /dev/null +++ b/QXLive/Manager/QXHapticManager.h @@ -0,0 +1,32 @@ +// +// QXHapticManager.h +// QXLive +// +// Created by 启星 on 2025/12/5. +// + +#import +#import + +NS_ASSUME_NONNULL_BEGIN + +@interface QXHapticManager : NSObject + ++ (instancetype)shared; + +// 检查是否支持触觉反馈 ++ (BOOL)isHapticFeedbackSupported; + +// 各种触觉反馈方法 +- (void)impactWithStyle:(UIImpactFeedbackStyle)style; +- (void)impactMedium; +- (void)notificationWithType:(UINotificationFeedbackType)type; +- (void)selectionChanged; + +// 带准备的触觉反馈 +- (void)prepareImpactWithStyle:(UIImpactFeedbackStyle)style; +- (void)triggerPreparedImpact; + +@end + +NS_ASSUME_NONNULL_END diff --git a/QXLive/Manager/QXHapticManager.m b/QXLive/Manager/QXHapticManager.m new file mode 100644 index 0000000..d3d5369 --- /dev/null +++ b/QXLive/Manager/QXHapticManager.m @@ -0,0 +1,172 @@ +// +// QXQXQXHapticManager.m +// QXLive +// +// Created by 启星 on 2025/12/5. +// + +#import "QXHapticManager.h" +#import +@interface QXHapticManager () +@property (nonatomic, strong) UIImpactFeedbackGenerator *impactGenerator; +@property (nonatomic, strong) UINotificationFeedbackGenerator *notificationGenerator; +@property (nonatomic, strong) UISelectionFeedbackGenerator *selectionGenerator; +@property (nonatomic, assign) BOOL isImpactPrepared; +@property (nonatomic, assign) UIImpactFeedbackStyle preparedStyle; +@end + +@implementation QXHapticManager + ++ (instancetype)shared { + static QXHapticManager *instance = nil; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + instance = [[QXHapticManager alloc] init]; + }); + return instance; +} + +- (instancetype)init { + self = [super init]; + if (self) { + _isImpactPrepared = NO; + // 提前初始化所有生成器 + _impactGenerator = [[UIImpactFeedbackGenerator alloc] initWithStyle:UIImpactFeedbackStyleMedium]; + _notificationGenerator = [[UINotificationFeedbackGenerator alloc] init]; + _selectionGenerator = [[UISelectionFeedbackGenerator alloc] init]; + + // 提前准备所有生成器 + [self prepareAllGenerators]; + } + return self; +} + +#pragma mark - 支持性检查 ++ (BOOL)isHapticFeedbackSupported { + if (@available(iOS 10.0, *)) { + // 检查设备型号是否支持 + NSString *deviceModel = [[UIDevice currentDevice] model]; + + // 检查是否是iPhone 7及以后 + // 这里简化检查,实际应使用更精确的设备型号检测 + // 可以使用 sysctlbyname 获取更精确的设备信息 + struct utsname systemInfo; + uname(&systemInfo); + NSString *deviceIdentifier = [NSString stringWithCString:systemInfo.machine + encoding:NSUTF8StringEncoding]; + + // iPhone 7及以后的设备标识符(部分示例) + NSArray *supportedDevices = @[ + @"iPhone9,", @"iPhone10,", @"iPhone11,", @"iPhone12,", + @"iPhone13,", @"iPhone14,", @"iPhone15,", @"iPhone16,", + @"iPhone8,4" // iPhone SE (第二代) + ]; + + BOOL isSupportedDevice = NO; + for (NSString *prefix in supportedDevices) { + if ([deviceIdentifier hasPrefix:prefix]) { + isSupportedDevice = YES; + break; + } + } + + // 如果是模拟器,返回YES以支持调试 + #if TARGET_IPHONE_SIMULATOR + return YES; + #else + return isSupportedDevice; + #endif + } + return NO; +} + +- (void)prepareAllGenerators { + if (![QXHapticManager isHapticFeedbackSupported]) { + return; + } + + // 在主线程准备所有生成器 + dispatch_async(dispatch_get_main_queue(), ^{ + [self.impactGenerator prepare]; + [self.notificationGenerator prepare]; + [self.selectionGenerator prepare]; + }); +} + +#pragma mark - 即时触觉反馈 +- (void)impactWithStyle:(UIImpactFeedbackStyle)style { + if (![QXHapticManager isHapticFeedbackSupported]) { + return; + } + + dispatch_async(dispatch_get_main_queue(), ^{ + // 创建新的生成器确保每次都触发 + UIImpactFeedbackGenerator *generator = [[UIImpactFeedbackGenerator alloc] initWithStyle:style]; + [generator prepare]; + [generator impactOccurred]; + + // 延迟释放 + dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ + [generator prepare]; + }); + }); +} + +- (void)impactMedium { + [self impactWithStyle:UIImpactFeedbackStyleMedium]; +} + +#pragma mark - 带准备的触觉反馈 +- (void)prepareImpactWithStyle:(UIImpactFeedbackStyle)style { + if (![QXHapticManager isHapticFeedbackSupported]) { + return; + } + + self.preparedStyle = style; + + dispatch_async(dispatch_get_main_queue(), ^{ + // 重新创建生成器 + self.impactGenerator = [[UIImpactFeedbackGenerator alloc] initWithStyle:style]; + [self.impactGenerator prepare]; + self.isImpactPrepared = YES; + }); +} + +- (void)triggerPreparedImpact { + if (![QXHapticManager isHapticFeedbackSupported] || !self.isImpactPrepared) { + return; + } + + dispatch_async(dispatch_get_main_queue(), ^{ + if (self.impactGenerator) { + [self.impactGenerator impactOccurred]; + // 准备下一次 + [self.impactGenerator prepare]; + } + }); +} + +#pragma mark - 其他类型的触觉反馈 +- (void)notificationWithType:(UINotificationFeedbackType)type { + if (![QXHapticManager isHapticFeedbackSupported]) { + return; + } + + dispatch_async(dispatch_get_main_queue(), ^{ + [self.notificationGenerator notificationOccurred:type]; + [self.notificationGenerator prepare]; + }); +} + +- (void)selectionChanged { + if (![QXHapticManager isHapticFeedbackSupported]) { + return; + } + + dispatch_async(dispatch_get_main_queue(), ^{ + [self.selectionGenerator selectionChanged]; + [self.selectionGenerator prepare]; + }); +} + +@end diff --git a/QXLive/Mine(音域)/View/QXMainHeaderView.m b/QXLive/Mine(音域)/View/QXMainHeaderView.m index 1efbc27..bd8d650 100644 --- a/QXLive/Mine(音域)/View/QXMainHeaderView.m +++ b/QXLive/Mine(音域)/View/QXMainHeaderView.m @@ -420,6 +420,7 @@ } self.nameLabel.text = userModel.nickname; self.idLabel.text = [NSString stringWithFormat:@"ID:%@",userModel.user_code]; + self.bodyPriceMoneyLabel.text = userModel.market_value; UILabel *followLabel = [self viewWithTag:10]; UILabel *fansLabel = [self viewWithTag:11]; UILabel *lookLabel = [self viewWithTag:12]; diff --git a/QXLive/Mine(音域)/View/歌手认证/QXAudioRecorderView.m b/QXLive/Mine(音域)/View/歌手认证/QXAudioRecorderView.m index cee1bbd..ff68650 100644 --- a/QXLive/Mine(音域)/View/歌手认证/QXAudioRecorderView.m +++ b/QXLive/Mine(音域)/View/歌手认证/QXAudioRecorderView.m @@ -10,6 +10,7 @@ #import "UIButton+QX.h" #import "QXCOSUploadManager.h" #import "QXMineNetwork.h" +#import "QXHapticManager.h" @interface QXAudioRecorderView() // UI Components @@ -63,6 +64,8 @@ } - (void)setupUI { + BOOL isSupported = [QXHapticManager isHapticFeedbackSupported]; + NSLog(@"触觉反馈支持: %@", isSupported ? @"是" : @"否"); self.backgroundColor = [UIColor whiteColor]; [self addRoundedCornersWithRadius:16 byRoundingCorners:(UIRectCornerTopLeft|UIRectCornerTopRight)]; @@ -248,14 +251,18 @@ - (void)handleLongPress:(UILongPressGestureRecognizer *)gesture { CGPoint touchPoint = [gesture locationInView:self]; - + UIImpactFeedbackGenerator *generator = [[UIImpactFeedbackGenerator alloc] initWithStyle:UIImpactFeedbackStyleMedium]; + [generator prepare]; + [generator impactOccurred]; switch (gesture.state) { - case UIGestureRecognizerStateBegan: + case UIGestureRecognizerStateBegan:{ [self stopPlayback]; +// [[QXHapticManager shared] impactMedium]; NSLog(@"开始录制 - 第%ld段", (long)self.recordingSessionCount + 1); self.isCancelled = NO; [self startRecording]; - break; + + } break; case UIGestureRecognizerStateChanged: // 检查是否上滑取消 diff --git a/TUIKit/TUIConversation/UI_Classic/UI/TUIConversationListController.m b/TUIKit/TUIConversation/UI_Classic/UI/TUIConversationListController.m index 5cb6b49..66f6f31 100644 --- a/TUIKit/TUIConversation/UI_Classic/UI/TUIConversationListController.m +++ b/TUIKit/TUIConversation/UI_Classic/UI/TUIConversationListController.m @@ -66,9 +66,43 @@ -(void)reloadConversationList{ self.settingDataProvider.delegate = nil; self.settingDataProvider = nil; + [_tableViewForAll removeFromSuperview]; + _tableViewForAll.delegate = nil; + _tableViewForAll = nil; + TUIConversationListDataProvider *dataProvider = [[TUIConversationListDataProvider alloc] init]; self.settingDataProvider = dataProvider; - [_tableViewForAll setDataProvider:dataProvider]; + [self.tableViewContainer addSubview:self.tableViewForAll]; + if (self.isShowConversationGroup) { + dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ + NSArray *extensionList = [TUICore getExtensionList:TUICore_TUIConversationExtension_ConversationGroupListBanner_ClassicExtensionID param:nil]; + @weakify(self); + [[[RACObserve(self, actualShowConversationGroup) distinctUntilChanged] skip:0] subscribeNext:^(NSNumber *showConversationGroup) { + @strongify(self); + if ([showConversationGroup boolValue]) { + [self.tableViewContainer setFrame:CGRectMake(0, self.groupView.mm_maxY, self.view.mm_w, self.viewHeight - self.groupView.mm_maxY)]; + + self.groupItemList = [NSMutableArray array]; + [self addGroup:self.allGroupItem]; + + for (TUIExtensionInfo *info in extensionList) { + TUIConversationGroupItem *groupItem = info.data[TUICore_TUIConversationExtension_ConversationGroupListBanner_GroupItemKey]; + if (groupItem) { + [self addGroup:groupItem]; + } + } + [self onSelectGroup:self.allGroupItem]; + } else { + self.tableViewContainer.frame = CGRectMake(0, self.bannerView.mm_maxY, self.view.mm_w, self.viewHeight - self.bannerView.mm_maxY); + self.tableViewForAll.frame = self.tableViewContainer.bounds; + } + }]; + self.actualShowConversationGroup = (extensionList.count > 0); + }); + } else { + self.tableViewContainer.frame = CGRectMake(0, 0, self.view.mm_w, self.viewHeight - TabBar_Height-NavBar_Height-StatusBar_Height); + self.tableViewForAll.frame = self.tableViewContainer.bounds; + } } #pragma mark - Life Cycle - (void)viewDidLoad {