2022-04-16 16:43:17 +02:00
|
|
|
package org.telegram.ui.Components;
|
|
|
|
|
|
|
|
import android.animation.Animator;
|
|
|
|
import android.animation.AnimatorListenerAdapter;
|
|
|
|
import android.animation.ValueAnimator;
|
|
|
|
import android.content.Context;
|
2022-04-21 20:03:20 +02:00
|
|
|
import android.content.res.Configuration;
|
2022-04-16 16:43:17 +02:00
|
|
|
import android.graphics.Canvas;
|
|
|
|
import android.graphics.Paint;
|
|
|
|
import android.os.Build;
|
|
|
|
import android.os.Bundle;
|
|
|
|
import android.view.GestureDetector;
|
|
|
|
import android.view.Gravity;
|
|
|
|
import android.view.MotionEvent;
|
|
|
|
import android.view.View;
|
|
|
|
import android.view.ViewConfiguration;
|
|
|
|
import android.view.WindowManager;
|
|
|
|
import android.webkit.WebView;
|
|
|
|
import android.widget.FrameLayout;
|
|
|
|
|
|
|
|
import androidx.annotation.NonNull;
|
|
|
|
import androidx.core.math.MathUtils;
|
|
|
|
import androidx.core.view.GestureDetectorCompat;
|
|
|
|
import androidx.dynamicanimation.animation.SpringAnimation;
|
|
|
|
import androidx.dynamicanimation.animation.SpringForce;
|
|
|
|
import androidx.recyclerview.widget.ChatListItemAnimator;
|
|
|
|
|
|
|
|
import org.json.JSONObject;
|
|
|
|
import org.telegram.messenger.AndroidUtilities;
|
|
|
|
import org.telegram.messenger.FileLog;
|
|
|
|
import org.telegram.messenger.LocaleController;
|
|
|
|
import org.telegram.messenger.MediaDataController;
|
|
|
|
import org.telegram.messenger.MessagesController;
|
|
|
|
import org.telegram.messenger.NotificationCenter;
|
|
|
|
import org.telegram.messenger.R;
|
|
|
|
import org.telegram.messenger.UserObject;
|
|
|
|
import org.telegram.tgnet.ConnectionsManager;
|
|
|
|
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.ChatActivity;
|
|
|
|
|
|
|
|
public class ChatAttachAlertBotWebViewLayout extends ChatAttachAlert.AttachAlertLayout implements NotificationCenter.NotificationCenterDelegate {
|
|
|
|
private final static int POLL_PERIOD = 60000;
|
|
|
|
|
|
|
|
private BotWebViewContainer webViewContainer;
|
|
|
|
private ValueAnimator webViewScrollAnimator;
|
|
|
|
|
|
|
|
private boolean ignoreLayout;
|
|
|
|
|
|
|
|
private long botId;
|
|
|
|
private long peerId;
|
|
|
|
private long queryId;
|
|
|
|
private boolean silent;
|
|
|
|
private int replyToMsgId;
|
|
|
|
private int currentAccount;
|
|
|
|
private String startCommand;
|
|
|
|
|
|
|
|
private boolean needReload;
|
|
|
|
private WebProgressView progressView;
|
|
|
|
private WebViewSwipeContainer swipeContainer;
|
|
|
|
private ActionBarMenuItem otherItem;
|
|
|
|
|
|
|
|
private int measureOffsetY;
|
|
|
|
|
|
|
|
private long lastSwipeTime;
|
|
|
|
|
|
|
|
private boolean ignoreMeasure;
|
|
|
|
private boolean isBotButtonAvailable;
|
|
|
|
|
|
|
|
private boolean destroyed;
|
|
|
|
private Runnable pollRunnable = () -> {
|
|
|
|
if (!destroyed) {
|
|
|
|
TLRPC.TL_messages_prolongWebView prolongWebView = new TLRPC.TL_messages_prolongWebView();
|
|
|
|
prolongWebView.bot = MessagesController.getInstance(currentAccount).getInputUser(botId);
|
|
|
|
prolongWebView.peer = MessagesController.getInstance(currentAccount).getInputPeer(peerId);
|
|
|
|
prolongWebView.query_id = queryId;
|
|
|
|
prolongWebView.silent = silent;
|
|
|
|
if (replyToMsgId != 0) {
|
|
|
|
prolongWebView.reply_to_msg_id = replyToMsgId;
|
|
|
|
prolongWebView.flags |= 1;
|
|
|
|
}
|
|
|
|
ConnectionsManager.getInstance(currentAccount).sendRequest(prolongWebView, (response, error) -> AndroidUtilities.runOnUIThread(() -> {
|
|
|
|
if (destroyed) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (error != null) {
|
|
|
|
parentAlert.dismiss();
|
|
|
|
} else {
|
|
|
|
AndroidUtilities.runOnUIThread(this.pollRunnable, POLL_PERIOD);
|
|
|
|
}
|
|
|
|
}));
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
public ChatAttachAlertBotWebViewLayout(ChatAttachAlert alert, Context context, Theme.ResourcesProvider resourcesProvider) {
|
|
|
|
super(alert, context, resourcesProvider);
|
|
|
|
|
|
|
|
ActionBarMenu menu = parentAlert.actionBar.createMenu();
|
|
|
|
otherItem = menu.addItem(0, R.drawable.ic_ab_other);
|
|
|
|
otherItem.addSubItem(R.id.menu_open_bot, R.drawable.msg_bot, LocaleController.getString(R.string.BotWebViewOpenBot));
|
|
|
|
otherItem.addSubItem(R.id.menu_reload_page, R.drawable.msg_retry, LocaleController.getString(R.string.BotWebViewReloadPage));
|
|
|
|
otherItem.addSubItem(R.id.menu_delete_bot, R.drawable.msg_delete, LocaleController.getString(R.string.BotWebViewDeleteBot));
|
|
|
|
parentAlert.actionBar.setActionBarMenuOnItemClick(new ActionBar.ActionBarMenuOnItemClick() {
|
|
|
|
@Override
|
|
|
|
public void onItemClick(int id) {
|
|
|
|
if (id == -1) {
|
|
|
|
parentAlert.dismiss();
|
|
|
|
} else if (id == R.id.menu_open_bot) {
|
|
|
|
Bundle bundle = new Bundle();
|
|
|
|
bundle.putLong("user_id", botId);
|
|
|
|
parentAlert.baseFragment.presentFragment(new ChatActivity(bundle));
|
|
|
|
parentAlert.dismiss();
|
|
|
|
} else if (id == R.id.menu_reload_page) {
|
2022-04-21 20:03:20 +02:00
|
|
|
if (webViewContainer.getWebView() != null) {
|
|
|
|
webViewContainer.getWebView().animate().cancel();
|
|
|
|
webViewContainer.getWebView().animate().alpha(0).start();
|
|
|
|
}
|
|
|
|
|
|
|
|
progressView.setLoadProgress(0);
|
|
|
|
progressView.setAlpha(1f);
|
|
|
|
progressView.setVisibility(VISIBLE);
|
|
|
|
|
|
|
|
webViewContainer.setBotUser(MessagesController.getInstance(currentAccount).getUser(botId));
|
|
|
|
webViewContainer.loadFlicker(currentAccount, botId);
|
|
|
|
webViewContainer.reload();
|
2022-04-16 16:43:17 +02:00
|
|
|
} else if (id == R.id.menu_delete_bot) {
|
|
|
|
for (TLRPC.TL_attachMenuBot bot : MediaDataController.getInstance(currentAccount).getAttachMenuBots().bots) {
|
|
|
|
if (bot.bot_id == botId) {
|
|
|
|
parentAlert.onLongClickBotButton(bot, MessagesController.getInstance(currentAccount).getUser(botId));
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
webViewContainer = new BotWebViewContainer(context, resourcesProvider, getThemedColor(Theme.key_dialogBackground)) {
|
|
|
|
@Override
|
|
|
|
public boolean dispatchTouchEvent(MotionEvent ev) {
|
|
|
|
if (ev.getAction() == MotionEvent.ACTION_DOWN) {
|
|
|
|
if (!isBotButtonAvailable) {
|
|
|
|
isBotButtonAvailable = true;
|
|
|
|
webViewContainer.restoreButtonData();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return super.dispatchTouchEvent(ev);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
swipeContainer = new WebViewSwipeContainer(context) {
|
|
|
|
@Override
|
|
|
|
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
|
|
|
|
super.onMeasure(widthMeasureSpec, MeasureSpec.makeMeasureSpec(MeasureSpec.getSize(heightMeasureSpec) - ActionBar.getCurrentActionBarHeight() - AndroidUtilities.dp(84) + measureOffsetY, MeasureSpec.EXACTLY));
|
|
|
|
}
|
|
|
|
};
|
|
|
|
swipeContainer.addView(webViewContainer, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT));
|
|
|
|
swipeContainer.setScrollListener(() -> {
|
|
|
|
parentAlert.updateLayout(this, true, 0);
|
|
|
|
webViewContainer.invalidateViewPortHeight();
|
|
|
|
lastSwipeTime = System.currentTimeMillis();
|
|
|
|
});
|
|
|
|
swipeContainer.setScrollEndListener(()-> webViewContainer.invalidateViewPortHeight(true));
|
|
|
|
swipeContainer.setDelegate(() -> parentAlert.dismiss());
|
|
|
|
|
|
|
|
addView(swipeContainer, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT));
|
|
|
|
addView(progressView = new WebProgressView(context, resourcesProvider), LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.BOTTOM, 0, 0, 0, 84));
|
|
|
|
|
|
|
|
webViewContainer.setWebViewProgressListener(progress -> {
|
|
|
|
progressView.setLoadProgressAnimated(progress);
|
|
|
|
if (progress == 1f) {
|
|
|
|
ValueAnimator animator = ValueAnimator.ofFloat(1, 0).setDuration(200);
|
|
|
|
animator.setInterpolator(CubicBezierInterpolator.DEFAULT);
|
|
|
|
animator.addUpdateListener(animation -> progressView.setAlpha((Float) animation.getAnimatedValue()));
|
|
|
|
animator.addListener(new AnimatorListenerAdapter() {
|
|
|
|
@Override
|
|
|
|
public void onAnimationEnd(Animator animation) {
|
|
|
|
progressView.setVisibility(GONE);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
animator.start();
|
2022-04-21 20:03:20 +02:00
|
|
|
|
|
|
|
requestEnableKeyboard();
|
2022-04-16 16:43:17 +02:00
|
|
|
}
|
|
|
|
});
|
2022-04-21 20:03:20 +02:00
|
|
|
|
|
|
|
NotificationCenter.getGlobalInstance().addObserver(this, NotificationCenter.didSetNewTheme);
|
2022-04-16 16:43:17 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
public boolean canExpandByRequest() {
|
2022-04-21 20:03:20 +02:00
|
|
|
return /* System.currentTimeMillis() - lastSwipeTime > 1000 && */ !swipeContainer.isSwipeInProgress();
|
2022-04-16 16:43:17 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
public void setMeasureOffsetY(int measureOffsetY) {
|
|
|
|
this.measureOffsetY = measureOffsetY;
|
|
|
|
swipeContainer.requestLayout();
|
|
|
|
}
|
|
|
|
|
|
|
|
public void disallowSwipeOffsetAnimation() {
|
|
|
|
swipeContainer.setSwipeOffsetAnimationDisallowed(true);
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
|
|
|
|
if (ignoreMeasure) {
|
|
|
|
setMeasuredDimension(getMeasuredWidth(), getMeasuredHeight());
|
|
|
|
} else {
|
|
|
|
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public void onPanTransitionStart(boolean keyboardVisible, int contentHeight) {
|
|
|
|
if (!keyboardVisible) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2022-04-23 11:51:09 +02:00
|
|
|
webViewContainer.setViewPortByMeasureSuppressed(true);
|
|
|
|
|
|
|
|
boolean doNotScroll = false;
|
|
|
|
float openOffset = -swipeContainer.getOffsetY() + swipeContainer.getTopActionBarOffsetY();
|
|
|
|
if (swipeContainer.getSwipeOffsetY() != openOffset) {
|
|
|
|
swipeContainer.stickTo(openOffset);
|
|
|
|
doNotScroll = true;
|
|
|
|
}
|
|
|
|
|
2022-04-16 16:43:17 +02:00
|
|
|
int oldh = contentHeight + parentAlert.sizeNotifierFrameLayout.measureKeyboardHeight();
|
|
|
|
setMeasuredDimension(getMeasuredWidth(), contentHeight);
|
|
|
|
ignoreMeasure = true;
|
2022-04-23 11:51:09 +02:00
|
|
|
swipeContainer.setSwipeOffsetAnimationDisallowed(true);
|
2022-04-16 16:43:17 +02:00
|
|
|
|
2022-04-23 11:51:09 +02:00
|
|
|
if (!doNotScroll) {
|
|
|
|
if (webViewScrollAnimator != null) {
|
|
|
|
webViewScrollAnimator.cancel();
|
|
|
|
webViewScrollAnimator = null;
|
|
|
|
}
|
2022-04-16 16:43:17 +02:00
|
|
|
|
2022-04-23 11:51:09 +02:00
|
|
|
if (webViewContainer.getWebView() != null) {
|
|
|
|
int fromY = webViewContainer.getWebView().getScrollY();
|
|
|
|
int toY = fromY + (oldh - contentHeight);
|
|
|
|
webViewScrollAnimator = ValueAnimator.ofInt(fromY, toY).setDuration(250);
|
|
|
|
webViewScrollAnimator.setInterpolator(ChatListItemAnimator.DEFAULT_INTERPOLATOR);
|
|
|
|
webViewScrollAnimator.addUpdateListener(animation -> {
|
|
|
|
int val = (int) animation.getAnimatedValue();
|
2022-04-21 20:03:20 +02:00
|
|
|
if (webViewContainer.getWebView() != null) {
|
2022-04-23 11:51:09 +02:00
|
|
|
webViewContainer.getWebView().setScrollY(val);
|
2022-04-21 20:03:20 +02:00
|
|
|
}
|
2022-04-23 11:51:09 +02:00
|
|
|
});
|
|
|
|
webViewScrollAnimator.addListener(new AnimatorListenerAdapter() {
|
|
|
|
@Override
|
|
|
|
public void onAnimationEnd(Animator animation) {
|
|
|
|
if (webViewContainer.getWebView() != null) {
|
|
|
|
webViewContainer.getWebView().setScrollY(toY);
|
|
|
|
}
|
|
|
|
if (animation == webViewScrollAnimator) {
|
|
|
|
webViewScrollAnimator = null;
|
|
|
|
}
|
2022-04-21 20:03:20 +02:00
|
|
|
}
|
2022-04-23 11:51:09 +02:00
|
|
|
});
|
|
|
|
webViewScrollAnimator.start();
|
|
|
|
}
|
2022-04-21 20:03:20 +02:00
|
|
|
}
|
2022-04-16 16:43:17 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public void onPanTransitionEnd() {
|
|
|
|
ignoreMeasure = false;
|
2022-04-23 11:51:09 +02:00
|
|
|
swipeContainer.setSwipeOffsetAnimationDisallowed(false);
|
|
|
|
webViewContainer.setViewPortByMeasureSuppressed(false);
|
2022-04-16 16:43:17 +02:00
|
|
|
requestLayout();
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
void onShow(ChatAttachAlert.AttachAlertLayout previousLayout) {
|
|
|
|
parentAlert.actionBar.setTitle(UserObject.getUserName(MessagesController.getInstance(currentAccount).getUser(botId)));
|
|
|
|
swipeContainer.setSwipeOffsetY(0);
|
2022-04-21 20:03:20 +02:00
|
|
|
if (webViewContainer.getWebView() != null) {
|
|
|
|
webViewContainer.getWebView().scrollTo(0, 0);
|
|
|
|
}
|
2022-04-16 16:43:17 +02:00
|
|
|
if (parentAlert.getBaseFragment() != null) {
|
|
|
|
webViewContainer.setParentActivity(parentAlert.getBaseFragment().getParentActivity());
|
|
|
|
}
|
|
|
|
otherItem.setVisibility(VISIBLE);
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
void onShown() {
|
2022-04-21 20:03:20 +02:00
|
|
|
if (webViewContainer.isPageLoaded()) {
|
|
|
|
requestEnableKeyboard();
|
|
|
|
}
|
2022-04-16 16:43:17 +02:00
|
|
|
|
|
|
|
swipeContainer.setSwipeOffsetAnimationDisallowed(false);
|
|
|
|
AndroidUtilities.runOnUIThread(() -> webViewContainer.restoreButtonData());
|
|
|
|
}
|
|
|
|
|
|
|
|
private void requestEnableKeyboard() {
|
|
|
|
BaseFragment fragment = parentAlert.getBaseFragment();
|
|
|
|
if (fragment instanceof ChatActivity && ((ChatActivity) fragment).contentView.measureKeyboardHeight() > AndroidUtilities.dp(20)) {
|
|
|
|
AndroidUtilities.hideKeyboard(parentAlert.baseFragment.getFragmentView());
|
2022-04-21 20:03:20 +02:00
|
|
|
AndroidUtilities.runOnUIThread(this::requestEnableKeyboard, 250);
|
2022-04-16 16:43:17 +02:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2022-04-21 20:03:20 +02:00
|
|
|
parentAlert.getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_VISIBLE | WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE);
|
2022-04-16 16:43:17 +02:00
|
|
|
setFocusable(true);
|
|
|
|
parentAlert.setFocusable(true);
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
void onHidden() {
|
|
|
|
super.onHidden();
|
|
|
|
|
|
|
|
parentAlert.setFocusable(false);
|
|
|
|
parentAlert.getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_NOTHING);
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
int getCurrentItemTop() {
|
|
|
|
return (int) (swipeContainer.getSwipeOffsetY() + swipeContainer.getOffsetY());
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public void setTranslationY(float translationY) {
|
|
|
|
super.setTranslationY(translationY);
|
|
|
|
parentAlert.getSheetContainer().invalidate();
|
|
|
|
}
|
|
|
|
|
|
|
|
public String getStartCommand() {
|
|
|
|
return startCommand;
|
|
|
|
}
|
|
|
|
|
|
|
|
public void requestWebView(int currentAccount, long peerId, long botId, boolean silent, int replyToMsgId) {
|
|
|
|
requestWebView(currentAccount, peerId, botId, silent, replyToMsgId, null);
|
|
|
|
}
|
|
|
|
|
|
|
|
public void requestWebView(int currentAccount, long peerId, long botId, boolean silent, int replyToMsgId, String startCommand) {
|
|
|
|
this.currentAccount = currentAccount;
|
|
|
|
this.peerId = peerId;
|
|
|
|
this.botId = botId;
|
|
|
|
this.silent = silent;
|
|
|
|
this.replyToMsgId = replyToMsgId;
|
|
|
|
this.startCommand = startCommand;
|
|
|
|
|
|
|
|
webViewContainer.setBotUser(MessagesController.getInstance(currentAccount).getUser(botId));
|
|
|
|
webViewContainer.loadFlicker(currentAccount, botId);
|
|
|
|
|
|
|
|
TLRPC.TL_messages_requestWebView req = new TLRPC.TL_messages_requestWebView();
|
|
|
|
req.peer = MessagesController.getInstance(currentAccount).getInputPeer(peerId);
|
|
|
|
req.bot = MessagesController.getInstance(currentAccount).getInputUser(botId);
|
|
|
|
req.silent = silent;
|
|
|
|
if (startCommand != null) {
|
|
|
|
req.start_param = startCommand;
|
|
|
|
req.flags |= 8;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (replyToMsgId != 0) {
|
|
|
|
req.reply_to_msg_id = replyToMsgId;
|
|
|
|
req.flags |= 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
try {
|
|
|
|
JSONObject jsonObject = new JSONObject();
|
|
|
|
jsonObject.put("bg_color", getThemedColor(Theme.key_dialogBackground));
|
|
|
|
jsonObject.put("text_color", getThemedColor(Theme.key_windowBackgroundWhiteBlackText));
|
|
|
|
jsonObject.put("hint_color", getThemedColor(Theme.key_windowBackgroundWhiteHintText));
|
|
|
|
jsonObject.put("link_color", getThemedColor(Theme.key_windowBackgroundWhiteLinkText));
|
|
|
|
jsonObject.put("button_color", getThemedColor(Theme.key_featuredStickers_addButton));
|
|
|
|
jsonObject.put("button_text_color", getThemedColor(Theme.key_featuredStickers_buttonText));
|
|
|
|
|
|
|
|
req.theme_params = new TLRPC.TL_dataJSON();
|
|
|
|
req.theme_params.data = jsonObject.toString();
|
|
|
|
req.flags |= 4;
|
|
|
|
} catch (Exception e) {
|
|
|
|
FileLog.e(e);
|
|
|
|
}
|
|
|
|
|
|
|
|
ConnectionsManager.getInstance(currentAccount).sendRequest(req, (response, error) -> AndroidUtilities.runOnUIThread(() -> {
|
|
|
|
if (response instanceof TLRPC.TL_webViewResultUrl) {
|
|
|
|
TLRPC.TL_webViewResultUrl resultUrl = (TLRPC.TL_webViewResultUrl) response;
|
|
|
|
queryId = resultUrl.query_id;
|
|
|
|
webViewContainer.loadUrl(resultUrl.url);
|
2022-04-21 20:03:20 +02:00
|
|
|
swipeContainer.setWebView(webViewContainer.getWebView());
|
2022-04-16 16:43:17 +02:00
|
|
|
|
|
|
|
AndroidUtilities.runOnUIThread(pollRunnable);
|
|
|
|
}
|
|
|
|
}));
|
|
|
|
|
|
|
|
NotificationCenter.getInstance(currentAccount).addObserver(this, NotificationCenter.webViewResultSent);
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
void onDestroy() {
|
|
|
|
NotificationCenter.getInstance(currentAccount).removeObserver(this, NotificationCenter.webViewResultSent);
|
2022-04-21 20:03:20 +02:00
|
|
|
NotificationCenter.getGlobalInstance().removeObserver(this, NotificationCenter.didSetNewTheme);
|
2022-04-16 16:43:17 +02:00
|
|
|
|
|
|
|
ActionBarMenu menu = parentAlert.actionBar.createMenu();
|
|
|
|
otherItem.removeAllSubItems();
|
|
|
|
menu.removeView(otherItem);
|
|
|
|
|
|
|
|
webViewContainer.destroyWebView();
|
|
|
|
destroyed = true;
|
|
|
|
|
|
|
|
AndroidUtilities.cancelRunOnUIThread(pollRunnable);
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
void onHide() {
|
|
|
|
super.onHide();
|
|
|
|
otherItem.setVisibility(GONE);
|
|
|
|
isBotButtonAvailable = false;
|
|
|
|
|
|
|
|
if (webViewContainer.hasUserPermissions()) {
|
|
|
|
webViewContainer.destroyWebView();
|
|
|
|
needReload = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
public boolean needReload() {
|
|
|
|
if (needReload) {
|
|
|
|
needReload = false;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
int getListTopPadding() {
|
|
|
|
return (int) swipeContainer.getOffsetY();
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
int getFirstOffset() {
|
|
|
|
return getListTopPadding() + AndroidUtilities.dp(56);
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
void onPreMeasure(int availableWidth, int availableHeight) {
|
|
|
|
int padding;
|
|
|
|
if (!AndroidUtilities.isTablet() && AndroidUtilities.displaySize.x > AndroidUtilities.displaySize.y) {
|
|
|
|
padding = (int) (availableHeight / 3.5f);
|
|
|
|
} else {
|
|
|
|
padding = (availableHeight / 5 * 2);
|
|
|
|
}
|
|
|
|
parentAlert.setAllowNestedScroll(true);
|
|
|
|
|
|
|
|
if (padding < 0) {
|
|
|
|
padding = 0;
|
|
|
|
}
|
|
|
|
if (swipeContainer.getOffsetY() != padding) {
|
|
|
|
ignoreLayout = true;
|
|
|
|
swipeContainer.setOffsetY(padding);
|
|
|
|
ignoreLayout = false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
int getButtonsHideOffset() {
|
2022-04-23 11:51:09 +02:00
|
|
|
return (int) swipeContainer.getTopActionBarOffsetY() + AndroidUtilities.dp(12);
|
2022-04-16 16:43:17 +02:00
|
|
|
}
|
|
|
|
|
2022-04-21 20:03:20 +02:00
|
|
|
@Override
|
|
|
|
boolean onBackPressed() {
|
|
|
|
return webViewContainer.onBackPressed();
|
|
|
|
}
|
|
|
|
|
2022-04-16 16:43:17 +02:00
|
|
|
@Override
|
|
|
|
public void requestLayout() {
|
|
|
|
if (ignoreLayout) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
super.requestLayout();
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
void scrollToTop() {
|
|
|
|
swipeContainer.stickTo(-swipeContainer.getOffsetY() + swipeContainer.getTopActionBarOffsetY());
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
boolean shouldHideBottomButtons() {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
int needsActionBar() {
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
public BotWebViewContainer getWebViewContainer() {
|
|
|
|
return webViewContainer;
|
|
|
|
}
|
|
|
|
|
|
|
|
public void setDelegate(BotWebViewContainer.Delegate delegate) {
|
|
|
|
webViewContainer.setDelegate(delegate);
|
|
|
|
}
|
|
|
|
|
|
|
|
public boolean isBotButtonAvailable() {
|
|
|
|
return isBotButtonAvailable;
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public void didReceivedNotification(int id, int account, Object... args) {
|
|
|
|
if (id == NotificationCenter.webViewResultSent) {
|
|
|
|
long queryId = (long) args[0];
|
|
|
|
|
|
|
|
if (this.queryId == queryId) {
|
|
|
|
webViewContainer.destroyWebView();
|
|
|
|
needReload = true;
|
|
|
|
parentAlert.dismiss();
|
|
|
|
}
|
2022-04-21 20:03:20 +02:00
|
|
|
} else if (id == NotificationCenter.didSetNewTheme) {
|
|
|
|
webViewContainer.updateFlickerBackgroundColor(getThemedColor(Theme.key_dialogBackground));
|
2022-04-16 16:43:17 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
public static class WebViewSwipeContainer extends FrameLayout {
|
|
|
|
public final static SimpleFloatPropertyCompat<WebViewSwipeContainer> SWIPE_OFFSET_Y = new SimpleFloatPropertyCompat<>("swipeOffsetY", WebViewSwipeContainer::getSwipeOffsetY, WebViewSwipeContainer::setSwipeOffsetY);
|
|
|
|
|
|
|
|
private GestureDetectorCompat gestureDetector;
|
|
|
|
private boolean isScrolling;
|
|
|
|
private boolean isSwipeDisallowed;
|
|
|
|
|
|
|
|
private float topActionBarOffsetY = ActionBar.getCurrentActionBarHeight();
|
|
|
|
private float offsetY = -1;
|
2022-04-23 11:51:09 +02:00
|
|
|
private float pendingOffsetY = -1;
|
2022-04-16 16:43:17 +02:00
|
|
|
private float swipeOffsetY;
|
|
|
|
private boolean isSwipeOffsetAnimationDisallowed;
|
|
|
|
|
2022-04-23 11:51:09 +02:00
|
|
|
private ValueAnimator offsetYAnimator;
|
|
|
|
|
2022-04-16 16:43:17 +02:00
|
|
|
private boolean flingInProgress;
|
|
|
|
|
|
|
|
private WebView webView;
|
|
|
|
|
|
|
|
private Runnable scrollListener;
|
|
|
|
private Runnable scrollEndListener;
|
|
|
|
private Delegate delegate;
|
|
|
|
|
|
|
|
private SpringAnimation scrollAnimator;
|
|
|
|
|
2022-04-21 20:03:20 +02:00
|
|
|
private int swipeStickyRange;
|
|
|
|
|
2022-04-16 16:43:17 +02:00
|
|
|
public WebViewSwipeContainer(@NonNull Context context) {
|
|
|
|
super(context);
|
|
|
|
|
|
|
|
int touchSlop = ViewConfiguration.get(context).getScaledTouchSlop();
|
|
|
|
gestureDetector = new GestureDetectorCompat(context, new GestureDetector.SimpleOnGestureListener() {
|
|
|
|
@Override
|
|
|
|
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
|
|
|
|
if (isSwipeDisallowed) {
|
|
|
|
return false;
|
|
|
|
}
|
2022-04-21 20:03:20 +02:00
|
|
|
if (velocityY >= 700 && (webView == null || webView.getScrollY() == 0)) {
|
2022-04-16 16:43:17 +02:00
|
|
|
flingInProgress = true;
|
|
|
|
|
2022-04-21 20:03:20 +02:00
|
|
|
if (swipeOffsetY >= swipeStickyRange) {
|
2022-04-16 16:43:17 +02:00
|
|
|
if (delegate != null) {
|
|
|
|
delegate.onDismiss();
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
stickTo(0);
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
} else if (velocityY <= -700 && swipeOffsetY > -offsetY + topActionBarOffsetY) {
|
|
|
|
flingInProgress = true;
|
|
|
|
stickTo(-offsetY + topActionBarOffsetY);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
|
|
|
|
if (!isScrolling && !isSwipeDisallowed) {
|
2022-04-28 22:24:40 +02:00
|
|
|
if (Math.abs(distanceY) >= touchSlop && Math.abs(distanceY) * 1.5f >= Math.abs(distanceX) && (swipeOffsetY != -offsetY + topActionBarOffsetY || webView == null || distanceY < 0 && webView.getScrollY() == 0)) {
|
2022-04-16 16:43:17 +02:00
|
|
|
isScrolling = true;
|
|
|
|
|
|
|
|
MotionEvent ev = MotionEvent.obtain(0, 0, MotionEvent.ACTION_CANCEL, 0, 0, 0);
|
|
|
|
for (int i = 0; i < getChildCount(); i++) {
|
|
|
|
getChildAt(i).dispatchTouchEvent(ev);
|
|
|
|
}
|
|
|
|
ev.recycle();
|
|
|
|
|
|
|
|
return true;
|
2022-04-21 20:03:20 +02:00
|
|
|
} else if (webView != null && webView.canScrollHorizontally(distanceX >= 0 ? 1 : -1)) {
|
2022-04-16 16:43:17 +02:00
|
|
|
isSwipeDisallowed = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (isScrolling) {
|
|
|
|
if (distanceY < 0) {
|
|
|
|
if (swipeOffsetY > -offsetY + topActionBarOffsetY) {
|
|
|
|
swipeOffsetY -= distanceY;
|
2022-04-21 20:03:20 +02:00
|
|
|
} else if (webView != null) {
|
2022-04-16 16:43:17 +02:00
|
|
|
float newWebScrollY = webView.getScrollY() + distanceY;
|
|
|
|
webView.setScrollY((int) MathUtils.clamp(newWebScrollY, 0, Math.max(webView.getContentHeight(), webView.getHeight()) - topActionBarOffsetY));
|
|
|
|
|
|
|
|
if (newWebScrollY < 0) {
|
|
|
|
swipeOffsetY -= newWebScrollY;
|
|
|
|
}
|
2022-04-21 20:03:20 +02:00
|
|
|
} else {
|
|
|
|
swipeOffsetY -= distanceY;
|
2022-04-16 16:43:17 +02:00
|
|
|
}
|
|
|
|
} else {
|
2022-04-21 20:03:20 +02:00
|
|
|
swipeOffsetY -= distanceY;
|
2022-04-16 16:43:17 +02:00
|
|
|
|
2022-04-21 20:03:20 +02:00
|
|
|
if (webView != null && swipeOffsetY < -offsetY + topActionBarOffsetY) {
|
2022-04-16 16:43:17 +02:00
|
|
|
float newWebScrollY = webView.getScrollY() - (swipeOffsetY + offsetY - topActionBarOffsetY);
|
|
|
|
webView.setScrollY((int) MathUtils.clamp(newWebScrollY, 0, Math.max(webView.getContentHeight(), webView.getHeight()) - topActionBarOffsetY));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
swipeOffsetY = MathUtils.clamp(swipeOffsetY, -offsetY + topActionBarOffsetY, getHeight() - offsetY + topActionBarOffsetY);
|
|
|
|
invalidateTranslation();
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
});
|
2022-04-21 20:03:20 +02:00
|
|
|
updateStickyRange();
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
protected void onConfigurationChanged(Configuration newConfig) {
|
|
|
|
super.onConfigurationChanged(newConfig);
|
|
|
|
updateStickyRange();
|
|
|
|
}
|
|
|
|
|
|
|
|
private void updateStickyRange() {
|
|
|
|
swipeStickyRange = AndroidUtilities.dp(AndroidUtilities.displaySize.x > AndroidUtilities.displaySize.y ? 8 : 64);
|
2022-04-16 16:43:17 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public void requestDisallowInterceptTouchEvent(boolean disallowIntercept) {
|
|
|
|
super.requestDisallowInterceptTouchEvent(disallowIntercept);
|
|
|
|
|
|
|
|
if (disallowIntercept) {
|
|
|
|
isSwipeDisallowed = true;
|
|
|
|
isScrolling = false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
public void setSwipeOffsetAnimationDisallowed(boolean swipeOffsetAnimationDisallowed) {
|
|
|
|
isSwipeOffsetAnimationDisallowed = swipeOffsetAnimationDisallowed;
|
|
|
|
}
|
|
|
|
|
|
|
|
public void setScrollListener(Runnable scrollListener) {
|
|
|
|
this.scrollListener = scrollListener;
|
|
|
|
}
|
|
|
|
|
|
|
|
public void setScrollEndListener(Runnable scrollEndListener) {
|
|
|
|
this.scrollEndListener = scrollEndListener;
|
|
|
|
}
|
|
|
|
|
|
|
|
public void setWebView(WebView webView) {
|
|
|
|
this.webView = webView;
|
|
|
|
}
|
|
|
|
|
|
|
|
public void setTopActionBarOffsetY(float topActionBarOffsetY) {
|
|
|
|
this.topActionBarOffsetY = topActionBarOffsetY;
|
|
|
|
invalidateTranslation();
|
|
|
|
}
|
|
|
|
|
|
|
|
public void setSwipeOffsetY(float swipeOffsetY) {
|
|
|
|
this.swipeOffsetY = swipeOffsetY;
|
|
|
|
invalidateTranslation();
|
|
|
|
}
|
|
|
|
|
|
|
|
public void setOffsetY(float offsetY) {
|
|
|
|
float wasOffsetY = this.offsetY;
|
|
|
|
boolean wasOnTop = swipeOffsetY == -wasOffsetY + topActionBarOffsetY;
|
|
|
|
if (wasOffsetY != -1 && !isSwipeOffsetAnimationDisallowed) {
|
2022-04-23 11:51:09 +02:00
|
|
|
offsetYAnimator = ValueAnimator.ofFloat(wasOffsetY, offsetY).setDuration(200);
|
|
|
|
offsetYAnimator.setInterpolator(CubicBezierInterpolator.DEFAULT);
|
|
|
|
offsetYAnimator.addUpdateListener(animation -> {
|
2022-04-16 16:43:17 +02:00
|
|
|
this.offsetY = (float) animation.getAnimatedValue();
|
|
|
|
if (wasOnTop) {
|
|
|
|
swipeOffsetY = -this.offsetY + topActionBarOffsetY;
|
|
|
|
} else {
|
|
|
|
swipeOffsetY = MathUtils.clamp(swipeOffsetY, -this.offsetY + topActionBarOffsetY, getHeight() - this.offsetY + topActionBarOffsetY);
|
|
|
|
}
|
2022-04-23 11:51:09 +02:00
|
|
|
if (scrollAnimator != null && scrollAnimator.getSpring().getFinalPosition() == -wasOffsetY + topActionBarOffsetY) {
|
|
|
|
scrollAnimator.getSpring().setFinalPosition(-offsetY + topActionBarOffsetY);
|
|
|
|
}
|
2022-04-16 16:43:17 +02:00
|
|
|
invalidateTranslation();
|
|
|
|
});
|
2022-04-23 11:51:09 +02:00
|
|
|
offsetYAnimator.addListener(new AnimatorListenerAdapter() {
|
|
|
|
private boolean isCanceled;
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public void onAnimationEnd(Animator animation) {
|
|
|
|
if (offsetYAnimator == animation) {
|
|
|
|
offsetYAnimator = null;
|
|
|
|
|
|
|
|
if (!isCanceled) {
|
|
|
|
WebViewSwipeContainer.this.offsetY = offsetY;
|
|
|
|
invalidateTranslation();
|
|
|
|
} else {
|
|
|
|
pendingOffsetY = offsetY;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public void onAnimationCancel(Animator animation) {
|
|
|
|
isCanceled = true;
|
|
|
|
}
|
|
|
|
});
|
|
|
|
offsetYAnimator.start();
|
2022-04-16 16:43:17 +02:00
|
|
|
} else {
|
|
|
|
this.offsetY = offsetY;
|
|
|
|
if (wasOnTop) {
|
|
|
|
this.swipeOffsetY = -this.offsetY + topActionBarOffsetY;
|
|
|
|
}
|
|
|
|
invalidateTranslation();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
private void invalidateTranslation() {
|
|
|
|
setTranslationY(Math.max(topActionBarOffsetY, offsetY + swipeOffsetY));
|
|
|
|
if (scrollListener != null) {
|
|
|
|
scrollListener.run();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
public float getTopActionBarOffsetY() {
|
|
|
|
return topActionBarOffsetY;
|
|
|
|
}
|
|
|
|
|
|
|
|
public float getOffsetY() {
|
|
|
|
return offsetY;
|
|
|
|
}
|
|
|
|
|
|
|
|
public float getSwipeOffsetY() {
|
|
|
|
return swipeOffsetY;
|
|
|
|
}
|
|
|
|
|
|
|
|
public void setDelegate(Delegate delegate) {
|
|
|
|
this.delegate = delegate;
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public boolean dispatchTouchEvent(MotionEvent ev) {
|
|
|
|
if (isScrolling && ev.getActionIndex() != 0) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
MotionEvent rawEvent = MotionEvent.obtain(ev);
|
|
|
|
int index = ev.getActionIndex();
|
|
|
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
|
|
|
|
rawEvent.setLocation(ev.getRawX(index), ev.getRawY(index));
|
|
|
|
} else {
|
|
|
|
float offsetX = ev.getRawX() - ev.getX(), offsetY = ev.getRawY() - ev.getY();
|
|
|
|
rawEvent.setLocation(ev.getX(index) + offsetX, ev.getY(index) + offsetY);
|
|
|
|
}
|
|
|
|
boolean detector = gestureDetector.onTouchEvent(rawEvent);
|
|
|
|
rawEvent.recycle();
|
|
|
|
|
|
|
|
if (ev.getAction() == MotionEvent.ACTION_UP || ev.getAction() == MotionEvent.ACTION_CANCEL) {
|
|
|
|
isSwipeDisallowed = false;
|
|
|
|
isScrolling = false;
|
|
|
|
|
|
|
|
if (flingInProgress) {
|
|
|
|
flingInProgress = false;
|
|
|
|
} else {
|
2022-04-21 20:03:20 +02:00
|
|
|
if (swipeOffsetY <= -swipeStickyRange) {
|
2022-04-23 11:51:09 +02:00
|
|
|
if (swipeOffsetY != -offsetY + topActionBarOffsetY) {
|
|
|
|
stickTo(-offsetY + topActionBarOffsetY);
|
|
|
|
}
|
2022-04-21 20:03:20 +02:00
|
|
|
} else if (swipeOffsetY > -swipeStickyRange && swipeOffsetY <= swipeStickyRange) {
|
2022-04-23 11:51:09 +02:00
|
|
|
if (swipeOffsetY != 0) {
|
|
|
|
stickTo(0);
|
|
|
|
}
|
2022-04-16 16:43:17 +02:00
|
|
|
} else {
|
|
|
|
if (delegate != null) {
|
|
|
|
delegate.onDismiss();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
boolean superTouch = super.dispatchTouchEvent(ev);
|
|
|
|
if (!superTouch && !detector && ev.getAction() == MotionEvent.ACTION_DOWN) {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return superTouch || detector;
|
|
|
|
}
|
|
|
|
|
|
|
|
public void stickTo(float offset) {
|
|
|
|
stickTo(offset, null);
|
|
|
|
}
|
|
|
|
|
|
|
|
public void stickTo(float offset, Runnable callback) {
|
2022-04-23 11:51:09 +02:00
|
|
|
if (swipeOffsetY == offset || scrollAnimator != null && scrollAnimator.getSpring().getFinalPosition() == offset) {
|
2022-04-16 16:43:17 +02:00
|
|
|
if (callback != null) {
|
|
|
|
callback.run();
|
|
|
|
}
|
|
|
|
if (scrollEndListener != null) {
|
|
|
|
scrollEndListener.run();
|
|
|
|
}
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2022-04-23 11:51:09 +02:00
|
|
|
if (offsetYAnimator != null) {
|
|
|
|
offsetYAnimator.cancel();
|
|
|
|
}
|
2022-04-16 16:43:17 +02:00
|
|
|
if (scrollAnimator != null) {
|
|
|
|
scrollAnimator.cancel();
|
|
|
|
}
|
|
|
|
scrollAnimator = new SpringAnimation(this, SWIPE_OFFSET_Y, offset)
|
|
|
|
.setSpring(new SpringForce(offset)
|
|
|
|
.setStiffness(1400)
|
|
|
|
.setDampingRatio(SpringForce.DAMPING_RATIO_NO_BOUNCY))
|
|
|
|
.addEndListener((animation, canceled, value, velocity) -> {
|
|
|
|
if (animation == scrollAnimator) {
|
|
|
|
scrollAnimator = null;
|
|
|
|
|
|
|
|
if (callback != null) {
|
|
|
|
callback.run();
|
|
|
|
}
|
|
|
|
|
|
|
|
if (scrollEndListener != null) {
|
|
|
|
scrollEndListener.run();
|
|
|
|
}
|
2022-04-23 11:51:09 +02:00
|
|
|
|
|
|
|
if (pendingOffsetY != -1) {
|
|
|
|
boolean wasDisallowed = isSwipeOffsetAnimationDisallowed;
|
|
|
|
isSwipeOffsetAnimationDisallowed = true;
|
|
|
|
setOffsetY(pendingOffsetY);
|
|
|
|
pendingOffsetY = -1;
|
|
|
|
isSwipeOffsetAnimationDisallowed = wasDisallowed;
|
|
|
|
}
|
2022-04-16 16:43:17 +02:00
|
|
|
}
|
|
|
|
});
|
|
|
|
scrollAnimator.start();
|
|
|
|
}
|
|
|
|
|
|
|
|
public boolean isSwipeInProgress() {
|
|
|
|
return isScrolling;
|
|
|
|
}
|
|
|
|
|
|
|
|
public interface Delegate {
|
|
|
|
/**
|
|
|
|
* Called to dismiss parent layout
|
|
|
|
*/
|
|
|
|
void onDismiss();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-04-28 22:24:40 +02:00
|
|
|
public final static class WebProgressView extends View {
|
2022-04-16 16:43:17 +02:00
|
|
|
private final SimpleFloatPropertyCompat<WebProgressView> LOAD_PROGRESS_PROPERTY = new SimpleFloatPropertyCompat<>("loadProgress", obj -> obj.loadProgress, WebProgressView::setLoadProgress).setMultiplier(100f);
|
|
|
|
|
|
|
|
private Paint bluePaint = new Paint(Paint.ANTI_ALIAS_FLAG);
|
|
|
|
private float loadProgress;
|
|
|
|
private SpringAnimation springAnimation;
|
|
|
|
private Theme.ResourcesProvider resourcesProvider;
|
|
|
|
|
|
|
|
public WebProgressView(Context context, Theme.ResourcesProvider resourcesProvider) {
|
|
|
|
super(context);
|
|
|
|
this.resourcesProvider = resourcesProvider;
|
|
|
|
|
|
|
|
bluePaint.setColor(getThemedColor(Theme.key_featuredStickers_addButton));
|
|
|
|
bluePaint.setStyle(Paint.Style.STROKE);
|
|
|
|
bluePaint.setStrokeWidth(AndroidUtilities.dp(2));
|
|
|
|
bluePaint.setStrokeCap(Paint.Cap.ROUND);
|
|
|
|
}
|
|
|
|
|
|
|
|
protected int getThemedColor(String key) {
|
|
|
|
Integer color = resourcesProvider != null ? resourcesProvider.getColor(key) : null;
|
|
|
|
return color != null ? color : Theme.getColor(key);
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
protected void onAttachedToWindow() {
|
|
|
|
super.onAttachedToWindow();
|
|
|
|
|
|
|
|
springAnimation = new SpringAnimation(this, LOAD_PROGRESS_PROPERTY)
|
|
|
|
.setSpring(new SpringForce()
|
|
|
|
.setStiffness(400f)
|
|
|
|
.setDampingRatio(SpringForce.DAMPING_RATIO_NO_BOUNCY));
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
protected void onDetachedFromWindow() {
|
|
|
|
super.onDetachedFromWindow();
|
|
|
|
|
|
|
|
springAnimation.cancel();
|
|
|
|
springAnimation = null;
|
|
|
|
}
|
|
|
|
|
|
|
|
public void setLoadProgressAnimated(float loadProgress) {
|
|
|
|
if (springAnimation == null) {
|
|
|
|
setLoadProgress(loadProgress);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
springAnimation.getSpring().setFinalPosition(loadProgress * 100f);
|
|
|
|
springAnimation.start();
|
|
|
|
}
|
|
|
|
|
|
|
|
public void setLoadProgress(float loadProgress) {
|
|
|
|
this.loadProgress = loadProgress;
|
|
|
|
invalidate();
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public void draw(Canvas canvas) {
|
|
|
|
super.draw(canvas);
|
|
|
|
|
|
|
|
float y = getHeight() - bluePaint.getStrokeWidth() / 2f;
|
|
|
|
canvas.drawLine(0, y, getWidth() * loadProgress, y, bluePaint);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|