// // XPMonentsDetailViewController.m // xplan-ios // // Created by 冯硕 on 2022/6/22. // #import "XPMonentsDetailViewController.h" ///Third #import #import ///Tool #import "XPMonentsLayoutConfig.h" #import "ThemeColor.h" #import "QEmotionHelper.h" #import "QKeyboardManager.h" #import "TTPopup.h" ///Model #import "MonentsInfoModel.h" #import "MonentsCommentModel.h" #import "MonentsCommentReplyModel.h" ///View #import "XPMonentsTableViewCell.h" #import "XPMonentsCommentTableViewCell.h" #import "XPMonentsEmptyTableViewCell.h" #import "QInputBarView.h" #import "QKeyboardManager.h" #import "QEmotionBoardView.h" ///P #import "XPMonentDetailPresenter.h" #import "XPMonentsDetailProtocol.h" @interface XPMonentsDetailViewController () ///列表 @property (nonatomic,strong) UITableView *tableView; ///数据源 @property (nonatomic,strong) NSMutableArray *datasource; ///头部view @property (nonatomic,strong) UIView * sectionView; ///评论的个数 @property (nonatomic,strong) UILabel *commentLabel; @property(nonatomic,strong)QInputBarView *inputBarView; @property(nonatomic,strong)QKeyboardManager *keyboardManager; ///当前选中的评论信息 @property (nonatomic,strong) NSString *commentId; @end @implementation XPMonentsDetailViewController - (__kindof id)createPresenter { return [[XPMonentDetailPresenter alloc] init]; } - (void)viewDidLoad { [super viewDidLoad]; [self initHeaderAndFooterRrfresh]; [self initSubViews]; [self initSubViewConstraints]; } #pragma mark - 下拉刷新 - (void)initHeaderAndFooterRrfresh { MJRefreshNormalHeader *header = [MJRefreshNormalHeader headerWithRefreshingTarget:self refreshingAction:@selector(headerRefresh)]; header.stateLabel.font = [UIFont systemFontOfSize:10.0]; header.lastUpdatedTimeLabel.font = [UIFont systemFontOfSize:10.0]; header.stateLabel.textColor = [ThemeColor secondTextColor]; header.lastUpdatedTimeLabel.textColor = [ThemeColor secondTextColor]; self.tableView.mj_header = header; MJRefreshBackNormalFooter *footer = [MJRefreshBackNormalFooter footerWithRefreshingTarget:self refreshingAction:@selector(footerRefresh)]; footer.stateLabel.textColor = [ThemeColor secondTextColor]; footer.stateLabel.font = [UIFont systemFontOfSize:10.0]; self.tableView.mj_footer = footer; [self headerRefresh]; } - (void)headerRefresh { [self.presenter getMonentsDetail:self.monentsInfo.dynamicId]; [self.presenter getMonentsCommentList:self.monentsInfo.dynamicId timestamp:@"" status:0]; } - (void)footerRefresh { NSString *timestamp = @""; if (self.datasource.count > 0) { MonentsCommentModel * commentInfo = [self.datasource lastObject]; timestamp = commentInfo.publishTime; } [self.presenter getMonentsCommentList:self.monentsInfo.dynamicId timestamp:timestamp status:1]; } #pragma mark - Private Method - (void)initInputView { // 初始化输入工具条,frame可以先这样临时设置,下面的addBottomInputBarView方法会重置输入条frame // 如果你想要自定义输入条View,请参考TextFieldViewController代码 _inputBarView = [[QInputBarView alloc] initWithFrame:CGRectMake(0,0,self.view.frame.size.width,UIInputBarViewMinHeight)]; QInputBarViewConfiguration *inputBarViewConfiguration = [QInputBarViewConfiguration defaultInputBarViewConfiguration]; inputBarViewConfiguration.voiceButtonHidden = YES;//隐藏语音按钮 inputBarViewConfiguration.extendButtonHidden = YES;//隐藏拓展按钮 [_inputBarView setupWithConfiguration:inputBarViewConfiguration]; _inputBarView.delegate = self; //keyboard管理类,用来管理键盘,各大面板的切换 _keyboardManager = [[QKeyboardManager alloc] initWithViewController:self]; _keyboardManager.dataSource = self; //因为addBottomInputBarView方法会立刻触发delegate,所以这里需要先设置delegate _keyboardManager.delegate = self; [_keyboardManager addBottomInputBarView:_inputBarView belowViewController:NO]; //把输入框(如果有的话)绑定给管理类 [_keyboardManager bindTextView:_inputBarView.inputTextView]; } - (void)sendTextMessage:(NSString *)inputText { if (inputText.length > 0) { [_keyboardManager hideAllBoardView]; if (self.commentId && self.commentId.length > 0) { [self.presenter replayCommon:self.commentId dynamicId:self.monentsInfo.dynamicId content:inputText]; } else { [self.presenter commontMonents:self.monentsInfo.dynamicId content:inputText]; } self.inputBarView.inputTextView.text = nil; } else { [self showErrorToast:@"请输入您要评论的内容"]; } } - (void)initSubViews { self.title = @"详情"; [self.view addSubview:self.tableView]; [self.sectionView addSubview:self.commentLabel]; [self initInputView]; } - (void)initSubViewConstraints { [self.tableView mas_makeConstraints:^(MASConstraintMaker *make) { make.left.right.top.mas_equalTo(self.view); make.bottom.mas_equalTo(self.view).offset(-UIInputBarViewMinHeight); }]; [self.commentLabel mas_makeConstraints:^(MASConstraintMaker *make) { make.left.mas_equalTo(self.sectionView).offset(15); make.centerY.mas_equalTo(self.sectionView); }]; } #pragma mark - UITableViewDelegate And UITableViewDataSource - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView { return 2; } - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { if (section == 0) { return 1; } return self.datasource.count > 0 ? self.datasource.count : 1; } - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath { if (indexPath.section == 0) { [XPMonentsLayoutConfig layoutMonentsModel:self.monentsInfo]; return self.monentsInfo.rowHeight; } else if(indexPath.section == 1) { if (self.datasource.count > 0) { MonentsCommentModel * commentInfo = [self.datasource objectAtIndex:indexPath.row]; return [XPMonentsLayoutConfig commentCommentRowHeight:commentInfo]; } else { return 400; } } return 0; } - (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section { if (section == 1) { return 44; } return 0.0;; } - (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section { self.commentLabel.text = [NSString stringWithFormat:@"所有评论(%@)", self.monentsInfo.commentCount]; return self.sectionView; } - (CGFloat)tableView:(UITableView *)tableView heightForFooterInSection:(NSInteger)section { return 0.0f; } - (UIView *)tableView:(UITableView *)tableView viewForFooterInSection:(NSInteger)section { return [UIView new]; } - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { if (indexPath.section ==0) { XPMonentsTableViewCell * cell = [tableView dequeueReusableCellWithIdentifier:NSStringFromClass([XPMonentsTableViewCell class])]; cell.delegate = self; cell.monentsInfo = self.monentsInfo; return cell; } else { if (self.datasource.count > 0) { XPMonentsCommentTableViewCell * cell = [tableView dequeueReusableCellWithIdentifier:NSStringFromClass([XPMonentsCommentTableViewCell class])]; cell.commentInfo = [self.datasource objectAtIndex:indexPath.row]; cell.delegate = self; return cell; } else { XPMonentsEmptyTableViewCell * cell = [tableView dequeueReusableCellWithIdentifier:NSStringFromClass([XPMonentsEmptyTableViewCell class])]; return cell; } } } - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { [tableView deselectRowAtIndexPath:indexPath animated:YES]; if (indexPath.section == 1) { if (self.datasource.count > 0) { MonentsCommentModel* monent = [self.datasource objectAtIndex:indexPath.row]; self.commentId = monent.commentId; self.inputBarView.inputTextView.placeholder = [NSString stringWithFormat:@"回复: %@", monent.nick]; [self.inputBarView textViewBecomeFirstResponder]; } } } - (void)scrollViewDidScroll:(UIScrollView *)scrollView { [_keyboardManager hideAllBoardView]; } #pragma mark - XPMonentsCommentTableViewCellDelegate - (void)xPMonentsCommentTableViewCell:(XPMonentsCommentTableViewCell *)view didClickMoreReply:(MonentsCommentModel *)commentInfo { [self.presenter getMonentsCommentReplyList:self.monentsInfo.dynamicId commentId:commentInfo.commentId timestamp:commentInfo.replyInfo.nextTimestamp]; } - (void)xPMonentsCommentTableViewCell:(XPMonentsCommentTableViewCell *)view didClickCommon:(MonentsReplyModel *)commentInfo { if (commentInfo) { self.commentId = commentInfo.replyId; self.inputBarView.inputTextView.placeholder = [NSString stringWithFormat:@"回复: %@", commentInfo.nick]; [self.inputBarView textViewBecomeFirstResponder]; } } #pragma mark - XPMonentsTableViewCellDelegate - (void)xPMonentsTableViewCell:(XPMonentsTableViewCell *)view didClickLike:(MonentsInfoModel *)monentsInfo { [self.presenter likeMonent:monentsInfo.dynamicId status:!monentsInfo.isLike likedUid:monentsInfo.uid worldId:[NSString stringWithFormat:@"%ld", monentsInfo.worldId]]; } - (void)xPMonentsTableViewCell:(XPMonentsTableViewCell *)view didClicDelete:(MonentsInfoModel *)monentsInfo { [TTPopup alertWithMessage:@"删除后不可恢复\n确定删除该动态吗?" confirmHandler:^{ [self.presenter deleteMonents:monentsInfo.dynamicId worldId:[NSString stringWithFormat:@"%ld", monentsInfo.worldId]]; } cancelHandler:^{ }]; } - (void)xPMonentsTableViewCell:(XPMonentsTableViewCell *)view didClicCommon:(MonentsInfoModel *)monentsInfo { if (monentsInfo) { self.commentId = nil; self.inputBarView.inputTextView.placeholder = @"发表评论"; [self.inputBarView textViewBecomeFirstResponder]; } } #pragma mark - InputBoardDataSource //@return 点加号按钮弹出的拓展面板View,且无需设置frame - (UIView *)keyboardManagerExtendBoardView:(QKeyboardManager *)keyboardManager { UIView *boardView = [UIView new]; boardView.backgroundColor = UIColor.blueColor; return boardView; } //@return 点表情按钮弹出的表情面板View,且无需设置frame - (UIView *)keyboardManagerEmotionBoardView:(QKeyboardManager *)keyboardManager { QEmotionBoardView *emotionView = [[QEmotionBoardView alloc] init]; QEmotionHelper *faceManager = [QEmotionHelper sharedEmotionHelper]; emotionView.emotions = faceManager.emotionArray; emotionView.delegate = self; if (@available(iOS 11.0, *)) { NSBundle *bundle = [NSBundle bundleForClass:[self class]]; emotionView.backgroundColor = [UIColor colorNamed:@"q_input_extend_bg" inBundle:bundle compatibleWithTraitCollection:nil]; } else { emotionView.backgroundColor = [UIColor colorWithRed:(246)/255.0f green:(246)/255.0f blue:(246)/255.0f alpha:1]; } return emotionView; } //@return 点表情按钮弹出的表情面板View的高度 - (CGFloat)keyboardManagerEmotionBoardHeight:(QKeyboardManager *)keyboardManager { return 294; } //@return 点加号按钮弹出的拓展面板View的高度 - (CGFloat)keyboardManagerExtendBoardHeight:(QKeyboardManager *)keyboardManager { return 174; } - (QInputBarViewConfiguration *)inputBarViewConfiguration { //输入条配置,子类可以重写 QInputBarViewConfiguration *inputBarViewConfiguration = [QInputBarViewConfiguration defaultInputBarViewConfiguration]; inputBarViewConfiguration.voiceButtonHidden = YES;//隐藏语音按钮 inputBarViewConfiguration.extendButtonHidden = YES;//隐藏拓展按钮 return inputBarViewConfiguration; } //点击表情按钮,切换到表情面板 - (void)inputBarView:(QInputBarView *)inputBarView onEmotionButtonClick:(UIButton *)emotionSwitchButton { if (emotionSwitchButton.isSelected) { [_keyboardManager switchToEmotionBoardKeyboard]; } else { self.commentId = nil; _inputBarView.inputTextView.placeholder = @"发表评论"; [_inputBarView textViewBecomeFirstResponder]; } } #pragma mark - QEmotionBoardViewDelegate /** * 选中表情时的回调 * @param index 被选中的表情在`emotions`里的索引 * @param emotion 被选中的表情对应的`QMUIEmotion`对象 */ - (void)emotionView:(QEmotionBoardView *)emotionView didSelectEmotion:(QEmotion *)emotion atIndex:(NSInteger)index { //把😊插入到输入栏 [_inputBarView insertEmotion:emotion.displayName]; } // 删除按钮的点击事件回调 - (void)emotionViewDidSelectDeleteButton:(QEmotionBoardView *)emotionView { if (![_inputBarView deleteEmotion]){ //根据当前的光标,这次点击删除按钮并没有删除表情,那么就删除文字 [_inputBarView.inputTextView deleteBackward]; } } // 发送按钮的点击事件回调 - (void)emotionViewDidSelectSendButton:(QEmotionBoardView *)emotionView { [self sendTextMessage:[_inputBarView textViewInputNormalText]]; } #pragma mark - /** * 点击了系统键盘的发送按钮 * @param inputNormalText :"害~你好啊[微笑]" */ - (void)inputBarView:(QInputBarView *)inputBarView onKeyboardSendClick:(NSString *)inputNormalText { [self sendTextMessage:inputNormalText]; } #pragma mark - XPMonentsDetailProtocol - (void)getMonentsDetailSuccess:(MonentsInfoModel *)commentInfo { self.monentsInfo = commentInfo; [self.tableView reloadData]; } - (void)getMonentsCommentListSuccess:(MonentsCommentListModel *)commentInfo state:(int)state{ if (state == 0) { [self.datasource removeAllObjects]; [self.tableView.mj_header endRefreshing]; } else { [self.tableView.mj_footer endRefreshing]; } if (commentInfo.commentList.count > 0) { [self.datasource addObjectsFromArray:commentInfo.commentList]; } [self.tableView reloadData]; } - (void)getMonentsCommentReplyListSuccess:(MonentsCommentReplyModel *)replyInfo commentId:(nonnull NSString *)commentId { if (commentId) { __block MonentsCommentModel * commentInfo; [self.datasource enumerateObjectsUsingBlock:^(MonentsCommentModel * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) { if ([obj.commentId isEqualToString:commentId]) { commentInfo = obj; *stop = YES; } }]; if (commentInfo) { NSMutableArray * replyList= commentInfo.replyInfo.replyList.mutableCopy; [replyList addObjectsFromArray:replyInfo.replyList]; commentInfo.replyInfo.replyList = replyList.copy; commentInfo.replyInfo.leftCount = replyInfo.leftCount; commentInfo.replyInfo.nextTimestamp = replyInfo.nextTimestamp; commentInfo.isReloadHeight = YES; } [self.tableView reloadData]; } } - (void)likeMonentsSuccess:(NSString *)dynamicId status:(BOOL)status { if ([self.monentsInfo.dynamicId isEqualToString:dynamicId]) { NSInteger count = self.monentsInfo.likeCount.integerValue; self.monentsInfo.isLike = status; if (status) { count += 1; } else { count -= 1; } self.monentsInfo.likeCount = [NSString stringWithFormat:@"%ld", count]; [self.tableView reloadData]; } } - (void)replyMonentsSuccess { [self.presenter getMonentsCommentList:self.monentsInfo.dynamicId timestamp:@"" status:0]; } - (void)commonMonentsSuccess { [self.presenter getMonentsCommentList:self.monentsInfo.dynamicId timestamp:@"" status:0]; } - (void)deleteMonentsSuccess:(NSString *)monentsInfo { [self showSuccessToast:@"删除成功"]; [self.navigationController popViewControllerAnimated:YES]; if (self.delegate && [self.delegate respondsToSelector:@selector(xPMonentsDetailViewController:deleteMonents:)]) { [self.delegate xPMonentsDetailViewController:self deleteMonents:self.monentsInfo.dynamicId]; } } #pragma mark - Getters And Setters - (UITableView *)tableView { if (!_tableView) { _tableView = [[UITableView alloc] initWithFrame:CGRectZero style:UITableViewStyleGrouped]; _tableView.delegate = self; _tableView.dataSource = self; _tableView.tableFooterView = [UIView new]; _tableView.tableFooterView = [UIView new]; _tableView.separatorStyle = UITableViewCellSeparatorStyleNone; _tableView.backgroundColor = [UIColor clearColor]; if (@available(iOS 11.0, *)) { _tableView.contentInsetAdjustmentBehavior = UIScrollViewContentInsetAdjustmentNever; } [_tableView registerClass:[XPMonentsTableViewCell class] forCellReuseIdentifier:NSStringFromClass([XPMonentsTableViewCell class])]; [_tableView registerClass:[XPMonentsCommentTableViewCell class] forCellReuseIdentifier:NSStringFromClass([XPMonentsCommentTableViewCell class])]; [_tableView registerClass:[XPMonentsEmptyTableViewCell class] forCellReuseIdentifier:NSStringFromClass([XPMonentsEmptyTableViewCell class])]; } return _tableView; } - (UIView *)sectionView { if (!_sectionView) { _sectionView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, KScreenWidth, 44)]; _sectionView.backgroundColor = [UIColor clearColor]; } return _sectionView; } - (UILabel *)commentLabel { if (!_commentLabel) { _commentLabel = [[UILabel alloc] init]; _commentLabel.font = [UIFont systemFontOfSize:14]; _commentLabel.textColor = [ThemeColor mainTextColor]; } return _commentLabel; } - (NSMutableArray *)datasource { if (!_datasource) { _datasource = [NSMutableArray array]; } return _datasource; } @end