Add cancel-by-swipe of voice memo recording.

// FREEBIE
This commit is contained in:
Matthew Chen 2017-05-04 22:35:02 -04:00
parent 608cb70a3b
commit c34d61b93f

View file

@ -97,11 +97,13 @@ typedef enum : NSUInteger {
- (void)didPasteAttachment:(SignalAttachment * _Nullable)attachment; - (void)didPasteAttachment:(SignalAttachment * _Nullable)attachment;
- (void)gestureDidStartVoiceMemo; - (void)voiceMemoGestureDidStart;
- (void)gestureDidEndVoiceMemo; - (void)voiceMemoGestureDidEnd;
- (void)gestureDidCancelVoiceMemo; - (void)voiceMemoGestureDidCancel;
- (void)voiceMemoGestureDidChange:(CGFloat)cancelAlpha;
@end @end
@ -121,6 +123,8 @@ typedef enum : NSUInteger {
@property (nonatomic) BOOL isRecordingVoiceMemo; @property (nonatomic) BOOL isRecordingVoiceMemo;
@property (nonatomic) CGPoint voiceMemoGestureStart;
@end @end
#pragma mark - #pragma mark -
@ -382,24 +386,38 @@ typedef enum : NSUInteger {
case UIGestureRecognizerStateFailed: case UIGestureRecognizerStateFailed:
if (self.isRecordingVoiceMemo) { if (self.isRecordingVoiceMemo) {
self.isRecordingVoiceMemo = NO; self.isRecordingVoiceMemo = NO;
[self.textViewPasteDelegate gestureDidCancelVoiceMemo]; [self.textViewPasteDelegate voiceMemoGestureDidCancel];
} }
break; break;
case UIGestureRecognizerStateBegan: case UIGestureRecognizerStateBegan:
if (self.isRecordingVoiceMemo) { if (self.isRecordingVoiceMemo) {
self.isRecordingVoiceMemo = NO; self.isRecordingVoiceMemo = NO;
[self.textViewPasteDelegate gestureDidCancelVoiceMemo]; [self.textViewPasteDelegate voiceMemoGestureDidCancel];
} }
[self resignFirstResponder];
self.isRecordingVoiceMemo = YES; self.isRecordingVoiceMemo = YES;
[self.textViewPasteDelegate gestureDidStartVoiceMemo]; self.voiceMemoGestureStart = [sender locationInView:self];
[self.textViewPasteDelegate voiceMemoGestureDidStart];
break; break;
case UIGestureRecognizerStateChanged: case UIGestureRecognizerStateChanged:
// TODO: if (self.isRecordingVoiceMemo) {
CGPoint location = [sender locationInView:self];
CGFloat offset = MAX(0, self.voiceMemoGestureStart.x - location.x);
const CGFloat kCancelOffsetPoints = 50.f;
CGFloat cancelAlpha = offset / kCancelOffsetPoints;
BOOL isCancelled = cancelAlpha >= 1.f;
if (isCancelled) {
self.isRecordingVoiceMemo = NO;
[self.textViewPasteDelegate voiceMemoGestureDidCancel];
} else {
[self.textViewPasteDelegate voiceMemoGestureDidChange:cancelAlpha];
}
}
break; break;
case UIGestureRecognizerStateEnded: case UIGestureRecognizerStateEnded:
if (self.isRecordingVoiceMemo) { if (self.isRecordingVoiceMemo) {
self.isRecordingVoiceMemo = NO; self.isRecordingVoiceMemo = NO;
[self.textViewPasteDelegate gestureDidEndVoiceMemo]; [self.textViewPasteDelegate voiceMemoGestureDidEnd];
} }
break; break;
} }
@ -493,6 +511,8 @@ typedef enum : NSUInteger {
- (void)showVoiceMemoUI - (void)showVoiceMemoUI
{ {
OWSAssert([NSThread isMainThread]);
self.voiceMemoStartTime = [NSDate date]; self.voiceMemoStartTime = [NSDate date];
[self.voiceMemoUI removeFromSuperview]; [self.voiceMemoUI removeFromSuperview];
@ -577,6 +597,8 @@ typedef enum : NSUInteger {
- (void)hideVoiceMemoUI:(BOOL)animated - (void)hideVoiceMemoUI:(BOOL)animated
{ {
OWSAssert([NSThread isMainThread]);
UIView *voiceMemoUI = self.voiceMemoUI; UIView *voiceMemoUI = self.voiceMemoUI;
self.voiceMemoUI = nil; self.voiceMemoUI = nil;
NSTimer *voiceMemoUpdateTimer = self.voiceMemoUpdateTimer; NSTimer *voiceMemoUpdateTimer = self.voiceMemoUpdateTimer;
@ -599,8 +621,21 @@ typedef enum : NSUInteger {
} }
} }
- (void)setVoiceMemoUICancelAlpha:(CGFloat)cancelAlpha
{
OWSAssert([NSThread isMainThread]);
// Fade out the voice memo views as the cancel gesture
// proceeds as feedback.
for (UIView *subview in self.voiceMemoUI.subviews) {
subview.layer.opacity = MAX(0.f, MIN(1.f, 1.f - (float)cancelAlpha));
}
}
- (void)updateVoiceMemo - (void)updateVoiceMemo
{ {
OWSAssert([NSThread isMainThread]);
NSTimeInterval durationSeconds = fabs([self.voiceMemoStartTime timeIntervalSinceNow]); NSTimeInterval durationSeconds = fabs([self.voiceMemoStartTime timeIntervalSinceNow]);
self.recordingLabel.text = [ViewControllerUtils formatDurationSeconds:(long)round(durationSeconds)]; self.recordingLabel.text = [ViewControllerUtils formatDurationSeconds:(long)round(durationSeconds)];
[self.recordingLabel sizeToFit]; [self.recordingLabel sizeToFit];
@ -3223,8 +3258,17 @@ typedef enum : NSUInteger {
return; return;
} }
NSTimeInterval currentTime = self.audioRecorder.currentTime;
[self.audioRecorder stop]; [self.audioRecorder stop];
const NSTimeInterval kMinimumRecordingTimeSeconds = 1.f;
if (currentTime < kMinimumRecordingTimeSeconds) {
DDLogInfo(@"Discarding voice memo; too short.");
self.audioRecorder = nil;
return;
}
NSData *audioData = [NSData dataWithContentsOfURL:self.audioRecorder.url]; NSData *audioData = [NSData dataWithContentsOfURL:self.audioRecorder.url];
self.audioRecorder = nil; self.audioRecorder = nil;
@ -3556,36 +3600,43 @@ typedef enum : NSUInteger {
completion:nil]; completion:nil];
} }
- (void)gestureDidStartVoiceMemo - (void)voiceMemoGestureDidStart
{ {
OWSAssert([NSThread isMainThread]); OWSAssert([NSThread isMainThread]);
DDLogInfo(@"gestureDidStartVoiceMemo"); DDLogInfo(@"voiceMemoGestureDidStart");
[((OWSMessagesInputToolbar *)self.inputToolbar)showVoiceMemoUI]; [((OWSMessagesInputToolbar *)self.inputToolbar)showVoiceMemoUI];
[self startRecordingVoiceMemo]; [self startRecordingVoiceMemo];
} }
- (void)gestureDidEndVoiceMemo - (void)voiceMemoGestureDidEnd
{ {
OWSAssert([NSThread isMainThread]); OWSAssert([NSThread isMainThread]);
DDLogInfo(@"gestureDidEndVoiceMemo"); DDLogInfo(@"voiceMemoGestureDidEnd");
[((OWSMessagesInputToolbar *)self.inputToolbar) hideVoiceMemoUI:YES]; [((OWSMessagesInputToolbar *)self.inputToolbar) hideVoiceMemoUI:YES];
[self endRecordingVoiceMemo]; [self endRecordingVoiceMemo];
} }
- (void)gestureDidCancelVoiceMemo - (void)voiceMemoGestureDidCancel
{ {
OWSAssert([NSThread isMainThread]); OWSAssert([NSThread isMainThread]);
DDLogInfo(@"gestureDidCancelVoiceMemo"); DDLogInfo(@"voiceMemoGestureDidCancel");
[((OWSMessagesInputToolbar *)self.inputToolbar) hideVoiceMemoUI:NO]; [((OWSMessagesInputToolbar *)self.inputToolbar) hideVoiceMemoUI:NO];
[self cancelRecordingVoiceMemo]; [self cancelRecordingVoiceMemo];
} }
- (void)voiceMemoGestureDidChange:(CGFloat)cancelAlpha
{
OWSAssert([NSThread isMainThread]);
[((OWSMessagesInputToolbar *)self.inputToolbar) setVoiceMemoUICancelAlpha:cancelAlpha];
}
- (void)cancelVoiceMemo - (void)cancelVoiceMemo
{ {
OWSAssert([NSThread isMainThread]); OWSAssert([NSThread isMainThread]);