2020-02-22 15:38:54 +04:00

949 lines
27 KiB
Objective-C

#import "TGEmbedPlayerView.h"
#import "LegacyComponentsInternal.h"
#import <LegacyComponents/TGPhotoEditorUtils.h>
#import <LegacyComponents/TGImageView.h>
#import "TGEmbedPlayerState.h"
#import "TGEmbedYoutubePlayerView.h"
#import "TGEmbedVimeoPlayerView.h"
#import "TGEmbedCoubPlayerView.h"
#import "TGEmbedVKPlayerView.h"
#import "TGEmbedVinePlayerView.h"
#import "TGEmbedInstagramPlayerView.h"
#import "TGEmbedSoundCloudPlayerView.h"
#import "TGEmbedTwitchPlayerView.h"
#import "TGEmbedVideoPlayerView.h"
#import <libkern/OSAtomic.h>
@interface TGEmbedPlayerView () <UIWebViewDelegate, WKNavigationDelegate>
{
CGFloat _embedScale;
TGImageView *_coverView;
UIView *_dimView;
UILabel *_errorLabel;
UIWebView *_uiWebView;
WKWebView *_wkWebView;
UIView *_interactionView;
CGSize _maxPlayerSize;
bool _loading;
dispatch_semaphore_t _sema;
SQueue *_jsQueue;
SPipe *_statePipe;
bool _pausedManually;
bool _shouldResumePIPPlayback;
id<SDisposable> _currentAudioSession;
SVariable *_loadProgressValue;
}
@end
@implementation TGEmbedPlayerView
@synthesize requestPictureInPicture = _requestPictureInPicture;
@synthesize disallowPIP = _disallowPIP;
@synthesize initialFrame = _initialFrame;
- (instancetype)initWithWebPageAttachment:(TGWebPageMediaAttachment *)webPage
{
return [self initWithWebPageAttachment:webPage thumbnailSignal:nil];
}
- (instancetype)initWithWebPageAttachment:(TGWebPageMediaAttachment *)webPage thumbnailSignal:(SSignal *)thumbnailSignal
{
return [self initWithWebPageAttachment:webPage thumbnailSignal:nil alternateCachePathSignal:nil];
}
- (instancetype)initWithWebPageAttachment:(TGWebPageMediaAttachment *)webPage thumbnailSignal:(SSignal *)thumbnailSignal alternateCachePathSignal:(SSignal *)__unused alternateCachePathSignal
{
self = [super initWithFrame:CGRectZero];
if (self != nil)
{
self.clipsToBounds = true;
_statePipe = [[SPipe alloc] init];
_loadProgressValue = [[SVariable alloc] init];
_webPage = webPage;
_state = [TGEmbedPlayerState stateWithPlaying:false duration:0.0 position:0.0 downloadProgress:0.0f buffering:false];
TGEmbedPlayerControlsType controlsType = [self _controlsType];
if (controlsType != TGEmbedPlayerControlsTypeNone)
{
__weak TGEmbedPlayerView *weakSelf = self;
_controlsView = [[TGEmbedPlayerControls alloc] initWithFrame:CGRectZero type:controlsType];
_controlsView.playPressed = ^
{
__strong TGEmbedPlayerView *strongSelf = weakSelf;
if (strongSelf != nil)
[strongSelf playVideo];
};
_controlsView.pausePressed = ^
{
__strong TGEmbedPlayerView *strongSelf = weakSelf;
if (strongSelf != nil)
[strongSelf pauseVideo];
};
_controlsView.seekToPosition = ^(CGFloat position)
{
__strong TGEmbedPlayerView *strongSelf = weakSelf;
if (strongSelf != nil)
[strongSelf seekToFractPosition:position];
};
_controlsView.fullscreenPressed = ^
{
__strong TGEmbedPlayerView *strongSelf = weakSelf;
if (strongSelf != nil)
[strongSelf enterFullscreen:0.0];
};
_controlsView.pictureInPicturePressed = ^
{
__strong TGEmbedPlayerView *strongSelf = weakSelf;
if (strongSelf != nil)
[strongSelf _pictureInPicturePressed];
};
_controlsView.watermarkPressed = ^
{
__strong TGEmbedPlayerView *strongSelf = weakSelf;
if (strongSelf != nil && !strongSelf.disableWatermarkAction)
[strongSelf _watermarkAction];
};
_controlsView.panelVisibilityChange = ^(bool hidden)
{
if (hidden)
return;
__strong TGEmbedPlayerView *strongSelf = weakSelf;
if (strongSelf != nil)
[strongSelf _onPanelAppearance];
};
[_controlsView setPictureInPictureHidden:![self supportsPIP]];
[self addSubview:_controlsView];
}
CGSize imageSize = CGSizeZero;
if (webPage.photo != nil)
[webPage.photo.imageInfo closestImageUrlWithSize:CGSizeMake(1136, 1136) resultingSize:&imageSize];
CGFloat imageAspect = imageSize.width / imageSize.height;
CGSize fitSize = CGSizeMake(215.0f, 180.0f);
if (ABS(imageAspect - 1.0f) < FLT_EPSILON)
fitSize = CGSizeMake(215.0f, 215.0f);
imageSize = TGScaleToFill(imageSize, fitSize);
_dimWrapperView = [[UIView alloc] init];
_dimWrapperView.backgroundColor = [UIColor blackColor];
[self addSubview:_dimWrapperView];
SSignal *coverSignal = thumbnailSignal ?: [[LegacyComponentsGlobals provider] squarePhotoThumbnail:webPage.photo ofSize:imageSize threadPool:[[LegacyComponentsGlobals provider] sharedMediaImageProcessingThreadPool] memoryCache:[[LegacyComponentsGlobals provider] sharedMediaMemoryImageCache] pixelProcessingBlock:nil downloadLargeImage:false placeholder:nil];
_coverView = [[TGImageView alloc] init];
_coverView.contentMode = UIViewContentModeScaleAspectFill;
[_coverView setSignal:coverSignal];
[_dimWrapperView addSubview:_coverView];
_dimView = [[UIView alloc] init];
_dimView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
_dimView.backgroundColor = UIColorRGBA(0x000000, 0.5f);
[_dimWrapperView addSubview:_dimView];
_overlayView = [[TGMessageImageViewOverlayView alloc] initWithFrame:CGRectMake(0.0f, 0.0f, 44.0f, 44.0f)];
[_overlayView setRadius:44.0f];
[_dimWrapperView addSubview:_overlayView];
_errorLabel = [[UILabel alloc] init];
_errorLabel.backgroundColor = [UIColor clearColor];
_errorLabel.font = TGSystemFontOfSize(16.0f);
_errorLabel.hidden = true;
_errorLabel.text = TGLocalized(@"Web.Error");
_errorLabel.textColor = [UIColor whiteColor];
[_errorLabel sizeToFit];
[_dimWrapperView addSubview:_errorLabel];
if (iosMajorVersion() >= 11)
{
_coverView.accessibilityIgnoresInvertColors = true;
_dimView.accessibilityIgnoresInvertColors = true;
_overlayView.accessibilityIgnoresInvertColors = true;
_errorLabel.accessibilityIgnoresInvertColors = true;
}
_interactionView = [[UIView alloc] initWithFrame:self.bounds];
_interactionView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
_interactionView.hidden = true;
[self addSubview:_interactionView];
_jsQueue = [[SQueue alloc] init];
_sema = dispatch_semaphore_create(0);
}
return self;
}
- (void)dealloc
{
WKWebView *wkWebView = _wkWebView;
[_jsQueue dispatchSync:^
{
wkWebView.navigationDelegate = nil;
}];
_uiWebView.delegate = nil;
[_currentAudioSession dispose];
[[LegacyComponentsGlobals provider] resumePictureInPicturePlayback];
TGDispatchAfter(0.1, dispatch_get_main_queue(), ^
{
[[LegacyComponentsGlobals provider] maybeReleaseVolumeOverlay];
});
}
- (void)setDisallowPIP:(bool)disallowPIP
{
_disallowPIP = disallowPIP;
[_controlsView setPictureInPictureHidden:disallowPIP];
}
- (void)setDisallowAutoplay:(bool)disallowAutoplay
{
_disallowAutoplay = disallowAutoplay;
_dimView.hidden = true;
[_controlsView showLargePlayButton:true];
[self insertSubview:_dimWrapperView belowSubview:_controlsView];
}
- (void)setDisableControls:(bool)disableControls {
_disableControls = disableControls;
if (disableControls) {
for (UIView *view in [_dimWrapperView.subviews copy]) {
if (view != _coverView) {
view.alpha = 0.0f;
view.hidden = true;
}
}
_controlsView.hidden = true;
_dimView.hidden = true;
}
}
- (void)_setupAudioSessionIfNeeded
{
if (_currentAudioSession != nil)
return;
_currentAudioSession = [[LegacyComponentsGlobals provider] requestAudioSession:TGAudioSessionTypePlayEmbedVideo interrupted:^{}];
}
- (void)setupWithEmbedSize:(CGSize)embedSize
{
if (!self.disallowAutoplay || iosMajorVersion() < 8)
[self _setupAudioSessionIfNeeded];
CGFloat horEdge = [self _compensationEdges];
CGFloat verEdge = horEdge * embedSize.width / embedSize.height;
_embedSize = CGSizeMake(embedSize.width + horEdge * 2.0f, embedSize.height + verEdge * 2.0f);
CGSize screenSize = TGScreenSize();
screenSize = CGSizeMake(screenSize.height, screenSize.width);
_maxPlayerSize = [self _scaleViewToMaxSize] ? TGScaleToSize(embedSize, screenSize) : _embedSize;
_embedScale = _embedSize.width / _maxPlayerSize.width;
if (iosMajorVersion() >= 8)
[self setupWKWebView];
else
[self setupUIWebView];
if (!self.disallowAutoplay)
{
_overlayView.hidden = false;
[self setLoadProgress:0.01f duration:0.01];
[_loadProgressValue set:[SSignal single:@(0.01f)]];
}
}
- (CGFloat)_compensationEdges
{
return 0.0f;
}
- (SSignal *)loadProgress {
return [_loadProgressValue signal];
}
- (void)hideControls
{
[_controlsView hidePlayButton];
}
- (void)switchToPictureInPicture
{
[self _pictureInPicturePressed];
}
- (void)_requestSystemPictureInPictureMode
{
[self _evaluateJS:@"injectCmd('switchToPIP');" completion:^(__unused NSString *result)
{
}];
}
- (void)pausePIPPlayback
{
if (_pausedManually)
return;
_shouldResumePIPPlayback = true;
[self pauseVideo:false];
}
- (void)resumePIPPlayback
{
if (_shouldResumePIPPlayback)
[self playVideo];
_shouldResumePIPPlayback = false;
}
- (bool)supportsPIP
{
CGSize screenSize = TGScreenSize();
return !self.disallowPIP && (int)screenSize.height != 480;
}
- (void)setDimmed:(bool)dimmed animated:(bool)animated
{
[self setDimmed:dimmed animated:animated shouldDelay:false];
}
- (void)setDimmed:(bool)dimmed animated:(bool)animated shouldDelay:(bool)shouldDelay
{
bool useFakeProgress = [self _useFakeLoadingProgress];
if (animated)
{
if (dimmed)
{
_overlayView.hidden = false;
if (useFakeProgress) {
[self setLoadProgress:0.88f duration:3.0];
[_loadProgressValue set:[SSignal single:@(0.88f)]];
}
_dimWrapperView.hidden = false;
_dimWrapperView.alpha = 1.0f;
}
else
{
[self setLoadProgress:1.0f duration:0.2];
[_loadProgressValue set:[SSignal single:@(1.0f)]];
NSTimeInterval delay = shouldDelay ? 0.4 : 0.0;
[UIView animateWithDuration:0.2 delay:delay options:UIViewAnimationOptionAllowAnimatedContent | UIViewAnimationOptionCurveLinear animations:^
{
_dimWrapperView.alpha = 0.0f;
} completion:^(__unused BOOL finished)
{
_dimWrapperView.hidden = true;
_dimWrapperView.alpha = 1.0f;
}];
}
}
else
{
_dimWrapperView.hidden = !dimmed;
_overlayView.hidden = !dimmed;
if (dimmed && useFakeProgress) {
[self setLoadProgress:0.88f duration:3.0];
[_loadProgressValue set:[SSignal single:@(0.88f)]];
}
else
[_overlayView setNone];
}
}
- (void)setLoadProgress:(CGFloat)value duration:(NSTimeInterval)duration
{
[_overlayView setProgressAnimated:value duration:duration cancelEnabled:false];
[_loadProgressValue set:[SSignal single:@(value)]];
}
- (bool)_useFakeLoadingProgress
{
return true;
}
- (void)setCoverImage:(UIImage *)image
{
[_coverView setSignal:[SSignal single:image]];
}
#pragma mark -
- (void)beginLeavingFullscreen
{
UIBezierPath *maskPath = [UIBezierPath bezierPathWithRoundedRect:self.bounds byRoundingCorners:self.roundCorners cornerRadii:CGSizeMake(14.5f, 14.5f)];
CAShapeLayer *maskLayer = [CAShapeLayer layer];
maskLayer.frame = self.bounds;
maskLayer.path = maskPath.CGPath;
self.layer.mask = maskLayer;
}
- (void)finishedLeavingFullscreen
{
self.layer.mask = nil;
}
- (void)onLockInPlace
{
[_controlsView setFullscreenButtonHidden:false animated:true];
}
- (void)setInhibitFullscreenButton:(bool)inhibitFullscreenButton
{
_inhibitFullscreenButton = inhibitFullscreenButton;
_controlsView.inhibitFullscreenButton = inhibitFullscreenButton;
}
#pragma mark -
- (void)setupWKWebView
{
WKUserContentController *contentController = [[WKUserContentController alloc] init];
if ([self _applyViewportUserScript])
{
NSString *jScript = @"var meta = document.createElement('meta'); meta.setAttribute('name', 'viewport'); meta.setAttribute('content', 'width=device-width'); document.getElementsByTagName('head')[0].appendChild(meta);";
WKUserScript *viewportScript = [[WKUserScript alloc] initWithSource:jScript injectionTime:WKUserScriptInjectionTimeAtDocumentEnd forMainFrameOnly:true];
[contentController addUserScript:viewportScript];
}
[self _setupUserScripts:contentController];
WKWebViewConfiguration *conf = [[WKWebViewConfiguration alloc] init];
conf.allowsInlineMediaPlayback = true;
conf.userContentController = contentController;
if ([conf respondsToSelector:@selector(setRequiresUserActionForMediaPlayback:)])
conf.requiresUserActionForMediaPlayback = false;
else if ([conf respondsToSelector:@selector(setMediaPlaybackRequiresUserAction:)])
conf.mediaPlaybackRequiresUserAction = false;
if ([conf respondsToSelector:@selector(setAllowsPictureInPictureMediaPlayback:)] && !TGIsPad())
conf.allowsPictureInPictureMediaPlayback = false;
_wkWebView = [[WKWebView alloc] initWithFrame:CGRectZero configuration:conf];
_wkWebView.navigationDelegate = self;
_wkWebView.scrollView.scrollEnabled = false;
if (iosMajorVersion() >= 11)
_wkWebView.scrollView.contentInsetAdjustmentBehavior = UIScrollViewContentInsetAdjustmentNever;
NSString *embedHTML = [self _embedHTML];
bool useURL = (embedHTML.length == 0);
[self commonSetupWithWebView:_wkWebView useURL:useURL completion:^(NSURLRequest *request)
{
if (useURL)
[_wkWebView loadRequest:request];
else
[_wkWebView loadHTMLString:embedHTML baseURL:[self _baseURL]];
}];
}
- (void)webView:(WKWebView *)__unused webView didStartProvisionalNavigation:(WKNavigation *)__unused navigation
{
if (_loading)
return;
_loading = true;
if (!self.disallowAutoplay)
[self setDimmed:true animated:false];
if (self.onBeganLoading != nil)
self.onBeganLoading();
}
- (void)webView:(WKWebView *)__unused webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler
{
NSURL *url = navigationAction.request.URL;
if (![url.scheme isEqualToString:@"http"] && ![url.scheme isEqualToString:@"https"] && ![url.absoluteString isEqualToString:@"about:blank"])
{
[self _notifyOfCallbackURL:url];
decisionHandler(WKNavigationActionPolicyCancel);
}
else
{
if (navigationAction.targetFrame == nil)
{
[self _openWebPage:url];
decisionHandler(WKNavigationActionPolicyCancel);
}
else
{
decisionHandler(WKNavigationActionPolicyAllow);
}
}
}
- (void)webView:(WKWebView *)__unused webView didFinishNavigation:(WKNavigation *)__unused navigation
{
if (!_loading)
return;
_loading = false;
[self _onPageReady];
}
- (void)webView:(WKWebView *)__unused webView didFailNavigation:(WKNavigation *)__unused navigation withError:(NSError *)__unused error
{
if ([error.domain isEqualToString:@"WebKitErrorDomain"] && error.code == 204)
return;
if (!_loading)
return;
_loading = false;
_overlayView.hidden = true;
[_overlayView setNone];
_errorLabel.hidden = false;
}
#pragma mark -
- (void)setupUIWebView
{
_uiWebView = [[UIWebView alloc] initWithFrame:CGRectZero];
_uiWebView.mediaPlaybackRequiresUserAction = false;
_uiWebView.delegate = self;
_uiWebView.scrollView.scrollEnabled = false;
NSString *embedHTML = [self _embedHTML];
bool useURL = (embedHTML.length == 0);
[self commonSetupWithWebView:_uiWebView useURL:useURL completion:^(NSURLRequest *request)
{
if (useURL)
[_uiWebView loadRequest:request];
else
[_uiWebView loadHTMLString:embedHTML baseURL:[self _baseURL]];
}];
}
- (BOOL)webView:(UIWebView *)__unused webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)__unused navigationType
{
NSURL *url = request.URL;
if (![url.scheme isEqualToString:@"http"] && ![url.scheme isEqualToString:@"https"] && ![url.absoluteString isEqualToString:@"about:blank"])
{
[self _notifyOfCallbackURL:url];
return false;
}
return true;
}
- (void)webViewDidStartLoad:(UIWebView *)__unused webView
{
if (_loading)
return;
_loading = true;
[self setDimmed:true animated:false];
if (self.onBeganLoading != nil)
self.onBeganLoading();
}
- (void)webViewDidFinishLoad:(UIWebView *)__unused webView
{
if (!_loading)
return;
_loading = false;
[self _onPageReady];
}
- (void)webView:(UIWebView *)__unused webView didFailLoadWithError:(NSError *)__unused error
{
if (!_loading)
return;
_loading = false;
_overlayView.hidden = true;
[_overlayView setNone];
_errorLabel.hidden = false;
}
- (void)commonSetupWithWebView:(UIView *)webView useURL:(bool)useURL completion:(void (^)(NSURLRequest *))completion
{
CGFloat horEdge = [self _compensationEdges];
CGFloat verEdge = horEdge * _embedSize.width / _embedSize.height;
if (iosMajorVersion() >= 11)
webView.accessibilityIgnoresInvertColors = true;
webView.backgroundColor = [UIColor blackColor];
webView.frame = CGRectMake(0, 0, _maxPlayerSize.width, _maxPlayerSize.height);
webView.transform = CGAffineTransformMakeScale(_embedScale, _embedScale);
webView.center = CGPointMake((_embedSize.width - horEdge * 2.0f) / 2.0f, (_embedSize.height - verEdge * 2.0f) / 2.0f);
if (_controlsView != nil && !_disallowAutoplay)
[self insertSubview:webView belowSubview:_controlsView];
else
[self insertSubview:webView belowSubview:_dimWrapperView];
if (useURL)
{
NSURL *url = [self _embedURL];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
NSString *referer = [[NSString alloc] initWithFormat:@"%@://%@", [url scheme], [url host]];
[request setValue:referer forHTTPHeaderField:@"Referer"];
if (completion != nil)
completion(request);
}
else
{
if (completion != nil)
completion(nil);
}
}
#pragma mark -
- (void)_openWebPage:(NSURL *)url
{
[[LegacyComponentsGlobals provider] openURLNative:url];
}
- (void)playVideo
{
if (_disallowAutoplay)
_dimWrapperView.hidden = true;
[self _setupAudioSessionIfNeeded];
}
- (void)pauseVideo
{
[self pauseVideo:true];
}
- (void)pauseVideo:(bool)manually
{
_pausedManually = manually;
}
- (void)seekToPosition:(NSTimeInterval)__unused position
{
}
- (void)seekToFractPosition:(CGFloat)position
{
NSTimeInterval timePosition = self.state.duration * position;
[self seekToPosition:timePosition];
}
- (void)enterFullscreen:(NSTimeInterval)duration
{
if (self.requestFullscreen != nil)
self.requestFullscreen(duration);
}
- (void)enterPictureInPicture:(TGEmbedPIPCorner)corner
{
if (self.requestPictureInPicture != nil)
self.requestPictureInPicture(corner);
}
- (void)_pictureInPicturePressed
{
[self enterPictureInPicture:TGEmbedPIPCornerNone];
}
- (SSignal *)stateSignal
{
return _statePipe.signalProducer();
}
- (void)updateState:(TGEmbedPlayerState *)state
{
_state = state;
[_controlsView setState:state];
_statePipe.sink(state);
}
#pragma mark -
- (void)_onPageReady
{
[self setDimmed:false animated:true];
}
- (void)_didBeginPlayback
{
[_controlsView notifyOfPlaybackStart];
[[LegacyComponentsGlobals provider] pausePictureInPicturePlayback];
if (self.onBeganPlaying != nil)
self.onBeganPlaying();
}
- (void)_onPanelAppearance
{
}
- (void)_watermarkAction
{
[self pauseVideo];
}
- (void)_prepareToEnterFullscreen
{
[_controlsView setWatermarkHidden:true];
[_controlsView setHidden:true animated:true];
_interactionView.hidden = false;
}
- (void)_prepareToLeaveFullscreen
{
[_controlsView setWatermarkHidden:false];
[_controlsView setHidden:false animated:true];
_interactionView.hidden = true;
}
#pragma mark -
- (TGEmbedPlayerControlsType)_controlsType
{
return TGEmbedPlayerControlsTypeNone;
}
- (void)_evaluateJS:(NSString *)jsString completion:(void (^)(NSString *))completion
{
if (_wkWebView != nil)
{
[_jsQueue dispatch:^
{
void (^block)(void) = ^
{
[_wkWebView evaluateJavaScript:jsString completionHandler:^(id result, __unused NSError *error)
{
dispatch_semaphore_signal(_sema);
TGDispatchOnMainThread(^
{
if (completion != nil)
completion(result);
});
}];
};
if (iosMajorVersion() >= 11)
TGDispatchOnMainThread(block);
else
block();
dispatch_semaphore_wait(_sema, DISPATCH_TIME_FOREVER);
}];
}
else if (_uiWebView != nil)
{
NSString *result = [_uiWebView stringByEvaluatingJavaScriptFromString:jsString];
if (completion != nil)
completion(result);
}
}
- (NSString *)_embedHTML
{
NSString *path = TGComponentsPathForResource(@"DefaultPlayer", @"html");
NSError *error = nil;
NSString *embedHTMLTemplate = [NSString stringWithContentsOfFile:path encoding:NSUTF8StringEncoding error:&error];
if (error != nil)
{
TGLegacyLog(@"[DefaultEmbedPlayer]: Received error rendering template: %@", error);
return nil;
}
NSString *embedHTML = [NSString stringWithFormat:embedHTMLTemplate, [self _embedURL].absoluteString];
return embedHTML;
}
- (NSURL *)_embedURL
{
return [NSURL URLWithString:_webPage.embedUrl];
}
- (NSURL *)_baseURL
{
return [NSURL URLWithString:@"about:blank"];
}
- (void)_setupUserScripts:(WKUserContentController *)__unused contentController
{
NSError *error = nil;
NSString *path = TGComponentsPathForResource(@"DefaultPlayerInject", @"js");
NSString *scriptText = [NSString stringWithContentsOfFile:path encoding:NSUTF8StringEncoding error:&error];
if (error != nil)
TGLegacyLog(@"[DefaultEmbedPlayer]: Received error loading inject script: %@", error);
WKUserScript *script = [[WKUserScript alloc] initWithSource:scriptText injectionTime:WKUserScriptInjectionTimeAtDocumentEnd forMainFrameOnly:false];
[contentController addUserScript:script];
}
- (bool)_applyViewportUserScript
{
return true;
}
- (void)_notifyOfCallbackURL:(NSURL *)__unused url
{
}
- (UIView *)_webView
{
if (_wkWebView != nil)
return _wkWebView;
else if (_uiWebView != nil)
return _uiWebView;
return nil;
}
- (bool)_scaleViewToMaxSize
{
return false;
}
- (void)_cleanWebView
{
_wkWebView.navigationDelegate = nil;
[_wkWebView removeFromSuperview];
_wkWebView = nil;
_uiWebView.delegate = nil;
[_uiWebView removeFromSuperview];
_uiWebView = nil;
}
+ (bool)_supportsWebPage:(TGWebPageMediaAttachment *)__unused webPage
{
return true;
}
+ (Class)playerViewClassForWebPage:(TGWebPageMediaAttachment *)webPage onlySpecial:(bool)onlySpecial
{
static dispatch_once_t onceToken;
static NSArray *playerViewClasses;
dispatch_once(&onceToken, ^
{
playerViewClasses = @
[
[TGEmbedYoutubePlayerView class],
[TGEmbedVimeoPlayerView class],
[TGEmbedCoubPlayerView class],
[TGEmbedVKPlayerView class],
[TGEmbedVinePlayerView class],
[TGEmbedInstagramPlayerView class],
[TGEmbedSoundCloudPlayerView class],
[TGEmbedTwitchPlayerView class],
[TGEmbedVideoPlayerView class]
];
});
if (iosMajorVersion() >= 8)
{
for (Class playerViewClass in playerViewClasses)
{
if ([playerViewClass _supportsWebPage:webPage])
{
if (playerViewClass == [TGEmbedVideoPlayerView class] && onlySpecial)
return nil;
return playerViewClass;
}
}
}
if (onlySpecial)
return nil;
return self;
}
- (void)layoutSubviews
{
_dimWrapperView.frame = self.bounds;
_coverView.frame = _dimWrapperView.bounds;
_overlayView.center = CGPointMake(CGRectGetMidX(_dimWrapperView.bounds), CGRectGetMidY(_dimWrapperView.bounds));
_errorLabel.center = _overlayView.center;
_controlsView.frame = self.bounds;
}
+ (TGEmbedPlayerView *)makePlayerViewForWebPage:(TGWebPageMediaAttachment *)webPage thumbnailSignal:(SSignal *)signal {
Class playerClass = [self playerViewClassForWebPage:webPage onlySpecial:false];
if (playerClass != nil) {
return [[playerClass alloc] initWithWebPageAttachment:webPage thumbnailSignal:signal];
} else {
return nil;
}
}
+ (bool)hasNativeSupportForX:(TGWebPageMediaAttachment *)webPage {
static dispatch_once_t onceToken;
static NSArray *playerViewClasses;
dispatch_once(&onceToken, ^
{
playerViewClasses = @
[
[TGEmbedYoutubePlayerView class],
/*[TGEmbedVimeoPlayerView class],
[TGEmbedCoubPlayerView class],
[TGEmbedVKPlayerView class],
[TGEmbedVinePlayerView class],
[TGEmbedInstagramPlayerView class],
[TGEmbedSoundCloudPlayerView class],
[TGEmbedTwitchPlayerView class],
[TGEmbedVideoPlayerView class]*/
];
});
if (iosMajorVersion() >= 8)
{
for (Class playerViewClass in playerViewClasses)
{
if ([playerViewClass _supportsWebPage:webPage])
{
if (playerViewClass == [TGEmbedVideoPlayerView class])
return false;
return true;
}
}
}
return false;
}
@end