Merge branch 'main' into sponsorpost-votes
This commit is contained in:
+29
-38
@@ -49,6 +49,7 @@ import com.vk.im.ui.views.msg.bubble.MsgBubbleView;
|
||||
import com.vk.im.ui.views.sticker.StickerAnimationState;
|
||||
import kotlin.Unit;
|
||||
import kotlin.jvm.b.Functions;
|
||||
import ru.vtosters.lite.themes.ThemesHacks;
|
||||
|
||||
public class VhMsg extends VhBase implements SwipeToReplyItemTouchCallback.b {
|
||||
public static final int h0 = Screen.a(124);
|
||||
@@ -133,7 +134,7 @@ public class VhMsg extends VhBase implements SwipeToReplyItemTouchCallback.b {
|
||||
this.h = itemView.findViewById(com.vk.im.ui.h.status_space);
|
||||
this.P = itemView.findViewById(com.vk.im.ui.h.bomb);
|
||||
this.B = vhBase;
|
||||
this.H = new ColorDrawable(context.getResources().getColor(com.vk.im.ui.d.msg_search_selection));
|
||||
this.H = new ColorDrawable(ThemesHacks.getColors(context, com.vk.im.ui.d.msg_search_selection));
|
||||
this.I = ContextExtKt.b(context, com.vk.im.ui.e.msg_bubble_max_width);
|
||||
this.J = ContextExtKt.b(context, com.vk.im.ui.e.msg_reply_max_width);
|
||||
this.K = ContextExtKt.b(context, com.vk.im.ui.e.msg_sticker_max_width);
|
||||
@@ -150,49 +151,39 @@ public class VhMsg extends VhBase implements SwipeToReplyItemTouchCallback.b {
|
||||
var6.right = var7.rightMargin;
|
||||
var6.top = var7.topMargin;
|
||||
var6.bottom = var7.bottomMargin;
|
||||
ViewExtKt.b(this.c, new View.OnClickListener() {
|
||||
public void onClick(View var1) {
|
||||
if (VhMsg.this.c0 != null && VhMsg.this.d0 != null) {
|
||||
VhMsg.this.c0.a(VhMsg.this.d0.getFrom());
|
||||
}
|
||||
|
||||
ViewExtKt.b(this.c, var1 -> {
|
||||
if (VhMsg.this.c0 != null && VhMsg.this.d0 != null) {
|
||||
VhMsg.this.c0.a(VhMsg.this.d0.getFrom());
|
||||
}
|
||||
});
|
||||
this.c.setOnLongClickListener(new View.OnLongClickListener() {
|
||||
public boolean onLongClick(View var1) {
|
||||
if (VhMsg.this.c0 != null && VhMsg.this.d0 != null) {
|
||||
VhMsg.this.c0.a(VhMsg.this.d0.getFrom());
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
});
|
||||
ViewExtKt.b(this.g, new View.OnClickListener() {
|
||||
public void onClick(View var1) {
|
||||
if (VhMsg.this.c0 != null && VhMsg.this.d0 != null) {
|
||||
VhMsg.this.c0.a(VhMsg.this.d0);
|
||||
}
|
||||
|
||||
}
|
||||
});
|
||||
ViewExtKt.b(this.itemView, new View.OnClickListener() {
|
||||
public void onClick(View var1) {
|
||||
if (VhMsg.this.c0 != null && VhMsg.this.d0 != null) {
|
||||
VhMsg.this.c0.a(VhMsg.this.d0.getLocalId());
|
||||
}
|
||||
|
||||
}
|
||||
});
|
||||
this.itemView.setOnLongClickListener(new View.OnLongClickListener() {
|
||||
public boolean onLongClick(View var1) {
|
||||
if (VhMsg.this.c0 != null && VhMsg.this.d0 != null) {
|
||||
VhMsg.this.c0.b(VhMsg.this.d0.getLocalId());
|
||||
}
|
||||
|
||||
this.c.setOnLongClickListener(var1 -> {
|
||||
if (VhMsg.this.c0 != null && VhMsg.this.d0 != null) {
|
||||
VhMsg.this.c0.a(VhMsg.this.d0.getFrom());
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
});
|
||||
ViewExtKt.b(this.g, var1 -> {
|
||||
if (VhMsg.this.c0 != null && VhMsg.this.d0 != null) {
|
||||
VhMsg.this.c0.a(VhMsg.this.d0);
|
||||
}
|
||||
|
||||
});
|
||||
ViewExtKt.b(this.itemView, (View.OnClickListener) var1 -> {
|
||||
if (VhMsg.this.c0 != null && VhMsg.this.d0 != null) {
|
||||
VhMsg.this.c0.a(VhMsg.this.d0.getLocalId());
|
||||
}
|
||||
|
||||
});
|
||||
this.itemView.setOnLongClickListener((View.OnLongClickListener) var1 -> {
|
||||
if (VhMsg.this.c0 != null && VhMsg.this.d0 != null) {
|
||||
VhMsg.this.c0.b(VhMsg.this.d0.getLocalId());
|
||||
}
|
||||
|
||||
return true;
|
||||
});
|
||||
this.R = ContextExtKt.i(context, com.vk.im.ui.c.im_msg_part_corner_radius_small);
|
||||
this.S = ContextExtKt.i(context, com.vk.im.ui.c.im_msg_part_corner_radius_big);
|
||||
this.c0 = null;
|
||||
|
||||
+2
-2
@@ -69,10 +69,10 @@ public class BottomNavigationItemView extends FrameLayout implements MenuView.It
|
||||
this.mIcon.getLayoutParams().height = V.a(28.0F);
|
||||
|
||||
this.mSmallLabel = this.findViewById(R.id.smallLabel);
|
||||
mSmallLabel.setTextColor(getCSTDock());
|
||||
mSmallLabel.setTextColor(getCSTDock(this.getContext()));
|
||||
|
||||
this.mLargeLabel = this.findViewById(R.id.largeLabel);
|
||||
mLargeLabel.setTextColor(getCSTDock());
|
||||
mLargeLabel.setTextColor(getCSTDock(this.getContext()));
|
||||
|
||||
LayoutInflater.from(this.getContext()).inflate(R.layout.navigation_bottom_counter, this, true);
|
||||
this.mCounterContainer = this.findViewById(R.id.counter_container);
|
||||
|
||||
@@ -65,7 +65,7 @@ public class DockBarInjector {
|
||||
for (DockBarTab tab : sManager.getSelectedTabs()) {
|
||||
MenuItem add = menu.add(0, tab.id, 0, tab.titleID);
|
||||
|
||||
add.setIcon(new RecoloredDrawable(getResources().getDrawable(tab.iconID), getCSTDock()));
|
||||
add.setIcon(new RecoloredDrawable(getResources().getDrawable(tab.iconID), getCSTDock(navigationView.getContext())));
|
||||
add.setTitle(getGlobalContext().getString(tab.titleID));
|
||||
add.setCheckable(true);
|
||||
}
|
||||
@@ -76,7 +76,7 @@ public class DockBarInjector {
|
||||
item.setStaticMode(true);
|
||||
item.setIconsMode(false);
|
||||
item.setShiftingMode(false);
|
||||
item.setTextColor(getCSTDock());
|
||||
item.setTextColor(getCSTDock(item.getContext()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
package ru.vtosters.hooks;
|
||||
|
||||
import android.content.Context;
|
||||
import android.net.NetworkInfo;
|
||||
import android.os.PowerManager;
|
||||
import android.telephony.TelephonyManager;
|
||||
import android.util.Log;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
import com.vk.core.preference.Preference;
|
||||
@@ -82,18 +84,18 @@ public class NewsfeedHook {
|
||||
}
|
||||
|
||||
public static void adsParams(HashSet<String> hashSet) {
|
||||
String[] adsParams = {"ads_disabled", "ads_app_slider", "ads_site_slider", "ads_app", "ads_site", "ads_post", "ads_app_video", "ads_post_pretty_cards", "ads_post_snippet_video"};
|
||||
String[] adsParams = {"ads_app_slider", "ads_site_slider", "ads_app", "ads_site", "ads_post", "ads_app_video", "ads_post_pretty_cards", "ads_post_snippet_video"};
|
||||
String noAdParam = "ads_disabled";
|
||||
|
||||
if (ads()) {
|
||||
hashSet.add(adsParams[0]);
|
||||
hashSet.add(adsParams[1]);
|
||||
hashSet.add(noAdParam);
|
||||
|
||||
if (!Preferences.milkshake()) {
|
||||
hashSet.add(adsParams[0]);
|
||||
}
|
||||
} else {
|
||||
Collections.addAll(hashSet, adsParams);
|
||||
}
|
||||
|
||||
if (Preferences.milkshake()) {
|
||||
hashSet.remove(adsParams[1]);
|
||||
}
|
||||
}
|
||||
|
||||
public static void takeOwnerIdSponsorPost(int ownerid) {
|
||||
@@ -150,4 +152,12 @@ public class NewsfeedHook {
|
||||
// return !getBoolValue("force_disable_psm", false) && pw.isPowerSaveMode();
|
||||
return false;
|
||||
}
|
||||
|
||||
public static boolean isRoaming(NetworkInfo networkInfo) {
|
||||
return !Preferences.disableForceTrafficSaver() && networkInfo.isRoaming();
|
||||
}
|
||||
|
||||
public static boolean isNetworkRoaming(TelephonyManager telephonyManager) {
|
||||
return !Preferences.disableForceTrafficSaver() && telephonyManager.isNetworkRoaming();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ package ru.vtosters.hooks.other;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.app.Activity;
|
||||
import android.content.Context;
|
||||
import android.content.res.ColorStateList;
|
||||
import android.content.res.Resources;
|
||||
import android.graphics.Color;
|
||||
@@ -73,7 +74,7 @@ public class ThemesUtils {
|
||||
}
|
||||
|
||||
public static boolean isMonetTheme() {
|
||||
return getBoolValue("monettheme", false) && Build.VERSION.SDK_INT >= Build.VERSION_CODES.S;
|
||||
return getBoolValue("monettheme", false);
|
||||
}
|
||||
|
||||
public static boolean isAmoledTheme() {
|
||||
@@ -340,7 +341,7 @@ public class ThemesUtils {
|
||||
}
|
||||
|
||||
public static int getColor(int i) {
|
||||
return ThemesHacks.getHackedColor(getGlobalContext(), i);
|
||||
return ThemesHacks.getHackedColor(LifecycleUtils.getCurrentActivity(), i);
|
||||
} // Android Support color injector + accent color checker
|
||||
|
||||
public static int getAlertStyle() {
|
||||
@@ -391,14 +392,14 @@ public class ThemesUtils {
|
||||
return vkme() ? R.dimen.app_minimumsize_h : Default;
|
||||
}
|
||||
|
||||
public static ColorStateList getCSTDock() {
|
||||
public static ColorStateList getCSTDock(Context ctx) {
|
||||
return new ColorStateList(
|
||||
new int[][]{
|
||||
new int[]{android.R.attr.state_checked},
|
||||
new int[]{-android.R.attr.state_checked}
|
||||
},
|
||||
new int[]{
|
||||
dockbar_accent() ? getAccentColor() : (isDarkTheme() ? getResources().getColor(R.color.white) : getResources().getColor(R.color.gray_700)),
|
||||
dockbar_accent() ? getAccentColor() : (isDarkTheme() ? ThemesHacks.getColors(ctx, R.color.white) : ThemesHacks.getColors(ctx, R.color.gray_700)),
|
||||
getColorFromAttr(R.attr.tabbar_inactive_icon)
|
||||
}
|
||||
);
|
||||
|
||||
@@ -31,22 +31,30 @@ public class ThemesHacks {
|
||||
}
|
||||
}
|
||||
|
||||
if (ThemesCore.isCachedAccents() && ColorReferences.isAccentedColor(context.getResources().getColor(color))) {
|
||||
if (ThemesCore.isCachedAccents() && ColorReferences.isAccentedColor(getColors(context, color))) {
|
||||
return ThemesUtils.getAccentColor();
|
||||
}
|
||||
|
||||
if (ThemesCore.isCachedAccents() && ColorReferences.isMutedAccentedColor(context.getResources().getColor(color))) {
|
||||
if (ThemesCore.isCachedAccents() && ColorReferences.isMutedAccentedColor(getColors(context, color))) {
|
||||
return ThemesUtils.getMutedAccentColor();
|
||||
}
|
||||
}
|
||||
|
||||
return Build.VERSION.SDK_INT > 23 ? context.getColor(color) : context.getResources().getColor(color);
|
||||
return getColors(context, color);
|
||||
}
|
||||
|
||||
public static int getColors(Context context, int color) {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
||||
return context.getColor(color);
|
||||
} else {
|
||||
return context.getResources().getColor(color);
|
||||
}
|
||||
}
|
||||
|
||||
// Фиксит селектор (все/свои/архив) в профиле
|
||||
public static void fixProfileSelector(View view) {
|
||||
if (!ThemesUtils.isMilkshake()) return;
|
||||
var id = view.getId();
|
||||
int 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);
|
||||
|
||||
@@ -3,6 +3,7 @@ package ru.vtosters.lite.themes;
|
||||
import android.app.Application;
|
||||
import android.content.Context;
|
||||
import android.graphics.Color;
|
||||
import android.os.Build;
|
||||
import com.google.devrel.gmscore.tools.apk.arsc.BinaryResourceFile;
|
||||
import com.vtosters.lite.R;
|
||||
import ru.vtosters.hooks.other.Preferences;
|
||||
@@ -12,6 +13,8 @@ import ru.vtosters.lite.themes.utils.ArscEditor;
|
||||
import ru.vtosters.lite.utils.IOUtils;
|
||||
|
||||
import java.io.*;
|
||||
import java.util.Arrays;
|
||||
import java.util.Enumeration;
|
||||
import java.util.zip.CRC32;
|
||||
import java.util.zip.ZipEntry;
|
||||
import java.util.zip.ZipFile;
|
||||
@@ -123,7 +126,7 @@ public class ThemesManager {
|
||||
ResourcesLoader.load(app, modApk.getAbsolutePath(), false);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
//
|
||||
}
|
||||
}
|
||||
|
||||
@@ -152,61 +155,72 @@ public class ThemesManager {
|
||||
}
|
||||
|
||||
public static void generateModApk(int accentColor) throws Throwable {
|
||||
try (var apk = new ZipFile(baseApkPath)) {
|
||||
var arscEntry = apk.getEntry("resources.arsc");
|
||||
var arscBis = new BufferedInputStream(apk.getInputStream(arscEntry));
|
||||
var arsc = BinaryResourceFile.fromInputStream(arscBis);
|
||||
try (ZipFile apk = new ZipFile(baseApkPath);
|
||||
ZipOutputStream zos = new ZipOutputStream(new BufferedOutputStream(new FileOutputStream(modApk)))) {
|
||||
|
||||
ZipEntry arscEntry = apk.getEntry("resources.arsc");
|
||||
BufferedInputStream arscBis = new BufferedInputStream(apk.getInputStream(arscEntry));
|
||||
BinaryResourceFile arsc = BinaryResourceFile.fromInputStream(arscBis);
|
||||
ArscEditor.changeColors(arsc, ACCENT_COLORS, accentColor);
|
||||
|
||||
try (var zos = new ZipOutputStream(new BufferedOutputStream(new FileOutputStream(modApk)))) {
|
||||
var arscBuff = arsc.toByteArray();
|
||||
var newArscEntry = new ZipEntry("resources.arsc");
|
||||
byte[] arscBuff = arsc.toByteArray();
|
||||
ZipEntry newArscEntry = new ZipEntry("resources.arsc");
|
||||
|
||||
var crc = new CRC32();
|
||||
crc.update(arscBuff);
|
||||
CRC32 crc = new CRC32();
|
||||
crc.update(arscBuff);
|
||||
|
||||
newArscEntry.setSize(arscBuff.length);
|
||||
newArscEntry.setMethod(ZipEntry.STORED);
|
||||
newArscEntry.setCrc(crc.getValue());
|
||||
newArscEntry.setSize(arscBuff.length);
|
||||
newArscEntry.setMethod(ZipEntry.STORED);
|
||||
newArscEntry.setCrc(crc.getValue());
|
||||
|
||||
zos.putNextEntry(newArscEntry);
|
||||
zos.write(arscBuff);
|
||||
zos.closeEntry();
|
||||
zos.putNextEntry(newArscEntry);
|
||||
zos.write(arscBuff);
|
||||
zos.closeEntry();
|
||||
|
||||
var entries = apk.entries();
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||
apk.stream()
|
||||
.filter(entry -> entry.getName().startsWith("res/") || entry.getName().startsWith("assets/") && !entry.getName().equals("resources.arsc"))
|
||||
.forEach(entry -> {
|
||||
try {
|
||||
String name = entry.getName();
|
||||
workWithApk(zos, name, apk.getInputStream(entry), entry.getSize(), entry.getCrc());
|
||||
} catch (IOException e) {
|
||||
e.fillInStackTrace();
|
||||
}
|
||||
});
|
||||
} else {
|
||||
Enumeration<? extends ZipEntry> entries = apk.entries();
|
||||
while (entries.hasMoreElements()) {
|
||||
var entry = entries.nextElement();
|
||||
var name = entry.getName();
|
||||
|
||||
if (!name.startsWith("res/") && !name.startsWith("assets/") || name.equals("resources.arsc"))
|
||||
continue;
|
||||
|
||||
var doNotCompress = false;
|
||||
for (var suffix : DO_NOT_COMPRESS) {
|
||||
if (name.endsWith(suffix)) {
|
||||
doNotCompress = true;
|
||||
break;
|
||||
}
|
||||
ZipEntry entry = entries.nextElement();
|
||||
String name = entry.getName();
|
||||
if (name.startsWith("res/") || name.startsWith("assets/") && !name.equals("resources.arsc")) {
|
||||
workWithApk(zos, name, apk.getInputStream(entry), entry.getSize(), entry.getCrc());
|
||||
}
|
||||
|
||||
var entryBis = new BufferedInputStream(apk.getInputStream(entry));
|
||||
var newEntry = new ZipEntry(name);
|
||||
|
||||
if (doNotCompress) {
|
||||
newEntry.setMethod(ZipEntry.STORED);
|
||||
newEntry.setSize(entry.getSize());
|
||||
newEntry.setCrc(entry.getCrc());
|
||||
} else newEntry.setMethod(ZipEntry.DEFLATED);
|
||||
|
||||
zos.putNextEntry(newEntry);
|
||||
IOUtils.copy(entryBis, zos);
|
||||
entryBis.close();
|
||||
zos.closeEntry();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void workWithApk(ZipOutputStream zos, String name, InputStream inputStream, long size, long crc) throws IOException {
|
||||
boolean doNotCompress = Arrays.stream(DO_NOT_COMPRESS).anyMatch(name::endsWith);
|
||||
|
||||
BufferedInputStream entryBis = new BufferedInputStream(inputStream);
|
||||
ZipEntry newEntry = new ZipEntry(name);
|
||||
|
||||
if (doNotCompress) {
|
||||
newEntry.setMethod(ZipEntry.STORED);
|
||||
newEntry.setSize(size);
|
||||
newEntry.setCrc(crc);
|
||||
} else {
|
||||
newEntry.setMethod(ZipEntry.DEFLATED);
|
||||
}
|
||||
|
||||
zos.putNextEntry(newEntry);
|
||||
IOUtils.copy(entryBis, zos);
|
||||
entryBis.close();
|
||||
zos.closeEntry();
|
||||
}
|
||||
|
||||
public static void deleteModification() {
|
||||
modApk.delete();
|
||||
}
|
||||
|
||||
@@ -13,6 +13,7 @@ import ru.vtosters.hooks.other.ThemesUtils;
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.stream.IntStream;
|
||||
|
||||
public class VTLResources extends Resources {
|
||||
private static final String TAG = "VTLResources";
|
||||
@@ -32,12 +33,8 @@ public class VTLResources extends Resources {
|
||||
attributesToTheme.add(16843173);
|
||||
}
|
||||
|
||||
private final Context context;
|
||||
|
||||
public VTLResources(Context context, Resources parent) {
|
||||
super(parent.getAssets(), parent.getDisplayMetrics(), parent.getConfiguration());
|
||||
this.context = context;
|
||||
// Log.d(TAG, "VTLResources: init");
|
||||
}
|
||||
|
||||
private static boolean isAttrThemeable(int attrID) {
|
||||
@@ -49,42 +46,49 @@ public class VTLResources extends Resources {
|
||||
return (int[]) typedArrayField.get(arr);
|
||||
} catch (IllegalAccessException e) {
|
||||
Log.e(TAG, "getArrayData: ", e);
|
||||
e.printStackTrace();
|
||||
e.fillInStackTrace();
|
||||
return new int[0];
|
||||
}
|
||||
}
|
||||
|
||||
@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];
|
||||
TypedArray typedArray = super.obtainAttributes(set, attrs);
|
||||
|
||||
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
|
||||
if (ThemesUtils.isMonetTheme()) {
|
||||
int[] data = getArrayData(typedArray);
|
||||
IntStream.range(0, attrs.length).forEach(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.fillInStackTrace();
|
||||
}
|
||||
} 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);
|
||||
}
|
||||
Drawable drawable = super.getDrawable(id, theme);
|
||||
fixDropdown(id, drawable);
|
||||
return drawable;
|
||||
}
|
||||
|
||||
private void fixDropdown(int id, Drawable drawable) {
|
||||
if (id == com.vtosters.lite.R.drawable.newsfeed_tab_dropdown_16 && ThemesUtils.isMonetTheme()) {
|
||||
ThemesHacks.fixDropdown(drawable);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,11 +1,13 @@
|
||||
package ru.vtosters.lite.themes;
|
||||
|
||||
import android.os.Build;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import ru.vtosters.hooks.other.ThemesUtils;
|
||||
import ru.vtosters.lite.themes.hooks.*;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.stream.IntStream;
|
||||
|
||||
public class ViewInjector {
|
||||
public static ArrayList<BaseHook> hooks = new ArrayList<>();
|
||||
@@ -22,15 +24,19 @@ public class ViewInjector {
|
||||
|
||||
public static View inject(View view, int i, boolean z) {
|
||||
if (ThemesUtils.isMonetTheme()) {
|
||||
for (BaseHook hook : hooks) {
|
||||
hook.inject(view, i, z);
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
|
||||
hooks.forEach(hook -> hook.inject(view, i, z));
|
||||
} else {
|
||||
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);
|
||||
}
|
||||
ViewGroup viewGroup = (ViewGroup) view;
|
||||
IntStream.range(0, viewGroup.getChildCount())
|
||||
.mapToObj(viewGroup::getChildAt)
|
||||
.forEach(child -> inject(child, i, false));
|
||||
}
|
||||
}
|
||||
return view;
|
||||
|
||||
@@ -43,7 +43,7 @@ public class TextViewHook implements BaseHook {
|
||||
@SuppressLint("RestrictedApi")
|
||||
@Override
|
||||
public void inject(View view, int i, boolean z) {
|
||||
if (view instanceof TextView) {
|
||||
if (view instanceof TextView && ThemesUtils.isMonetTheme()) {
|
||||
var textView = (TextView) view;
|
||||
|
||||
if (ColorReferences.isAccentedColor(textView.getCurrentTextColor())) {
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
package ru.vtosters.lite.themes.hooks;
|
||||
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuItem;
|
||||
import android.view.View;
|
||||
import androidx.appcompat.widget.Toolbar;
|
||||
import com.vk.core.drawable.RecoloredDrawable;
|
||||
@@ -9,16 +12,17 @@ public class ToolbarHook implements BaseHook {
|
||||
@Override
|
||||
public void inject(View view, int i, boolean z) {
|
||||
if (view instanceof Toolbar) {
|
||||
var color = (ThemesUtils.isMilkshake() && !ThemesUtils.isDarkTheme()) ? ThemesUtils.getAccentColor() : ThemesUtils.getHeaderText();
|
||||
var menu = ((Toolbar) view).getMenu();
|
||||
int color = (ThemesUtils.isMilkshake() && !ThemesUtils.isDarkTheme()) ? ThemesUtils.getAccentColor() : ThemesUtils.getHeaderText();
|
||||
Menu menu = ((Toolbar) view).getMenu();
|
||||
for (int j = 0; j < menu.size(); ++j) {
|
||||
var item = menu.getItem(j);
|
||||
var icon = item.getIcon();
|
||||
MenuItem item = menu.getItem(j);
|
||||
Drawable icon = item.getIcon();
|
||||
if (icon != null) {
|
||||
if (icon instanceof RecoloredDrawable)
|
||||
if (icon instanceof RecoloredDrawable) {
|
||||
((RecoloredDrawable) icon).a(color);
|
||||
else
|
||||
} else {
|
||||
icon = new RecoloredDrawable(icon, color);
|
||||
}
|
||||
item.setIcon(icon);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,11 +1,13 @@
|
||||
package ru.vtosters.lite.themes.items;
|
||||
|
||||
import android.graphics.Color;
|
||||
import org.json.JSONArray;
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.stream.IntStream;
|
||||
|
||||
public class VTLPalette {
|
||||
public String id;
|
||||
@@ -25,29 +27,38 @@ public class VTLPalette {
|
||||
}
|
||||
|
||||
public static VTLPalette fromJson(JSONObject json) throws JSONException {
|
||||
var palette = new VTLPalette()
|
||||
VTLPalette palette = new VTLPalette()
|
||||
.setId(json.optString("palette_id"))
|
||||
.setName(json.optString("name"))
|
||||
.setAuthor(json.optString("author"));
|
||||
var paletteNode = json.getJSONArray("palette");
|
||||
for (int i = 0; i < paletteNode.length(); i++) {
|
||||
var colorNode = paletteNode.getJSONObject(i);
|
||||
var name = colorNode.getString("name");
|
||||
if (colorNode.has("colors")) {
|
||||
var colorsNode = colorNode.getJSONArray("colors");
|
||||
for (int j = 0; j < colorsNode.length(); j++) {
|
||||
var subColorNode = colorsNode.getJSONObject(j);
|
||||
var index = subColorNode.getString("index");
|
||||
var subColor = subColorNode.getString("color");
|
||||
if (!subColor.startsWith("#")) subColor = "#" + subColor;
|
||||
palette.setColor(name + " " + index, Color.parseColor(subColor));
|
||||
}
|
||||
} else {
|
||||
var color = colorNode.getString("color");
|
||||
if (!color.startsWith("#")) color = "#" + color;
|
||||
palette.setColor(name, Color.parseColor(color));
|
||||
}
|
||||
}
|
||||
JSONArray paletteNode = json.getJSONArray("palette");
|
||||
IntStream.range(0, paletteNode.length())
|
||||
.mapToObj(paletteNode::optJSONObject)
|
||||
.forEach(colorNode -> {
|
||||
String name = colorNode.optString("name");
|
||||
if (colorNode.has("colors")) {
|
||||
JSONArray colorsNode;
|
||||
try {
|
||||
colorsNode = colorNode.getJSONArray("colors");
|
||||
} catch (JSONException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
IntStream.range(0, colorsNode.length())
|
||||
.mapToObj(colorsNode::optJSONObject)
|
||||
.forEach(subColorNode -> {
|
||||
String index = subColorNode.optString("index");
|
||||
String subColor = subColorNode.optString("color");
|
||||
if (!subColor.startsWith("#")) subColor = "#" + subColor;
|
||||
palette.setColor(name + " " + index, Color.parseColor(subColor));
|
||||
});
|
||||
} else {
|
||||
String color = colorNode.optString("color");
|
||||
if (!color.startsWith("#")) {
|
||||
color = "#" + color;
|
||||
}
|
||||
palette.setColor(name, Color.parseColor(color));
|
||||
}
|
||||
});
|
||||
return palette;
|
||||
}
|
||||
|
||||
@@ -79,15 +90,15 @@ public class VTLPalette {
|
||||
return this;
|
||||
}
|
||||
|
||||
public VTLPalette setColor(String name, int color) {
|
||||
public void setColor(String name, int color) {
|
||||
this.colors.add(new VTLColor(name, 0, color));
|
||||
return this;
|
||||
}
|
||||
|
||||
public int getColor(String name) {
|
||||
for (var item : colors)
|
||||
if (name.equals(item.resName))
|
||||
return item.color;
|
||||
return -1;
|
||||
return colors.stream()
|
||||
.filter(item -> name.equals(item.resName))
|
||||
.map(item -> item.color)
|
||||
.findFirst()
|
||||
.orElse(-1);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,23 +2,11 @@ package ru.vtosters.lite.themes.loaders;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.content.res.AssetManager;
|
||||
import ru.vtosters.lite.utils.ReflectionUtils;
|
||||
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
|
||||
@SuppressLint("PrivateApi")
|
||||
public class AssetManagerHelper {
|
||||
public static String getApkPath(Object assetManager, String packagename) throws InvocationTargetException, IllegalAccessException, ClassNotFoundException, NoSuchMethodException {
|
||||
Object[] apkAssetsArr = (Object[]) ReflectionUtils.findMethod(Class.forName("android.content.res.ApkAssets"), "getAssetPath").invoke(assetManager);
|
||||
// By default, base apk is the last element of array if is not, for execution speed, we should iterate array from the end to the beginning
|
||||
for (int i = apkAssetsArr.length - 1; i >= 0; i--) {
|
||||
String pathname = (String) ReflectionUtils.findMethod(AssetManager.class, "getApkAssets").invoke(apkAssetsArr[i]);
|
||||
if (pathname != null && pathname.contains(packagename)) return pathname;
|
||||
}
|
||||
|
||||
throw new NullPointerException();
|
||||
}
|
||||
|
||||
//region Uses for adding own assets or getting existing cookies
|
||||
public static void addAssetPath(AssetManager manager, String path) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
|
||||
manager.getClass().getMethod("addAssetPath", String.class).invoke(manager, path);
|
||||
|
||||
@@ -171,8 +171,6 @@ public class ResourcesLoader {
|
||||
implAssets.set(resourceImpl, sAssetManager);
|
||||
}
|
||||
|
||||
clearPreloadTypedArrayIssue(resources);
|
||||
|
||||
resources.updateConfiguration(resources.getConfiguration(), resources.getDisplayMetrics());
|
||||
}
|
||||
|
||||
@@ -235,33 +233,6 @@ public class ResourcesLoader {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Why must I do these?
|
||||
* Resource has mTypedArrayPool field, which just like Message Poll to reduce gc
|
||||
* MiuiResource change TypedArray to MiuiTypedArray, but it get string block from offset instead of assetManager
|
||||
*/
|
||||
private static void clearPreloadTypedArrayIssue(Resources resources) {
|
||||
// Perform this trick not only in Miui system since we can't predict if any other
|
||||
// manufacturer would do the same modification to Android.
|
||||
// if (!isMiuiSystem) {
|
||||
// return;
|
||||
// }
|
||||
Log.w("ResourcesLoader", "try to clear typedArray cache!");
|
||||
// Clear typedArray cache.
|
||||
try {
|
||||
Field typedArrayPoolField = ReflectionUtils.findField(Resources.class, "mTypedArrayPool");
|
||||
Object origTypedArrayPool = typedArrayPoolField.get(resources);
|
||||
Method acquireMethod = ReflectionUtils.findMethod(origTypedArrayPool, "acquire");
|
||||
while (true) {
|
||||
if (acquireMethod.invoke(origTypedArrayPool) == null) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
} catch (Throwable ignored) {
|
||||
Log.e("ResourcesLoader", "clearPreloadTypedArrayIssue failed, ignore error: " + ignored);
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean shouldAddSharedLibraryAssets(ApplicationInfo applicationInfo) {
|
||||
return Build.VERSION.SDK_INT >= Build.VERSION_CODES.N && applicationInfo != null &&
|
||||
applicationInfo.sharedLibraryFiles != null;
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
package ru.vtosters.lite.themes.palettes;
|
||||
|
||||
import android.content.res.AssetManager;
|
||||
import android.os.Build;
|
||||
import android.os.Environment;
|
||||
import android.util.Log;
|
||||
import android.widget.Toast;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
@@ -15,8 +15,7 @@ import ru.vtosters.lite.utils.LifecycleUtils;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.*;
|
||||
|
||||
import static android.widget.Toast.makeText;
|
||||
import static ru.vtosters.lite.utils.AndroidUtils.getGlobalContext;
|
||||
@@ -51,7 +50,7 @@ public class PalettesManager {
|
||||
return;
|
||||
}
|
||||
|
||||
var palettes = PALETTES_DIR.listFiles((dir, name) -> name.endsWith(".json"));
|
||||
File[] palettes = PALETTES_DIR.listFiles((dir, name) -> name.endsWith(".json"));
|
||||
if (palettes == null || palettes.length == 0)
|
||||
copyPaletteFromAssets();
|
||||
parsePalettes();
|
||||
@@ -59,45 +58,49 @@ public class PalettesManager {
|
||||
|
||||
private void copyPaletteFromAssets() {
|
||||
try {
|
||||
var manager = AndroidUtils.getGlobalContext().getAssets();
|
||||
var assets = manager.list(ASSETS_DIR);
|
||||
if (assets == null || assets.length == 0) return;
|
||||
for (var asset : assets) {
|
||||
try {
|
||||
IOUtils.copy(manager.open(ASSETS_DIR + asset), new File(PALETTES_DIR, asset));
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
AssetManager manager = getGlobalContext().getAssets();
|
||||
Arrays.stream(manager.list(ASSETS_DIR))
|
||||
.filter(Objects::nonNull)
|
||||
.forEach(asset -> {
|
||||
try {
|
||||
IOUtils.copy(manager.open(ASSETS_DIR + asset), new File(PALETTES_DIR, asset));
|
||||
} catch (IOException e) {
|
||||
e.fillInStackTrace();
|
||||
}
|
||||
});
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
e.fillInStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
private void parsePalettes() {
|
||||
var arr = PALETTES_DIR.listFiles((dir, name) -> name.endsWith(".json"));
|
||||
|
||||
if (arr == null || arr.length == 0) {
|
||||
Log.d("PalettesManager", "arr.length null");
|
||||
return;
|
||||
}
|
||||
|
||||
for (var file : arr) {
|
||||
try {
|
||||
var json = new JSONObject(IOUtils.readAllLines(file));
|
||||
mPalettes.add(VTLPalette.fromJson(json));
|
||||
} catch (IOException | JSONException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
Optional.ofNullable(PALETTES_DIR.listFiles((dir, name) -> name.endsWith(".json")))
|
||||
.ifPresent(arr -> Arrays.stream(arr)
|
||||
.map(file -> {
|
||||
try {
|
||||
return new JSONObject(IOUtils.readAllLines(file));
|
||||
} catch (IOException | JSONException e) {
|
||||
e.printStackTrace();
|
||||
return null;
|
||||
}
|
||||
})
|
||||
.filter(Objects::nonNull)
|
||||
.map(json -> {
|
||||
try {
|
||||
return json != null ? VTLPalette.fromJson(json) : null;
|
||||
} catch (JSONException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
})
|
||||
.forEach(mPalettes::add));
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public VTLPalette getPalette(String id) {
|
||||
for (var palette : mPalettes)
|
||||
if (id.equals(palette.id))
|
||||
return palette;
|
||||
return null;
|
||||
return mPalettes.stream()
|
||||
.filter(palette -> id.equals(palette.id))
|
||||
.findFirst()
|
||||
.orElse(null);
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@@ -108,4 +111,4 @@ public class PalettesManager {
|
||||
public int getPalettesCount() {
|
||||
return mPalettes.size();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -4,29 +4,30 @@ import com.google.devrel.gmscore.tools.apk.arsc.BinaryResourceFile;
|
||||
import com.google.devrel.gmscore.tools.apk.arsc.BinaryResourceValue;
|
||||
import com.google.devrel.gmscore.tools.apk.arsc.ResourceTableChunk;
|
||||
|
||||
import java.util.AbstractMap;
|
||||
import java.util.Arrays;
|
||||
|
||||
public class ArscEditor {
|
||||
|
||||
public static void changeColors(BinaryResourceFile arsc, int[] colorIds, int color) {
|
||||
for (var chunk : arsc.getChunks()) {
|
||||
var resTableChunk = (ResourceTableChunk) chunk;
|
||||
for (var packageChunk : resTableChunk.getPackages()) {
|
||||
for (var typeChunk : packageChunk.getTypeChunks("color")) {
|
||||
for (var entry : typeChunk.getEntries().entrySet()) {
|
||||
var value = entry.getValue();
|
||||
if (value.isComplex()) continue;
|
||||
var binValue = value.value();
|
||||
if (!isColorResourceValue(binValue)) continue;
|
||||
var resId = packageChunk.getId() << 24 | typeChunk.getId() << 16 | entry.getKey();
|
||||
for (var colodId : colorIds) {
|
||||
if (resId == colodId) {
|
||||
binValue.data = color;
|
||||
break;
|
||||
arsc.getChunks().stream()
|
||||
.filter(chunk -> chunk instanceof ResourceTableChunk)
|
||||
.map(chunk -> (ResourceTableChunk) chunk)
|
||||
.flatMap(resTableChunk -> resTableChunk.getPackages().stream())
|
||||
.flatMap(packageChunk -> packageChunk.getTypeChunks("color").stream()
|
||||
.map(typeChunk -> new AbstractMap.SimpleEntry<>(packageChunk, typeChunk)))
|
||||
.forEach(entry -> entry.getValue().getEntries().entrySet().stream()
|
||||
.filter(e -> !e.getValue().isComplex())
|
||||
.filter(e -> isColorResourceValue(e.getValue().value()))
|
||||
.forEach(e -> {
|
||||
BinaryResourceValue binValue = e.getValue().value();
|
||||
int resId = entry.getKey().getId() << 24 | entry.getValue().getId() << 16 | e.getKey();
|
||||
if (Arrays.stream(colorIds).anyMatch(colorId -> resId == colorId)) {
|
||||
if (binValue != null) {
|
||||
binValue.data = color;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
private static boolean isColorResourceValue(BinaryResourceValue value) {
|
||||
@@ -35,4 +36,4 @@ public class ArscEditor {
|
||||
|| value.type == BinaryResourceValue.Type.INT_COLOR_ARGB4
|
||||
|| value.type == BinaryResourceValue.Type.INT_COLOR_RGB4;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3,27 +3,55 @@ package ru.vtosters.lite.themes.utils;
|
||||
import android.annotation.SuppressLint;
|
||||
import android.content.Context;
|
||||
import android.content.res.ColorStateList;
|
||||
import android.content.res.Configuration;
|
||||
import android.content.res.Resources;
|
||||
import android.content.res.TypedArray;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.os.Build;
|
||||
import android.util.SparseArray;
|
||||
import android.util.TypedValue;
|
||||
import android.widget.TextView;
|
||||
import androidx.annotation.ColorRes;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.core.content.res.ColorStateListInflaterCompat;
|
||||
import com.vk.core.drawable.RecoloredDrawable;
|
||||
import ru.vtosters.hooks.other.ThemesUtils;
|
||||
import ru.vtosters.lite.themes.ColorReferences;
|
||||
import ru.vtosters.lite.themes.ThemesManager;
|
||||
import ru.vtosters.lite.utils.AndroidUtils;
|
||||
|
||||
import java.util.WeakHashMap;
|
||||
|
||||
public class RecolorUtils {
|
||||
public static Drawable recolorDrawableToolbar(Drawable drawable) {
|
||||
if (drawable == null) return null;
|
||||
private static final ThreadLocal<TypedValue> TL_TYPED_VALUE = new ThreadLocal<>();
|
||||
private static final WeakHashMap<Context, SparseArray<ColorStateListCacheEntry>> sColorStateCaches = new WeakHashMap<>(0);
|
||||
private static final Object sColorStateCacheLock = new Object();
|
||||
|
||||
return new RecoloredDrawable(drawable, ThemesUtils.getHeaderText());
|
||||
} // Recolor toolbar drawable to accent color
|
||||
private static void addColorStateListToCache(@NonNull Context context, @ColorRes int i, @NonNull ColorStateList colorStateList) {
|
||||
synchronized (sColorStateCacheLock) {
|
||||
SparseArray<ColorStateListCacheEntry> sparseArray = sColorStateCaches.get(context);
|
||||
if (sparseArray == null) {
|
||||
sparseArray = new SparseArray<>();
|
||||
sColorStateCaches.put(context, sparseArray);
|
||||
}
|
||||
sparseArray.append(i, new ColorStateListCacheEntry(colorStateList, context.getResources().getConfiguration()));
|
||||
}
|
||||
}
|
||||
|
||||
public static Drawable recolorDrawableInt(int drawable) {
|
||||
return recolorDrawable(drawable, ThemesUtils.getAccentColor());
|
||||
} // Get res drawable via id and coloring to accent
|
||||
private static ColorStateList getCachedColorStateList(@NonNull Context context, @ColorRes int i) {
|
||||
ColorStateListCacheEntry colorStateListCacheEntry;
|
||||
synchronized (sColorStateCacheLock) {
|
||||
SparseArray<ColorStateListCacheEntry> sparseArray = sColorStateCaches.get(context);
|
||||
if (sparseArray != null && sparseArray.size() > 0 && (colorStateListCacheEntry = sparseArray.get(i)) != null) {
|
||||
if (colorStateListCacheEntry.configuration.equals(context.getResources().getConfiguration())) {
|
||||
return colorStateListCacheEntry.value;
|
||||
}
|
||||
sparseArray.remove(i);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public static Drawable recolorDrawable(int drawable, int color) {
|
||||
return new RecoloredDrawable(AndroidUtils.getResources().getDrawable(drawable), color);
|
||||
@@ -34,19 +62,19 @@ public class RecolorUtils {
|
||||
}
|
||||
|
||||
public static int getColor(TypedArray ta, int index, int defval) {
|
||||
return recolorHexColor(ta.getColor(index, defval));
|
||||
return ThemesUtils.isMonetTheme() ? ta.getColor(index, defval) : recolorHexColor(ta.getColor(index, defval));
|
||||
}
|
||||
|
||||
public static void recolorTextView(TextView tw) {
|
||||
if (ColorReferences.isAccentedColor(tw.getTextColors())) {
|
||||
if (ColorReferences.isAccentedColor(tw.getTextColors()) && ThemesUtils.isMonetTheme()) {
|
||||
tw.setTextColor(ThemesUtils.getAccentColor());
|
||||
}
|
||||
}
|
||||
|
||||
public static int recolorHexColor(int i) {
|
||||
if (!ThemesUtils.isMonetTheme() || !ThemesManager.canApplyCustomAccent()) return i;
|
||||
var accented = ColorReferences.isAccentedColor(i);
|
||||
var mutedaccented = ColorReferences.isMutedAccentedColor(i);
|
||||
boolean accented = ColorReferences.isAccentedColor(i);
|
||||
boolean mutedaccented = ColorReferences.isMutedAccentedColor(i);
|
||||
return (accented || mutedaccented) ? (accented ? ThemesUtils.getAccentColor() : ThemesUtils.getMutedAccentColor()) : i;
|
||||
}
|
||||
|
||||
@@ -56,9 +84,51 @@ public class RecolorUtils {
|
||||
return ColorStateList.valueOf(ThemesUtils.getAccentColor());
|
||||
} // Recolor ColorStateList to accent color
|
||||
|
||||
@SuppressLint("RestrictedApi")
|
||||
private static ColorStateList inflateColorStateList(Context context, int i) {
|
||||
if (isColorInt(context, i)) {
|
||||
return null;
|
||||
}
|
||||
Resources resources = context.getResources();
|
||||
try {
|
||||
return ColorStateListInflaterCompat.createFromXml(resources, resources.getXml(i), context.getTheme());
|
||||
} catch (Exception e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean isColorInt(@NonNull Context context, @ColorRes int i) {
|
||||
Resources resources = context.getResources();
|
||||
TypedValue typedValue = getTypedValue();
|
||||
resources.getValue(i, typedValue, true);
|
||||
int i2 = typedValue.type;
|
||||
return i2 >= 28 && i2 <= 31;
|
||||
}
|
||||
|
||||
private static TypedValue getTypedValue() {
|
||||
TypedValue typedValue = TL_TYPED_VALUE.get();
|
||||
if (typedValue == null) {
|
||||
TypedValue typedValue2 = new TypedValue();
|
||||
TL_TYPED_VALUE.set(typedValue2);
|
||||
return typedValue2;
|
||||
}
|
||||
return typedValue;
|
||||
}
|
||||
|
||||
@SuppressLint("UseCompatLoadingForColorStateLists")
|
||||
public static ColorStateList themeCSL(Context context, int color) {
|
||||
if (!ThemesUtils.isMonetTheme()) {
|
||||
ColorStateList cachedColorStateList = getCachedColorStateList(context, color);
|
||||
if (cachedColorStateList != null) {
|
||||
return cachedColorStateList;
|
||||
}
|
||||
|
||||
ColorStateList inflateColorStateList = inflateColorStateList(context, color);
|
||||
if (inflateColorStateList != null) {
|
||||
addColorStateListToCache(context, color, inflateColorStateList);
|
||||
return inflateColorStateList;
|
||||
}
|
||||
|
||||
if (Build.VERSION.SDK_INT >= 23) {
|
||||
return context.getColorStateList(color);
|
||||
} else {
|
||||
@@ -72,15 +142,7 @@ public class RecolorUtils {
|
||||
return ColorStateList.valueOf(ThemesUtils.getMutedAccentColor());
|
||||
}
|
||||
|
||||
ColorStateList csl;
|
||||
|
||||
if (Build.VERSION.SDK_INT >= 23) {
|
||||
csl = context.getColorStateList(color);
|
||||
} else {
|
||||
csl = context.getResources().getColorStateList(color);
|
||||
}
|
||||
|
||||
return themeCSL(csl);
|
||||
return themeCSL(context.getColorStateList(color));
|
||||
} // Recolor ColorStateList
|
||||
|
||||
public static ColorStateList themeCSL(ColorStateList csl) {
|
||||
@@ -120,4 +182,14 @@ public class RecolorUtils {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
static class ColorStateListCacheEntry {
|
||||
final Configuration configuration;
|
||||
final ColorStateList value;
|
||||
|
||||
ColorStateListCacheEntry(@NonNull ColorStateList colorStateList, @NonNull Configuration configuration) {
|
||||
this.value = colorStateList;
|
||||
this.configuration = configuration;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -74,7 +74,7 @@ public class VkUiThemer {
|
||||
}
|
||||
} catch (Exception e) {
|
||||
// This must go wrong, so we ignore any exceptions that may occur
|
||||
e.printStackTrace(); // REMOVE THIS!
|
||||
e.fillInStackTrace(); // REMOVE THIS!
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -109,7 +109,7 @@ public class ThemesFragment extends TrackedMaterialPreferenceToolbarFragment {
|
||||
|
||||
newsfeedNotificationsPreference.setVisible(Preferences.milkshake());
|
||||
|
||||
findPreference("accentprefs").setVisible(!ThemesUtils.isMonetTheme());
|
||||
findPreference("accentprefs").setVisible(!ThemesUtils.isMonetTheme() && Build.VERSION.SDK_INT >= Build.VERSION_CODES.M);
|
||||
|
||||
findPreference("systememoji").setOnPreferenceClickListener(preference -> {
|
||||
restart();
|
||||
|
||||
@@ -70,19 +70,22 @@ public class VKAccountDB {
|
||||
LifecycleUtils.getCurrentActivity().requestPermissions(new String[]{"android.permission.WRITE_EXTERNAL_STORAGE"}, 228);
|
||||
}
|
||||
|
||||
var db = getDatabase().getReadableDatabase();
|
||||
var dateFormat = new SimpleDateFormat("yyyy-MM-dd.HH-mm-ss", Locale.getDefault());
|
||||
var dir = new File(getExternalStoragePublicDirectory(DIRECTORY_DOWNLOADS), "/VTLBackups/");
|
||||
var file = new File(dir, "saved_accounts_" + dateFormat.format(new Date()) + ".vtl");
|
||||
SQLiteDatabase db = getDatabase().getReadableDatabase();
|
||||
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd.HH-mm-ss", Locale.getDefault());
|
||||
File dir = new File(getExternalStoragePublicDirectory(DIRECTORY_DOWNLOADS), "/VTLBackups/");
|
||||
File file = new File(dir, "saved_accounts_" + dateFormat.format(new Date()) + ".vtl");
|
||||
|
||||
try (InputStream inputStream = new FileInputStream(db.getPath())) {
|
||||
dir.mkdirs();
|
||||
if (!dir.exists()) {
|
||||
dir.mkdirs();
|
||||
}
|
||||
|
||||
FileOutputStream outputStream = new FileOutputStream(file);
|
||||
byte[] buff = new byte[1024];
|
||||
int read;
|
||||
while ((read = inputStream.read(buff, 0, buff.length)) > 0)
|
||||
while ((read = inputStream.read(buff, 0, buff.length)) > 0) {
|
||||
outputStream.write(buff, 0, read);
|
||||
}
|
||||
inputStream.close();
|
||||
outputStream.close();
|
||||
|
||||
|
||||
@@ -39,8 +39,14 @@ public class FiltersPreferences {
|
||||
preferences.edit().putBoolean("sponsorpost_filters_marking", status).apply();
|
||||
}
|
||||
|
||||
public static void clearAll() {
|
||||
preferences.edit().clear().apply();
|
||||
public static void clearAllCachedLists() {
|
||||
SharedPreferences.Editor editor = preferences.edit();
|
||||
|
||||
preferences.getAll().keySet().stream()
|
||||
.filter(key -> key.endsWith(":" + PREF_KEY_LIST))
|
||||
.forEach(editor::remove);
|
||||
|
||||
editor.apply();
|
||||
}
|
||||
|
||||
public static boolean getSavedKeyValue(int id) {
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package ru.vtosters.sponsorpost.utils;
|
||||
|
||||
import ru.vtosters.lite.utils.NetworkUtils;
|
||||
import ru.vtosters.lite.utils.newsfeed.NewsFeedFiltersUtils;
|
||||
import ru.vtosters.sponsorpost.data.Filter;
|
||||
import ru.vtosters.sponsorpost.data.Post;
|
||||
import ru.vtosters.sponsorpost.internal.VotesPreferences;
|
||||
@@ -25,7 +26,7 @@ public class Updates {
|
||||
List<Filter> localFilters = FiltersPreferences.getAllDownloadedFilters();
|
||||
|
||||
if (!filters.isEmpty()) {
|
||||
FiltersPreferences.clearAll(); // removes deleted filters from server
|
||||
FiltersPreferences.clearAllCachedLists(); // removes deleted filters from server and cache
|
||||
|
||||
for (Filter filter : filters) {
|
||||
Filter localFilter = findLocalFilterById(localFilters, filter.getId());
|
||||
@@ -41,6 +42,8 @@ public class Updates {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
NewsFeedFiltersUtils.updateFilters();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1101,7 +1101,7 @@
|
||||
|
||||
if-eqz v0, :cond_0
|
||||
|
||||
invoke-virtual {v0}, Landroid/net/NetworkInfo;->isRoaming()Z
|
||||
invoke-static {v0}, Lru/vtosters/hooks/NewsfeedHook;->isRoaming(Landroid/net/NetworkInfo;)Z
|
||||
|
||||
move-result v0
|
||||
|
||||
@@ -1125,7 +1125,7 @@
|
||||
|
||||
move-result-object v0
|
||||
|
||||
invoke-virtual {v0}, Landroid/telephony/TelephonyManager;->isNetworkRoaming()Z
|
||||
invoke-static {v0}, Lru/vtosters/hooks/NewsfeedHook;->isNetworkRoaming(Landroid/telephony/TelephonyManager;)Z
|
||||
|
||||
move-result v0
|
||||
|
||||
|
||||
@@ -163,7 +163,7 @@
|
||||
|
||||
if-eqz v0, :cond_0
|
||||
|
||||
invoke-virtual {v0}, Landroid/net/NetworkInfo;->isRoaming()Z
|
||||
invoke-static {v0}, Lru/vtosters/hooks/NewsfeedHook;->isRoaming(Landroid/net/NetworkInfo;)Z
|
||||
|
||||
move-result v0
|
||||
|
||||
@@ -187,7 +187,7 @@
|
||||
|
||||
move-result-object v0
|
||||
|
||||
invoke-virtual {v0}, Landroid/telephony/TelephonyManager;->isNetworkRoaming()Z
|
||||
invoke-static {v0}, Lru/vtosters/hooks/NewsfeedHook;->isNetworkRoaming(Landroid/telephony/TelephonyManager;)Z
|
||||
|
||||
move-result v0
|
||||
|
||||
|
||||
@@ -400,7 +400,7 @@
|
||||
|
||||
if-eqz v1, :cond_8
|
||||
|
||||
invoke-virtual {v1}, Landroid/telephony/TelephonyManager;->isNetworkRoaming()Z
|
||||
invoke-static {v1}, Lru/vtosters/hooks/NewsfeedHook;->isNetworkRoaming(Landroid/telephony/TelephonyManager;)Z
|
||||
|
||||
move-result v1
|
||||
|
||||
|
||||
@@ -794,7 +794,7 @@
|
||||
|
||||
.line 3
|
||||
:cond_0
|
||||
invoke-virtual {v0}, Landroid/net/NetworkInfo;->isRoaming()Z
|
||||
invoke-static {v0}, Lru/vtosters/hooks/NewsfeedHook;->isRoaming(Landroid/net/NetworkInfo;)Z
|
||||
|
||||
move-result v0
|
||||
|
||||
|
||||
@@ -277,7 +277,7 @@
|
||||
|
||||
iput-object v2, v1, Lru/mail/libverify/accounts/e;->m:Ljava/lang/String;
|
||||
|
||||
invoke-virtual {p0}, Landroid/telephony/TelephonyManager;->isNetworkRoaming()Z
|
||||
invoke-static {p0}, Lru/vtosters/hooks/NewsfeedHook;->isNetworkRoaming(Landroid/telephony/TelephonyManager;)Z
|
||||
|
||||
move-result v2
|
||||
|
||||
|
||||
@@ -1419,7 +1419,7 @@
|
||||
|
||||
check-cast p0, Landroid/telephony/TelephonyManager;
|
||||
|
||||
invoke-virtual {p0}, Landroid/telephony/TelephonyManager;->isNetworkRoaming()Z
|
||||
invoke-static {p0}, Lru/vtosters/hooks/NewsfeedHook;->isNetworkRoaming(Landroid/telephony/TelephonyManager;)Z
|
||||
|
||||
move-result p0
|
||||
|
||||
|
||||
@@ -441,7 +441,7 @@
|
||||
goto :goto_1
|
||||
|
||||
:cond_1
|
||||
invoke-virtual {v0}, Landroid/net/NetworkInfo;->isRoaming()Z
|
||||
invoke-static {v0}, Lru/vtosters/hooks/NewsfeedHook;->isRoaming(Landroid/net/NetworkInfo;)Z
|
||||
|
||||
move-result v0
|
||||
|
||||
|
||||
@@ -4055,7 +4055,7 @@
|
||||
iget-object v1, p0, Lvigo/sdk/Vigo;->tm:Landroid/telephony/TelephonyManager;
|
||||
|
||||
.line 13
|
||||
invoke-virtual {v1}, Landroid/telephony/TelephonyManager;->isNetworkRoaming()Z
|
||||
invoke-static {v1}, Lru/vtosters/hooks/NewsfeedHook;->isNetworkRoaming(Landroid/telephony/TelephonyManager;)Z
|
||||
|
||||
move-result v1
|
||||
|
||||
|
||||
Reference in New Issue
Block a user