NekoX/TMessagesProj/src/main/java/org/telegram/ui/Cells/ThemesHorizontalListCell.java

906 lines
42 KiB
Java

package org.telegram.ui.Cells;
import android.animation.ArgbEvaluator;
import android.animation.ObjectAnimator;
import android.app.Activity;
import android.content.Context;
import android.content.SharedPreferences;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.BitmapShader;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffColorFilter;
import android.graphics.RectF;
import android.graphics.Shader;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.GradientDrawable;
import android.net.Uri;
import android.os.Build;
import android.os.SystemClock;
import android.text.TextPaint;
import android.text.TextUtils;
import android.view.Gravity;
import android.view.HapticFeedbackConstants;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.view.accessibility.AccessibilityNodeInfo;
import android.widget.Button;
import android.widget.FrameLayout;
import org.telegram.messenger.AndroidUtilities;
import org.telegram.messenger.ApplicationLoader;
import org.telegram.messenger.FileLoader;
import org.telegram.messenger.FileLog;
import org.telegram.messenger.LocaleController;
import org.telegram.messenger.NotificationCenter;
import org.telegram.messenger.R;
import org.telegram.messenger.SharedConfig;
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.BaseFragment;
import org.telegram.ui.ActionBar.EmojiThemes;
import org.telegram.ui.ActionBar.Theme;
import org.telegram.ui.Components.LayoutHelper;
import org.telegram.ui.Components.MotionBackgroundDrawable;
import org.telegram.ui.Components.RadioButton;
import org.telegram.ui.Components.RecyclerListView;
import org.telegram.ui.ThemeActivity;
import org.telegram.ui.ThemeSetUrlActivity;
import java.io.File;
import java.io.FileInputStream;
import java.util.ArrayList;
import java.util.HashMap;
import androidx.annotation.Keep;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import tw.nekomimi.nkmr.NekomuraConfig;
public class ThemesHorizontalListCell extends RecyclerListView implements NotificationCenter.NotificationCenterDelegate {
public static byte[] bytes = new byte[1024];
private boolean drawDivider;
private LinearLayoutManager horizontalLayoutManager;
private HashMap<String, Theme.ThemeInfo> loadingThemes = new HashMap<>();
private HashMap<Theme.ThemeInfo, String> loadingWallpapers = new HashMap<>();
private Theme.ThemeInfo prevThemeInfo;
private ThemesListAdapter adapter;
private ArrayList<Theme.ThemeInfo> customThemes;
private ArrayList<Theme.ThemeInfo> defaultThemes;
private int currentType;
private int prevCount;
private class ThemesListAdapter extends RecyclerListView.SelectionAdapter {
private Context mContext;
ThemesListAdapter(Context context) {
mContext = context;
}
@Override
public boolean isEnabled(RecyclerView.ViewHolder holder) {
return false;
}
@Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
return new RecyclerListView.Holder(new InnerThemeView(mContext));
}
@Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
InnerThemeView view = (InnerThemeView) holder.itemView;
ArrayList<Theme.ThemeInfo> arrayList;
int p = position;
if (position < defaultThemes.size()) {
arrayList = defaultThemes;
} else {
arrayList = customThemes;
p -= defaultThemes.size();
}
view.setTheme(arrayList.get(p), position == getItemCount() - 1, position == 0);
}
@Override
public int getItemCount() {
return prevCount = defaultThemes.size() + customThemes.size();
}
}
private class InnerThemeView extends FrameLayout {
private RadioButton button;
private Theme.ThemeInfo themeInfo;
private RectF rect = new RectF();
private Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
private Drawable optionsDrawable;
private TextPaint textPaint = new TextPaint(Paint.ANTI_ALIAS_FLAG);
private Drawable inDrawable;
private Drawable outDrawable;
private boolean isLast;
private boolean isFirst;
private float placeholderAlpha;
private int inColor;
private int outColor;
private int backColor;
private int checkColor;
private int accentId;
private int oldInColor;
private int oldOutColor;
private int oldBackColor;
private int oldCheckColor;
private boolean accentColorChanged;
private ObjectAnimator accentAnimator;
private float accentState;
private final ArgbEvaluator evaluator = new ArgbEvaluator();
private Drawable backgroundDrawable;
private Paint bitmapPaint = new Paint(Paint.ANTI_ALIAS_FLAG | Paint.FILTER_BITMAP_FLAG);
private BitmapShader bitmapShader;
private boolean hasWhiteBackground;
private Matrix shaderMatrix = new Matrix();
private Drawable loadingDrawable;
private int loadingColor;
private long lastDrawTime;
private boolean pressed;
public InnerThemeView(Context context) {
super(context);
setWillNotDraw(false);
inDrawable = context.getResources().getDrawable(R.drawable.minibubble_in).mutate();
outDrawable = context.getResources().getDrawable(R.drawable.minibubble_out).mutate();
textPaint.setTextSize(AndroidUtilities.dp(13));
button = new RadioButton(context);
button.setSize(AndroidUtilities.dp(20));
addView(button, LayoutHelper.createFrame(22, 22, Gravity.LEFT | Gravity.TOP, 27, 75, 0, 0));
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(MeasureSpec.makeMeasureSpec(AndroidUtilities.dp(76 + (isLast ? 22 : 15) + (isFirst ? 22 : 0)), MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec(AndroidUtilities.dp(148), MeasureSpec.EXACTLY));
}
@Override
public boolean onTouchEvent(MotionEvent event) {
if (optionsDrawable == null || themeInfo == null || themeInfo.info != null && !themeInfo.themeLoaded || currentType != ThemeActivity.THEME_TYPE_BASIC) {
return super.onTouchEvent(event);
}
int action = event.getAction();
if (action == MotionEvent.ACTION_DOWN || action == MotionEvent.ACTION_UP) {
float x = event.getX();
float y = event.getY();
if (x > rect.centerX() && y < rect.centerY() - AndroidUtilities.dp(10)) {
if (action == MotionEvent.ACTION_DOWN) {
pressed = true;
} else {
if (!NekomuraConfig.disableVibration.Bool()) {
performHapticFeedback(HapticFeedbackConstants.KEYBOARD_TAP);
}
showOptionsForTheme(themeInfo);
}
}
if (action == MotionEvent.ACTION_UP) {
pressed = false;
}
}
return pressed;
}
private boolean parseTheme() {
if (themeInfo == null || themeInfo.pathToFile == null) {
return false;
}
boolean finished = false;
File file = new File(themeInfo.pathToFile);
try (FileInputStream stream = new FileInputStream(file)) {
int currentPosition = 0;
int idx;
int read;
int linesRead = 0;
while ((read = stream.read(bytes)) != -1) {
int previousPosition = currentPosition;
int start = 0;
for (int a = 0; a < read; a++) {
if (bytes[a] == '\n') {
linesRead++;
int len = a - start + 1;
String line = new String(bytes, start, len - 1, "UTF-8");
if (line.startsWith("WLS=")) {
String wallpaperLink = line.substring(4);
Uri uri = Uri.parse(wallpaperLink);
themeInfo.slug = uri.getQueryParameter("slug");
themeInfo.pathToWallpaper = new File(ApplicationLoader.getFilesDirFixed(), Utilities.MD5(wallpaperLink) + ".wp").getAbsolutePath();
String mode = uri.getQueryParameter("mode");
if (mode != null) {
mode = mode.toLowerCase();
String[] modes = mode.split(" ");
if (modes != null && modes.length > 0) {
for (int b = 0; b < modes.length; b++) {
if ("blur".equals(modes[b])) {
themeInfo.isBlured = true;
break;
}
}
}
}
String pattern = uri.getQueryParameter("pattern");
if (!TextUtils.isEmpty(pattern)) {
try {
String bgColor = uri.getQueryParameter("bg_color");
if (!TextUtils.isEmpty(bgColor)) {
themeInfo.patternBgColor = Integer.parseInt(bgColor.substring(0, 6), 16) | 0xff000000;
if (bgColor.length() >= 13 && AndroidUtilities.isValidWallChar(bgColor.charAt(6))) {
themeInfo.patternBgGradientColor1 = Integer.parseInt(bgColor.substring(7, 13), 16) | 0xff000000;
}
if (bgColor.length() >= 20 && AndroidUtilities.isValidWallChar(bgColor.charAt(13))) {
themeInfo.patternBgGradientColor2 = Integer.parseInt(bgColor.substring(14, 20), 16) | 0xff000000;
}
if (bgColor.length() == 27 && AndroidUtilities.isValidWallChar(bgColor.charAt(20))) {
themeInfo.patternBgGradientColor3 = Integer.parseInt(bgColor.substring(21), 16) | 0xff000000;
}
}
} catch (Exception ignore) {
}
try {
String rotation = uri.getQueryParameter("rotation");
if (!TextUtils.isEmpty(rotation)) {
themeInfo.patternBgGradientRotation = Utilities.parseInt(rotation);
}
} catch (Exception ignore) {
}
String intensity = uri.getQueryParameter("intensity");
if (!TextUtils.isEmpty(intensity)) {
themeInfo.patternIntensity = Utilities.parseInt(intensity);
}
if (themeInfo.patternIntensity == 0) {
themeInfo.patternIntensity = 50;
}
}
} else if (line.startsWith("WPS")) {
themeInfo.previewWallpaperOffset = currentPosition + len;
finished = true;
break;
} else {
if ((idx = line.indexOf('=')) != -1) {
String key = line.substring(0, idx);
if (key.equals(Theme.key_chat_inBubble) || key.equals(Theme.key_chat_outBubble) || key.equals(Theme.key_chat_wallpaper) || key.equals(Theme.key_chat_wallpaper_gradient_to1) || key.equals(Theme.key_chat_wallpaper_gradient_to2) || key.equals(Theme.key_chat_wallpaper_gradient_to3)) {
String param = line.substring(idx + 1);
int value;
if (param.length() > 0 && param.charAt(0) == '#') {
try {
value = Color.parseColor(param);
} catch (Exception ignore) {
value = Utilities.parseInt(param);
}
} else {
value = Utilities.parseInt(param);
}
switch (key) {
case Theme.key_chat_inBubble:
themeInfo.setPreviewInColor(value);
break;
case Theme.key_chat_outBubble:
themeInfo.setPreviewOutColor(value);
break;
case Theme.key_chat_wallpaper:
themeInfo.setPreviewBackgroundColor(value);
break;
case Theme.key_chat_wallpaper_gradient_to1:
themeInfo.previewBackgroundGradientColor1 = value;
break;
case Theme.key_chat_wallpaper_gradient_to2:
themeInfo.previewBackgroundGradientColor2 = value;
break;
case Theme.key_chat_wallpaper_gradient_to3:
themeInfo.previewBackgroundGradientColor3 = value;
break;
}
}
}
}
start += len;
currentPosition += len;
}
}
if (finished || previousPosition == currentPosition) {
break;
}
stream.getChannel().position(currentPosition);
}
} catch (Throwable e) {
FileLog.e(e);
}
if (themeInfo.pathToWallpaper != null && !themeInfo.badWallpaper) {
file = new File(themeInfo.pathToWallpaper);
if (!file.exists()) {
if (!loadingWallpapers.containsKey(themeInfo)) {
loadingWallpapers.put(themeInfo, themeInfo.slug);
TLRPC.TL_account_getWallPaper req = new TLRPC.TL_account_getWallPaper();
TLRPC.TL_inputWallPaperSlug inputWallPaperSlug = new TLRPC.TL_inputWallPaperSlug();
inputWallPaperSlug.slug = themeInfo.slug;
req.wallpaper = inputWallPaperSlug;
ConnectionsManager.getInstance(themeInfo.account).sendRequest(req, (response, error) -> AndroidUtilities.runOnUIThread(() -> {
if (response instanceof TLRPC.TL_wallPaper) {
TLRPC.WallPaper wallPaper = (TLRPC.WallPaper) response;
String name = FileLoader.getAttachFileName(wallPaper.document);
if (!loadingThemes.containsKey(name)) {
loadingThemes.put(name, themeInfo);
FileLoader.getInstance(themeInfo.account).loadFile(wallPaper.document, wallPaper, 1, 1);
}
} else {
themeInfo.badWallpaper = true;
}
}));
}
return false;
}
}
themeInfo.previewParsed = true;
return true;
}
private void applyTheme() {
inDrawable.setColorFilter(new PorterDuffColorFilter(themeInfo.getPreviewInColor(), PorterDuff.Mode.SRC_IN));
outDrawable.setColorFilter(new PorterDuffColorFilter(themeInfo.getPreviewOutColor(), PorterDuff.Mode.SRC_IN));
if (themeInfo.pathToFile == null) {
updateColors(false);
optionsDrawable = null;
} else {
optionsDrawable = getResources().getDrawable(R.drawable.preview_dots).mutate();
oldBackColor = backColor = themeInfo.getPreviewBackgroundColor();
}
bitmapShader = null;
backgroundDrawable = null;
double[] hsv = null;
if (themeInfo.previewBackgroundGradientColor1 != 0 && themeInfo.previewBackgroundGradientColor2 != 0) {
final MotionBackgroundDrawable drawable = new MotionBackgroundDrawable(themeInfo.getPreviewBackgroundColor(), themeInfo.previewBackgroundGradientColor1, themeInfo.previewBackgroundGradientColor2, themeInfo.previewBackgroundGradientColor3, true);
drawable.setRoundRadius(AndroidUtilities.dp(6));
backgroundDrawable = drawable;
hsv = AndroidUtilities.rgbToHsv(Color.red(themeInfo.getPreviewBackgroundColor()), Color.green(themeInfo.getPreviewBackgroundColor()), Color.blue(themeInfo.getPreviewBackgroundColor()));
} else if (themeInfo.previewBackgroundGradientColor1 != 0) {
final GradientDrawable drawable = new GradientDrawable(GradientDrawable.Orientation.BL_TR, new int[]{themeInfo.getPreviewBackgroundColor(), themeInfo.previewBackgroundGradientColor1});
drawable.setCornerRadius(AndroidUtilities.dp(6));
backgroundDrawable = drawable;
hsv = AndroidUtilities.rgbToHsv(Color.red(themeInfo.getPreviewBackgroundColor()), Color.green(themeInfo.getPreviewBackgroundColor()), Color.blue(themeInfo.getPreviewBackgroundColor()));
} else if (themeInfo.previewWallpaperOffset > 0 || themeInfo.pathToWallpaper != null) {
Bitmap wallpaper = AndroidUtilities.getScaledBitmap(AndroidUtilities.dp(76), AndroidUtilities.dp(97), themeInfo.pathToWallpaper, themeInfo.pathToFile, themeInfo.previewWallpaperOffset);
if (wallpaper != null) {
backgroundDrawable = new BitmapDrawable(wallpaper);
bitmapShader = new BitmapShader(wallpaper, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP);
bitmapPaint.setShader(bitmapShader);
int[] colors = AndroidUtilities.calcDrawableColor(backgroundDrawable);
hsv = AndroidUtilities.rgbToHsv(Color.red(colors[0]), Color.green(colors[0]), Color.blue(colors[0]));
}
} else if (themeInfo.getPreviewBackgroundColor() != 0) {
hsv = AndroidUtilities.rgbToHsv(Color.red(themeInfo.getPreviewBackgroundColor()), Color.green(themeInfo.getPreviewBackgroundColor()), Color.blue(themeInfo.getPreviewBackgroundColor()));
}
if (hsv != null && hsv[1] <= 0.1f && hsv[2] >= 0.96f) {
hasWhiteBackground = true;
} else {
hasWhiteBackground = false;
}
if (themeInfo.getPreviewBackgroundColor() == 0 && themeInfo.previewParsed && backgroundDrawable == null) {
backgroundDrawable = Theme.createDefaultWallpaper(100, 200);
if (backgroundDrawable instanceof MotionBackgroundDrawable) {
((MotionBackgroundDrawable) backgroundDrawable).setRoundRadius(AndroidUtilities.dp(6));
}
}
invalidate();
}
public void setTheme(Theme.ThemeInfo theme, boolean last, boolean first) {
themeInfo = theme;
isFirst = first;
isLast = last;
accentId = theme.currentAccentId;
FrameLayout.LayoutParams layoutParams = (FrameLayout.LayoutParams) button.getLayoutParams();
layoutParams.leftMargin = AndroidUtilities.dp(isFirst ? 22 + 27 : 27);
button.setLayoutParams(layoutParams);
placeholderAlpha = 0.0f;
if (themeInfo.pathToFile != null && !themeInfo.previewParsed) {
themeInfo.setPreviewInColor(Theme.getDefaultColor(Theme.key_chat_inBubble));
themeInfo.setPreviewOutColor(Theme.getDefaultColor(Theme.key_chat_outBubble));
File file = new File(themeInfo.pathToFile);
boolean fileExists = file.exists();
boolean parsed = fileExists && parseTheme();
if ((!parsed || !fileExists) && themeInfo.info != null) {
if (themeInfo.info.document != null) {
themeInfo.themeLoaded = false;
placeholderAlpha = 1.0f;
loadingDrawable = getResources().getDrawable(R.drawable.baseline_palette_24).mutate();
Theme.setDrawableColor(loadingDrawable, loadingColor = Theme.getColor(Theme.key_windowBackgroundWhiteGrayText7));
if (!fileExists) {
String name = FileLoader.getAttachFileName(themeInfo.info.document);
if (!loadingThemes.containsKey(name)) {
loadingThemes.put(name, themeInfo);
FileLoader.getInstance(themeInfo.account).loadFile(themeInfo.info.document, themeInfo.info, 1, 1);
}
}
} else {
loadingDrawable = getResources().getDrawable(R.drawable.preview_custom).mutate();
Theme.setDrawableColor(loadingDrawable, loadingColor = Theme.getColor(Theme.key_windowBackgroundWhiteGrayText7));
}
}
}
applyTheme();
}
@Override
protected void onAttachedToWindow() {
super.onAttachedToWindow();
Theme.ThemeInfo t = currentType == ThemeActivity.THEME_TYPE_NIGHT ? Theme.getCurrentNightTheme() : Theme.getCurrentTheme();
button.setChecked(themeInfo == t, false);
if (themeInfo != null && themeInfo.info != null && !themeInfo.themeLoaded) {
String name = FileLoader.getAttachFileName(themeInfo.info.document);
if (!loadingThemes.containsKey(name) && !loadingWallpapers.containsKey(themeInfo)) {
themeInfo.themeLoaded = true;
placeholderAlpha = 0.0f;
parseTheme();
applyTheme();
}
}
}
public void updateCurrentThemeCheck() {
Theme.ThemeInfo t = currentType == ThemeActivity.THEME_TYPE_NIGHT ? Theme.getCurrentNightTheme() : Theme.getCurrentTheme();
button.setChecked(themeInfo == t, true);
}
void updateColors(boolean animate) {
oldInColor = inColor;
oldOutColor = outColor;
oldBackColor = backColor;
oldCheckColor = checkColor;
Theme.ThemeAccent accent = themeInfo.getAccent(false);
int accentColor;
int myAccentColor;
int backAccent;
if (accent != null) {
accentColor = accent.accentColor;
myAccentColor = accent.myMessagesAccentColor != 0 ? accent.myMessagesAccentColor : accentColor;
int backgroundOverrideColor = (int) accent.backgroundOverrideColor;
backAccent = backgroundOverrideColor != 0 ? backgroundOverrideColor : accentColor;
} else {
accentColor = 0;
myAccentColor = 0;
backAccent = 0;
}
inColor = Theme.changeColorAccent(themeInfo, accentColor, themeInfo.getPreviewInColor());
outColor = Theme.changeColorAccent(themeInfo, myAccentColor, themeInfo.getPreviewOutColor());
backColor = Theme.changeColorAccent(themeInfo, backAccent, themeInfo.getPreviewBackgroundColor());
checkColor = outColor;
accentId = themeInfo.currentAccentId;
if (accentAnimator != null) {
accentAnimator.cancel();
}
if (animate) {
accentAnimator = ObjectAnimator.ofFloat(this, "accentState", 0f, 1f);
accentAnimator.setDuration(200);
accentAnimator.start();
} else {
setAccentState(1f);
}
}
@Keep
public float getAccentState() {
return accentState;
}
@Keep
public void setAccentState(float state) {
accentState = state;
accentColorChanged = true;
invalidate();
}
@Override
protected void onDraw(Canvas canvas) {
if (accentId != themeInfo.currentAccentId) {
updateColors(true);
}
int x = isFirst ? AndroidUtilities.dp(22) : 0;
int y = AndroidUtilities.dp(11);
rect.set(x, y, x + AndroidUtilities.dp(76), y + AndroidUtilities.dp(97));
String name = getThemeName();
int maxWidth = getMeasuredWidth() - AndroidUtilities.dp(isFirst ? 10 : 15) - (isLast ? AndroidUtilities.dp(7) : 0);
String text = TextUtils.ellipsize(name, textPaint, maxWidth, TextUtils.TruncateAt.END).toString();
int width = (int) Math.ceil(textPaint.measureText(text));
textPaint.setColor(Theme.getColor(Theme.key_windowBackgroundWhiteBlackText));
canvas.drawText(text, x + (AndroidUtilities.dp(76) - width) / 2, AndroidUtilities.dp(131), textPaint);
boolean drawContent = themeInfo.info == null || themeInfo.info.document != null && themeInfo.themeLoaded;
if (drawContent) {
paint.setColor(blend(oldBackColor, backColor));
if (accentColorChanged) {
inDrawable.setColorFilter(new PorterDuffColorFilter(blend(oldInColor, inColor), PorterDuff.Mode.SRC_IN));
outDrawable.setColorFilter(new PorterDuffColorFilter(blend(oldOutColor, outColor), PorterDuff.Mode.SRC_IN));
accentColorChanged = false;
}
if (backgroundDrawable != null) {
if (bitmapShader != null) {
BitmapDrawable bitmapDrawable = (BitmapDrawable) backgroundDrawable;
float bitmapW = bitmapDrawable.getBitmap().getWidth();
float bitmapH = bitmapDrawable.getBitmap().getHeight();
float scaleW = bitmapW / rect.width();
float scaleH = bitmapH / rect.height();
shaderMatrix.reset();
float scale = 1.0f / Math.min(scaleW, scaleH);
if (bitmapW / scaleH > rect.width()) {
bitmapW /= scaleH;
shaderMatrix.setTranslate(x - (bitmapW - rect.width()) / 2, y);
} else {
bitmapH /= scaleW;
shaderMatrix.setTranslate(x, y - (bitmapH - rect.height()) / 2);
}
shaderMatrix.preScale(scale, scale);
bitmapShader.setLocalMatrix(shaderMatrix);
canvas.drawRoundRect(rect, AndroidUtilities.dp(6), AndroidUtilities.dp(6), bitmapPaint);
} else {
backgroundDrawable.setBounds((int) rect.left, (int) rect.top, (int) rect.right, (int) rect.bottom);
backgroundDrawable.draw(canvas);
}
} else {
canvas.drawRoundRect(rect, AndroidUtilities.dp(6), AndroidUtilities.dp(6), paint);
}
button.setColor(0x66ffffff, 0xffffffff);
if (themeInfo.accentBaseColor != 0) {
if ("Day".equals(themeInfo.name) || "Arctic Blue".equals(themeInfo.name)) {
button.setColor(0xffb3b3b3, blend(oldCheckColor, checkColor));
Theme.chat_instantViewRectPaint.setColor(0x2bb0b5ba);
canvas.drawRoundRect(rect, AndroidUtilities.dp(6), AndroidUtilities.dp(6), Theme.chat_instantViewRectPaint);
}
} else if (hasWhiteBackground) {
button.setColor(0xffb3b3b3, themeInfo.getPreviewOutColor());
Theme.chat_instantViewRectPaint.setColor(0x2bb0b5ba);
canvas.drawRoundRect(rect, AndroidUtilities.dp(6), AndroidUtilities.dp(6), Theme.chat_instantViewRectPaint);
}
inDrawable.setBounds(x + AndroidUtilities.dp(6), AndroidUtilities.dp(22), x + AndroidUtilities.dp(6 + 43), AndroidUtilities.dp(22 + 14));
inDrawable.draw(canvas);
outDrawable.setBounds(x + AndroidUtilities.dp(27), AndroidUtilities.dp(41), x + AndroidUtilities.dp(27 + 43), AndroidUtilities.dp(41 + 14));
outDrawable.draw(canvas);
if (optionsDrawable != null && currentType == ThemeActivity.THEME_TYPE_BASIC) {
x = (int) rect.right - AndroidUtilities.dp(16);
y = (int) rect.top + AndroidUtilities.dp(6);
optionsDrawable.setBounds(x, y, x + optionsDrawable.getIntrinsicWidth(), y + optionsDrawable.getIntrinsicHeight());
optionsDrawable.draw(canvas);
}
}
if (themeInfo.info != null && themeInfo.info.document == null) {
button.setAlpha(0.0f);
Theme.chat_instantViewRectPaint.setColor(0x2bb0b5ba);
canvas.drawRoundRect(rect, AndroidUtilities.dp(6), AndroidUtilities.dp(6), Theme.chat_instantViewRectPaint);
if (loadingDrawable != null) {
int newColor = Theme.getColor(Theme.key_windowBackgroundWhiteGrayText7);
if (loadingColor != newColor) {
Theme.setDrawableColor(loadingDrawable, loadingColor = newColor);
}
x = (int) (rect.centerX() - loadingDrawable.getIntrinsicWidth() / 2);
y = (int) (rect.centerY() - loadingDrawable.getIntrinsicHeight() / 2);
loadingDrawable.setBounds(x, y, x + loadingDrawable.getIntrinsicWidth(), y + loadingDrawable.getIntrinsicHeight());
loadingDrawable.draw(canvas);
}
} else if (themeInfo.info != null && !themeInfo.themeLoaded || placeholderAlpha > 0.0f) {
button.setAlpha(1.0f - placeholderAlpha);
paint.setColor(Theme.getColor(Theme.key_windowBackgroundGray));
paint.setAlpha((int) (placeholderAlpha * 255));
canvas.drawRoundRect(rect, AndroidUtilities.dp(6), AndroidUtilities.dp(6), paint);
if (loadingDrawable != null) {
int newColor = Theme.getColor(Theme.key_windowBackgroundWhiteGrayText7);
if (loadingColor != newColor) {
Theme.setDrawableColor(loadingDrawable, loadingColor = newColor);
}
x = (int) (rect.centerX() - loadingDrawable.getIntrinsicWidth() / 2);
y = (int) (rect.centerY() - loadingDrawable.getIntrinsicHeight() / 2);
loadingDrawable.setAlpha((int) (placeholderAlpha * 255));
loadingDrawable.setBounds(x, y, x + loadingDrawable.getIntrinsicWidth(), y + loadingDrawable.getIntrinsicHeight());
loadingDrawable.draw(canvas);
}
if (themeInfo.themeLoaded) {
long newTime = SystemClock.elapsedRealtime();
long dt = Math.min(17, newTime - lastDrawTime);
lastDrawTime = newTime;
placeholderAlpha -= dt / 180.0f;
if (placeholderAlpha < 0.0f) {
placeholderAlpha = 0.0f;
}
invalidate();
}
} else if (button.getAlpha() != 1.0f) {
button.setAlpha(1.0f);
}
}
private String getThemeName() {
String name = themeInfo.getName();
if (name.toLowerCase().endsWith(".attheme")) {
name = name.substring(0, name.lastIndexOf('.'));
}
return name;
}
private int blend(int color1, int color2) {
if (accentState == 1.0f) {
return color2;
} else {
return (int) evaluator.evaluate(accentState, color1, color2);
}
}
@Override
public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
super.onInitializeAccessibilityNodeInfo(info);
info.setText(getThemeName());
info.setClassName(Button.class.getName());
info.setChecked(button.isChecked());
info.setCheckable(true);
info.setEnabled(true);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
info.addAction(AccessibilityNodeInfo.AccessibilityAction.ACTION_CLICK);
info.addAction(new AccessibilityNodeInfo.AccessibilityAction(AccessibilityNodeInfo.ACTION_LONG_CLICK, LocaleController.getString("AccDescrMoreOptions", R.string.AccDescrMoreOptions)));
}
}
}
public ThemesHorizontalListCell(Context context, int type, ArrayList<Theme.ThemeInfo> def, ArrayList<Theme.ThemeInfo> custom) {
super(context);
customThemes = custom;
defaultThemes = def;
currentType = type;
if (type == ThemeActivity.THEME_TYPE_OTHER) {
setBackgroundColor(Theme.getColor(Theme.key_dialogBackground));
} else {
setBackgroundColor(Theme.getColor(Theme.key_windowBackgroundWhite));
}
setItemAnimator(null);
setLayoutAnimation(null);
horizontalLayoutManager = new LinearLayoutManager(context) {
@Override
public boolean supportsPredictiveItemAnimations() {
return false;
}
};
setPadding(0, 0, 0, 0);
setClipToPadding(false);
horizontalLayoutManager.setOrientation(LinearLayoutManager.HORIZONTAL);
setLayoutManager(horizontalLayoutManager);
setAdapter(adapter = new ThemesListAdapter(context));
setOnItemClickListener((view1, position) -> {
selectTheme(((InnerThemeView) view1).themeInfo);
int left = view1.getLeft();
int right = view1.getRight();
if (left < 0) {
smoothScrollBy(left - AndroidUtilities.dp(8), 0);
} else if (right > getMeasuredWidth()) {
smoothScrollBy(right - getMeasuredWidth(), 0);
}
});
setOnItemLongClickListener((view12, position) -> {
InnerThemeView innerThemeView = (InnerThemeView) view12;
showOptionsForTheme(innerThemeView.themeInfo);
return true;
});
}
public void selectTheme(Theme.ThemeInfo themeInfo) {
if (themeInfo.info != null) {
if (!themeInfo.themeLoaded) {
return;
}
if (themeInfo.info.document == null) {
presentFragment(new ThemeSetUrlActivity(themeInfo, null, true));
return;
}
}
if (!TextUtils.isEmpty(themeInfo.assetName)) {
Theme.PatternsLoader.createLoader(false);
}
SharedPreferences.Editor editor = ApplicationLoader.applicationContext.getSharedPreferences("themeconfig", Activity.MODE_PRIVATE).edit();
editor.putString(currentType == ThemeActivity.THEME_TYPE_NIGHT || themeInfo.isDark() ? "lastDarkTheme" : "lastDayTheme", themeInfo.getKey());
editor.apply();
if (currentType == ThemeActivity.THEME_TYPE_NIGHT) {
if (themeInfo == Theme.getCurrentNightTheme()) {
return;
}
Theme.setCurrentNightTheme(themeInfo);
} else {
if (themeInfo == Theme.getCurrentTheme()) {
return;
}
NotificationCenter.getGlobalInstance().postNotificationName(NotificationCenter.needSetDayNightTheme, themeInfo, false, null, -1);
}
updateRows();
int count = getChildCount();
for (int a = 0; a < count; a++) {
View child = getChildAt(a);
if (child instanceof InnerThemeView) {
((InnerThemeView) child).updateCurrentThemeCheck();
}
}
EmojiThemes.saveCustomTheme(themeInfo, themeInfo.currentAccentId);
}
public void setDrawDivider(boolean draw) {
drawDivider = draw;
}
public void notifyDataSetChanged(int width) {
if (prevCount == adapter.getItemCount()) {
return;
}
adapter.notifyDataSetChanged();
Theme.ThemeInfo t = currentType == ThemeActivity.THEME_TYPE_NIGHT ? Theme.getCurrentNightTheme() : Theme.getCurrentTheme();
if (prevThemeInfo != t) {
scrollToCurrentTheme(width, false);
}
}
@Override
public boolean onInterceptTouchEvent(MotionEvent e) {
if (getParent() != null && getParent().getParent() != null) {
getParent().getParent().requestDisallowInterceptTouchEvent(canScrollHorizontally(-1));
}
return super.onInterceptTouchEvent(e);
}
@Override
public void onDraw(Canvas canvas) {
super.onDraw(canvas);
if (drawDivider) {
canvas.drawLine(0, getMeasuredHeight() - 1, getMeasuredWidth(), getMeasuredHeight() - 1, Theme.dividerPaint);
}
}
@Override
public void setBackgroundColor(int color) {
super.setBackgroundColor(color);
invalidateViews();
}
@Override
protected void onAttachedToWindow() {
super.onAttachedToWindow();
for (int a : SharedConfig.activeAccounts) {
NotificationCenter.getInstance(a).addObserver(this, NotificationCenter.fileLoaded);
NotificationCenter.getInstance(a).addObserver(this, NotificationCenter.fileLoadFailed);
}
}
@Override
protected void onDetachedFromWindow() {
super.onDetachedFromWindow();
for (int a : SharedConfig.activeAccounts) {
NotificationCenter.getInstance(a).removeObserver(this, NotificationCenter.fileLoaded);
NotificationCenter.getInstance(a).removeObserver(this, NotificationCenter.fileLoadFailed);
}
}
@Override
public void didReceivedNotification(int id, int account, Object... args) {
if (id == NotificationCenter.fileLoaded) {
String fileName = (String) args[0];
File file = (File) args[1];
Theme.ThemeInfo info = loadingThemes.get(fileName);
if (info != null) {
loadingThemes.remove(fileName);
if (loadingWallpapers.remove(info) != null) {
Utilities.globalQueue.postRunnable(() -> {
info.badWallpaper = !info.createBackground(file, info.pathToWallpaper);
AndroidUtilities.runOnUIThread(() -> checkVisibleTheme(info));
});
} else {
checkVisibleTheme(info);
}
}
} else if (id == NotificationCenter.fileLoadFailed) {
String fileName = (String) args[0];
loadingThemes.remove(fileName);
}
}
private void checkVisibleTheme(Theme.ThemeInfo info) {
int count = getChildCount();
for (int a = 0; a < count; a++) {
View child = getChildAt(a);
if (child instanceof InnerThemeView) {
InnerThemeView view = (InnerThemeView) child;
if (view.themeInfo == info) {
if (view.parseTheme()) {
view.themeInfo.themeLoaded = true;
view.applyTheme();
}
}
}
}
}
public void scrollToCurrentTheme(int width, boolean animated) {
if (width == 0) {
View parent = (View) getParent();
if (parent != null) {
width = parent.getMeasuredWidth();
}
}
if (width == 0) {
return;
}
prevThemeInfo = currentType == ThemeActivity.THEME_TYPE_NIGHT ? Theme.getCurrentNightTheme() : Theme.getCurrentTheme();
int index = defaultThemes.indexOf(prevThemeInfo);
if (index < 0) {
index = customThemes.indexOf(prevThemeInfo) + defaultThemes.size();
if (index < 0) {
return;
}
}
if (animated) {
smoothScrollToPosition(index);
} else {
horizontalLayoutManager.scrollToPositionWithOffset(index, (width - AndroidUtilities.dp(76)) / 2);
}
}
protected void showOptionsForTheme(Theme.ThemeInfo themeInfo) {
}
protected void presentFragment(BaseFragment fragment) {
}
protected void updateRows() {
}
}