XYVoiceMatchViewController.m 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497
  1. //
  2. // XYVoiceMatchViewController.m
  3. // Starbuds
  4. //
  5. // Created by 翟玉磊 on 2020/12/4.
  6. // Copyright © 2020 翟玉磊. All rights reserved.
  7. //
  8. #import "XYVoiceMatchViewController.h"
  9. #import "XYVoiceMatchFilterView.h"
  10. #import "XYVoiceMatchButton.h"
  11. #import "XYSphereView.h"
  12. #import <SDWebImage/UIButton+WebCache.h>
  13. #import "XYVoiceMatchSuccessView.h"
  14. #import "XYVoiceMatchMessageModel.h"
  15. #import "XYVoiceChatManager.h"
  16. #import "XYQuickMatchTopMatchSuccessView.h"
  17. #import "XYChatAPIManager.h"
  18. #import "XYVoiceChatViewController.h"
  19. #import "XYPeiPlayUserInfoEditAlertView.h"
  20. @interface XYVoiceMatchViewController ()<XYVoiceMatchingFilterViewDelegate>
  21. @property (nonatomic, strong) XYVoiceMatchViewModel *viewModel;
  22. @property (nonatomic, strong) UIButton *filterButton;
  23. @property (nonatomic, strong) XYVoiceMatchFilterView *filterView;
  24. @property (nonatomic, strong) XYSphereView *sphereView;
  25. @property (nonatomic, strong) XYVoiceMatchButton *matchButton;
  26. @property (nonatomic, strong) XYVoiceMatchSuccessView *matchSuccessView;
  27. @property (nonatomic, strong) XYQuickMatchTopMatchSuccessView *quickMatchTopMatchSuccessView;
  28. @property (nonatomic, assign) BOOL isAnimation;
  29. @property (nonatomic, strong) UIButton *backButton;
  30. @end
  31. @implementation XYVoiceMatchViewController
  32. - (void)dealloc {
  33. // if (_sphereView) {
  34. // [_sphereView clear];
  35. // [_sphereView removeFromSuperview];
  36. // _sphereView = nil;
  37. // }
  38. // if(_quickMatchTopMatchSuccessView){
  39. // [_quickMatchTopMatchSuccessView clear];
  40. // [_quickMatchTopMatchSuccessView removeFromSuperview];
  41. // _quickMatchTopMatchSuccessView = nil;
  42. // }
  43. }
  44. - (instancetype)init
  45. {
  46. self = [super init];
  47. if (self) {
  48. self.prefersNavigationBarHidden = YES;
  49. }
  50. return self;
  51. }
  52. - (void)viewDidLoad {
  53. [super viewDidLoad];
  54. // Do any additional setup after loading the view.
  55. [self setupUI];
  56. /// 速配通知
  57. [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(voiceMatchMessageNotification:) name:VOICE_MATCH_NOTIFICATION object:nil];
  58. /// 语聊退出操作 彻底退出/重新匹配
  59. [[XYVoiceChatManager sharedInstance] setCloseVoiceChatBlock:^(BOOL isMatch) {
  60. self.viewModel.matchStatus = XYVoiceMatchingStatusNormal;
  61. [self updateViewMatchStatus];
  62. if (isMatch) {
  63. [self startVoiceMatch];
  64. }
  65. [self requestRemoteData];
  66. }];
  67. }
  68. - (void)viewWillDisappear:(BOOL)animated{
  69. [super viewWillDisappear:animated];
  70. self.quickMatchTopMatchSuccessView.isViewAppear = NO;
  71. }
  72. - (void)viewWillAppear:(BOOL)animated{
  73. [super viewWillAppear:animated];
  74. self.quickMatchTopMatchSuccessView.isViewAppear = YES;
  75. [self getMatchUserList];
  76. }
  77. - (void)voiceMatchMessageNotification:(NSNotification *)notification {
  78. NSDictionary *msg = notification.object;
  79. XYVoiceMatchMessageModel *msgModel = XYVoiceMatchMessageModel.new;
  80. [msgModel yy_modelSetWithDictionary:msg];
  81. if ([msgModel.type isEqualToString:VOICE_CHAT_MATCH_FAIL]) {
  82. // 语音速配失败
  83. [SVProgressHUD showInfoWithStatus:kLocalizedString(@"匹配失败,请稍后再试")];
  84. if ([msgModel.hisId isEqualToString:self.viewModel.hisId]) {
  85. self.viewModel.matchStatus = XYVoiceMatchingStatusMatchFailure;
  86. [self updateViewMatchStatus];
  87. }
  88. }else if ([msgModel.type isEqualToString:VOICE_CHAT_MATCH_SUCCESS]) {
  89. // 语音速配成功
  90. if ([msgModel.hisId isEqualToString:self.viewModel.hisId]) {
  91. [self.matchSuccessView setupVoiceMatchWaitMessage:msgModel];
  92. self.viewModel.matchStatus = XYVoiceMatchingStatusMatchSuccess;
  93. [self updateViewMatchStatus];
  94. // 延迟跳转语聊界面
  95. dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
  96. // 进入聊天界面
  97. [[XYVoiceChatManager sharedInstance] pushVoiceChatWithHisId:msgModel.hisId token:msgModel.userToken channelName:msgModel.channelName block:^{
  98. }];
  99. });
  100. }
  101. }else if ([msgModel.type isEqualToString:VOICE_CHAT_REJECT]) {
  102. // 语音速配拒绝
  103. if ([msgModel.hisId isEqualToString:self.viewModel.hisId]) {
  104. self.viewModel.matchStatus = XYVoiceMatchingStatusMatchFailure;
  105. [self startVoiceMatch];
  106. }
  107. }else if ([msgModel.type isEqualToString:VOICE_CHAT_CANCEL]) {
  108. // 语音速配取消
  109. if ([msgModel.hisId isEqualToString:self.viewModel.hisId]) {
  110. self.viewModel.matchStatus = XYVoiceMatchingStatusMatchFailure;
  111. [self updateViewMatchStatus];
  112. }
  113. }else {
  114. }
  115. }
  116. #pragma mark — Ovrride
  117. - (void)bindViewModel {
  118. self.viewModel = XYVoiceMatchViewModel.new;
  119. }
  120. - (void)requestRemoteData {
  121. //获取配置
  122. [self.viewModel loadData:^(id _Nullable responseModel) {
  123. [self setupViewData];
  124. [self reloadQuickMatchTopMatchSuccessView];
  125. } failure:^(ZYLNetworkError * _Nullable error) {
  126. [SVProgressHUD showInfoWithStatus:error.domain];
  127. }];
  128. }
  129. - (void)setupViewData {
  130. // 更新状态
  131. [self updateViewMatchStatus];
  132. }
  133. - (void)updateViewMatchStatus {
  134. switch (self.viewModel.matchStatus) {
  135. case XYVoiceMatchingStatusNormal:
  136. case XYVoiceMatchingStatusMatchFailure:
  137. self.matchSuccessView.hidden = YES;
  138. self.matchButton.title = kLocalizedString(@"心动速配");
  139. if (self.viewModel.freeTime > 0) {
  140. self.matchButton.subtitle = [NSString stringWithFormat:kLocalizedString(@"免费试聊%ld秒"), self.viewModel.freeTime];
  141. }else {
  142. self.matchButton.subtitle = @"";
  143. }
  144. self.sphereView.isTimerStart = NO;
  145. break;
  146. case XYVoiceMatchingStatusOpenMatching:
  147. self.sphereView.isTimerStart = YES;
  148. self.matchSuccessView.hidden = YES;
  149. [self.filterView dismiss];
  150. self.matchButton.title = kLocalizedString(@"取消匹配");
  151. self.matchButton.subtitle = @"";
  152. break;
  153. case XYVoiceMatchingStatusMatchSuccess:
  154. self.sphereView.isTimerStart = NO;
  155. self.matchSuccessView.hidden = NO;
  156. [self.view bringSubviewToFront:self.matchSuccessView];
  157. break;
  158. default:
  159. break;
  160. }
  161. }
  162. - (void)reloadsphereView{
  163. [_sphereView removeFromSuperview];
  164. _sphereView = nil;
  165. [self.view addSubview:self.sphereView];
  166. }
  167. - (void)getMatchUserList{
  168. [self.viewModel getMatchUserList:^(ZYLResponseModel *_Nullable responseModel) {
  169. [self reloadsphereView];
  170. NSMutableArray *array = [[NSMutableArray alloc] initWithCapacity:0];
  171. NSMutableArray *userarray = [[NSMutableArray alloc] initWithCapacity:0];
  172. NSArray *list = (NSArray *)responseModel.data[@"list"];
  173. for (NSInteger i = 0; i < list.count; i ++) {
  174. NSDictionary *dict = list[i];
  175. XYUserModel *model = [[XYUserModel alloc] init];
  176. model.userAvatar = dict[@"userAvatar"];
  177. [userarray addObject:model];
  178. UIButton *btn = [UIButton buttonWithType:UIButtonTypeCustom];
  179. [btn sd_setImageWithURL:UrlForString(model.userAvatar) forState:UIControlStateNormal placeholderImage:placeholderUserMainBgImage(model.userSex)];
  180. btn.contentMode = UIViewContentModeScaleAspectFill;
  181. btn.frame = CGRectMake(0, 0, 44.0f, 44.0f);
  182. btn.tag = i;
  183. [btn addTarget:self action:@selector(buttonPressed:) forControlEvents:UIControlEventTouchUpInside];
  184. [array addObject:btn];
  185. [self.sphereView addSubview:btn];
  186. }
  187. [self.sphereView setItems:array];
  188. if (self.XYVoiceMatchViewControllerUserArrsBlock) {
  189. self.XYVoiceMatchViewControllerUserArrsBlock(userarray);
  190. }
  191. } failure:^(ZYLNetworkError * _Nullable error) {
  192. [SVProgressHUD showInfoWithStatus:error.domain];
  193. }];
  194. }
  195. - (void)reloadQuickMatchTopMatchSuccessView{
  196. [self.viewModel getMatchSuccessList:^(ZYLResponseModel *_Nullable responseModel) {
  197. NSMutableArray *userarray = [[NSMutableArray alloc] initWithCapacity:0];
  198. NSArray *list = (NSArray *)responseModel.data[@"list"];
  199. for (NSInteger i = 0; i < list.count; i ++) {
  200. NSDictionary *dict = list[i];
  201. XYUserModel *model = [[XYUserModel alloc] init];
  202. model.userAvatar = dict[@"userAvatar"];
  203. model.userName = dict[@"targetUserName"];
  204. model.userId = dict[@"targetUserAvatar"];
  205. model.userNo = dict[@"targetUserName"];
  206. [userarray addObject:model];
  207. }
  208. [self.quickMatchTopMatchSuccessView reload:userarray];
  209. } failure:^(ZYLNetworkError * _Nullable error) {
  210. [SVProgressHUD showInfoWithStatus:error.domain];
  211. }];
  212. }
  213. #pragma mark — Action
  214. - (void)backButtonAction{
  215. [_sphereView clear];
  216. [_sphereView removeFromSuperview];
  217. _sphereView = nil;
  218. [_quickMatchTopMatchSuccessView clear];
  219. [_quickMatchTopMatchSuccessView removeFromSuperview];
  220. _quickMatchTopMatchSuccessView = nil;
  221. if(self.viewModel.matchStatus == XYVoiceMatchingStatusOpenMatching){
  222. [self.viewModel cancelVoiceMatch:^(id _Nullable responseModel) {
  223. } failure:^(ZYLNetworkError * _Nullable error) {
  224. }];
  225. }
  226. [self.navigationController popViewControllerAnimated:YES];
  227. }
  228. /// 显示筛选view
  229. - (void)filterButtonAction:(id)sender {
  230. // 交友Tab,点[筛选]的次数
  231. [StatisticsManager event:@"home_match_screen_click"];
  232. if (self.filterView.hidden) {
  233. [self.filterView show];
  234. }else {
  235. [self.filterView dismiss];
  236. }
  237. }
  238. - (void)buttonPressed:(UIButton *)btn {
  239. // 交友Tab,点匹配模块-[用户头像]的次数
  240. [StatisticsManager event:@"home_match_headportrait_click"];
  241. if (self.isAnimation) {
  242. return;
  243. }
  244. self.isAnimation = YES;
  245. [self.sphereView timerStop];
  246. [UIView animateWithDuration:0.3 animations:^{
  247. btn.transform = CGAffineTransformMakeScale(2., 2.);
  248. } completion:^(BOOL finished) {
  249. [UIView animateWithDuration:0.3 animations:^{
  250. btn.transform = CGAffineTransformMakeScale(1., 1.);
  251. } completion:^(BOOL finished) {
  252. [self.sphereView timerStart];
  253. self.isAnimation = NO;
  254. XYUserModel *model = self.viewModel.matchUserArray[btn.tag];
  255. if (StringIsNotEmpty(model.userNo)) {
  256. [[XYChatRoomManager sharedInstance] showChatRoomWithRoomId:model.userNo roomCoverUrl:@"" completion:^{
  257. }];
  258. }else if (StringIsNotEmpty(model.userId)) {
  259. XYUserMainViewController *controller = XYUserMainViewController.new;
  260. controller.targetId = model.userId;
  261. [self.navigationController pushViewController:controller animated:YES];
  262. }
  263. }];
  264. }];
  265. }
  266. /// 开始语音匹配
  267. - (void)startVoiceMatch {
  268. if ([self.matchButton.title isEqualToString:kLocalizedString(@"心动速配")]) {
  269. // 交友Tab,点[匹配动态]的次数
  270. [StatisticsManager event:@"home_match_heartbeat_click"];
  271. }
  272. if ([XYUserInfoManager nowUser].userScore < 50 && [self.matchButton.title isEqualToString:kLocalizedString(@"心动速配")]) {
  273. [[XYPeiPlayUserInfoEditAlertView shareInstance] show:JoinTypeVoiceChatStart];
  274. //return;
  275. }
  276. if (![XYUserInfoManager nowUser]) {
  277. [ApplicationDelegate createQulickLoginPageVC];
  278. return;
  279. }
  280. [self voiceMatchAction];
  281. }
  282. - (void)voiceMatchAction {
  283. switch (self.viewModel.matchStatus) {
  284. case XYVoiceMatchingStatusNormal:
  285. case XYVoiceMatchingStatusMatchFailure:
  286. // 默认/暂停/失败->开始匹配
  287. {
  288. // 隐藏筛选viwe
  289. [self.filterView dismiss];
  290. [SVProgressHUD show];
  291. [self.viewModel sendVoiceMatch:^(id _Nullable responseModel) {
  292. [SVProgressHUD dismiss];
  293. [self updateViewMatchStatus];
  294. } failure:^(ZYLNetworkError * _Nullable error) {
  295. [SVProgressHUD showInfoWithStatus:error.domain];
  296. }];
  297. }
  298. break;
  299. case XYVoiceMatchingStatusOpenMatching:
  300. // 匹配中->取消匹配
  301. {
  302. [SVProgressHUD show];
  303. [self.viewModel cancelVoiceMatch:^(id _Nullable responseModel) {
  304. [SVProgressHUD showSuccessWithStatus:kLocalizedString(@"已取消匹配")];
  305. [self updateViewMatchStatus];
  306. } failure:^(ZYLNetworkError * _Nullable error) {
  307. [SVProgressHUD showInfoWithStatus:error.domain];
  308. }];
  309. }
  310. break;
  311. default:
  312. break;
  313. }
  314. }
  315. - (XYVoiceMatchingStatus)matchStatus {
  316. return self.viewModel.matchStatus;
  317. }
  318. - (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
  319. [super touchesBegan:touches withEvent:event];
  320. [self.filterView dismiss];
  321. }
  322. #pragma mark — XYVoiceMatchingFilterViewDelegate
  323. - (void)voiceMatchingFilterType:(XYVoiceMatchingFilterType)type {
  324. self.viewModel.filterType = type;
  325. [self getMatchUserList];
  326. }
  327. #pragma mark — 设置子view
  328. - (void)setupUI {
  329. self.view.backgroundColor = Color_Clear;
  330. [self.view addSubview:self.filterButton];
  331. [self.view addSubview:self.sphereView];
  332. [self.view addSubview:self.matchButton];
  333. [self.filterButton mas_makeConstraints:^(MASConstraintMaker *make) {
  334. make.right.equalTo(self.view).offset(-10.0f);
  335. make.top.equalTo(self.view).offset(STATUS_HEIGHT);
  336. make.height.equalTo(@48.0f);
  337. make.width.equalTo(@50.0f);
  338. }];
  339. [self.matchButton mas_makeConstraints:^(MASConstraintMaker *make) {
  340. make.centerX.equalTo(self.view);
  341. make.width.equalTo(@160.0f);
  342. make.height.equalTo(@40.0f);
  343. make.bottom.equalTo(self.view).offset(-(68.0f+30.0f+40.0f));
  344. }];
  345. [self.matchButton addViewBorder:Color_Clear redian:20];
  346. [self quickMatchTopMatchSuccessView];
  347. [self backButton];
  348. }
  349. #pragma mark — Getter
  350. - (UIButton *)filterButton {
  351. if (!_filterButton) {
  352. _filterButton = [UIButton createButtonTextColor:Color_White textFont:Font(12)];
  353. [_filterButton setImage:ImageNamed(@"xy_Friend_voicematch_filter") forState:UIControlStateNormal];
  354. [_filterButton setTitle:kLocalizedString(@" 筛选") forState:UIControlStateNormal];
  355. [_filterButton addTarget:self action:@selector(filterButtonAction:) forControlEvents:UIControlEventTouchUpInside];
  356. }
  357. return _filterButton;
  358. }
  359. - (XYVoiceMatchFilterView *)filterView {
  360. if (!_filterView) {
  361. _filterView = [[XYVoiceMatchFilterView alloc] init];
  362. [_filterView setupSelectedType:self.viewModel.filterType];
  363. _filterView.delegate = self;
  364. _filterView.hidden = YES;
  365. _filterView.alpha = 0;
  366. [self.view addSubview:_filterView];
  367. [_filterView mas_makeConstraints:^(MASConstraintMaker *make) {
  368. make.right.equalTo(self.view).offset(-16.0f);
  369. make.top.equalTo(self.filterButton.mas_bottom).offset(-10.0f);
  370. make.width.equalTo(@152.0f);
  371. make.height.equalTo(@74.0f);
  372. }];
  373. }
  374. return _filterView;
  375. }
  376. - (XYSphereView *)sphereView {
  377. if (!_sphereView) {
  378. CGFloat sphereViewW = SCREEN_WIDTH - 40 * 2;
  379. CGFloat sphereViewH = sphereViewW;
  380. _sphereView = [[XYSphereView alloc] initWithFrame:CGRectMake(40.0f, NAVGATION_HEIGHT+60.0f+40, sphereViewW, sphereViewH)];
  381. }
  382. return _sphereView;
  383. }
  384. - (XYVoiceMatchButton *)matchButton {
  385. if (!_matchButton) {
  386. _matchButton = [[XYVoiceMatchButton alloc] init];
  387. _matchButton.title = kLocalizedString(@"心动速配");
  388. _matchButton.subtitle = kLocalizedString(@"免费试聊0秒");
  389. _matchButton.backgroundColor = [UIColor colorGradientChangeWithSize:CGSizeMake(160.0f, 40.0f) direction:GradientChangeDirectionLevel startColor:ColorFromHexString(@"#5F0AFF") endColor:ColorFromHexString(@"#9858FF")];
  390. WeakSelf
  391. [_matchButton setActionButtonBlock:^{
  392. [weakSelf startVoiceMatch];
  393. }];
  394. }
  395. return _matchButton;
  396. }
  397. - (XYVoiceMatchSuccessView *)matchSuccessView {
  398. if (!_matchSuccessView) {
  399. _matchSuccessView = [[XYVoiceMatchSuccessView alloc] initWithFrame:self.view.bounds];
  400. _matchSuccessView.backgroundColor = ColorFromHexStringWithAlpha(@"#000000", 0.4f);
  401. _matchSuccessView.hidden = YES;
  402. [self.view addSubview:_matchSuccessView];
  403. }
  404. return _matchSuccessView;
  405. }
  406. - (XYQuickMatchTopMatchSuccessView *)quickMatchTopMatchSuccessView{
  407. if (_quickMatchTopMatchSuccessView == nil) {
  408. _quickMatchTopMatchSuccessView = [[XYQuickMatchTopMatchSuccessView alloc] init];
  409. _quickMatchTopMatchSuccessView.frame = CGRectMake(56, STATUS_HEIGHT+12, 165, 24);
  410. [self.view addSubview:_quickMatchTopMatchSuccessView];
  411. [_quickMatchTopMatchSuccessView setup];
  412. }
  413. return _quickMatchTopMatchSuccessView;
  414. }
  415. - (UIButton *)backButton {
  416. if (!_backButton) {
  417. _backButton = [UIButton buttonWithType:UIButtonTypeCustom];
  418. _backButton.frame = CGRectMake(16.0f, STATUS_HEIGHT+12, 24, 24);
  419. [_backButton setImage:ImageNamed(@"icon_back_bai") forState:UIControlStateNormal];
  420. [_backButton addTarget:self action:@selector(backButtonAction) forControlEvents:UIControlEventTouchUpInside];
  421. [self.view addSubview:_backButton];
  422. }
  423. return _backButton;
  424. }
  425. @end