Compare commits
46
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
cdaf7909d4 | ||
|
|
c70ab388c1 | ||
|
|
50c66c2703 | ||
|
|
357e520bb0 | ||
|
|
6379ce5741 | ||
|
|
02807739a1 | ||
|
|
40635ab75a | ||
|
|
32e1bfe6fd | ||
|
|
281a0e8499 | ||
|
|
220c61afe1 | ||
|
|
7a632d5224 | ||
|
|
3218c1a46b | ||
|
|
b2028d86ba | ||
|
|
45ed5879e6 | ||
|
|
48479dd064 | ||
|
|
3b556b81a1 | ||
|
|
526c9a607a | ||
|
|
81752895ab | ||
|
|
ad970d097a | ||
|
|
bc2010b49d | ||
|
|
ff4a4094ff | ||
|
|
3629e71098 | ||
|
|
b955ac355f | ||
|
|
409279eca0 | ||
|
|
ea0a0f1d93 | ||
|
|
3cc81dfddc | ||
|
|
86041e6031 | ||
|
|
e140ce2661 | ||
|
|
f6f15132a2 | ||
|
|
e73751ecf3 | ||
|
|
3c0516b4cd | ||
|
|
38d9f4a818 | ||
|
|
207fa4f2e7 | ||
|
|
f9f778b8f4 | ||
|
|
962dcdec67 | ||
|
|
486026b8aa | ||
|
|
e78d08fb94 | ||
|
|
a5e81dbd87 | ||
|
|
49051dae9a | ||
|
|
94236c87e3 | ||
|
|
449ba8c768 | ||
|
|
0da81c01e9 | ||
|
|
b4a0b7e1ea | ||
|
|
f2209eca49 | ||
|
|
4a004971c6 | ||
|
|
e400b8761c |
@@ -21,10 +21,10 @@ jobs:
|
|||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Set up JDK 14
|
- name: Set up JDK
|
||||||
uses: actions/setup-java@v3
|
uses: actions/setup-java@v3
|
||||||
with:
|
with:
|
||||||
java-version: '14'
|
java-version: '17'
|
||||||
distribution: 'adopt'
|
distribution: 'adopt'
|
||||||
|
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v3
|
||||||
|
|||||||
+54
-71
@@ -1,8 +1,6 @@
|
|||||||
import org.apache.tools.ant.taskdefs.condition.Os
|
import org.apache.tools.ant.taskdefs.condition.Os
|
||||||
|
|
||||||
import java.util.zip.ZipEntry
|
|
||||||
import java.util.zip.ZipFile
|
import java.util.zip.ZipFile
|
||||||
import java.util.zip.ZipInputStream
|
|
||||||
|
|
||||||
plugins {
|
plugins {
|
||||||
id 'com.android.application'
|
id 'com.android.application'
|
||||||
@@ -21,6 +19,10 @@ cargo {
|
|||||||
|
|
||||||
def smaliFolder = projectDir.toPath().resolve("../smali").normalize()
|
def smaliFolder = projectDir.toPath().resolve("../smali").normalize()
|
||||||
def scriptsFolder = projectDir.toPath().resolve("../scripts").normalize()
|
def scriptsFolder = projectDir.toPath().resolve("../scripts").normalize()
|
||||||
|
//you can add own folders with decompiled smali code
|
||||||
|
def dexes=smaliFolder.toFile()
|
||||||
|
.listFiles( { f -> f.isDirectory() && f.name.startsWith("smali") } as FileFilter)
|
||||||
|
.size()
|
||||||
|
|
||||||
versionFile {
|
versionFile {
|
||||||
file = projectDir.toPath().resolve("src/main/assets/version.properties").toFile()
|
file = projectDir.toPath().resolve("src/main/assets/version.properties").toFile()
|
||||||
@@ -50,19 +52,24 @@ android {
|
|||||||
}
|
}
|
||||||
|
|
||||||
buildTypes {
|
buildTypes {
|
||||||
|
release {
|
||||||
|
minifyEnabled true
|
||||||
|
buildConfigField 'String', 'APPCENTER_KEY', '""'
|
||||||
|
proguardFile 'proguard-rules.pro'
|
||||||
|
}
|
||||||
|
rc {
|
||||||
|
minifyEnabled true
|
||||||
|
buildConfigField 'String', 'APPCENTER_KEY', '""'
|
||||||
|
proguardFile 'proguard-rules.pro'
|
||||||
|
}
|
||||||
dev {
|
dev {
|
||||||
initWith release
|
minifyEnabled false
|
||||||
buildConfigField 'String', 'APPCENTER_KEY', '""'
|
buildConfigField 'String', 'APPCENTER_KEY', '""'
|
||||||
}
|
}
|
||||||
beta {
|
beta {
|
||||||
initWith release
|
minifyEnabled false
|
||||||
buildConfigField 'String', 'APPCENTER_KEY', '""'
|
buildConfigField 'String', 'APPCENTER_KEY', '""'
|
||||||
}
|
}
|
||||||
release {
|
|
||||||
buildConfigField 'String', 'APPCENTER_KEY', '""'
|
|
||||||
minifyEnabled true
|
|
||||||
proguardFile 'proguard-rules.pro'
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
compileOptions {
|
compileOptions {
|
||||||
@@ -72,6 +79,9 @@ android {
|
|||||||
}
|
}
|
||||||
namespace 'ru.vtosters.lite'
|
namespace 'ru.vtosters.lite'
|
||||||
ndkVersion '25.2.9519653'
|
ndkVersion '25.2.9519653'
|
||||||
|
buildFeatures {
|
||||||
|
aidl true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
@@ -79,70 +89,44 @@ dependencies {
|
|||||||
implementation 'com.microsoft.appcenter:appcenter-crashes:5.0.1'
|
implementation 'com.microsoft.appcenter:appcenter-crashes:5.0.1'
|
||||||
coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:2.0.3'
|
coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:2.0.3'
|
||||||
implementation 'net.sourceforge.streamsupport:streamsupport-minifuture:1.7.4'
|
implementation 'net.sourceforge.streamsupport:streamsupport-minifuture:1.7.4'
|
||||||
|
implementation 'com.google.guava:guava:23.3-android'
|
||||||
|
|
||||||
implementation fileTree(dir: 'libs', include: ['*.aar'])
|
implementation fileTree(dir: 'libs', include: ['*.aar'])
|
||||||
compileOnly fileTree(dir: 'libs', include: ['*.jar'])
|
compileOnly fileTree(dir: 'libs', include: ['*.jar'])
|
||||||
implementation 'com.google.guava:guava:23.3-android'
|
|
||||||
}
|
}
|
||||||
|
|
||||||
task generateBuildTasks() {
|
task generateBuildTasks() {
|
||||||
android.applicationVariants.all { variant ->
|
android.applicationVariants.all { variant ->
|
||||||
variant.outputs.each { output ->
|
variant.outputs.each { output ->
|
||||||
def buildType = output.name.toString().capitalize()
|
def buildType = output.name.toString().capitalize()
|
||||||
def lowerBuildType = buildType.toLowerCase()
|
if(buildType=="Base")return
|
||||||
task "exportDex$buildType"() {
|
task "exportDex$buildType"() {
|
||||||
dependsOn('assemble' + buildType)
|
dependsOn('assemble' + buildType)
|
||||||
doLast {
|
doLast {
|
||||||
try {
|
try {
|
||||||
var z = ""
|
def suffix=buildType.toLowerCase()
|
||||||
if (lowerBuildType != "debug") {
|
String apkPath=projectDir.getAbsolutePath()+"/build/outputs/apk/$suffix/app-$suffix"
|
||||||
z = "-unsigned"
|
def apk=new File(apkPath+"-unsigned.apk")
|
||||||
}
|
if(!apk.exists())apk=new File(apkPath+".apk")
|
||||||
|
def zip=new ZipFile(apk)
|
||||||
File moduleDir = projectDir
|
def entries=zip.entries()
|
||||||
ZipInputStream inputStream = new ZipInputStream(new FileInputStream(moduleDir.getAbsolutePath() + "/build/outputs/apk/$lowerBuildType/app-$lowerBuildType${z}.apk"))
|
def dexCounter=dexes
|
||||||
ZipFile file = new ZipFile(moduleDir.getAbsolutePath() + "/build/outputs/apk/$lowerBuildType/app-$lowerBuildType${z}.apk");
|
while(entries.hasMoreElements())
|
||||||
ZipEntry entry
|
{
|
||||||
while ((entry = inputStream.nextEntry) != null) {
|
def entry=entries.nextElement()
|
||||||
if (entry.getName().equals("classes.dex")) {
|
String filename
|
||||||
print('classes.dex found!')
|
if(entry.name.matches("^classes(?:(?=\\d)2|)\\.dex\$"))filename="classes${++dexCounter}.dex"
|
||||||
|
else if(entry.name=="assets/version.properties")filename="version.properties"
|
||||||
FileOutputStream outputStream = new FileOutputStream(new File(moduleDir.getAbsoluteFile(), "classes6.dex"))
|
else continue
|
||||||
|
println("Exporting "+entry.name)
|
||||||
byte[] buffer = new byte[1024]
|
def tmpFile=new File(projectDir,filename)
|
||||||
int len = 0
|
def is=zip.getInputStream(entry)
|
||||||
while ((len = inputStream.read(buffer)) > 0) {
|
def fos=new FileOutputStream(tmpFile)
|
||||||
outputStream.write(buffer, 0, len)
|
def buff=new byte[0x800]
|
||||||
}
|
int len
|
||||||
outputStream.close()
|
while((len=is.read(buff))>0)fos.write(buff,0,len)
|
||||||
}
|
is.close()
|
||||||
if (entry.getName().equals("classes2.dex")) {
|
fos.close()
|
||||||
print('\nclasses2.dex found!')
|
|
||||||
|
|
||||||
FileOutputStream outputStream = new FileOutputStream(new File(moduleDir.getAbsoluteFile(), "classes7.dex"))
|
|
||||||
|
|
||||||
byte[] buffer = new byte[1024]
|
|
||||||
int len = 0
|
|
||||||
while ((len = inputStream.read(buffer)) > 0) {
|
|
||||||
outputStream.write(buffer, 0, len)
|
|
||||||
}
|
|
||||||
outputStream.close()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (ZipEntry e : Collections.list(file.entries())) {
|
|
||||||
if (e.getName().endsWith("assets/version.properties")) {
|
|
||||||
var is = file.getInputStream(e)
|
|
||||||
FileOutputStream outputStream = new FileOutputStream(new File(moduleDir.getAbsoluteFile(), "version.properties"))
|
|
||||||
|
|
||||||
byte[] buffer = new byte[1024]
|
|
||||||
int len = 0
|
|
||||||
while ((len = is.read(buffer)) > 0) {
|
|
||||||
outputStream.write(buffer, 0, len)
|
|
||||||
}
|
|
||||||
outputStream.close()
|
|
||||||
|
|
||||||
print('\nversion.properties found!')
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
e.printStackTrace()
|
e.printStackTrace()
|
||||||
@@ -152,17 +136,16 @@ task generateBuildTasks() {
|
|||||||
task "prepareDexForMerge$buildType"(type: Copy) {
|
task "prepareDexForMerge$buildType"(type: Copy) {
|
||||||
dependsOn('exportDex' + buildType)
|
dependsOn('exportDex' + buildType)
|
||||||
// Remove comment for native lib build
|
// Remove comment for native lib build
|
||||||
dependsOn('cargoBuild')
|
//dependsOn('cargoBuild')
|
||||||
into smaliFolder.toString()
|
into smaliFolder.toString()
|
||||||
from(projectDir) {
|
from(projectDir) {
|
||||||
include 'classes6.dex'
|
into '../smali'
|
||||||
include 'classes7.dex'
|
include "classes*.dex"
|
||||||
}
|
}
|
||||||
from(projectDir) {
|
from(projectDir) {
|
||||||
include 'version.properties'
|
include 'version.properties'
|
||||||
into 'assets'
|
into 'assets'
|
||||||
}
|
}
|
||||||
// Remove comment for native lib build
|
|
||||||
from('../native-effects/target/aarch64-linux-android/release'){
|
from('../native-effects/target/aarch64-linux-android/release'){
|
||||||
include 'libnative_effects.so'
|
include 'libnative_effects.so'
|
||||||
into 'lib/arm64-v8a'
|
into 'lib/arm64-v8a'
|
||||||
@@ -171,15 +154,16 @@ task generateBuildTasks() {
|
|||||||
include 'libnative_effects.so'
|
include 'libnative_effects.so'
|
||||||
into 'lib/armeabi-v7a'
|
into 'lib/armeabi-v7a'
|
||||||
}
|
}
|
||||||
doLast {
|
}
|
||||||
new File(projectDir, "classes6.dex").delete()
|
task "cleanTemporaryFiles$buildType"(type:Delete)
|
||||||
new File(projectDir, "classes7.dex").delete()
|
{
|
||||||
new File(projectDir, "version.properties").delete()
|
delete fileTree(dir:projectDir,include:["*.dex","version.properties"])
|
||||||
}
|
delete fileTree(dir:smaliFolder,include:['*.dex',"assets/version.properties"])
|
||||||
}
|
}
|
||||||
task "buildVTL$buildType"(type: Exec) {
|
task "buildVTL$buildType"(type: Exec) {
|
||||||
dependsOn('prepareDexForMerge' + buildType)
|
dependsOn('prepareDexForMerge' + buildType)
|
||||||
workingDir(projectDir.parentFile)
|
workingDir(projectDir.parentFile)
|
||||||
|
finalizedBy "cleanTemporaryFiles$buildType"
|
||||||
if (Os.isFamily("unix") || Os.isFamily("mac")) {
|
if (Os.isFamily("unix") || Os.isFamily("mac")) {
|
||||||
commandLine 'bash', '-c', './scripts/build.sh'
|
commandLine 'bash', '-c', './scripts/build.sh'
|
||||||
} else {
|
} else {
|
||||||
@@ -207,7 +191,6 @@ task generateBuildTasks() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
task generateRjava(type: Exec) {
|
task generateRjava(type: Exec) {
|
||||||
workingDir(projectDir.parentFile)
|
workingDir(projectDir.parentFile)
|
||||||
if (Os.isFamily("unix") || Os.isFamily("mac"))
|
if (Os.isFamily("unix") || Os.isFamily("mac"))
|
||||||
|
|||||||
@@ -130,9 +130,9 @@ public class BinaryResourceValue implements SerializableResource {
|
|||||||
*/
|
*/
|
||||||
public static final int SIZE = 8;
|
public static final int SIZE = 8;
|
||||||
|
|
||||||
private final int size;
|
public int size;
|
||||||
private final Type type;
|
public Type type;
|
||||||
private final int data;
|
public int data;
|
||||||
|
|
||||||
public static BinaryResourceValue create(ByteBuffer buffer) {
|
public static BinaryResourceValue create(ByteBuffer buffer) {
|
||||||
int size = (buffer.getShort() & 0xFFFF);
|
int size = (buffer.getShort() & 0xFFFF);
|
||||||
|
|||||||
@@ -19658,6 +19658,12 @@ public final class R {
|
|||||||
public static final int vkx_integration_enabled_info = 0x7f12188a; // 2131892362
|
public static final int vkx_integration_enabled_info = 0x7f12188a; // 2131892362
|
||||||
public static final int whitelisted_ad_groups_stories_title = 0x7f12188b; // 2131892363
|
public static final int whitelisted_ad_groups_stories_title = 0x7f12188b; // 2131892363
|
||||||
public static final int writebar_ios_title = 0x7f12188c; // 2131892364
|
public static final int writebar_ios_title = 0x7f12188c; // 2131892364
|
||||||
|
public static final int cache_size = 0x7f12188d; // 2131892365
|
||||||
|
public static final int cache_size_summ = 0x7f12188e; // 2131892366
|
||||||
|
public static final int clear_all_cache = 0x7f12188f; // 2131892367
|
||||||
|
public static final int invalidate_theme_cache_each_update_title = 0x7f121890; // 2131892368
|
||||||
|
public static final int invertFilters = 0x7f121891; // 2131892369
|
||||||
|
public static final int invertFilters_summ = 0x7f121892; // 2131892370
|
||||||
}
|
}
|
||||||
|
|
||||||
public static final class style {
|
public static final class style {
|
||||||
|
|||||||
@@ -19,11 +19,8 @@ import static ru.vtosters.hooks.other.Preferences.isValidSignature;
|
|||||||
|
|
||||||
|
|
||||||
public class GcmHook {
|
public class GcmHook {
|
||||||
|
|
||||||
private static final String agent = String.format("Android-GCM/1.5 (%s %s)", Build.MODEL, Build.MODEL);
|
private static final String agent = String.format("Android-GCM/1.5 (%s %s)", Build.MODEL, Build.MODEL);
|
||||||
|
|
||||||
private static KeyPair pair;
|
private static KeyPair pair;
|
||||||
|
|
||||||
private static int rid = 0;
|
private static int rid = 0;
|
||||||
|
|
||||||
static {
|
static {
|
||||||
@@ -35,15 +32,15 @@ public class GcmHook {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static String requestToken(String orig) {
|
public static String requestToken(String orig) {
|
||||||
return "yssp9o9p9pamz5t-nvmq8spgwtin3e0==";
|
return isValidSignature() ? "yssp9o9p9pamz5t-nvmq8spgwtin3e0==" : requestToken();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String requestToken() {
|
public static String requestToken() {
|
||||||
String xappide;
|
|
||||||
try {
|
try {
|
||||||
String aid = getRandomAid();
|
String aid = getRandomAid();
|
||||||
String pub2 = genNewKey();
|
String pub2 = genNewKey();
|
||||||
String sig = getSig(pub2);
|
String sig = getSig(pub2);
|
||||||
|
String xappide;
|
||||||
try {
|
try {
|
||||||
byte[] bytes = MessageDigest.getInstance("SHA1").digest(pair.getPublic().getEncoded());
|
byte[] bytes = MessageDigest.getInstance("SHA1").digest(pair.getPublic().getEncoded());
|
||||||
bytes[0] = (byte) (((bytes[0] & 15) + 112) & 255);
|
bytes[0] = (byte) (((bytes[0] & 15) + 112) & 255);
|
||||||
@@ -200,7 +197,6 @@ public class GcmHook {
|
|||||||
}).getBytes(StandardCharsets.UTF_8));
|
}).getBytes(StandardCharsets.UTF_8));
|
||||||
return Base64.encodeToString(sign.sign(), 0);
|
return Base64.encodeToString(sign.sign(), 0);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
e.printStackTrace();
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -46,7 +46,10 @@ public class MainActivityInjector {
|
|||||||
NotificationChannels.createChannels();
|
NotificationChannels.createChannels();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Preferences.isNewBuild() && !ThemesUtils.isMonetTheme() && ThemesManager.canApplyCustomAccent() && ThemesUtils.useNewColorEngine()) {
|
if (Preferences.isNewBuild()
|
||||||
|
&&!ThemesUtils.isMonetTheme()
|
||||||
|
&&ThemesManager.canApplyCustomAccent())
|
||||||
|
{
|
||||||
Preferences.updateBuildNumber();
|
Preferences.updateBuildNumber();
|
||||||
updateBinsAndTmpArchive(activity);
|
updateBinsAndTmpArchive(activity);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,7 +6,9 @@ import androidx.recyclerview.widget.RecyclerView;
|
|||||||
import com.vk.core.preference.Preference;
|
import com.vk.core.preference.Preference;
|
||||||
import com.vk.discover.DiscoverItemDecorator;
|
import com.vk.discover.DiscoverItemDecorator;
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
import static java.lang.Long.MAX_VALUE;
|
import static java.lang.Long.MAX_VALUE;
|
||||||
import static ru.vtosters.hooks.other.Preferences.*;
|
import static ru.vtosters.hooks.other.Preferences.*;
|
||||||
|
|||||||
@@ -130,6 +130,8 @@ public class PhotoViewer {
|
|||||||
.setItems(items, (di, i) -> openUrl(SearchEngine.values()[i].buildSearchUrl(url)))
|
.setItems(items, (di, i) -> openUrl(SearchEngine.values()[i].buildSearchUrl(url)))
|
||||||
.show();
|
.show();
|
||||||
} else {
|
} else {
|
||||||
|
// index correction for old versions with numeration "1-x"
|
||||||
|
if (selectedEngine >= SearchEngine.values().length) SearchEngine.setDefaultSearchEngine(--selectedEngine);
|
||||||
openUrl(SearchEngine.values()[selectedEngine].buildSearchUrl(url));
|
openUrl(SearchEngine.values()[selectedEngine].buildSearchUrl(url));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,9 +1,7 @@
|
|||||||
package ru.vtosters.hooks;
|
package ru.vtosters.hooks;
|
||||||
|
|
||||||
import androidx.core.util.Pair;
|
|
||||||
import org.json.JSONException;
|
import org.json.JSONException;
|
||||||
import org.json.JSONObject;
|
import org.json.JSONObject;
|
||||||
import ru.vtosters.lite.utils.RenameTool;
|
|
||||||
|
|
||||||
public class RenameHook {
|
public class RenameHook {
|
||||||
public static void injectIntoJson(JSONObject obj) throws JSONException {
|
public static void injectIntoJson(JSONObject obj) throws JSONException {
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ public class VKUIHook {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private static void applyVKUIStyles(WebView webView) {
|
private static void applyVKUIStyles(WebView webView) {
|
||||||
if (getBoolValue("VKUI_INJ", true)) {
|
if (getBoolValue("VKUI_INJ", true) && !webView.getUrl().contains("static.vk.com/memories")) {
|
||||||
if (!WebViewColoringUtils.isLoaded) {
|
if (!WebViewColoringUtils.isLoaded) {
|
||||||
WebViewColoringUtils.load();
|
WebViewColoringUtils.load();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -292,12 +292,16 @@ public class Preferences {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static boolean isNewBuild() {
|
public static boolean isNewBuild() {
|
||||||
try {
|
if(Preferences.getBoolValue("invalidate_theme_cache_each_update",true))
|
||||||
return getPreferences().getLong("setupTime", 0L) != AndroidUtils.getGlobalContext().getPackageManager().getPackageInfo(AndroidUtils.getPackageName(), 0).lastUpdateTime;
|
try {
|
||||||
} catch (PackageManager.NameNotFoundException e) {
|
return AndroidUtils.getGlobalContext()
|
||||||
e.printStackTrace();
|
.getPackageManager()
|
||||||
return false;
|
.getPackageInfo(AndroidUtils.getPackageName(), 0)
|
||||||
}
|
.lastUpdateTime != getPreferences().getLong("setupTime", 0L);
|
||||||
|
} catch (PackageManager.NameNotFoundException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void updateBuildNumber() {
|
public static void updateBuildNumber() {
|
||||||
@@ -330,7 +334,7 @@ public class Preferences {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static long getSizeForDelete() {
|
public static long getSizeForDelete() {
|
||||||
return switch (Preferences.getPreferences().getString("clearcache", "")) {
|
return switch (Preferences.getPreferences().getString("autoclearcache", "")) {
|
||||||
case "100mb" -> 104857600L;
|
case "100mb" -> 104857600L;
|
||||||
case "500mb" -> 524288000L;
|
case "500mb" -> 524288000L;
|
||||||
case "1gb" -> 1073741824L;
|
case "1gb" -> 1073741824L;
|
||||||
|
|||||||
@@ -16,19 +16,19 @@ import android.webkit.WebView;
|
|||||||
import android.widget.EditText;
|
import android.widget.EditText;
|
||||||
import android.widget.ImageView;
|
import android.widget.ImageView;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
import androidx.appcompat.app.AppCompatDelegate;
|
|
||||||
import androidx.core.content.ContextCompat;
|
import androidx.core.content.ContextCompat;
|
||||||
import androidx.core.graphics.ColorUtils;
|
import androidx.core.graphics.ColorUtils;
|
||||||
import com.vk.articles.preload.WebCachePreloader;
|
import com.vk.articles.preload.WebCachePreloader;
|
||||||
import com.vk.core.drawable.RecoloredDrawable;
|
import com.vk.core.drawable.RecoloredDrawable;
|
||||||
import com.vk.core.preference.Preference;
|
|
||||||
import com.vk.core.ui.themes.MilkshakeHelper;
|
import com.vk.core.ui.themes.MilkshakeHelper;
|
||||||
import com.vk.core.ui.themes.VKTheme;
|
import com.vk.core.ui.themes.VKTheme;
|
||||||
import com.vk.core.ui.themes.VKThemeHelper;
|
import com.vk.core.ui.themes.VKThemeHelper;
|
||||||
import com.vtosters.lite.R;
|
import com.vtosters.lite.R;
|
||||||
import com.vtosters.lite.data.ThemeTracker;
|
import com.vtosters.lite.data.ThemeTracker;
|
||||||
import ru.vtosters.lite.deviceinfo.OEMDetector;
|
import ru.vtosters.lite.deviceinfo.OEMDetector;
|
||||||
|
import ru.vtosters.lite.themes.ThemesCore;
|
||||||
import ru.vtosters.lite.themes.ThemesHacks;
|
import ru.vtosters.lite.themes.ThemesHacks;
|
||||||
|
import ru.vtosters.lite.themes.ThemesManager;
|
||||||
import ru.vtosters.lite.ui.wallpapers.WallpapersHooks;
|
import ru.vtosters.lite.ui.wallpapers.WallpapersHooks;
|
||||||
import ru.vtosters.lite.utils.LifecycleUtils;
|
import ru.vtosters.lite.utils.LifecycleUtils;
|
||||||
import ru.vtosters.lite.utils.WebViewColoringUtils;
|
import ru.vtosters.lite.utils.WebViewColoringUtils;
|
||||||
@@ -47,22 +47,10 @@ public class ThemesUtils {
|
|||||||
}
|
}
|
||||||
} // Apply VKTheme and ImTheme (hard applying without dynamic theme changing)
|
} // Apply VKTheme and ImTheme (hard applying without dynamic theme changing)
|
||||||
|
|
||||||
public static boolean isCustomAccentEnabled() {
|
|
||||||
return ThemesUtils.isMonetTheme() || !useNewColorEngine();
|
|
||||||
}
|
|
||||||
|
|
||||||
public static ColorStateList getAccenedColorStateList() {
|
public static ColorStateList getAccenedColorStateList() {
|
||||||
return ColorStateList.valueOf(getAccentColor());
|
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, Boolean restartActivity) {
|
public static void setTheme(VKTheme theme, Activity activity, Boolean restartActivity) {
|
||||||
setThemeFL(theme, activity, getCenterScreenCoords(), restartActivity);
|
setThemeFL(theme, activity, getCenterScreenCoords(), restartActivity);
|
||||||
} // apply changed theme
|
} // apply changed theme
|
||||||
@@ -72,6 +60,7 @@ public class ThemesUtils {
|
|||||||
activity = LifecycleUtils.getCurrentActivity();
|
activity = LifecycleUtils.getCurrentActivity();
|
||||||
}
|
}
|
||||||
VKThemeHelper.theme(theme, activity, fl);
|
VKThemeHelper.theme(theme, activity, fl);
|
||||||
|
if (isMonetTheme() || ThemesManager.canApplyCustomAccent()) ThemesCore.clear();
|
||||||
if (restartActivity) activity.recreate();
|
if (restartActivity) activity.recreate();
|
||||||
ThemeTracker.a();
|
ThemeTracker.a();
|
||||||
WebViewColoringUtils.isLoaded = false;
|
WebViewColoringUtils.isLoaded = false;
|
||||||
@@ -91,13 +80,8 @@ public class ThemesUtils {
|
|||||||
return getBoolValue("amoledtheme", false);
|
return getBoolValue("amoledtheme", false);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean useNewColorEngine() {
|
|
||||||
return getBoolValue("useNewColorEngine", false);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static int getAccentColor() {
|
public static int getAccentColor() {
|
||||||
var color = Preferences.getPreferences().getInt("accent_color", getColorFromAttr(R.attr.accent));
|
return getColorFromAttr(R.attr.accent);
|
||||||
return color == 0 || useNewColorEngine() || isMonetTheme() ? getColorFromAttr(R.attr.accent) : color;
|
|
||||||
} // Color accent
|
} // Color accent
|
||||||
|
|
||||||
//region Used for migrating accent color to new version
|
//region Used for migrating accent color to new version
|
||||||
@@ -261,14 +245,6 @@ public class ThemesUtils {
|
|||||||
return Build.VERSION.SDK_INT >= Build.VERSION_CODES.O ? isDarkTheme() ? View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR : 0 : 0;
|
return Build.VERSION.SDK_INT >= Build.VERSION_CODES.O ? isDarkTheme() ? View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR : 0 : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static int getStockAccent() {
|
|
||||||
if (isMilkshake()) {
|
|
||||||
return isDarkTheme() ? Color.parseColor("#71aaeb") : Color.parseColor("#3f8ae0");
|
|
||||||
} else {
|
|
||||||
return isDarkTheme() ? Color.parseColor("#71aaeb") : Color.parseColor("#528bcc");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static int getDarkThemeRes() {
|
public static int getDarkThemeRes() {
|
||||||
if (isMonetTheme()) {
|
if (isMonetTheme()) {
|
||||||
if (isAmoledTheme()) {
|
if (isAmoledTheme()) {
|
||||||
@@ -323,7 +299,7 @@ public class ThemesUtils {
|
|||||||
} // Recolor drawable to accent color
|
} // Recolor drawable to accent color
|
||||||
|
|
||||||
public static Drawable recolorToolbarDrawable(Drawable drawable) {
|
public static Drawable recolorToolbarDrawable(Drawable drawable) {
|
||||||
if (!ThemesUtils.isCustomAccentEnabled()) return drawable;
|
if (!ThemesUtils.isMonetTheme()) return drawable;
|
||||||
if (drawable == null) return null;
|
if (drawable == null) return null;
|
||||||
return new RecoloredDrawable(drawable, (ThemesUtils.isMilkshake() && !ThemesUtils.isDarkTheme()) ? ThemesUtils.getAccentColor() : ThemesUtils.getHeaderText());
|
return new RecoloredDrawable(drawable, (ThemesUtils.isMilkshake() && !ThemesUtils.isDarkTheme()) ? ThemesUtils.getAccentColor() : ThemesUtils.getHeaderText());
|
||||||
}
|
}
|
||||||
@@ -408,15 +384,11 @@ public class ThemesUtils {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static int getNavigationHeight(int Default) {
|
public static int getNavigationHeight(int Default) {
|
||||||
int VKME = R.dimen.design_bottom_sheet_peek_height_min;
|
return vkme() ? R.dimen.design_bottom_sheet_peek_height_min : Default;
|
||||||
|
|
||||||
return vkme() ? VKME : Default;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static int getNavigationWidth(int Default) {
|
public static int getNavigationWidth(int Default) {
|
||||||
int VKME = R.dimen.app_minimumsize_h;
|
return vkme() ? R.dimen.app_minimumsize_h : Default;
|
||||||
|
|
||||||
return vkme() ? VKME : Default;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static ColorStateList getCSTDock() {
|
public static ColorStateList getCSTDock() {
|
||||||
@@ -427,12 +399,8 @@ public class ThemesUtils {
|
|||||||
},
|
},
|
||||||
new int[]{
|
new int[]{
|
||||||
dockbar_accent() ? getAccentColor() : (isDarkTheme() ? getResources().getColor(R.color.white) : getResources().getColor(R.color.gray_700)),
|
dockbar_accent() ? getAccentColor() : (isDarkTheme() ? getResources().getColor(R.color.white) : getResources().getColor(R.color.gray_700)),
|
||||||
isDarkTheme() ? getResources().getColor(R.color.gray_500) : getResources().getColor(R.color.vk_steel_gray_300)
|
getColorFromAttr(R.attr.tabbar_inactive_icon)
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void getCurrentThemeID(VKTheme paramVKTheme) {
|
|
||||||
Preference.b("vk_theme_helper", "current_theme", paramVKTheme.getId());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
package ru.vtosters.hooks.ssfs;
|
package ru.vtosters.hooks.ssfs;
|
||||||
|
|
||||||
import com.vk.core.dialogs.alert.VkAlertDialog;
|
import com.vk.core.dialogs.alert.VkAlertDialog;
|
||||||
import org.json.JSONException;
|
|
||||||
import org.json.JSONObject;
|
import org.json.JSONObject;
|
||||||
import ru.vtosters.hooks.other.Preferences;
|
import ru.vtosters.hooks.other.Preferences;
|
||||||
import ru.vtosters.lite.ssfs.ImBanner;
|
import ru.vtosters.lite.ssfs.ImBanner;
|
||||||
|
|||||||
@@ -4,8 +4,8 @@ import android.text.TextUtils;
|
|||||||
|
|
||||||
public class TransportStream {
|
public class TransportStream {
|
||||||
|
|
||||||
private String mKeyUri;
|
|
||||||
private final String mMediaSegmentUri;
|
private final String mMediaSegmentUri;
|
||||||
|
private String mKeyUri;
|
||||||
private String mMediaSegmentName;
|
private String mMediaSegmentName;
|
||||||
|
|
||||||
public TransportStream(String baseURI, String mediaSegmentName) {
|
public TransportStream(String baseURI, String mediaSegmentName) {
|
||||||
|
|||||||
@@ -15,10 +15,9 @@ public class VKM3UParser {
|
|||||||
//Playlist types
|
//Playlist types
|
||||||
static public int PLAYLIST_TYPE_VOD = 0;
|
static public int PLAYLIST_TYPE_VOD = 0;
|
||||||
static public int PLAYLIST_TYPE_EVENT = 1;
|
static public int PLAYLIST_TYPE_EVENT = 1;
|
||||||
|
private final String mData;
|
||||||
//region Extended M3U global extensions
|
//region Extended M3U global extensions
|
||||||
public List<TransportStream> mTransportStreams = new ArrayList<>();
|
public List<TransportStream> mTransportStreams = new ArrayList<>();
|
||||||
private final String mData;
|
|
||||||
/**
|
/**
|
||||||
* @see <a href="https://datatracker.ietf.org/doc/html/rfc8216#section-4.3.1.2">EXT-X-VERSION</a>
|
* @see <a href="https://datatracker.ietf.org/doc/html/rfc8216#section-4.3.1.2">EXT-X-VERSION</a>
|
||||||
**/
|
**/
|
||||||
|
|||||||
@@ -19,8 +19,8 @@ import ru.vtosters.lite.utils.AndroidUtils;
|
|||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
|
||||||
import static ru.vtosters.hooks.DateHook.getLocale;
|
import static ru.vtosters.hooks.DateHook.getLocale;
|
||||||
import static ru.vtosters.hooks.other.Preferences.getBoolValue;
|
|
||||||
import static ru.vtosters.hooks.GroupsCatalogInjector.injectIntoCatalog;
|
import static ru.vtosters.hooks.GroupsCatalogInjector.injectIntoCatalog;
|
||||||
|
import static ru.vtosters.hooks.other.Preferences.getBoolValue;
|
||||||
import static ru.vtosters.lite.music.cache.helpers.PlaylistHelper.*;
|
import static ru.vtosters.lite.music.cache.helpers.PlaylistHelper.*;
|
||||||
import static ru.vtosters.lite.proxy.ProxyUtils.getApi;
|
import static ru.vtosters.lite.proxy.ProxyUtils.getApi;
|
||||||
import static ru.vtosters.lite.utils.AccountManagerUtils.getUserId;
|
import static ru.vtosters.lite.utils.AccountManagerUtils.getUserId;
|
||||||
@@ -30,79 +30,22 @@ public class CatalogJsonInjector {
|
|||||||
|
|
||||||
public static JSONObject music(JSONObject json) throws JSONException {
|
public static JSONObject music(JSONObject json) throws JSONException {
|
||||||
var catalog = json.optJSONObject("catalog");
|
var catalog = json.optJSONObject("catalog");
|
||||||
|
var oldItems = catalog != null ? catalog.optJSONArray("sections") : null;
|
||||||
JSONArray oldItems = null;
|
|
||||||
|
|
||||||
if (catalog != null) {
|
|
||||||
oldItems = catalog.optJSONArray("sections");
|
|
||||||
}
|
|
||||||
|
|
||||||
var useOldAppVer = getBoolValue("useOldAppVer", false);
|
var useOldAppVer = getBoolValue("useOldAppVer", false);
|
||||||
var isUsersCatalog = oldItems.optJSONObject(0).optString("url").equals("https://vk.com/audios" + getUserId() + "?section=" + (useOldAppVer ? "all" : "general"));
|
var isUsersCatalog = oldItems.optJSONObject(0).optString("url").equals("https://vk.com/audios" + getUserId() + "?section=" + (useOldAppVer ? "all" : "general"));
|
||||||
|
var blocks = oldItems.optJSONObject(0).optJSONArray("blocks");
|
||||||
|
|
||||||
if (isUsersCatalog) {
|
if (isUsersCatalog && blocks != null) {
|
||||||
var blocks = oldItems.optJSONObject(0).optJSONArray("blocks");
|
|
||||||
|
|
||||||
if (!useOldAppVer) {
|
if (!useOldAppVer) {
|
||||||
fixDailyMix(blocks);
|
fixDailyMix(blocks);
|
||||||
if (blocks != null) {
|
|
||||||
for (int i = 0; i < blocks.length(); i++) {
|
|
||||||
var block = blocks.optJSONObject(i);
|
|
||||||
var layout = block.optJSONObject("layout");
|
|
||||||
if (layout != null) {
|
|
||||||
var name = layout.optString("name");
|
|
||||||
if (name.equals("header_extended")) {
|
|
||||||
if (layout.has("top_title")) blocks.remove(i);
|
|
||||||
try {
|
|
||||||
layout.put("name", "header");
|
|
||||||
} catch (JSONException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var playlists = fetchCatalogId("https://vk.com/audio?section=my_playlists");
|
removeUnsupportedLayouts(blocks);
|
||||||
if (playlists != null) {
|
|
||||||
var catalogarr = playlists.optJSONObject("catalog").optJSONArray("sections").optJSONObject(0);
|
|
||||||
|
|
||||||
var title = catalogarr.optString("title");
|
fetchCatalogId("https://vk.com/audio?section=my_playlists", oldItems);
|
||||||
var id = catalogarr.optString("id");
|
|
||||||
var url = catalogarr.optString("url");
|
|
||||||
|
|
||||||
Log.d("VKMusic", "Added " + title + " in music sections");
|
fetchCatalogId("https://vk.com/audio?section=albums", oldItems);
|
||||||
|
|
||||||
oldItems.put(new JSONObject().put("id", id).put("title", title).put("url", url));
|
setDefaultAudioPage(oldItems, catalog);
|
||||||
}
|
|
||||||
|
|
||||||
var albums = fetchCatalogId("https://vk.com/audio?section=albums");
|
|
||||||
if (albums != null) {
|
|
||||||
var catalogarr = albums.optJSONObject("catalog").optJSONArray("sections").optJSONObject(0);
|
|
||||||
|
|
||||||
var title = catalogarr.optString("title");
|
|
||||||
var id = catalogarr.optString("id");
|
|
||||||
var url = catalogarr.optString("url");
|
|
||||||
|
|
||||||
Log.d("VKMusic", "Added " + title + " in music sections");
|
|
||||||
|
|
||||||
oldItems.put(new JSONObject().put("id", id).put("title", title).put("url", url));
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int i = 0; i < oldItems.length(); i++) {
|
|
||||||
var item = oldItems.optJSONObject(i);
|
|
||||||
var title = item.optString("title");
|
|
||||||
var id = item.optString("id");
|
|
||||||
var url = item.optString("url");
|
|
||||||
var value = Preferences.getString("musicdefcatalog");
|
|
||||||
|
|
||||||
Log.d("VKMusic", "title: " + title + " id: " + id + " url: " + url + " value: " + value);
|
|
||||||
|
|
||||||
if (url.contains(value) && !value.isEmpty()) {
|
|
||||||
catalog.put("default_section", id);
|
|
||||||
Log.d("VKMusic", "Added " + title + " as default music section");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (CacheDatabaseDelegate.hasTracks() && !LibVKXClient.isIntegrationEnabled()) { // inj in playlist list
|
if (CacheDatabaseDelegate.hasTracks() && !LibVKXClient.isIntegrationEnabled()) { // inj in playlist list
|
||||||
@@ -112,15 +55,11 @@ public class CatalogJsonInjector {
|
|||||||
json.put("playlists", new JSONArray().put(getPlaylist()));
|
json.put("playlists", new JSONArray().put(getPlaylist()));
|
||||||
Log.d("catalogInjector", "added new pl");
|
Log.d("catalogInjector", "added new pl");
|
||||||
} else {
|
} else {
|
||||||
try {
|
json.optJSONArray("playlists").put(getPlaylist());
|
||||||
json.optJSONArray("playlists").put(getPlaylist());
|
Log.d("catalogInjector", "added to exist pl");
|
||||||
Log.d("catalogInjector", "added to exist pl");
|
|
||||||
} catch (Exception e) {
|
|
||||||
Log.d("catalogInjector", e.toString());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (blocks != null && (!useOldAppVer || noPlaylists)) {
|
if (!useOldAppVer || noPlaylists) {
|
||||||
var newBlocks = new JSONArray();
|
var newBlocks = new JSONArray();
|
||||||
|
|
||||||
newBlocks
|
newBlocks
|
||||||
@@ -155,6 +94,7 @@ public class CatalogJsonInjector {
|
|||||||
if (!isUsersCatalog || !CacheDatabaseDelegate.hasTracks() || LibVKXClient.isIntegrationEnabled()) {
|
if (!isUsersCatalog || !CacheDatabaseDelegate.hasTracks() || LibVKXClient.isIntegrationEnabled()) {
|
||||||
return; // early return if not users catalog or no tracks or integration enabled
|
return; // early return if not users catalog or no tracks or integration enabled
|
||||||
}
|
}
|
||||||
|
|
||||||
var noPlaylists = !json.has("playlists");
|
var noPlaylists = !json.has("playlists");
|
||||||
|
|
||||||
if (noPlaylists) {
|
if (noPlaylists) {
|
||||||
@@ -169,7 +109,7 @@ public class CatalogJsonInjector {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!useOldAppVer || noPlaylists) {
|
if (!useOldAppVer && !noPlaylists) {
|
||||||
var newBlocks = new JSONArray();
|
var newBlocks = new JSONArray();
|
||||||
|
|
||||||
newBlocks
|
newBlocks
|
||||||
@@ -278,9 +218,38 @@ public class CatalogJsonInjector {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static JSONObject fetchCatalogId(String section) {
|
private static void removeUnsupportedLayouts(JSONArray blocks) throws JSONException {
|
||||||
if (section.isEmpty()) return null;
|
for (int i = 0; i < blocks.length(); i++) {
|
||||||
|
var block = blocks.optJSONObject(i);
|
||||||
|
var layout = block.optJSONObject("layout");
|
||||||
|
if (layout != null) {
|
||||||
|
var name = layout.optString("name");
|
||||||
|
if (name.equals("header_extended")) {
|
||||||
|
if (layout.has("top_title")) blocks.remove(i);
|
||||||
|
layout.put("name", "header");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void setDefaultAudioPage(JSONArray jsonArray, JSONObject catalog) throws JSONException {
|
||||||
|
for (int i = 0; i < jsonArray.length(); i++) {
|
||||||
|
var item = jsonArray.optJSONObject(i);
|
||||||
|
var title = item.optString("title");
|
||||||
|
var id = item.optString("id");
|
||||||
|
var url = item.optString("url");
|
||||||
|
var value = Preferences.getString("musicdefcatalog");
|
||||||
|
|
||||||
|
Log.d("VKMusic", "title: " + title + " id: " + id + " url: " + url + " value: " + value);
|
||||||
|
|
||||||
|
if (url.contains(value) && !value.isEmpty()) {
|
||||||
|
catalog.put("default_section", id);
|
||||||
|
Log.d("VKMusic", "Added " + title + " as default music section");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void fetchCatalogId(String sectionUrl, JSONArray jsonArray) {
|
||||||
var request = new Request.a()
|
var request = new Request.a()
|
||||||
.b("https://" + getApi() + "/method/" + "catalog.getAudio"
|
.b("https://" + getApi() + "/method/" + "catalog.getAudio"
|
||||||
+ "?v=5.119"
|
+ "?v=5.119"
|
||||||
@@ -291,16 +260,23 @@ public class CatalogJsonInjector {
|
|||||||
+ "&device_id="
|
+ "&device_id="
|
||||||
+ DeviceIdProvider.d(AndroidUtils.getGlobalContext())
|
+ DeviceIdProvider.d(AndroidUtils.getGlobalContext())
|
||||||
+ "&url="
|
+ "&url="
|
||||||
+ section
|
+ sectionUrl
|
||||||
+ "&access_token="
|
+ "&access_token="
|
||||||
+ AccountManagerUtils.getUserToken())
|
+ AccountManagerUtils.getUserToken())
|
||||||
.a(Headers.a("User-Agent", Network.l.c().a(), "Content-Type", "application/x-www-form-urlencoded; charset=utf-8")).a();
|
.a(Headers.a("User-Agent", Network.l.c().a(), "Content-Type", "application/x-www-form-urlencoded; charset=utf-8")).a();
|
||||||
try {
|
try {
|
||||||
return new JSONObject(mClient.a(request).execute().a().g()).getJSONObject("response");
|
var json = new JSONObject(mClient.a(request).execute().a().g()).getJSONObject("response");
|
||||||
|
var catalogarr = json.optJSONObject("catalog").optJSONArray("sections").optJSONObject(0);
|
||||||
|
|
||||||
|
var title = catalogarr.optString("title");
|
||||||
|
var id = catalogarr.optString("id");
|
||||||
|
var url = catalogarr.optString("url");
|
||||||
|
|
||||||
|
Log.d("VKMusic", "Added " + title + " in music sections");
|
||||||
|
|
||||||
|
jsonArray.put(new JSONObject().put("id", id).put("title", title).put("url", url));
|
||||||
} catch (JSONException | IOException e) {
|
} catch (JSONException | IOException e) {
|
||||||
Log.d("VTLMusic", "Error: " + e.getMessage());
|
Log.d("VTLMusic", "Error: " + e.getMessage());
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,15 +11,15 @@ public class ImBanner {
|
|||||||
private static final String TAG = "ImBanner";
|
private static final String TAG = "ImBanner";
|
||||||
|
|
||||||
public static JSONObject convertToBanner(JSONObject original) {
|
public static JSONObject convertToBanner(JSONObject original) {
|
||||||
final String PEER = "peer";
|
String PEER = "peer";
|
||||||
final String ID = "id";
|
String ID = "id";
|
||||||
final String PICTURE = "picture";
|
String PICTURE = "picture";
|
||||||
final String TEXT = "text";
|
String TEXT = "text";
|
||||||
final String LINK = "link";
|
String LINK = "link";
|
||||||
final String LINK_TEXT = "link_text";
|
String LINK_TEXT = "link_text";
|
||||||
final String NAME = "name";
|
String NAME = "name";
|
||||||
final String BUTTONS = "buttons";
|
String BUTTONS = "buttons";
|
||||||
final String ICON = "icon";
|
String ICON = "icon";
|
||||||
|
|
||||||
Optional<JSONObject> user = Optional.ofNullable(original.optJSONObject(PEER));
|
Optional<JSONObject> user = Optional.ofNullable(original.optJSONObject(PEER));
|
||||||
int userId = user.map(u -> u.optInt(ID)).orElse(0);
|
int userId = user.map(u -> u.optInt(ID)).orElse(0);
|
||||||
|
|||||||
@@ -143,8 +143,11 @@ public class ThemesCore {
|
|||||||
themedColors.put(R.attr.im_reply_separator, accentColor);
|
themedColors.put(R.attr.im_reply_separator, accentColor);
|
||||||
themedColors.put(R.attr.im_text_name, accentColor);
|
themedColors.put(R.attr.im_text_name, accentColor);
|
||||||
|
|
||||||
outgoinging_msg = ThemesUtils.lighten(accentColor, 0.76f);
|
float out = ThemesUtils.isMonetTheme() ? 0.85f : 0.76f;
|
||||||
outgoinging_msg_highlight = ThemesUtils.lighten(accentColor, 0.5f);
|
float outhighlight = ThemesUtils.isMonetTheme() ? 0.75f : 0.5f;
|
||||||
|
|
||||||
|
outgoinging_msg = ThemesUtils.lighten(accentColor, out);
|
||||||
|
outgoinging_msg_highlight = ThemesUtils.lighten(accentColor, outhighlight);
|
||||||
|
|
||||||
themedColors.put(R.attr.im_ic_send_msg, accentColor);
|
themedColors.put(R.attr.im_ic_send_msg, accentColor);
|
||||||
themedColors.put(R.attr.im_bubble_wallpaper_outgoing, accentColor);
|
themedColors.put(R.attr.im_bubble_wallpaper_outgoing, accentColor);
|
||||||
@@ -163,26 +166,25 @@ public class ThemesCore {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static boolean hasThemedAttr(Context context, int attrID) {
|
public static boolean hasThemedAttr(Context context, int attrID) {
|
||||||
if (ThemesUtils.isCustomAccentEnabled()) {
|
if (Preferences.getBoolValue("logColors", false)) {
|
||||||
if (Preferences.getBoolValue("logColors", false)) {
|
try {
|
||||||
try {
|
Log.d(TAG, "Requesting color by attr " + context.getResources().getResourceName(attrID));
|
||||||
Log.d(TAG, "Requesting color by attr " + context.getResources().getResourceName(attrID));
|
} catch (Exception ignored) {
|
||||||
} catch (Exception ignored) {
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ThemesUtils.isMonetTheme() || ThemesManager.canApplyCustomAccent()) {
|
||||||
if (isCachedAccents()) {
|
if (isCachedAccents()) {
|
||||||
if (ThemesUtils.isDarkTheme()) {
|
boolean isDark = ThemesUtils.isDarkTheme();
|
||||||
return (themedColors.get(attrID) != 0 && ACCENT_THEME_ONLY_DARK.get(attrID, true) && (
|
boolean isMilkshake = ThemesUtils.isMilkshake();
|
||||||
ThemesUtils.isMilkshake() ?
|
SparseBooleanArray themeOnlyMap = isDark ? ACCENT_THEME_ONLY_DARK : ACCENT_THEME_ONLY_LIGHT;
|
||||||
ACCENT_THEME_ONLY_MILK_DARK.get(attrID, true) :
|
SparseBooleanArray milkshakeMap = isDark ? ACCENT_THEME_ONLY_MILK_DARK : ACCENT_THEME_ONLY_MILK_LIGHT;
|
||||||
ACCENT_THEME_ONLY_NOMILK_DARK.get(attrID, true)));
|
SparseBooleanArray noMilkshakeMap = isDark ? ACCENT_THEME_ONLY_NOMILK_DARK : ACCENT_THEME_ONLY_NOMILK_LIGHT;
|
||||||
} else {
|
|
||||||
return (themedColors.get(attrID) != 0 && ACCENT_THEME_ONLY_LIGHT.get(attrID, true) && (
|
return (themedColors.get(attrID) != 0 && themeOnlyMap.get(attrID, true) && (
|
||||||
ThemesUtils.isMilkshake() ?
|
isMilkshake ?
|
||||||
ACCENT_THEME_ONLY_MILK_LIGHT.get(attrID, true) :
|
milkshakeMap.get(attrID, true) :
|
||||||
ACCENT_THEME_ONLY_NOMILK_LIGHT.get(attrID, true)));
|
noMilkshakeMap.get(attrID, true)));
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
return themedColors.get(attrID) != 0;
|
return themedColors.get(attrID) != 0;
|
||||||
}
|
}
|
||||||
@@ -191,7 +193,6 @@ public class ThemesCore {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public static void clear() {
|
public static void clear() {
|
||||||
cachedAccents = false;
|
cachedAccents = false;
|
||||||
themedColors.clear();
|
themedColors.clear();
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ public class ThemesHacks {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static int getHackedColor(@NonNull Context context, @ColorRes int color) {
|
public static int getHackedColor(@NonNull Context context, @ColorRes int color) {
|
||||||
if (ThemesUtils.isCustomAccentEnabled()) {
|
if (ThemesUtils.isMonetTheme()) {
|
||||||
if (Preferences.getBoolValue("logColors", false)) {
|
if (Preferences.getBoolValue("logColors", false)) {
|
||||||
try {
|
try {
|
||||||
Log.d("ThemesCore", "Requesting color by color " + context.getResources().getResourceName(color));
|
Log.d("ThemesCore", "Requesting color by color " + context.getResources().getResourceName(color));
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ import java.util.zip.ZipOutputStream;
|
|||||||
|
|
||||||
public class ThemesManager {
|
public class ThemesManager {
|
||||||
|
|
||||||
private final static int[] ACCENT_COLORS = {
|
private static final int[] ACCENT_COLORS = {
|
||||||
R.color.vk_sky_300,
|
R.color.vk_sky_300,
|
||||||
R.color.sky_300,
|
R.color.sky_300,
|
||||||
R.color.viewer_retry_button_text_color,
|
R.color.viewer_retry_button_text_color,
|
||||||
@@ -96,7 +96,7 @@ public class ThemesManager {
|
|||||||
R.color.header_blue_opacity40
|
R.color.header_blue_opacity40
|
||||||
};
|
};
|
||||||
// modify it if "doNotCompress" in apktool.yml has been edited
|
// modify it if "doNotCompress" in apktool.yml has been edited
|
||||||
private final static String[] DO_NOT_COMPRESS = {
|
private static final String[] DO_NOT_COMPRESS = {
|
||||||
".png",
|
".png",
|
||||||
".jpg",
|
".jpg",
|
||||||
".mp3",
|
".mp3",
|
||||||
@@ -119,19 +119,18 @@ public class ThemesManager {
|
|||||||
initPaths(app);
|
initPaths(app);
|
||||||
validateModApk();
|
validateModApk();
|
||||||
|
|
||||||
if (!Preferences.isNewBuild() && !ThemesUtils.isMonetTheme() && canApplyCustomAccent() && ThemesUtils.useNewColorEngine()) {
|
if (!Preferences.isNewBuild() && !ThemesUtils.isMonetTheme() && canApplyCustomAccent()) {
|
||||||
ResourcesLoader.init(app);
|
ResourcesLoader.init(app);
|
||||||
ResourcesLoader.load(app, modApk.getAbsolutePath(), false);
|
ResourcesLoader.load(app, modApk.getAbsolutePath(), false);
|
||||||
}
|
}
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
Log.e("ThemesManager", e.getMessage());
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// validate modded apk before loading
|
// validate modded apk before loading
|
||||||
private static void validateModApk()
|
private static void validateModApk() throws IOException {
|
||||||
throws IOException {
|
var apk = new ZipFile(modApk);
|
||||||
final var apk = new ZipFile(modApk);
|
|
||||||
apk.close();
|
apk.close();
|
||||||
|
|
||||||
validated = true;
|
validated = true;
|
||||||
@@ -153,24 +152,18 @@ public class ThemesManager {
|
|||||||
return validated && modApk.exists() && ThemesUtils.getReservedAccent() != Color.TRANSPARENT;
|
return validated && modApk.exists() && ThemesUtils.getReservedAccent() != Color.TRANSPARENT;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void generateModApk(int accentColor)
|
public static void generateModApk(int accentColor) throws Throwable {
|
||||||
throws Throwable {
|
try (var apk = new ZipFile(baseApkPath)) {
|
||||||
try (
|
var arscEntry = apk.getEntry("resources.arsc");
|
||||||
final var apk = new ZipFile(baseApkPath)
|
var arscBis = new BufferedInputStream(apk.getInputStream(arscEntry));
|
||||||
) {
|
var arsc = BinaryResourceFile.fromInputStream(arscBis);
|
||||||
final var arscEntry = apk.getEntry("resources.arsc");
|
ArscEditor.changeColors(arsc, ACCENT_COLORS, accentColor);
|
||||||
final var arscBis = new BufferedInputStream(apk.getInputStream(arscEntry));
|
|
||||||
final var arsc = BinaryResourceFile.fromInputStream(arscBis);
|
|
||||||
if (!ArscEditor.changeColors(arsc, ACCENT_COLORS, accentColor))
|
|
||||||
throw new IllegalStateException("Not all colors have been changed");
|
|
||||||
|
|
||||||
try (
|
try (var zos = new ZipOutputStream(new BufferedOutputStream(new FileOutputStream(modApk)))) {
|
||||||
final var zos = new ZipOutputStream(new BufferedOutputStream(new FileOutputStream(modApk)))
|
var arscBuff = arsc.toByteArray();
|
||||||
) {
|
var newArscEntry = new ZipEntry("resources.arsc");
|
||||||
final var arscBuff = arsc.toByteArray();
|
|
||||||
final var newArscEntry = new ZipEntry("resources.arsc");
|
|
||||||
|
|
||||||
final var crc = new CRC32();
|
var crc = new CRC32();
|
||||||
crc.update(arscBuff);
|
crc.update(arscBuff);
|
||||||
|
|
||||||
newArscEntry.setSize(arscBuff.length);
|
newArscEntry.setSize(arscBuff.length);
|
||||||
@@ -181,10 +174,10 @@ public class ThemesManager {
|
|||||||
zos.write(arscBuff);
|
zos.write(arscBuff);
|
||||||
zos.closeEntry();
|
zos.closeEntry();
|
||||||
|
|
||||||
final var entries = apk.entries();
|
var entries = apk.entries();
|
||||||
while (entries.hasMoreElements()) {
|
while (entries.hasMoreElements()) {
|
||||||
final var entry = entries.nextElement();
|
var entry = entries.nextElement();
|
||||||
final var name = entry.getName();
|
var name = entry.getName();
|
||||||
|
|
||||||
if (!name.startsWith("res/") && !name.startsWith("assets/") || name.equals("resources.arsc"))
|
if (!name.startsWith("res/") && !name.startsWith("assets/") || name.equals("resources.arsc"))
|
||||||
continue;
|
continue;
|
||||||
@@ -197,8 +190,8 @@ public class ThemesManager {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
final var entryBis = new BufferedInputStream(apk.getInputStream(entry));
|
var entryBis = new BufferedInputStream(apk.getInputStream(entry));
|
||||||
final var newEntry = new ZipEntry(name);
|
var newEntry = new ZipEntry(name);
|
||||||
|
|
||||||
if (doNotCompress) {
|
if (doNotCompress) {
|
||||||
newEntry.setMethod(ZipEntry.STORED);
|
newEntry.setMethod(ZipEntry.STORED);
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ public class ViewInjector {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static View inject(View view, int i, boolean z) {
|
public static View inject(View view, int i, boolean z) {
|
||||||
if (ThemesUtils.isCustomAccentEnabled()) {
|
if (ThemesUtils.isMonetTheme()) {
|
||||||
for (BaseHook hook : hooks) {
|
for (BaseHook hook : hooks) {
|
||||||
hook.inject(view, i, z);
|
hook.inject(view, i, z);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,59 +1,44 @@
|
|||||||
package ru.vtosters.lite.themes.loaders;
|
package ru.vtosters.lite.themes.loaders;
|
||||||
|
|
||||||
|
import android.annotation.SuppressLint;
|
||||||
import android.content.res.AssetManager;
|
import android.content.res.AssetManager;
|
||||||
|
import android.util.Log;
|
||||||
import ru.vtosters.lite.utils.ReflectionUtils;
|
import ru.vtosters.lite.utils.ReflectionUtils;
|
||||||
|
|
||||||
import java.lang.reflect.InvocationTargetException;
|
import java.lang.reflect.InvocationTargetException;
|
||||||
import java.lang.reflect.Method;
|
import java.lang.reflect.Method;
|
||||||
|
|
||||||
|
@SuppressLint("PrivateApi")
|
||||||
public class AssetManagerHelper {
|
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);
|
||||||
// methods
|
|
||||||
private final static Method getAssetPathMtd;
|
|
||||||
private final static Method getApkAssetsMtd;
|
|
||||||
private final static Method addAssetPathMtd;
|
|
||||||
private final static Method addAssetPathAsSharedLibraryMtd;
|
|
||||||
private final static Method addOverlayPathMtd;
|
|
||||||
|
|
||||||
static {
|
|
||||||
try {
|
|
||||||
getAssetPathMtd = ReflectionUtils.findMethod(Class.forName("android.content.res.ApkAssets"), "getAssetPath");
|
|
||||||
getApkAssetsMtd = ReflectionUtils.findMethod(AssetManager.class, "getApkAssets");
|
|
||||||
addAssetPathMtd = AssetManager.class.getMethod("addAssetPath", String.class);
|
|
||||||
addAssetPathAsSharedLibraryMtd = AssetManager.class.getMethod("addAssetPathAsSharedLibrary", String.class);
|
|
||||||
addOverlayPathMtd = AssetManager.class.getMethod("addOverlayPath", String.class);
|
|
||||||
} catch (ClassNotFoundException | NoSuchMethodException e) {
|
|
||||||
throw new RuntimeException();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static String getApkPath(Object assetManager, String packagename)
|
|
||||||
throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, IllegalAccessException {
|
|
||||||
Object[] apkAssetsArr = (Object[]) getAssetPathMtd.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
|
// 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--) {
|
for (int i = apkAssetsArr.length - 1; i >= 0; i--) {
|
||||||
final String pathname = (String) getApkAssetsMtd.invoke(apkAssetsArr[i]);
|
String pathname = (String) ReflectionUtils.findMethod(AssetManager.class, "getApkAssets").invoke(apkAssetsArr[i]);
|
||||||
if (pathname.contains(packagename)) return pathname;
|
if (pathname != null && pathname.contains(packagename)) return pathname;
|
||||||
}
|
}
|
||||||
|
|
||||||
throw new NullPointerException();
|
throw new NullPointerException();
|
||||||
}
|
}
|
||||||
|
|
||||||
//region Uses for adding own assets or getting existing cookies
|
//region Uses for adding own assets or getting existing cookies
|
||||||
public static int addAssetPath(AssetManager manager, String path)
|
public static void addAssetPath(AssetManager manager, String path) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
|
||||||
throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
|
manager.getClass().getMethod("addAssetPath", String.class).invoke(manager, path);
|
||||||
return (int) addAssetPathMtd.invoke(manager, path);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static int addAssetPathAsSharedLibrary(AssetManager manager, String path)
|
public static int addAssetPathAsSharedLibrary(AssetManager manager, String path) {
|
||||||
throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
|
try {
|
||||||
return (int) addAssetPathAsSharedLibraryMtd.invoke(manager, path);
|
return (int) AssetManager.class.getMethod("addAssetPathAsSharedLibrary", String.class).invoke(manager, path);
|
||||||
|
} catch (IllegalAccessException | InvocationTargetException | NoSuchMethodException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static int addOverlayPath(AssetManager manager, String path)
|
public static int addOverlayPath(AssetManager manager, String path) {
|
||||||
throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
|
try {
|
||||||
return (int) addOverlayPathMtd.invoke(manager, path);
|
return (int) AssetManager.class.getMethod("addOverlayPath", String.class).invoke(manager, path);
|
||||||
|
} catch (IllegalAccessException | InvocationTargetException | NoSuchMethodException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
//endregion
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
package ru.vtosters.lite.themes.loaders;
|
package ru.vtosters.lite.themes.loaders;
|
||||||
|
|
||||||
|
import android.annotation.SuppressLint;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.pm.ApplicationInfo;
|
import android.content.pm.ApplicationInfo;
|
||||||
import android.content.res.AssetManager;
|
import android.content.res.AssetManager;
|
||||||
@@ -13,17 +14,19 @@ import ru.vtosters.lite.utils.ReflectionUtils;
|
|||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.lang.ref.WeakReference;
|
import java.lang.ref.WeakReference;
|
||||||
|
import java.lang.reflect.Array;
|
||||||
import java.lang.reflect.Field;
|
import java.lang.reflect.Field;
|
||||||
|
import java.lang.reflect.InvocationTargetException;
|
||||||
import java.lang.reflect.Method;
|
import java.lang.reflect.Method;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
|
@SuppressLint("PrivateApi")
|
||||||
public class ResourcesLoader {
|
public class ResourcesLoader {
|
||||||
|
|
||||||
private static Collection<WeakReference<Resources>> sResourceReferences = null;
|
private static Collection<WeakReference<Resources>> sResourceReferences = null;
|
||||||
private static Object sCurrentActivityThread = null;
|
private static Object sCurrentActivityThread = null;
|
||||||
private static AssetManager sAssetManager = null;
|
|
||||||
|
|
||||||
// methods
|
// methods
|
||||||
private static Method ensureStringBlocksMtd = null;
|
private static Method ensureStringBlocksMtd = null;
|
||||||
@@ -42,7 +45,7 @@ public class ResourcesLoader {
|
|||||||
static {
|
static {
|
||||||
try {
|
try {
|
||||||
// API version 8 has PackageInfo, 10 has LoadedApk. Needs to check 9
|
// API version 8 has PackageInfo, 10 has LoadedApk. Needs to check 9
|
||||||
final Class<?> activityThreadClz = Class.forName("android.app.ActivityThread");
|
Class<?> activityThreadClz = Class.forName("android.app.ActivityThread");
|
||||||
Class<?> loadedApkClz;
|
Class<?> loadedApkClz;
|
||||||
try {
|
try {
|
||||||
loadedApkClz = Class.forName("android.app.LoadedApk");
|
loadedApkClz = Class.forName("android.app.LoadedApk");
|
||||||
@@ -87,43 +90,40 @@ public class ResourcesLoader {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void init(Context context)
|
public static void init(Context context) throws Exception {
|
||||||
throws Exception {
|
|
||||||
sCurrentActivityThread = ReflectionUtils.getActivityThread(context, null);
|
sCurrentActivityThread = ReflectionUtils.getActivityThread(context, null);
|
||||||
|
|
||||||
//pre-N
|
//pre-N
|
||||||
// Find the singleton instance of ResourcesManager
|
// Find the singleton instance of ResourcesManager
|
||||||
final Class<?> resourcesManagerClass = Class.forName("android.app.ResourcesManager");
|
Class<?> resourcesManagerClass = Class.forName("android.app.ResourcesManager");
|
||||||
final Method mGetInstance = ReflectionUtils.findMethod(resourcesManagerClass, "getInstance");
|
Method mGetInstance = ReflectionUtils.findMethod(resourcesManagerClass, "getInstance");
|
||||||
final Object resourcesManager = mGetInstance.invoke(null);
|
Object resourcesManager = mGetInstance.invoke(null);
|
||||||
try {
|
try {
|
||||||
Field fMActiveResources = ReflectionUtils.findField(resourcesManagerClass, "mActiveResources");
|
Field fMActiveResources = ReflectionUtils.findField(resourcesManagerClass, "mActiveResources");
|
||||||
final ArrayMap<?, WeakReference<Resources>> activeResources19 =
|
ArrayMap<?, WeakReference<Resources>> activeResources19 =
|
||||||
(ArrayMap<?, WeakReference<Resources>>) fMActiveResources.get(resourcesManager);
|
(ArrayMap<?, WeakReference<Resources>>) fMActiveResources.get(resourcesManager);
|
||||||
sResourceReferences = activeResources19.values();
|
sResourceReferences = activeResources19.values();
|
||||||
} catch (NoSuchFieldException ignore) {
|
} catch (NoSuchFieldException ignore) {
|
||||||
// N moved the resources to mResourceReferences
|
// N moved the resources to mResourceReferences
|
||||||
final Field mResourceReferences = ReflectionUtils.findField(resourcesManagerClass, "mResourceReferences");
|
Field mResourceReferences = ReflectionUtils.findField(resourcesManagerClass, "mResourceReferences");
|
||||||
sResourceReferences = (Collection<WeakReference<Resources>>) mResourceReferences.get(resourcesManager);
|
sResourceReferences = (Collection<WeakReference<Resources>>) mResourceReferences.get(resourcesManager);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void load(Context context, String resPath, boolean reinject)
|
public static void load(Context context, String resPath, boolean reinject) throws IllegalAccessException, InstantiationException, InvocationTargetException, NoSuchFieldException, NoSuchMethodException {
|
||||||
throws Exception {
|
ApplicationInfo appInfo = context.getApplicationInfo();
|
||||||
final ApplicationInfo appInfo = context.getApplicationInfo();
|
|
||||||
|
|
||||||
final Field[] packagesFlds = Build.VERSION.SDK_INT < Build.VERSION_CODES.O_MR1
|
Field[] packagesFlds = Build.VERSION.SDK_INT < Build.VERSION_CODES.O_MR1
|
||||||
? new Field[]{packagesFld, resourcePackagesFld}
|
? new Field[]{packagesFld, resourcePackagesFld}
|
||||||
: new Field[]{packagesFld};
|
: new Field[]{packagesFld};
|
||||||
for (var fld : packagesFlds) {
|
for (var fld : packagesFlds) {
|
||||||
final var value = fld.get(sCurrentActivityThread);
|
var value = fld.get(sCurrentActivityThread);
|
||||||
|
|
||||||
for (var entry
|
for (var entry : ((Map<String, WeakReference<?>>) value).entrySet()) {
|
||||||
: ((Map<String, WeakReference<?>>) value).entrySet()) {
|
var loadedApk = entry.getValue().get();
|
||||||
final var loadedApk = entry.getValue().get();
|
|
||||||
if (loadedApk == null) continue;
|
if (loadedApk == null) continue;
|
||||||
|
|
||||||
final var resDirPath = (String) resDirFld.get(loadedApk);
|
var resDirPath = (String) resDirFld.get(loadedApk);
|
||||||
if (appInfo.sourceDir.equals(resDirPath))
|
if (appInfo.sourceDir.equals(resDirPath))
|
||||||
resDirFld.set(loadedApk, resPath);
|
resDirFld.set(loadedApk, resPath);
|
||||||
}
|
}
|
||||||
@@ -134,10 +134,10 @@ public class ResourcesLoader {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
sAssetManager = AssetManager.class.newInstance();
|
|
||||||
// Create a new AssetManager instance and point it to the resources installed under
|
// Create a new AssetManager instance and point it to the resources installed under
|
||||||
if (AssetManagerHelper.addAssetPath(sAssetManager, resPath) == 0)
|
AssetManager sAssetManager = AssetManager.class.newInstance();
|
||||||
throw new IllegalStateException("Could not create new AssetManager");
|
|
||||||
|
AssetManagerHelper.addAssetPath(sAssetManager, resPath);
|
||||||
|
|
||||||
// Add SharedLibraries to AssetManager for resolve system resources not found issue
|
// Add SharedLibraries to AssetManager for resolve system resources not found issue
|
||||||
// This influence SharedLibrary Package ID
|
// This influence SharedLibrary Package ID
|
||||||
@@ -157,7 +157,7 @@ public class ResourcesLoader {
|
|||||||
ensureStringBlocksMtd.invoke(sAssetManager);
|
ensureStringBlocksMtd.invoke(sAssetManager);
|
||||||
}
|
}
|
||||||
for (var wr : sResourceReferences) {
|
for (var wr : sResourceReferences) {
|
||||||
final var resources = wr.get();
|
var resources = wr.get();
|
||||||
if (resources == null) continue;
|
if (resources == null) continue;
|
||||||
|
|
||||||
// Set the AssetManager of the Resources instance to our brand new one
|
// Set the AssetManager of the Resources instance to our brand new one
|
||||||
@@ -166,9 +166,9 @@ public class ResourcesLoader {
|
|||||||
assetsFld.set(resources, sAssetManager);
|
assetsFld.set(resources, sAssetManager);
|
||||||
} catch (Throwable ignore) {
|
} catch (Throwable ignore) {
|
||||||
// N
|
// N
|
||||||
final var resourceImpl = resourcesImplFld.get(resources);
|
var resourceImpl = resourcesImplFld.get(resources);
|
||||||
// for Huawei HwResourcesImpl
|
// for Huawei HwResourcesImpl
|
||||||
final Field implAssets = ReflectionUtils.findField(resourceImpl, "mAssets");
|
Field implAssets = ReflectionUtils.findField(resourceImpl, "mAssets");
|
||||||
implAssets.set(resourceImpl, sAssetManager);
|
implAssets.set(resourceImpl, sAssetManager);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -196,13 +196,13 @@ public class ResourcesLoader {
|
|||||||
|
|
||||||
private static void installResourceInsuranceHacks(Context context, String patchedResApkPath) {
|
private static void installResourceInsuranceHacks(Context context, String patchedResApkPath) {
|
||||||
try {
|
try {
|
||||||
final Object activityThread = ReflectionUtils.getActivityThread(context, null);
|
Object activityThread = ReflectionUtils.getActivityThread(context, null);
|
||||||
final Field mHField = ReflectionUtils.findField(activityThread, "mH");
|
Field mHField = ReflectionUtils.findField(activityThread, "mH");
|
||||||
final Handler mH = (Handler) mHField.get(activityThread);
|
Handler mH = (Handler) mHField.get(activityThread);
|
||||||
final Field mCallbackField = ReflectionUtils.findField(Handler.class, "mCallback");
|
Field mCallbackField = ReflectionUtils.findField(Handler.class, "mCallback");
|
||||||
final Handler.Callback originCallback = (Handler.Callback) mCallbackField.get(mH);
|
Handler.Callback originCallback = (Handler.Callback) mCallbackField.get(mH);
|
||||||
if (!(originCallback instanceof ResourceInsuranceHandlerCallback)) {
|
if (!(originCallback instanceof ResourceInsuranceHandlerCallback)) {
|
||||||
final ResourceInsuranceHandlerCallback hackCallback = new ResourceInsuranceHandlerCallback(
|
ResourceInsuranceHandlerCallback hackCallback = new ResourceInsuranceHandlerCallback(
|
||||||
context, patchedResApkPath, originCallback, mH.getClass());
|
context, patchedResApkPath, originCallback, mH.getClass());
|
||||||
mCallbackField.set(mH, hackCallback);
|
mCallbackField.set(mH, hackCallback);
|
||||||
} else {
|
} else {
|
||||||
@@ -250,9 +250,9 @@ public class ResourcesLoader {
|
|||||||
Log.w("ResourcesLoader", "try to clear typedArray cache!");
|
Log.w("ResourcesLoader", "try to clear typedArray cache!");
|
||||||
// Clear typedArray cache.
|
// Clear typedArray cache.
|
||||||
try {
|
try {
|
||||||
final Field typedArrayPoolField = ReflectionUtils.findField(Resources.class, "mTypedArrayPool");
|
Field typedArrayPoolField = ReflectionUtils.findField(Resources.class, "mTypedArrayPool");
|
||||||
final Object origTypedArrayPool = typedArrayPoolField.get(resources);
|
Object origTypedArrayPool = typedArrayPoolField.get(resources);
|
||||||
final Method acquireMethod = ReflectionUtils.findMethod(origTypedArrayPool, "acquire");
|
Method acquireMethod = ReflectionUtils.findMethod(origTypedArrayPool, "acquire");
|
||||||
while (true) {
|
while (true) {
|
||||||
if (acquireMethod.invoke(origTypedArrayPool) == null) {
|
if (acquireMethod.invoke(origTypedArrayPool) == null) {
|
||||||
break;
|
break;
|
||||||
@@ -268,9 +268,8 @@ public class ResourcesLoader {
|
|||||||
applicationInfo.sharedLibraryFiles != null;
|
applicationInfo.sharedLibraryFiles != null;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static final class ResourceInsuranceHandlerCallback implements Handler.Callback {
|
private static class ResourceInsuranceHandlerCallback implements Handler.Callback {
|
||||||
private static final String LAUNCH_ACTIVITY_LIFECYCLE_ITEM_CLASSNAME = "android.app.servertransaction.LaunchActivityItem";
|
private static final String LAUNCH_ACTIVITY_LIFECYCLE_ITEM_CLASSNAME = "android.app.servertransaction.LaunchActivityItem";
|
||||||
|
|
||||||
private final Context mContext;
|
private final Context mContext;
|
||||||
private final String mPatchResApkPath;
|
private final String mPatchResApkPath;
|
||||||
private final Handler.Callback mOriginalCallback;
|
private final Handler.Callback mOriginalCallback;
|
||||||
@@ -319,48 +318,56 @@ public class ResourcesLoader {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
private boolean hackMessage(Message msg) {
|
// A method to check if the message requires re-injecting patched resources
|
||||||
boolean shouldReInjectPatchedResources = false;
|
private boolean shouldReInjectPatchedResources(Message msg) {
|
||||||
if (!isPatchedResModifiedAfterLastLoad(mPatchResApkPath)) {
|
if (!isPatchedResModifiedAfterLastLoad(mPatchResApkPath)) {
|
||||||
shouldReInjectPatchedResources = false;
|
return false;
|
||||||
} else {
|
}
|
||||||
if (msg.what == LAUNCH_ACTIVITY || msg.what == RELAUNCH_ACTIVITY) {
|
if (msg.what == LAUNCH_ACTIVITY || msg.what == RELAUNCH_ACTIVITY) {
|
||||||
shouldReInjectPatchedResources = true;
|
return true;
|
||||||
} else if (msg.what == EXECUTE_TRANSACTION) {
|
}
|
||||||
do {
|
// If the message is executing a transaction, check the callbacks
|
||||||
if (mSkipInterceptExecuteTransaction) {
|
if (msg.what == EXECUTE_TRANSACTION) {
|
||||||
break;
|
// Skip the logic if the method is not found or an error occurs
|
||||||
}
|
if (mSkipInterceptExecuteTransaction) {
|
||||||
final Object transaction = msg.obj;
|
return false;
|
||||||
if (transaction == null) {
|
}
|
||||||
Log.w("ResourcesLoader", "transaction is null, skip rest insurance logic.");
|
// Get the transaction object from the message
|
||||||
break;
|
Object transaction = msg.obj;
|
||||||
}
|
if (transaction == null) {
|
||||||
if (mGetCallbacksMethod == null) {
|
Log.w("ResourcesLoader", "transaction is null, skip rest insurance logic.");
|
||||||
try {
|
return false;
|
||||||
mGetCallbacksMethod = ReflectionUtils.findMethod(transaction, "getCallbacks");
|
}
|
||||||
} catch (Throwable ignored) {
|
// Get the getCallbacks method from the transaction class
|
||||||
// Ignored.
|
if (mGetCallbacksMethod == null) {
|
||||||
}
|
try {
|
||||||
}
|
mGetCallbacksMethod = ReflectionUtils.findMethod(transaction, "getCallbacks");
|
||||||
if (mGetCallbacksMethod == null) {
|
} catch (Throwable ignored) {
|
||||||
Log.e("ResourcesLoader", "fail to find getLifecycleStateRequest method, skip rest insurance logic.");
|
// Ignored.
|
||||||
mSkipInterceptExecuteTransaction = true;
|
}
|
||||||
break;
|
}
|
||||||
}
|
if (mGetCallbacksMethod == null) {
|
||||||
try {
|
Log.e("ResourcesLoader", "fail to find getCallbacks method, skip rest insurance logic.");
|
||||||
final List<Object> req = (List<Object>) mGetCallbacksMethod.invoke(transaction);
|
mSkipInterceptExecuteTransaction = true;
|
||||||
if (req != null && req.size() > 0) {
|
return false;
|
||||||
final Object cb = req.get(0);
|
}
|
||||||
shouldReInjectPatchedResources = cb != null && cb.getClass().getName().equals(LAUNCH_ACTIVITY_LIFECYCLE_ITEM_CLASSNAME);
|
try {
|
||||||
}
|
List<Object> callbacks = (List<Object>) mGetCallbacksMethod.invoke(transaction);
|
||||||
} catch (Throwable ignored) {
|
if (callbacks != null && !callbacks.isEmpty()) {
|
||||||
Log.e("ResourcesLoader", "fail to call getLifecycleStateRequest method, skip rest insurance logic.");
|
Object cb = callbacks.get(0);
|
||||||
}
|
return cb != null && cb.getClass().getName().equals(LAUNCH_ACTIVITY_LIFECYCLE_ITEM_CLASSNAME);
|
||||||
} while (false);
|
}
|
||||||
|
} catch (Throwable ignored) {
|
||||||
|
Log.e("ResourcesLoader", "fail to call getCallbacks method, skip rest insurance logic.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (shouldReInjectPatchedResources) {
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// A method to hack the message and re-inject patched resources if needed
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
private boolean hackMessage(Message msg) {
|
||||||
|
if (shouldReInjectPatchedResources(msg)) {
|
||||||
try {
|
try {
|
||||||
load(mContext, mPatchResApkPath, true);
|
load(mContext, mPatchResApkPath, true);
|
||||||
} catch (Throwable thr) {
|
} catch (Throwable thr) {
|
||||||
|
|||||||
@@ -23,8 +23,8 @@ import static ru.vtosters.lite.utils.AndroidUtils.getGlobalContext;
|
|||||||
|
|
||||||
public class PalettesManager {
|
public class PalettesManager {
|
||||||
|
|
||||||
private final static File PALETTES_DIR = new File(Environment.getExternalStorageDirectory(), "VTL/palettes");
|
private static final File PALETTES_DIR = new File(Environment.getExternalStorageDirectory(), "VTL/palettes");
|
||||||
private final static String ASSETS_DIR = "vtl_themes/palettes/";
|
private static final String ASSETS_DIR = "vtl_themes/palettes/";
|
||||||
|
|
||||||
private static PalettesManager sInstance;
|
private static PalettesManager sInstance;
|
||||||
|
|
||||||
@@ -51,17 +51,17 @@ public class PalettesManager {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
final var palettes = PALETTES_DIR.listFiles((dir, name) -> name.endsWith(".json"));
|
var palettes = PALETTES_DIR.listFiles((dir, name) -> name.endsWith(".json"));
|
||||||
if (palettes == null || palettes.length == 0)
|
if (palettes == null || palettes.length == 0)
|
||||||
copyPaletteFromAssets();
|
copyPaletteFromAssets();
|
||||||
parsePalettes();
|
parsePalettes();
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean copyPaletteFromAssets() {
|
private void copyPaletteFromAssets() {
|
||||||
try {
|
try {
|
||||||
final var manager = AndroidUtils.getGlobalContext().getAssets();
|
var manager = AndroidUtils.getGlobalContext().getAssets();
|
||||||
final var assets = manager.list(ASSETS_DIR);
|
var assets = manager.list(ASSETS_DIR);
|
||||||
if (assets == null || assets.length == 0) return false;
|
if (assets == null || assets.length == 0) return;
|
||||||
for (var asset : assets) {
|
for (var asset : assets) {
|
||||||
try {
|
try {
|
||||||
IOUtils.copy(manager.open(ASSETS_DIR + asset), new File(PALETTES_DIR, asset));
|
IOUtils.copy(manager.open(ASSETS_DIR + asset), new File(PALETTES_DIR, asset));
|
||||||
@@ -69,11 +69,9 @@ public class PalettesManager {
|
|||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return true;
|
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void parsePalettes() {
|
private void parsePalettes() {
|
||||||
|
|||||||
@@ -1,37 +1,38 @@
|
|||||||
package ru.vtosters.lite.themes.utils;
|
package ru.vtosters.lite.themes.utils;
|
||||||
|
|
||||||
import com.google.devrel.gmscore.tools.apk.arsc.*;
|
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;
|
||||||
|
|
||||||
public class ArscEditor {
|
public class ArscEditor {
|
||||||
|
|
||||||
public static boolean changeColors(BinaryResourceFile arsc, int[] colorIds, int color /*int[] colors*/) {
|
public static void changeColors(BinaryResourceFile arsc, int[] colorIds, int color) {
|
||||||
int q = 0;
|
|
||||||
for (var chunk : arsc.getChunks()) {
|
for (var chunk : arsc.getChunks()) {
|
||||||
final var resourceTableChunk = (ResourceTableChunk) chunk;
|
var resTableChunk = (ResourceTableChunk) chunk;
|
||||||
|
for (var packageChunk : resTableChunk.getPackages()) {
|
||||||
for (PackageChunk packageChunk : resourceTableChunk.getPackages()) {
|
for (var typeChunk : packageChunk.getTypeChunks("color")) {
|
||||||
for (TypeSpecChunk typeSpecChunk : packageChunk.getTypeSpecChunks()) {
|
for (var entry : typeChunk.getEntries().entrySet()) {
|
||||||
for (TypeChunk typeChunk : packageChunk.getTypeChunks(typeSpecChunk.getId())) {
|
var value = entry.getValue();
|
||||||
if (!"color".equals(typeChunk.getTypeName())) continue;
|
if (value.isComplex()) continue;
|
||||||
|
var binValue = value.value();
|
||||||
for (var entry : typeChunk.getEntries().entrySet()) {
|
if (!isColorResourceValue(binValue)) continue;
|
||||||
if (entry.getValue().isComplex()) continue;
|
var resId = packageChunk.getId() << 24 | typeChunk.getId() << 16 | entry.getKey();
|
||||||
|
for (var colodId : colorIds) {
|
||||||
final var id = BinaryResourceIdentifier.create(packageChunk.getId(), typeSpecChunk.getId(), entry.getKey());
|
if (resId == colodId) {
|
||||||
|
binValue.data = color;
|
||||||
for (int colorId : colorIds) {
|
break;
|
||||||
if (colorId != id.resId()) continue;
|
|
||||||
|
|
||||||
final var value = entry.getValue();
|
|
||||||
value.updateValue(new BinaryResourceValue(8, value.value().type(), color /*colors[i]*/));
|
|
||||||
++q;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return q == colorIds.length;
|
private static boolean isColorResourceValue(BinaryResourceValue value) {
|
||||||
|
return value.type == BinaryResourceValue.Type.INT_COLOR_ARGB8
|
||||||
|
|| value.type == BinaryResourceValue.Type.INT_COLOR_RGB8
|
||||||
|
|| value.type == BinaryResourceValue.Type.INT_COLOR_ARGB4
|
||||||
|
|| value.type == BinaryResourceValue.Type.INT_COLOR_RGB4;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -43,7 +43,7 @@ public class RecolorUtils {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static int recolorHexColor(int i) {
|
public static int recolorHexColor(int i) {
|
||||||
if (!ThemesUtils.isCustomAccentEnabled()) return i;
|
if (!ThemesUtils.isMonetTheme()) return i;
|
||||||
var accented = ColorReferences.isAccentedColor(i);
|
var accented = ColorReferences.isAccentedColor(i);
|
||||||
var mutedaccented = ColorReferences.isMutedAccentedColor(i);
|
var mutedaccented = ColorReferences.isMutedAccentedColor(i);
|
||||||
return (accented || mutedaccented) ? (accented ? ThemesUtils.getAccentColor() : ThemesUtils.getMutedAccentColor()) : i;
|
return (accented || mutedaccented) ? (accented ? ThemesUtils.getAccentColor() : ThemesUtils.getMutedAccentColor()) : i;
|
||||||
@@ -57,7 +57,7 @@ public class RecolorUtils {
|
|||||||
|
|
||||||
@SuppressLint("UseCompatLoadingForColorStateLists")
|
@SuppressLint("UseCompatLoadingForColorStateLists")
|
||||||
public static ColorStateList themeCSL(Context context, int color) {
|
public static ColorStateList themeCSL(Context context, int color) {
|
||||||
if (!ThemesUtils.isCustomAccentEnabled()) {
|
if (!ThemesUtils.isMonetTheme()) {
|
||||||
if (Build.VERSION.SDK_INT >= 23) {
|
if (Build.VERSION.SDK_INT >= 23) {
|
||||||
return context.getColorStateList(color);
|
return context.getColorStateList(color);
|
||||||
} else {
|
} else {
|
||||||
@@ -83,7 +83,7 @@ public class RecolorUtils {
|
|||||||
} // Recolor ColorStateList
|
} // Recolor ColorStateList
|
||||||
|
|
||||||
public static ColorStateList themeCSL(ColorStateList csl) {
|
public static ColorStateList themeCSL(ColorStateList csl) {
|
||||||
if (!ThemesUtils.isCustomAccentEnabled()) return csl;
|
if (!ThemesUtils.isMonetTheme()) return csl;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
int unsel = csl.getColorForState(new int[]{-android.R.attr.state_selected}, Color.BLACK);
|
int unsel = csl.getColorForState(new int[]{-android.R.attr.state_selected}, Color.BLACK);
|
||||||
|
|||||||
@@ -301,7 +301,7 @@ public class PreferenceFragmentUtils {
|
|||||||
return addPreference(screen, key, title, null, null, preference -> {
|
return addPreference(screen, key, title, null, null, preference -> {
|
||||||
LinearLayout linearLayout = new LinearLayout(screen.getContext());
|
LinearLayout linearLayout = new LinearLayout(screen.getContext());
|
||||||
|
|
||||||
final EditText editText = new EditText(screen.getContext());
|
EditText editText = new EditText(screen.getContext());
|
||||||
editText.setText(PreferenceManager.getDefaultSharedPreferences(screen.getContext()).getString(key, ""));
|
editText.setText(PreferenceManager.getDefaultSharedPreferences(screen.getContext()).getString(key, ""));
|
||||||
editText.setHint(title);
|
editText.setHint(title);
|
||||||
editText.setTextColor(ThemesUtils.getTextAttr());
|
editText.setTextColor(ThemesUtils.getTextAttr());
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ import ru.vtosters.lite.utils.AndroidUtils;
|
|||||||
import ru.vtosters.lite.utils.LayoutUtils;
|
import ru.vtosters.lite.utils.LayoutUtils;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
@@ -35,6 +36,7 @@ public class CategorizedAdapter<T> extends RecyclerView.Adapter<CategorizedAdapt
|
|||||||
private final List<T> mSelectedItems;
|
private final List<T> mSelectedItems;
|
||||||
private final List<T> mDisabledItems;
|
private final List<T> mDisabledItems;
|
||||||
private final List<T> mUnmovedItems;
|
private final List<T> mUnmovedItems;
|
||||||
|
private final List<T> mExceptions = new ArrayList<>();
|
||||||
private final IViewHolderBinder mBinder;
|
private final IViewHolderBinder mBinder;
|
||||||
|
|
||||||
// Min and max counts
|
// Min and max counts
|
||||||
@@ -48,6 +50,12 @@ public class CategorizedAdapter<T> extends RecyclerView.Adapter<CategorizedAdapt
|
|||||||
this.mBinder = binder;
|
this.mBinder = binder;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@SafeVarargs
|
||||||
|
public final void setExceptions(T... exceptions) {
|
||||||
|
mExceptions.clear();
|
||||||
|
mExceptions.addAll(Arrays.asList(exceptions));
|
||||||
|
}
|
||||||
|
|
||||||
public void setMinAndMaxCounts(int min, int max) {
|
public void setMinAndMaxCounts(int min, int max) {
|
||||||
this.mMinSelectedItems = min;
|
this.mMinSelectedItems = min;
|
||||||
this.mMaxSelectedItems = max;
|
this.mMaxSelectedItems = max;
|
||||||
@@ -173,16 +181,25 @@ public class CategorizedAdapter<T> extends RecyclerView.Adapter<CategorizedAdapt
|
|||||||
public boolean onItemMove(int fromPosition, int toPosition) {
|
public boolean onItemMove(int fromPosition, int toPosition) {
|
||||||
if (toPosition == 0 || isUnmovedItem(toPosition))
|
if (toPosition == 0 || isUnmovedItem(toPosition))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
switch (getTabType(fromPosition)) {
|
switch (getTabType(fromPosition)) {
|
||||||
case SELECTED_STATE -> {
|
case SELECTED_STATE -> {
|
||||||
if (getTabType(toPosition) == DISABLED_STATE
|
if ((getTabType(toPosition) == DISABLED_STATE
|
||||||
&& mSelectedItems.size() == mMinSelectedItems)
|
&& mSelectedItems.size() == mMinSelectedItems))
|
||||||
return false;
|
return false;
|
||||||
if (getItemViewType(toPosition) == CATEGORY_TITLE)
|
if (getItemViewType(toPosition) == CATEGORY_TITLE) {
|
||||||
|
if (!mExceptions.isEmpty()) {
|
||||||
|
boolean except = false;
|
||||||
|
int q = 0;
|
||||||
|
for (var ex : mExceptions) {
|
||||||
|
var i = mSelectedItems.indexOf(ex);
|
||||||
|
if (i == -1) continue;
|
||||||
|
if (i + 1 == fromPosition) except = true;
|
||||||
|
++q;
|
||||||
|
}
|
||||||
|
if (except && q == 1) return false;
|
||||||
|
}
|
||||||
mDisabledItems.add(0, mSelectedItems.remove(fromPosition - 1));
|
mDisabledItems.add(0, mSelectedItems.remove(fromPosition - 1));
|
||||||
else
|
} else Collections.swap(mSelectedItems, fromPosition - 1, toPosition - 1);
|
||||||
Collections.swap(mSelectedItems, fromPosition - 1, toPosition - 1);
|
|
||||||
}
|
}
|
||||||
case DISABLED_STATE -> {
|
case DISABLED_STATE -> {
|
||||||
if (getTabType(toPosition) == SELECTED_STATE
|
if (getTabType(toPosition) == SELECTED_STATE
|
||||||
@@ -198,7 +215,6 @@ public class CategorizedAdapter<T> extends RecyclerView.Adapter<CategorizedAdapt
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
notifyItemMoved(fromPosition, toPosition);
|
notifyItemMoved(fromPosition, toPosition);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -208,7 +224,6 @@ public class CategorizedAdapter<T> extends RecyclerView.Adapter<CategorizedAdapt
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static class CategorizedViewHolder extends RecyclerView.ViewHolder {
|
public static class CategorizedViewHolder extends RecyclerView.ViewHolder {
|
||||||
|
|
||||||
private final LinearLayout mMovingItemContainer;
|
private final LinearLayout mMovingItemContainer;
|
||||||
private final ImageView mIcon;
|
private final ImageView mIcon;
|
||||||
private final TextView mName;
|
private final TextView mName;
|
||||||
|
|||||||
@@ -18,7 +18,6 @@ import ru.vtosters.hooks.other.ThemesUtils;
|
|||||||
import ru.vtosters.lite.utils.AndroidUtils;
|
import ru.vtosters.lite.utils.AndroidUtils;
|
||||||
|
|
||||||
public class MessagesPreviewAdapter extends RecyclerView.Adapter<MessagesPreviewAdapter.MessagePreviewViewHolder> {
|
public class MessagesPreviewAdapter extends RecyclerView.Adapter<MessagesPreviewAdapter.MessagePreviewViewHolder> {
|
||||||
|
|
||||||
private final String[] mMessages;
|
private final String[] mMessages;
|
||||||
|
|
||||||
public MessagesPreviewAdapter(String... messages) {
|
public MessagesPreviewAdapter(String... messages) {
|
||||||
@@ -35,9 +34,9 @@ public class MessagesPreviewAdapter extends RecyclerView.Adapter<MessagesPreview
|
|||||||
public MessagePreviewViewHolder onCreateViewHolder(@NonNull ViewGroup viewGroup, int viewType) {
|
public MessagePreviewViewHolder onCreateViewHolder(@NonNull ViewGroup viewGroup, int viewType) {
|
||||||
Context context = viewGroup.getContext();
|
Context context = viewGroup.getContext();
|
||||||
|
|
||||||
final var inflater = LayoutInflater.from(context);
|
var inflater = LayoutInflater.from(context);
|
||||||
|
|
||||||
final var bubbleFluidLayout = (BubbleFluidLayout) inflater.inflate(R.layout.vkim_msg_list_item_msg_from_user, viewGroup, false);
|
var bubbleFluidLayout = (BubbleFluidLayout) inflater.inflate(R.layout.vkim_msg_list_item_msg_from_user, viewGroup, false);
|
||||||
bubbleFluidLayout.setPadding(0, AndroidUtils.dp2px(4), 0, 0);
|
bubbleFluidLayout.setPadding(0, AndroidUtils.dp2px(4), 0, 0);
|
||||||
bubbleFluidLayout.setGravity(viewType);
|
bubbleFluidLayout.setGravity(viewType);
|
||||||
|
|
||||||
@@ -47,7 +46,7 @@ public class MessagesPreviewAdapter extends RecyclerView.Adapter<MessagesPreview
|
|||||||
bubbleFluidLayout.findViewById(R.id.status).setVisibility(View.GONE);
|
bubbleFluidLayout.findViewById(R.id.status).setVisibility(View.GONE);
|
||||||
bubbleFluidLayout.findViewById(R.id.status_space).setVisibility(View.GONE);
|
bubbleFluidLayout.findViewById(R.id.status_space).setVisibility(View.GONE);
|
||||||
|
|
||||||
final var messageBubbleView = (MsgBubbleView) bubbleFluidLayout.findViewById(R.id.bubble);
|
var messageBubbleView = (MsgBubbleView) bubbleFluidLayout.findViewById(R.id.bubble);
|
||||||
messageBubbleView.setContentPaddingLeft(AndroidUtils.dp2px(10));
|
messageBubbleView.setContentPaddingLeft(AndroidUtils.dp2px(10));
|
||||||
messageBubbleView.setContentPaddingTop(AndroidUtils.dp2px(4));
|
messageBubbleView.setContentPaddingTop(AndroidUtils.dp2px(4));
|
||||||
messageBubbleView.setContentPaddingRight(AndroidUtils.dp2px(4));
|
messageBubbleView.setContentPaddingRight(AndroidUtils.dp2px(4));
|
||||||
@@ -59,10 +58,10 @@ public class MessagesPreviewAdapter extends RecyclerView.Adapter<MessagesPreview
|
|||||||
}
|
}
|
||||||
bubbleFluidLayout.setLayoutDirection(viewType);
|
bubbleFluidLayout.setLayoutDirection(viewType);
|
||||||
|
|
||||||
final var msgTextView = inflater.inflate(R.layout.vkim_msg_part_text, viewGroup, false);
|
var msgTextView = inflater.inflate(R.layout.vkim_msg_part_text, viewGroup, false);
|
||||||
msgTextView.setId(R.id.msg_text);
|
msgTextView.setId(R.id.msg_text);
|
||||||
|
|
||||||
final var msgBubbleView = (MsgBubbleView) bubbleFluidLayout.findViewById(R.id.bubble);
|
var msgBubbleView = (MsgBubbleView) bubbleFluidLayout.findViewById(R.id.bubble);
|
||||||
msgBubbleView.setContentView(msgTextView);
|
msgBubbleView.setContentView(msgTextView);
|
||||||
|
|
||||||
return new MessagePreviewViewHolder(bubbleFluidLayout);
|
return new MessagePreviewViewHolder(bubbleFluidLayout);
|
||||||
|
|||||||
@@ -59,71 +59,7 @@ public class DockBarEditorManager {
|
|||||||
: sInstance;
|
: sInstance;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void init() {
|
public static DockBarTab getTabByTag(String tag) {
|
||||||
if (vkme()) {
|
|
||||||
mSelectedTabs.add(getTabByTag("tab_settings"));
|
|
||||||
if (vkme_notifs()) {
|
|
||||||
if (milkshake()) {
|
|
||||||
mSelectedTabs.add(getTabByTag("tab_feedback"));
|
|
||||||
} else {
|
|
||||||
mSelectedTabs.add(getTabByTag("tab_friends"));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
mSelectedTabs.add(getTabByTag("tab_messages"));
|
|
||||||
mSelectedTabs.add(getTabByTag("tab_profile"));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
checkOldConfig();
|
|
||||||
|
|
||||||
var selectedTabsTags = getPreferences()
|
|
||||||
.getString("dockbar_tabs",
|
|
||||||
"tab_news,tab_superapps,tab_messages,tab_friends,tab_profile")
|
|
||||||
.split(",");
|
|
||||||
parseSelectedTabs(selectedTabsTags);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void checkOldConfig() {
|
|
||||||
File config = new File(getGlobalContext().getFilesDir(), "dockbar.json");
|
|
||||||
if (config.exists()) config.deleteOnExit();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void parseSelectedTabs(String[] selectedTabsTags) {
|
|
||||||
var allTags = new ArrayList<>(ALL_TAGS);
|
|
||||||
|
|
||||||
for (String tag : selectedTabsTags) {
|
|
||||||
mSelectedTabs.add(getTabByTag(tag));
|
|
||||||
allTags.remove(tag);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (String tag : allTags) {
|
|
||||||
mDisabledTabs.add(getTabByTag(tag));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void save() {
|
|
||||||
var sb = new StringBuilder();
|
|
||||||
for (DockBarTab tab : mSelectedTabs)
|
|
||||||
sb.append(tab.tag).append(",");
|
|
||||||
getPreferences().edit().putString("dockbar_tabs", sb.toString()).commit();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void reset() {
|
|
||||||
Preferences.getPreferences()
|
|
||||||
.edit()
|
|
||||||
.putString("dockbar_tabs", "tab_news,tab_superapps,tab_messages,tab_friends,tab_profile")
|
|
||||||
.commit();
|
|
||||||
}
|
|
||||||
|
|
||||||
public List<DockBarTab> getSelectedTabs() {
|
|
||||||
return mSelectedTabs;
|
|
||||||
}
|
|
||||||
|
|
||||||
public List<DockBarTab> getDisabledTabs() {
|
|
||||||
return mDisabledTabs;
|
|
||||||
}
|
|
||||||
|
|
||||||
private DockBarTab getTabByTag(String tag) {
|
|
||||||
return switch (tag) {
|
return switch (tag) {
|
||||||
case "tab_news" -> DockBarTab.valuesOf(
|
case "tab_news" -> DockBarTab.valuesOf(
|
||||||
"tab_news",
|
"tab_news",
|
||||||
@@ -235,4 +171,68 @@ public class DockBarEditorManager {
|
|||||||
useNewSettings());
|
useNewSettings());
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void init() {
|
||||||
|
if (vkme()) {
|
||||||
|
mSelectedTabs.add(getTabByTag("tab_settings"));
|
||||||
|
if (vkme_notifs()) {
|
||||||
|
if (milkshake()) {
|
||||||
|
mSelectedTabs.add(getTabByTag("tab_feedback"));
|
||||||
|
} else {
|
||||||
|
mSelectedTabs.add(getTabByTag("tab_friends"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
mSelectedTabs.add(getTabByTag("tab_messages"));
|
||||||
|
mSelectedTabs.add(getTabByTag("tab_profile"));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
checkOldConfig();
|
||||||
|
|
||||||
|
var selectedTabsTags = getPreferences()
|
||||||
|
.getString("dockbar_tabs",
|
||||||
|
"tab_news,tab_superapps,tab_messages,tab_friends,tab_profile")
|
||||||
|
.split(",");
|
||||||
|
parseSelectedTabs(selectedTabsTags);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void checkOldConfig() {
|
||||||
|
File config = new File(getGlobalContext().getFilesDir(), "dockbar.json");
|
||||||
|
if (config.exists()) config.deleteOnExit();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void parseSelectedTabs(String[] selectedTabsTags) {
|
||||||
|
var allTags = new ArrayList<>(ALL_TAGS);
|
||||||
|
|
||||||
|
for (String tag : selectedTabsTags) {
|
||||||
|
mSelectedTabs.add(getTabByTag(tag));
|
||||||
|
allTags.remove(tag);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (String tag : allTags) {
|
||||||
|
mDisabledTabs.add(getTabByTag(tag));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void save() {
|
||||||
|
var sb = new StringBuilder();
|
||||||
|
for (DockBarTab tab : mSelectedTabs)
|
||||||
|
sb.append(tab.tag).append(",");
|
||||||
|
getPreferences().edit().putString("dockbar_tabs", sb.toString()).commit();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void reset() {
|
||||||
|
Preferences.getPreferences()
|
||||||
|
.edit()
|
||||||
|
.putString("dockbar_tabs", "tab_news,tab_superapps,tab_messages,tab_friends,tab_profile")
|
||||||
|
.commit();
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<DockBarTab> getSelectedTabs() {
|
||||||
|
return mSelectedTabs;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<DockBarTab> getDisabledTabs() {
|
||||||
|
return mDisabledTabs;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,8 +17,8 @@ public class DisableBattery {
|
|||||||
public static void alert(Activity activity) {
|
public static void alert(Activity activity) {
|
||||||
if (!(OEMDetector.isOEM() && Build.VERSION.SDK_INT >= 23 && Preferences.getBoolValue("showDoze", true)))
|
if (!(OEMDetector.isOEM() && Build.VERSION.SDK_INT >= 23 && Preferences.getBoolValue("showDoze", true)))
|
||||||
return;
|
return;
|
||||||
final String packName = activity.getPackageName();
|
String packName = activity.getPackageName();
|
||||||
final PowerManager manager = (PowerManager) activity.getSystemService(Context.POWER_SERVICE);
|
PowerManager manager = (PowerManager) activity.getSystemService(Context.POWER_SERVICE);
|
||||||
if (manager.isIgnoringBatteryOptimizations(packName)) return;
|
if (manager.isIgnoringBatteryOptimizations(packName)) return;
|
||||||
new VkAlertDialog.Builder(activity)
|
new VkAlertDialog.Builder(activity)
|
||||||
.setTitle(R.string.batteryissuetitle)
|
.setTitle(R.string.batteryissuetitle)
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
package ru.vtosters.lite.ui.dialogs;
|
package ru.vtosters.lite.ui.dialogs;
|
||||||
|
|
||||||
|
import android.annotation.SuppressLint;
|
||||||
import android.app.Activity;
|
import android.app.Activity;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.widget.LinearLayout;
|
import android.widget.LinearLayout;
|
||||||
@@ -41,6 +42,7 @@ public class OTADialog extends ModalBottomSheetWrapper<OTADialog> implements OTA
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@SuppressLint("SetTextI18n")
|
||||||
private View makeUpdateInfoView(String changelog) {
|
private View makeUpdateInfoView(String changelog) {
|
||||||
LinearLayout container = new LinearLayout(mActivity);
|
LinearLayout container = new LinearLayout(mActivity);
|
||||||
TextView changelogView = new TextView(mActivity);
|
TextView changelogView = new TextView(mActivity);
|
||||||
|
|||||||
@@ -1,21 +1,37 @@
|
|||||||
package ru.vtosters.lite.ui.fragments;
|
package ru.vtosters.lite.ui.fragments;
|
||||||
|
|
||||||
|
import android.annotation.SuppressLint;
|
||||||
import android.app.Activity;
|
import android.app.Activity;
|
||||||
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
|
import android.content.SharedPreferences;
|
||||||
import android.os.Build;
|
import android.os.Build;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
|
import android.util.TypedValue;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.WindowInsetsController;
|
import android.view.WindowInsetsController;
|
||||||
|
import android.webkit.WebView;
|
||||||
|
import android.widget.RadioButton;
|
||||||
|
import android.widget.RadioGroup;
|
||||||
import android.widget.Toast;
|
import android.widget.Toast;
|
||||||
|
import androidx.appcompat.view.ContextThemeWrapper;
|
||||||
|
import b.h.g.m.FileUtils;
|
||||||
import com.vk.core.dialogs.alert.VkAlertDialog;
|
import com.vk.core.dialogs.alert.VkAlertDialog;
|
||||||
|
import com.vk.im.engine.ImEngine1;
|
||||||
|
import com.vk.im.engine.ImEngineExt;
|
||||||
|
import com.vk.im.ui.providers.audiomsg.ImAudioMsgPlayerProvider;
|
||||||
|
import com.vk.im.ui.providers.audiomsg.PlayerActionSources;
|
||||||
|
import com.vk.imageloader.VKImageLoader;
|
||||||
|
import com.vk.media.player.cache.AutoPlayCacheHolder;
|
||||||
|
import com.vk.mediastore.MediaStorage;
|
||||||
|
import com.vk.stickers.Stickers;
|
||||||
|
import com.vtosters.lite.im.ImEngineProvider;
|
||||||
|
import ru.vtosters.hooks.SwitchHook;
|
||||||
import ru.vtosters.hooks.other.Preferences;
|
import ru.vtosters.hooks.other.Preferences;
|
||||||
import ru.vtosters.hooks.other.ThemesUtils;
|
import ru.vtosters.hooks.other.ThemesUtils;
|
||||||
import ru.vtosters.lite.ui.PreferenceFragmentUtils;
|
import ru.vtosters.lite.ui.PreferenceFragmentUtils;
|
||||||
import ru.vtosters.lite.ui.components.BackupManager;
|
import ru.vtosters.lite.ui.components.BackupManager;
|
||||||
import ru.vtosters.lite.utils.AccountManagerUtils;
|
import ru.vtosters.lite.utils.*;
|
||||||
import ru.vtosters.lite.utils.AndroidUtils;
|
|
||||||
import ru.vtosters.lite.utils.LifecycleUtils;
|
|
||||||
import ru.vtosters.lite.utils.VKAccountDB;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
|
||||||
@@ -58,6 +74,114 @@ public class DataSettingsFragment extends TrackedMaterialPreferenceToolbarFragme
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PreferenceFragmentUtils.addPreferenceCategory(getPreferenceScreen(), AndroidUtils.getString("data"));
|
||||||
|
|
||||||
|
PreferenceFragmentUtils.addPreference(
|
||||||
|
getPreferenceScreen(),
|
||||||
|
"currcache",
|
||||||
|
getString(com.vtosters.lite.R.string.cache_size),
|
||||||
|
getString(com.vtosters.lite.R.string.cache_size_summ) + ": " + CacheUtils.humanReadableByteCountBin(IOUtils.getDirSize(AndroidUtils.getGlobalContext().getCacheDir())),
|
||||||
|
null,
|
||||||
|
preference -> {
|
||||||
|
new VkAlertDialog.Builder(requireContext())
|
||||||
|
.setTitle(getString(com.vtosters.lite.R.string.clear_all_cache))
|
||||||
|
.setPositiveButton(requireContext().getString(com.vtosters.lite.R.string.yes), (dialogInterface, i) -> {
|
||||||
|
new WebView(requireContext()).clearCache(true);
|
||||||
|
VKImageLoader.e();
|
||||||
|
ImAudioMsgPlayerProvider.b().e(PlayerActionSources.a);
|
||||||
|
ImAudioMsgPlayerProvider.b().d(PlayerActionSources.a);
|
||||||
|
FileUtils.l();
|
||||||
|
AutoPlayCacheHolder.d.a();
|
||||||
|
MediaStorage.a();
|
||||||
|
updateCacheSize();
|
||||||
|
})
|
||||||
|
.setNegativeButton(requireContext().getString(com.vtosters.lite.R.string.cancel), (dialogInterface, i) -> dialogInterface.dismiss())
|
||||||
|
.show();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
PreferenceFragmentUtils.addPreference(
|
||||||
|
getPreferenceScreen(),
|
||||||
|
"",
|
||||||
|
AndroidUtils.getString("clearcache_other_title"),
|
||||||
|
"",
|
||||||
|
null,
|
||||||
|
preference -> {
|
||||||
|
new VkAlertDialog.Builder(getContext())
|
||||||
|
.setTitle(requireContext().getString(com.vtosters.lite.R.string.select_which_clean))
|
||||||
|
.setItems(AndroidUtils.getArray(com.vtosters.lite.R.array.cache_cleaner), (dialog, which) -> {
|
||||||
|
switch (which) {
|
||||||
|
case 0 -> {
|
||||||
|
SharedPreferences prefs2 = getContext().getSharedPreferences("stickers_storage", Context.MODE_PRIVATE);
|
||||||
|
prefs2.edit().clear().commit();
|
||||||
|
new WebView(requireContext()).clearCache(true);
|
||||||
|
VKImageLoader.e();
|
||||||
|
ImEngineProvider.b().a();
|
||||||
|
ImAudioMsgPlayerProvider.b().e(PlayerActionSources.a);
|
||||||
|
ImAudioMsgPlayerProvider.b().d(PlayerActionSources.a);
|
||||||
|
FileUtils.l();
|
||||||
|
Stickers.l.c();
|
||||||
|
ImEngineExt.a(ImEngine1.a());
|
||||||
|
AutoPlayCacheHolder.d.a();
|
||||||
|
MediaStorage.a();
|
||||||
|
}
|
||||||
|
case 1 -> {
|
||||||
|
SharedPreferences prefs2 = getContext().getSharedPreferences("stickers_storage", Context.MODE_PRIVATE);
|
||||||
|
prefs2.edit().clear().commit();
|
||||||
|
Stickers.l.c();
|
||||||
|
}
|
||||||
|
case 2 -> {
|
||||||
|
VKImageLoader.e();
|
||||||
|
ImEngineExt.a(ImEngine1.a());
|
||||||
|
}
|
||||||
|
case 3 -> {
|
||||||
|
AutoPlayCacheHolder.d.a();
|
||||||
|
MediaStorage.a();
|
||||||
|
}
|
||||||
|
case 4 -> {
|
||||||
|
ImEngineProvider.b().a();
|
||||||
|
ImAudioMsgPlayerProvider.b().e(PlayerActionSources.a);
|
||||||
|
ImAudioMsgPlayerProvider.b().d(PlayerActionSources.a);
|
||||||
|
}
|
||||||
|
case 5 -> new WebView(requireContext()).clearCache(true);
|
||||||
|
}
|
||||||
|
Toast.makeText(getContext(), requireContext().getString(com.vtosters.lite.R.string.cache_cleaned), Toast.LENGTH_SHORT).show();
|
||||||
|
updateCacheSize();
|
||||||
|
})
|
||||||
|
.show();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
PreferenceFragmentUtils.addPreference(
|
||||||
|
getPreferenceScreen(),
|
||||||
|
"autoclearcache_btn",
|
||||||
|
AndroidUtils.getString("autoclearcache"),
|
||||||
|
"",
|
||||||
|
null,
|
||||||
|
preference -> {
|
||||||
|
cacheAutoCleanDialog();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
var pref = Preferences.getPreferences().getString("autoclearcache", "Default");
|
||||||
|
switch (pref) {
|
||||||
|
case "Default" ->
|
||||||
|
findPreference("autoclearcache_btn").setSummary(requireContext().getString(com.vtosters.lite.R.string.cache_disabled));
|
||||||
|
case "100mb" ->
|
||||||
|
findPreference("autoclearcache_btn").setSummary(requireContext().getString(com.vtosters.lite.R.string.cache_100mb));
|
||||||
|
case "500mb" ->
|
||||||
|
findPreference("autoclearcache_btn").setSummary(requireContext().getString(com.vtosters.lite.R.string.cache_500mb));
|
||||||
|
case "1gb" ->
|
||||||
|
findPreference("autoclearcache_btn").setSummary(requireContext().getString(com.vtosters.lite.R.string.cache_1gb));
|
||||||
|
case "2gb" ->
|
||||||
|
findPreference("autoclearcache_btn").setSummary(requireContext().getString(com.vtosters.lite.R.string.cache_2gb));
|
||||||
|
case "5gb" ->
|
||||||
|
findPreference("autoclearcache_btn").setSummary(requireContext().getString(com.vtosters.lite.R.string.cache_5gb));
|
||||||
|
}
|
||||||
|
|
||||||
PreferenceFragmentUtils.addPreferenceCategory(getPreferenceScreen(), AndroidUtils.getString("accounts"));
|
PreferenceFragmentUtils.addPreferenceCategory(getPreferenceScreen(), AndroidUtils.getString("accounts"));
|
||||||
|
|
||||||
PreferenceFragmentUtils.addPreference(
|
PreferenceFragmentUtils.addPreference(
|
||||||
@@ -177,4 +301,59 @@ public class DataSettingsFragment extends TrackedMaterialPreferenceToolbarFragme
|
|||||||
|
|
||||||
findPreference("analyticsDisabled").setVisible(Preferences.isValidSignature());
|
findPreference("analyticsDisabled").setVisible(Preferences.isValidSignature());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void updateCacheSize() {
|
||||||
|
findPreference("currcache").setSummary(getString(com.vtosters.lite.R.string.cache_size_summ) + ": " + CacheUtils.humanReadableByteCountBin(IOUtils.getDirSize(AndroidUtils.getGlobalContext().getCacheDir())));
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressLint({"CommitPrefEdits", "SetTextI18n"})
|
||||||
|
private void cacheAutoCleanDialog() {
|
||||||
|
String[] cacheText = {null, "100 MB", "500 MB", "1 GB", "2 GB", "5 GB"};
|
||||||
|
|
||||||
|
var val = Preferences.getPreferences().getInt("autoclearcache_size", 0);
|
||||||
|
RadioGroup rg = new RadioGroup(getContext());
|
||||||
|
|
||||||
|
rg.setPadding(AndroidUtils.dp2px(18f), AndroidUtils.dp2px(12f), AndroidUtils.dp2px(18f), 0);
|
||||||
|
|
||||||
|
for (int item = 0; item <= 5; item++) {
|
||||||
|
RadioButton rb = new RadioButton(new ContextThemeWrapper(getContext(), com.vtosters.lite.R.style.Widget_AppCompat_CompoundButton_RadioButton));
|
||||||
|
SwitchHook.setCompoundButton(rb);
|
||||||
|
rg.addView(rb);
|
||||||
|
rb.setId(item);
|
||||||
|
rb.setTextSize(TypedValue.COMPLEX_UNIT_PX, AndroidUtils.dp2px(14f));
|
||||||
|
|
||||||
|
var text = cacheText[item];
|
||||||
|
rb.setText(text != null ? text : AndroidUtils.getString("autoclearcachedisabled"));
|
||||||
|
|
||||||
|
rb.setTextColor(ThemesUtils.getTextAttr());
|
||||||
|
rb.setChecked(val == item);
|
||||||
|
}
|
||||||
|
|
||||||
|
new VkAlertDialog.Builder(getContext())
|
||||||
|
.setTitle(requireContext().getString(com.vtosters.lite.R.string.cache_clean_title))
|
||||||
|
.setMessage(requireContext().getString(com.vtosters.lite.R.string.cache_select_size))
|
||||||
|
.setCancelable(true)
|
||||||
|
.setNegativeButton(requireContext().getString(com.vtosters.lite.R.string.cancel), null)
|
||||||
|
.setView(rg)
|
||||||
|
.setPositiveButton(requireContext().getString(com.vtosters.lite.R.string.save), (dialog, which) -> {
|
||||||
|
var sizes = new String[]{"Default", "100mb", "500mb", "1gb", "2gb", "5gb"};
|
||||||
|
var id = rg.getCheckedRadioButtonId();
|
||||||
|
Preferences.getPreferences().edit()
|
||||||
|
.putInt("autoclearcache_size", id)
|
||||||
|
.putString("autoclearcache", sizes[id])
|
||||||
|
.apply();
|
||||||
|
})
|
||||||
|
.show();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int T4() {
|
||||||
|
return com.vtosters.lite.R.string.data;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onResume() {
|
||||||
|
super.onResume();
|
||||||
|
updateCacheSize();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -82,6 +82,9 @@ public class DockBarEditorFragment extends BaseToolbarFragment {
|
|||||||
holder.bindMovingItem(tab.iconID, tab.titleID);
|
holder.bindMovingItem(tab.iconID, tab.titleID);
|
||||||
});
|
});
|
||||||
adapter.setMinAndMaxCounts(DockBarEditorManager.MIN_SELECTED_TABS, DockBarEditorManager.MAX_SELECTED_TABS);
|
adapter.setMinAndMaxCounts(DockBarEditorManager.MIN_SELECTED_TABS, DockBarEditorManager.MAX_SELECTED_TABS);
|
||||||
|
adapter.setExceptions(
|
||||||
|
DockBarEditorManager.getTabByTag("tab_profile"),
|
||||||
|
DockBarEditorManager.getTabByTag("")/*settings*/);
|
||||||
|
|
||||||
var recyclerView = new RecyclerView(requireContext());
|
var recyclerView = new RecyclerView(requireContext());
|
||||||
recyclerView.setLayoutManager(new LinearLayoutManager(getContext()));
|
recyclerView.setLayoutManager(new LinearLayoutManager(getContext()));
|
||||||
|
|||||||
@@ -17,7 +17,6 @@ import com.vtosters.lite.R;
|
|||||||
import okhttp3.Headers;
|
import okhttp3.Headers;
|
||||||
import okhttp3.OkHttpClient;
|
import okhttp3.OkHttpClient;
|
||||||
import okhttp3.Request;
|
import okhttp3.Request;
|
||||||
import org.json.JSONException;
|
|
||||||
import org.json.JSONObject;
|
import org.json.JSONObject;
|
||||||
import ru.vtosters.hooks.other.Preferences;
|
import ru.vtosters.hooks.other.Preferences;
|
||||||
import ru.vtosters.hooks.other.ThemesUtils;
|
import ru.vtosters.hooks.other.ThemesUtils;
|
||||||
@@ -33,7 +32,6 @@ import ru.vtosters.lite.utils.AndroidUtils;
|
|||||||
import ru.vtosters.lite.utils.LifecycleUtils;
|
import ru.vtosters.lite.utils.LifecycleUtils;
|
||||||
import ru.vtosters.lite.utils.SearchEngine;
|
import ru.vtosters.lite.utils.SearchEngine;
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.concurrent.ExecutorService;
|
import java.util.concurrent.ExecutorService;
|
||||||
import java.util.concurrent.Executors;
|
import java.util.concurrent.Executors;
|
||||||
@@ -261,7 +259,7 @@ public class MediaFragment extends TrackedMaterialPreferenceToolbarFragment {
|
|||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
});;
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private void deleteVideoHistoryDialog(Context context) {
|
private void deleteVideoHistoryDialog(Context context) {
|
||||||
|
|||||||
@@ -1,35 +1,16 @@
|
|||||||
package ru.vtosters.lite.ui.fragments;
|
package ru.vtosters.lite.ui.fragments;
|
||||||
|
|
||||||
import android.annotation.SuppressLint;
|
|
||||||
import android.app.Activity;
|
import android.app.Activity;
|
||||||
import android.content.*;
|
import android.content.*;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.util.TypedValue;
|
|
||||||
import android.webkit.WebView;
|
|
||||||
import android.widget.RadioButton;
|
|
||||||
import android.widget.RadioGroup;
|
|
||||||
import android.widget.Toast;
|
import android.widget.Toast;
|
||||||
import androidx.appcompat.view.ContextThemeWrapper;
|
|
||||||
import b.h.g.m.FileUtils;
|
|
||||||
import com.vk.auth.api.VKAccount;
|
import com.vk.auth.api.VKAccount;
|
||||||
import com.vk.core.dialogs.alert.VkAlertDialog;
|
|
||||||
import com.vk.core.util.ToastUtils;
|
import com.vk.core.util.ToastUtils;
|
||||||
import com.vk.im.engine.ImEngine1;
|
|
||||||
import com.vk.im.engine.ImEngineExt;
|
|
||||||
import com.vk.im.ui.providers.audiomsg.ImAudioMsgPlayerProvider;
|
|
||||||
import com.vk.im.ui.providers.audiomsg.PlayerActionSources;
|
|
||||||
import com.vk.imageloader.VKImageLoader;
|
|
||||||
import com.vk.media.player.cache.AutoPlayCacheHolder;
|
|
||||||
import com.vk.mediastore.MediaStorage;
|
|
||||||
import com.vk.pushes.PushSubscriber;
|
import com.vk.pushes.PushSubscriber;
|
||||||
import com.vk.stickers.Stickers;
|
|
||||||
import com.vtosters.lite.R;
|
import com.vtosters.lite.R;
|
||||||
import com.vtosters.lite.auth.VKAccountManager;
|
import com.vtosters.lite.auth.VKAccountManager;
|
||||||
import com.vtosters.lite.im.ImEngineProvider;
|
|
||||||
import ru.vtosters.hooks.GmsHook;
|
import ru.vtosters.hooks.GmsHook;
|
||||||
import ru.vtosters.hooks.SwitchHook;
|
|
||||||
import ru.vtosters.hooks.other.Preferences;
|
import ru.vtosters.hooks.other.Preferences;
|
||||||
import ru.vtosters.hooks.other.ThemesUtils;
|
|
||||||
import ru.vtosters.lite.deviceinfo.DeviceInfoCollector;
|
import ru.vtosters.lite.deviceinfo.DeviceInfoCollector;
|
||||||
import ru.vtosters.lite.ssfs.UsersList;
|
import ru.vtosters.lite.ssfs.UsersList;
|
||||||
import ru.vtosters.lite.ui.activities.VKAdminTokenActivity;
|
import ru.vtosters.lite.ui.activities.VKAdminTokenActivity;
|
||||||
@@ -111,11 +92,6 @@ public class OtherFragment extends TrackedMaterialPreferenceToolbarFragment {
|
|||||||
return true;
|
return true;
|
||||||
});
|
});
|
||||||
|
|
||||||
findPreference("clearcache").setOnPreferenceClickListener(preference -> {
|
|
||||||
cacheCleanDialog();
|
|
||||||
return true;
|
|
||||||
});
|
|
||||||
|
|
||||||
findPreference("copyownlink").setOnPreferenceClickListener(preference -> {
|
findPreference("copyownlink").setOnPreferenceClickListener(preference -> {
|
||||||
copyText("https://vk.com/id" + AccountManagerUtils.getUserId());
|
copyText("https://vk.com/id" + AccountManagerUtils.getUserId());
|
||||||
ToastUtils.a(requireContext().getString(R.string.link_copied));
|
ToastUtils.a(requireContext().getString(R.string.link_copied));
|
||||||
@@ -127,11 +103,6 @@ public class OtherFragment extends TrackedMaterialPreferenceToolbarFragment {
|
|||||||
return true;
|
return true;
|
||||||
});
|
});
|
||||||
|
|
||||||
findPreference("autoclearcache").setOnPreferenceClickListener(preference -> {
|
|
||||||
cacheAutoCleanDialog();
|
|
||||||
return true;
|
|
||||||
});
|
|
||||||
|
|
||||||
findPreference("datasettings").setOnPreferenceClickListener(preference -> {
|
findPreference("datasettings").setOnPreferenceClickListener(preference -> {
|
||||||
NavigatorUtils.switchFragment(requireContext(), DataSettingsFragment.class);
|
NavigatorUtils.switchFragment(requireContext(), DataSettingsFragment.class);
|
||||||
return true;
|
return true;
|
||||||
@@ -146,19 +117,6 @@ public class OtherFragment extends TrackedMaterialPreferenceToolbarFragment {
|
|||||||
return true;
|
return true;
|
||||||
});
|
});
|
||||||
|
|
||||||
var pref = Preferences.getPreferences().getString("autoclearcache", "Default");
|
|
||||||
switch (pref) {
|
|
||||||
case "Default" ->
|
|
||||||
findPreference("autoclearcache").setSummary(requireContext().getString(R.string.cache_disabled));
|
|
||||||
case "100mb" ->
|
|
||||||
findPreference("autoclearcache").setSummary(requireContext().getString(R.string.cache_100mb));
|
|
||||||
case "500mb" ->
|
|
||||||
findPreference("autoclearcache").setSummary(requireContext().getString(R.string.cache_500mb));
|
|
||||||
case "1gb" -> findPreference("autoclearcache").setSummary(requireContext().getString(R.string.cache_1gb));
|
|
||||||
case "2gb" -> findPreference("autoclearcache").setSummary(requireContext().getString(R.string.cache_2gb));
|
|
||||||
case "5gb" -> findPreference("autoclearcache").setSummary(requireContext().getString(R.string.cache_5gb));
|
|
||||||
}
|
|
||||||
|
|
||||||
var vkAdminTokenPref = findPreference("vk_admin_token");
|
var vkAdminTokenPref = findPreference("vk_admin_token");
|
||||||
vkAdminTokenPref.setVisible(Preferences.getPreferences().getBoolean("new_music_downloading_way", false));
|
vkAdminTokenPref.setVisible(Preferences.getPreferences().getBoolean("new_music_downloading_way", false));
|
||||||
if (vkAdminTokenPref.isVisible()) {
|
if (vkAdminTokenPref.isVisible()) {
|
||||||
@@ -170,93 +128,6 @@ public class OtherFragment extends TrackedMaterialPreferenceToolbarFragment {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressLint({"CommitPrefEdits", "SetTextI18n"})
|
|
||||||
private void cacheAutoCleanDialog() {
|
|
||||||
String[] cacheText = {null, "100 MB", "500 MB", "1 GB", "2 GB", "5 GB"};
|
|
||||||
|
|
||||||
var val = Preferences.getPreferences().getInt("autoclearcache_size", 0);
|
|
||||||
RadioGroup rg = new RadioGroup(getContext());
|
|
||||||
|
|
||||||
rg.setPadding(AndroidUtils.dp2px(18f), AndroidUtils.dp2px(12f), AndroidUtils.dp2px(18f), 0);
|
|
||||||
|
|
||||||
for (int item = 0; item <= 5; item++) {
|
|
||||||
RadioButton rb = new RadioButton(new ContextThemeWrapper(getContext(), com.vtosters.lite.R.style.Widget_AppCompat_CompoundButton_RadioButton));
|
|
||||||
SwitchHook.setCompoundButton(rb);
|
|
||||||
rg.addView(rb);
|
|
||||||
rb.setId(item);
|
|
||||||
rb.setTextSize(TypedValue.COMPLEX_UNIT_PX, AndroidUtils.dp2px(14f));
|
|
||||||
|
|
||||||
var text = cacheText[item];
|
|
||||||
rb.setText(text != null ? text : AndroidUtils.getString("autoclearcachedisabled"));
|
|
||||||
|
|
||||||
rb.setTextColor(ThemesUtils.getTextAttr());
|
|
||||||
rb.setChecked(val == item);
|
|
||||||
}
|
|
||||||
|
|
||||||
new VkAlertDialog.Builder(getContext())
|
|
||||||
.setTitle(requireContext().getString(R.string.cache_clean_title))
|
|
||||||
.setMessage(requireContext().getString(R.string.cache_select_size))
|
|
||||||
.setCancelable(true)
|
|
||||||
.setNegativeButton(requireContext().getString(R.string.cancel), null)
|
|
||||||
.setView(rg)
|
|
||||||
.setPositiveButton(requireContext().getString(R.string.save), (dialog, which) -> {
|
|
||||||
var sizes = new String[]{"Default", "100mb", "500mb", "1gb", "2gb", "5gb"};
|
|
||||||
var id = rg.getCheckedRadioButtonId();
|
|
||||||
Preferences.getPreferences().edit()
|
|
||||||
.putInt("autoclearcache_size", id)
|
|
||||||
.putString("autoclearcache", sizes[id])
|
|
||||||
.apply();
|
|
||||||
})
|
|
||||||
.show();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void cacheCleanDialog() {
|
|
||||||
new VkAlertDialog.Builder(getContext())
|
|
||||||
.setTitle(requireContext().getString(R.string.select_which_clean))
|
|
||||||
.setItems(AndroidUtils.getArray(R.array.cache_cleaner), (dialog, which) -> {
|
|
||||||
switch (which) {
|
|
||||||
case 0 -> {
|
|
||||||
SharedPreferences prefs2 = getContext().getSharedPreferences("stickers_storage", Context.MODE_PRIVATE);
|
|
||||||
prefs2.edit().clear().commit();
|
|
||||||
clearWebViewCache();
|
|
||||||
VKImageLoader.e();
|
|
||||||
ImEngineProvider.b().a();
|
|
||||||
ImAudioMsgPlayerProvider.b().e(PlayerActionSources.a);
|
|
||||||
ImAudioMsgPlayerProvider.b().d(PlayerActionSources.a);
|
|
||||||
FileUtils.l();
|
|
||||||
Stickers.l.c();
|
|
||||||
ImEngineExt.a(ImEngine1.a());
|
|
||||||
AutoPlayCacheHolder.d.a();
|
|
||||||
MediaStorage.a();
|
|
||||||
}
|
|
||||||
case 1 -> {
|
|
||||||
SharedPreferences prefs2 = getContext().getSharedPreferences("stickers_storage", Context.MODE_PRIVATE);
|
|
||||||
prefs2.edit().clear().commit();
|
|
||||||
Stickers.l.c();
|
|
||||||
}
|
|
||||||
case 2 -> {
|
|
||||||
VKImageLoader.e();
|
|
||||||
ImEngineExt.a(ImEngine1.a());
|
|
||||||
}
|
|
||||||
case 3 -> {
|
|
||||||
AutoPlayCacheHolder.d.a();
|
|
||||||
MediaStorage.a();
|
|
||||||
}
|
|
||||||
case 4 -> {
|
|
||||||
ImEngineProvider.b().a();
|
|
||||||
ImAudioMsgPlayerProvider.b().e(PlayerActionSources.a);
|
|
||||||
ImAudioMsgPlayerProvider.b().d(PlayerActionSources.a);
|
|
||||||
}
|
|
||||||
case 5 -> clearWebViewCache();
|
|
||||||
}
|
|
||||||
Toast.makeText(getContext(), requireContext().getString(R.string.cache_cleaned), Toast.LENGTH_SHORT).show();
|
|
||||||
})
|
|
||||||
.show();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void clearWebViewCache() {
|
|
||||||
new WebView(requireContext()).clearCache(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void copyText(String src) {
|
private void copyText(String src) {
|
||||||
var manager = (ClipboardManager) requireContext().getSystemService(Context.CLIPBOARD_SERVICE);
|
var manager = (ClipboardManager) requireContext().getSystemService(Context.CLIPBOARD_SERVICE);
|
||||||
|
|||||||
@@ -43,15 +43,15 @@ public class ThemesFragment extends TrackedMaterialPreferenceToolbarFragment {
|
|||||||
|
|
||||||
findPreference("systememoji").setSummary(AndroidUtils.getGlobalContext().getString(R.string.systememojisum) + " \uD83D\uDE00\uD83D\uDE01\uD83E\uDD11\uD83E\uDD75\uD83D\uDC4D");
|
findPreference("systememoji").setSummary(AndroidUtils.getGlobalContext().getString(R.string.systememojisum) + " \uD83D\uDE00\uD83D\uDE01\uD83E\uDD11\uD83E\uDD75\uD83D\uDC4D");
|
||||||
|
|
||||||
findPreference("useNewColorEngine").setVisible(Preferences.dev());
|
|
||||||
|
|
||||||
var invalidateThemeCache = findPreference("invalidate_theme_cache");
|
var invalidateThemeCache = findPreference("invalidate_theme_cache");
|
||||||
if (ThemesUtils.getReservedAccent() != Color.TRANSPARENT && Preferences.dev() && ThemesUtils.useNewColorEngine())
|
if (ThemesUtils.getReservedAccent() != Color.TRANSPARENT && Preferences.dev()) {
|
||||||
invalidateThemeCache.setOnPreferenceClickListener(preference -> {
|
invalidateThemeCache.setOnPreferenceClickListener(preference -> {
|
||||||
setAccentColor(ThemesUtils.getReservedAccent());
|
setAccentColor(ThemesUtils.getReservedAccent());
|
||||||
return true;
|
return true;
|
||||||
});
|
});
|
||||||
else invalidateThemeCache.setVisible(false);
|
} else {
|
||||||
|
invalidateThemeCache.setVisible(false);
|
||||||
|
}
|
||||||
|
|
||||||
var navBarPreference = findPreference("navbar");
|
var navBarPreference = findPreference("navbar");
|
||||||
navBarPreference.setOnPreferenceClickListener(preference -> {
|
navBarPreference.setOnPreferenceClickListener(preference -> {
|
||||||
@@ -156,12 +156,8 @@ public class ThemesFragment extends TrackedMaterialPreferenceToolbarFragment {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
.setNegativeButton(R.string.reset, (dialog, which) -> {
|
.setNegativeButton(R.string.reset, (dialog, which) -> {
|
||||||
if (ThemesUtils.useNewColorEngine()) {
|
ThemesManager.deleteModification();
|
||||||
ThemesManager.deleteModification();
|
ThemesUtils.reserveAccentColor(Color.TRANSPARENT, false);
|
||||||
ThemesUtils.reserveAccentColor(Color.TRANSPARENT, false);
|
|
||||||
} else {
|
|
||||||
ThemesUtils.setCustomAccentColor(0, false);
|
|
||||||
}
|
|
||||||
restart();
|
restart();
|
||||||
})
|
})
|
||||||
.setPositiveButton(R.string.cancel, null)
|
.setPositiveButton(R.string.cancel, null)
|
||||||
@@ -207,35 +203,29 @@ public class ThemesFragment extends TrackedMaterialPreferenceToolbarFragment {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void setAccentColor(int color) {
|
void setAccentColor(int color) {
|
||||||
if (ThemesUtils.useNewColorEngine()) {
|
final VKProgressDialog dialog = new VKProgressDialog(requireContext());
|
||||||
final VKProgressDialog dialog = new VKProgressDialog(requireContext());
|
dialog.setCancelable(false);
|
||||||
dialog.setCancelable(false);
|
dialog.setMessage(AndroidUtils.getString("applying_accent") + "...");
|
||||||
dialog.setMessage(AndroidUtils.getString("applying_accent") + "...");
|
dialog.show();
|
||||||
dialog.show();
|
|
||||||
|
|
||||||
VTExecutors.getIoExecutor().execute(() -> {
|
VTExecutors.getIoExecutor().execute(() -> {
|
||||||
try {
|
try {
|
||||||
ThemesUtils.reserveAccentColor(color, true);
|
ThemesUtils.reserveAccentColor(color, true);
|
||||||
ThemesManager.generateModApk(color);
|
ThemesManager.generateModApk(color);
|
||||||
requireActivity().runOnUiThread(this::restart);
|
requireActivity().runOnUiThread(this::restart);
|
||||||
} catch (Throwable e) {
|
} catch (Throwable e) {
|
||||||
Log.e("ThemesFragment", e.getMessage());
|
Log.e("ThemesFragment", e.getMessage());
|
||||||
ThemesManager.deleteModification();
|
ThemesManager.deleteModification();
|
||||||
requireActivity().runOnUiThread(() -> {
|
requireActivity().runOnUiThread(() -> {
|
||||||
dialog.dismiss();
|
dialog.dismiss();
|
||||||
new VkAlertDialog.Builder(requireContext())
|
new VkAlertDialog.Builder(requireContext())
|
||||||
.setTitle(AndroidUtils.getString("error"))
|
.setTitle(AndroidUtils.getString("error"))
|
||||||
.setMessage(AndroidUtils.getString("error_applying_accent") + ":\n" + e)
|
.setMessage(AndroidUtils.getString("error_applying_accent") + ":\n" + e)
|
||||||
.setPositiveButton("OK", null)
|
.setPositiveButton("OK", null)
|
||||||
.show();
|
.show();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
} else {
|
|
||||||
ThemesUtils.setCustomAccentColor(color, false);
|
|
||||||
ThemesCore.setThemedColors(color);
|
|
||||||
restart();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void restart() {
|
void restart() {
|
||||||
|
|||||||
@@ -31,4 +31,9 @@ public class DockBarTab {
|
|||||||
Class<?> fragmentClass) {
|
Class<?> fragmentClass) {
|
||||||
return new DockBarTab(tag, iconID, titleID, resID, fragmentClass);
|
return new DockBarTab(tag, iconID, titleID, resID, fragmentClass);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object arg) {
|
||||||
|
return this.id == ((DockBarTab) arg).id;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,4 +13,10 @@ public class SuperAppItem {
|
|||||||
public static SuperAppItem valuesOf(String type, String title) {
|
public static SuperAppItem valuesOf(String type, String title) {
|
||||||
return new SuperAppItem(type, title);
|
return new SuperAppItem(type, title);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object arg) {
|
||||||
|
var item = (SuperAppItem) arg;
|
||||||
|
return this.type.equals(item.type) && this.title.equals(item.title);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -37,16 +37,16 @@ public class AlphaView extends SliderViewBase implements ColorObserver {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected Bitmap makeBitmap(int w, int h) {
|
protected Bitmap makeBitmap(int w, int h) {
|
||||||
final boolean isWide = w > h;
|
boolean isWide = w > h;
|
||||||
final int n = Math.max(w, h);
|
int n = Math.max(w, h);
|
||||||
int color = observableColor.getColor();
|
int color = observableColor.getColor();
|
||||||
int[] colors = new int[n];
|
int[] colors = new int[n];
|
||||||
for (int i = 0; i < n; ++i) {
|
for (int i = 0; i < n; ++i) {
|
||||||
float alpha = isWide ? (float) i / n : 1 - (float) i / n;
|
float alpha = isWide ? (float) i / n : 1 - (float) i / n;
|
||||||
colors[i] = color & 0xffffff | (int) (alpha * 0xff) << 24;
|
colors[i] = color & 0xffffff | (int) (alpha * 0xff) << 24;
|
||||||
}
|
}
|
||||||
final int bmpWidth = isWide ? w : 1;
|
int bmpWidth = isWide ? w : 1;
|
||||||
final int bmpHeight = isWide ? 1 : h;
|
int bmpHeight = isWide ? 1 : h;
|
||||||
return Bitmap.createBitmap(colors, bmpWidth, bmpHeight, Bitmap.Config.ARGB_8888);
|
return Bitmap.createBitmap(colors, bmpWidth, bmpHeight, Bitmap.Config.ARGB_8888);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -18,13 +18,12 @@ class HexEdit {
|
|||||||
new HexFilter()
|
new HexFilter()
|
||||||
};
|
};
|
||||||
|
|
||||||
public static void setUpListeners(final EditText hexEdit, final ObservableColor observableColor) {
|
public static void setUpListeners(EditText hexEdit, ObservableColor observableColor) {
|
||||||
|
|
||||||
class MultiObserver implements ColorObserver, TextWatcher {
|
class MultiObserver implements ColorObserver, TextWatcher {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void updateColor(ObservableColor observableColor) {
|
public void updateColor(ObservableColor observableColor) {
|
||||||
final String colorString = formatColor(observableColor.getColor());
|
String colorString = formatColor(observableColor.getColor());
|
||||||
// Prevent onTextChanged getting called when we update text programmatically
|
// Prevent onTextChanged getting called when we update text programmatically
|
||||||
hexEdit.removeTextChangedListener(this);
|
hexEdit.removeTextChangedListener(this);
|
||||||
hexEdit.setText(colorString);
|
hexEdit.setText(colorString);
|
||||||
@@ -57,7 +56,7 @@ class HexEdit {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
final MultiObserver multiObserver = new MultiObserver();
|
MultiObserver multiObserver = new MultiObserver();
|
||||||
hexEdit.addTextChangedListener(multiObserver);
|
hexEdit.addTextChangedListener(multiObserver);
|
||||||
observableColor.addObserver(multiObserver);
|
observableColor.addObserver(multiObserver);
|
||||||
setShowAlphaDigits(hexEdit, true);
|
setShowAlphaDigits(hexEdit, true);
|
||||||
@@ -71,14 +70,13 @@ class HexEdit {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void setShowAlphaDigits(final EditText hexEdit, boolean showAlphaDigits) {
|
public static void setShowAlphaDigits(EditText hexEdit, boolean showAlphaDigits) {
|
||||||
hexEdit.setFilters(showAlphaDigits ? withAlphaDigits : withoutAlphaDigits);
|
hexEdit.setFilters(showAlphaDigits ? withAlphaDigits : withoutAlphaDigits);
|
||||||
hexEdit.setText(hexEdit.getText()); // trigger a reformat of text
|
hexEdit.setText(hexEdit.getText()); // trigger a reformat of text
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private static class ColorPasteLengthFilter implements InputFilter {
|
private static class ColorPasteLengthFilter implements InputFilter {
|
||||||
|
|
||||||
private static final int MAX_LENGTH = 6;
|
private static final int MAX_LENGTH = 6;
|
||||||
private static final int PASTED_LEN = 8;
|
private static final int PASTED_LEN = 8;
|
||||||
private final InputFilter sixDigitFilter = new InputFilter.LengthFilter(MAX_LENGTH);
|
private final InputFilter sixDigitFilter = new InputFilter.LengthFilter(MAX_LENGTH);
|
||||||
@@ -86,8 +84,8 @@ class HexEdit {
|
|||||||
public CharSequence filter(CharSequence source, int start, int end, Spanned dest, int dstart, int dend) {
|
public CharSequence filter(CharSequence source, int start, int end, Spanned dest, int dstart, int dend) {
|
||||||
// If 8 digits have been pasted, replacing all source, trim alpha digits.
|
// If 8 digits have been pasted, replacing all source, trim alpha digits.
|
||||||
// Otherwise standard LengthFilter behavior.
|
// Otherwise standard LengthFilter behavior.
|
||||||
final int srcLength = end - start;
|
int srcLength = end - start;
|
||||||
final int dstSelLength = dend - dstart;
|
int dstSelLength = dend - dstart;
|
||||||
if (srcLength == PASTED_LEN && dstSelLength == dest.length()) {
|
if (srcLength == PASTED_LEN && dstSelLength == dest.length()) {
|
||||||
// Discard alpha digits:
|
// Discard alpha digits:
|
||||||
return source.subSequence(PASTED_LEN - MAX_LENGTH, PASTED_LEN);
|
return source.subSequence(PASTED_LEN - MAX_LENGTH, PASTED_LEN);
|
||||||
@@ -98,7 +96,6 @@ class HexEdit {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private static class HexFilter implements InputFilter {
|
private static class HexFilter implements InputFilter {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public CharSequence filter(CharSequence source, int start, int end, Spanned dest, int dstart, int dend) {
|
public CharSequence filter(CharSequence source, int start, int end, Spanned dest, int dstart, int dend) {
|
||||||
boolean state = true;
|
boolean state = true;
|
||||||
|
|||||||
@@ -57,9 +57,9 @@ public class HueSatView extends SquareView implements ColorObserver {
|
|||||||
float[] hsv = new float[]{0f, 0f, 1f};
|
float[] hsv = new float[]{0f, 0f, 1f};
|
||||||
for (int y = 0; y < radiusPx; ++y) {
|
for (int y = 0; y < radiusPx; ++y) {
|
||||||
for (int x = 0; x < radiusPx; ++x) {
|
for (int x = 0; x < radiusPx; ++x) {
|
||||||
final int i = x + y * radiusPx;
|
int i = x + y * radiusPx;
|
||||||
final float sat = satForPos(x, y, radiusPx);
|
float sat = satForPos(x, y, radiusPx);
|
||||||
final float arcBleed = 2f / radiusPx; // extend curved edge pixels just outside clip area.
|
float arcBleed = 2f / radiusPx; // extend curved edge pixels just outside clip area.
|
||||||
if (sat <= 1 + arcBleed) {
|
if (sat <= 1 + arcBleed) {
|
||||||
hsv[0] = hueForPos(x, y, radiusPx);
|
hsv[0] = hueForPos(x, y, radiusPx);
|
||||||
hsv[1] = sat;
|
hsv[1] = sat;
|
||||||
@@ -71,35 +71,35 @@ public class HueSatView extends SquareView implements ColorObserver {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private static float hueForPos(float x, float y, float radiusPx) {
|
private static float hueForPos(float x, float y, float radiusPx) {
|
||||||
final double r = radiusPx - 1; // gives values 0...1 inclusive
|
double r = radiusPx - 1; // gives values 0...1 inclusive
|
||||||
final double dx = (r - x) / r;
|
double dx = (r - x) / r;
|
||||||
final double dy = (r - y) / r;
|
double dy = (r - y) / r;
|
||||||
final double angle = Math.atan2(dy, dx);
|
double angle = Math.atan2(dy, dx);
|
||||||
final double hue = 360 * angle / (Math.PI / 2);
|
double hue = 360 * angle / (Math.PI / 2);
|
||||||
return (float) hue;
|
return (float) hue;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static float satForPos(float x, float y, float radiusPx) {
|
private static float satForPos(float x, float y, float radiusPx) {
|
||||||
final double r = radiusPx - 1; // gives values 0...1 inclusive
|
double r = radiusPx - 1; // gives values 0...1 inclusive
|
||||||
final double dx = (r - x) / r;
|
double dx = (r - x) / r;
|
||||||
final double dy = (r - y) / r;
|
double dy = (r - y) / r;
|
||||||
final double sat = dx * dx + dy * dy; // leave it squared -- exaggerates pale colors
|
double sat = dx * dx + dy * dy; // leave it squared -- exaggerates pale colors
|
||||||
return (float) sat;
|
return (float) sat;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void setPointer(PointF pointer, float hue, float sat, float radiusPx) {
|
private static void setPointer(PointF pointer, float hue, float sat, float radiusPx) {
|
||||||
final float r = radiusPx - 1; // for values 0...1 inclusive
|
float r = radiusPx - 1; // for values 0...1 inclusive
|
||||||
final double distance = r * Math.sqrt(sat);
|
double distance = r * Math.sqrt(sat);
|
||||||
final double angle = hue / 360 * Math.PI / 2;
|
double angle = hue / 360 * Math.PI / 2;
|
||||||
final double dx = distance * Math.cos(angle);
|
double dx = distance * Math.cos(angle);
|
||||||
final double dy = distance * Math.sin(angle);
|
double dy = distance * Math.sin(angle);
|
||||||
pointer.set(r - (float) dx, r - (float) dy);
|
pointer.set(r - (float) dx, r - (float) dy);
|
||||||
}
|
}
|
||||||
|
|
||||||
private int optimalBitmapSize() {
|
private int optimalBitmapSize() {
|
||||||
final int scale = 2;
|
int scale = 2;
|
||||||
final int maxBitmapSize = 128;
|
int maxBitmapSize = 128;
|
||||||
final DisplayMetrics dm = getResources().getDisplayMetrics();
|
DisplayMetrics dm = getResources().getDisplayMetrics();
|
||||||
return Math.min(maxBitmapSize, Math.min(dm.widthPixels, dm.heightPixels) / scale);
|
return Math.min(maxBitmapSize, Math.min(dm.widthPixels, dm.heightPixels) / scale);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -159,9 +159,9 @@ public class HueSatView extends SquareView implements ColorObserver {
|
|||||||
private boolean clamp(PointF pointer, float x, float y, boolean rejectOutside) {
|
private boolean clamp(PointF pointer, float x, float y, boolean rejectOutside) {
|
||||||
x = Math.min(x, w);
|
x = Math.min(x, w);
|
||||||
y = Math.min(y, h);
|
y = Math.min(y, h);
|
||||||
final float dx = w - x;
|
float dx = w - x;
|
||||||
final float dy = h - y;
|
float dy = h - y;
|
||||||
final float r = (float) Math.sqrt(dx * dx + dy * dy);
|
float r = (float) Math.sqrt(dx * dx + dy * dy);
|
||||||
boolean outside = r > w;
|
boolean outside = r > w;
|
||||||
if (!outside || !rejectOutside) {
|
if (!outside || !rejectOutside) {
|
||||||
if (outside) {
|
if (outside) {
|
||||||
|
|||||||
@@ -6,7 +6,6 @@ import android.view.MotionEvent;
|
|||||||
import android.view.View;
|
import android.view.View;
|
||||||
|
|
||||||
public abstract class SliderViewBase extends View {
|
public abstract class SliderViewBase extends View {
|
||||||
|
|
||||||
private final Paint borderPaint;
|
private final Paint borderPaint;
|
||||||
private final Paint checkerPaint;
|
private final Paint checkerPaint;
|
||||||
private final Rect viewRect = new Rect();
|
private final Rect viewRect = new Rect();
|
||||||
|
|||||||
@@ -18,10 +18,10 @@ class SquareView extends View {
|
|||||||
@Override
|
@Override
|
||||||
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
|
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
|
||||||
// Constrain to square
|
// Constrain to square
|
||||||
final int w = MeasureSpec.getSize(widthMeasureSpec);
|
int w = MeasureSpec.getSize(widthMeasureSpec);
|
||||||
final int h = MeasureSpec.getSize(heightMeasureSpec);
|
int h = MeasureSpec.getSize(heightMeasureSpec);
|
||||||
final int modeW = MeasureSpec.getMode(widthMeasureSpec);
|
int modeW = MeasureSpec.getMode(widthMeasureSpec);
|
||||||
final int modeH = MeasureSpec.getMode(heightMeasureSpec);
|
int modeH = MeasureSpec.getMode(heightMeasureSpec);
|
||||||
int size = minSizePx;
|
int size = minSizePx;
|
||||||
if (modeW == MeasureSpec.UNSPECIFIED) {
|
if (modeW == MeasureSpec.UNSPECIFIED) {
|
||||||
size = h;
|
size = h;
|
||||||
|
|||||||
@@ -8,7 +8,6 @@ import android.graphics.RectF;
|
|||||||
import ru.vtosters.lite.utils.AndroidUtils;
|
import ru.vtosters.lite.utils.AndroidUtils;
|
||||||
|
|
||||||
public class SwatchView extends SquareView implements ColorObserver {
|
public class SwatchView extends SquareView implements ColorObserver {
|
||||||
|
|
||||||
private final Paint borderPaint;
|
private final Paint borderPaint;
|
||||||
private final Path borderPath;
|
private final Path borderPath;
|
||||||
private final Paint checkerPaint;
|
private final Paint checkerPaint;
|
||||||
@@ -46,14 +45,14 @@ public class SwatchView extends SquareView implements ColorObserver {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private static void cornerArc(Path path, float cx, float cy, float r, float startAngle, float sweepAngle) {
|
private static void cornerArc(Path path, float cx, float cy, float r, float startAngle, float sweepAngle) {
|
||||||
final RectF ovalRect = new RectF(-r, -r, r, r);
|
RectF ovalRect = new RectF(-r, -r, r, r);
|
||||||
ovalRect.offset(cx, cy);
|
ovalRect.offset(cx, cy);
|
||||||
path.arcTo(ovalRect, startAngle, sweepAngle);
|
path.arcTo(ovalRect, startAngle, sweepAngle);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void mainArc(Path path, float viewSize, float margin, float startAngle, float sweepAngle) {
|
private static void mainArc(Path path, float viewSize, float margin, float startAngle, float sweepAngle) {
|
||||||
float r = viewSize + margin;
|
float r = viewSize + margin;
|
||||||
final RectF ovalRect = new RectF(-r, -r, r, r);
|
RectF ovalRect = new RectF(-r, -r, r, r);
|
||||||
ovalRect.offset(viewSize, viewSize);
|
ovalRect.offset(viewSize, viewSize);
|
||||||
path.arcTo(ovalRect, startAngle, sweepAngle);
|
path.arcTo(ovalRect, startAngle, sweepAngle);
|
||||||
}
|
}
|
||||||
@@ -77,23 +76,23 @@ public class SwatchView extends SquareView implements ColorObserver {
|
|||||||
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
|
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
|
||||||
// We expect to be stacked behind a square HueSatView and fill the top left corner.
|
// We expect to be stacked behind a square HueSatView and fill the top left corner.
|
||||||
|
|
||||||
final float inset = borderPaint.getStrokeWidth() / 2;
|
float inset = borderPaint.getStrokeWidth() / 2;
|
||||||
final float r = Math.min(w, h);
|
float r = Math.min(w, h);
|
||||||
|
|
||||||
// Trim the corners of the swatch is where it is radialMarginPx thick.
|
// Trim the corners of the swatch is where it is radialMarginPx thick.
|
||||||
// find how long the outeredges are:
|
// find how long the outeredges are:
|
||||||
final float margin = radialMarginPx;
|
float margin = radialMarginPx;
|
||||||
final float diagonal = r + 2 * margin;
|
float diagonal = r + 2 * margin;
|
||||||
final float opp = (float) Math.sqrt(diagonal * diagonal - r * r);
|
float opp = (float) Math.sqrt(diagonal * diagonal - r * r);
|
||||||
final float edgeLen = r - opp;
|
float edgeLen = r - opp;
|
||||||
|
|
||||||
// Arc angles for drawing CCW
|
// Arc angles for drawing CCW
|
||||||
final float outerAngle = (float) Math.toDegrees(Math.atan2(opp, r));
|
float outerAngle = (float) Math.toDegrees(Math.atan2(opp, r));
|
||||||
final float startAngle = 270 - outerAngle;
|
float startAngle = 270 - outerAngle;
|
||||||
// Sweep angle for each half of the swatch:
|
// Sweep angle for each half of the swatch:
|
||||||
final float sweepAngle = outerAngle - 45;
|
float sweepAngle = outerAngle - 45;
|
||||||
// Sweep angle for the smooth corners:
|
// Sweep angle for the smooth corners:
|
||||||
final float cornerSweepAngle = 90 - outerAngle;
|
float cornerSweepAngle = 90 - outerAngle;
|
||||||
|
|
||||||
// Outer border:
|
// Outer border:
|
||||||
beginBorder(borderPath, inset, edgeLen, margin, cornerSweepAngle);
|
beginBorder(borderPath, inset, edgeLen, margin, cornerSweepAngle);
|
||||||
|
|||||||
@@ -5,7 +5,6 @@ import android.graphics.Bitmap;
|
|||||||
import android.graphics.Color;
|
import android.graphics.Color;
|
||||||
|
|
||||||
public class ValueView extends SliderViewBase implements ColorObserver {
|
public class ValueView extends SliderViewBase implements ColorObserver {
|
||||||
|
|
||||||
private ObservableColor observableColor = new ObservableColor(0);
|
private ObservableColor observableColor = new ObservableColor(0);
|
||||||
|
|
||||||
public ValueView(Context context) {
|
public ValueView(Context context) {
|
||||||
@@ -37,8 +36,8 @@ public class ValueView extends SliderViewBase implements ColorObserver {
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected Bitmap makeBitmap(int w, int h) {
|
protected Bitmap makeBitmap(int w, int h) {
|
||||||
final boolean isWide = w > h;
|
boolean isWide = w > h;
|
||||||
final int n = Math.max(w, h);
|
int n = Math.max(w, h);
|
||||||
int[] colors = new int[n];
|
int[] colors = new int[n];
|
||||||
|
|
||||||
float[] hsv = new float[]{0, 0, 0};
|
float[] hsv = new float[]{0, 0, 0};
|
||||||
@@ -48,8 +47,8 @@ public class ValueView extends SliderViewBase implements ColorObserver {
|
|||||||
hsv[2] = isWide ? (float) i / n : 1 - (float) i / n;
|
hsv[2] = isWide ? (float) i / n : 1 - (float) i / n;
|
||||||
colors[i] = Color.HSVToColor(hsv);
|
colors[i] = Color.HSVToColor(hsv);
|
||||||
}
|
}
|
||||||
final int bmpWidth = isWide ? w : 1;
|
int bmpWidth = isWide ? w : 1;
|
||||||
final int bmpHeight = isWide ? 1 : h;
|
int bmpHeight = isWide ? 1 : h;
|
||||||
return Bitmap.createBitmap(colors, bmpWidth, bmpHeight, Bitmap.Config.ARGB_8888);
|
return Bitmap.createBitmap(colors, bmpWidth, bmpHeight, Bitmap.Config.ARGB_8888);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -18,7 +18,6 @@ import ru.vtosters.hooks.other.Preferences;
|
|||||||
import ru.vtosters.lite.foaf.FoafBase;
|
import ru.vtosters.lite.foaf.FoafBase;
|
||||||
import ru.vtosters.lite.utils.AccountManagerUtils;
|
import ru.vtosters.lite.utils.AccountManagerUtils;
|
||||||
import ru.vtosters.lite.utils.AndroidUtils;
|
import ru.vtosters.lite.utils.AndroidUtils;
|
||||||
import ru.vtosters.lite.utils.RenameTool;
|
|
||||||
|
|
||||||
import java.lang.reflect.Field;
|
import java.lang.reflect.Field;
|
||||||
import java.lang.reflect.InvocationTargetException;
|
import java.lang.reflect.InvocationTargetException;
|
||||||
@@ -46,15 +45,17 @@ public class MenuBuilder {
|
|||||||
cfambObject = CommunityFragmentActionsMenuBuilder.class.getDeclaredField("b");
|
cfambObject = CommunityFragmentActionsMenuBuilder.class.getDeclaredField("b");
|
||||||
cfambObject.setAccessible(true);
|
cfambObject.setAccessible(true);
|
||||||
} catch (NoSuchFieldException | NoSuchMethodException e) {
|
} catch (NoSuchFieldException | NoSuchMethodException e) {
|
||||||
Log.e("VTLite", "Reflection failed");
|
Log.e("MenuBuilder", "Reflection failed");
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void injectAP(final ProfileFragmentActionsMenuBuilder mb, final ActionsPopup.b builder) {
|
public static void injectAP(final ProfileFragmentActionsMenuBuilder mb, final ActionsPopup.b builder) {
|
||||||
try {
|
try {
|
||||||
final ExtendedUserProfile eup = (ExtendedUserProfile) pfambObject.get(mb);
|
ExtendedUserProfile eup = (ExtendedUserProfile) pfambObject.get(mb);
|
||||||
final Context ctx = ((View) Objects.requireNonNull(apView.get(builder))).getContext();
|
Context ctx = ((View) Objects.requireNonNull(apView.get(builder))).getContext();
|
||||||
|
boolean isPageWhitelistedFilter = isWhitelistedFilter(eup);
|
||||||
|
boolean isPageWhitelistedAdsStories = isWhitelistedAdStories(eup);
|
||||||
addItem(builder, AndroidUtils.getString(R.string.menu_copy_id), () -> {
|
addItem(builder, AndroidUtils.getString(R.string.menu_copy_id), () -> {
|
||||||
copy(ctx, String.valueOf(AccountManagerUtils.getUserID(eup)));
|
copy(ctx, String.valueOf(AccountManagerUtils.getUserID(eup)));
|
||||||
return Unit.a;
|
return Unit.a;
|
||||||
@@ -70,6 +71,17 @@ public class MenuBuilder {
|
|||||||
// return Unit.a;
|
// return Unit.a;
|
||||||
// });
|
// });
|
||||||
|
|
||||||
|
addItem(builder, AndroidUtils.getString(isPageWhitelistedFilter ? R.string.remove_from_filter_whitelist : R.string.add_to_filter_whitelist), () -> {
|
||||||
|
setWhitelistedFilter(eup, !isPageWhitelistedFilter);
|
||||||
|
AndroidUtils.sendToast(AndroidUtils.getString(isPageWhitelistedFilter ? R.string.removed_from_whitelist_success : R.string.added_to_whitelist_success));
|
||||||
|
return Unit.a;
|
||||||
|
});
|
||||||
|
|
||||||
|
addItem(builder, AndroidUtils.getString(isPageWhitelistedAdsStories ? R.string.remove_from_ads_stories_whitelist : R.string.add_to_ads_stories_whitelist), () -> {
|
||||||
|
setWhitelistedAdStories(eup, !isPageWhitelistedAdsStories);
|
||||||
|
AndroidUtils.sendToast(AndroidUtils.getString(isPageWhitelistedAdsStories ? R.string.removed_from_whitelist_success : R.string.added_to_whitelist_success));
|
||||||
|
return Unit.a;
|
||||||
|
});
|
||||||
} catch (IllegalAccessException | InvocationTargetException e) {
|
} catch (IllegalAccessException | InvocationTargetException e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
@@ -77,11 +89,11 @@ public class MenuBuilder {
|
|||||||
|
|
||||||
public static void injectAP(final CommunityFragmentActionsMenuBuilder mb, final ActionsPopup.b builder) {
|
public static void injectAP(final CommunityFragmentActionsMenuBuilder mb, final ActionsPopup.b builder) {
|
||||||
try {
|
try {
|
||||||
final ExtendedCommunityProfile ecp = (ExtendedCommunityProfile) cfambObject.get(mb);
|
ExtendedCommunityProfile ecp = (ExtendedCommunityProfile) cfambObject.get(mb);
|
||||||
final Context ctx = ((View) apView.get(builder)).getContext();
|
Context ctx = ((View) apView.get(builder)).getContext();
|
||||||
final boolean isPageWhitelistedFilter = isWhitelistedFilter(ecp);
|
boolean isPageWhitelistedFilter = isWhitelistedFilter(ecp);
|
||||||
final boolean isPageWhitelistedAds = isWhitelistedAd(ecp);
|
boolean isPageWhitelistedAds = isWhitelistedAd(ecp);
|
||||||
final boolean isPageWhitelistedAdsStories = isWhitelistedAdStories(ecp);
|
boolean isPageWhitelistedAdsStories = isWhitelistedAdStories(ecp);
|
||||||
|
|
||||||
addItem(builder, AndroidUtils.getString(R.string.menu_copy_id), () -> {
|
addItem(builder, AndroidUtils.getString(R.string.menu_copy_id), () -> {
|
||||||
copy(ctx, String.valueOf(AccountManagerUtils.getUserID(ecp)));
|
copy(ctx, String.valueOf(AccountManagerUtils.getUserID(ecp)));
|
||||||
@@ -110,7 +122,6 @@ public class MenuBuilder {
|
|||||||
AndroidUtils.sendToast(AndroidUtils.getString(isPageWhitelistedAdsStories ? R.string.removed_from_whitelist_success : R.string.added_to_whitelist_success));
|
AndroidUtils.sendToast(AndroidUtils.getString(isPageWhitelistedAdsStories ? R.string.removed_from_whitelist_success : R.string.added_to_whitelist_success));
|
||||||
return Unit.a;
|
return Unit.a;
|
||||||
});
|
});
|
||||||
|
|
||||||
} catch (IllegalAccessException | InvocationTargetException e) {
|
} catch (IllegalAccessException | InvocationTargetException e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
@@ -148,6 +159,19 @@ public class MenuBuilder {
|
|||||||
).contains(String.valueOf(AccountManagerUtils.getUserID(eup)));
|
).contains(String.valueOf(AccountManagerUtils.getUserID(eup)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static boolean isWhitelistedFilter(ExtendedUserProfile eup) {
|
||||||
|
return Preferences.getPreferences().getStringSet(
|
||||||
|
"whitelisted_filters_groups", Collections.emptySet()
|
||||||
|
).contains(String.valueOf(AccountManagerUtils.getUserID(eup)));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean isWhitelistedAdStories(ExtendedUserProfile eup) {
|
||||||
|
return Preferences.getPreferences().getStringSet(
|
||||||
|
"whitelisted_stories_ad",
|
||||||
|
Collections.emptySet()
|
||||||
|
).contains(String.valueOf(AccountManagerUtils.getUserID(eup)));
|
||||||
|
}
|
||||||
|
|
||||||
public static void setWhitelistedFilter(ExtendedCommunityProfile eup, boolean needWhitelist) {
|
public static void setWhitelistedFilter(ExtendedCommunityProfile eup, boolean needWhitelist) {
|
||||||
var id = String.valueOf(AccountManagerUtils.getUserID(eup));
|
var id = String.valueOf(AccountManagerUtils.getUserID(eup));
|
||||||
|
|
||||||
@@ -195,4 +219,36 @@ public class MenuBuilder {
|
|||||||
|
|
||||||
Preferences.getPreferences().edit().putStringSet("whitelisted_stories_ad", mutableAdsSet).apply();
|
Preferences.getPreferences().edit().putStringSet("whitelisted_stories_ad", mutableAdsSet).apply();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void setWhitelistedFilter(ExtendedUserProfile eup, boolean needWhitelist) {
|
||||||
|
var id = String.valueOf(AccountManagerUtils.getUserID(eup));
|
||||||
|
|
||||||
|
var mutableAdsSet = new LinkedHashSet<>(Preferences.getPreferences().getStringSet(
|
||||||
|
"whitelisted_filters_groups",
|
||||||
|
Collections.emptySet())
|
||||||
|
);
|
||||||
|
if (needWhitelist) {
|
||||||
|
mutableAdsSet.add(id);
|
||||||
|
} else {
|
||||||
|
mutableAdsSet.remove(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
Preferences.getPreferences().edit().putStringSet("whitelisted_filters_groups", mutableAdsSet).apply();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void setWhitelistedAdStories(ExtendedUserProfile eup, boolean needWhitelist) {
|
||||||
|
var id = String.valueOf(AccountManagerUtils.getUserID(eup));
|
||||||
|
|
||||||
|
var mutableAdsSet = new LinkedHashSet<>(Preferences.getPreferences().getStringSet(
|
||||||
|
"whitelisted_stories_ad",
|
||||||
|
Collections.emptySet()));
|
||||||
|
|
||||||
|
if (needWhitelist) {
|
||||||
|
mutableAdsSet.add(id);
|
||||||
|
} else {
|
||||||
|
mutableAdsSet.remove(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
Preferences.getPreferences().edit().putStringSet("whitelisted_stories_ad", mutableAdsSet).apply();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -5,12 +5,8 @@ import android.graphics.BitmapFactory;
|
|||||||
import android.graphics.drawable.BitmapDrawable;
|
import android.graphics.drawable.BitmapDrawable;
|
||||||
import android.graphics.drawable.Drawable;
|
import android.graphics.drawable.Drawable;
|
||||||
import android.os.Build;
|
import android.os.Build;
|
||||||
import android.view.View;
|
|
||||||
import android.widget.ImageView;
|
|
||||||
import com.vk.im.engine.h;
|
|
||||||
import com.vtosters.lite.R;
|
import com.vtosters.lite.R;
|
||||||
import ru.vtosters.hooks.other.Preferences;
|
import ru.vtosters.hooks.other.Preferences;
|
||||||
import ru.vtosters.hooks.other.ThemesUtils;
|
|
||||||
import ru.vtosters.lite.utils.AndroidUtils;
|
import ru.vtosters.lite.utils.AndroidUtils;
|
||||||
import vigo.sdk.Log;
|
import vigo.sdk.Log;
|
||||||
|
|
||||||
|
|||||||
@@ -46,7 +46,7 @@ public class AndroidUtils {
|
|||||||
@NonNull
|
@NonNull
|
||||||
public static Context getGlobalContext() {
|
public static Context getGlobalContext() {
|
||||||
try {
|
try {
|
||||||
final Method getInitialApplicationMtd = ReflectionUtils.findMethod(Class.forName("android.app.AppGlobals"), "getInitialApplication");
|
Method getInitialApplicationMtd = ReflectionUtils.findMethod(Class.forName("android.app.AppGlobals"), "getInitialApplication");
|
||||||
return (Context) getInitialApplicationMtd.invoke(null);
|
return (Context) getInitialApplicationMtd.invoke(null);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
Log.d("GlobalContext", "Error while fetching context via refl");
|
Log.d("GlobalContext", "Error while fetching context via refl");
|
||||||
@@ -186,8 +186,8 @@ public class AndroidUtils {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private static String getRandomString(int sizeOfRandomString) {
|
private static String getRandomString(int sizeOfRandomString) {
|
||||||
final Random random = new Random();
|
Random random = new Random();
|
||||||
final StringBuilder sb = new StringBuilder(sizeOfRandomString);
|
StringBuilder sb = new StringBuilder(sizeOfRandomString);
|
||||||
for (int i = 0; i < sizeOfRandomString; ++i)
|
for (int i = 0; i < sizeOfRandomString; ++i)
|
||||||
sb.append(ALLOWED_CHARACTERS.charAt(random.nextInt(ALLOWED_CHARACTERS.length())));
|
sb.append(ALLOWED_CHARACTERS.charAt(random.nextInt(ALLOWED_CHARACTERS.length())));
|
||||||
return sb.toString();
|
return sb.toString();
|
||||||
@@ -221,7 +221,6 @@ public class AndroidUtils {
|
|||||||
long lastUpdateTime = context.getPackageManager().getPackageInfo(context.getPackageName(), 0).lastUpdateTime;
|
long lastUpdateTime = context.getPackageManager().getPackageInfo(context.getPackageName(), 0).lastUpdateTime;
|
||||||
return firstInstallTime == lastUpdateTime;
|
return firstInstallTime == lastUpdateTime;
|
||||||
} catch (PackageManager.NameNotFoundException e) {
|
} catch (PackageManager.NameNotFoundException e) {
|
||||||
e.printStackTrace();
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ public class CrashReporter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static void init(Activity activity) {
|
public static void init(Activity activity) {
|
||||||
final var defaultUncaughtExceptionHandler = Thread.getDefaultUncaughtExceptionHandler();
|
var defaultUncaughtExceptionHandler = Thread.getDefaultUncaughtExceptionHandler();
|
||||||
Thread.setDefaultUncaughtExceptionHandler((thread, th) -> CrashReporter.start(defaultUncaughtExceptionHandler, thread, th, activity));
|
Thread.setDefaultUncaughtExceptionHandler((thread, th) -> CrashReporter.start(defaultUncaughtExceptionHandler, thread, th, activity));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -76,9 +76,8 @@ public class CrashReporter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private static boolean isFoxbinInstalled() {
|
private static boolean isFoxbinInstalled() {
|
||||||
var pm = getGlobalContext().getPackageManager();
|
|
||||||
try {
|
try {
|
||||||
pm.getPackageInfo("com.f0x1d.dogbin", 0);
|
getGlobalContext().getPackageManager().getPackageInfo("com.f0x1d.dogbin", 0);
|
||||||
return true;
|
return true;
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
return false;
|
return false;
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ import java.security.NoSuchAlgorithmException;
|
|||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
|
||||||
public class IOUtils {
|
public class IOUtils {
|
||||||
public static final int BUFFER_SIZE = 8192;
|
public static int BUFFER_SIZE = 8192;
|
||||||
|
|
||||||
public static byte[] decodeStream(InputStream encIs, byte[] aesKey)
|
public static byte[] decodeStream(InputStream encIs, byte[] aesKey)
|
||||||
throws NoSuchPaddingException, NoSuchAlgorithmException, InvalidAlgorithmParameterException, InvalidKeyException, IOException {
|
throws NoSuchPaddingException, NoSuchAlgorithmException, InvalidAlgorithmParameterException, InvalidKeyException, IOException {
|
||||||
@@ -51,11 +51,11 @@ public class IOUtils {
|
|||||||
return new String(readFully(is), StandardCharsets.UTF_8);
|
return new String(readFully(is), StandardCharsets.UTF_8);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static byte[] readFully(final InputStream is)
|
public static byte[] readFully(InputStream is)
|
||||||
throws IOException {
|
throws IOException {
|
||||||
final var bos = new ByteArrayOutputStream();
|
var bos = new ByteArrayOutputStream();
|
||||||
try (bos) {
|
try (bos) {
|
||||||
final byte[] buff = new byte[BUFFER_SIZE];
|
byte[] buff = new byte[BUFFER_SIZE];
|
||||||
int len;
|
int len;
|
||||||
while ((len = is.read(buff)) > 0)
|
while ((len = is.read(buff)) > 0)
|
||||||
bos.write(buff, 0, len);
|
bos.write(buff, 0, len);
|
||||||
@@ -63,7 +63,7 @@ public class IOUtils {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static byte[] readFully(final File in)
|
public static byte[] readFully(File in)
|
||||||
throws IOException {
|
throws IOException {
|
||||||
return readFully(new FileInputStream(in));
|
return readFully(new FileInputStream(in));
|
||||||
}
|
}
|
||||||
@@ -80,25 +80,25 @@ public class IOUtils {
|
|||||||
fos.close();
|
fos.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void copy(final InputStream is, final OutputStream os)
|
public static void copy(InputStream is, OutputStream os)
|
||||||
throws IOException {
|
throws IOException {
|
||||||
final byte[] buff = new byte[BUFFER_SIZE];
|
byte[] buff = new byte[BUFFER_SIZE];
|
||||||
int len;
|
int len;
|
||||||
while ((len = is.read(buff)) > 0)
|
while ((len = is.read(buff)) > 0)
|
||||||
os.write(buff, 0, len);
|
os.write(buff, 0, len);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void copy(final byte[] buffer, final File out)
|
public static void copy(byte[] buffer, File out)
|
||||||
throws IOException {
|
throws IOException {
|
||||||
copy(new ByteArrayInputStream(buffer), new FileOutputStream(out));
|
copy(new ByteArrayInputStream(buffer), new FileOutputStream(out));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void copy(final InputStream is, final File out)
|
public static void copy(InputStream is, File out)
|
||||||
throws IOException {
|
throws IOException {
|
||||||
copy(is, new FileOutputStream(out));
|
copy(is, new FileOutputStream(out));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void copy(final File in, final File out)
|
public static void copy(File in, File out)
|
||||||
throws IOException {
|
throws IOException {
|
||||||
copy(new FileInputStream(in), new FileOutputStream(out));
|
copy(new FileInputStream(in), new FileOutputStream(out));
|
||||||
}
|
}
|
||||||
@@ -119,7 +119,7 @@ public class IOUtils {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static long getDirSize(File dir) {
|
public static long getDirSize(File dir) {
|
||||||
final var arr = dir.listFiles();
|
var arr = dir.listFiles();
|
||||||
if (arr == null || arr.length == 0)
|
if (arr == null || arr.length == 0)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
|||||||
@@ -14,57 +14,46 @@ import static ru.vtosters.hooks.other.Preferences.*;
|
|||||||
import static ru.vtosters.lite.utils.AndroidUtils.getGlobalContext;
|
import static ru.vtosters.lite.utils.AndroidUtils.getGlobalContext;
|
||||||
|
|
||||||
public class NewsFeedFiltersUtils {
|
public class NewsFeedFiltersUtils {
|
||||||
public static List<String> mFilters;
|
public static List<String> mFilters = new ArrayList<>();
|
||||||
public static List<String> mFiltersNames;
|
public static List<String> mFiltersNames = new ArrayList<>();
|
||||||
public static List<String> mFiltersLinks;
|
public static List<String> mFiltersLinks = new ArrayList<>();
|
||||||
|
|
||||||
public static void setupFilters() {
|
public static void setupFilters() {
|
||||||
mFilters = new ArrayList<>();
|
|
||||||
mFiltersNames = new ArrayList<>();
|
|
||||||
mFiltersLinks = new ArrayList<>();
|
|
||||||
|
|
||||||
getFilter("refsfilter", "Referals.txt", mFilters);
|
getFilter("refsfilter", "Referals.txt", mFilters);
|
||||||
getFilter("shortlinkfilter", "LinkShorter.txt", mFilters);
|
getFilter("shortlinkfilter", "LinkShorter.txt", mFilters);
|
||||||
getFilter("default_ad_list", "StandartFilter.txt", mFilters);
|
getFilter("default_ad_list", "StandartFilter.txt", mFilters);
|
||||||
getFilter("shitposting", "IDontWantToReadIt.txt", mFilters);
|
getFilter("shitposting", "IDontWantToReadIt.txt", mFilters);
|
||||||
getFilter("cringecopyright", "CopyrightAds.txt", mFiltersLinks);
|
getFilter("cringecopyright", "CopyrightAds.txt", mFiltersLinks);
|
||||||
|
|
||||||
var customFilters = getString("spamfilters");
|
setCustomFilters(mFilters, getString("spamfilters"));
|
||||||
if (!customFilters.isEmpty()) {
|
setCustomFilters(mFiltersNames, getString("sourcenamefilter"));
|
||||||
mFilters.addAll(Arrays.asList(customFilters.toLowerCase().split(", ")));
|
setCustomFilters(mFiltersLinks, getString("linkfilter"));
|
||||||
}
|
|
||||||
|
|
||||||
var sourceNameFilter = getString("sourcenamefilter");
|
|
||||||
if (!sourceNameFilter.isEmpty()) {
|
|
||||||
mFiltersNames.addAll(Arrays.asList(sourceNameFilter.toLowerCase().split(", ")));
|
|
||||||
}
|
|
||||||
|
|
||||||
var linkFilter = getString("linkfilter");
|
|
||||||
if (!linkFilter.isEmpty()) {
|
|
||||||
mFiltersLinks.addAll(Arrays.asList(linkFilter.toLowerCase().split(", ")));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Get needed filter list from assets
|
||||||
public static void getFilter(String boolname, String filename, List<String> list) {
|
public static void getFilter(String boolname, String filename, List<String> list) {
|
||||||
var ctx = getGlobalContext();
|
|
||||||
|
|
||||||
if (getBoolValue(boolname, false)) {
|
if (getBoolValue(boolname, false)) {
|
||||||
try {
|
try (Scanner scanner = new Scanner(getGlobalContext().getAssets().open(filename))) {
|
||||||
Scanner scanner;
|
|
||||||
scanner = new Scanner(ctx.getAssets().open(filename));
|
|
||||||
|
|
||||||
while (scanner.hasNextLine()) {
|
while (scanner.hasNextLine()) {
|
||||||
var line = scanner.nextLine();
|
addNonEmptyLineToList(scanner.nextLine(), list);
|
||||||
if (!line.isEmpty())
|
|
||||||
list.add(line.toLowerCase());
|
|
||||||
}
|
}
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
Log.d("NewsFeedFiltersUtils", e.getMessage());
|
Log.d("NewsFeedFiltersUtils", e.getMessage());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} // Get needed filter list from assets
|
}
|
||||||
|
|
||||||
public static boolean injectFiltersReposts(JSONObject obj) throws JSONException {
|
private static void addNonEmptyLineToList(String line, List<String> list) {
|
||||||
|
if (!line.isEmpty()) {
|
||||||
|
list.add(line.toLowerCase());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void setCustomFilters(List<String> list, String filters) {
|
||||||
|
if (!filters.isEmpty()) list.addAll(Arrays.asList(filters.toLowerCase().split(", ")));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean injectFiltersReposts(JSONObject obj) {
|
||||||
if (obj.has("copy_history")) {
|
if (obj.has("copy_history")) {
|
||||||
var copyHistoryNode = obj.optJSONArray("copy_history");
|
var copyHistoryNode = obj.optJSONArray("copy_history");
|
||||||
if (copyHistoryNode != null && copyHistoryNode.length() != 0) {
|
if (copyHistoryNode != null && copyHistoryNode.length() != 0) {
|
||||||
@@ -94,6 +83,7 @@ public class NewsFeedFiltersUtils {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -101,17 +91,12 @@ public class NewsFeedFiltersUtils {
|
|||||||
if (json.has("copyright")) {
|
if (json.has("copyright")) {
|
||||||
if (copyright_post()) return true;
|
if (copyright_post()) return true;
|
||||||
|
|
||||||
var copyright = json.optJSONObject("copyright");
|
JSONObject copyright = json.optJSONObject("copyright");
|
||||||
|
|
||||||
String copyrightName = null;
|
String copyrightName = null;
|
||||||
|
|
||||||
if (copyright != null) {
|
|
||||||
copyrightName = copyright.getString("name").toLowerCase();
|
|
||||||
}
|
|
||||||
|
|
||||||
String copyrightLink = null;
|
String copyrightLink = null;
|
||||||
|
|
||||||
if (copyright != null) {
|
if (copyright != null) {
|
||||||
|
copyrightName = copyright.getString("name").toLowerCase();
|
||||||
copyrightLink = copyright.getString("link").toLowerCase();
|
copyrightLink = copyright.getString("link").toLowerCase();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -126,8 +111,8 @@ public class NewsFeedFiltersUtils {
|
|||||||
if (copyrightLink != null && copyrightLink.contains(filter)) return true;
|
if (copyrightLink != null && copyrightLink.contains(filter)) return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -144,7 +129,6 @@ public class NewsFeedFiltersUtils {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -154,9 +138,8 @@ public class NewsFeedFiltersUtils {
|
|||||||
var caption = postJson.optJSONObject("caption");
|
var caption = postJson.optJSONObject("caption");
|
||||||
if (postsrecomm()) {
|
if (postsrecomm()) {
|
||||||
try {
|
try {
|
||||||
String type;
|
|
||||||
if (caption != null) {
|
if (caption != null) {
|
||||||
type = caption.getString("type");
|
String type = caption.getString("type");
|
||||||
return type.equals("explorebait") || // Может быть интересно
|
return type.equals("explorebait") || // Может быть интересно
|
||||||
type.equals("shared") || // Поделился записью
|
type.equals("shared") || // Поделился записью
|
||||||
type.equals("digest") || // Рекомедации
|
type.equals("digest") || // Рекомедации
|
||||||
@@ -187,7 +170,7 @@ public class NewsFeedFiltersUtils {
|
|||||||
var title = item.optString("title");
|
var title = item.optString("title");
|
||||||
|
|
||||||
if (TextUtils.isEmpty(id) || TextUtils.isEmpty(title)
|
if (TextUtils.isEmpty(id) || TextUtils.isEmpty(title)
|
||||||
// this items not working
|
// these items not working
|
||||||
|| id.equals("kpop") || id.equals("foryou")
|
|| id.equals("kpop") || id.equals("foryou")
|
||||||
|| id.equals("qazaqstan") || id.equals("podcasts"))
|
|| id.equals("qazaqstan") || id.equals("podcasts"))
|
||||||
continue;
|
continue;
|
||||||
@@ -201,8 +184,8 @@ public class NewsFeedFiltersUtils {
|
|||||||
.put("is_unavailable", hide);
|
.put("is_unavailable", hide);
|
||||||
Log.d("NewsfeedListInj", "Unlocked " + id + " in newsfeed list");
|
Log.d("NewsfeedListInj", "Unlocked " + id + " in newsfeed list");
|
||||||
}
|
}
|
||||||
Preferences.getPreferences().edit().putStringSet("news_feed_items_set", mutableFiltersSet)
|
|
||||||
.apply();
|
Preferences.getPreferences().edit().putStringSet("news_feed_items_set", mutableFiltersSet).apply();
|
||||||
|
|
||||||
return items;
|
return items;
|
||||||
}
|
}
|
||||||
@@ -259,13 +242,13 @@ public class NewsFeedFiltersUtils {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (checkCopyright(post) && !isWhitelistedFilters(post)) {
|
if (checkCopyright(post)) {
|
||||||
if (dev())
|
if (dev())
|
||||||
Log.d("NewsfeedAdBlockV2", "Removed post " + post.optInt("post_id") + " from discover, Reason: copyright filters");
|
Log.d("NewsfeedAdBlockV2", "Removed post " + post.optInt("post_id") + " from discover, Reason: copyright filters");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (checkCaption(post) && !isWhitelistedFilters(post)) {
|
if (checkCaption(post)) {
|
||||||
if (dev())
|
if (dev())
|
||||||
Log.d("NewsfeedAdBlockV2", "Removed post " + post.optInt("post_id") + " from discover, Reason: caption filters");
|
Log.d("NewsfeedAdBlockV2", "Removed post " + post.optInt("post_id") + " from discover, Reason: caption filters");
|
||||||
return false;
|
return false;
|
||||||
@@ -284,45 +267,6 @@ public class NewsFeedFiltersUtils {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static JSONObject discoverObj() throws JSONException {
|
|
||||||
var mainjson = new JSONObject();
|
|
||||||
|
|
||||||
var info = new JSONObject();
|
|
||||||
info.put("title", "Test Injection");
|
|
||||||
info.put("text_color", "#ffffff");
|
|
||||||
info.put("description", "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat");
|
|
||||||
|
|
||||||
var image = new JSONArray();
|
|
||||||
var imageQuality1 = new JSONObject();
|
|
||||||
imageQuality1.put("url", "https://w7.pngwing.com/pngs/505/1021/png-transparent-konata-izumi-lucky-star-desktop-anime-anime-blue-mammal-face.png");
|
|
||||||
imageQuality1.put("width", 72); // 72, 108, 144, 216, 288
|
|
||||||
imageQuality1.put("height", 72); // 72, 108, 144, 216, 288
|
|
||||||
image.put(imageQuality1);
|
|
||||||
|
|
||||||
var background = new JSONArray();
|
|
||||||
var backgroundQuality1 = new JSONObject();
|
|
||||||
backgroundQuality1.put("url", "https://2ch.life/vg/arch/2022-08-22/src/38524739/16440606579870.jpg");
|
|
||||||
backgroundQuality1.put("width", 344); // 344, 516, 680, 1032, 1376
|
|
||||||
backgroundQuality1.put("height", 215); // 215, 323, 426, 645, 860
|
|
||||||
background.put(backgroundQuality1);
|
|
||||||
|
|
||||||
info.put("image", image);
|
|
||||||
info.put("background", background);
|
|
||||||
|
|
||||||
mainjson.put("info", info);
|
|
||||||
mainjson.put("track_code", "info_banner_donut_catalog");
|
|
||||||
mainjson.put("template", "info");
|
|
||||||
|
|
||||||
var action = new JSONObject();
|
|
||||||
action.put("type", "open_url");
|
|
||||||
action.put("url", "vk.com/vtosters_official");
|
|
||||||
action.put("target", "internal");
|
|
||||||
|
|
||||||
mainjson.put("action", action);
|
|
||||||
|
|
||||||
return mainjson;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void parseStoriesItem(JSONObject item) throws JSONException {
|
public static void parseStoriesItem(JSONObject item) throws JSONException {
|
||||||
var stories = item.optJSONArray("stories");
|
var stories = item.optJSONArray("stories");
|
||||||
var newStories = new JSONArray();
|
var newStories = new JSONArray();
|
||||||
@@ -382,7 +326,7 @@ public class NewsFeedFiltersUtils {
|
|||||||
id = String.valueOf(list.optInt("source_id"));
|
id = String.valueOf(list.optInt("source_id"));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (id.equals("-189659924")) {
|
if (id.equals("-189659924") || id.equals(String.valueOf(AccountManagerUtils.getUserId()))) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -391,7 +335,7 @@ public class NewsFeedFiltersUtils {
|
|||||||
Collections.emptySet()
|
Collections.emptySet()
|
||||||
);
|
);
|
||||||
|
|
||||||
return whitelist.contains(id);
|
return Preferences.getBoolValue("invertFilters", false) != whitelist.contains(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Boolean isWhitelistedAd(JSONObject list) {
|
public static Boolean isWhitelistedAd(JSONObject list) {
|
||||||
@@ -425,7 +369,7 @@ public class NewsFeedFiltersUtils {
|
|||||||
|
|
||||||
if (attachments != null && getBoolValue("blockminiapps", false)) {
|
if (attachments != null && getBoolValue("blockminiapps", false)) {
|
||||||
for (int j = 0; j < attachments.length(); j++) {
|
for (int j = 0; j < attachments.length(); j++) {
|
||||||
var type = attachments.optJSONObject(j).optString("type");
|
String type = attachments.optJSONObject(j).optString("type");
|
||||||
if (type.contains("mini_app")) return true;
|
if (type.contains("mini_app")) return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -439,7 +383,7 @@ public class NewsFeedFiltersUtils {
|
|||||||
|
|
||||||
for (int i = 0; i < (items != null ? items.length() : 0); i++) {
|
for (int i = 0; i < (items != null ? items.length() : 0); i++) {
|
||||||
try {
|
try {
|
||||||
var curr = items.getJSONObject(i);
|
JSONObject curr = items.getJSONObject(i);
|
||||||
if (!curr.optString("template").contains("info") && discoverAdBlock(curr)) {
|
if (!curr.optString("template").contains("info") && discoverAdBlock(curr)) {
|
||||||
newObj.put(items.optJSONObject(i));
|
newObj.put(items.optJSONObject(i));
|
||||||
}
|
}
|
||||||
@@ -460,11 +404,11 @@ public class NewsFeedFiltersUtils {
|
|||||||
var newItems = new JSONArray();
|
var newItems = new JSONArray();
|
||||||
|
|
||||||
for (int j = 0; j < items.length(); j++) {
|
for (int j = 0; j < items.length(); j++) {
|
||||||
var list = items.optJSONObject(j);
|
JSONObject list = items.optJSONObject(j);
|
||||||
|
|
||||||
if (list == null) continue;
|
if (list == null) continue;
|
||||||
|
|
||||||
var type = list.optString("type");
|
String type = list.optString("type");
|
||||||
|
|
||||||
if (isAds(list, type)) {
|
if (isAds(list, type)) {
|
||||||
continue;
|
continue;
|
||||||
@@ -504,13 +448,13 @@ public class NewsFeedFiltersUtils {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (checkCopyright(list) && !isWhitelistedFilters(list)) {
|
if (checkCopyright(list)) {
|
||||||
if (dev())
|
if (dev())
|
||||||
Log.d("NewsfeedAdBlockV2", "Removed post " + list.optInt("post_id") + " from feed, Reason: copyright filters");
|
Log.d("NewsfeedAdBlockV2", "Removed post " + list.optInt("post_id") + " from feed, Reason: copyright filters");
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (checkCaption(list) && !isWhitelistedFilters(list)) {
|
if (checkCaption(list)) {
|
||||||
if (dev())
|
if (dev())
|
||||||
Log.d("NewsfeedAdBlockV2", "Removed post " + list.optInt("post_id") + " from feed, Reason: caption filters");
|
Log.d("NewsfeedAdBlockV2", "Removed post " + list.optInt("post_id") + " from feed, Reason: caption filters");
|
||||||
continue;
|
continue;
|
||||||
@@ -549,7 +493,7 @@ public class NewsFeedFiltersUtils {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (json.has("ads")) {
|
if (json.has("ads")) {
|
||||||
var ad = json.optJSONObject("ads");
|
JSONObject ad = json.optJSONObject("ads");
|
||||||
if (isDeleteFix) {
|
if (isDeleteFix) {
|
||||||
if (ad != null) {
|
if (ad != null) {
|
||||||
ad.optJSONObject("settings")
|
ad.optJSONObject("settings")
|
||||||
@@ -567,10 +511,10 @@ public class NewsFeedFiltersUtils {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var items = json.optJSONArray("items");
|
JSONArray items = json.optJSONArray("items");
|
||||||
if (items != null) {
|
if (items != null) {
|
||||||
for (int i = 0; i < items.length(); i++) {
|
for (int i = 0; i < items.length(); i++) {
|
||||||
var item = items.optJSONObject(i);
|
JSONObject item = items.optJSONObject(i);
|
||||||
if (item != null) {
|
if (item != null) {
|
||||||
parseStoriesItem(item);
|
parseStoriesItem(item);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,6 +17,9 @@ import java.text.SimpleDateFormat;
|
|||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
|
|
||||||
|
import static android.os.Environment.DIRECTORY_DOWNLOADS;
|
||||||
|
import static android.os.Environment.getExternalStoragePublicDirectory;
|
||||||
|
|
||||||
public class VKAccountDB {
|
public class VKAccountDB {
|
||||||
private static SQLiteOpenHelper getDatabase() {
|
private static SQLiteOpenHelper getDatabase() {
|
||||||
return new UsersDbHelper(AndroidUtils.getGlobalContext());
|
return new UsersDbHelper(AndroidUtils.getGlobalContext());
|
||||||
@@ -70,11 +73,11 @@ public class VKAccountDB {
|
|||||||
|
|
||||||
var db = getDatabase().getReadableDatabase();
|
var db = getDatabase().getReadableDatabase();
|
||||||
var dateFormat = new SimpleDateFormat("yyyy-MM-dd.HH-mm-ss", Locale.getDefault());
|
var dateFormat = new SimpleDateFormat("yyyy-MM-dd.HH-mm-ss", Locale.getDefault());
|
||||||
var file = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS) + "/VTLBackups/saved_accounts_" + dateFormat.format(new Date()) + ".vtl");
|
var dir = new File(getExternalStoragePublicDirectory(DIRECTORY_DOWNLOADS), "/VTLBackups/");
|
||||||
|
var file = new File(dir, "saved_accounts_" + dateFormat.format(new Date()) + ".vtl");
|
||||||
|
|
||||||
InputStream inputStream;
|
try (InputStream inputStream = new FileInputStream(db.getPath())){
|
||||||
try {
|
dir.mkdirs();
|
||||||
inputStream = new FileInputStream(db.getPath());
|
|
||||||
|
|
||||||
FileOutputStream outputStream = new FileOutputStream(file);
|
FileOutputStream outputStream = new FileOutputStream(file);
|
||||||
byte[] buff = new byte[1024];
|
byte[] buff = new byte[1024];
|
||||||
@@ -86,7 +89,6 @@ public class VKAccountDB {
|
|||||||
|
|
||||||
AndroidUtils.sendToast(AndroidUtils.getString("accounts_saved_by_path") + " " + file.getPath());
|
AndroidUtils.sendToast(AndroidUtils.getString("accounts_saved_by_path") + " " + file.getPath());
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
e.printStackTrace();
|
|
||||||
AndroidUtils.sendToast(AndroidUtils.getString("error_saving_file"));
|
AndroidUtils.sendToast(AndroidUtils.getString("error_saving_file"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,3 +14,6 @@
|
|||||||
android.useAndroidX=true
|
android.useAndroidX=true
|
||||||
android.enableJetifier=true
|
android.enableJetifier=true
|
||||||
android.jetifier.ignorelist=classes-dex2jar.jar, classes2-dex2jar.jar, classes3-dex2jar.jar, classes4-dex2jar.jar, classes5-dex2jar.jar, classes6-dex2jar.jar, classes7-dex2jar.jar
|
android.jetifier.ignorelist=classes-dex2jar.jar, classes2-dex2jar.jar, classes3-dex2jar.jar, classes4-dex2jar.jar, classes5-dex2jar.jar, classes6-dex2jar.jar, classes7-dex2jar.jar
|
||||||
|
android.defaults.buildfeatures.buildconfig=true
|
||||||
|
android.nonTransitiveRClass=false
|
||||||
|
android.nonFinalResIds=false
|
||||||
|
|||||||
@@ -22,9 +22,6 @@ if "%ERRORLEVEL%" == "0" (
|
|||||||
echo %ESC%[31mFailed%ESC%[0m
|
echo %ESC%[31mFailed%ESC%[0m
|
||||||
exit /B 1
|
exit /B 1
|
||||||
)
|
)
|
||||||
del classes6.dex
|
|
||||||
del classes7.dex
|
|
||||||
del assets\version.properties
|
|
||||||
|
|
||||||
echo.
|
echo.
|
||||||
echo %ESC%[1;4mSign apk...%ESC%[0m
|
echo %ESC%[1;4mSign apk...%ESC%[0m
|
||||||
|
|||||||
+1
-5
@@ -33,8 +33,4 @@ cd ../scripts
|
|||||||
./apksigner sign --ks debug.keystore --ks-key-alias androiddebugkey --ks-pass pass:android ../scripts/VTLite.apk
|
./apksigner sign --ks debug.keystore --ks-key-alias androiddebugkey --ks-pass pass:android ../scripts/VTLite.apk
|
||||||
check_result
|
check_result
|
||||||
|
|
||||||
echo -e "${BOLD}VTosters Lite успешно собран! APK находится в папке scripts${NC}"
|
echo -e "${BOLD}VTosters Lite успешно собран! APK находится в папке scripts${NC}"
|
||||||
|
|
||||||
cd ../smali
|
|
||||||
rm classes6.dex
|
|
||||||
rm classes7.dex
|
|
||||||
@@ -57,6 +57,7 @@ cпocоб зaрaбoтать
|
|||||||
В закрепленном комментарии
|
В закрепленном комментарии
|
||||||
В Закрепленном комментарии
|
В Закрепленном комментарии
|
||||||
В закрепленном Комментарии
|
В закрепленном Комментарии
|
||||||
|
в комментариях
|
||||||
Успей подать заявку
|
Успей подать заявку
|
||||||
Успей Подать Заявку
|
Успей Подать Заявку
|
||||||
Успей подать Заявку
|
Успей подать Заявку
|
||||||
@@ -94,6 +95,6 @@ cкорее подписывайся
|
|||||||
Подписывайтесь👇
|
Подписывайтесь👇
|
||||||
Подписывайся👇
|
Подписывайся👇
|
||||||
ссылка в комментариях
|
ссылка в комментариях
|
||||||
в комментариях👇
|
|
||||||
👉https://
|
👉https://
|
||||||
👉http://
|
👉http://
|
||||||
|
Ссылка удалится через часов
|
||||||
@@ -6823,8 +6823,8 @@
|
|||||||
<string name="remove_from_ads_whitelist">Выдаліць з вайтліста рэкламы</string>
|
<string name="remove_from_ads_whitelist">Выдаліць з вайтліста рэкламы</string>
|
||||||
<string name="add_to_ads_stories_whitelist">Дадаць у вайтліст гісторый</string>
|
<string name="add_to_ads_stories_whitelist">Дадаць у вайтліст гісторый</string>
|
||||||
<string name="remove_from_ads_stories_whitelist">Выдаліць з вайтліста гісторый</string>
|
<string name="remove_from_ads_stories_whitelist">Выдаліць з вайтліста гісторый</string>
|
||||||
<string name="removed_from_whitelist_success">Група выдалена з вайтліста</string>
|
<string name="removed_from_whitelist_success">Выдаленая з вайтлиста</string>
|
||||||
<string name="added_to_whitelist_success">Група дададзена ў вайтліст</string>
|
<string name="added_to_whitelist_success">Дададзена ў вайтліст</string>
|
||||||
<string name="whitelisted_ad_groups_title">Вайтліст рэкламы</string>
|
<string name="whitelisted_ad_groups_title">Вайтліст рэкламы</string>
|
||||||
|
|
||||||
<string name="whitelisted_ad_groups_stories_title">Вайтліст рэкламы гісторый</string>
|
<string name="whitelisted_ad_groups_stories_title">Вайтліст рэкламы гісторый</string>
|
||||||
@@ -6942,6 +6942,8 @@
|
|||||||
<string name="promotedstickers_title">Не атрымліваць промостикеры</string>
|
<string name="promotedstickers_title">Не атрымліваць промостикеры</string>
|
||||||
<string name="useOldAppVer_title">Выкарыстоўваць стары дызайн</string>
|
<string name="useOldAppVer_title">Выкарыстоўваць стары дызайн</string>
|
||||||
<string name="useOldAppVer_summ">Працуе \"як ёсць\". Могуць быць памылкі</string>
|
<string name="useOldAppVer_summ">Працуе \"як ёсць\". Могуць быць памылкі</string>
|
||||||
|
<string name="invertFilters">Інвертаваць выключэння</string>
|
||||||
|
<string name="invertFilters_summ">Дададзеныя ў выключэння групы будуць фільтраваць</string>
|
||||||
<string name="downloading_update">Спампоўка абнаўлення</string>
|
<string name="downloading_update">Спампоўка абнаўлення</string>
|
||||||
<string name="sources">Крыніцы</string>
|
<string name="sources">Крыніцы</string>
|
||||||
<string name="businessDisabler_title">Адключыць бізнес-паведамлення</string>
|
<string name="businessDisabler_title">Адключыць бізнес-паведамлення</string>
|
||||||
@@ -7010,6 +7012,7 @@
|
|||||||
|
|
||||||
<string name="datasettings_title">Налады дадзеных прыкладання</string>
|
<string name="datasettings_title">Налады дадзеных прыкладання</string>
|
||||||
<string name="invalidate_theme_cache_title">Інвалідацыя кэша тэмы</string>
|
<string name="invalidate_theme_cache_title">Інвалідацыя кэша тэмы</string>
|
||||||
|
<string name="invalidate_theme_cache_each_update_title">Ачыстка кэша тэмы пасля абнаўлення для прадухілення праблем з акцэнтамі</string>
|
||||||
|
|
||||||
<string name="useCustomPrefsStyle_title">Выкарыстоўваць новыя тумблеры</string>
|
<string name="useCustomPrefsStyle_title">Выкарыстоўваць новыя тумблеры</string>
|
||||||
<string name="useCustomPrefsStyle_summ">Больш сучасны і стыльны выгляд тумблераў у наладах</string>
|
<string name="useCustomPrefsStyle_summ">Больш сучасны і стыльны выгляд тумблераў у наладах</string>
|
||||||
@@ -7025,4 +7028,8 @@
|
|||||||
|
|
||||||
<string name="compression_types">Спосаб кампрэсіі фота</string>
|
<string name="compression_types">Спосаб кампрэсіі фота</string>
|
||||||
<string name="compression_types_selection">Выберыце спосаб кампрэсіі</string>
|
<string name="compression_types_selection">Выберыце спосаб кампрэсіі</string>
|
||||||
|
|
||||||
|
<string name="clear_all_cache">Ачысціць ўвесь кэш?</string>
|
||||||
|
<string name="cache_size">Памер прыкладання</string>
|
||||||
|
<string name="cache_size_summ">Вага кэша прыкладання</string>
|
||||||
</resources>
|
</resources>
|
||||||
@@ -6191,8 +6191,8 @@
|
|||||||
<string name="remove_from_ads_whitelist">Удалить из вайтлиста рекламы</string>
|
<string name="remove_from_ads_whitelist">Удалить из вайтлиста рекламы</string>
|
||||||
<string name="add_to_ads_stories_whitelist">Добавить в вайтлист историй</string>
|
<string name="add_to_ads_stories_whitelist">Добавить в вайтлист историй</string>
|
||||||
<string name="remove_from_ads_stories_whitelist">Удалить из вайтлиста историй</string>
|
<string name="remove_from_ads_stories_whitelist">Удалить из вайтлиста историй</string>
|
||||||
<string name="removed_from_whitelist_success">Группа удалена из вайтлиста</string>
|
<string name="removed_from_whitelist_success">Удалено из вайтлиста</string>
|
||||||
<string name="added_to_whitelist_success">Группа добавлена в вайтлист</string>
|
<string name="added_to_whitelist_success">Добавлено в вайтлист</string>
|
||||||
|
|
||||||
<string name="whitelisted_ad_groups_title">Вайтлист рекламы</string>
|
<string name="whitelisted_ad_groups_title">Вайтлист рекламы</string>
|
||||||
<string name="whitelisted_filters_groups_title">Вайтлист фильтров и источников</string>
|
<string name="whitelisted_filters_groups_title">Вайтлист фильтров и источников</string>
|
||||||
@@ -6330,6 +6330,8 @@
|
|||||||
<string name="promotedstickers_title">Не получать промостикеры</string>
|
<string name="promotedstickers_title">Не получать промостикеры</string>
|
||||||
<string name="useOldAppVer_title">Использовать старый дизайн</string>
|
<string name="useOldAppVer_title">Использовать старый дизайн</string>
|
||||||
<string name="useOldAppVer_summ">Работает \"как есть\". Могут быть ошибки</string>
|
<string name="useOldAppVer_summ">Работает \"как есть\". Могут быть ошибки</string>
|
||||||
|
<string name="invertFilters">Инвертировать исключения</string>
|
||||||
|
<string name="invertFilters_summ">Добавленные в исключения группы будут фильтроваться</string>
|
||||||
|
|
||||||
<string name="downloading_update">Скачивание обновления</string>
|
<string name="downloading_update">Скачивание обновления</string>
|
||||||
<string name="sources">Источники</string>
|
<string name="sources">Источники</string>
|
||||||
@@ -6392,6 +6394,7 @@
|
|||||||
|
|
||||||
<string name="datasettings_title">Настройки данных приложения</string>
|
<string name="datasettings_title">Настройки данных приложения</string>
|
||||||
<string name="invalidate_theme_cache_title">Инвалидация кэша темы</string>
|
<string name="invalidate_theme_cache_title">Инвалидация кэша темы</string>
|
||||||
|
<string name="invalidate_theme_cache_each_update_title">Очистка кэша темы после обновления для предотвращения проблем с акцентами</string>
|
||||||
|
|
||||||
<string name="useCustomPrefsStyle_title">Использовать новые переключатели</string>
|
<string name="useCustomPrefsStyle_title">Использовать новые переключатели</string>
|
||||||
<string name="useCustomPrefsStyle_summ">Более современный и стильный вид тумблеров в настройках</string>
|
<string name="useCustomPrefsStyle_summ">Более современный и стильный вид тумблеров в настройках</string>
|
||||||
@@ -6407,4 +6410,8 @@
|
|||||||
|
|
||||||
<string name="compression_types">Способ компрессии фото</string>
|
<string name="compression_types">Способ компрессии фото</string>
|
||||||
<string name="compression_types_selection">Выберите способ компрессии</string>
|
<string name="compression_types_selection">Выберите способ компрессии</string>
|
||||||
|
|
||||||
|
<string name="clear_all_cache">Очистить весь кеш?</string>
|
||||||
|
<string name="cache_size">Размер приложения</string>
|
||||||
|
<string name="cache_size_summ">Вес кеша приложения</string>
|
||||||
</resources>
|
</resources>
|
||||||
@@ -6116,8 +6116,8 @@
|
|||||||
<string name="remove_from_ads_whitelist">Видалити з вайтліста реклами</string>
|
<string name="remove_from_ads_whitelist">Видалити з вайтліста реклами</string>
|
||||||
<string name="add_to_ads_stories_whitelist">Додати до вайтліста історій</string>
|
<string name="add_to_ads_stories_whitelist">Додати до вайтліста історій</string>
|
||||||
<string name="remove_from_ads_stories_whitelist">Видалити з вайтліста історій</string>
|
<string name="remove_from_ads_stories_whitelist">Видалити з вайтліста історій</string>
|
||||||
<string name="removed_from_whitelist_success">Група видалена з вайтліста</string>
|
<string name="removed_from_whitelist_success">Видалена з вайтліста</string>
|
||||||
<string name="added_to_whitelist_success">Група додана до вайтліста</string>
|
<string name="added_to_whitelist_success">Додана до вайтліста</string>
|
||||||
|
|
||||||
<string name="whitelisted_ad_groups_title">Вайтліст реклами</string>
|
<string name="whitelisted_ad_groups_title">Вайтліст реклами</string>
|
||||||
<string name="whitelisted_filters_groups_title">Вайтліст фільтрів та джерел</string>
|
<string name="whitelisted_filters_groups_title">Вайтліст фільтрів та джерел</string>
|
||||||
@@ -6255,6 +6255,8 @@
|
|||||||
<string name="promotedstickers_title">Не отримувати промостикери</string>
|
<string name="promotedstickers_title">Не отримувати промостикери</string>
|
||||||
<string name="useOldAppVer_title">Використовувати старий дизайн</string>
|
<string name="useOldAppVer_title">Використовувати старий дизайн</string>
|
||||||
<string name="useOldAppVer_summ">Працює \"як є\". Можливі помилки</string>
|
<string name="useOldAppVer_summ">Працює \"як є\". Можливі помилки</string>
|
||||||
|
<string name="invertFilters">Інвертувати винятки</string>
|
||||||
|
<string name="invertFilters_summ">Додані в виключення групи будуть фільтруватися</string>
|
||||||
|
|
||||||
<string name="downloading_update">Завантаження оновлення</string>
|
<string name="downloading_update">Завантаження оновлення</string>
|
||||||
<string name="sources">Джерела</string>
|
<string name="sources">Джерела</string>
|
||||||
@@ -6317,6 +6319,7 @@
|
|||||||
|
|
||||||
<string name="datasettings_title">Налаштування даних додатку</string>
|
<string name="datasettings_title">Налаштування даних додатку</string>
|
||||||
<string name="invalidate_theme_cache_title">Інвалідація кешу теми</string>
|
<string name="invalidate_theme_cache_title">Інвалідація кешу теми</string>
|
||||||
|
<string name="invalidate_theme_cache_each_update_title">Очищення кешу теми після оновлення для запобігання проблем з акцентами</string>
|
||||||
|
|
||||||
<string name="useCustomPrefsStyle_title">Використовувати нові перемикачі</string>
|
<string name="useCustomPrefsStyle_title">Використовувати нові перемикачі</string>
|
||||||
<string name="useCustomPrefsStyle_summ">Більш сучасний і стильний вигляд тумблерів у налаштуваннях</string>
|
<string name="useCustomPrefsStyle_summ">Більш сучасний і стильний вигляд тумблерів у налаштуваннях</string>
|
||||||
@@ -6332,4 +6335,8 @@
|
|||||||
|
|
||||||
<string name="compression_types">Спосіб компресії фото</string>
|
<string name="compression_types">Спосіб компресії фото</string>
|
||||||
<string name="compression_types_selection">Виберіть спосіб компресії</string>
|
<string name="compression_types_selection">Виберіть спосіб компресії</string>
|
||||||
|
|
||||||
|
<string name="clear_all_cache">Очистити весь кеш?</string>
|
||||||
|
<string name="cache_size">Розмір програми</string>
|
||||||
|
<string name="cache_size_summ">Вага кеша додатки</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
|||||||
+578
-578
File diff suppressed because it is too large
Load Diff
@@ -6329,8 +6329,8 @@ May look like a fake leaving the online"</string>
|
|||||||
<string name="remove_from_ads_stories_whitelist">Remove from stories whitelist</string>
|
<string name="remove_from_ads_stories_whitelist">Remove from stories whitelist</string>
|
||||||
<string name="add_to_ads_whitelist">Add to ads stories whitelist</string>
|
<string name="add_to_ads_whitelist">Add to ads stories whitelist</string>
|
||||||
<string name="remove_from_ads_whitelist">Remove from ads stories whitelist</string>
|
<string name="remove_from_ads_whitelist">Remove from ads stories whitelist</string>
|
||||||
<string name="removed_from_whitelist_success">Group removed from whitelist</string>
|
<string name="removed_from_whitelist_success">Removed from whitelist</string>
|
||||||
<string name="added_to_whitelist_success">Group added to whitelist</string>
|
<string name="added_to_whitelist_success">Added to whitelist</string>
|
||||||
|
|
||||||
<string name="whitelisted_ad_groups_title">Ads whitelist</string>
|
<string name="whitelisted_ad_groups_title">Ads whitelist</string>
|
||||||
<string name="whitelisted_filters_groups_title">Filters whitelist and copyrights</string>
|
<string name="whitelisted_filters_groups_title">Filters whitelist and copyrights</string>
|
||||||
@@ -6468,6 +6468,8 @@ May look like a fake leaving the online"</string>
|
|||||||
<string name="promotedstickers_title">Don\'t receive promoted stickers</string>
|
<string name="promotedstickers_title">Don\'t receive promoted stickers</string>
|
||||||
<string name="useOldAppVer_title">Use old music catalog</string>
|
<string name="useOldAppVer_title">Use old music catalog</string>
|
||||||
<string name="useOldAppVer_summ">Works \"as is\". There may be errors</string>
|
<string name="useOldAppVer_summ">Works \"as is\". There may be errors</string>
|
||||||
|
<string name="invertFilters">Invert exceptions</string>
|
||||||
|
<string name="invertFilters_summ">Groups added to exceptions will be filtered</string>
|
||||||
|
|
||||||
<string name="downloading_update">Downloading update</string>
|
<string name="downloading_update">Downloading update</string>
|
||||||
<string name="sources">Sources</string>
|
<string name="sources">Sources</string>
|
||||||
@@ -6530,6 +6532,7 @@ May look like a fake leaving the online"</string>
|
|||||||
|
|
||||||
<string name="datasettings_title">Application data settings</string>
|
<string name="datasettings_title">Application data settings</string>
|
||||||
<string name="invalidate_theme_cache_title">Invalidate theme cache</string>
|
<string name="invalidate_theme_cache_title">Invalidate theme cache</string>
|
||||||
|
<string name="invalidate_theme_cache_each_update_title">Clear theme cache after update to prevent problems with accents</string>
|
||||||
|
|
||||||
<string name="useCustomPrefsStyle_title">Use new switches</string>
|
<string name="useCustomPrefsStyle_title">Use new switches</string>
|
||||||
<string name="useCustomPrefsStyle_summ">More modern and stylish toggle switches in settings</string>
|
<string name="useCustomPrefsStyle_summ">More modern and stylish toggle switches in settings</string>
|
||||||
@@ -6545,4 +6548,8 @@ May look like a fake leaving the online"</string>
|
|||||||
|
|
||||||
<string name="compression_types">Photo compression method</string>
|
<string name="compression_types">Photo compression method</string>
|
||||||
<string name="compression_types_selection">Choose the compression method</string>
|
<string name="compression_types_selection">Choose the compression method</string>
|
||||||
|
|
||||||
|
<string name="clear_all_cache">Clear all cache?</string>
|
||||||
|
<string name="cache_size">App size</string>
|
||||||
|
<string name="cache_size_summ">Cache size</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
|||||||
@@ -89,6 +89,11 @@
|
|||||||
<Preference
|
<Preference
|
||||||
android:key="whitelisted_filters_groups"
|
android:key="whitelisted_filters_groups"
|
||||||
android:title="@string/whitelisted_filters_groups_title"/>
|
android:title="@string/whitelisted_filters_groups_title"/>
|
||||||
|
<com.vtosters.lite.ui.MaterialSwitchPreference
|
||||||
|
android:defaultValue="false"
|
||||||
|
android:key="invertFilters"
|
||||||
|
android:summary="@string/invertFilters_summ"
|
||||||
|
android:title="@string/invertFilters"/>
|
||||||
<com.vtosters.lite.ui.MaterialSwitchPreference
|
<com.vtosters.lite.ui.MaterialSwitchPreference
|
||||||
android:defaultValue="false"
|
android:defaultValue="false"
|
||||||
android:key="blockminiapps"
|
android:key="blockminiapps"
|
||||||
|
|||||||
@@ -4,12 +4,6 @@
|
|||||||
<Preference
|
<Preference
|
||||||
android:key="datasettings"
|
android:key="datasettings"
|
||||||
android:title="@string/datasettings_title"/>
|
android:title="@string/datasettings_title"/>
|
||||||
<Preference
|
|
||||||
android:key="clearcache"
|
|
||||||
android:title="@string/clearcache_other_title"/>
|
|
||||||
<Preference
|
|
||||||
android:key="autoclearcache"
|
|
||||||
android:title="@string/autoclearcache"/>
|
|
||||||
</PreferenceCategory>
|
</PreferenceCategory>
|
||||||
<PreferenceCategory android:title="@string/other_fix_app">
|
<PreferenceCategory android:title="@string/other_fix_app">
|
||||||
<Preference
|
<Preference
|
||||||
|
|||||||
@@ -7,6 +7,11 @@
|
|||||||
android:summary="@string/accent_color_summ"
|
android:summary="@string/accent_color_summ"
|
||||||
android:icon="@drawable/bg_accent_circle"
|
android:icon="@drawable/bg_accent_circle"
|
||||||
android:title="@string/accent_color_title"/>
|
android:title="@string/accent_color_title"/>
|
||||||
|
<com.vtosters.lite.ui.MaterialSwitchPreference
|
||||||
|
android:defaultValue="true"
|
||||||
|
android:key="invalidate_theme_cache_each_update"
|
||||||
|
android:summary="@string/invalidate_theme_cache_each_update_title"
|
||||||
|
android:title="@string/invalidate_theme_cache_title"/>
|
||||||
<Preference
|
<Preference
|
||||||
android:key="invalidate_theme_cache"
|
android:key="invalidate_theme_cache"
|
||||||
android:title="@string/invalidate_theme_cache_title" />
|
android:title="@string/invalidate_theme_cache_title" />
|
||||||
@@ -84,10 +89,5 @@
|
|||||||
android:key="VKUI_INJ"
|
android:key="VKUI_INJ"
|
||||||
android:summary="@string/appearance_other_color_webview_summary"
|
android:summary="@string/appearance_other_color_webview_summary"
|
||||||
android:title="@string/vkuiinj"/>
|
android:title="@string/vkuiinj"/>
|
||||||
<com.vtosters.lite.ui.MaterialSwitchPreference
|
|
||||||
android:defaultValue="false"
|
|
||||||
android:key="useNewColorEngine"
|
|
||||||
android:summary="@string/useNewColorEngine_summ"
|
|
||||||
android:title="@string/useNewColorEngine_title"/>
|
|
||||||
</PreferenceCategory>
|
</PreferenceCategory>
|
||||||
</PreferenceScreen>
|
</PreferenceScreen>
|
||||||
@@ -157,7 +157,7 @@
|
|||||||
.method public getResources()Landroid/content/res/Resources;
|
.method public getResources()Landroid/content/res/Resources;
|
||||||
.registers 3
|
.registers 3
|
||||||
|
|
||||||
invoke-static {}, Lru/vtosters/hooks/other/ThemesUtils;->isCustomAccentEnabled()Z
|
invoke-static {}, Lru/vtosters/hooks/other/ThemesUtils;->isMonetTheme()Z
|
||||||
|
|
||||||
move-result v1
|
move-result v1
|
||||||
|
|
||||||
|
|||||||
+20
-20
@@ -222,41 +222,41 @@
|
|||||||
|
|
||||||
.line 14
|
.line 14
|
||||||
:cond_0
|
:cond_0
|
||||||
new-instance v0, Lcom/vk/api/audio/AudioSendStartEvent;
|
# new-instance v0, Lcom/vk/api/audio/AudioSendStartEvent;
|
||||||
|
|
||||||
invoke-virtual {p1}, Lcom/vk/dto/music/MusicTrack;->y1()Ljava/lang/String;
|
# invoke-virtual {p1}, Lcom/vk/dto/music/MusicTrack;->y1()Ljava/lang/String;
|
||||||
|
|
||||||
move-result-object p1
|
# move-result-object p1
|
||||||
|
|
||||||
sget-object v2, Lcom/vk/api/base/ApiConfig;->d:Lcom/vk/api/base/ApiConfig$a;
|
# sget-object v2, Lcom/vk/api/base/ApiConfig;->d:Lcom/vk/api/base/ApiConfig$a;
|
||||||
|
|
||||||
invoke-interface {v2}, Lcom/vk/api/base/ApiConfig$a;->O1()Ljava/lang/String;
|
# invoke-interface {v2}, Lcom/vk/api/base/ApiConfig$a;->O1()Ljava/lang/String;
|
||||||
|
|
||||||
move-result-object v2
|
# move-result-object v2
|
||||||
|
|
||||||
invoke-direct {v0, p1, v2}, Lcom/vk/api/audio/AudioSendStartEvent;-><init>(Ljava/lang/String;Ljava/lang/String;)V
|
# invoke-direct {v0, p1, v2}, Lcom/vk/api/audio/AudioSendStartEvent;-><init>(Ljava/lang/String;Ljava/lang/String;)V
|
||||||
|
|
||||||
const/4 p1, 0x0
|
# const/4 p1, 0x0
|
||||||
|
|
||||||
.line 15
|
# .line 15
|
||||||
invoke-static {v0, p1, v1, p1}, Lcom/vk/api/base/ApiRequest;->d(Lcom/vk/api/base/ApiRequest;Lcom/vk/api/base/ApiThreadHolder;ILjava/lang/Object;)Lio/reactivex/Observable;
|
# invoke-static {v0, p1, v1, p1}, Lcom/vk/api/base/ApiRequest;->d(Lcom/vk/api/base/ApiRequest;Lcom/vk/api/base/ApiThreadHolder;ILjava/lang/Object;)Lio/reactivex/Observable;
|
||||||
|
|
||||||
move-result-object p1
|
# move-result-object p1
|
||||||
|
|
||||||
.line 16
|
# .line 16
|
||||||
new-instance v0, Lcom/vk/music/notifications/restriction/MusicRestrictionModelImpl$d;
|
# new-instance v0, Lcom/vk/music/notifications/restriction/MusicRestrictionModelImpl$d;
|
||||||
|
|
||||||
invoke-direct {v0, p0}, Lcom/vk/music/notifications/restriction/MusicRestrictionModelImpl$d;-><init>(Lcom/vk/music/notifications/restriction/MusicRestrictionModelImpl;)V
|
# invoke-direct {v0, p0}, Lcom/vk/music/notifications/restriction/MusicRestrictionModelImpl$d;-><init>(Lcom/vk/music/notifications/restriction/MusicRestrictionModelImpl;)V
|
||||||
|
|
||||||
.line 17
|
# .line 17
|
||||||
sget-object v1, Lcom/vk/music/notifications/restriction/MusicRestrictionModelImpl$e;->a:Lcom/vk/music/notifications/restriction/MusicRestrictionModelImpl$e;
|
# sget-object v1, Lcom/vk/music/notifications/restriction/MusicRestrictionModelImpl$e;->a:Lcom/vk/music/notifications/restriction/MusicRestrictionModelImpl$e;
|
||||||
|
|
||||||
.line 18
|
# .line 18
|
||||||
invoke-virtual {p1, v0, v1}, Lio/reactivex/Observable;->a(Lio/reactivex/functions/Consumer;Lio/reactivex/functions/Consumer;)Lio/reactivex/disposables/Disposable;
|
# invoke-virtual {p1, v0, v1}, Lio/reactivex/Observable;->a(Lio/reactivex/functions/Consumer;Lio/reactivex/functions/Consumer;)Lio/reactivex/disposables/Disposable;
|
||||||
|
|
||||||
move-result-object p1
|
# move-result-object p1
|
||||||
|
|
||||||
iput-object p1, p0, Lcom/vk/music/notifications/restriction/MusicRestrictionModelImpl;->a:Lio/reactivex/disposables/Disposable;
|
# iput-object p1, p0, Lcom/vk/music/notifications/restriction/MusicRestrictionModelImpl;->a:Lio/reactivex/disposables/Disposable;
|
||||||
|
|
||||||
return-void
|
return-void
|
||||||
.end method
|
.end method
|
||||||
|
|||||||
Reference in New Issue
Block a user