// // ICRQuestionBaseViewController.m // XFFruit // // Created by Xummer on 15/6/2. // Copyright (c) 2015年 Xummer. All rights reserved. // #import "ICRQuestionBaseViewController.h" #import "ICRQuestionManager.h" #import "IBTImagePicker.h" #import "ICRAttachmentView.h" #import "ICRStoreResult.h" #import "IBTFileManager.h" #import "JTRecordView.h" #import "ICRTask.h" #import "ICRPostTask.h" #import "ICRAttachment.h" #import "ICRPostAttachment.h" #import "JTImagePreviewer.h" #import "ICRQSingleSelectViewController.h" #import "ICRQMutiSelectViewController.h" #import "ICRQAViewController.h" #import "ICRQScoreViewController.h" #import "ICRQStoreStudyViewController.h" #import "ICRQReseachViewController.h" #import "ICRQStarViewController.h" #import "ICRQResultViewController.h" #import "ICRPatrolResultViewController.h" #import "ICRTaskEditViewController.h" #define F_GAP (5) const CGFloat m_fMaxAudioRecoderDuration = 58; const CGFloat m_fMinAudioRecoderDuration = 1; @interface ICRQuestionBaseViewController () < IBTImagePickerDelegate, ICRTaskEditViewDelegate, UITextFieldDelegate > { BOOL m_bIsLoaded; } @property (nonatomic, strong) JTRecordView *m_recordView; @end @implementation ICRQuestionBaseViewController #pragma mark - Life Cycle - (instancetype)initWithQuestion:(ICRQuestion *)question answer:(ICRAnswer *)answer { switch (question.type) { case kICRQestionTypeSingleSel: self = [[ICRQSingleSelectViewController alloc] init]; break; case kICRQestionTypeMultipleSel: self = [[ICRQMutiSelectViewController alloc] init]; break; case kICRQestionTypeReply: self = [[ICRQAViewController alloc] init]; break; case kICRQestionTypeScore: self = [[ICRQScoreViewController alloc] init]; break; case kICRQestionTypeStoreInv: self = [[ICRQStoreStudyViewController alloc] init]; break; case kICRQestionTypeSpeciesInv: self = [[ICRQReseachViewController alloc] init]; break; case kICRQestionTypeStarNum: self = [[ICRQStarViewController alloc] init]; break; default: self = [super init]; break; } if (!self) { return nil; } self.m_question = question; self.m_answer = answer; [self setupDefaultAnswer]; return self; } - (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view. NSSortDescriptor *sort = [NSSortDescriptor sortDescriptorWithKey:@"seq" ascending:YES]; // self.m_arrOptions = [self.m_question.options sortedArrayUsingDescriptors:@[sort]]; [self setupSubviews]; [self registerForKVO]; } - (void)viewDidAppear:(BOOL)animated { [super viewDidAppear:animated]; if (!m_bIsLoaded) { m_bIsLoaded = YES; if (_m_answer.photo) { ICRPostAttachment *pPic = [ICRPostAttachment DBObject]; [pPic praseFromJsonDict:_m_answer.photo]; NSData *imageData = [NSData dataFromBase64String:pPic.content]; UIImage *image = [UIImage imageWithData:imageData]; [self addAttachment:image]; } if (_m_answer.task) { ICRPostTask *pTask = [ICRPostTask DBObject]; [pTask praseFromLocalDict:_m_answer.task]; [self addAttachment:pTask]; } if (_m_answer.voice) { ICRPostAttachment *pVoice = [ICRPostAttachment DBObject]; [pVoice praseFromJsonDict:_m_answer.voice]; NSData *voiceData = [NSData dataFromBase64String:pVoice.content]; [self addAttachment:voiceData]; } } } - (void)didReceiveMemoryWarning { [super didReceiveMemoryWarning]; // Dispose of any resources that can be recreated. } - (void)disMissSelf { [IBTLoadingView showProgressLabel:@"正在保存..."]; ICRQuestionManager *mgr = [ICRQuestionManager sharedManager]; ICRStoreResult *storeR = [mgr getStoreResult]; [storeR saveToDBWithHandleData:NULL complete:^{ [IBTLoadingView hideHUDWithText:nil]; [super disMissSelf]; [ICRQuestionManager sharedManager].m_patrolPlan = nil; } fail:^(NSError *error) { [IBTLoadingView hideHUDWithText:error.localizedDescription]; }]; } - (void)dealloc { [self unregisterFromKVO]; } #pragma mark - Private Method - (void)setupSubviews { self.view.backgroundColor = [UIColor colorWithR:240 g:246 b:255 a:1]; self.m_titleLabel = [[IBTUILabel alloc] init]; _m_titleLabel.numberOfLines = 0; _m_titleLabel.font = [UIFont boldSystemFontOfSize:18]; _m_titleLabel.textColor = [UIColor grayColor]; _m_titleLabel.text = [NSString stringWithFormat:@"%@.%@",@(self.m_question.type+ 1),self.m_question.title]; CGFloat fMargin = 15.0f; CGSize size = CGSizeMake(self.view.width - 2 * fMargin,CGFLOAT_MAX); size = [self.m_titleLabel widthLimitedSizeThatFits:size]; _m_titleLabel.frame = (CGRect){ .origin.x = fMargin, .origin.y = F_GAP, .size = size }; CGFloat fHeight = 300; self.m_helperView = [[ICRQuestionHelperView alloc] initWithFrame:(CGRect){ .origin.x = 0, .origin.y = self.view.height - fHeight, .size.width = self.view.width, .size.height = fHeight }]; _m_helperView.autoresizingMask = UIViewAutoresizingFlexibleTopMargin; [_m_helperView.m_photoAttachView.m_addButton addTarget:self action:@selector(onShowImagePicker:) forControlEvents:UIControlEventTouchUpInside]; [_m_helperView.m_taskAttachView.m_addButton addTarget:self action:@selector(onAddTask:) forControlEvents:UIControlEventTouchUpInside]; [_m_helperView.m_voiceAttachView.m_addButton addTarget:self action:@selector(onStartRecord:) forControlEvents:UIControlEventTouchDown | UIControlEventTouchDownRepeat]; [_m_helperView.m_voiceAttachView.m_addButton addTarget:self action:@selector(onEndRecord:) forControlEvents:UIControlEventTouchUpInside|UIControlEventTouchDragOutside]; _m_helperView.m_inputTxtF.delegate = self; [_m_helperView.m_nextBtn addTarget:self action:@selector(onNextBtnAction:) forControlEvents:UIControlEventTouchUpInside]; [self initScrollViewWithRect:(CGRect){ .origin.x = 0, .origin.y = _m_titleLabel.bottom + F_GAP, .size.width = self.view.width, .size.height = self.view.height - _m_titleLabel.bottom - F_GAP }]; [self.m_contentScrollView autoresizingWithStrechFullSize]; [self.m_contentScrollView setContentInsetTop:0 andBottom:_m_helperView.top]; [self.view addSubview:_m_titleLabel]; [self.view addSubview:_m_contentScrollView]; [self.view addSubview:_m_helperView]; } - (void)initScrollViewWithRect:(CGRect)rect { IBTUIScrollView *scrollV = [[IBTUIScrollView alloc] initWithFrame:rect]; scrollV.bHandleKeyboard = YES; self.m_contentScrollView = scrollV; } - (void)openEditTaskView:(ICRTask *)task { ICRQuestionManager *mgr = [ICRQuestionManager sharedManager]; ICRTaskEditViewController *tVC = [[ICRTaskEditViewController alloc] initWithTask:task store:mgr.m_store]; tVC.m_delegate = self; [self PushViewController:tVC animated:YES]; } - (void)addAttachment:(id)oAtt { SEL selector = NULL; UIImage *iconImg; ICRAttachmentView *attachView = nil; if ([oAtt isKindOfClass:[ICRPostTask class]]) { iconImg = [UIImage imageNamed:@"icon_task_default"]; selector = @selector(onTapTask:); attachView = self.m_helperView.m_taskAttachView; } else if ([oAtt isKindOfClass:[NSData class]]) { iconImg = [UIImage imageNamed:@"icon_voice"]; selector = @selector(onAttVoicePlay:); attachView = self.m_helperView.m_voiceAttachView; } else if ([oAtt isKindOfClass:[UIImage class]]) { iconImg = oAtt; selector = @selector(onTapImage:); attachView = self.m_helperView.m_photoAttachView; } ICRAttachmentUnit *attV = [[ICRAttachmentUnit alloc] initWithFrame:(CGRect){ .origin.x = 0, .origin.y = 0, .size.width = IBT_ATTACH_UNIT_DEFAULT_WIDTH, .size.height = IBT_ATTACH_UNIT_DEFAULT_WIDTH }]; [attV updateWithType:kATTCloseBtn masker:nil placeHolder:nil image:iconImg title:nil]; attV.m_oAttachmentWrap = oAtt; [attV addTarget:self action:selector forControlEvents:UIControlEventTouchUpInside]; [attachView addContentAttachmentView:attV]; } #pragma mark - ICRTaskEditViewDelegate - (void)taskEditViewCtrl:(ICRTaskEditViewController *)viewCtrl taskData:(id)taskData edit:(BOOL)bEdit { if (bEdit) { [self.m_helperView.m_taskAttachView removeContentAttachmentViewAtIndex:0]; } ICRPostTask *pTask = taskData; // pTask.questionAnswer = _m_answer.mobileId; self.m_answer.task = [pTask dictForLocalSave]; [self addAttachment:pTask]; [viewCtrl PopViewControllerAnimated:YES]; } #pragma mark - Action - (void)onShowImagePicker:(__unused id)sender { [[ICRQuestionManager sharedManager].m_imagePicker showImagePickerTitle:nil mediaType:kIBTMediaBImage editable:NO fromViewController:self]; } - (void)onAddTask:(__unused id)sender { [self openEditTaskView:nil]; } - (void)onTapTask:(ICRAttachmentUnit *)unit { ICRPostTask *pTask = unit.m_oAttachmentWrap; [self openEditTaskView:[ICRTask taskFromPostTask:pTask]]; } - (void)onTapImage:(ICRAttachmentUnit *)unit { CGRect rect = [self.view.window convertRect:unit.frame fromView:unit.superview]; UIImage *img = unit.m_oAttachmentWrap; JTImagePreviewer *ipv = [[JTImagePreviewer alloc] initWithViewController:self tempImage:img url:nil startRect:rect]; [ipv show]; } - (void)onNextBtnAction:(__unused id)sender { ICRQuestionManager *mgr = [ICRQuestionManager sharedManager]; UIViewController *qVC = [mgr questionViewControlAtIndex:self.m_uiIndex + 1]; if (qVC) { [self PushViewController:qVC animated:YES]; } else { // TODO } } #pragma mark - Public Method - (void)openResultView { [IBTLoadingView showProgressLabel:@"正在保存..."]; ICRQuestionManager *mgr = [ICRQuestionManager sharedManager]; ICRStoreResult *storeR = [mgr getStoreResult]; __weak typeof(self)weakSelf = self; [storeR saveToDBWithHandleData:NULL complete:^{ __strong __typeof(weakSelf)strongSelf = weakSelf; [IBTLoadingView hideHUDWithText:nil]; ICRQResultViewController *rVC = [[ICRQResultViewController alloc] initWithPatrolPlan:mgr.m_patrolPlan andStoreResult:storeR]; [strongSelf PushViewController:rVC animated:YES]; } fail:^(NSError *error) { [IBTLoadingView hideHUDWithText:error.localizedDescription]; }]; } - (void)setupDefaultAnswer { if (!self.m_answer) { self.m_answer = [ICRAnswer DBObject]; self.m_answer.content = @""; } ICRUserUtil *userUtil = [ICRUserUtil sharedInstance]; self.m_answer.uuid = [userUtil mobileID]; self.m_answer.questionUuid = self.m_question.qID; } #pragma mark - UITextFieldDelegate - (BOOL)textFieldShouldReturn:(UITextField *)textField { [textField resignFirstResponder]; return YES; } #pragma mark - IBTImagePickerDelegate - (void)imagePicker:(IBTImagePickerController *)picker didImagePicked:(UIImage *)image referenceURL:(NSURL *)imageUrl { IBTFileData *imgFile = [IBTCommon saveImageToLocal:image]; // ICRPostAttachment *attE = [[ICRPostAttachment alloc] init]; // attE.type = @"answer"; // attE.objectId = _m_answer.mobileId; // attE.filename = imgFile.fileName; // attE.content = [imgFile.fileData base64EncodedString]; // attE.seq = @(1); // attE.attachmentType = @"answer"; // self.m_answer.photo = [attE dictForCommit]; [self addAttachment:image]; } - (void)imagePicker:(IBTImagePickerController *)picker didVideoPickedWithURL:(NSURL *)videoUrl { } #pragma mark - KVO - (void)registerForKVO { for (NSString *keyPath in [self observableKeypaths]) { [_m_helperView addObserver:self forKeyPath:keyPath options:NSKeyValueObservingOptionNew context:NULL]; } } - (void)unregisterFromKVO { for (NSString *keyPath in [self observableKeypaths]) { [_m_helperView removeObserver:self forKeyPath:keyPath]; } } - (NSArray *)observableKeypaths { return @[ @"frame" ]; } - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context { [self.m_contentScrollView setContentInsetTop:0 andBottom:self.view.height - _m_helperView.y]; } #pragma mark - Keyboard - (void)keyboardWillShow:(NSNotification *)note { // get keyboard size and loctaion CGRect keyboardBounds; [[note.userInfo valueForKey:UIKeyboardFrameEndUserInfoKey] getValue: &keyboardBounds]; NSNumber *duration = [note.userInfo objectForKey:UIKeyboardAnimationDurationUserInfoKey]; NSNumber *curve = [note.userInfo objectForKey:UIKeyboardAnimationCurveUserInfoKey]; // Need to translate the bounds to account for rotation. keyboardBounds = [self.view convertRect:keyboardBounds toView:nil]; // animations settings [UIView beginAnimations:nil context:NULL]; [UIView setAnimationBeginsFromCurrentState:YES]; [UIView setAnimationDuration:[duration doubleValue]]; [UIView setAnimationCurve:[curve intValue]]; // set views with new info if ([_m_helperView.m_inputTxtF isFirstResponder]) { _m_helperView.y = self.view.height - CGRectGetHeight(keyboardBounds) - 75; } // commit animations [UIView commitAnimations]; } - (void)keyboardWillHide:(NSNotification *)note { NSNumber *duration = [note.userInfo objectForKey:UIKeyboardAnimationDurationUserInfoKey]; NSNumber *curve = [note.userInfo objectForKey:UIKeyboardAnimationCurveUserInfoKey]; // animations settings [UIView beginAnimations:nil context:NULL]; [UIView setAnimationBeginsFromCurrentState:YES]; [UIView setAnimationDuration:[duration doubleValue]]; [UIView setAnimationCurve:[curve intValue]]; // set views with new info _m_helperView.y = self.view.height - _m_helperView.height; // commit animations [UIView commitAnimations]; } #pragma mark - Audio - (void)StartRecording { ICRQuestionManager *qMgr = [ICRQuestionManager sharedManager]; if(qMgr.m_oAudioRecorder == nil){ qMgr.m_oAudioRecorder = [[IBTAudioRecorder alloc] init]; __weak typeof(qMgr)weakMgr = qMgr; [qMgr.m_oAudioRecorder setFinishRecordingBlock:(^(IBTAudioRecorder* recorder,BOOL success){ __strong __typeof(weakMgr)strongMgr = weakMgr; NSString *filePath = [recorder recorderingPath]; if(strongMgr.m_fRecoderTime >= m_fMinAudioRecoderDuration){ NSData *audioData = [[NSData alloc] initWithContentsOfFile:filePath]; NSString *fileName = [NSString stringWithFormat:@"ICRAUDIO-%@.mp4", [[NSDate date] YMDHMSFormatterString]]; ICRPostAttachment *attE = [[ICRPostAttachment alloc] init]; // attE.type = @"answer"; // attE.objectId = _m_answer.mobileId; // attE.filename = fileName; // attE.content = [audioData base64EncodedString]; // attE.seq = @(2); // attE.attachmentType = @"answer"; // self.m_answer.voice = [attE dictForCommit]; [self addAttachment:audioData]; } else{ [IBTCommon runOnMainThreadWithoutDeadlocking:^{ [IBTLoadingView showTips:@"录音时间太短"]; }]; [self OnAudioEndRecord]; [IBTFileManager removeFileAtPath:filePath]; } })]; [qMgr.m_oAudioRecorder setEncodeErrorRecordingBlock:^(IBTAudioRecorder *recorder,NSError *error){ [IBTCommon runOnMainThreadWithoutDeadlocking:^{ [IBTLoadingView showTips:@"编码错误"]; }]; [self OnAudioEndRecord]; }]; [qMgr.m_oAudioRecorder setReceivedRecordingBlock:^(IBTAudioRecorder *recorder,float peakPower,float averagePower,float currentTime){ __strong __typeof(weakMgr)strongMgr = weakMgr; CLog(@"recording, peakPower = %f,averagePower = %f,currentTime = %f",peakPower,averagePower,currentTime); [self UpdateRecordPower:peakPower]; if (currentTime > 0) { strongMgr.m_fRecoderTime = currentTime; } }]; } qMgr.m_fRecoderTime = 0; [qMgr.m_oAudioRecorder startRecordForDuration:m_fMaxAudioRecoderDuration]; } - (void)StopRecording { ICRQuestionManager *qMgr = [ICRQuestionManager sharedManager]; [qMgr.m_oAudioRecorder performSelector:@selector(stopRecord) withObject:nil afterDelay:.2f]; } - (void)onAttVoicePlay:(id)sender { NSData *audioData = [sender valueForKey:@"m_oAttachmentWrap"]; ICRQuestionManager *qMgr = [ICRQuestionManager sharedManager]; if (!qMgr.m_oAudioPlayer) { qMgr.m_oAudioPlayer = [[IBTAVAudioPlayWrapper alloc] init]; } __weak typeof(qMgr)weakMgr = qMgr; [qMgr.m_oAudioPlayer playWithData:audioData complete:^(BOOL finished, NSError *error) { __strong __typeof(weakMgr)strongMgr = weakMgr; [strongMgr.m_oAudioPlayer stopPlay]; }]; } #pragma mark - Audio Actions - (void)onStartRecord:(id)sender { __weak typeof(self)weakSelf = self; void(^recordAction)(void) = ^(void) { __strong __typeof(weakSelf)strongSelf = weakSelf; UIButton *btn = strongSelf.m_helperView.m_voiceAttachView.m_addButton; if (btn.tracking && btn.touchInside) { strongSelf.m_recordView.hidden = NO; [strongSelf StartRecording]; } }; [IBTAudioRecorder checkMicrophonePermissionAndRunAction:recordAction]; } - (void)onEndRecord:(id)sender { _m_recordView.hidden = YES; [self StopRecording]; } - (void)OnAudioEndRecord { _m_recordView.hidden = YES; } - (void)UpdateRecordPower:(float)power { if (_m_recordView.hidden) { return; } // 10^-160 ~ 10^0 NSUInteger waveLevel = 1; if (power < (1.0f/4.0f)) { waveLevel = 1; } else if (power < (2.0f/4.0f)) { waveLevel = 2; } else if (power < (3.0f/4.0f)) { waveLevel = 3; } else { waveLevel = 4; } [_m_recordView updateWithWavePower:waveLevel]; } @end