Swiftgram/submodules/LegacyComponents/Sources/TGEmbedVimeoPlayerView.m
2020-02-22 15:38:54 +04:00

234 lines
6.8 KiB
Objective-C

#import "TGEmbedVimeoPlayerView.h"
#import "TGEmbedPlayerState.h"
#import "LegacyComponentsInternal.h"
NSString *const TGVimeoPlayerCallbackOnReady = @"onReady";
NSString *const TGVimeoPlayerCallbackOnState = @"onState";
@interface TGEmbedVimeoPlayerView ()
{
NSString *_videoId;
bool _started;
bool _initiallyPlayed;
NSInteger _ignorePositionUpdates;
}
@end
@implementation TGEmbedVimeoPlayerView
- (instancetype)initWithWebPageAttachment:(TGWebPageMediaAttachment *)webPage thumbnailSignal:(SSignal *)thumbnailSignal alternateCachePathSignal:(SSignal *)alternateCachePathSignal
{
self = [super initWithWebPageAttachment:webPage thumbnailSignal:thumbnailSignal alternateCachePathSignal:alternateCachePathSignal];
if (self != nil)
{
_videoId = [TGEmbedVimeoPlayerView _vimeoVideoIdFromText:webPage.embedUrl];
}
return self;
}
- (void)playVideo
{
[super playVideo];
if (_initiallyPlayed)
{
[self _evaluateJS:@"player.api('play');" completion:nil];
}
else
{
[self _evaluateJS:@"injectCmd('initialPlay')" completion:nil];
_initiallyPlayed = true;
}
_ignorePositionUpdates = 2;
}
- (void)pauseVideo:(bool)manually
{
[super pauseVideo:manually];
[self _evaluateJS:@"player.api('pause');" completion:nil];
}
- (void)seekToPosition:(NSTimeInterval)position
{
NSString *command = [NSString stringWithFormat:@"player.api('seekTo', %@);", @(position)];
[self _evaluateJS:command completion:nil];
TGEmbedPlayerState *newState = [TGEmbedPlayerState stateWithPlaying:self.state.isPlaying duration:self.state.duration position:position downloadProgress:self.state.downloadProgress buffering:self.state.buffering];
[self updateState:newState];
_ignorePositionUpdates = 2;
}
- (TGEmbedPlayerControlsType)_controlsType
{
return TGEmbedPlayerControlsTypeFull;
}
- (void)_onPageReady
{
}
- (void)_didBeginPlayback
{
[super _didBeginPlayback];
TGDispatchAfter(0.5, dispatch_get_main_queue(), ^
{
[self setDimmed:false animated:true shouldDelay:false];
});
}
- (void)_notifyOfCallbackURL:(NSURL *)url
{
NSString *action = url.host;
NSString *query = url.query;
NSString *data;
if (query != nil)
data = [query componentsSeparatedByString:@"="][1];
if ([action isEqual:TGVimeoPlayerCallbackOnReady])
{
}
else if ([action isEqualToString:TGVimeoPlayerCallbackOnState])
{
NSURLComponents *urlComponents = [NSURLComponents componentsWithURL:url resolvingAgainstBaseURL:false];
NSArray *queryItems = urlComponents.queryItems;
bool playing = self.state.playing;
bool finished = false;
NSTimeInterval position = self.state.position;
NSTimeInterval duration = self.state.duration;
CGFloat downloadProgress = self.state.downloadProgress;
bool buffering = self.state.buffering;
for (NSURLQueryItem *queryItem in queryItems)
{
if ([queryItem.name isEqualToString:@"playback"])
{
playing = ([queryItem.value integerValue] == 1);
finished = ([queryItem.value integerValue] == 2);
}
else if ([queryItem.name isEqualToString:@"position"])
{
if (_ignorePositionUpdates > 0)
_ignorePositionUpdates--;
else
position = [queryItem.value doubleValue];
}
else if ([queryItem.name isEqualToString:@"duration"])
{
duration = [queryItem.value doubleValue];
}
else if ([queryItem.name isEqualToString:@"download"])
{
downloadProgress = [queryItem.value floatValue];
}
}
if (!_started && playing)
{
_started = true;
[self _didBeginPlayback];
}
if (finished)
position = 0.0;
TGEmbedPlayerState *newState = [TGEmbedPlayerState stateWithPlaying:playing duration:duration position:position downloadProgress:downloadProgress buffering:buffering];
[self updateState:newState];
}
}
- (NSString *)_embedHTML
{
NSError *error = nil;
NSString *path = TGComponentsPathForResource(@"VimeoPlayer", @"html");
NSString *embedHTMLTemplate = [NSString stringWithContentsOfFile:path encoding:NSUTF8StringEncoding error:&error];
if (error != nil)
{
TGLegacyLog(@"[VimeoEmbedPlayer]: Received error rendering template: %@", error);
return nil;
}
NSString *autoplay = self.disallowAutoplay ? @"false" : @"true";
NSString *embedHTML = [NSString stringWithFormat:embedHTMLTemplate, _videoId, autoplay];
return embedHTML;
}
- (NSURL *)_baseURL
{
return [NSURL URLWithString:@"https://player.vimeo.com/"];
}
- (void)_setupUserScripts:(WKUserContentController *)contentController
{
NSError *error = nil;
NSString *path = TGComponentsPathForResource(@"VimeoPlayerInject", @"js");
NSString *scriptText = [NSString stringWithContentsOfFile:path encoding:NSUTF8StringEncoding error:&error];
if (error != nil)
TGLegacyLog(@"[VimeoEmbedPlayer]: Received error loading inject script: %@", error);
WKUserScript *script = [[WKUserScript alloc] initWithSource:scriptText injectionTime:WKUserScriptInjectionTimeAtDocumentEnd forMainFrameOnly:false];
[contentController addUserScript:script];
}
- (bool)_scaleViewToMaxSize
{
return true;
}
+ (NSString *)_vimeoVideoIdFromText:(NSString *)text
{
if ([text hasPrefix:@"http://player.vimeo.com/video/"] || [text hasPrefix:@"https://player.vimeo.com/video/"])
{
NSString *suffix = @"";
NSMutableArray *prefixes = [NSMutableArray arrayWithArray:@
[
@"http://player.vimeo.com/video/",
@"https://player.vimeo.com/video/"
]];
while (suffix.length == 0 && prefixes.count > 0)
{
NSString *prefix = prefixes.firstObject;
if ([text hasPrefix:prefix])
{
suffix = [text substringFromIndex:prefix.length];
break;
}
else
{
[prefixes removeObjectAtIndex:0];
}
}
for (int i = 0; i < (int)suffix.length; i++)
{
unichar c = [suffix characterAtIndex:i];
if (!((c >= '0' && c <= '9')))
break;
}
return suffix;
}
return nil;
}
+ (bool)_supportsWebPage:(TGWebPageMediaAttachment *)webPage
{
NSString *url = webPage.embedUrl;
return ([url hasPrefix:@"http://player.vimeo.com/video/"] || [url hasPrefix:@"https://player.vimeo.com/video/"]);
}
@end