This commit is contained in:
aliveoutside
2022-11-22 16:58:09 +03:00
parent fcbf9238cf
commit 47f4c5c911
20 changed files with 834 additions and 16 deletions
@@ -0,0 +1,43 @@
package ru.vtosters.lite.themes;
import android.content.res.ColorStateList;
import android.graphics.Color;
import java.util.Arrays;
import java.util.List;
import ru.vtosters.lite.utils.ThemesUtils;
public class ColorReferences {
public static List<String> accentColors = Arrays.asList(
"5692d7", "528bcc", "7aa0cc", "518bcc", "6296d0", "2f68aa", "638ebf", "5181b8", "71aaeb",
"4774a8", "5baaf4", "4186c8", "add3ff", "4774a8", "718198", "5a9eff", "99a2ad", "74a2d6",
"e9eef3", "dfe3e7", "eff1f3", "5c9ce6", "4986cc", "4680c2", "3f8ae0"
);
public static boolean isAccentedColor(ColorStateList target) {
return target != null && isAccentedColor(target.getDefaultColor());
}
public static boolean isAccentedColor(int target) {
return accentColors.contains(ThemesUtils.hexx(target).toLowerCase());
}
public static boolean isColorRefAccented(int target) {
return target == com.vtosters.lite.R.color.accent_blue || // accent_blue
target == com.vtosters.lite.R.color.blue_gray || // light_blue_gray
target == com.vtosters.lite.R.color.azure_300 ||
target == com.vtosters.lite.R.color.light_blue_old || // light_blue
target == com.vtosters.lite.R.color.blue_200 || // blue_200
target == com.vtosters.lite.R.color.vk_blue_400 || // blue_200
target == com.vtosters.lite.R.color.blue_200_muted; // blue_200_muted
}
public static boolean isCslNeedToBeThemed(ColorStateList csl) {
int unsel = csl.getColorForState(new int[]{-android.R.attr.state_selected}, Color.BLACK);
int sel = csl.getColorForState(new int[]{android.R.attr.state_selected}, Color.BLACK);
boolean isUnselAccent = isAccentedColor(unsel);
boolean isSelAccent = isAccentedColor(sel);
return ThemesCore.isCachedAccents() && (isUnselAccent || isSelAccent);
}
}
@@ -0,0 +1,143 @@
package ru.vtosters.lite.themes;
import android.content.Context;
import android.util.Log;
import android.util.SparseBooleanArray;
import android.util.SparseIntArray;
import androidx.annotation.IdRes;
import ru.vtosters.lite.utils.ThemesUtils;
public class ThemesCore {
private static final String TAG = "ThemesCore";
public static SparseIntArray themedColors = new SparseIntArray();
public static SparseBooleanArray ACCENT_THEME_ONLY_LIGHT = new SparseBooleanArray();
public static SparseBooleanArray ACCENT_THEME_ONLY_NOMILK_LIGHT = new SparseBooleanArray();
public static SparseBooleanArray ACCENT_THEME_ONLY_NOMILK = new SparseBooleanArray();
public static SparseBooleanArray ACCENT_THEME_ONLY_MILK_LIGHT = new SparseBooleanArray();
public static SparseBooleanArray ACCENT_THEME_ONLY_MILK_DARK = new SparseBooleanArray();
private static boolean cachedAccents = false;
private static int wallDarkColor;
private static int wallLightColor;
public static void setExceptions() {
ACCENT_THEME_ONLY_LIGHT.clear();
ACCENT_THEME_ONLY_NOMILK_LIGHT.clear();
ACCENT_THEME_ONLY_NOMILK.clear();
ACCENT_THEME_ONLY_MILK_LIGHT.clear();
ACCENT_THEME_ONLY_MILK_DARK.clear();
ACCENT_THEME_ONLY_LIGHT.put(com.vtosters.lite.R.attr.button_primary_background, false);
ACCENT_THEME_ONLY_LIGHT.put(com.vtosters.lite.R.attr.button_secondary_foreground, false);
ACCENT_THEME_ONLY_LIGHT.put(com.vtosters.lite.R.attr.button_tertiary_foreground, false);
ACCENT_THEME_ONLY_LIGHT.put(com.vtosters.lite.R.attr.button_muted_foreground, false);
ACCENT_THEME_ONLY_LIGHT.put(com.vtosters.lite.R.attr.button_outline_border, false);
ACCENT_THEME_ONLY_LIGHT.put(com.vtosters.lite.R.attr.text_name, false);
ACCENT_THEME_ONLY_LIGHT.put(com.vtosters.lite.R.attr.newsfeed_post_title_color, false);
ACCENT_THEME_ONLY_LIGHT.put(com.vtosters.lite.R.attr.attach_picker_tab_active_background, false);
ACCENT_THEME_ONLY_LIGHT.put(com.vtosters.lite.R.attr.attach_picker_tab_active_text, false);
ACCENT_THEME_ONLY_LIGHT.put(com.vtosters.lite.R.attr.newsfeed_action_color, false);
ACCENT_THEME_ONLY_LIGHT.put(com.vtosters.lite.R.attr.counter_primary_background, false);
ACCENT_THEME_ONLY_LIGHT.put(com.vtosters.lite.R.attr.action_sheet_action_foreground, false);
ACCENT_THEME_ONLY_NOMILK_LIGHT.put(com.vtosters.lite.R.attr.header_background, false);
ACCENT_THEME_ONLY_MILK_LIGHT.put(com.vtosters.lite.R.attr.header_tint, false);
ACCENT_THEME_ONLY_MILK_LIGHT.put(com.vtosters.lite.R.attr.header_tint_alternate, false);
ACCENT_THEME_ONLY_MILK_LIGHT.put(com.vtosters.lite.R.attr.toolbarIconsColor, false);
ACCENT_THEME_ONLY_MILK_LIGHT.put(com.vtosters.lite.R.attr.header_tab_active_indicator, false);
ACCENT_THEME_ONLY_MILK_LIGHT.put(com.vtosters.lite.R.attr.im_dropdown_arrow_tint, false);
ACCENT_THEME_ONLY_NOMILK.put(com.vtosters.lite.R.attr.im_dropdown_icon_color, false);
}
public static void setThemedColors(int accentColor) {
cachedAccents = true;
themedColors.clear();
themedColors.put(com.vtosters.lite.R.attr.text_link, accentColor);
themedColors.put(com.vtosters.lite.R.attr.accent, accentColor);
themedColors.put(com.vtosters.lite.R.attr.newsfeed_dropdown_color, accentColor);
themedColors.put(com.vtosters.lite.R.attr.vk_accent, accentColor);
themedColors.put(com.vtosters.lite.R.attr.accentColor, accentColor);
themedColors.put(com.vtosters.lite.R.attr.text_name, accentColor);
themedColors.put(com.vtosters.lite.R.attr.tabbar_active_icon, accentColor);
//themedColors.put(com.vtosters.lite.R.attr.header_background, accentColor);
themedColors.put(com.vtosters.lite.R.attr.header_tint, accentColor);
themedColors.put(com.vtosters.lite.R.attr.header_tint_alternate, accentColor);
themedColors.put(com.vtosters.lite.R.attr.activity_indicator_tint, accentColor);
themedColors.put(com.vtosters.lite.R.attr.toolbarIconsColor, accentColor);
themedColors.put(com.vtosters.lite.R.attr.button_primary_background, accentColor);
themedColors.put(com.vtosters.lite.R.attr.button_secondary_foreground, accentColor);
themedColors.put(com.vtosters.lite.R.attr.button_tertiary_foreground, accentColor);
themedColors.put(com.vtosters.lite.R.attr.button_outline_border, accentColor);
themedColors.put(com.vtosters.lite.R.attr.button_muted_foreground, accentColor);
themedColors.put(com.vtosters.lite.R.attr.header_tab_active_indicator, accentColor);
themedColors.put(com.vtosters.lite.R.attr.im_dropdown_icon_color, accentColor);
themedColors.put(com.vtosters.lite.R.attr.im_dropdown_arrow_tint, accentColor);
themedColors.put(com.vtosters.lite.R.attr.im_attach_tint, accentColor);
themedColors.put(com.vtosters.lite.R.attr.im_forward_line_tint, accentColor);
themedColors.put(com.vtosters.lite.R.attr.link_alternate, accentColor);
themedColors.put(com.vtosters.lite.R.attr.newsfeed_post_title_color, accentColor);
themedColors.put(com.vtosters.lite.R.attr.attach_picker_tab_active_background, accentColor);
themedColors.put(com.vtosters.lite.R.attr.attach_picker_tab_active_text, accentColor);
themedColors.put(com.vtosters.lite.R.attr.newsfeed_action_color, accentColor);
themedColors.put(com.vtosters.lite.R.attr.counter_primary_background, accentColor);
themedColors.put(com.vtosters.lite.R.attr.action_sheet_action_foreground, accentColor);
// messages
wallDarkColor = ThemesUtils.darken(accentColor, 0.25f);
wallLightColor = ThemesUtils.lighten(accentColor, 0.25f);
//themedColors.put(com.vtosters.lite.R.attr.im_ic_send_msg, accentColor);
themedColors.put(com.vtosters.lite.R.attr.im_bubble_wallpaper_outgoing, accentColor);
themedColors.put(com.vtosters.lite.R.attr.im_bubble_outgoing, accentColor);
themedColors.put(com.vtosters.lite.R.attr.im_bubble_outgoing_highlighted, accentColor);
}
public static int getThemedAttr(Context context, @IdRes int attr) {
if (attr == com.vtosters.lite.R.attr.im_bubble_wallpaper_outgoing || attr == com.vtosters.lite.R.attr.im_bubble_outgoing) {
return (!ThemesUtils.isDarkTheme()) ? wallLightColor : wallDarkColor;
}
if (attr == com.vtosters.lite.R.attr.im_bubble_outgoing_highlighted) {
return (!ThemesUtils.isDarkTheme()) ? ThemesUtils.lighten(wallLightColor, 0.2f) : ThemesUtils.darken(wallDarkColor, 0.2f);
}
return 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_MILK_DARK.get(attrID, true)
&& ACCENT_THEME_ONLY_NOMILK_LIGHT.get(attrID, true));
} else {
return (themedColors.get(attrID) != 0
&& ACCENT_THEME_ONLY_MILK_LIGHT.get(attrID, true)
&& ACCENT_THEME_ONLY_NOMILK_LIGHT.get(attrID, true));
}
} else return themedColors.get(attrID) != 0;
}
public static boolean isCachedAccents() {
return cachedAccents;
}
}
@@ -0,0 +1,61 @@
package ru.vtosters.lite.themes;
import android.content.Context;
import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.DrawableContainer;
import android.graphics.drawable.InsetDrawable;
import android.graphics.drawable.LayerDrawable;
import android.graphics.drawable.StateListDrawable;
import android.os.Build;
import android.util.Log;
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.utils.AndroidUtils;
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(ThemesUtils.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.isColorRefAccented(color)) {
Log.d("ThemesHacks", "getHackedColor: got accent color: " + AndroidUtils.getResources().getResourceName(color));
return ThemesUtils.getAccentColor();
}
if (Build.VERSION.SDK_INT > 23) {
return context.getColor(color);
} else return 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];
}
}
}
@@ -0,0 +1,45 @@
package ru.vtosters.lite.themes;
import android.view.View;
import android.view.ViewGroup;
import java.util.ArrayList;
import ru.vtosters.lite.themes.hooks.BaseHook;
import ru.vtosters.lite.themes.hooks.ButtonHook;
import ru.vtosters.lite.themes.hooks.ImageViewHook;
import ru.vtosters.lite.themes.hooks.ProgressWheelHook;
import ru.vtosters.lite.themes.hooks.TabLayoutHook;
import ru.vtosters.lite.themes.hooks.TextViewHook;
import ru.vtosters.lite.themes.hooks.ToolbarHook;
import ru.vtosters.lite.themes.hooks.VKImageViewHook;
import ru.vtosters.lite.themes.hooks.WaveformViewHook;
public class ViewInjector {
public static ArrayList<BaseHook> hooks = new ArrayList<>();
static {
hooks.add(new ButtonHook());
hooks.add(new ImageViewHook());
hooks.add(new TabLayoutHook());
hooks.add(new TextViewHook());
hooks.add(new ToolbarHook());
hooks.add(new VKImageViewHook());
hooks.add(new WaveformViewHook());
hooks.add(new ProgressWheelHook());
}
public static View inject(View view, int i, boolean z) {
for (BaseHook hook : hooks) {
hook.inject(view, i, z);
}
if (view instanceof ViewGroup) {
var viewGroup = (ViewGroup) view;
for (int i2 = 0; i2 < viewGroup.getChildCount(); i2++) {
inject(viewGroup.getChildAt(i2), i, false);
}
}
return view;
}
}
@@ -0,0 +1,7 @@
package ru.vtosters.lite.themes.hooks;
import android.view.View;
public interface BaseHook {
void inject(View view, int i, boolean z);
}
@@ -0,0 +1,24 @@
package ru.vtosters.lite.themes.hooks;
import android.content.res.ColorStateList;
import android.view.View;
import android.widget.Button;
import ru.vtosters.lite.themes.ColorReferences;
import ru.vtosters.lite.utils.ThemesUtils;
public class ButtonHook implements BaseHook {
@Override
public void inject(View view, int i, boolean z) {
if (view instanceof Button) {
var button = (Button) view;
if (button.getBackgroundTintList() != null && ColorReferences.isAccentedColor(button.getBackgroundTintList())) {
button.setBackgroundTintList(ColorStateList.valueOf(ThemesUtils.getAccentColor()));
}
if (TextViewHook.isPositiveButton(button) || TextViewHook.isVkUiButton(view)) {
button.setBackgroundTintList(ColorStateList.valueOf(ThemesUtils.getAccentColor()));
}
}
}
}
@@ -0,0 +1,24 @@
package ru.vtosters.lite.themes.hooks;
import android.content.res.ColorStateList;
import android.view.View;
import android.widget.ImageView;
import ru.vtosters.lite.themes.ColorReferences;
import ru.vtosters.lite.themes.ThemesCore;
import ru.vtosters.lite.utils.ThemesUtils;
public class ImageViewHook implements BaseHook {
@Override
public void inject(View view, int i, boolean z) {
if (view instanceof ImageView) {
if (ThemesCore.isCachedAccents()) {
var imageView = (ImageView) view;
if (imageView.getImageTintList() == null) return;
if (ColorReferences.isCslNeedToBeThemed(imageView.getImageTintList())) {
imageView.setImageTintList(ColorStateList.valueOf(ThemesUtils.getAccentColor()));
}
}
}
}
}
@@ -0,0 +1,21 @@
package ru.vtosters.lite.themes.hooks;
import android.view.View;
import com.pnikosis.materialishprogress.ProgressWheel;
import ru.vtosters.lite.themes.ThemesCore;
import ru.vtosters.lite.utils.ThemesUtils;
public class ProgressWheelHook implements BaseHook {
@Override
public void inject(View view, int i, boolean z) {
if (view instanceof ProgressWheel) {
if (ThemesCore.isCachedAccents()) {
var progressWheel = (ProgressWheel) view;
progressWheel.setBarColor(ThemesUtils.getAccentColor());
}
}
}
}
@@ -0,0 +1,21 @@
package ru.vtosters.lite.themes.hooks;
import android.content.res.ColorStateList;
import android.view.View;
import com.vk.core.view.VKTabLayout;
import ru.vtosters.lite.utils.ThemesUtils;
public class TabLayoutHook implements BaseHook {
@Override
public void inject(View view, int i, boolean z) {
if (view instanceof VKTabLayout) {
var tabLayout = (VKTabLayout) view;
tabLayout.setSelectedTabIndicatorColor(ThemesUtils.getAccentColor());
tabLayout.setTabRippleColor(ColorStateList.valueOf(ThemesUtils.getAccentColor()));
}
}
}
@@ -0,0 +1,92 @@
package ru.vtosters.lite.themes.hooks;
import android.annotation.SuppressLint;
import android.content.res.ColorStateList;
import android.os.Build;
import android.view.View;
import android.widget.TextView;
import androidx.appcompat.widget.AppCompatCheckedTextView;
import com.vk.core.view.TintTextView;
import com.vk.core.view.links.LinkedTextView;
import com.vtosters.lite.R;
import ru.vtosters.lite.themes.ColorReferences;
import ru.vtosters.lite.themes.ThemesHacks;
import ru.vtosters.lite.themes.utils.VkUiThemer;
import ru.vtosters.lite.utils.ThemesUtils;
public class TextViewHook implements BaseHook {
private static final String TAG = "TextViewHook";
@SuppressLint("RestrictedApi")
@Override
public void inject(View view, int i, boolean z) {
if (view instanceof TextView) {
var textView = (TextView) view;
if (ColorReferences.isAccentedColor(textView.getCurrentTextColor())) {
textView.setTextColor(ThemesUtils.getAccentColor());
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && textView.getCompoundDrawableTintList() != null) {
if (ColorReferences.isAccentedColor(textView.getCompoundDrawableTintList())) {
textView.setCompoundDrawableTintList(ColorStateList.valueOf(ThemesUtils.getAccentColor()));
}
}
if (textView.getLinkTextColors() != null && ColorReferences.isAccentedColor(textView.getLinkTextColors())) {
textView.setLinkTextColor(ThemesUtils.getAccentColor());
}
if (isPositiveButton(textView) || isVkUiButton(textView)) {
view.setBackgroundTintList(ColorStateList.valueOf(ThemesUtils.getAccentColor()));
}
if (view instanceof TintTextView) {
if (eligibleForStartTinting((TintTextView) view)) {
((TintTextView) view).setDrawableStartTint(ThemesUtils.getAccentColor());
}
if (eligibleForTinting(view.getId())) {
((TintTextView) view).setDrawableTint(ThemesUtils.getAccentColor());
}
}
if (view instanceof LinkedTextView) {
((LinkedTextView) view).setLinkTextColor(ThemesUtils.getAccentColor());
}
if (view instanceof AppCompatCheckedTextView) {
var check = (AppCompatCheckedTextView) view;
if (ColorReferences.isAccentedColor(check.getCheckMarkTintList())) {
check.setCheckMarkTintList(ColorStateList.valueOf(ThemesUtils.getAccentColor()));
}
}
VkUiThemer.autoThemeVkuiButtons(textView);
ThemesHacks.fixProfileSelector(textView);
ThemesHacks.fixThemedFeed(textView, i);
}
}
public static boolean eligibleForStartTinting(TintTextView view) {
return ColorReferences.isAccentedColor(view.getTextColors()) || view.getTextColors().getDefaultColor() == ThemesUtils.getAccentColor();
}
public static boolean eligibleForTinting(int id) {
return !ThemesUtils.isDarkTheme() && (id == R.id.attach_title);
}
public static boolean isPositiveButton(View view) {
return !ThemesUtils.isDarkTheme() && (view.getId() == R.id.positive || view.getId() == R.id.positive_button);
}
public static boolean isVkUiButton(View view) {
return !ThemesUtils.isDarkTheme() && (
view.getId() == R.id.empty_button
);
}
}
@@ -0,0 +1,14 @@
package ru.vtosters.lite.themes.hooks;
import android.view.View;
import android.widget.Toolbar;
public class ToolbarHook implements BaseHook {
@Override
public void inject(View view, int i, boolean z) {
if (view instanceof Toolbar) {
// wtf?
}
}
}
@@ -0,0 +1,29 @@
package ru.vtosters.lite.themes.hooks;
import android.graphics.Paint;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffColorFilter;
import android.view.View;
import com.vk.imageloader.view.VKImageView;
import ru.vtosters.lite.utils.ThemesUtils;
public class VKImageViewHook implements BaseHook {
private static Paint paint = new Paint();
static {
paint.setColorFilter(new PorterDuffColorFilter(ThemesUtils.getAccentColor(), PorterDuff.Mode.SRC_IN));
}
@Override
public void inject(View view, int i, boolean z) {
if (view instanceof VKImageView) {
var imageView = (VKImageView) view;
if (imageView.getImageTintList() != null) {
imageView.setImageTintList(ThemesUtils.recolorCSL(imageView.getImageTintList()));
imageView.setColorFilter(ThemesUtils.getAccentColor(), PorterDuff.Mode.SRC_IN);
}
}
}
}
@@ -0,0 +1,16 @@
package ru.vtosters.lite.themes.hooks;
import android.view.View;
import com.vtosters.lite.ui.widget.WaveformView;
public class WaveformViewHook implements BaseHook {
@Override
public void inject(View view, int i, boolean z) {
if (view instanceof WaveformView) {
var waveformView = (WaveformView) view;
//waveformView.set(ThemesUtils.getAccentColor());
}
}
}
@@ -0,0 +1,81 @@
package ru.vtosters.lite.themes.utils;
import android.content.res.ColorStateList;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.DrawableContainer;
import android.graphics.drawable.GradientDrawable;
import android.graphics.drawable.RippleDrawable;
import android.graphics.drawable.StateListDrawable;
import android.os.Build;
import android.util.Log;
import android.widget.TextView;
import ru.vtosters.lite.themes.ColorReferences;
import ru.vtosters.lite.utils.ThemesUtils;
public class VkUiThemer {
public static void autoThemeVkuiButtons(TextView view) {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.N) return;
if (ThemesUtils.isDarkTheme())
return; // no need to theme b/w buttons, well it should skip, but I do it for extra performance
try {
if (!(view.getBackground() instanceof StateListDrawable)) return;
StateListDrawable states = ((StateListDrawable) view.getBackground());
if (states.getConstantState() == null) return;
DrawableContainer.DrawableContainerState dStates = (DrawableContainer.DrawableContainerState) states.getConstantState();
if (dStates.getChildCount() == 2) {
Drawable target = dStates.getChildren()[0];
if (!(target instanceof RippleDrawable)) return;
RippleDrawable ripple = (RippleDrawable) target;
for (int i = 0; i < ripple.getNumberOfLayers(); i++) {
if (ripple.getId(i) == android.R.id.mask) continue;
Drawable currentTarget = ripple.getDrawable(i);
if (!(currentTarget instanceof GradientDrawable)) continue;
//if (TSColorRefs.TS_DEBUG_MODE) Log.d("TSCore", "[tsh] finally, obamium = ["+currentTarget.toString()+"]");
GradientDrawable spd = (GradientDrawable) currentTarget;
if (spd.getShape() != GradientDrawable.RECTANGLE) continue;
Log.d("TSCore", "[tsh] got a color!");
ColorStateList csl = spd.getColor();
if (csl != null) {
Log.d("TSCore", "[tsh] csl2 <def: " + csl.getDefaultColor() + " = " + ThemesUtils.hex(csl.getDefaultColor()) + "> | " + csl);
}
if (ColorReferences.isAccentedColor(spd.getColor())) {
Log.d("TSCore", "[tsh] theming CSL");
spd.setTint(ThemesUtils.getAccentColor());
}
}
Drawable draw2 = dStates.getChildren()[0];
if (!(draw2 instanceof GradientDrawable)) return;
GradientDrawable spd = (GradientDrawable) draw2;
if (spd.getShape() != GradientDrawable.RECTANGLE) return;
Log.d("TSCore", "[tsh:disabled] got a color!");
ColorStateList csl = spd.getColor();
if (csl != null) {
Log.d("TSCore", "[tsh:disabled] csl2 <def: " + csl.getDefaultColor() + " = " + ThemesUtils.hex(csl.getDefaultColor()) + "> | " + csl);
}
if (ColorReferences.isAccentedColor(spd.getColor())) {
Log.d("TSCore", "[tsh:disabled] theming CSL");
spd.setTint(ThemesUtils.getAccentColor());
}
}
} catch (Exception e) {
// This must go wrong, so we ignore any exceptions that may occur
e.printStackTrace(); // REMOVE THIS!
}
}
}
@@ -40,14 +40,9 @@ import com.vk.core.ui.themes.VKThemeHelper;
import com.vtosters.lite.R;
import com.vtosters.lite.data.ThemeTracker;
import java.util.Arrays;
import java.util.List;
import ru.vtosters.lite.themes.ColorReferences;
public class ThemesUtils {
public static List<String> accentColors = Arrays.asList(
"5692d7", "528bcc", "7aa0cc", "518bcc", "6296d0", "2f68aa", "638ebf", "5181b8", "71aaeb", "4774a8", "5baaf4", "4186c8", "add3ff", "4774a8", "718198", "5a9eff", "99a2ad", "74a2d6", "e9eef3", "dfe3e7", "eff1f3", "5c9ce6", "4986cc", "4680c2"
);
public static void applyTheme(VKTheme theme) {
var currentActivity = LifecycleUtils.getCurrentActivity();
if (currentActivity != null) {
@@ -100,7 +95,7 @@ public class ThemesUtils {
}
public static int getAccentColor() {
return getColorFromAttr(R.attr.accent);
return getColor2(R.color.red);
} // Color accent
public static int getTextAttr() {
@@ -267,8 +262,8 @@ public class ThemesUtils {
int unsel = csl.getColorForState(new int[]{-android.R.attr.state_selected}, Color.BLACK);
int sel = csl.getColorForState(new int[]{android.R.attr.state_selected}, Color.BLACK);
boolean isUnselAccent = isAccentedColor(unsel);
boolean isSelAccent = isAccentedColor(sel);
boolean isUnselAccent = ColorReferences.isAccentedColor(unsel);
boolean isSelAccent = ColorReferences.isAccentedColor(sel);
if (isUnselAccent || isSelAccent) {
@@ -311,13 +306,6 @@ public class ThemesUtils {
return ColorUtils.setAlphaComponent(src, 169);
}
public static boolean isAccentedColor(ColorStateList target) {
return target != null && isAccentedColor(target.getDefaultColor());
}
public static boolean isAccentedColor(int target) {
return accentColors.contains(hex(target).toLowerCase());
}
public static int getColor(Context context, int i) {
if (isColorRefAccented(i) && isAndroidMonet()) {
@@ -384,6 +372,11 @@ public class ThemesUtils {
return String.format("#%06X", i & 16777215);
} // Get color as hex string
// hex, but without # at the beginning
public static String hexx(int i) {
return String.format("%06X", i & 16777215);
}
public static int getNavigationHeight(int Default) {
int VKME = R.dimen.design_bottom_sheet_peek_height_min;