revert attribute hooks for monet

This commit is contained in:
Vologhat
2023-02-19 16:48:20 +03:00
parent 9264e7f5df
commit 9fd01db880
19 changed files with 419 additions and 63 deletions
@@ -152,6 +152,39 @@ public class ThemesCore {
themedColors.put(R.attr.im_bubble_outgoing_highlighted, accentColor);
}
@SuppressLint("NonConstantResourceId")
public static int getThemedAttr(Context context, @IdRes int attr) {
return switch (attr) {
case R.attr.im_bubble_wallpaper_outgoing, R.attr.im_bubble_outgoing -> outgoinging_msg;
case R.attr.im_bubble_outgoing_highlighted -> outgoinging_msg_highlight;
case R.attr.newsfeed_post_title_color -> darken_color;
default -> themedColors.get(attr);
};
}
public static boolean hasThemedAttr(Context context, int attrID) {
// try {
// Log.d(TAG, "Requesting color by attr " + context.getResources().getResourceName(attrID));
// } catch (Exception e) {
// }
if (isCachedAccents()) {
if (ThemesUtils.isDarkTheme()) {
return (themedColors.get(attrID) != 0 && ACCENT_THEME_ONLY_DARK.get(attrID, true) && (
ThemesUtils.isMilkshake() ?
ACCENT_THEME_ONLY_MILK_DARK.get(attrID, true) :
ACCENT_THEME_ONLY_NOMILK_DARK.get(attrID, true)));
} else {
return (themedColors.get(attrID) != 0 && ACCENT_THEME_ONLY_LIGHT.get(attrID, true) && (
ThemesUtils.isMilkshake() ?
ACCENT_THEME_ONLY_MILK_LIGHT.get(attrID, true) :
ACCENT_THEME_ONLY_NOMILK_LIGHT.get(attrID, true)));
}
} else {
return themedColors.get(attrID) != 0;
}
}
public static void clear() {
cachedAccents = false;
themedColors.clear();
@@ -0,0 +1,54 @@
package ru.vtosters.lite.themes;
import android.content.Context;
import android.graphics.drawable.*;
import android.os.Build;
import android.view.View;
import android.widget.TextView;
import androidx.annotation.ColorRes;
import androidx.annotation.NonNull;
import com.vtosters.lite.R;
import ru.vtosters.lite.themes.utils.RecolorUtils;
import ru.vtosters.lite.utils.ThemesUtils;
public class ThemesHacks {
// Фиксит селектор (все/свои/архив) в профиле
public static void fixProfileSelector(View view) {
if (!ThemesUtils.isMilkshake()) return;
var id = view.getId();
if (id == R.id.profile_wall_owner_posts || id == R.id.profile_wall_all_posts || id == R.id.profile_wall_archived_posts) {
StateListDrawable states = (StateListDrawable) ((LayerDrawable) view.getBackground()).getDrawable(0);
LayerDrawable selected = (LayerDrawable) ((DrawableContainer.DrawableContainerState) states.getConstantState()).getChildren()[0];
((ColorDrawable) selected.getDrawable(0)).setColor(ThemesUtils.getAccentColor());
}
}
public static void fixThemedFeed(TextView textView, int i) {
if (i != R.layout.themed_feed_tab_2) {
return;
}
textView.setTextColor(RecolorUtils.recolorCSL(textView.getTextColors()));
((InsetDrawable) ((DrawableContainer.DrawableContainerState) textView.getBackground().getConstantState()).getChildren()[0]).getDrawable().setTint(ThemesUtils.lighten(ThemesUtils.getAccentColor(), 0.15f));
}
public static void fixDropdown(Drawable drawable) {
if (!ThemesUtils.isDarkTheme() && ThemesUtils.isMilkshake() && ThemesCore.isCachedAccents()) {
StateListDrawable stateListDrawable = (StateListDrawable) drawable;
((DrawableContainer.DrawableContainerState) stateListDrawable.getConstantState()).getChildren()[0].setTint(ThemesUtils.getAccentColor());
((DrawableContainer.DrawableContainerState) stateListDrawable.getConstantState()).getChildren()[1].setTint(ThemesUtils.halfAlpha(ThemesUtils.getAccentColor()));
}
}
public static int getHackedColor(@NonNull Context context, @ColorRes int color) {
if (ThemesCore.isCachedAccents() && ColorReferences.isAccentedColor(context.getResources().getColor(color))) {
return ThemesUtils.getAccentColor();
}
if (ThemesCore.isCachedAccents() && ColorReferences.isMutedAccentedColor(context.getResources().getColor(color))) {
return ThemesUtils.getMutedAccentColor();
}
return Build.VERSION.SDK_INT > 23 ? context.getColor(color) : context.getResources().getColor(color);
}
}
@@ -0,0 +1,92 @@
package ru.vtosters.lite.themes;
import android.content.Context;
import android.content.res.Resources;
import android.content.res.TypedArray;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.util.Log;
import android.util.TypedValue;
import androidx.annotation.Nullable;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.List;
import ru.vtosters.lite.utils.ThemesUtils;
public class VTLResources extends Resources {
private static final String TAG = "VTLResources";
private final Context context;
private static Field typedArrayField;
private static final List<Integer> attributesToTheme = new ArrayList<>();
static {
try {
typedArrayField = TypedArray.class.getDeclaredField("mData");
typedArrayField.setAccessible(true);
} catch (NoSuchFieldException e) {
e.printStackTrace();
}
attributesToTheme.add(16843041);
attributesToTheme.add(android.R.attr.backgroundTint);
attributesToTheme.add(16843173);
}
public VTLResources(Context context, Resources parent) {
super(parent.getAssets(), parent.getDisplayMetrics(), parent.getConfiguration());
this.context = context;
// Log.d(TAG, "VTLResources: init");
}
@Override
public TypedArray obtainAttributes(AttributeSet set, int[] attrs) {
var typedArray = super.obtainAttributes(set, attrs);
var data = getArrayData(typedArray);
for (int i = 0; i < attrs.length; i++) {
try {
int attrID = attrs[i];
if (attributesToTheme.contains(attrID)) {
int type = data[i*6];
int cnt = data[(i*6)+1];
if (type == TypedValue.TYPE_ATTRIBUTE && isAttrThemeable(cnt)) {
data[i*6] = TypedValue.TYPE_INT_COLOR_RGB8;
data[(i*6)+1] = ThemesUtils.getAccentColor();
data[(i*6)+2] = 0; // clear reference content
}
}
} catch (Exception e) {
Log.e(TAG, "TAVzlom failed! (obtainAttributes)");
e.printStackTrace();
}
}
return typedArray;
}
@Override
public Drawable getDrawable(int id, @Nullable Theme theme) throws NotFoundException {
var drawable = super.getDrawable(id, theme);
if (id == com.vtosters.lite.R.drawable.newsfeed_tab_dropdown_16) {
ThemesHacks.fixDropdown(drawable);
}
return drawable;
}
private static boolean isAttrThemeable(int attrID) {
return !ThemesUtils.isDarkTheme() && attrID == com.vtosters.lite.R.attr.button_primary_background;
}
private static int[] getArrayData(TypedArray arr) {
try {
return (int[]) typedArrayField.get(arr);
} catch (IllegalAccessException e) {
Log.e(TAG, "getArrayData: ", e);
e.printStackTrace();
return new int[0];
}
}
}
@@ -12,6 +12,18 @@ import ru.vtosters.lite.utils.AndroidUtils;
import ru.vtosters.lite.utils.ThemesUtils;
public class RecolorUtils {
public static Drawable recolorDrawableToolbar(Drawable drawable) {
if (drawable == null) return null;
return new RecoloredDrawable(drawable, ThemesUtils.getHeaderText());
} // Recolor toolbar drawable to accent color
@SuppressLint("UseCompatLoadingForDrawables")
public static Drawable recolorDrawableInt(int drawable) {
@SuppressLint("UseCompatLoadingForDrawables") Drawable res = AndroidUtils.getResources().getDrawable(drawable);
return new RecoloredDrawable(res, ThemesUtils.getAccentColor());
} // Get res drawable via id and coloring to accent
public static int recolorHexColor(int i){
var accented = ColorReferences.isAccentedColor(i);
@@ -19,6 +31,12 @@ public class RecolorUtils {
return (accented || mutedaccented) ? (accented ? ThemesUtils.getAccentColor() : ThemesUtils.getMutedAccentColor()) : i;
}
public static ColorStateList recolorCSL(ColorStateList colorStateList) {
if (colorStateList == null) return null;
return ColorStateList.valueOf(ThemesUtils.getAccentColor());
} // Recolor ColorStateList to accent color
@SuppressLint("UseCompatLoadingForColorStateLists")
public static ColorStateList themeCSL(Context context, int color) {
if (ColorReferences.isColorRefAccented(color)) {
@@ -67,7 +67,7 @@ public class ThemesFragment extends MaterialPreferenceToolbarFragment {
requireActivity().runOnUiThread(() -> showErrorDialog("Ошибка при инвалидации кэша"));
}
});
return false;
return true;
});
var navBarPreference = findPreference("navbar");
@@ -1,17 +1,23 @@
package ru.vtosters.lite.utils;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.res.ColorStateList;
import android.content.res.Resources;
import android.graphics.Color;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffColorFilter;
import android.graphics.drawable.Drawable;
import android.os.Build;
import android.util.Log;
import android.view.View;
import android.view.Window;
import android.webkit.WebView;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.TextView;
import androidx.appcompat.app.AppCompatDelegate;
import androidx.core.content.ContextCompat;
import androidx.core.graphics.ColorUtils;
import com.vk.articles.preload.WebCachePreloader;
import com.vk.core.drawable.RecoloredDrawable;
@@ -21,9 +27,13 @@ import com.vk.core.ui.themes.VKTheme;
import com.vk.core.ui.themes.VKThemeHelper;
import com.vtosters.lite.R;
import com.vtosters.lite.data.ThemeTracker;
import ru.vtosters.lite.deviceinfo.OEMDetector;
import ru.vtosters.lite.hooks.VKUIHook;
import ru.vtosters.lite.themes.ThemesHacks;
import ru.vtosters.lite.ui.wallpapers.WallpapersHooks;
import java.lang.reflect.Field;
import static ru.vtosters.lite.utils.AndroidUtils.*;
import static ru.vtosters.lite.utils.Preferences.*;
@@ -40,6 +50,14 @@ public class ThemesUtils {
return ColorStateList.valueOf(getAccentColor());
}
public static int getSystemModeTheme() {
return AppCompatDelegate.getDefaultNightMode();
}
public static void setSystemModeTheme(int theme) {
AppCompatDelegate.setDefaultNightMode(theme);
}
public static void setTheme(VKTheme theme, Activity activity) {
if (activity == null) {
activity = LifecycleUtils.getCurrentActivity();
@@ -51,6 +69,17 @@ public class ThemesUtils {
WebCachePreloader.e();
} // apply changed theme
public static void setThemeFL(VKTheme theme, Activity activity, float[] fl) {
if (activity == null) {
activity = LifecycleUtils.getCurrentActivity();
}
VKThemeHelper.theme(theme, activity, fl);
ThemeTracker.a();
VKUIHook.isLoaded = false;
new WebView(activity).clearCache(true);
WebCachePreloader.e();
}
public static boolean isDarkTheme() {
return VKThemeHelper.r();
}
@@ -64,17 +93,111 @@ public class ThemesUtils {
}
public static int getAccentColor() {
return getColorFromAttr(R.attr.accent);
var accent = AndroidUtils.getPreferences().getInt("accent_color", getColorFromAttr(R.attr.accent));
return (accent == 0 || !isMilkshake()) || isMonetTheme() ? getColorFromAttr(R.attr.accent) : accent;
} // Color accent
public static int getMutedAccentColor() {
return getMutedColor(getAccentColor());
}
@SuppressLint("DiscouragedPrivateApi")
public static void setCursorColor(EditText view) {
try {
view.setHighlightColor(ThemesUtils.getMutedAccentColor());
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
view.getTextCursorDrawable().setColorFilter(new PorterDuffColorFilter(ThemesUtils.getAccentColor(), PorterDuff.Mode.SRC_IN));
} else if (!OEMDetector.isMIUI()) {
Field field = TextView.class.getDeclaredField("mCursorDrawableRes");
field.setAccessible(true);
int drawableResId = field.getInt(view);
field = TextView.class.getDeclaredField("mEditor");
field.setAccessible(true);
Object editor = field.get(view);
if (editor != null) {
Drawable drawable = ContextCompat.getDrawable(view.getContext(), drawableResId);
drawable.setColorFilter(getAccentColor(), PorterDuff.Mode.SRC_IN);
Drawable[] drawables = {drawable, drawable};
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
field = editor.getClass().getDeclaredField("mCursorDrawable");
} else {
field = editor.getClass().getDeclaredField("mDrawableForCursor");
}
field.setAccessible(true);
field.set(editor, drawables);
}
}
} catch (Exception e) {
Log.e("ThemesUtils", "setCursorColor: ", e);
}
}
@SuppressLint("DiscouragedPrivateApi")
public static void colorHandles(TextView view) {
try {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
PorterDuffColorFilter filter = new PorterDuffColorFilter(ThemesUtils.getAccentColor(), PorterDuff.Mode.SRC_IN);
view.getTextSelectHandle().setColorFilter(filter);
view.getTextSelectHandleRight().setColorFilter(filter);
view.getTextSelectHandleLeft().setColorFilter(filter);
} else if (!OEMDetector.isMIUI()) {
Field editorField = TextView.class.getDeclaredField("mEditor");
if (!editorField.isAccessible()) editorField.setAccessible(true);
Object editor = editorField.get(view);
if (editor != null) {
Class<?> editorClass;
editorClass = editor.getClass();
String[] handleNames = {"mSelectHandleLeft", "mSelectHandleRight", "mSelectHandleCenter"};
String[] resNames = {"mTextSelectHandleLeftRes", "mTextSelectHandleRightRes", "mTextSelectHandleRes"};
for (int i = 0; i < handleNames.length; i++) {
Field handleField = editorClass.getDeclaredField(handleNames[i]);
if (!handleField.isAccessible()) {
handleField.setAccessible(true);
}
Drawable handleDrawable = (Drawable) handleField.get(editor);
if (handleDrawable == null) {
Field resField = TextView.class.getDeclaredField(resNames[i]);
if (!resField.isAccessible()) {
resField.setAccessible(true);
}
int resId = resField.getInt(view);
handleDrawable = view.getResources().getDrawable(resId);
}
if (handleDrawable != null) {
Drawable drawable = handleDrawable.mutate();
drawable.setColorFilter(getAccentColor(), PorterDuff.Mode.SRC_IN);
handleField.set(editor, drawable);
}
}
}
}
} catch (Exception e) {
Log.e("ThemesUtils", "colorHandles: ", e);
}
}
public static int getMutedColor(int color) {
return ColorUtils.blendARGB(color, (isDarkTheme() ? Color.BLACK : Color.WHITE), (isMilkshake() ? 0.5f : isDarkTheme() ? 0.32f : 0.1f));
}
public static void setCustomAccentColor(int newColor, boolean async) {
var editor = AndroidUtils.edit().putInt("accent_color", newColor);
if (async) editor.apply();
else editor.commit();
}
public static int getTextAttr() {
return getColorFromAttr(R.attr.text_primary);
} // Text Primary color
@@ -181,6 +304,10 @@ public class ThemesUtils {
tw.getBackground().setColorFilter(ThemesUtils.getAccentColor(), PorterDuff.Mode.SRC_OVER);
}
public static void recolorBGView(View view) {
view.getBackground().setColorFilter(ThemesUtils.getAccentColor(), PorterDuff.Mode.SRC_OVER);
}
public static int darken(int color, float by) {
float[] hsl = new float[3];
ColorUtils.colorToHSL(color, hsl);
@@ -208,8 +335,8 @@ public class ThemesUtils {
return ColorUtils.setAlphaComponent(src, 169);
}
public static int getColor(int color) {
return Build.VERSION.SDK_INT > 23 ? getGlobalContext().getColor(color) : getGlobalContext().getResources().getColor(color);
public static int getColor(int i) {
return ThemesHacks.getHackedColor(getGlobalContext(), i);
} // Android Support color injector + accent color checker
public static int getAlertStyle() {