1
0
mirror of https://github.com/danog/Telegram.git synced 2024-12-02 09:27:55 +01:00
Telegram/Telegraph/TGMusicPlayerView.m
2016-02-25 01:03:51 +01:00

344 lines
12 KiB
Objective-C

#import "TGMusicPlayerView.h"
#import "TGImageUtils.h"
#import "TGFont.h"
#import "TGModernButton.h"
#import "TGTelegraph.h"
#import "TGMusicPlayerController.h"
#import "TGNavigationController.h"
#import "TGDateUtils.h"
#import <pop/POP.h>
@interface TGMusicPlayerView ()
{
__weak UINavigationController *_navigationController;
UIView *_minimizedBar;
UIButton *_minimizedButton;
UIView *_minimizedBarStripe;
UILabel *_titleLabel;
UILabel *_performerLabel;
UIView *_scrubbingIndicator;
TGModernButton *_closeButton;
TGModernButton *_pauseButton;
TGModernButton *_playButton;
id<SDisposable> _playerStatusDisposable;
TGMusicPlayerStatus *_currentStatus;
NSString *_title;
NSString *_performer;
CGFloat _playbackOffset;
bool _isVoice;
bool _updateLabelsLayout;
}
@end
@implementation TGMusicPlayerView
- (instancetype)initWithNavigationController:(UINavigationController *)navigationController
{
self = [super init];
if (self != nil)
{
_navigationController = navigationController;
self.clipsToBounds = true;
_minimizedBar = [[UIView alloc] init];
_minimizedBar.backgroundColor = UIColorRGB(0xf7f7f7);
_minimizedButton = [[UIButton alloc] init];
[_minimizedButton addTarget:self action:@selector(minimizedButtonPressed) forControlEvents:UIControlEventTouchUpInside];
[_minimizedBar addSubview:_minimizedButton];
[self addSubview:_minimizedBar];
_minimizedBarStripe = [[UIView alloc] init];
_minimizedBarStripe.backgroundColor = UIColorRGB(0xb2b2b2);
[_minimizedBar addSubview:_minimizedBarStripe];
_closeButton = [[TGModernButton alloc] init];
_closeButton.adjustsImageWhenHighlighted = false;
[_closeButton setImage:[UIImage imageNamed:@"MusicPlayerMinimizedClose.png"] forState:UIControlStateNormal];
[_closeButton addTarget:self action:@selector(closeButtonPressed) forControlEvents:UIControlEventTouchUpInside];
[_minimizedBar addSubview:_closeButton];
_playButton = [[TGModernButton alloc] init];
_playButton.adjustsImageWhenHighlighted = false;
[_playButton setImage:[UIImage imageNamed:@"MusicPlayerMinimizedPlay.png"] forState:UIControlStateNormal];
[_playButton addTarget:self action:@selector(playButtonPressed) forControlEvents:UIControlEventTouchUpInside];
[_minimizedBar addSubview:_playButton];
_playButton.hidden = true;
_pauseButton = [[TGModernButton alloc] init];
_pauseButton.adjustsImageWhenHighlighted = false;
[_pauseButton setImage:[UIImage imageNamed:@"MusicPlayerMinimizedPause.png"] forState:UIControlStateNormal];
[_pauseButton addTarget:self action:@selector(pauseButtonPressed) forControlEvents:UIControlEventTouchUpInside];
[_minimizedBar addSubview:_pauseButton];
_pauseButton.hidden = true;
_titleLabel = [[UILabel alloc] init];
_titleLabel.backgroundColor = [UIColor clearColor];
_titleLabel.textColor = [UIColor blackColor];
_titleLabel.font = TGSystemFontOfSize(12.0f);
[_minimizedBar addSubview:_titleLabel];
_performerLabel = [[UILabel alloc] init];
_performerLabel.backgroundColor = [UIColor clearColor];
_performerLabel.textColor = UIColorRGB(0x8b8b8b);
_performerLabel.font = TGSystemFontOfSize(10.0f);
[_minimizedBar addSubview:_performerLabel];
_scrubbingIndicator = [[UIView alloc] init];
_scrubbingIndicator.backgroundColor = TGAccentColor();
[_minimizedBar addSubview:_scrubbingIndicator];
__weak TGMusicPlayerView *weakSelf = self;
_playerStatusDisposable = [[TGTelegraphInstance.musicPlayer playingStatus] startWithNext:^(TGMusicPlayerStatus *status)
{
__strong TGMusicPlayerView *strongSelf = weakSelf;
if (strongSelf != nil)
{
[strongSelf setStatus:status];
}
}];
UISwipeGestureRecognizer *upSwipeGesture = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(swipeGesture:)];
upSwipeGesture.direction = UISwipeGestureRecognizerDirectionUp;
[_minimizedButton addGestureRecognizer:upSwipeGesture];
_updateLabelsLayout = true;
}
return self;
}
- (void)dealloc
{
[_playerStatusDisposable dispose];
}
- (void)setFrame:(CGRect)frame
{
_updateLabelsLayout = ABS(frame.size.width - self.frame.size.width) > FLT_EPSILON;
[super setFrame:frame];
if (_updateLabelsLayout)
[self setNeedsLayout];
}
- (void)setStatus:(TGMusicPlayerStatus *)status
{
TGMusicPlayerStatus *previousStatus = _currentStatus;
_currentStatus = status;
if (!TGObjectCompare(status.item, previousStatus.item))
{
NSString *title = nil;
NSString *performer = nil;
if (status.item.isVoice) {
if (status.item.author != nil) {
NSString *authorName = [status.item.author displayFirstName];
if (TGTelegraphInstance.clientUserId == status.item.author.uid) {
authorName = TGLocalized(@"DialogList.You");
}
title = authorName;
performer = [TGDateUtils stringForApproximateDate:status.item.date];
} else {
title = TGLocalized(@"MusicPlayer.VoiceNote");
}
} else {
if ([status.item.media isKindOfClass:[TGDocumentMediaAttachment class]]) {
TGDocumentMediaAttachment *document = ((TGDocumentMediaAttachment *)status.item.media);
for (id attribute in document.attributes)
{
if ([attribute isKindOfClass:[TGDocumentAttributeAudio class]])
{
title = ((TGDocumentAttributeAudio *)attribute).title;
performer = ((TGDocumentAttributeAudio *)attribute).performer;
break;
}
}
if (title.length == 0) {
title = document.fileName;
}
}
if (title.length == 0)
title = @"Unknown Track";
if (performer.length == 0)
performer = @"Unknown Artist";
}
if (status != nil)
{
if (!TGStringCompare(_title, title) || !TGStringCompare(_performer, performer))
{
_updateLabelsLayout = true;
_title = title;
_performer = performer;
_titleLabel.text = title;
_performerLabel.text = performer;
[self setNeedsLayout];
}
}
}
static POPAnimatableProperty *property = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^
{
property = [POPAnimatableProperty propertyWithName:@"playbackOffset" initializer:^(POPMutableAnimatableProperty *prop)
{
prop.readBlock = ^(TGMusicPlayerView *strongSelf, CGFloat *values)
{
values[0] = strongSelf->_playbackOffset;
};
prop.writeBlock = ^(TGMusicPlayerView *strongSelf, CGFloat const *values)
{
strongSelf->_playbackOffset = values[0];
[strongSelf layoutScrubbingIndicator];
};
}];
});
_playButton.hidden = !status.paused;
_pauseButton.hidden = status.paused;
_scrubbingIndicator.hidden = status.isVoice;
if (status == nil || status.paused || status.duration < FLT_EPSILON || status.offset < 0.01)
{
[self pop_removeAnimationForKey:@"scrubbingIndicator"];
_playbackOffset = status.offset;
[self layoutScrubbingIndicator];
}
else
{
[self pop_removeAnimationForKey:@"scrubbingIndicator"];
POPBasicAnimation *animation = [self pop_animationForKey:@"scrubbingIndicator"];
if (animation == nil)
{
animation = [POPBasicAnimation linearAnimation];
[animation setProperty:property];
animation.removedOnCompletion = true;
animation.fromValue = @(status.offset);
animation.toValue = @(1.0f);
animation.beginTime = status.timestamp;
animation.duration = (1.0f - status.offset) * status.duration;
[self pop_addAnimation:animation forKey:@"scrubbingIndicator"];
}
}
}
- (void)layoutScrubbingIndicator
{
CGFloat indicatorHeight = 2.0f - TGRetinaPixel;
_scrubbingIndicator.frame = CGRectMake(0.0f, 37.0f - indicatorHeight, TGRetinaFloor(self.frame.size.width * _playbackOffset), indicatorHeight);
}
- (void)layoutSubviews
{
[super layoutSubviews];
self.backgroundColor = [UIColor whiteColor];
_minimizedBar.frame = CGRectMake(0.0f, 0.0f, self.frame.size.width, 37.0f);
CGFloat separatorHeight = TGIsRetina() ? 0.5f : 1.0f;
_minimizedBarStripe.frame = CGRectMake(0.0f, 37.0f - separatorHeight, self.frame.size.width, separatorHeight);
_closeButton.frame = CGRectMake(self.frame.size.width - 44.0f, TGRetinaPixel, 44.0f, 36.0f);
_pauseButton.frame = CGRectMake(0.0f, 0.0f, 46.0f, 36.0f);
_playButton.frame = CGRectMake(0.0f, 0.0f, 48.0f, 36.0f);
CGSize titleSize = _titleLabel.frame.size;
CGSize performerSize = _performerLabel.frame.size;
if (_updateLabelsLayout)
{
titleSize = [_titleLabel.text sizeWithFont:_titleLabel.font];
performerSize = [_performerLabel.text sizeWithFont:_performerLabel.font];
CGFloat maxWidth = self.frame.size.width - 54.0f * 2.0f;
titleSize.width = MIN(titleSize.width, maxWidth);
performerSize.width = MIN(performerSize.width, maxWidth);
}
_titleLabel.frame = CGRectMake(CGFloor((self.frame.size.width - titleSize.width) / 2.0f), _performerLabel.text.length == 0 ? 10.0f : 4.0f, titleSize.width, titleSize.height);
_performerLabel.frame = CGRectMake(CGFloor((self.frame.size.width - performerSize.width) / 2.0f), 20.0f - TGRetinaPixel, performerSize.width, performerSize.height);
_minimizedButton.frame = CGRectMake(44.0f, 0.0f, _minimizedBar.frame.size.width - 44.0f * 2.0f, _minimizedBar.frame.size.height);
[self layoutScrubbingIndicator];
}
- (void)closeButtonPressed
{
[TGTelegraphInstance.musicPlayer setPlaylist:nil initialItemKey:nil metadata:nil];
}
- (void)pauseButtonPressed
{
[TGTelegraphInstance.musicPlayer controlPause];
}
- (void)playButtonPressed
{
[TGTelegraphInstance.musicPlayer controlPlay];
}
- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event
{
CGRect closeButtonFrame = CGRectOffset(_closeButton.frame, _minimizedBar.frame.origin.x, _minimizedBar.frame.origin.y);
if (CGRectContainsPoint(closeButtonFrame, point))
{
return _closeButton;
}
return [super hitTest:point withEvent:event];
}
- (void)minimizedButtonPressed
{
if (_currentStatus.item == nil || _currentStatus.item.isVoice) {
return;
}
TGMusicPlayerController *controller = [[TGMusicPlayerController alloc] init];
TGNavigationController *playerNavigationController = [TGNavigationController navigationControllerWithControllers:@[controller]];
UINavigationController *navigationController = _navigationController;
if ([UIDevice currentDevice].userInterfaceIdiom == UIUserInterfaceIdiomPad) {
playerNavigationController.presentationStyle = TGNavigationControllerPresentationStyleInFormSheet;
playerNavigationController.modalPresentationStyle = UIModalPresentationFormSheet;
playerNavigationController.preferredContentSize = CGSizeMake(414.0f, 667.0f);
} else {
playerNavigationController.restrictLandscape = true;
}
[navigationController presentViewController:playerNavigationController animated:true completion:nil];
}
- (void)swipeGesture:(UISwipeGestureRecognizer *)recognizer
{
if (recognizer.state == UIGestureRecognizerStateEnded)
{
//__strong TGNavigationController *navigationController = (TGNavigationController *)_navigationController;
//[navigationController setMinimizePlayer:true];
}
}
@end