NekoX/TMessagesProj/src/main/java/org/telegram/ui/Components/PhotoViewerWebView.java

385 lines
15 KiB
Java

package org.telegram.ui.Components;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.graphics.Canvas;
import android.net.Uri;
import android.os.Build;
import android.provider.Settings;
import android.view.Gravity;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.webkit.CookieManager;
import android.webkit.JavascriptInterface;
import android.webkit.WebSettings;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import android.widget.FrameLayout;
import org.telegram.messenger.AndroidUtilities;
import org.telegram.messenger.ApplicationLoader;
import org.telegram.messenger.BringAppForegroundService;
import org.telegram.messenger.FileLog;
import org.telegram.messenger.MessagesController;
import org.telegram.messenger.UserConfig;
import org.telegram.messenger.Utilities;
import org.telegram.messenger.browser.Browser;
import org.telegram.tgnet.TLRPC;
import org.telegram.ui.PhotoViewer;
import java.util.HashMap;
import java.util.Locale;
public class PhotoViewerWebView extends FrameLayout {
private int currentAccount = UserConfig.selectedAccount;
private WebView webView;
private View progressBarBlackBackground;
private RadialProgressView progressBar;
private View pipItem;
private boolean isYouTube;
private TLRPC.WebPage currentWebpage;
private float playbackSpeed;
private boolean setPlaybackSpeed;
private class YoutubeProxy {
@JavascriptInterface
public void postEvent(final String eventName, final String eventData) {
if ("loaded".equals(eventName)) {
AndroidUtilities.runOnUIThread(() -> {
progressBar.setVisibility(View.INVISIBLE);
progressBarBlackBackground.setVisibility(View.INVISIBLE);
if (setPlaybackSpeed) {
setPlaybackSpeed = false;
setPlaybackSpeed(playbackSpeed);
}
pipItem.setEnabled(true);
pipItem.setAlpha(1.0f);
});
}
}
}
private static final String youtubeFrame = "<!DOCTYPE html><html><head><style>" +
"body { margin: 0; width:100%%; height:100%%; background-color:#000; }" +
"html { width:100%%; height:100%%; background-color:#000; }" +
".embed-container iframe," +
".embed-container object," +
" .embed-container embed {" +
" position: absolute;" +
" top: 0;" +
" left: 0;" +
" width: 100%% !important;" +
" height: 100%% !important;" +
" }" +
" </style></head><body>" +
" <div class=\"embed-container\">" +
" <div id=\"player\"></div>" +
" </div>" +
" <script src=\"https://www.youtube.com/iframe_api\"></script>" +
" <script>" +
" var player;" +
" var posted = false;" +
" YT.ready(function() {" +
" player = new YT.Player(\"player\", {" +
" \"width\" : \"100%%\"," +
" \"events\" : {" +
" \"onReady\" : \"onReady\"," +
" \"onError\" : \"onError\"," +
" \"onStateChange\" : \"onStateChange\"," +
" }," +
" \"videoId\" : \"%1$s\"," +
" \"height\" : \"100%%\"," +
" \"playerVars\" : {" +
" \"start\" : %2$d," +
" \"rel\" : 1," +
" \"showinfo\" : 0," +
" \"modestbranding\" : 0," +
" \"iv_load_policy\" : 3," +
" \"autohide\" : 1," +
" \"autoplay\" : 1," +
" \"cc_load_policy\" : 1," +
" \"playsinline\" : 1," +
" \"controls\" : 1" +
" }" +
" });" +
" player.setSize(window.innerWidth, window.innerHeight);" +
" });" +
" function setPlaybackSpeed(speed) { " +
" player.setPlaybackRate(speed);" +
" }" +
" function onError(event) {" +
" if (!posted) {" +
" if (window.YoutubeProxy !== undefined) {" +
" YoutubeProxy.postEvent(\"loaded\", null); " +
" }" +
" posted = true;" +
" }" +
" }" +
" function onStateChange(event) {" +
" if (event.data == YT.PlayerState.PLAYING && !posted) {" +
" if (window.YoutubeProxy !== undefined) {" +
" YoutubeProxy.postEvent(\"loaded\", null); " +
" }" +
" posted = true;" +
" }" +
" }" +
" function onReady(event) {" +
" player.playVideo();" +
" }" +
" window.onresize = function() {" +
" player.setSize(window.innerWidth, window.innerHeight);" +
" player.playVideo();" +
" }" +
" </script>" +
"</body>" +
"</html>";
@SuppressLint("SetJavaScriptEnabled")
public PhotoViewerWebView(Context context, View pip) {
super(context);
pipItem = pip;
webView = new WebView(context) {
@Override
public boolean onTouchEvent(MotionEvent event) {
processTouch(event);
return super.onTouchEvent(event);
}
};
webView.getSettings().setJavaScriptEnabled(true);
webView.getSettings().setDomStorageEnabled(true);
if (Build.VERSION.SDK_INT >= 17) {
webView.getSettings().setMediaPlaybackRequiresUserGesture(false);
}
if (Build.VERSION.SDK_INT >= 21) {
webView.getSettings().setMixedContentMode(WebSettings.MIXED_CONTENT_ALWAYS_ALLOW);
CookieManager cookieManager = CookieManager.getInstance();
cookieManager.setAcceptThirdPartyCookies(webView, true);
}
webView.setWebViewClient(new WebViewClient() {
@Override
public void onLoadResource(WebView view, String url) {
super.onLoadResource(view, url);
}
@Override
public void onPageFinished(WebView view, String url) {
super.onPageFinished(view, url);
if (!isYouTube || Build.VERSION.SDK_INT < 17) {
progressBar.setVisibility(View.INVISIBLE);
progressBarBlackBackground.setVisibility(View.INVISIBLE);
pipItem.setEnabled(true);
pipItem.setAlpha(1.0f);
}
}
@Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
if (isYouTube) {
Browser.openUrl(view.getContext(), url);
return true;
}
return super.shouldOverrideUrlLoading(view, url);
}
});
addView(webView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, Gravity.TOP | Gravity.LEFT));
progressBarBlackBackground = new View(context) {
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
drawBlackBackground(canvas, getMeasuredWidth(), getMeasuredHeight());
}
};
progressBarBlackBackground.setBackgroundColor(0xff000000);
progressBarBlackBackground.setVisibility(View.INVISIBLE);
addView(progressBarBlackBackground, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT));
progressBar = new RadialProgressView(context);
progressBar.setVisibility(View.INVISIBLE);
addView(progressBar, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.CENTER));
}
private void runJsCode(String code) {
if (Build.VERSION.SDK_INT >= 21) {
webView.evaluateJavascript(code, null);
} else {
try {
webView.loadUrl("javascript:" + code);
} catch (Exception e) {
FileLog.e(e);
}
}
}
protected void processTouch(MotionEvent event) {
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
if (webView.getParent() == this) {
int w = currentWebpage.embed_width != 0 ? currentWebpage.embed_width : 100;
int h = currentWebpage.embed_height != 0 ? currentWebpage.embed_height : 100;
int viewWidth = MeasureSpec.getSize(widthMeasureSpec);
int viewHeight = MeasureSpec.getSize(heightMeasureSpec);
float minScale = Math.min(viewWidth / (float) w, viewHeight / (float) h);
FrameLayout.LayoutParams layoutParams = (FrameLayout.LayoutParams) webView.getLayoutParams();
layoutParams.width = (int) (w * minScale);
layoutParams.height = (int) (h * minScale);
layoutParams.topMargin = (viewHeight - layoutParams.height) / 2;
layoutParams.leftMargin = (viewWidth - layoutParams.width) / 2;
}
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
protected void drawBlackBackground(Canvas canvas, int w, int h) {
}
public boolean isLoaded() {
return progressBar.getVisibility() != View.VISIBLE;
}
public boolean isInAppOnly() {
return isYouTube && "inapp".equals(MessagesController.getInstance(currentAccount).youtubePipType);
}
public boolean openInPip() {
boolean inAppOnly = isInAppOnly();
if (!inAppOnly && !checkInlinePermissions()) {
return false;
}
if (progressBar.getVisibility() == View.VISIBLE) {
return false;
}
if (PipVideoOverlay.isVisible()) {
PipVideoOverlay.dismiss();
AndroidUtilities.runOnUIThread(this::openInPip, 300);
return true;
}
if (PipVideoOverlay.show(inAppOnly, (Activity) getContext(), webView, currentWebpage.embed_width, currentWebpage.embed_height)) {
PipVideoOverlay.setPhotoViewer(PhotoViewer.getInstance());
}
return true;
}
public void setPlaybackSpeed(float speed) {
playbackSpeed = speed;
if (progressBar.getVisibility() != View.VISIBLE) {
if (isYouTube) {
runJsCode("setPlaybackSpeed(" + speed + ");");
}
} else {
setPlaybackSpeed = true;
}
}
@SuppressLint("AddJavascriptInterface")
public void init(int seekTime, TLRPC.WebPage webPage) {
currentWebpage = webPage;
String currentYoutubeId = WebPlayerView.getYouTubeVideoId(webPage.embed_url);
String originalUrl = webPage.url;
requestLayout();
try {
if (currentYoutubeId != null) {
progressBarBlackBackground.setVisibility(View.VISIBLE);
isYouTube = true;
if (Build.VERSION.SDK_INT >= 17) {
webView.addJavascriptInterface(new YoutubeProxy(), "YoutubeProxy");
}
int seekToTime = 0;
if (originalUrl != null) {
try {
Uri uri = Uri.parse(originalUrl);
String t = seekTime > 0 ? "" + seekTime : null;
if (t == null) {
t = uri.getQueryParameter("t");
if (t == null) {
t = uri.getQueryParameter("time_continue");
}
}
if (t != null) {
if (t.contains("m")) {
String[] arg = t.split("m");
seekToTime = Utilities.parseInt(arg[0]) * 60 + Utilities.parseInt(arg[1]);
} else {
seekToTime = Utilities.parseInt(t);
}
}
} catch (Exception e) {
FileLog.e(e);
}
}
webView.loadDataWithBaseURL("https://messenger.telegram.org/", String.format(Locale.US, youtubeFrame, currentYoutubeId, seekToTime), "text/html", "UTF-8", "https://youtube.com");
} else {
HashMap<String, String> args = new HashMap<>();
args.put("Referer", "messenger.telegram.org");
webView.loadUrl(webPage.embed_url, args);
}
} catch (Exception e) {
FileLog.e(e);
}
pipItem.setEnabled(false);
pipItem.setAlpha(0.5f);
progressBar.setVisibility(View.VISIBLE);
if (currentYoutubeId != null) {
progressBarBlackBackground.setVisibility(View.VISIBLE);
}
webView.setVisibility(View.VISIBLE);
webView.setKeepScreenOn(true);
if (currentYoutubeId != null && "disabled".equals(MessagesController.getInstance(currentAccount).youtubePipType)) {
pipItem.setVisibility(View.GONE);
}
}
public boolean checkInlinePermissions() {
if (Build.VERSION.SDK_INT < 23 || Settings.canDrawOverlays(getContext())) {
return true;
} else {
AlertsCreator.createDrawOverlayPermissionDialog((Activity) getContext(), null);
}
return false;
}
public void exitFromPip() {
if (webView == null) {
return;
}
if (ApplicationLoader.mainInterfacePaused) {
try {
getContext().startService(new Intent(ApplicationLoader.applicationContext, BringAppForegroundService.class));
} catch (Throwable e) {
FileLog.e(e);
}
}
ViewGroup parent = (ViewGroup) webView.getParent();
if (parent != null) {
parent.removeView(webView);
}
addView(webView, 0, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, Gravity.TOP | Gravity.LEFT));
PipVideoOverlay.dismiss();
}
public void release() {
webView.stopLoading();
webView.loadUrl("about:blank");
webView.destroy();
}
}