mirror of
https://github.com/danog/Telegram.git
synced 2024-12-04 10:27:46 +01:00
530 lines
18 KiB
Mathematica
530 lines
18 KiB
Mathematica
|
/*
|
||
|
* This is the source code of Telegram for iOS v. 1.1
|
||
|
* It is licensed under GNU GPL v. 2 or later.
|
||
|
* You should have received a copy of the license in this archive (see LICENSE).
|
||
|
*
|
||
|
* Copyright Peter Iakovlev, 2013.
|
||
|
*/
|
||
|
|
||
|
#import "TGAudioMessageViewModel.h"
|
||
|
|
||
|
#import "TGImageUtils.h"
|
||
|
#import "TGMessage.h"
|
||
|
|
||
|
#import "TGFont.h"
|
||
|
|
||
|
#import "TGModernViewContext.h"
|
||
|
#import "TGTelegraphConversationMessageAssetsSource.h"
|
||
|
#import "TGModernConversationItem.h"
|
||
|
#import "TGModernButtonViewModel.h"
|
||
|
#import "TGTextMessageBackgroundViewModel.h"
|
||
|
#import "TGModernLabelViewModel.h"
|
||
|
#import "TGModernFlatteningViewModel.h"
|
||
|
#import "TGModernDateViewModel.h"
|
||
|
#import "TGModernColorViewModel.h"
|
||
|
#import "TGAudioSliderViewModel.h"
|
||
|
#import "TGModernTextViewModel.h"
|
||
|
|
||
|
#import "TGAudioSliderView.h"
|
||
|
#import "TGModernViewInlineMediaContext.h"
|
||
|
#import "TGDoubleTapGestureRecognizer.h"
|
||
|
|
||
|
typedef enum {
|
||
|
TGAudioMessageButtonPlay = 0,
|
||
|
TGAudioMessageButtonPause = 1,
|
||
|
TGAudioMessageButtonDownload = 2,
|
||
|
TGAudioMessageButtonCancel = 3
|
||
|
} TGAudioMessageButtonType;
|
||
|
|
||
|
@interface TGAudioMessageViewModel () <TGModernViewInlineMediaContextDelegate, TGAudioSliderViewDelegate>
|
||
|
{
|
||
|
bool _progressVisible;
|
||
|
bool _mediaIsAvailable;
|
||
|
float _progress;
|
||
|
|
||
|
int32_t _duration;
|
||
|
|
||
|
CGPoint _boundOffset;
|
||
|
|
||
|
TGAudioMediaAttachment *_audio;
|
||
|
TGModernButtonViewModel *_playButtonModel;
|
||
|
TGAudioMessageButtonType _playButtonType;
|
||
|
|
||
|
TGAudioSliderViewModel *_sliderModel;
|
||
|
|
||
|
CGFloat _headerHeight;
|
||
|
|
||
|
bool _isPlayerActive;
|
||
|
bool _isPaused;
|
||
|
float _audioPosition;
|
||
|
NSTimeInterval _preciseDuration;
|
||
|
|
||
|
NSTimeInterval _audioPositionTimestamp;
|
||
|
|
||
|
TGModernViewInlineMediaContext *_inlineMediaContext;
|
||
|
}
|
||
|
|
||
|
@end
|
||
|
|
||
|
@implementation TGAudioMessageViewModel
|
||
|
|
||
|
static UIImage *playImageWithColor(UIColor *color)
|
||
|
{
|
||
|
CGFloat radius = 28.0f;
|
||
|
UIGraphicsBeginImageContextWithOptions(CGSizeMake(radius, radius), false, 0.0f);
|
||
|
CGContextRef context = UIGraphicsGetCurrentContext();
|
||
|
|
||
|
CGContextSetFillColorWithColor(context, color.CGColor);
|
||
|
CGContextFillEllipseInRect(context, CGRectMake(0.0f, 0.0f, radius, radius));
|
||
|
|
||
|
CGContextSetBlendMode(context, kCGBlendModeCopy);
|
||
|
|
||
|
CGContextBeginPath(context);
|
||
|
CGContextMoveToPoint(context, 11.0f, 8.0f);
|
||
|
CGContextAddLineToPoint(context, 21.0f, 14.0f);
|
||
|
CGContextAddLineToPoint(context, 11.0f, 20.0f);
|
||
|
CGContextClosePath(context);
|
||
|
CGContextSetFillColorWithColor(context, [UIColor clearColor].CGColor);
|
||
|
CGContextFillPath(context);
|
||
|
|
||
|
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
|
||
|
UIGraphicsEndImageContext();
|
||
|
|
||
|
return image;
|
||
|
}
|
||
|
|
||
|
static UIImage *pauseImageWithColor(UIColor *color)
|
||
|
{
|
||
|
CGFloat radius = 28.0f;
|
||
|
UIGraphicsBeginImageContextWithOptions(CGSizeMake(radius, radius), false, 0.0f);
|
||
|
CGContextRef context = UIGraphicsGetCurrentContext();
|
||
|
|
||
|
CGContextSetFillColorWithColor(context, color.CGColor);
|
||
|
CGContextFillEllipseInRect(context, CGRectMake(0.0f, 0.0f, radius, radius));
|
||
|
|
||
|
CGContextSetBlendMode(context, kCGBlendModeCopy);
|
||
|
CGContextSetFillColorWithColor(context, [UIColor clearColor].CGColor);
|
||
|
CGContextFillRect(context, CGRectMake(10.0f, 9.0f, 2.5f, 10.0f));
|
||
|
CGContextFillRect(context, CGRectMake(15.5f, 9.0f, 2.5f, 10.0f));
|
||
|
|
||
|
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
|
||
|
UIGraphicsEndImageContext();
|
||
|
|
||
|
return image;
|
||
|
}
|
||
|
|
||
|
static UIImage *downloadImageWithColor(UIColor *color)
|
||
|
{
|
||
|
CGFloat radius = 28.0f;
|
||
|
UIGraphicsBeginImageContextWithOptions(CGSizeMake(radius, radius), false, 0.0f);
|
||
|
CGContextRef context = UIGraphicsGetCurrentContext();
|
||
|
|
||
|
CGContextSetStrokeColorWithColor(context, color.CGColor);
|
||
|
CGContextSetLineWidth(context, 1.0f);
|
||
|
CGContextStrokeEllipseInRect(context, CGRectMake(0.5f, 0.5f, radius - 1.0f, radius - 1.0f));
|
||
|
|
||
|
CGContextSetFillColorWithColor(context, color.CGColor);
|
||
|
CGContextFillRect(context, CGRectMake(13.0f, 8.5f, 2.0f, 8.0f));
|
||
|
|
||
|
CGContextBeginPath(context);
|
||
|
CGContextMoveToPoint(context, 10.0f, 16.5f);
|
||
|
CGContextAddLineToPoint(context, 18.0f, 16.5f);
|
||
|
CGContextAddLineToPoint(context, 14.5f, 20.5f);
|
||
|
CGContextAddLineToPoint(context, 13.5f, 20.5f);
|
||
|
CGContextClosePath(context);
|
||
|
CGContextFillPath(context);
|
||
|
|
||
|
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
|
||
|
UIGraphicsEndImageContext();
|
||
|
|
||
|
return image;
|
||
|
}
|
||
|
|
||
|
static UIImage *cancelImageWithColor(UIColor *color, bool incoming)
|
||
|
{
|
||
|
CGFloat radius = 28.0f;
|
||
|
UIGraphicsBeginImageContextWithOptions(CGSizeMake(radius, radius), false, 0.0f);
|
||
|
CGContextRef context = UIGraphicsGetCurrentContext();
|
||
|
|
||
|
CGContextSetStrokeColorWithColor(context, color.CGColor);
|
||
|
CGContextSetLineWidth(context, 1.0f);
|
||
|
CGContextStrokeEllipseInRect(context, CGRectMake(0.5f, 0.5f, radius - 1.0f, radius - 1.0f));
|
||
|
|
||
|
UIImage *crossImage = incoming ? [UIImage imageNamed:@"ModernMessageAudioCancel_Incoming.png"] : [UIImage imageNamed:@"ModernMessageAudioCancel_Outgoing.png"];
|
||
|
CGContextDrawImage(context, CGRectMake(CGFloor((radius - crossImage.size.width) / 2), CGFloor((radius - crossImage.size.height) / 2), crossImage.size.width, crossImage.size.height), crossImage.CGImage);
|
||
|
|
||
|
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
|
||
|
UIGraphicsEndImageContext();
|
||
|
|
||
|
return image;
|
||
|
}
|
||
|
|
||
|
- (UIImage *)playImage:(bool)incoming
|
||
|
{
|
||
|
static UIImage *incomingImage = nil;
|
||
|
static UIImage *outgoingImage = nil;
|
||
|
static dispatch_once_t onceToken;
|
||
|
dispatch_once(&onceToken, ^
|
||
|
{
|
||
|
incomingImage = playImageWithColor(TGAccentColor());
|
||
|
outgoingImage = playImageWithColor(UIColorRGB(0x3fc33b));
|
||
|
});
|
||
|
|
||
|
return incoming ? incomingImage : outgoingImage;
|
||
|
}
|
||
|
|
||
|
- (UIImage *)pauseImage:(bool)incoming
|
||
|
{
|
||
|
static UIImage *incomingImage = nil;
|
||
|
static UIImage *outgoingImage = nil;
|
||
|
static dispatch_once_t onceToken;
|
||
|
dispatch_once(&onceToken, ^
|
||
|
{
|
||
|
incomingImage = pauseImageWithColor(TGAccentColor());
|
||
|
outgoingImage = pauseImageWithColor(UIColorRGB(0x3fc33b));
|
||
|
});
|
||
|
|
||
|
return incoming ? incomingImage : outgoingImage;
|
||
|
}
|
||
|
|
||
|
- (UIImage *)downloadImage:(bool)incoming
|
||
|
{
|
||
|
static UIImage *incomingImage = nil;
|
||
|
static UIImage *outgoingImage = nil;
|
||
|
static dispatch_once_t onceToken;
|
||
|
dispatch_once(&onceToken, ^
|
||
|
{
|
||
|
incomingImage = downloadImageWithColor(TGAccentColor());
|
||
|
outgoingImage = downloadImageWithColor(UIColorRGB(0x3fc33b));
|
||
|
});
|
||
|
|
||
|
return incoming ? incomingImage : outgoingImage;
|
||
|
}
|
||
|
|
||
|
- (UIImage *)cancelImage:(bool)incoming
|
||
|
{
|
||
|
static UIImage *incomingImage = nil;
|
||
|
static UIImage *outgoingImage = nil;
|
||
|
static dispatch_once_t onceToken;
|
||
|
dispatch_once(&onceToken, ^
|
||
|
{
|
||
|
incomingImage = cancelImageWithColor(TGAccentColor(), true);
|
||
|
outgoingImage = cancelImageWithColor(UIColorRGB(0x3fc33b), false);
|
||
|
});
|
||
|
|
||
|
return incoming ? incomingImage : outgoingImage;
|
||
|
}
|
||
|
|
||
|
- (instancetype)initWithMessage:(TGMessage *)message audio:(TGAudioMediaAttachment *)audio author:(TGUser *)author context:(TGModernViewContext *)context
|
||
|
{
|
||
|
self = [super initWithMessage:message author:author context:context];
|
||
|
if (self != nil)
|
||
|
{
|
||
|
_audio = audio;
|
||
|
|
||
|
_playButtonModel = [[TGModernButtonViewModel alloc] init];
|
||
|
[_playButtonModel setBackgroundImage:[self downloadImage:_incoming]];
|
||
|
_playButtonModel.modernHighlight = true;
|
||
|
_playButtonModel.skipDrawInContext = true;
|
||
|
[self updateButtonText:false];
|
||
|
[self addSubmodel:_playButtonModel];
|
||
|
|
||
|
_duration = audio.duration;
|
||
|
_isPaused = true;
|
||
|
|
||
|
_sliderModel = [[TGAudioSliderViewModel alloc] init];
|
||
|
_sliderModel.incoming = _incoming;
|
||
|
_sliderModel.duration = _duration;
|
||
|
_sliderModel.audioDurationText = [[NSString alloc] initWithFormat:@"%d:%02d", (int)audio.duration / 60, (int)audio.duration % 60];
|
||
|
[self addSubmodel:_sliderModel];
|
||
|
}
|
||
|
return self;
|
||
|
}
|
||
|
|
||
|
- (void)updateButtonText:(bool)animated
|
||
|
{
|
||
|
TGAudioMessageButtonType playButtonType = TGAudioMessageButtonPlay;
|
||
|
|
||
|
_sliderModel.progressMode = _progressVisible || !_mediaIsAvailable;
|
||
|
|
||
|
if (_progressVisible)
|
||
|
{
|
||
|
playButtonType = TGAudioMessageButtonCancel;
|
||
|
|
||
|
[_sliderModel setAudioPosition:_progress animated:animated timestamp:DBL_MAX isPlaying:false];
|
||
|
|
||
|
_sliderModel.audioDurationText = [[NSString alloc] initWithFormat:@"%d:%02d", (int)_audio.duration / 60, (int)_audio.duration % 60];
|
||
|
|
||
|
_sliderModel.manualPositionAdjustmentEnabled = false;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
if (_mediaIsAvailable)
|
||
|
playButtonType = _isPaused ? TGAudioMessageButtonPlay : TGAudioMessageButtonPause;
|
||
|
else
|
||
|
playButtonType = TGAudioMessageButtonDownload;
|
||
|
|
||
|
_sliderModel.viewUserInteractionDisabled = !_isPlayerActive;
|
||
|
|
||
|
[_sliderModel setPreciseDuration:_preciseDuration];
|
||
|
bool isPlaying = _isPlayerActive && !_isPaused;
|
||
|
[_sliderModel setAudioPosition:_audioPosition animated:animated timestamp:isPlaying ? _audioPositionTimestamp : DBL_MAX isPlaying:isPlaying];
|
||
|
|
||
|
int currentDuration = _isPlayerActive ? (int)(_duration * _audioPosition) : (int)_duration;
|
||
|
_sliderModel.audioDurationText = [[NSString alloc] initWithFormat:@"%d:%02d", (int)currentDuration / 60, (int)currentDuration % 60];
|
||
|
|
||
|
_sliderModel.manualPositionAdjustmentEnabled = _isPlayerActive;
|
||
|
}
|
||
|
|
||
|
if (_playButtonType != playButtonType)
|
||
|
{
|
||
|
_playButtonType = playButtonType;
|
||
|
|
||
|
switch (_playButtonType)
|
||
|
{
|
||
|
case TGAudioMessageButtonPlay:
|
||
|
[_playButtonModel setBackgroundImage:[self playImage:_incoming]];
|
||
|
break;
|
||
|
case TGAudioMessageButtonPause:
|
||
|
[_playButtonModel setBackgroundImage:[self pauseImage:_incoming]];
|
||
|
break;
|
||
|
case TGAudioMessageButtonDownload:
|
||
|
[_playButtonModel setBackgroundImage:[self downloadImage:_incoming]];
|
||
|
break;
|
||
|
case TGAudioMessageButtonCancel:
|
||
|
[_playButtonModel setBackgroundImage:[self cancelImage:_incoming]];
|
||
|
break;
|
||
|
default:
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return;
|
||
|
|
||
|
NSMutableString *text = [[NSMutableString alloc] init];
|
||
|
|
||
|
if (_progressVisible)
|
||
|
{
|
||
|
if (_deliveryState == TGMessageDeliveryStatePending)
|
||
|
[text appendFormat:@"Uploading %d%%", (int)(_progress * 100)];
|
||
|
else
|
||
|
[text appendFormat:@"Downloading %d%%", (int)(_progress * 100)];
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
if (_mediaIsAvailable)
|
||
|
[text appendFormat:@"Play %" PRId32 "s", _audio.duration];
|
||
|
else
|
||
|
[text appendFormat:@"Download %" PRId32 "kB", _audio.fileSize / 1024];
|
||
|
}
|
||
|
|
||
|
[_playButtonModel setPossibleTitles:@[text]];
|
||
|
|
||
|
if (self.frame.size.width > FLT_EPSILON)
|
||
|
{
|
||
|
[_playButtonModel layoutForContainerSize:CGSizeMake(200.0f, 0.0f)];
|
||
|
CGRect playButtonFrame = _playButtonModel.frame;
|
||
|
playButtonFrame.origin = CGPointMake(_backgroundModel.frame.origin.x + 4.0f, 4.0f);
|
||
|
_playButtonModel.frame = playButtonFrame;
|
||
|
|
||
|
if ([_playButtonModel boundView] != nil)
|
||
|
[_playButtonModel boundView].frame = CGRectOffset([_playButtonModel boundView].frame, _boundOffset.x, _boundOffset.y);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
- (void)updateMessage:(TGMessage *)message viewStorage:(TGModernViewStorage *)viewStorage
|
||
|
{
|
||
|
[super updateMessage:message viewStorage:viewStorage];
|
||
|
|
||
|
[self updateButtonText:false];
|
||
|
}
|
||
|
|
||
|
- (void)updateMediaAvailability:(bool)mediaIsAvailable viewStorage:(TGModernViewStorage *)__unused viewStorage
|
||
|
{
|
||
|
[super updateMediaAvailability:mediaIsAvailable viewStorage:viewStorage];
|
||
|
|
||
|
_mediaIsAvailable = mediaIsAvailable;
|
||
|
|
||
|
[self updateButtonText:false];
|
||
|
}
|
||
|
|
||
|
- (void)updateProgress:(bool)progressVisible progress:(float)progress viewStorage:(TGModernViewStorage *)viewStorage
|
||
|
{
|
||
|
[super updateProgress:progressVisible progress:progress viewStorage:viewStorage];
|
||
|
_progressVisible = progressVisible;
|
||
|
_progress = progress;
|
||
|
|
||
|
[self updateButtonText:_progress < 0.01f ? false : true];
|
||
|
}
|
||
|
|
||
|
- (void)updateInlineMediaContext
|
||
|
{
|
||
|
bool isPlayerActive = false;
|
||
|
bool isPaused = true;
|
||
|
float audioPosition = 0.0f;
|
||
|
NSTimeInterval playbackPositionTimestamp = DBL_MAX;
|
||
|
|
||
|
_inlineMediaContext = [_context inlineMediaContext:_mid];
|
||
|
if (_inlineMediaContext != nil)
|
||
|
{
|
||
|
_inlineMediaContext.delegate = self;
|
||
|
|
||
|
isPlayerActive = true;
|
||
|
isPaused = [_inlineMediaContext isPaused];
|
||
|
audioPosition = [_inlineMediaContext playbackPosition:&playbackPositionTimestamp];
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
isPlayerActive = false;
|
||
|
isPaused = true;
|
||
|
audioPosition = 0.0f;
|
||
|
}
|
||
|
|
||
|
if (_isPlayerActive != isPlayerActive || _isPaused != isPaused || ABS(audioPosition - _audioPosition) > FLT_EPSILON || ABS(playbackPositionTimestamp - _audioPositionTimestamp) > DBL_EPSILON)
|
||
|
{
|
||
|
_isPlayerActive = isPlayerActive;
|
||
|
_isPaused = isPaused;
|
||
|
_audioPosition = audioPosition;
|
||
|
_audioPositionTimestamp = playbackPositionTimestamp;
|
||
|
|
||
|
[self updateButtonText:false];
|
||
|
}
|
||
|
}
|
||
|
|
||
|
- (void)bindSpecialViewsToContainer:(UIView *)container viewStorage:(TGModernViewStorage *)viewStorage atItemPosition:(CGPoint)itemPosition
|
||
|
{
|
||
|
_boundOffset = itemPosition;
|
||
|
|
||
|
[super bindSpecialViewsToContainer:container viewStorage:viewStorage atItemPosition:itemPosition];
|
||
|
|
||
|
[_playButtonModel bindViewToContainer:container viewStorage:viewStorage];
|
||
|
[_playButtonModel boundView].frame = CGRectOffset([_playButtonModel boundView].frame, itemPosition.x, itemPosition.y);
|
||
|
|
||
|
[_sliderModel bindViewToContainer:container viewStorage:viewStorage];
|
||
|
[_sliderModel boundView].frame = CGRectOffset([_sliderModel boundView].frame, itemPosition.x, itemPosition.y);
|
||
|
}
|
||
|
|
||
|
- (void)bindViewToContainer:(UIView *)container viewStorage:(TGModernViewStorage *)viewStorage
|
||
|
{
|
||
|
_boundOffset = CGPointZero;
|
||
|
|
||
|
[self updateInlineMediaContext];
|
||
|
|
||
|
[self updateEditingState:nil viewStorage:nil animationDelay:-1.0];
|
||
|
|
||
|
[super bindViewToContainer:container viewStorage:viewStorage];
|
||
|
|
||
|
[(UIButton *)[_playButtonModel boundView] addTarget:self action:@selector(playButtonPressed) forControlEvents:UIControlEventTouchUpInside];
|
||
|
|
||
|
((TGAudioSliderView *)[_sliderModel boundView]).delegate = self;
|
||
|
}
|
||
|
|
||
|
- (void)unbindView:(TGModernViewStorage *)viewStorage
|
||
|
{
|
||
|
[(UIButton *)[_playButtonModel boundView] removeTarget:self action:@selector(playButtonPressed) forControlEvents:UIControlEventTouchUpInside];
|
||
|
|
||
|
((TGAudioSliderView *)[_sliderModel boundView]).delegate = nil;
|
||
|
|
||
|
[_inlineMediaContext removeDelegate:self];
|
||
|
|
||
|
[super unbindView:viewStorage];
|
||
|
}
|
||
|
|
||
|
- (void)playButtonPressed
|
||
|
{
|
||
|
if (_playButtonType == TGAudioMessageButtonCancel)
|
||
|
[_context.companionHandle requestAction:@"mediaProgressCancelRequested" options:@{@"mid": @(_mid)}];
|
||
|
else
|
||
|
{
|
||
|
if (_mediaIsAvailable)
|
||
|
{
|
||
|
if (_inlineMediaContext != nil)
|
||
|
{
|
||
|
if (_isPaused)
|
||
|
[_inlineMediaContext play];
|
||
|
else
|
||
|
[_inlineMediaContext pause];
|
||
|
}
|
||
|
else if (!_isPlayerActive)
|
||
|
[_context.companionHandle requestAction:@"openMediaRequested" options:@{@"mid": @(_mid)}];
|
||
|
else
|
||
|
[_inlineMediaContext pause];
|
||
|
}
|
||
|
else
|
||
|
[_context.companionHandle requestAction:@"mediaDownloadRequested" options:@{@"mid": @(_mid)}];
|
||
|
}
|
||
|
}
|
||
|
|
||
|
- (void)layoutContentForHeaderHeight:(CGFloat)headerHeight
|
||
|
{
|
||
|
_headerHeight = headerHeight;
|
||
|
}
|
||
|
|
||
|
- (CGSize)contentSizeForContainerSize:(CGSize)__unused containerSize needsContentsUpdate:(bool *)__unused needsContentsUpdate
|
||
|
{
|
||
|
return CGSizeMake(MAX(160, MIN(205, _duration * 30)), 41);
|
||
|
}
|
||
|
|
||
|
- (void)layoutForContainerSize:(CGSize)containerSize
|
||
|
{
|
||
|
[super layoutForContainerSize:containerSize];
|
||
|
|
||
|
_playButtonModel.frame = CGRectMake(_backgroundModel.frame.origin.x + (_incoming ? 14.0f : 9.0f), _headerHeight + _backgroundModel.frame.origin.y + 11.0f, 28.0f, 28.0f);
|
||
|
|
||
|
CGFloat trackOriginX = CGRectGetMaxX(_playButtonModel.frame) + 5.0f;
|
||
|
CGRect sliderFrame = CGRectMake(trackOriginX, _playButtonModel.frame.origin.y + 7.0f, CGRectGetMaxX(_backgroundModel.frame) - trackOriginX - 13.0f + (_incoming ? 5.0f : 0.0f), 14.0f);
|
||
|
_sliderModel.frame = sliderFrame;
|
||
|
}
|
||
|
|
||
|
- (void)inlineMediaPlaybackStateUpdated:(bool)isPaused playbackPosition:(float)playbackPosition timestamp:(MTAbsoluteTime)timestamp preciseDuration:(NSTimeInterval)preciseDuration
|
||
|
{
|
||
|
_isPaused = isPaused;
|
||
|
_audioPosition = playbackPosition;
|
||
|
_audioPositionTimestamp = timestamp;
|
||
|
_preciseDuration = preciseDuration;
|
||
|
|
||
|
[self updateButtonText:false];
|
||
|
}
|
||
|
|
||
|
- (void)audioSliderViewDidBeginPositionAdjustment:(TGAudioSliderView *)__unused audioSliderView
|
||
|
{
|
||
|
[_inlineMediaContext pause];
|
||
|
}
|
||
|
|
||
|
- (void)audioSliderViewDidEndPositionAdjustment:(TGAudioSliderView *)__unused audioSliderView atPosition:(float)position
|
||
|
{
|
||
|
[_inlineMediaContext play:position];
|
||
|
}
|
||
|
|
||
|
- (void)audioSliderViewDidCancelPositionAdjustment:(TGAudioSliderView *)__unused audioSliderView
|
||
|
{
|
||
|
[_inlineMediaContext play];
|
||
|
}
|
||
|
|
||
|
- (int)gestureRecognizer:(TGDoubleTapGestureRecognizer *)__unused recognizer shouldFailTap:(CGPoint)__unused point
|
||
|
{
|
||
|
return 3;
|
||
|
}
|
||
|
|
||
|
- (void)messageDoubleTapGesture:(TGDoubleTapGestureRecognizer *)recognizer
|
||
|
{
|
||
|
if (recognizer.state != UIGestureRecognizerStateBegan)
|
||
|
{
|
||
|
if (recognizer.state == UIGestureRecognizerStateRecognized)
|
||
|
{
|
||
|
CGPoint point = [recognizer locationInView:[_contentModel boundView]];
|
||
|
|
||
|
if (recognizer.longTapped)
|
||
|
[_context.companionHandle requestAction:@"messageSelectionRequested" options:@{@"mid": @(_mid)}];
|
||
|
else if (recognizer.doubleTapped)
|
||
|
[_context.companionHandle requestAction:@"messageSelectionRequested" options:@{@"mid": @(_mid)}];
|
||
|
else if (_forwardedHeaderModel && CGRectContainsPoint(_forwardedHeaderModel.frame, point))
|
||
|
[_context.companionHandle requestAction:@"userAvatarTapped" options:@{@"uid": @(_forwardedUid)}];
|
||
|
else if (!_isPlayerActive || _isPaused)
|
||
|
[self playButtonPressed];
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
@end
|