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

1046 lines
52 KiB
Java

package org.telegram.ui;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.app.Dialog;
import android.content.Context;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.LinearGradient;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffColorFilter;
import android.graphics.Rect;
import android.graphics.Shader;
import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.os.Build;
import android.text.SpannableString;
import android.text.Spanned;
import android.text.TextUtils;
import android.util.TypedValue;
import android.view.Gravity;
import android.view.HapticFeedbackConstants;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.widget.FrameLayout;
import android.widget.LinearLayout;
import android.widget.ScrollView;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.core.graphics.ColorUtils;
import androidx.recyclerview.widget.RecyclerView;
import org.telegram.PhoneFormat.PhoneFormat;
import org.telegram.messenger.AndroidUtilities;
import org.telegram.messenger.BuildVars;
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.UserConfig;
import org.telegram.messenger.Utilities;
import org.telegram.tgnet.ConnectionsManager;
import org.telegram.tgnet.TLRPC;
import org.telegram.ui.ActionBar.ActionBar;
import org.telegram.ui.ActionBar.BaseFragment;
import org.telegram.ui.ActionBar.Theme;
import org.telegram.ui.ActionBar.ThemeDescription;
import org.telegram.ui.Cells.ShadowSectionCell;
import org.telegram.ui.Cells.TextInfoPrivacyCell;
import org.telegram.ui.Components.AlertsCreator;
import org.telegram.ui.Components.CombinedDrawable;
import org.telegram.ui.Components.CubicBezierInterpolator;
import org.telegram.ui.Components.FillLastLinearLayoutManager;
import org.telegram.ui.Components.LayoutHelper;
import org.telegram.ui.Components.Premium.AboutPremiumView;
import org.telegram.ui.Components.Premium.DoubledLimitsBottomSheet;
import org.telegram.ui.Components.Premium.GLIcon.GLIconRenderer;
import org.telegram.ui.Components.Premium.GLIcon.GLIconTextureView;
import org.telegram.ui.Components.Premium.PremiumButtonView;
import org.telegram.ui.Components.Premium.PremiumFeatureBottomSheet;
import org.telegram.ui.Components.Premium.PremiumGradient;
import org.telegram.ui.Components.Premium.PremiumNotAvailableBottomSheet;
import org.telegram.ui.Components.Premium.StarParticlesView;
import org.telegram.ui.Components.RecyclerListView;
import org.telegram.ui.Components.SimpleThemeDescription;
import org.telegram.ui.Components.TextStyleSpan;
import org.telegram.ui.Components.URLSpanBotCommand;
import org.telegram.ui.Components.URLSpanBrowser;
import org.telegram.ui.Components.URLSpanMono;
import org.telegram.ui.Components.URLSpanNoUnderline;
import org.telegram.ui.Components.URLSpanReplacement;
import org.telegram.ui.Components.URLSpanUserMention;
import java.text.NumberFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Currency;
import java.util.List;
public class PremiumPreviewFragment extends BaseFragment implements NotificationCenter.NotificationCenterDelegate {
RecyclerListView listView;
ArrayList<PremiumFeatureData> premiumFeatures = new ArrayList<>();
int rowCount;
int paddingRow;
int featuresStartRow;
int featuresEndRow;
int sectionRow;
int helpUsRow;
int statusRow;
int privacyRow;
int lastPaddingRow;
Drawable shadowDrawable;
private FrameLayout buttonContainer;
private View buttonDivider;
PremiumFeatureCell dummyCell;
int totalGradientHeight;
FillLastLinearLayoutManager layoutManager;
//icons
Shader shader;
Matrix matrix = new Matrix();
Paint gradientPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
BackgroundView backgroundView;
StarParticlesView particlesView;
boolean isLandscapeMode;
public final static int PREMIUM_FEATURE_LIMITS = 0;
public final static int PREMIUM_FEATURE_UPLOAD_LIMIT = 1;
public final static int PREMIUM_FEATURE_DOWNLOAD_SPEED = 2;
public final static int PREMIUM_FEATURE_ADS = 3;
public final static int PREMIUM_FEATURE_REACTIONS = 4;
public final static int PREMIUM_FEATURE_STICKERS = 5;
public final static int PREMIUM_FEATURE_PROFILE_BADGE = 6;
public final static int PREMIUM_FEATURE_ANIMATED_AVATARS = 7;
public final static int PREMIUM_FEATURE_VOICE_TO_TEXT = 8;
public final static int PREMIUM_FEATURE_ADVANCED_CHAT_MANAGEMENT = 9;
public final static int PREMIUM_FEATURE_APPLICATION_ICONS = 10;
private int statusBarHeight;
private int firstViewHeight;
private boolean isDialogVisible;
boolean inc;
float progress;
private int currentYOffset;
private FrameLayout contentView;
private PremiumButtonView premiumButtonView;
float totalProgress;
private String source;
final Bitmap gradientTextureBitmap = Bitmap.createBitmap(100, 100, Bitmap.Config.ARGB_8888);
final Canvas gradientCanvas = new Canvas(gradientTextureBitmap);
PremiumGradient.GradientTools gradientTools = new PremiumGradient.GradientTools(Theme.key_premiumGradientBackground1, Theme.key_premiumGradientBackground2, Theme.key_premiumGradientBackground3, Theme.key_premiumGradientBackground4);
private boolean forcePremium;
float progressToFull;
public static int severStringToFeatureType(String s) {
switch (s) {
case "double_limits":
return PREMIUM_FEATURE_LIMITS;
case "more_upload":
return PREMIUM_FEATURE_UPLOAD_LIMIT;
case "faster_download":
return PREMIUM_FEATURE_DOWNLOAD_SPEED;
case "voice_to_text":
return PREMIUM_FEATURE_VOICE_TO_TEXT;
case "no_ads":
return PREMIUM_FEATURE_ADS;
case "unique_reactions":
return PREMIUM_FEATURE_REACTIONS;
case "premium_stickers":
return PREMIUM_FEATURE_STICKERS;
case "advanced_chat_management":
return PREMIUM_FEATURE_ADVANCED_CHAT_MANAGEMENT;
case "profile_badge":
return PREMIUM_FEATURE_PROFILE_BADGE;
case "animated_userpics":
return PREMIUM_FEATURE_ANIMATED_AVATARS;
case "app_icons":
return PREMIUM_FEATURE_APPLICATION_ICONS;
}
return -1;
}
public static String featureTypeToServerString(int type) {
switch (type) {
case PREMIUM_FEATURE_LIMITS:
return "double_limits";
case PREMIUM_FEATURE_UPLOAD_LIMIT:
return "more_upload";
case PREMIUM_FEATURE_DOWNLOAD_SPEED:
return "faster_download";
case PREMIUM_FEATURE_VOICE_TO_TEXT:
return "voice_to_text";
case PREMIUM_FEATURE_ADS:
return "no_ads";
case PREMIUM_FEATURE_REACTIONS:
return "unique_reactions";
case PREMIUM_FEATURE_STICKERS:
return "premium_stickers";
case PREMIUM_FEATURE_ADVANCED_CHAT_MANAGEMENT:
return "advanced_chat_management";
case PREMIUM_FEATURE_PROFILE_BADGE:
return "profile_badge";
case PREMIUM_FEATURE_ANIMATED_AVATARS:
return "animated_userpics";
case PREMIUM_FEATURE_APPLICATION_ICONS:
return "app_icons";
}
return null;
}
public PremiumPreviewFragment setForcePremium() {
this.forcePremium = true;
return this;
}
public PremiumPreviewFragment(String source) {
super();
this.source = source;
}
@SuppressLint("NotifyDataSetChanged")
@Override
public View createView(Context context) {
hasOwnBackground = true;
shader = new LinearGradient(0, 0, 0, 100, new int[]{0xffF38926, 0xffDB5C9D, 0xffA767FF, 0xff55A5FF}, new float[]{0f, 0.32f, 0.5f, 1f}, Shader.TileMode.CLAMP);
shader.setLocalMatrix(matrix);
gradientPaint.setShader(shader);
dummyCell = new PremiumFeatureCell(context);
premiumFeatures.clear();
fillPremiumFeaturesList(premiumFeatures, currentAccount);
Rect padding = new Rect();
shadowDrawable = context.getResources().getDrawable(R.drawable.sheet_shadow_round).mutate();
shadowDrawable.setColorFilter(new PorterDuffColorFilter(getThemedColor(Theme.key_dialogBackground), PorterDuff.Mode.MULTIPLY));
shadowDrawable.getPadding(padding);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
statusBarHeight = AndroidUtilities.isTablet() ? 0 : AndroidUtilities.statusBarHeight;
}
contentView = new FrameLayout(context) {
int lastSize;
boolean iconInterceptedTouch;
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
float iconX = backgroundView.getX() + backgroundView.imageView.getX();
float iconY = backgroundView.getY() + backgroundView.imageView.getY();
AndroidUtilities.rectTmp.set(iconX, iconY, iconX + backgroundView.imageView.getMeasuredWidth(), iconY + backgroundView.imageView.getMeasuredHeight());
if (AndroidUtilities.rectTmp.contains(ev.getX(), ev.getY()) || iconInterceptedTouch) {
ev.offsetLocation(-iconX, -iconY);
if (ev.getAction() == MotionEvent.ACTION_DOWN || ev.getAction() == MotionEvent.ACTION_MOVE) {
iconInterceptedTouch = true;
} else if (ev.getAction() == MotionEvent.ACTION_UP || ev.getAction() == MotionEvent.ACTION_CANCEL) {
iconInterceptedTouch = false;
}
backgroundView.imageView.dispatchTouchEvent(ev);
return true;
}
return super.dispatchTouchEvent(ev);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
if (MeasureSpec.getSize(widthMeasureSpec) > MeasureSpec.getSize(heightMeasureSpec)) {
isLandscapeMode = true;
} else {
isLandscapeMode = false;
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
statusBarHeight = AndroidUtilities.isTablet() ? 0 : AndroidUtilities.statusBarHeight;
}
backgroundView.measure(widthMeasureSpec, MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED));
particlesView.getLayoutParams().height = backgroundView.getMeasuredHeight();
int buttonHeight = (getUserConfig().isPremium() || forcePremium ? 0 : AndroidUtilities.dp(68));
layoutManager.setAdditionalHeight(buttonHeight + statusBarHeight - AndroidUtilities.dp(16));
layoutManager.setMinimumLastViewHeight(buttonHeight);
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
int size = getMeasuredHeight() + getMeasuredWidth() << 16;
if (lastSize != size) {
updateBackgroundImage();
}
}
@Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
super.onLayout(changed, left, top, right, bottom);
backgroundView.imageView.mRenderer.gradientScaleX = backgroundView.imageView.getMeasuredWidth() / (float) getMeasuredWidth();
backgroundView.imageView.mRenderer.gradientScaleY = backgroundView.imageView.getMeasuredHeight() / (float) getMeasuredHeight();
backgroundView.imageView.mRenderer.gradientStartX = (backgroundView.getX() + backgroundView.imageView.getX()) / getMeasuredWidth();
backgroundView.imageView.mRenderer.gradientStartY = (backgroundView.getY() + backgroundView.imageView.getY()) / getMeasuredHeight();
}
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
measureGradient(w, h);
}
@Override
protected void dispatchDraw(Canvas canvas) {
if (!isDialogVisible) {
if (inc) {
progress += 16f / 1000f;
if (progress > 3) {
inc = false;
}
} else {
progress -= 16f / 1000f;
if (progress < 1) {
inc = true;
}
}
}
View firstView = null;
if (listView.getLayoutManager() != null) {
firstView = listView.getLayoutManager().findViewByPosition(0);
}
currentYOffset = firstView == null ? 0 : firstView.getBottom();
int h = actionBar.getBottom() + AndroidUtilities.dp(16);
totalProgress = (1f - (currentYOffset - h) / (float) (firstViewHeight - h));
totalProgress = Utilities.clamp(totalProgress, 1f, 0f);
int maxTop = actionBar.getBottom() + AndroidUtilities.dp(16);
if (currentYOffset < maxTop) {
currentYOffset = maxTop;
}
float oldProgress = progressToFull;
progressToFull = 0;
if (currentYOffset < maxTop + AndroidUtilities.dp(30)) {
progressToFull = (maxTop + AndroidUtilities.dp(30) - currentYOffset) / (float) AndroidUtilities.dp(30);
}
if (isLandscapeMode) {
progressToFull = 1f;
totalProgress = 1f;
}
if (oldProgress != progressToFull) {
listView.invalidate();
}
float fromTranslation = currentYOffset - (actionBar.getMeasuredHeight() + backgroundView.getMeasuredHeight() - statusBarHeight) + AndroidUtilities.dp(16);
float toTranslation = ((actionBar.getMeasuredHeight() - statusBarHeight - backgroundView.titleView.getMeasuredHeight()) / 2f) + statusBarHeight - backgroundView.getTop() - backgroundView.titleView.getTop();
float translationsY = Math.max(toTranslation, fromTranslation);
float iconTranslationsY = -translationsY / 4f + AndroidUtilities.dp(16);
backgroundView.setTranslationY(translationsY);
backgroundView.imageView.setTranslationY(iconTranslationsY + AndroidUtilities.dp(16));
float s = 0.6f + (1f - totalProgress) * 0.4f;
float alpha = 1f - (totalProgress > 0.5f ? (totalProgress - 0.5f) / 0.5f : 0f);
backgroundView.imageView.setScaleX(s);
backgroundView.imageView.setScaleY(s);
backgroundView.imageView.setAlpha(alpha);
backgroundView.subtitleView.setAlpha(alpha);
particlesView.setAlpha(1f - totalProgress);
particlesView.setTranslationY(-(particlesView.getMeasuredHeight() - backgroundView.imageView.getMeasuredWidth()) / 2f + backgroundView.getY() + backgroundView.imageView.getY());
float toX = AndroidUtilities.dp(72) - backgroundView.titleView.getLeft();
float f = totalProgress > 0.3f ? (totalProgress - 0.3f) / 0.7f : 0f;
backgroundView.titleView.setTranslationX(toX * (1f - CubicBezierInterpolator.EASE_OUT_QUINT.getInterpolation(1 - f)));
backgroundView.imageView.mRenderer.gradientStartX = (backgroundView.getX() + backgroundView.imageView.getX() + getMeasuredWidth() * 0.1f * progress) / getMeasuredWidth();
backgroundView.imageView.mRenderer.gradientStartY = (backgroundView.getY() + backgroundView.imageView.getY()) / getMeasuredHeight();
if (!isDialogVisible) {
invalidate();
}
gradientTools.gradientMatrix(0, 0, getMeasuredWidth(), getMeasuredHeight(), -getMeasuredWidth() * 0.1f * progress, 0);
canvas.drawRect(0, 0, getMeasuredWidth(), currentYOffset + AndroidUtilities.dp(20), gradientTools.paint);
super.dispatchDraw(canvas);
}
@Override
protected boolean drawChild(Canvas canvas, View child, long drawingTime) {
if (child == listView) {
canvas.save();
canvas.clipRect(0, actionBar.getBottom(), getMeasuredWidth(), getMeasuredHeight());
super.drawChild(canvas, child, drawingTime);
canvas.restore();
return true;
}
return super.drawChild(canvas, child, drawingTime);
}
};
contentView.setFitsSystemWindows(true);
listView = new RecyclerListView(context) {
@Override
public void onDraw(Canvas canvas) {
shadowDrawable.setBounds((int) (-padding.left - AndroidUtilities.dp(16) * progressToFull), currentYOffset - padding.top - AndroidUtilities.dp(16), (int) (getMeasuredWidth() + padding.right + AndroidUtilities.dp(16) * progressToFull), getMeasuredHeight());
shadowDrawable.draw(canvas);
super.onDraw(canvas);
}
};
listView.setLayoutManager(layoutManager = new FillLastLinearLayoutManager(context, AndroidUtilities.dp(68) + statusBarHeight - AndroidUtilities.dp(16), listView));
layoutManager.setFixedLastItemHeight();
listView.setAdapter(new Adapter());
listView.addOnScrollListener(new RecyclerView.OnScrollListener() {
@Override
public void onScrollStateChanged(@NonNull RecyclerView recyclerView, int newState) {
super.onScrollStateChanged(recyclerView, newState);
if (newState == RecyclerView.SCROLL_STATE_IDLE) {
int maxTop = actionBar.getBottom() + AndroidUtilities.dp(16);
if (totalProgress > 0.5f) {
listView.smoothScrollBy(0, currentYOffset - maxTop);
} else {
View firstView = null;
if (listView.getLayoutManager() != null) {
firstView = listView.getLayoutManager().findViewByPosition(0);
}
if (firstView != null && firstView.getTop() < 0) {
listView.smoothScrollBy(0, firstView.getTop());
}
}
}
checkButtonDivider();
}
@Override
public void onScrolled(@NonNull RecyclerView recyclerView, int dx, int dy) {
super.onScrolled(recyclerView, dx, dy);
contentView.invalidate();
checkButtonDivider();
}
});
backgroundView = new BackgroundView(context) {
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
return true;
}
};
particlesView = new StarParticlesView(context);
backgroundView.imageView.setStarParticlesView(particlesView);
contentView.addView(particlesView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT));
contentView.addView(backgroundView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT));
listView.setOnItemClickListener((view, position) -> {
if (view instanceof PremiumFeatureCell) {
PremiumFeatureCell cell = (PremiumFeatureCell) view;
PremiumPreviewFragment.sentShowFeaturePreview(currentAccount, cell.data.type);
if (cell.data.type == PREMIUM_FEATURE_LIMITS) {
DoubledLimitsBottomSheet bottomSheet = new DoubledLimitsBottomSheet(PremiumPreviewFragment.this, currentAccount);
bottomSheet.setParentFragment(PremiumPreviewFragment.this);
showDialog(bottomSheet);
} else {
showDialog(new PremiumFeatureBottomSheet(PremiumPreviewFragment.this, cell.data.type, false));
}
}
});
contentView.addView(listView);
premiumButtonView = new PremiumButtonView(context, false);
premiumButtonView.setButton(getPremiumButtonText(currentAccount), v -> {
buyPremium(this);
});
buttonContainer = new FrameLayout(context);
buttonDivider = new View(context);
buttonDivider.setBackgroundColor(Theme.getColor(Theme.key_divider));
buttonContainer.addView(buttonDivider, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 1));
buttonDivider.getLayoutParams().height = 1;
AndroidUtilities.updateViewVisibilityAnimated(buttonDivider, true, 1f, false);
buttonContainer.addView(premiumButtonView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 48, Gravity.CENTER_VERTICAL, 16, 0, 16, 0));
buttonContainer.setBackgroundColor(getThemedColor(Theme.key_dialogBackground));
contentView.addView(buttonContainer, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 68, Gravity.BOTTOM));
fragmentView = contentView;
actionBar.setBackground(null);
actionBar.setCastShadows(false);
actionBar.setBackButtonImage(R.drawable.ic_ab_back);
actionBar.setActionBarMenuOnItemClick(new ActionBar.ActionBarMenuOnItemClick() {
@Override
public void onItemClick(int id) {
if (id == -1) {
finishFragment();
}
}
});
actionBar.setForceSkipTouches(true);
updateColors();
updateRows();
backgroundView.imageView.startEnterAnimation(-180, 200);
if (forcePremium) {
AndroidUtilities.runOnUIThread(() -> getMediaDataController().loadPremiumPromo(false), 400);
}
MediaDataController.getInstance(currentAccount).preloadPremiumPreviewStickers();
sentShowScreenStat(source);
return fragmentView;
}
public static void buyPremium(BaseFragment fragment) {
buyPremium(fragment, "settings");
}
public static void fillPremiumFeaturesList(ArrayList<PremiumFeatureData> premiumFeatures, int currentAccount) {
MessagesController messagesController = MessagesController.getInstance(currentAccount);
premiumFeatures.add(new PremiumFeatureData(PREMIUM_FEATURE_LIMITS, R.drawable.msg_premium_limits, LocaleController.getString("PremiumPreviewLimits", R.string.PremiumPreviewLimits), LocaleController.formatString("PremiumPreviewLimitsDescription", R.string.PremiumPreviewLimitsDescription,
messagesController.channelsLimitPremium, messagesController.dialogFiltersLimitPremium, messagesController.dialogFiltersPinnedLimitPremium, messagesController.publicLinksLimitPremium, 4)));
premiumFeatures.add(new PremiumFeatureData(PREMIUM_FEATURE_UPLOAD_LIMIT, R.drawable.msg_premium_uploads, LocaleController.getString("PremiumPreviewUploads", R.string.PremiumPreviewUploads), LocaleController.getString("PremiumPreviewUploadsDescription", R.string.PremiumPreviewUploadsDescription)));
premiumFeatures.add(new PremiumFeatureData(PREMIUM_FEATURE_DOWNLOAD_SPEED, R.drawable.msg_premium_speed, LocaleController.getString("PremiumPreviewDownloadSpeed", R.string.PremiumPreviewDownloadSpeed), LocaleController.getString("PremiumPreviewDownloadSpeedDescription", R.string.PremiumPreviewDownloadSpeedDescription)));
premiumFeatures.add(new PremiumFeatureData(PREMIUM_FEATURE_VOICE_TO_TEXT, R.drawable.msg_premium_voice, LocaleController.getString("PremiumPreviewVoiceToText", R.string.PremiumPreviewVoiceToText), LocaleController.getString("PremiumPreviewVoiceToTextDescription", R.string.PremiumPreviewVoiceToTextDescription)));
premiumFeatures.add(new PremiumFeatureData(PREMIUM_FEATURE_ADS, R.drawable.msg_premium_ads, LocaleController.getString("PremiumPreviewNoAds", R.string.PremiumPreviewNoAds), LocaleController.getString("PremiumPreviewNoAdsDescription", R.string.PremiumPreviewNoAdsDescription)));
premiumFeatures.add(new PremiumFeatureData(PREMIUM_FEATURE_REACTIONS, R.drawable.msg_premium_reactions, LocaleController.getString("PremiumPreviewReactions", R.string.PremiumPreviewReactions), LocaleController.getString("PremiumPreviewReactionsDescription", R.string.PremiumPreviewReactionsDescription)));
premiumFeatures.add(new PremiumFeatureData(PREMIUM_FEATURE_STICKERS, R.drawable.msg_premium_stickers, LocaleController.getString("PremiumPreviewStickers", R.string.PremiumPreviewStickers), LocaleController.getString("PremiumPreviewStickersDescription", R.string.PremiumPreviewStickersDescription)));
premiumFeatures.add(new PremiumFeatureData(PREMIUM_FEATURE_ADVANCED_CHAT_MANAGEMENT, R.drawable.msg_premium_tools, LocaleController.getString("PremiumPreviewAdvancedChatManagement", R.string.PremiumPreviewAdvancedChatManagement), LocaleController.getString("PremiumPreviewAdvancedChatManagementDescription", R.string.PremiumPreviewAdvancedChatManagementDescription)));
premiumFeatures.add(new PremiumFeatureData(PREMIUM_FEATURE_PROFILE_BADGE, R.drawable.msg_premium_badge, LocaleController.getString("PremiumPreviewProfileBadge", R.string.PremiumPreviewProfileBadge), LocaleController.getString("PremiumPreviewProfileBadgeDescription", R.string.PremiumPreviewProfileBadgeDescription)));
premiumFeatures.add(new PremiumFeatureData(PREMIUM_FEATURE_ANIMATED_AVATARS, R.drawable.msg_premium_avatar, LocaleController.getString("PremiumPreviewAnimatedProfiles", R.string.PremiumPreviewAnimatedProfiles), LocaleController.getString("PremiumPreviewAnimatedProfilesDescription", R.string.PremiumPreviewAnimatedProfilesDescription)));
premiumFeatures.add(new PremiumFeatureData(PREMIUM_FEATURE_APPLICATION_ICONS, R.drawable.msg_premium_icons, LocaleController.getString("PremiumPreviewAppIcon", R.string.PremiumPreviewAppIcon), LocaleController.getString("PremiumPreviewAppIconDescription", R.string.PremiumPreviewAppIconDescription)));
if (messagesController.premiumFeaturesTypesToPosition.size() > 0) {
for (int i = 0; i < premiumFeatures.size(); i++) {
if (messagesController.premiumFeaturesTypesToPosition.get(premiumFeatures.get(i).type, -1) == -1) {
premiumFeatures.remove(i);
i--;
}
}
}
Collections.sort(premiumFeatures, (o1, o2) -> {
int type1 = messagesController.premiumFeaturesTypesToPosition.get(o1.type, Integer.MAX_VALUE);
int type2 = messagesController.premiumFeaturesTypesToPosition.get(o2.type, Integer.MAX_VALUE);
return type1 - type2;
});
}
private void updateBackgroundImage() {
if (contentView.getMeasuredWidth() == 0 || contentView.getMeasuredHeight() == 0) {
return;
}
gradientTools.gradientMatrix(0, 0, contentView.getMeasuredWidth(), contentView.getMeasuredHeight(), 0, 0);
gradientCanvas.save();
gradientCanvas.scale(100f / contentView.getMeasuredWidth(), 100f / contentView.getMeasuredHeight());
gradientCanvas.drawRect(0, 0, contentView.getMeasuredWidth(), contentView.getMeasuredHeight(), gradientTools.paint);
gradientCanvas.restore();
backgroundView.imageView.setBackgroundBitmap(gradientTextureBitmap);
}
private void checkButtonDivider() {
AndroidUtilities.updateViewVisibilityAnimated(buttonDivider, listView.canScrollVertically(1), 1f, true);
}
public static void buyPremium(BaseFragment fragment, String source) {
if (BuildVars.IS_BILLING_UNAVAILABLE) {
fragment.showDialog(new PremiumNotAvailableBottomSheet(fragment));
return;
}
// NekoX: remove Google billing
}
public static String getPremiumButtonText(int currentAccount) {
return LocaleController.getString(R.string.SubscribeToPremiumNotAvailable);
// NekoX: remove Google billing
}
private void measureGradient(int w, int h) {
int yOffset = 0;
for (int i = 0; i < premiumFeatures.size(); i++) {
dummyCell.setData(premiumFeatures.get(i), false);
dummyCell.measure(View.MeasureSpec.makeMeasureSpec(w, View.MeasureSpec.EXACTLY), View.MeasureSpec.makeMeasureSpec(h, View.MeasureSpec.AT_MOST));
premiumFeatures.get(i).yOffset = yOffset;
yOffset += dummyCell.getMeasuredHeight();
}
totalGradientHeight = yOffset;
}
private void updateRows() {
rowCount = 0;
sectionRow = -1;
statusRow = -1;
privacyRow = -1;
paddingRow = rowCount++;
featuresStartRow = rowCount;
rowCount += premiumFeatures.size();
featuresEndRow = rowCount;
statusRow = rowCount++;
lastPaddingRow = rowCount++;
if (getUserConfig().isPremium() || forcePremium) {
buttonContainer.setVisibility(View.GONE);
} else {
buttonContainer.setVisibility(View.VISIBLE);
}
int buttonHeight = buttonContainer.getVisibility() == View.VISIBLE ? AndroidUtilities.dp(64) : 0;
layoutManager.setAdditionalHeight(buttonHeight + statusBarHeight - AndroidUtilities.dp(16));
layoutManager.setMinimumLastViewHeight(buttonHeight);
}
@Override
public boolean isSwipeBackEnabled(MotionEvent event) {
return true;
}
@Override
public boolean onFragmentCreate() {
if (getMessagesController().premiumLocked) {
return false;
}
NotificationCenter.getGlobalInstance().addObserver(this, NotificationCenter.billingProductDetailsUpdated);
NotificationCenter.getGlobalInstance().addObserver(this, NotificationCenter.currentUserPremiumStatusChanged);
getNotificationCenter().addObserver(this, NotificationCenter.premiumPromoUpdated);
return super.onFragmentCreate();
}
@Override
public void onFragmentDestroy() {
super.onFragmentDestroy();
NotificationCenter.getGlobalInstance().removeObserver(this, NotificationCenter.billingProductDetailsUpdated);
NotificationCenter.getGlobalInstance().removeObserver(this, NotificationCenter.currentUserPremiumStatusChanged);
getNotificationCenter().removeObserver(this, NotificationCenter.premiumPromoUpdated);
}
@SuppressLint("NotifyDataSetChanged")
@Override
public void didReceivedNotification(int id, int account, Object... args) {
if (id == NotificationCenter.billingProductDetailsUpdated || id == NotificationCenter.premiumPromoUpdated) {
premiumButtonView.buttonTextView.setText(getPremiumButtonText(currentAccount));
}
if (id == NotificationCenter.currentUserPremiumStatusChanged || id == NotificationCenter.premiumPromoUpdated) {
backgroundView.updateText();
updateRows();
listView.getAdapter().notifyDataSetChanged();
}
}
private class Adapter extends RecyclerListView.SelectionAdapter {
private final static int TYPE_PADDING = 0,
TYPE_FEATURE = 1,
TYPE_SHADOW_SECTION = 2,
TYPE_BUTTON = 3,
TYPE_HELP_US = 4,
TYPE_STATUS_TEXT = 5,
TYPE_BOTTOM_PADDING = 6;
@NonNull
@Override
public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View view;
Context context = parent.getContext();
switch (viewType) {
default:
case TYPE_PADDING:
view = new View(context) {
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
if (isLandscapeMode) {
firstViewHeight = statusBarHeight + actionBar.getMeasuredHeight() - AndroidUtilities.dp(16);
} else {
int h = AndroidUtilities.dp(300) + statusBarHeight;
if (backgroundView.getMeasuredHeight() + AndroidUtilities.dp(24) > h) {
h = backgroundView.getMeasuredHeight() + AndroidUtilities.dp(24);
}
firstViewHeight = h;
}
super.onMeasure(widthMeasureSpec, MeasureSpec.makeMeasureSpec(firstViewHeight, MeasureSpec.EXACTLY));
}
};
break;
case TYPE_STATUS_TEXT:
view = new TextInfoPrivacyCell(context);
break;
case TYPE_FEATURE:
view = new PremiumFeatureCell(context) {
@Override
protected void dispatchDraw(Canvas canvas) {
AndroidUtilities.rectTmp.set(imageView.getLeft(), imageView.getTop(), imageView.getRight(), imageView.getBottom());
matrix.reset();
matrix.postScale(1f, totalGradientHeight / 100f, 0, 0);
matrix.postTranslate(0, -data.yOffset);
shader.setLocalMatrix(matrix);
canvas.drawRoundRect(AndroidUtilities.rectTmp, AndroidUtilities.dp(8), AndroidUtilities.dp(8), gradientPaint);
super.dispatchDraw(canvas);
}
};
break;
case TYPE_SHADOW_SECTION:
ShadowSectionCell shadowSectionCell = new ShadowSectionCell(context, 12, Theme.getColor(Theme.key_windowBackgroundGray));
Drawable shadowDrawable = Theme.getThemedDrawable(context, R.drawable.greydivider_bottom, Theme.getColor(Theme.key_windowBackgroundGrayShadow));
Drawable background = new ColorDrawable(Theme.getColor(Theme.key_windowBackgroundGray));
CombinedDrawable combinedDrawable = new CombinedDrawable(background, shadowDrawable, 0, 0);
combinedDrawable.setFullsize(true);
shadowSectionCell.setBackgroundDrawable(combinedDrawable);
view = shadowSectionCell;
break;
case TYPE_HELP_US:
view = new AboutPremiumView(context);
break;
case TYPE_BOTTOM_PADDING:
view = new View(context);
view.setBackgroundColor(Theme.getColor(Theme.key_windowBackgroundGray));
break;
}
view.setLayoutParams(new RecyclerView.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT));
return new RecyclerListView.Holder(view);
}
@Override
public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position) {
if (position >= featuresStartRow && position < featuresEndRow) {
((PremiumFeatureCell) holder.itemView).setData(premiumFeatures.get(position - featuresStartRow), position != featuresEndRow - 1);
} else if (position == statusRow || position == privacyRow) {
TextInfoPrivacyCell privacyCell = (TextInfoPrivacyCell) holder.itemView;
Drawable shadowDrawable = Theme.getThemedDrawable(privacyCell.getContext(), R.drawable.greydivider, Theme.getColor(Theme.key_windowBackgroundGrayShadow));
Drawable background = new ColorDrawable(Theme.getColor(Theme.key_windowBackgroundGray));
CombinedDrawable combinedDrawable = new CombinedDrawable(background, shadowDrawable, 0, 0);
combinedDrawable.setFullsize(true);
privacyCell.setBackground(combinedDrawable);
if (position == statusRow) {
TLRPC.TL_help_premiumPromo premiumPromo = getMediaDataController().getPremiumPromo();
if (premiumPromo == null) {
return;
}
SpannableString spannableString = new SpannableString(premiumPromo.status_text);
MediaDataController.addTextStyleRuns(premiumPromo.status_entities, premiumPromo.status_text, spannableString);
byte t = 0;
for (TextStyleSpan span : spannableString.getSpans(0, spannableString.length(), TextStyleSpan.class)) {
TextStyleSpan.TextStyleRun run = span.getTextStyleRun();
boolean setRun = false;
String url = run.urlEntity != null ? TextUtils.substring(premiumPromo.status_text, run.urlEntity.offset, run.urlEntity.offset + run.urlEntity.length) : null;
if (run.urlEntity instanceof TLRPC.TL_messageEntityBotCommand) {
spannableString.setSpan(new URLSpanBotCommand(url, t, run), run.start, run.end, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
} else if (run.urlEntity instanceof TLRPC.TL_messageEntityHashtag || run.urlEntity instanceof TLRPC.TL_messageEntityMention || run.urlEntity instanceof TLRPC.TL_messageEntityCashtag) {
spannableString.setSpan(new URLSpanNoUnderline(url, run), run.start, run.end, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
} else if (run.urlEntity instanceof TLRPC.TL_messageEntityEmail) {
spannableString.setSpan(new URLSpanReplacement("mailto:" + url, run), run.start, run.end, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
} else if (run.urlEntity instanceof TLRPC.TL_messageEntityUrl) {
String lowerCase = url.toLowerCase();
if (!lowerCase.contains("://")) {
spannableString.setSpan(new URLSpanBrowser("http://" + url, run), run.start, run.end, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
} else {
spannableString.setSpan(new URLSpanBrowser(url, run), run.start, run.end, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
}
} else if (run.urlEntity instanceof TLRPC.TL_messageEntityBankCard) {
spannableString.setSpan(new URLSpanNoUnderline("card:" + url, run), run.start, run.end, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
} else if (run.urlEntity instanceof TLRPC.TL_messageEntityPhone) {
String tel = PhoneFormat.stripExceptNumbers(url);
if (url.startsWith("+")) {
tel = "+" + tel;
}
spannableString.setSpan(new URLSpanBrowser("tel:" + tel, run), run.start, run.end, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
} else if (run.urlEntity instanceof TLRPC.TL_messageEntityTextUrl) {
URLSpanReplacement spanReplacement = new URLSpanReplacement(run.urlEntity.url, run);
spanReplacement.setNavigateToPremiumBot(true);
spannableString.setSpan(spanReplacement, run.start, run.end, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
} else if (run.urlEntity instanceof TLRPC.TL_messageEntityMentionName) {
spannableString.setSpan(new URLSpanUserMention("" + ((TLRPC.TL_messageEntityMentionName) run.urlEntity).user_id, t, run), run.start, run.end, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
} else if (run.urlEntity instanceof TLRPC.TL_inputMessageEntityMentionName) {
spannableString.setSpan(new URLSpanUserMention("" + ((TLRPC.TL_inputMessageEntityMentionName) run.urlEntity).user_id.user_id, t, run), run.start, run.end, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
} else if ((run.flags & TextStyleSpan.FLAG_STYLE_MONO) != 0) {
spannableString.setSpan(new URLSpanMono(spannableString, run.start, run.end, t, run), run.start, run.end, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
} else {
setRun = true;
spannableString.setSpan(new TextStyleSpan(run), run.start, run.end, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
}
if (!setRun && (run.flags & TextStyleSpan.FLAG_STYLE_SPOILER) != 0) {
spannableString.setSpan(new TextStyleSpan(run), run.start, run.end, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
}
}
privacyCell.setText(spannableString);
}
}
}
@Override
public int getItemCount() {
return rowCount;
}
@Override
public int getItemViewType(int position) {
if (position == paddingRow) {
return TYPE_PADDING;
} else if (position >= featuresStartRow && position < featuresEndRow) {
return TYPE_FEATURE;
} else if (position == sectionRow) {
return TYPE_SHADOW_SECTION;
} else if (position == helpUsRow) {
return TYPE_HELP_US;
} else if (position == statusRow || position == privacyRow) {
return TYPE_STATUS_TEXT;
} else if (position == lastPaddingRow) {
return TYPE_BOTTOM_PADDING;
}
return TYPE_PADDING;
}
@Override
public boolean isEnabled(RecyclerView.ViewHolder holder) {
return holder.getItemViewType() == TYPE_FEATURE;
}
}
public static class PremiumFeatureData {
public final int type;
public final int icon;
public final String title;
public final String description;
public int yOffset;
public PremiumFeatureData(int type, int icon, String title, String description) {
this.type = type;
this.icon = icon;
this.title = title;
this.description = description;
}
}
FrameLayout settingsView;
private class BackgroundView extends LinearLayout {
TextView titleView;
private final TextView subtitleView;
private final GLIconTextureView imageView;
public BackgroundView(Context context) {
super(context);
setOrientation(VERTICAL);
imageView = new GLIconTextureView(context, GLIconRenderer.FRAGMENT_STYLE) {
@Override
public void onLongPress() {
super.onLongPress();
if (settingsView != null && !BuildVars.DEBUG_PRIVATE_VERSION) {
return;
}
settingsView = new FrameLayout(context);
ScrollView scrollView = new ScrollView(context);
LinearLayout linearLayout = new GLIconSettingsView(context, imageView.mRenderer);
scrollView.addView(linearLayout);
settingsView.addView(scrollView);
settingsView.setBackgroundColor(Theme.getColor(Theme.key_dialogBackground));
contentView.addView(settingsView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, Gravity.BOTTOM));
((MarginLayoutParams) settingsView.getLayoutParams()).topMargin = currentYOffset;
settingsView.setTranslationY(AndroidUtilities.dp(1000));
settingsView.animate().translationY(1).setDuration(300);
}
};
addView(imageView, LayoutHelper.createLinear(190, 190, Gravity.CENTER_HORIZONTAL));
titleView = new TextView(context);
titleView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 22);
titleView.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf"));
titleView.setGravity(Gravity.CENTER_HORIZONTAL);
addView(titleView, LayoutHelper.createLinear(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, 0, Gravity.CENTER_HORIZONTAL, 16, 20, 16, 0));
subtitleView = new TextView(context);
subtitleView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14);
subtitleView.setLineSpacing(AndroidUtilities.dp(2), 1f);
subtitleView.setGravity(Gravity.CENTER_HORIZONTAL);
addView(subtitleView, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, 0, 0, 16, 7, 16, 0));
updateText();
}
public void updateText() {
titleView.setText(LocaleController.getString(forcePremium ? R.string.TelegramPremiumSubscribedTitle : R.string.TelegramPremium));
subtitleView.setText(AndroidUtilities.replaceTags(LocaleController.getString(getUserConfig().isPremium() || forcePremium ? R.string.TelegramPremiumSubscribedSubtitle : R.string.TelegramPremiumSubtitle)));
}
}
@Override
public boolean isLightStatusBar() {
return false;
}
@Override
public void onResume() {
super.onResume();
backgroundView.imageView.setPaused(false);
backgroundView.imageView.setDialogVisible(false);
particlesView.setPaused(false);
}
@Override
public void onPause() {
super.onPause();
backgroundView.imageView.setDialogVisible(true);
particlesView.setPaused(true);
}
@Override
public boolean canBeginSlide() {
return !backgroundView.imageView.touched;
}
@Override
public ArrayList<ThemeDescription> getThemeDescriptions() {
return SimpleThemeDescription.createThemeDescriptions(this::updateColors,
Theme.key_premiumGradient1, Theme.key_premiumGradient2, Theme.key_premiumGradient3, Theme.key_premiumGradient4,
Theme.key_premiumGradientBackground1, Theme.key_premiumGradientBackground2, Theme.key_premiumGradientBackground3, Theme.key_premiumGradientBackground4,
Theme.key_premiumGradientBackgroundOverlay, Theme.key_premiumStartGradient1, Theme.key_premiumStartGradient2, Theme.key_premiumStartSmallStarsColor, Theme.key_premiumStartSmallStarsColor2
);
}
private void updateColors() {
if (backgroundView == null || actionBar == null) {
return;
}
actionBar.setItemsColor(Theme.getColor(Theme.key_premiumGradientBackgroundOverlay), false);
actionBar.setItemsBackgroundColor(ColorUtils.setAlphaComponent(Theme.getColor(Theme.key_premiumGradientBackgroundOverlay), 60), false);
backgroundView.titleView.setTextColor(Theme.getColor(Theme.key_premiumGradientBackgroundOverlay));
backgroundView.subtitleView.setTextColor(Theme.getColor(Theme.key_premiumGradientBackgroundOverlay));
particlesView.drawable.updateColors();
if (backgroundView.imageView.mRenderer != null) {
backgroundView.imageView.mRenderer.updateColors();
}
updateBackgroundImage();
}
@Override
public boolean onBackPressed() {
if (settingsView != null) {
closeSetting();
return false;
}
return super.onBackPressed();
}
private void closeSetting() {
settingsView.animate().translationY(AndroidUtilities.dp(1000)).setListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
contentView.removeView(settingsView);
settingsView = null;
super.onAnimationEnd(animation);
}
});
}
@Override
public Dialog showDialog(Dialog dialog) {
Dialog d = super.showDialog(dialog);
updateDialogVisibility(d != null);
return d;
}
@Override
protected void onDialogDismiss(Dialog dialog) {
super.onDialogDismiss(dialog);
updateDialogVisibility(false);
}
private void updateDialogVisibility(boolean isVisible) {
if (isVisible != isDialogVisible) {
isDialogVisible = isVisible;
backgroundView.imageView.setDialogVisible(isVisible);
particlesView.setPaused(isVisible);
contentView.invalidate();
}
}
private void sentShowScreenStat() {
if (source == null) {
return;
}
sentShowScreenStat(source);
source = null;
}
public static void sentShowScreenStat(String source) {
ConnectionsManager connectionsManager = ConnectionsManager.getInstance(UserConfig.selectedAccount);
TLRPC.TL_help_saveAppLog req = new TLRPC.TL_help_saveAppLog();
TLRPC.TL_inputAppEvent event = new TLRPC.TL_inputAppEvent();
event.time = connectionsManager.getCurrentTime();
event.type = "premium.promo_screen_show";
TLRPC.TL_jsonObject data = new TLRPC.TL_jsonObject();
event.data = data;
TLRPC.TL_jsonObjectValue sourceObj = new TLRPC.TL_jsonObjectValue();
TLRPC.TL_jsonString jsonString = new TLRPC.TL_jsonString();
jsonString.value = source;
sourceObj.key = "source";
sourceObj.value = jsonString;
data.value.add(sourceObj);
req.events.add(event);
connectionsManager.sendRequest(req, (response, error) -> {
});
}
public static void sentPremiumButtonClick() {
TLRPC.TL_help_saveAppLog req = new TLRPC.TL_help_saveAppLog();
TLRPC.TL_inputAppEvent event = new TLRPC.TL_inputAppEvent();
event.time = ConnectionsManager.getInstance(UserConfig.selectedAccount).getCurrentTime();
event.type = "premium.promo_screen_accept";
event.data = new TLRPC.TL_jsonNull();
req.events.add(event);
ConnectionsManager.getInstance(UserConfig.selectedAccount).sendRequest(req, (response, error) -> {
});
}
public static void sentPremiumBuyCanceled() {
TLRPC.TL_help_saveAppLog req = new TLRPC.TL_help_saveAppLog();
TLRPC.TL_inputAppEvent event = new TLRPC.TL_inputAppEvent();
event.time = ConnectionsManager.getInstance(UserConfig.selectedAccount).getCurrentTime();
event.type = "premium.promo_screen_fail";
event.data = new TLRPC.TL_jsonNull();
req.events.add(event);
ConnectionsManager.getInstance(UserConfig.selectedAccount).sendRequest(req, (response, error) -> {
});
}
public static void sentShowFeaturePreview(int currentAccount, int type) {
TLRPC.TL_help_saveAppLog req = new TLRPC.TL_help_saveAppLog();
TLRPC.TL_inputAppEvent event = new TLRPC.TL_inputAppEvent();
event.time = ConnectionsManager.getInstance(currentAccount).getCurrentTime();
event.type = "premium.promo_screen_tap";
TLRPC.TL_jsonObject data = new TLRPC.TL_jsonObject();
event.data = data;
TLRPC.TL_jsonObjectValue item = new TLRPC.TL_jsonObjectValue();
TLRPC.TL_jsonString jsonString = new TLRPC.TL_jsonString();
jsonString.value = PremiumPreviewFragment.featureTypeToServerString(type);
item.key = "item";
item.value = jsonString;
data.value.add(item);
req.events.add(event);
event.data = data;
ConnectionsManager.getInstance(currentAccount).sendRequest(req, (response, error) -> {
});
}
}