NekoX/TMessagesProj/src/main/java/org/telegram/ui/WebviewActivity.java

441 lines
21 KiB
Java

/*
* This is the source code of Telegram for Android v. 5.x.x.
* 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 Nikolai Kudashov, 2013-2018.
*/
package org.telegram.ui;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.AnimatorSet;
import android.animation.ObjectAnimator;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.net.Uri;
import android.os.Build;
import android.text.TextUtils;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewParent;
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.BuildVars;
import org.telegram.messenger.FileLog;
import org.telegram.messenger.LocaleController;
import org.telegram.messenger.MessageObject;
import org.telegram.messenger.MessagesController;
import org.telegram.messenger.R;
import org.telegram.messenger.Utilities;
import org.telegram.messenger.browser.Browser;
import org.telegram.tgnet.ConnectionsManager;
import org.telegram.tgnet.SerializedData;
import org.telegram.tgnet.TLRPC;
import org.telegram.ui.ActionBar.ActionBar;
import org.telegram.ui.ActionBar.ActionBarMenu;
import org.telegram.ui.ActionBar.ActionBarMenuItem;
import org.telegram.ui.ActionBar.BaseFragment;
import org.telegram.ui.ActionBar.Theme;
import org.telegram.ui.ActionBar.ThemeDescription;
import org.telegram.ui.Components.ContextProgressView;
import org.telegram.ui.Components.LayoutHelper;
import org.telegram.ui.Components.ShareAlert;
import java.net.URLEncoder;
import java.util.ArrayList;
public class WebviewActivity extends BaseFragment {
private WebView webView;
private ActionBarMenuItem progressItem;
private ContextProgressView progressView;
private String currentUrl;
private long currentDialogId;
private String currentBot;
private String currentGame;
private String linkToCopy;
private MessageObject currentMessageObject;
private String short_param;
private boolean loadStats;
private final static int share = 1;
private final static int open_in = 2;
private static final int TYPE_GAME = 0;
private static final int TYPE_STAT = 1;
private int type;
private class TelegramWebviewProxy {
@JavascriptInterface
public void postEvent(final String eventName, final String eventData) {
AndroidUtilities.runOnUIThread(() -> {
if (getParentActivity() == null) {
return;
}
if (BuildVars.LOGS_ENABLED) {
FileLog.d(eventName);
}
switch (eventName) {
case "share_game":
currentMessageObject.messageOwner.with_my_score = false;
break;
case "share_score":
currentMessageObject.messageOwner.with_my_score = true;
break;
}
showDialog(ShareAlert.createShareAlert(getParentActivity(), currentMessageObject, null, false, linkToCopy, false));
});
}
}
public Runnable typingRunnable = new Runnable() {
@Override
public void run() {
if (currentMessageObject == null || getParentActivity() == null || typingRunnable == null) {
return;
}
MessagesController.getInstance(currentAccount).sendTyping(currentMessageObject.getDialogId(), 0, 6, 0);
AndroidUtilities.runOnUIThread(typingRunnable, 25000);
}
};
public WebviewActivity(String url, String botName, String gameName, String startParam, MessageObject messageObject) {
super();
currentUrl = url;
currentBot = botName;
currentGame = gameName;
currentMessageObject = messageObject;
short_param = startParam;
linkToCopy = "https://" + MessagesController.getInstance(currentAccount).linkPrefix + "/" + currentBot + (TextUtils.isEmpty(startParam) ? "" : "?game=" + startParam);
type = TYPE_GAME;
}
public WebviewActivity(String statUrl, long did) {
super();
currentUrl = statUrl;
currentDialogId = did;
type = TYPE_STAT;
}
@Override
public void onFragmentDestroy() {
super.onFragmentDestroy();
AndroidUtilities.cancelRunOnUIThread(typingRunnable);
webView.setLayerType(View.LAYER_TYPE_NONE, null);
typingRunnable = null;
try {
ViewParent parent = webView.getParent();
if (parent != null) {
((FrameLayout) parent).removeView(webView);
}
webView.stopLoading();
webView.loadUrl("about:blank");
webView.destroy();
webView = null;
} catch (Exception e) {
FileLog.e(e);
}
}
@SuppressLint({"SetJavaScriptEnabled", "AddJavascriptInterface"})
@Override
public View createView(Context context) {
actionBar.setBackButtonImage(R.drawable.ic_ab_back);
actionBar.setAllowOverlayTitle(true);
actionBar.setActionBarMenuOnItemClick(new ActionBar.ActionBarMenuOnItemClick() {
@Override
public void onItemClick(int id) {
if (id == -1) {
finishFragment();
} else if (id == share) {
if (currentMessageObject != null) {
currentMessageObject.messageOwner.with_my_score = false;
showDialog(ShareAlert.createShareAlert(getParentActivity(), currentMessageObject, null, false, linkToCopy, false));
}
} else if (id == open_in) {
openGameInBrowser(currentUrl, currentMessageObject, getParentActivity(), short_param, currentBot);
}
}
});
ActionBarMenu menu = actionBar.createMenu();
progressItem = menu.addItemWithWidth(share, R.drawable.share, AndroidUtilities.dp(54));
if (type == TYPE_GAME) {
ActionBarMenuItem menuItem = menu.addItem(0, R.drawable.ic_ab_other);
menuItem.addSubItem(open_in, R.drawable.msg_openin, LocaleController.getString("OpenInExternalApp", R.string.OpenInExternalApp));
actionBar.setTitle(currentGame);
actionBar.setSubtitle("@" + currentBot);
progressView = new ContextProgressView(context, 1);
progressItem.addView(progressView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT));
progressView.setAlpha(0.0f);
progressView.setScaleX(0.1f);
progressView.setScaleY(0.1f);
progressView.setVisibility(View.INVISIBLE);
} else if (type == TYPE_STAT) {
actionBar.setBackgroundColor(Theme.getColor(Theme.key_player_actionBar));
actionBar.setItemsColor(Theme.getColor(Theme.key_player_actionBarItems), false);
actionBar.setItemsBackgroundColor(Theme.getColor(Theme.key_player_actionBarSelector), false);
actionBar.setTitleColor(Theme.getColor(Theme.key_player_actionBarTitle));
actionBar.setSubtitleColor(Theme.getColor(Theme.key_player_actionBarSubtitle));
actionBar.setTitle(LocaleController.getString("Statistics", R.string.Statistics));
progressView = new ContextProgressView(context, 3);
progressItem.addView(progressView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT));
progressView.setAlpha(1.0f);
progressView.setScaleX(1.0f);
progressView.setScaleY(1.0f);
progressView.setVisibility(View.VISIBLE);
progressItem.getContentView().setVisibility(View.GONE);
progressItem.setEnabled(false);
}
webView = new WebView(context);
webView.getSettings().setJavaScriptEnabled(true);
webView.getSettings().setDomStorageEnabled(true);
fragmentView = new FrameLayout(context);
FrameLayout frameLayout = (FrameLayout) fragmentView;
if (Build.VERSION.SDK_INT >= 19) {
webView.setLayerType(View.LAYER_TYPE_HARDWARE, null);
}
if (Build.VERSION.SDK_INT >= 21) {
webView.getSettings().setMixedContentMode(WebSettings.MIXED_CONTENT_ALWAYS_ALLOW);
CookieManager cookieManager = CookieManager.getInstance();
cookieManager.setAcceptThirdPartyCookies(webView, true);
if (type == TYPE_GAME) {
webView.addJavascriptInterface(new TelegramWebviewProxy(), "TelegramWebviewProxy");
}
}
webView.setWebViewClient(new WebViewClient() {
private boolean isInternalUrl(String url) {
if (TextUtils.isEmpty(url)) {
return false;
}
Uri uri = Uri.parse(url);
if ("tg".equals(uri.getScheme())) {
if (type == TYPE_STAT) {
try {
uri = Uri.parse(url.replace("tg:statsrefresh", "tg://telegram.org"));
reloadStats(uri.getQueryParameter("params"));
} catch (Throwable e) {
FileLog.e(e);
}
} else {
finishFragment(false);
try {
Intent intent = new Intent(Intent.ACTION_VIEW, uri);
ComponentName componentName = new ComponentName(ApplicationLoader.applicationContext.getPackageName(), LaunchActivity.class.getName());
intent.setComponent(componentName);
intent.putExtra(android.provider.Browser.EXTRA_APPLICATION_ID, ApplicationLoader.applicationContext.getPackageName());
ApplicationLoader.applicationContext.startActivity(intent);
} catch (Exception e) {
FileLog.e(e);
}
}
return true;
}
return false;
}
@Override
public void onLoadResource(WebView view, String url) {
if (isInternalUrl(url)) {
return;
}
super.onLoadResource(view, url);
}
@Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
return isInternalUrl(url) || super.shouldOverrideUrlLoading(view, url);
}
@Override
public void onPageFinished(WebView view, String url) {
super.onPageFinished(view, url);
if (progressView != null && progressView.getVisibility() == View.VISIBLE) {
AnimatorSet animatorSet = new AnimatorSet();
if (type == TYPE_GAME) {
progressItem.getContentView().setVisibility(View.VISIBLE);
progressItem.setEnabled(true);
animatorSet.playTogether(
ObjectAnimator.ofFloat(progressView, "scaleX", 1.0f, 0.1f),
ObjectAnimator.ofFloat(progressView, "scaleY", 1.0f, 0.1f),
ObjectAnimator.ofFloat(progressView, "alpha", 1.0f, 0.0f),
ObjectAnimator.ofFloat(progressItem.getContentView(), "scaleX", 0.0f, 1.0f),
ObjectAnimator.ofFloat(progressItem.getContentView(), "scaleY", 0.0f, 1.0f),
ObjectAnimator.ofFloat(progressItem.getContentView(), "alpha", 0.0f, 1.0f));
} else {
animatorSet.playTogether(
ObjectAnimator.ofFloat(progressView, "scaleX", 1.0f, 0.1f),
ObjectAnimator.ofFloat(progressView, "scaleY", 1.0f, 0.1f),
ObjectAnimator.ofFloat(progressView, "alpha", 1.0f, 0.0f));
}
animatorSet.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animator) {
if (type == TYPE_STAT) {
progressItem.setVisibility(View.GONE);
} else {
progressView.setVisibility(View.INVISIBLE);
}
}
});
animatorSet.setDuration(150);
animatorSet.start();
}
}
});
frameLayout.addView(webView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT));
return fragmentView;
}
@Override
public void onResume() {
super.onResume();
AndroidUtilities.cancelRunOnUIThread(typingRunnable);
typingRunnable.run();
}
@Override
protected void onTransitionAnimationEnd(boolean isOpen, boolean backward) {
if (isOpen && !backward && webView != null) {
webView.loadUrl(currentUrl);
}
}
@Override
public boolean isSwipeBackEnabled(MotionEvent event) {
return false;
}
public static boolean supportWebview() {
String manufacturer = Build.MANUFACTURER;
String model = Build.MODEL;
if ("samsung".equals(manufacturer)) {
if ("GT-I9500".equals(model)) {
return false;
}
}
return true;
}
private void reloadStats(String params) {
if (loadStats) {
return;
}
loadStats = true;
TLRPC.TL_messages_getStatsURL req = new TLRPC.TL_messages_getStatsURL();
req.peer = MessagesController.getInstance(currentAccount).getInputPeer(currentDialogId);
req.params = params != null ? params : "";
req.dark = Theme.getCurrentTheme().isDark();
ConnectionsManager.getInstance(currentAccount).sendRequest(req, (response, error) -> AndroidUtilities.runOnUIThread(() -> {
loadStats = false;
if (response != null) {
TLRPC.TL_statsURL url = (TLRPC.TL_statsURL) response;
webView.loadUrl(currentUrl = url.url);
}
}));
}
public static void openGameInBrowser(String urlStr, MessageObject messageObject, Activity parentActivity, String short_name, String username) {
try {
String url = urlStr;
SharedPreferences sharedPreferences = ApplicationLoader.applicationContext.getSharedPreferences("botshare", Activity.MODE_PRIVATE);
String existing = sharedPreferences.getString("" + messageObject.getId(), null);
StringBuilder hash = new StringBuilder(existing != null ? existing : "");
StringBuilder addHash = new StringBuilder("tgShareScoreUrl=" + URLEncoder.encode("tgb://share_game_score?hash=", "UTF-8"));
if (existing == null) {
final char[] chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ".toCharArray();
for (int i = 0; i < 20; i++) {
hash.append(chars[Utilities.random.nextInt(chars.length)]);
}
}
addHash.append(hash);
int index = url.indexOf('#');
if (index < 0) {
url += "#" + addHash;
} else {
String curHash = url.substring(index + 1);
if (curHash.indexOf('=') >= 0 || curHash.indexOf('?') >= 0) {
url += "&" + addHash;
} else {
if (curHash.length() > 0) {
url += "?" + addHash;
} else {
url += addHash;
}
}
}
SharedPreferences.Editor editor = sharedPreferences.edit();
editor.putInt(hash + "_date", (int) (System.currentTimeMillis() / 1000));
SerializedData serializedData = new SerializedData(messageObject.messageOwner.getObjectSize());
messageObject.messageOwner.serializeToStream(serializedData);
editor.putString(hash + "_m", Utilities.bytesToHex(serializedData.toByteArray()));
editor.putString(hash + "_link", "https://" + MessagesController.getInstance(messageObject.currentAccount).linkPrefix + "/" + username + (TextUtils.isEmpty(short_name) ? "" : "?game=" + short_name));
editor.commit();
Browser.openUrl(parentActivity, url, false);
serializedData.cleanup();
} catch (Exception e) {
FileLog.e(e);
}
}
@Override
public ArrayList<ThemeDescription> getThemeDescriptions() {
ArrayList<ThemeDescription> themeDescriptions = new ArrayList<>();
if (type == TYPE_GAME) {
themeDescriptions.add(new ThemeDescription(fragmentView, ThemeDescription.FLAG_BACKGROUND, null, null, null, null, Theme.key_windowBackgroundWhite));
themeDescriptions.add(new ThemeDescription(actionBar, ThemeDescription.FLAG_BACKGROUND, null, null, null, null, Theme.key_actionBarDefault));
themeDescriptions.add(new ThemeDescription(actionBar, ThemeDescription.FLAG_AB_ITEMSCOLOR, null, null, null, null, Theme.key_actionBarDefaultIcon));
themeDescriptions.add(new ThemeDescription(actionBar, ThemeDescription.FLAG_AB_TITLECOLOR, null, null, null, null, Theme.key_actionBarDefaultTitle));
themeDescriptions.add(new ThemeDescription(actionBar, ThemeDescription.FLAG_AB_SELECTORCOLOR, null, null, null, null, Theme.key_actionBarDefaultSelector));
themeDescriptions.add(new ThemeDescription(actionBar, ThemeDescription.FLAG_AB_SUBMENUBACKGROUND, null, null, null, null, Theme.key_actionBarDefaultSubmenuBackground));
themeDescriptions.add(new ThemeDescription(actionBar, ThemeDescription.FLAG_AB_SUBMENUITEM, null, null, null, null, Theme.key_actionBarDefaultSubmenuItem));
themeDescriptions.add(new ThemeDescription(actionBar, ThemeDescription.FLAG_AB_SUBMENUITEM | ThemeDescription.FLAG_IMAGECOLOR, null, null, null, null, Theme.key_actionBarDefaultSubmenuItemIcon));
themeDescriptions.add(new ThemeDescription(progressView, 0, null, null, null, null, Theme.key_contextProgressInner2));
themeDescriptions.add(new ThemeDescription(progressView, 0, null, null, null, null, Theme.key_contextProgressOuter2));
} else {
themeDescriptions.add(new ThemeDescription(fragmentView, ThemeDescription.FLAG_BACKGROUND, null, null, null, null, Theme.key_windowBackgroundWhite));
themeDescriptions.add(new ThemeDescription(actionBar, ThemeDescription.FLAG_BACKGROUND, null, null, null, null, Theme.key_player_actionBar));
themeDescriptions.add(new ThemeDescription(actionBar, ThemeDescription.FLAG_AB_ITEMSCOLOR, null, null, null, null, Theme.key_player_actionBarItems));
themeDescriptions.add(new ThemeDescription(actionBar, ThemeDescription.FLAG_AB_TITLECOLOR, null, null, null, null, Theme.key_player_actionBarTitle));
themeDescriptions.add(new ThemeDescription(actionBar, ThemeDescription.FLAG_AB_SUBTITLECOLOR, null, null, null, null, Theme.key_player_actionBarTitle));
themeDescriptions.add(new ThemeDescription(actionBar, ThemeDescription.FLAG_AB_SELECTORCOLOR, null, null, null, null, Theme.key_player_actionBarSelector));
themeDescriptions.add(new ThemeDescription(actionBar, ThemeDescription.FLAG_AB_SUBMENUBACKGROUND, null, null, null, null, Theme.key_actionBarDefaultSubmenuBackground));
themeDescriptions.add(new ThemeDescription(actionBar, ThemeDescription.FLAG_AB_SUBMENUITEM, null, null, null, null, Theme.key_actionBarDefaultSubmenuItem));
themeDescriptions.add(new ThemeDescription(actionBar, ThemeDescription.FLAG_AB_SUBMENUITEM | ThemeDescription.FLAG_IMAGECOLOR, null, null, null, null, Theme.key_actionBarDefaultSubmenuItemIcon));
themeDescriptions.add(new ThemeDescription(progressView, 0, null, null, null, null, Theme.key_contextProgressInner4));
themeDescriptions.add(new ThemeDescription(progressView, 0, null, null, null, null, Theme.key_contextProgressOuter4));
}
return themeDescriptions;
}
}