Merge branch 'main' into main

This commit is contained in:
gdlbo
2024-02-07 13:57:33 +03:00
committed by GitHub
98 changed files with 2802 additions and 2168 deletions
+28
View File
@@ -0,0 +1,28 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="RClass Regeneration" type="ShConfigurationType">
<option name="SCRIPT_TEXT" value="" />
<option name="INDEPENDENT_SCRIPT_PATH" value="true" />
<option name="SCRIPT_PATH" value="$PROJECT_DIR$/scripts/rclass_regenerator.sh" />
<option name="SCRIPT_OPTIONS" value="" />
<option name="INDEPENDENT_SCRIPT_WORKING_DIRECTORY" value="true" />
<option name="SCRIPT_WORKING_DIRECTORY" value="$PROJECT_DIR$" />
<option name="INDEPENDENT_INTERPRETER_PATH" value="true" />
<option name="INTERPRETER_PATH" value="/bin/zsh" />
<option name="INTERPRETER_OPTIONS" value="" />
<option name="EXECUTE_IN_TERMINAL" value="true" />
<option name="EXECUTE_SCRIPT_FILE" value="true" />
<envs />
<method v="2" />
</configuration>
<configuration default="false" name="RClass Regeneration" type="BatchConfigurationType" factoryName="Batch">
<option name="INTERPRETER_OPTIONS" value="" />
<option name="WORKING_DIRECTORY" value="" />
<option name="PARENT_ENVS" value="true" />
<module name="" />
<option name="SCRIPT_NAME" value="./scripts/rclass_regenerator.bat" />
<option name="PARAMETERS" value="" />
<method v="2">
<option name="Make" enabled="true" />
</method>
</configuration>
</component>
+17
View File
@@ -0,0 +1,17 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="Update APKs Jars (MacOS)" type="ShConfigurationType">
<option name="SCRIPT_TEXT" value="" />
<option name="INDEPENDENT_SCRIPT_PATH" value="true" />
<option name="SCRIPT_PATH" value="$PROJECT_DIR$/scripts/update_jars_brew.sh" />
<option name="SCRIPT_OPTIONS" value="" />
<option name="INDEPENDENT_SCRIPT_WORKING_DIRECTORY" value="true" />
<option name="SCRIPT_WORKING_DIRECTORY" value="$PROJECT_DIR$" />
<option name="INDEPENDENT_INTERPRETER_PATH" value="true" />
<option name="INTERPRETER_PATH" value="/bin/zsh" />
<option name="INTERPRETER_OPTIONS" value="" />
<option name="EXECUTE_IN_TERMINAL" value="true" />
<option name="EXECUTE_SCRIPT_FILE" value="true" />
<envs />
<method v="2" />
</configuration>
</component>
+17
View File
@@ -0,0 +1,17 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="Update APKs Jars" type="ShConfigurationType">
<option name="SCRIPT_TEXT" value="" />
<option name="INDEPENDENT_SCRIPT_PATH" value="true" />
<option name="SCRIPT_PATH" value="$PROJECT_DIR$/scripts/update_jars.sh" />
<option name="SCRIPT_OPTIONS" value="" />
<option name="INDEPENDENT_SCRIPT_WORKING_DIRECTORY" value="true" />
<option name="SCRIPT_WORKING_DIRECTORY" value="$PROJECT_DIR$" />
<option name="INDEPENDENT_INTERPRETER_PATH" value="true" />
<option name="INTERPRETER_PATH" value="/bin/zsh" />
<option name="INTERPRETER_OPTIONS" value="" />
<option name="EXECUTE_IN_TERMINAL" value="true" />
<option name="EXECUTE_SCRIPT_FILE" value="true" />
<envs />
<method v="2" />
</configuration>
</component>
@@ -0,0 +1,24 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="lite [app:buildAndInstallVTLBeta]" type="GradleRunConfiguration" factoryName="Gradle" nameIsGenerated="true">
<ExternalSystemSettings>
<option name="executionName" />
<option name="externalProjectPath" value="$PROJECT_DIR$" />
<option name="externalSystemIdString" value="GRADLE" />
<option name="scriptParameters" value="" />
<option name="taskDescriptions">
<list />
</option>
<option name="taskNames">
<list>
<option value="app:buildAndInstallVTLBeta" />
</list>
</option>
<option name="vmOptions" value="-Xms4g -Xmx4g" />
</ExternalSystemSettings>
<ExternalSystemDebugServerProcess>true</ExternalSystemDebugServerProcess>
<ExternalSystemReattachDebugProcess>true</ExternalSystemReattachDebugProcess>
<DebugAllEnabled>false</DebugAllEnabled>
<RunAsTest>false</RunAsTest>
<method v="2" />
</configuration>
</component>
@@ -0,0 +1,24 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="lite [app:buildAndInstallVTLDev]" type="GradleRunConfiguration" factoryName="Gradle" nameIsGenerated="true">
<ExternalSystemSettings>
<option name="executionName" />
<option name="externalProjectPath" value="$PROJECT_DIR$" />
<option name="externalSystemIdString" value="GRADLE" />
<option name="scriptParameters" value="" />
<option name="taskDescriptions">
<list />
</option>
<option name="taskNames">
<list>
<option value="app:buildAndInstallVTLDev" />
</list>
</option>
<option name="vmOptions" value="-Xms4g -Xmx4g" />
</ExternalSystemSettings>
<ExternalSystemDebugServerProcess>true</ExternalSystemDebugServerProcess>
<ExternalSystemReattachDebugProcess>true</ExternalSystemReattachDebugProcess>
<DebugAllEnabled>false</DebugAllEnabled>
<RunAsTest>false</RunAsTest>
<method v="2" />
</configuration>
</component>
@@ -0,0 +1,24 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="lite [app:buildAndInstallVTLRelease]" type="GradleRunConfiguration" factoryName="Gradle" nameIsGenerated="true">
<ExternalSystemSettings>
<option name="executionName" />
<option name="externalProjectPath" value="$PROJECT_DIR$" />
<option name="externalSystemIdString" value="GRADLE" />
<option name="scriptParameters" value="" />
<option name="taskDescriptions">
<list />
</option>
<option name="taskNames">
<list>
<option value="app:buildAndInstallVTLRelease" />
</list>
</option>
<option name="vmOptions" value="-Xms4g -Xmx4g" />
</ExternalSystemSettings>
<ExternalSystemDebugServerProcess>true</ExternalSystemDebugServerProcess>
<ExternalSystemReattachDebugProcess>true</ExternalSystemReattachDebugProcess>
<DebugAllEnabled>false</DebugAllEnabled>
<RunAsTest>false</RunAsTest>
<method v="2" />
</configuration>
</component>
@@ -0,0 +1,24 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="lite [app:buildAndLaunchVTLBeta]" type="GradleRunConfiguration" factoryName="Gradle" nameIsGenerated="true">
<ExternalSystemSettings>
<option name="executionName" />
<option name="externalProjectPath" value="$PROJECT_DIR$" />
<option name="externalSystemIdString" value="GRADLE" />
<option name="scriptParameters" value="" />
<option name="taskDescriptions">
<list />
</option>
<option name="taskNames">
<list>
<option value="app:buildAndLaunchVTLBeta" />
</list>
</option>
<option name="vmOptions" value="-Xms4g -Xmx4g" />
</ExternalSystemSettings>
<ExternalSystemDebugServerProcess>true</ExternalSystemDebugServerProcess>
<ExternalSystemReattachDebugProcess>true</ExternalSystemReattachDebugProcess>
<DebugAllEnabled>false</DebugAllEnabled>
<RunAsTest>false</RunAsTest>
<method v="2" />
</configuration>
</component>
@@ -0,0 +1,24 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="lite [app:buildAndLaunchVTLDev]" type="GradleRunConfiguration" factoryName="Gradle" nameIsGenerated="true">
<ExternalSystemSettings>
<option name="executionName" />
<option name="externalProjectPath" value="$PROJECT_DIR$" />
<option name="externalSystemIdString" value="GRADLE" />
<option name="scriptParameters" value="" />
<option name="taskDescriptions">
<list />
</option>
<option name="taskNames">
<list>
<option value="app:buildAndLaunchVTLDev" />
</list>
</option>
<option name="vmOptions" value="-Xms4g -Xmx4g" />
</ExternalSystemSettings>
<ExternalSystemDebugServerProcess>true</ExternalSystemDebugServerProcess>
<ExternalSystemReattachDebugProcess>true</ExternalSystemReattachDebugProcess>
<DebugAllEnabled>false</DebugAllEnabled>
<RunAsTest>false</RunAsTest>
<method v="2" />
</configuration>
</component>
@@ -0,0 +1,24 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="lite [app:buildAndLaunchVTLRelease]" type="GradleRunConfiguration" factoryName="Gradle" nameIsGenerated="true">
<ExternalSystemSettings>
<option name="executionName" />
<option name="externalProjectPath" value="$PROJECT_DIR$" />
<option name="externalSystemIdString" value="GRADLE" />
<option name="scriptParameters" value="" />
<option name="taskDescriptions">
<list />
</option>
<option name="taskNames">
<list>
<option value="app:buildAndLaunchVTLRelease" />
</list>
</option>
<option name="vmOptions" value="-Xms4g -Xmx4g" />
</ExternalSystemSettings>
<ExternalSystemDebugServerProcess>true</ExternalSystemDebugServerProcess>
<ExternalSystemReattachDebugProcess>true</ExternalSystemReattachDebugProcess>
<DebugAllEnabled>false</DebugAllEnabled>
<RunAsTest>false</RunAsTest>
<method v="2" />
</configuration>
</component>
+24
View File
@@ -0,0 +1,24 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="lite [app:buildVTLBeta]" type="GradleRunConfiguration" factoryName="Gradle" nameIsGenerated="true">
<ExternalSystemSettings>
<option name="executionName" />
<option name="externalProjectPath" value="$PROJECT_DIR$" />
<option name="externalSystemIdString" value="GRADLE" />
<option name="scriptParameters" value="" />
<option name="taskDescriptions">
<list />
</option>
<option name="taskNames">
<list>
<option value="app:buildVTLBeta" />
</list>
</option>
<option name="vmOptions" value="-Xms4g -Xmx4g" />
</ExternalSystemSettings>
<ExternalSystemDebugServerProcess>true</ExternalSystemDebugServerProcess>
<ExternalSystemReattachDebugProcess>true</ExternalSystemReattachDebugProcess>
<DebugAllEnabled>false</DebugAllEnabled>
<RunAsTest>false</RunAsTest>
<method v="2" />
</configuration>
</component>
+24
View File
@@ -0,0 +1,24 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="lite [app:buildVTLDev]" type="GradleRunConfiguration" factoryName="Gradle" nameIsGenerated="true">
<ExternalSystemSettings>
<option name="executionName" />
<option name="externalProjectPath" value="$PROJECT_DIR$" />
<option name="externalSystemIdString" value="GRADLE" />
<option name="scriptParameters" value="" />
<option name="taskDescriptions">
<list />
</option>
<option name="taskNames">
<list>
<option value="app:buildVTLDev" />
</list>
</option>
<option name="vmOptions" value="-Xms4g -Xmx4g" />
</ExternalSystemSettings>
<ExternalSystemDebugServerProcess>true</ExternalSystemDebugServerProcess>
<ExternalSystemReattachDebugProcess>true</ExternalSystemReattachDebugProcess>
<DebugAllEnabled>false</DebugAllEnabled>
<RunAsTest>false</RunAsTest>
<method v="2" />
</configuration>
</component>
+24
View File
@@ -0,0 +1,24 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="lite [app:buildVTLRelease]" type="GradleRunConfiguration" factoryName="Gradle" nameIsGenerated="true">
<ExternalSystemSettings>
<option name="executionName" />
<option name="externalProjectPath" value="$PROJECT_DIR$" />
<option name="externalSystemIdString" value="GRADLE" />
<option name="scriptParameters" value="" />
<option name="taskDescriptions">
<list />
</option>
<option name="taskNames">
<list>
<option value="app:buildVTLRelease" />
</list>
</option>
<option name="vmOptions" value="-Xms4g -Xmx4g" />
</ExternalSystemSettings>
<ExternalSystemDebugServerProcess>true</ExternalSystemDebugServerProcess>
<ExternalSystemReattachDebugProcess>true</ExternalSystemReattachDebugProcess>
<DebugAllEnabled>false</DebugAllEnabled>
<RunAsTest>false</RunAsTest>
<method v="2" />
</configuration>
</component>
+24
View File
@@ -0,0 +1,24 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="lite [app:exportDexBeta]" type="GradleRunConfiguration" factoryName="Gradle" nameIsGenerated="true">
<ExternalSystemSettings>
<option name="executionName" />
<option name="externalProjectPath" value="$PROJECT_DIR$" />
<option name="externalSystemIdString" value="GRADLE" />
<option name="scriptParameters" value="" />
<option name="taskDescriptions">
<list />
</option>
<option name="taskNames">
<list>
<option value="app:exportDexBeta" />
</list>
</option>
<option name="vmOptions" value="-Xms4g -Xmx4g" />
</ExternalSystemSettings>
<ExternalSystemDebugServerProcess>true</ExternalSystemDebugServerProcess>
<ExternalSystemReattachDebugProcess>true</ExternalSystemReattachDebugProcess>
<DebugAllEnabled>false</DebugAllEnabled>
<RunAsTest>false</RunAsTest>
<method v="2" />
</configuration>
</component>
+24
View File
@@ -0,0 +1,24 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="lite [app:exportDexDev]" type="GradleRunConfiguration" factoryName="Gradle" nameIsGenerated="true">
<ExternalSystemSettings>
<option name="executionName" />
<option name="externalProjectPath" value="$PROJECT_DIR$" />
<option name="externalSystemIdString" value="GRADLE" />
<option name="scriptParameters" value="" />
<option name="taskDescriptions">
<list />
</option>
<option name="taskNames">
<list>
<option value="app:exportDexDev" />
</list>
</option>
<option name="vmOptions" value="-Xms4g -Xmx4g" />
</ExternalSystemSettings>
<ExternalSystemDebugServerProcess>true</ExternalSystemDebugServerProcess>
<ExternalSystemReattachDebugProcess>true</ExternalSystemReattachDebugProcess>
<DebugAllEnabled>false</DebugAllEnabled>
<RunAsTest>false</RunAsTest>
<method v="2" />
</configuration>
</component>
+24
View File
@@ -0,0 +1,24 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="lite [app:exportDexRelease]" type="GradleRunConfiguration" factoryName="Gradle" nameIsGenerated="true">
<ExternalSystemSettings>
<option name="executionName" />
<option name="externalProjectPath" value="$PROJECT_DIR$" />
<option name="externalSystemIdString" value="GRADLE" />
<option name="scriptParameters" value="" />
<option name="taskDescriptions">
<list />
</option>
<option name="taskNames">
<list>
<option value="app:exportDexRelease" />
</list>
</option>
<option name="vmOptions" value="-Xms4g -Xmx4g" />
</ExternalSystemSettings>
<ExternalSystemDebugServerProcess>true</ExternalSystemDebugServerProcess>
<ExternalSystemReattachDebugProcess>true</ExternalSystemReattachDebugProcess>
<DebugAllEnabled>false</DebugAllEnabled>
<RunAsTest>false</RunAsTest>
<method v="2" />
</configuration>
</component>
@@ -0,0 +1,24 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="lite [app:prepareDexForMergeDev]" type="GradleRunConfiguration" factoryName="Gradle" nameIsGenerated="true">
<ExternalSystemSettings>
<option name="executionName" />
<option name="externalProjectPath" value="$PROJECT_DIR$" />
<option name="externalSystemIdString" value="GRADLE" />
<option name="scriptParameters" value="" />
<option name="taskDescriptions">
<list />
</option>
<option name="taskNames">
<list>
<option value="app:prepareDexForMergeDev" />
</list>
</option>
<option name="vmOptions" value="-Xms4g -Xmx4g" />
</ExternalSystemSettings>
<ExternalSystemDebugServerProcess>true</ExternalSystemDebugServerProcess>
<ExternalSystemReattachDebugProcess>true</ExternalSystemReattachDebugProcess>
<DebugAllEnabled>false</DebugAllEnabled>
<RunAsTest>false</RunAsTest>
<method v="2" />
</configuration>
</component>
@@ -0,0 +1,24 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="lite [app:prepareDexForMergeRelease]" type="GradleRunConfiguration" factoryName="Gradle" nameIsGenerated="true">
<ExternalSystemSettings>
<option name="executionName" />
<option name="externalProjectPath" value="$PROJECT_DIR$" />
<option name="externalSystemIdString" value="GRADLE" />
<option name="scriptParameters" value="" />
<option name="taskDescriptions">
<list />
</option>
<option name="taskNames">
<list>
<option value="app:prepareDexForMergeRelease" />
</list>
</option>
<option name="vmOptions" value="-Xms4g -Xmx4g" />
</ExternalSystemSettings>
<ExternalSystemDebugServerProcess>true</ExternalSystemDebugServerProcess>
<ExternalSystemReattachDebugProcess>true</ExternalSystemReattachDebugProcess>
<DebugAllEnabled>false</DebugAllEnabled>
<RunAsTest>false</RunAsTest>
<method v="2" />
</configuration>
</component>
@@ -81,6 +81,7 @@ public class LibVKXClient {
lambdaplay(list, musicTrack, iLibVkxService, null);
}
public static String asId(MusicTrack musicTrack)
{ return musicTrack.y1(); }
public static String asId(MusicTrack musicTrack) {
return musicTrack.y1();
}
}
@@ -59,26 +59,22 @@ public class ArscBlamer {
* Maps type chunk entries to blamed resources.
*/
private final Multimap<TypeChunk.Entry, ResourceEntry> typeEntryToBlame = HashMultimap.create();
/**
* Maps resources to the type chunk entries they reference.
*/
private Multimap<ResourceEntry, TypeChunk.Entry> resourceEntries;
/**
* Maps resources which have no base config to the type chunk entries they reference.
*/
private Multimap<ResourceEntry, TypeChunk.Entry> baselessKeys;
/**
* Contains all of the type chunks in {@link #resourceTable}.
*/
private List<TypeChunk> typeChunks;
/**
* This is the {@link ResourceTableChunk} inside of the resources.arsc file in the APK.
*/
private final ResourceTableChunk resourceTable;
/**
* Maps resources to the type chunk entries they reference.
*/
private Multimap<ResourceEntry, TypeChunk.Entry> resourceEntries;
/**
* Maps resources which have no base config to the type chunk entries they reference.
*/
private Multimap<ResourceEntry, TypeChunk.Entry> baselessKeys;
/**
* Contains all of the type chunks in {@link #resourceTable}.
*/
private List<TypeChunk> typeChunks;
/**
* Creates a new {@link ArscBlamer}.
@@ -90,6 +86,14 @@ public class ArscBlamer {
this.stringToBlame = createEntryListArray(resourceTable.getStringPool().getStringCount());
}
private static List<ResourceEntry>[] createEntryListArray(int size) {
ArrayListResourceEntry[] result = new ArrayListResourceEntry[size];
for (int i = 0; i < size; ++i) {
result[i] = new ArrayListResourceEntry();
}
return result;
}
/**
* Generates blame mappings.
*/
@@ -257,14 +261,6 @@ public class ArscBlamer {
return false;
}
private static List<ResourceEntry>[] createEntryListArray(int size) {
ArrayListResourceEntry[] result = new ArrayListResourceEntry[size];
for (int i = 0; i < size; ++i) {
result[i] = new ArrayListResourceEntry();
}
return result;
}
/**
* Allows creation of concrete parameterized type arr {@link ArscBlamer#createEntryListArray}.
*/
@@ -283,6 +279,12 @@ public class ArscBlamer {
private final String typeName;
private final String entryName;
private ResourceEntry(String packageName, String typeName, String entryName) {
this.packageName = packageName;
this.typeName = typeName;
this.entryName = entryName;
}
static ResourceEntry create(TypeChunk.Entry entry) {
PackageChunk packageChunk = Preconditions.checkNotNull(entry.parent().getPackageChunk());
String packageName = packageChunk.getPackageName();
@@ -291,12 +293,6 @@ public class ArscBlamer {
return new ResourceEntry(packageName, typeName, entryName);
}
private ResourceEntry(String packageName, String typeName, String entryName) {
this.packageName = packageName;
this.typeName = typeName;
this.entryName = entryName;
}
public String packageName() {
return packageName;
}
@@ -31,6 +31,148 @@ import static java.nio.charset.StandardCharsets.US_ASCII;
* Describes a particular resource configuration.
*/
public class BinaryResourceConfiguration implements SerializableResource {
/**
* The below constants are from android.content.res.Configuration.
*/
private static final int DENSITY_DPI_UNDEFINED = 0;
private static final int DENSITY_DPI_LDPI = 120;
private static final int DENSITY_DPI_MDPI = 160;
private static final int DENSITY_DPI_TVDPI = 213;
private static final int DENSITY_DPI_HDPI = 240;
private static final int DENSITY_DPI_XHDPI = 320;
private static final int DENSITY_DPI_XXHDPI = 480;
private static final int DENSITY_DPI_XXXHDPI = 640;
private static final int DENSITY_DPI_ANY = 0xFFFE;
private static final int DENSITY_DPI_NONE = 0xFFFF;
private static final Map<Integer, String> DENSITY_DPI_VALUES =
ImmutableMap.<Integer, String>builder()
.put(DENSITY_DPI_UNDEFINED, "")
.put(DENSITY_DPI_LDPI, "ldpi")
.put(DENSITY_DPI_MDPI, "mdpi")
.put(DENSITY_DPI_TVDPI, "tvdpi")
.put(DENSITY_DPI_HDPI, "hdpi")
.put(DENSITY_DPI_XHDPI, "xhdpi")
.put(DENSITY_DPI_XXHDPI, "xxhdpi")
.put(DENSITY_DPI_XXXHDPI, "xxxhdpi")
.put(DENSITY_DPI_ANY, "anydpi")
.put(DENSITY_DPI_NONE, "nodpi")
.build();
private static final int KEYBOARD_NOKEYS = 1;
private static final int KEYBOARD_QWERTY = 2;
private static final int KEYBOARD_12KEY = 3;
private static final Map<Integer, String> KEYBOARD_VALUES = ImmutableMap.of(
KEYBOARD_NOKEYS, "nokeys",
KEYBOARD_QWERTY, "qwerty",
KEYBOARD_12KEY, "12key");
private static final int KEYBOARDHIDDEN_MASK = 0x03;
private static final int KEYBOARDHIDDEN_NO = 1;
private static final int KEYBOARDHIDDEN_YES = 2;
private static final int KEYBOARDHIDDEN_SOFT = 3;
private static final Map<Integer, String> KEYBOARDHIDDEN_VALUES = ImmutableMap.of(
KEYBOARDHIDDEN_NO, "keysexposed",
KEYBOARDHIDDEN_YES, "keyshidden",
KEYBOARDHIDDEN_SOFT, "keyssoft");
private static final int NAVIGATION_NONAV = 1;
private static final int NAVIGATION_DPAD = 2;
private static final int NAVIGATION_TRACKBALL = 3;
private static final int NAVIGATION_WHEEL = 4;
private static final Map<Integer, String> NAVIGATION_VALUES = ImmutableMap.of(
NAVIGATION_NONAV, "nonav",
NAVIGATION_DPAD, "dpad",
NAVIGATION_TRACKBALL, "trackball",
NAVIGATION_WHEEL, "wheel");
private static final int NAVIGATIONHIDDEN_MASK = 0x0C;
private static final int NAVIGATIONHIDDEN_NO = 0x04;
private static final int NAVIGATIONHIDDEN_YES = 0x08;
private static final Map<Integer, String> NAVIGATIONHIDDEN_VALUES = ImmutableMap.of(
NAVIGATIONHIDDEN_NO, "navexposed",
NAVIGATIONHIDDEN_YES, "navhidden");
private static final int ORIENTATION_PORTRAIT = 0x01;
private static final int ORIENTATION_LANDSCAPE = 0x02;
private static final Map<Integer, String> ORIENTATION_VALUES = ImmutableMap.of(
ORIENTATION_PORTRAIT, "port",
ORIENTATION_LANDSCAPE, "land");
private static final int SCREENLAYOUT_LAYOUTDIR_MASK = 0xC0;
private static final int SCREENLAYOUT_LAYOUTDIR_LTR = 0x40;
private static final int SCREENLAYOUT_LAYOUTDIR_RTL = 0x80;
private static final Map<Integer, String> SCREENLAYOUT_LAYOUTDIR_VALUES = ImmutableMap.of(
SCREENLAYOUT_LAYOUTDIR_LTR, "ldltr",
SCREENLAYOUT_LAYOUTDIR_RTL, "ldrtl");
private static final int SCREENLAYOUT_LONG_MASK = 0x30;
private static final int SCREENLAYOUT_LONG_NO = 0x10;
private static final int SCREENLAYOUT_LONG_YES = 0x20;
private static final Map<Integer, String> SCREENLAYOUT_LONG_VALUES = ImmutableMap.of(
SCREENLAYOUT_LONG_NO, "notlong",
SCREENLAYOUT_LONG_YES, "long");
private static final int SCREENLAYOUT_ROUND_MASK = 0x03;
private static final int SCREENLAYOUT_ROUND_NO = 0x01;
private static final int SCREENLAYOUT_ROUND_YES = 0x02;
private static final Map<Integer, String> SCREENLAYOUT_ROUND_VALUES = ImmutableMap.of(
SCREENLAYOUT_ROUND_NO, "notround",
SCREENLAYOUT_ROUND_YES, "round");
private static final int SCREENLAYOUT_SIZE_MASK = 0x0F;
private static final int SCREENLAYOUT_SIZE_SMALL = 0x01;
private static final int SCREENLAYOUT_SIZE_NORMAL = 0x02;
private static final int SCREENLAYOUT_SIZE_LARGE = 0x03;
private static final int SCREENLAYOUT_SIZE_XLARGE = 0x04;
private static final Map<Integer, String> SCREENLAYOUT_SIZE_VALUES = ImmutableMap.of(
SCREENLAYOUT_SIZE_SMALL, "small",
SCREENLAYOUT_SIZE_NORMAL, "normal",
SCREENLAYOUT_SIZE_LARGE, "large",
SCREENLAYOUT_SIZE_XLARGE, "xlarge");
private static final int TOUCHSCREEN_NOTOUCH = 1;
private static final int TOUCHSCREEN_FINGER = 3;
private static final Map<Integer, String> TOUCHSCREEN_VALUES = ImmutableMap.of(
TOUCHSCREEN_NOTOUCH, "notouch",
TOUCHSCREEN_FINGER, "finger");
private static final int UI_MODE_NIGHT_MASK = 0x30;
private static final int UI_MODE_NIGHT_NO = 0x10;
private static final int UI_MODE_NIGHT_YES = 0x20;
private static final Map<Integer, String> UI_MODE_NIGHT_VALUES = ImmutableMap.of(
UI_MODE_NIGHT_NO, "notnight",
UI_MODE_NIGHT_YES, "night");
private static final int UI_MODE_TYPE_MASK = 0x0F;
private static final int UI_MODE_TYPE_DESK = 0x02;
private static final int UI_MODE_TYPE_CAR = 0x03;
private static final int UI_MODE_TYPE_TELEVISION = 0x04;
private static final int UI_MODE_TYPE_APPLIANCE = 0x05;
private static final int UI_MODE_TYPE_WATCH = 0x06;
private static final int UI_MODE_TYPE_VR_HEADSET = 0x07;
// start - miui
private static final int UI_MODE_TYPE_GODZILLAUI = 0x0b;
private static final int UI_MODE_TYPE_SMALLUI = 0x0c;
private static final int UI_MODE_TYPE_MEDIUMUI = 0x0d;
private static final int UI_MODE_TYPE_LARGEUI = 0x0e;
private static final int UI_MODE_TYPE_HUGEUI = 0x0f;
private static final Map<Integer, String> UI_MODE_TYPE_VALUES =
ImmutableMap.<Integer, String>builder()
.put(UI_MODE_TYPE_DESK, "desk")
.put(UI_MODE_TYPE_CAR, "car")
.put(UI_MODE_TYPE_TELEVISION, "television")
.put(UI_MODE_TYPE_APPLIANCE, "appliance")
.put(UI_MODE_TYPE_WATCH, "watch")
.put(UI_MODE_TYPE_VR_HEADSET, "vrheadset")
.put(UI_MODE_TYPE_GODZILLAUI, "godzillaui")
.put(UI_MODE_TYPE_SMALLUI, "smallui")
.put(UI_MODE_TYPE_MEDIUMUI, "mediumui")
.put(UI_MODE_TYPE_LARGEUI, "largeui")
.put(UI_MODE_TYPE_HUGEUI, "hugeui").build();
/**
* The minimum size in bytes that this configuration must be to contain screen config info.
*/
private static final int SCREEN_CONFIG_MIN_SIZE = 32;
/**
* The minimum size in bytes that this configuration must be to contain screen dp info.
*/
private static final int SCREEN_DP_MIN_SIZE = 36;
/**
* The minimum size in bytes that this configuration must be to contain locale info.
*/
private static final int LOCALE_MIN_SIZE = 48;
/**
* The minimum size in bytes that this config must be to contain the screenConfig extension.
*/
private static final int SCREEN_CONFIG_EXTENSION_MIN_SIZE = 52;
private final int size;
private final int mcc;
private final int mnc;
@@ -53,9 +195,60 @@ public class BinaryResourceConfiguration implements SerializableResource {
private final int screenHeightDp;
private final byte[] localeScript;
private final byte[] localeVariant;
// end - miui
private final int screenLayout2;
private final byte[] unknown;
private BinaryResourceConfiguration(int size,
int mcc,
int mnc,
byte[] language,
byte[] region,
int orientation,
int touchscreen,
int density,
int keyboard,
int navigation,
int inputFlags,
int screenWidth,
int screenHeight,
int sdkVersion,
int minorVersion,
int screenLayout,
int uiMode,
int smallestScreenWidthDp,
int screenWidthDp,
int screenHeightDp,
byte[] localeScript,
byte[] localeVariant,
int screenLayout2,
byte[] unknown) {
this.size = size;
this.mcc = mcc;
this.mnc = mnc;
this.language = language;
this.region = region;
this.orientation = orientation;
this.touchscreen = touchscreen;
this.density = density;
this.keyboard = keyboard;
this.navigation = navigation;
this.inputFlags = inputFlags;
this.screenWidth = screenWidth;
this.screenHeight = screenHeight;
this.sdkVersion = sdkVersion;
this.minorVersion = minorVersion;
this.screenLayout = screenLayout;
this.uiMode = uiMode;
this.smallestScreenWidthDp = smallestScreenWidthDp;
this.screenWidthDp = screenWidthDp;
this.screenHeightDp = screenHeightDp;
this.localeScript = localeScript;
this.localeVariant = localeVariant;
this.screenLayout2 = screenLayout2;
this.unknown = unknown;
}
static BinaryResourceConfiguration create(ByteBuffer buffer) {
int startPosition = buffer.position(); // The starting buffer position to calculate bytes read.
int size = buffer.getInt();
@@ -121,245 +314,6 @@ public class BinaryResourceConfiguration implements SerializableResource {
screenHeightDp, localeScript, localeVariant, screenLayout2, unknown);
}
private BinaryResourceConfiguration(int size,
int mcc,
int mnc,
byte[] language,
byte[] region,
int orientation,
int touchscreen,
int density,
int keyboard,
int navigation,
int inputFlags,
int screenWidth,
int screenHeight,
int sdkVersion,
int minorVersion,
int screenLayout,
int uiMode,
int smallestScreenWidthDp,
int screenWidthDp,
int screenHeightDp,
byte[] localeScript,
byte[] localeVariant,
int screenLayout2,
byte[] unknown) {
this.size = size;
this.mcc = mcc;
this.mnc = mnc;
this.language = language;
this.region = region;
this.orientation = orientation;
this.touchscreen = touchscreen;
this.density = density;
this.keyboard = keyboard;
this.navigation = navigation;
this.inputFlags = inputFlags;
this.screenWidth = screenWidth;
this.screenHeight = screenHeight;
this.sdkVersion = sdkVersion;
this.minorVersion = minorVersion;
this.screenLayout = screenLayout;
this.uiMode = uiMode;
this.smallestScreenWidthDp = smallestScreenWidthDp;
this.screenWidthDp = screenWidthDp;
this.screenHeightDp = screenHeightDp;
this.localeScript = localeScript;
this.localeVariant = localeVariant;
this.screenLayout2 = screenLayout2;
this.unknown = unknown;
}
/**
* The different types of configs that can be present in a {@link BinaryResourceConfiguration}.
*/
public enum Type {
MCC,
MNC,
LANGUAGE_STRING,
REGION_STRING,
SCREEN_LAYOUT_DIRECTION,
SMALLEST_SCREEN_WIDTH_DP,
SCREEN_WIDTH_DP,
SCREEN_HEIGHT_DP,
SCREEN_LAYOUT_SIZE,
SCREEN_LAYOUT_LONG,
SCREEN_LAYOUT_ROUND,
ORIENTATION,
UI_MODE_TYPE,
UI_MODE_NIGHT,
DENSITY_DPI,
TOUCHSCREEN,
KEYBOARD_HIDDEN,
KEYBOARD,
NAVIGATION_HIDDEN,
NAVIGATION,
SDK_VERSION
}
/**
* The below constants are from android.content.res.Configuration.
*/
private static final int DENSITY_DPI_UNDEFINED = 0;
private static final int DENSITY_DPI_LDPI = 120;
private static final int DENSITY_DPI_MDPI = 160;
private static final int DENSITY_DPI_TVDPI = 213;
private static final int DENSITY_DPI_HDPI = 240;
private static final int DENSITY_DPI_XHDPI = 320;
private static final int DENSITY_DPI_XXHDPI = 480;
private static final int DENSITY_DPI_XXXHDPI = 640;
private static final int DENSITY_DPI_ANY = 0xFFFE;
private static final int DENSITY_DPI_NONE = 0xFFFF;
private static final Map<Integer, String> DENSITY_DPI_VALUES =
ImmutableMap.<Integer, String>builder()
.put(DENSITY_DPI_UNDEFINED, "")
.put(DENSITY_DPI_LDPI, "ldpi")
.put(DENSITY_DPI_MDPI, "mdpi")
.put(DENSITY_DPI_TVDPI, "tvdpi")
.put(DENSITY_DPI_HDPI, "hdpi")
.put(DENSITY_DPI_XHDPI, "xhdpi")
.put(DENSITY_DPI_XXHDPI, "xxhdpi")
.put(DENSITY_DPI_XXXHDPI, "xxxhdpi")
.put(DENSITY_DPI_ANY, "anydpi")
.put(DENSITY_DPI_NONE, "nodpi")
.build();
private static final int KEYBOARD_NOKEYS = 1;
private static final int KEYBOARD_QWERTY = 2;
private static final int KEYBOARD_12KEY = 3;
private static final Map<Integer, String> KEYBOARD_VALUES = ImmutableMap.of(
KEYBOARD_NOKEYS, "nokeys",
KEYBOARD_QWERTY, "qwerty",
KEYBOARD_12KEY, "12key");
private static final int KEYBOARDHIDDEN_MASK = 0x03;
private static final int KEYBOARDHIDDEN_NO = 1;
private static final int KEYBOARDHIDDEN_YES = 2;
private static final int KEYBOARDHIDDEN_SOFT = 3;
private static final Map<Integer, String> KEYBOARDHIDDEN_VALUES = ImmutableMap.of(
KEYBOARDHIDDEN_NO, "keysexposed",
KEYBOARDHIDDEN_YES, "keyshidden",
KEYBOARDHIDDEN_SOFT, "keyssoft");
private static final int NAVIGATION_NONAV = 1;
private static final int NAVIGATION_DPAD = 2;
private static final int NAVIGATION_TRACKBALL = 3;
private static final int NAVIGATION_WHEEL = 4;
private static final Map<Integer, String> NAVIGATION_VALUES = ImmutableMap.of(
NAVIGATION_NONAV, "nonav",
NAVIGATION_DPAD, "dpad",
NAVIGATION_TRACKBALL, "trackball",
NAVIGATION_WHEEL, "wheel");
private static final int NAVIGATIONHIDDEN_MASK = 0x0C;
private static final int NAVIGATIONHIDDEN_NO = 0x04;
private static final int NAVIGATIONHIDDEN_YES = 0x08;
private static final Map<Integer, String> NAVIGATIONHIDDEN_VALUES = ImmutableMap.of(
NAVIGATIONHIDDEN_NO, "navexposed",
NAVIGATIONHIDDEN_YES, "navhidden");
private static final int ORIENTATION_PORTRAIT = 0x01;
private static final int ORIENTATION_LANDSCAPE = 0x02;
private static final Map<Integer, String> ORIENTATION_VALUES = ImmutableMap.of(
ORIENTATION_PORTRAIT, "port",
ORIENTATION_LANDSCAPE, "land");
private static final int SCREENLAYOUT_LAYOUTDIR_MASK = 0xC0;
private static final int SCREENLAYOUT_LAYOUTDIR_LTR = 0x40;
private static final int SCREENLAYOUT_LAYOUTDIR_RTL = 0x80;
private static final Map<Integer, String> SCREENLAYOUT_LAYOUTDIR_VALUES = ImmutableMap.of(
SCREENLAYOUT_LAYOUTDIR_LTR, "ldltr",
SCREENLAYOUT_LAYOUTDIR_RTL, "ldrtl");
private static final int SCREENLAYOUT_LONG_MASK = 0x30;
private static final int SCREENLAYOUT_LONG_NO = 0x10;
private static final int SCREENLAYOUT_LONG_YES = 0x20;
private static final Map<Integer, String> SCREENLAYOUT_LONG_VALUES = ImmutableMap.of(
SCREENLAYOUT_LONG_NO, "notlong",
SCREENLAYOUT_LONG_YES, "long");
private static final int SCREENLAYOUT_ROUND_MASK = 0x03;
private static final int SCREENLAYOUT_ROUND_NO = 0x01;
private static final int SCREENLAYOUT_ROUND_YES = 0x02;
private static final Map<Integer, String> SCREENLAYOUT_ROUND_VALUES = ImmutableMap.of(
SCREENLAYOUT_ROUND_NO, "notround",
SCREENLAYOUT_ROUND_YES, "round");
private static final int SCREENLAYOUT_SIZE_MASK = 0x0F;
private static final int SCREENLAYOUT_SIZE_SMALL = 0x01;
private static final int SCREENLAYOUT_SIZE_NORMAL = 0x02;
private static final int SCREENLAYOUT_SIZE_LARGE = 0x03;
private static final int SCREENLAYOUT_SIZE_XLARGE = 0x04;
private static final Map<Integer, String> SCREENLAYOUT_SIZE_VALUES = ImmutableMap.of(
SCREENLAYOUT_SIZE_SMALL, "small",
SCREENLAYOUT_SIZE_NORMAL, "normal",
SCREENLAYOUT_SIZE_LARGE, "large",
SCREENLAYOUT_SIZE_XLARGE, "xlarge");
private static final int TOUCHSCREEN_NOTOUCH = 1;
private static final int TOUCHSCREEN_FINGER = 3;
private static final Map<Integer, String> TOUCHSCREEN_VALUES = ImmutableMap.of(
TOUCHSCREEN_NOTOUCH, "notouch",
TOUCHSCREEN_FINGER, "finger");
private static final int UI_MODE_NIGHT_MASK = 0x30;
private static final int UI_MODE_NIGHT_NO = 0x10;
private static final int UI_MODE_NIGHT_YES = 0x20;
private static final Map<Integer, String> UI_MODE_NIGHT_VALUES = ImmutableMap.of(
UI_MODE_NIGHT_NO, "notnight",
UI_MODE_NIGHT_YES, "night");
private static final int UI_MODE_TYPE_MASK = 0x0F;
private static final int UI_MODE_TYPE_DESK = 0x02;
private static final int UI_MODE_TYPE_CAR = 0x03;
private static final int UI_MODE_TYPE_TELEVISION = 0x04;
private static final int UI_MODE_TYPE_APPLIANCE = 0x05;
private static final int UI_MODE_TYPE_WATCH = 0x06;
private static final int UI_MODE_TYPE_VR_HEADSET = 0x07;
// start - miui
private static final int UI_MODE_TYPE_GODZILLAUI = 0x0b;
private static final int UI_MODE_TYPE_SMALLUI = 0x0c;
private static final int UI_MODE_TYPE_MEDIUMUI = 0x0d;
private static final int UI_MODE_TYPE_LARGEUI = 0x0e;
private static final int UI_MODE_TYPE_HUGEUI = 0x0f;
// end - miui
private static final Map<Integer, String> UI_MODE_TYPE_VALUES =
ImmutableMap.<Integer, String>builder()
.put(UI_MODE_TYPE_DESK, "desk")
.put(UI_MODE_TYPE_CAR, "car")
.put(UI_MODE_TYPE_TELEVISION, "television")
.put(UI_MODE_TYPE_APPLIANCE, "appliance")
.put(UI_MODE_TYPE_WATCH, "watch")
.put(UI_MODE_TYPE_VR_HEADSET, "vrheadset")
.put(UI_MODE_TYPE_GODZILLAUI, "godzillaui")
.put(UI_MODE_TYPE_SMALLUI, "smallui")
.put(UI_MODE_TYPE_MEDIUMUI, "mediumui")
.put(UI_MODE_TYPE_LARGEUI, "largeui")
.put(UI_MODE_TYPE_HUGEUI, "hugeui").build();
/**
* The minimum size in bytes that this configuration must be to contain screen config info.
*/
private static final int SCREEN_CONFIG_MIN_SIZE = 32;
/**
* The minimum size in bytes that this configuration must be to contain screen dp info.
*/
private static final int SCREEN_DP_MIN_SIZE = 36;
/**
* The minimum size in bytes that this configuration must be to contain locale info.
*/
private static final int LOCALE_MIN_SIZE = 48;
/**
* The minimum size in bytes that this config must be to contain the screenConfig extension.
*/
private static final int SCREEN_CONFIG_EXTENSION_MIN_SIZE = 52;
/**
* The number of bytes that this resource configuration takes up.
*/
@@ -708,7 +662,7 @@ public class BinaryResourceConfiguration implements SerializableResource {
Map<Type, String> result = new LinkedHashMap<>(); // Preserve order for #toString().
result.put(Type.MCC, mcc() != 0 ? "mcc" + mcc() : "");
result.put(Type.MNC, mnc() != 0 ? "mnc" + mnc() : "");
result.put(Type.LANGUAGE_STRING, !languageString().isEmpty() ? "" + languageString() : "");
result.put(Type.LANGUAGE_STRING, !languageString().isEmpty() ? languageString() : "");
result.put(Type.REGION_STRING, !regionString().isEmpty() ? "r" + regionString() : "");
result.put(Type.SCREEN_LAYOUT_DIRECTION,
getOrDefault(SCREENLAYOUT_LAYOUTDIR_VALUES, screenLayoutDirection(), ""));
@@ -742,4 +696,31 @@ public class BinaryResourceConfiguration implements SerializableResource {
V value = map.get(key);
return value != null ? value : defaultValue;
}
/**
* The different types of configs that can be present in a {@link BinaryResourceConfiguration}.
*/
public enum Type {
MCC,
MNC,
LANGUAGE_STRING,
REGION_STRING,
SCREEN_LAYOUT_DIRECTION,
SMALLEST_SCREEN_WIDTH_DP,
SCREEN_WIDTH_DP,
SCREEN_HEIGHT_DP,
SCREEN_LAYOUT_SIZE,
SCREEN_LAYOUT_LONG,
SCREEN_LAYOUT_ROUND,
ORIENTATION,
UI_MODE_TYPE,
UI_MODE_NIGHT,
DENSITY_DPI,
TOUCHSCREEN,
KEYBOARD_HIDDEN,
KEYBOARD,
NAVIGATION_HIDDEN,
NAVIGATION,
SDK_VERSION
}
}
@@ -49,6 +49,12 @@ public class BinaryResourceIdentifier {
private final int typeId;
private final int entryId;
private BinaryResourceIdentifier(int packageId, int typeId, int entryId) {
this.packageId = packageId;
this.typeId = typeId;
this.entryId = entryId;
}
/**
* Returns a {@link BinaryResourceIdentifier} from a {@code resourceId} of the form 0xpptteeee.
*/
@@ -69,12 +75,6 @@ public class BinaryResourceIdentifier {
return new BinaryResourceIdentifier(packageId, typeId, entryId);
}
private BinaryResourceIdentifier(int packageId, int typeId, int entryId) {
this.packageId = packageId;
this.typeId = typeId;
this.entryId = entryId;
}
/**
* The (1-based) id of the {@link PackageChunk} containing this resource.
*/
@@ -31,24 +31,6 @@ import static java.nio.charset.StandardCharsets.UTF_8;
*/
public final class BinaryResourceString {
/**
* Type of {@link BinaryResourceString} to encode / decode.
*/
public enum Type {
UTF8(UTF_8),
UTF16(UTF_16LE);
private final Charset charset;
Type(Charset charset) {
this.charset = charset;
}
public Charset charset() {
return charset;
}
}
private BinaryResourceString() {
} // Private constructor
@@ -166,4 +148,22 @@ public final class BinaryResourceString {
}
return length;
}
/**
* Type of {@link BinaryResourceString} to encode / decode.
*/
public enum Type {
UTF8(UTF_8),
UTF16(UTF_16LE);
private final Charset charset;
Type(Charset charset) {
this.charset = charset;
}
public Charset charset() {
return charset;
}
}
}
@@ -31,6 +31,78 @@ import java.util.Objects;
*/
public class BinaryResourceValue implements SerializableResource {
/**
* The serialized size in bytes of a {@link BinaryResourceValue}.
*/
public static final int SIZE = 8;
public int size;
public Type type;
public int data;
public BinaryResourceValue(int size, Type type, int data) {
this.size = size;
this.type = type;
this.data = data;
}
public static BinaryResourceValue create(ByteBuffer buffer) {
int size = (buffer.getShort() & 0xFFFF);
buffer.get(); // Unused
Type type = Type.fromCode(buffer.get());
int data = buffer.getInt();
return new BinaryResourceValue(size, type, data);
}
/**
* The length in bytes of this value.
*/
public int size() {
return size;
}
/**
* The raw data type of this value.
*/
public Type type() {
return type;
}
/**
* The actual 4-byte value; interpretation of the value depends on {@code dataType}.
*/
public int data() {
return data;
}
@Override
public byte[] toByteArray() {
return toByteArray(false);
}
@Override
public byte[] toByteArray(boolean shrink) {
ByteBuffer buffer = ByteBuffer.allocate(SIZE).order(ByteOrder.LITTLE_ENDIAN);
buffer.putShort((short) size());
buffer.put((byte) 0); // Unused
buffer.put(type().code());
buffer.putInt(data());
return buffer.array();
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
BinaryResourceValue that = (BinaryResourceValue) o;
return size == that.size &&
data == that.data &&
type == that.type;
}
@Override
public int hashCode() {
return Objects.hash(size, type, data);
}
/**
* Resource type codes.
*/
@@ -100,8 +172,6 @@ public class BinaryResourceValue implements SerializableResource {
*/
INT_COLOR_RGB4(0x1f);
private final byte code;
private static final Map<Byte, Type> FROM_BYTE;
static {
@@ -112,90 +182,18 @@ public class BinaryResourceValue implements SerializableResource {
FROM_BYTE = builder.build();
}
private final byte code;
Type(int code) {
this.code = UnsignedBytes.checkedCast(code);
}
public byte code() {
return code;
}
public static Type fromCode(byte code) {
return Preconditions.checkNotNull(FROM_BYTE.get(code), "Unknown resource type: %s", code);
}
}
/**
* The serialized size in bytes of a {@link BinaryResourceValue}.
*/
public static final int SIZE = 8;
public int size;
public Type type;
public int data;
public static BinaryResourceValue create(ByteBuffer buffer) {
int size = (buffer.getShort() & 0xFFFF);
buffer.get(); // Unused
Type type = Type.fromCode(buffer.get());
int data = buffer.getInt();
return new BinaryResourceValue(size, type, data);
}
public BinaryResourceValue(int size, Type type, int data) {
this.size = size;
this.type = type;
this.data = data;
}
/**
* The length in bytes of this value.
*/
public int size() {
return size;
}
/**
* The raw data type of this value.
*/
public Type type() {
return type;
}
/**
* The actual 4-byte value; interpretation of the value depends on {@code dataType}.
*/
public int data() {
return data;
}
@Override
public byte[] toByteArray() {
return toByteArray(false);
}
@Override
public byte[] toByteArray(boolean shrink) {
ByteBuffer buffer = ByteBuffer.allocate(SIZE).order(ByteOrder.LITTLE_ENDIAN);
buffer.putShort((short) size());
buffer.put((byte) 0); // Unused
buffer.put(type().code());
buffer.putInt(data());
return buffer.array();
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
BinaryResourceValue that = (BinaryResourceValue) o;
return size == that.size &&
data == that.data &&
type == that.type;
}
@Override
public int hashCode() {
return Objects.hash(size, type, data);
public byte code() {
return code;
}
}
}
@@ -35,86 +35,36 @@ import java.util.Map;
*/
public abstract class Chunk implements SerializableResource {
/**
* Types of chunks that can exist.
*/
public enum Type {
NULL(0x0000),
STRING_POOL(0x0001),
TABLE(0x0002),
XML(0x0003),
XML_START_NAMESPACE(0x0100),
XML_END_NAMESPACE(0x0101),
XML_START_ELEMENT(0x0102),
XML_END_ELEMENT(0x0103),
XML_CDATA(0x0104),
XML_RESOURCE_MAP(0x0180),
TABLE_PACKAGE(0x0200),
TABLE_TYPE(0x0201),
TABLE_TYPE_SPEC(0x0202),
TABLE_LIBRARY(0x0203);
private final short code;
private static final Map<Short, Type> FROM_SHORT;
static {
Builder<Short, Type> builder = ImmutableMap.builder();
for (Type type : values()) {
builder.put(type.code(), type);
}
FROM_SHORT = builder.build();
}
Type(int code) {
this.code = Shorts.checkedCast(code);
}
public short code() {
return code;
}
public static Type fromCode(short code) {
return Preconditions.checkNotNull(FROM_SHORT.get(code), "Unknown chunk type: %s", code);
}
}
/**
* The byte boundary to pad chunks on.
*/
public static final int PAD_BOUNDARY = 4;
/**
* The number of bytes in every chunk that describes chunk type, header size, and chunk size.
*/
public static final int METADATA_SIZE = 8;
/**
* The offset in bytes, from the start of the chunk, where the chunk size can be found.
*/
private static final int CHUNK_SIZE_OFFSET = 4;
/**
* Size of the chunk header in bytes.
*/
protected final int headerSize;
/**
* headerSize + dataSize. The total size of this chunk.
*/
protected final int chunkSize;
/**
* Offset of this chunk from the start of the file.
*/
protected final int offset;
/**
* The parent to this chunk, if any.
*/
@Nullable
private final Chunk parent;
/**
* Size of the chunk header in bytes.
*/
protected final int headerSize;
/**
* headerSize + dataSize. The total size of this chunk.
*/
protected final int chunkSize;
/**
* Offset of this chunk from the start of the file.
*/
protected final int offset;
protected Chunk(ByteBuffer buffer, @Nullable Chunk parent) {
this.parent = parent;
offset = buffer.position() - 2;
@@ -122,6 +72,74 @@ public abstract class Chunk implements SerializableResource {
chunkSize = buffer.getInt();
}
/**
* Creates a new chunk whose contents start at {@code buffer}'s current position.
*
* @param buffer A buffer positioned at the start of a chunk.
* @return new chunk
*/
public static Chunk newInstance(ByteBuffer buffer) {
return newInstance(buffer, null);
}
/**
* Creates a new chunk whose contents start at {@code buffer}'s current position.
*
* @param buffer A buffer positioned at the start of a chunk.
* @param parent The parent to this chunk (or null if there's no parent).
* @return new chunk
*/
public static Chunk newInstance(ByteBuffer buffer, @Nullable Chunk parent) {
Chunk result;
Type type = Type.fromCode(buffer.getShort());
switch (type) {
case STRING_POOL:
result = new StringPoolChunk(buffer, parent);
break;
case TABLE:
result = new ResourceTableChunk(buffer, parent);
break;
case XML:
result = new XmlChunk(buffer, parent);
break;
case XML_START_NAMESPACE:
result = new XmlNamespaceStartChunk(buffer, parent);
break;
case XML_END_NAMESPACE:
result = new XmlNamespaceEndChunk(buffer, parent);
break;
case XML_START_ELEMENT:
result = new XmlStartElementChunk(buffer, parent);
break;
case XML_END_ELEMENT:
result = new XmlEndElementChunk(buffer, parent);
break;
case XML_CDATA:
result = new XmlCdataChunk(buffer, parent);
break;
case XML_RESOURCE_MAP:
result = new XmlResourceMapChunk(buffer, parent);
break;
case TABLE_PACKAGE:
result = new PackageChunk(buffer, parent);
break;
case TABLE_TYPE:
result = new TypeChunk(buffer, parent);
break;
case TABLE_TYPE_SPEC:
result = new TypeSpecChunk(buffer, parent);
break;
case TABLE_LIBRARY:
result = new LibraryChunk(buffer, parent);
break;
default:
result = new UnknownChunk(buffer, parent);
}
result.init(buffer);
result.seekToEndOfChunk(buffer);
return result;
}
/**
* Finishes initialization of a chunk. This should be called immediately after the constructor.
* This is separate from the constructor so that the header of a chunk can be fully initialized
@@ -256,70 +274,46 @@ public abstract class Chunk implements SerializableResource {
}
/**
* Creates a new chunk whose contents start at {@code buffer}'s current position.
*
* @param buffer A buffer positioned at the start of a chunk.
* @return new chunk
* Types of chunks that can exist.
*/
public static Chunk newInstance(ByteBuffer buffer) {
return newInstance(buffer, null);
}
public enum Type {
NULL(0x0000),
STRING_POOL(0x0001),
TABLE(0x0002),
XML(0x0003),
XML_START_NAMESPACE(0x0100),
XML_END_NAMESPACE(0x0101),
XML_START_ELEMENT(0x0102),
XML_END_ELEMENT(0x0103),
XML_CDATA(0x0104),
XML_RESOURCE_MAP(0x0180),
TABLE_PACKAGE(0x0200),
TABLE_TYPE(0x0201),
TABLE_TYPE_SPEC(0x0202),
TABLE_LIBRARY(0x0203);
/**
* Creates a new chunk whose contents start at {@code buffer}'s current position.
*
* @param buffer A buffer positioned at the start of a chunk.
* @param parent The parent to this chunk (or null if there's no parent).
* @return new chunk
*/
public static Chunk newInstance(ByteBuffer buffer, @Nullable Chunk parent) {
Chunk result;
Type type = Type.fromCode(buffer.getShort());
switch (type) {
case STRING_POOL:
result = new StringPoolChunk(buffer, parent);
break;
case TABLE:
result = new ResourceTableChunk(buffer, parent);
break;
case XML:
result = new XmlChunk(buffer, parent);
break;
case XML_START_NAMESPACE:
result = new XmlNamespaceStartChunk(buffer, parent);
break;
case XML_END_NAMESPACE:
result = new XmlNamespaceEndChunk(buffer, parent);
break;
case XML_START_ELEMENT:
result = new XmlStartElementChunk(buffer, parent);
break;
case XML_END_ELEMENT:
result = new XmlEndElementChunk(buffer, parent);
break;
case XML_CDATA:
result = new XmlCdataChunk(buffer, parent);
break;
case XML_RESOURCE_MAP:
result = new XmlResourceMapChunk(buffer, parent);
break;
case TABLE_PACKAGE:
result = new PackageChunk(buffer, parent);
break;
case TABLE_TYPE:
result = new TypeChunk(buffer, parent);
break;
case TABLE_TYPE_SPEC:
result = new TypeSpecChunk(buffer, parent);
break;
case TABLE_LIBRARY:
result = new LibraryChunk(buffer, parent);
break;
default:
result = new UnknownChunk(buffer, parent);
private static final Map<Short, Type> FROM_SHORT;
static {
Builder<Short, Type> builder = ImmutableMap.builder();
for (Type type : values()) {
builder.put(type.code(), type);
}
FROM_SHORT = builder.build();
}
private final short code;
Type(int code) {
this.code = Shorts.checkedCast(code);
}
public static Type fromCode(short code) {
return Preconditions.checkNotNull(FROM_SHORT.get(code), "Unknown chunk type: %s", code);
}
public short code() {
return code;
}
result.init(buffer);
result.seekToEndOfChunk(buffer);
return result;
}
}
@@ -43,7 +43,7 @@ public final class LibraryChunk extends Chunk {
*/
private final List<Entry> entries = new ArrayList<>();
protected LibraryChunk(ByteBuffer buffer, @Nullable Chunk parent) {
LibraryChunk(ByteBuffer buffer, @Nullable Chunk parent) {
super(buffer, parent);
entryCount = buffer.getInt();
}
@@ -98,17 +98,17 @@ public final class LibraryChunk extends Chunk {
private final int packageId;
private final String packageName;
private Entry(int packageId, String packageName) {
this.packageId = packageId;
this.packageName = packageName;
}
static Entry create(ByteBuffer buffer, int offset) {
int packageId = buffer.getInt(offset);
String packageName = PackageUtils.readPackageName(buffer, offset + 4);
return new Entry(packageId, packageName);
}
private Entry(int packageId, String packageName) {
this.packageId = packageId;
this.packageName = packageName;
}
/**
* The id assigned to the shared library at build time.
*/
@@ -43,58 +43,48 @@ public final class PackageChunk extends ChunkWithChunks {
* Offset in bytes, from the start of the chunk, where {@code keyStringsOffset} can be found.
*/
private static final int KEY_OFFSET_OFFSET = 276;
/**
* The package id if this is a base package, or 0 if not a base package.
*/
private int id;
/**
* The name of the package.
*/
private String packageName;
/**
* The offset (from {@code offset}) in the original buffer where type strings start.
*/
private final int typeStringsOffset;
/**
* The index into the type string pool of the last public type.
*/
private final int lastPublicType;
/**
* An offset to the string pool that contains the key strings for this package.
*/
private final int keyStringsOffset;
/**
* The index into the key string pool of the last public key.
*/
private final int lastPublicKey;
/**
* An offset to the type ID(s). This is undocumented in the original code.
*/
private final int typeIdOffset;
/**
* Contains a mapping of a type index to its {@link TypeSpecChunk}.
*/
private final Map<Integer, TypeSpecChunk> typeSpecs = new HashMap<>();
/**
* Contains a mapping of a type index to all of the {@link TypeChunk} with that index.
*/
private final Multimap<Integer, TypeChunk> types = ArrayListMultimap.create();
/**
* The package id if this is a base package, or 0 if not a base package.
*/
private int id;
/**
* The name of the package.
*/
private String packageName;
/**
* May contain a library chunk for mapping dynamic references to resolved references.
*/
private Optional<LibraryChunk> libraryChunk = Optional.empty();
protected PackageChunk(ByteBuffer buffer, @Nullable Chunk parent) {
PackageChunk(ByteBuffer buffer, @Nullable Chunk parent) {
super(buffer, parent);
id = buffer.getInt();
packageName = PackageUtils.readPackageName(buffer, buffer.position());
@@ -36,17 +36,16 @@ import java.util.Map;
*/
public final class ResourceTableChunk extends ChunkWithChunks {
/**
* The packages contained in this resource table.
*/
private final Map<String, PackageChunk> packages = new HashMap<>();
/**
* A string pool containing all string resource values in the entire resource table.
*/
private StringPoolChunk stringPool;
/**
* The packages contained in this resource table.
*/
private final Map<String, PackageChunk> packages = new HashMap<>();
protected ResourceTableChunk(ByteBuffer buffer, @Nullable Chunk parent) {
ResourceTableChunk(ByteBuffer buffer, @Nullable Chunk parent) {
super(buffer, parent);
// packageCount. We ignore this, because we already know how many chunks we have.
Preconditions.checkState(buffer.getInt() >= 1, "ResourceTableChunk package count was < 1.");
@@ -89,7 +89,7 @@ public final class StringPoolChunk extends Chunk {
*/
private boolean isOriginalDeduped = false;
protected StringPoolChunk(ByteBuffer buffer, @Nullable Chunk parent) {
StringPoolChunk(ByteBuffer buffer, @Nullable Chunk parent) {
super(buffer, parent);
stringCount = buffer.getInt();
styleCount = buffer.getInt();
@@ -310,6 +310,10 @@ public final class StringPoolChunk extends Chunk {
static final int RES_STRING_POOL_SPAN_END = 0xFFFFFFFF;
private final List<StringPoolSpan> spans;
private StringPoolStyle(List<StringPoolSpan> spans) {
this.spans = spans;
}
static StringPoolStyle create(ByteBuffer buffer, int offset, StringPoolChunk parent) {
Builder<StringPoolSpan> spans = ImmutableList.builder();
int nameIndex = buffer.getInt(offset);
@@ -321,10 +325,6 @@ public final class StringPoolChunk extends Chunk {
return new StringPoolStyle(spans.build());
}
private StringPoolStyle(List<StringPoolSpan> spans) {
this.spans = spans;
}
@Override
public byte[] toByteArray() throws IOException {
return toByteArray(false);
@@ -384,13 +384,6 @@ public final class StringPoolChunk extends Chunk {
private final int stop;
private final StringPoolChunk parent;
static StringPoolSpan create(ByteBuffer buffer, int offset, StringPoolChunk parent) {
int nameIndex = buffer.getInt(offset);
int start = buffer.getInt(offset + 4);
int stop = buffer.getInt(offset + 8);
return new StringPoolSpan(nameIndex, start, stop, parent);
}
private StringPoolSpan(int nameIndex, int start, int stop, StringPoolChunk parent) {
this.nameIndex = nameIndex;
this.start = start;
@@ -398,6 +391,13 @@ public final class StringPoolChunk extends Chunk {
this.parent = parent;
}
static StringPoolSpan create(ByteBuffer buffer, int offset, StringPoolChunk parent) {
int nameIndex = buffer.getInt(offset);
int start = buffer.getInt(offset + 4);
int stop = buffer.getInt(offset + 8);
return new StringPoolSpan(nameIndex, start, stop, parent);
}
@Override
public final byte[] toByteArray() {
return toByteArray(false);
@@ -52,18 +52,16 @@ public final class TypeChunk extends Chunk {
* The offset (from {@code offset}) in the original buffer where {@code entries} start.
*/
private final int entriesStart;
/**
* A sparse list of resource entries defined by this chunk.
*/
private final Map<Integer, Entry> entries = new TreeMap<>();
/**
* The resource configuration that these resource entries correspond to.
*/
private BinaryResourceConfiguration configuration;
/**
* A sparse list of resource entries defined by this chunk.
*/
private final Map<Integer, Entry> entries = new TreeMap<>();
protected TypeChunk(ByteBuffer buffer, @Nullable Chunk parent) {
TypeChunk(ByteBuffer buffer, @Nullable Chunk parent) {
super(buffer, parent);
id = UnsignedBytes.toInt(buffer.get());
buffer.position(buffer.position() + 3); // Skip 3 bytes for packing
@@ -176,13 +174,13 @@ public final class TypeChunk extends Chunk {
}
}
protected String getString(int index) {
private String getString(int index) {
ResourceTableChunk resourceTable = getResourceTableChunk();
Preconditions.checkNotNull(resourceTable, "%s has no resource table.", getClass());
return resourceTable.getStringPool().getString(index);
}
protected String getKeyName(int index) {
private String getKeyName(int index) {
PackageChunk packageChunk = getPackageChunk();
Preconditions.checkNotNull(packageChunk, "%s has no parent package.", getClass());
StringPoolChunk keyPool = packageChunk.getKeyStringPool();
@@ -190,7 +188,7 @@ public final class TypeChunk extends Chunk {
return keyPool.getString(index);
}
protected void updateKey(int index, String value) {
private void updateKey(int index, String value) {
PackageChunk packageChunk = getPackageChunk();
Preconditions.checkNotNull(packageChunk, "%s has no parent package.", getClass());
StringPoolChunk keyPool = packageChunk.getKeyStringPool();
@@ -293,10 +291,10 @@ public final class TypeChunk extends Chunk {
private final int headerSize;
private final int flags;
private final int keyIndex;
private BinaryResourceValue value;
private Map<Integer, BinaryResourceValue> values;
private final int parentEntry;
private final TypeChunk parent;
private BinaryResourceValue value;
private final Map<Integer, BinaryResourceValue> values;
private Entry(int headerSize,
int flags,
@@ -314,6 +312,52 @@ public final class TypeChunk extends Chunk {
this.parent = parent;
}
/**
* Creates a new {@link Entry} whose contents start at the 0-based position in
* {@code buffer} given by a 4-byte value read from {@code buffer} and then added to
* {@code baseOffset}. If the value read from {@code buffer} is equal to {@link #NO_ENTRY}, then
* null is returned as there is no resource at that position.
*
* <p>Otherwise, this position is parsed and returned as an {@link Entry}.
*
* @param buffer A buffer positioned at an offset to an {@link Entry}.
* @param baseOffset Offset that must be added to the value at {@code buffer}'s position.
* @param parent The {@link TypeChunk} that this resource entry belongs to.
* @return New {@link Entry} or null if there is no resource at this location.
*/
@Nullable
public static Entry create(ByteBuffer buffer, int baseOffset, TypeChunk parent) {
int offset = buffer.getInt();
if (offset == NO_ENTRY) {
return null;
}
int position = buffer.position();
buffer.position(baseOffset + offset); // Set buffer position to resource entry start
Entry result = newInstance(buffer, parent);
buffer.position(position); // Restore buffer position
return result;
}
@Nullable
private static Entry newInstance(ByteBuffer buffer, TypeChunk parent) {
int headerSize = buffer.getShort() & 0xFFFF;
int flags = buffer.getShort() & 0xFFFF;
int keyIndex = buffer.getInt();
BinaryResourceValue value = null;
Map<Integer, BinaryResourceValue> values = new LinkedHashMap<>();
int parentEntry = 0;
if ((flags & FLAG_COMPLEX) != 0) {
parentEntry = buffer.getInt();
int valueCount = buffer.getInt();
for (int i = 0; i < valueCount; ++i) {
values.put(buffer.getInt(), BinaryResourceValue.create(buffer));
}
} else {
value = BinaryResourceValue.create(buffer);
}
return new Entry(headerSize, flags, keyIndex, value, values, parentEntry, parent);
}
/**
* Number of bytes in the header of the {@link Entry}.
*/
@@ -422,52 +466,6 @@ public final class TypeChunk extends Chunk {
return (flags() & FLAG_COMPLEX) != 0;
}
/**
* Creates a new {@link Entry} whose contents start at the 0-based position in
* {@code buffer} given by a 4-byte value read from {@code buffer} and then added to
* {@code baseOffset}. If the value read from {@code buffer} is equal to {@link #NO_ENTRY}, then
* null is returned as there is no resource at that position.
*
* <p>Otherwise, this position is parsed and returned as an {@link Entry}.
*
* @param buffer A buffer positioned at an offset to an {@link Entry}.
* @param baseOffset Offset that must be added to the value at {@code buffer}'s position.
* @param parent The {@link TypeChunk} that this resource entry belongs to.
* @return New {@link Entry} or null if there is no resource at this location.
*/
@Nullable
public static Entry create(ByteBuffer buffer, int baseOffset, TypeChunk parent) {
int offset = buffer.getInt();
if (offset == NO_ENTRY) {
return null;
}
int position = buffer.position();
buffer.position(baseOffset + offset); // Set buffer position to resource entry start
Entry result = newInstance(buffer, parent);
buffer.position(position); // Restore buffer position
return result;
}
@Nullable
private static Entry newInstance(ByteBuffer buffer, TypeChunk parent) {
int headerSize = buffer.getShort() & 0xFFFF;
int flags = buffer.getShort() & 0xFFFF;
int keyIndex = buffer.getInt();
BinaryResourceValue value = null;
Map<Integer, BinaryResourceValue> values = new LinkedHashMap<>();
int parentEntry = 0;
if ((flags & FLAG_COMPLEX) != 0) {
parentEntry = buffer.getInt();
int valueCount = buffer.getInt();
for (int i = 0; i < valueCount; ++i) {
values.put(buffer.getInt(), BinaryResourceValue.create(buffer));
}
} else {
value = BinaryResourceValue.create(buffer);
}
return new Entry(headerSize, flags, keyIndex, value, values, parentEntry, parent);
}
@Override
public final byte[] toByteArray() {
return toByteArray(false);
@@ -39,7 +39,7 @@ public final class TypeSpecChunk extends Chunk {
*/
private final int[] resources;
protected TypeSpecChunk(ByteBuffer buffer, @Nullable Chunk parent) {
TypeSpecChunk(ByteBuffer buffer, @Nullable Chunk parent) {
super(buffer, parent);
id = UnsignedBytes.toInt(buffer.get());
buffer.position(buffer.position() + 3); // Skip 3 bytes for packing
@@ -34,7 +34,7 @@ public final class UnknownChunk extends Chunk {
private final byte[] payload;
protected UnknownChunk(ByteBuffer buffer, @Nullable Chunk parent) {
UnknownChunk(ByteBuffer buffer, @Nullable Chunk parent) {
super(buffer, parent);
type = Type.fromCode(buffer.getShort(offset));
@@ -36,6 +36,18 @@ public class XmlAttribute implements SerializableResource {
private final BinaryResourceValue typedValue;
private final XmlNodeChunk parent;
private XmlAttribute(int namespaceIndex,
int nameIndex,
int rawValueIndex,
BinaryResourceValue typedValue,
XmlNodeChunk parent) {
this.namespaceIndex = namespaceIndex;
this.nameIndex = nameIndex;
this.rawValueIndex = rawValueIndex;
this.typedValue = typedValue;
this.parent = parent;
}
/**
* Creates a new {@link XmlAttribute} based on the bytes at the current {@code buffer} position.
*
@@ -50,18 +62,6 @@ public class XmlAttribute implements SerializableResource {
return new XmlAttribute(namespace, name, rawValue, typedValue, parent);
}
private XmlAttribute(int namespaceIndex,
int nameIndex,
int rawValueIndex,
BinaryResourceValue typedValue,
XmlNodeChunk parent) {
this.namespaceIndex = namespaceIndex;
this.nameIndex = nameIndex;
this.rawValueIndex = rawValueIndex;
this.typedValue = typedValue;
this.parent = parent;
}
/**
* A string reference to the namespace URI, or -1 if not present.
*/
@@ -37,7 +37,7 @@ public final class XmlCdataChunk extends XmlNodeChunk {
*/
private final BinaryResourceValue binaryResourceValue;
protected XmlCdataChunk(ByteBuffer buffer, @Nullable Chunk parent) {
XmlCdataChunk(ByteBuffer buffer, @Nullable Chunk parent) {
super(buffer, parent);
rawValue = buffer.getInt();
binaryResourceValue = BinaryResourceValue.create(buffer);
@@ -28,7 +28,7 @@ import java.nio.ByteBuffer;
*/
public final class XmlChunk extends ChunkWithChunks {
protected XmlChunk(ByteBuffer buffer, @Nullable Chunk parent) {
XmlChunk(ByteBuffer buffer, @Nullable Chunk parent) {
super(buffer, parent);
}
@@ -37,7 +37,7 @@ public final class XmlEndElementChunk extends XmlNodeChunk {
*/
private final int name;
protected XmlEndElementChunk(ByteBuffer buffer, @Nullable Chunk parent) {
XmlEndElementChunk(ByteBuffer buffer, @Nullable Chunk parent) {
super(buffer, parent);
namespace = buffer.getInt();
name = buffer.getInt();
@@ -25,7 +25,7 @@ import java.nio.ByteBuffer;
*/
public final class XmlNamespaceEndChunk extends XmlNamespaceChunk {
protected XmlNamespaceEndChunk(ByteBuffer buffer, @Nullable Chunk parent) {
XmlNamespaceEndChunk(ByteBuffer buffer, @Nullable Chunk parent) {
super(buffer, parent);
}
@@ -25,7 +25,7 @@ import java.nio.ByteBuffer;
*/
public final class XmlNamespaceStartChunk extends XmlNamespaceChunk {
protected XmlNamespaceStartChunk(ByteBuffer buffer, @Nullable Chunk parent) {
XmlNamespaceStartChunk(ByteBuffer buffer, @Nullable Chunk parent) {
super(buffer, parent);
}
@@ -71,7 +71,7 @@ public final class XmlStartElementChunk extends XmlNodeChunk {
*/
private final List<XmlAttribute> attributes = new ArrayList<>();
protected XmlStartElementChunk(ByteBuffer buffer, @Nullable Chunk parent) {
XmlStartElementChunk(ByteBuffer buffer, @Nullable Chunk parent) {
super(buffer, parent);
namespace = buffer.getInt();
name = buffer.getInt();
@@ -7,16 +7,6 @@ import org.json.JSONException;
import org.json.JSONObject;
public class GiftGetByStickerId extends ApiRequest<GiftGetByStickerId.a> {
public static class a {
public final int a;
public final CatalogedGift b;
public a(int i, CatalogedGift catalogedGift) {
this.a = i;
this.b = catalogedGift;
}
}
public GiftGetByStickerId(Context context, int i) {
super("execute.getGiftByStickerId");
b("sticker_id", i);
@@ -30,4 +20,14 @@ public class GiftGetByStickerId extends ApiRequest<GiftGetByStickerId.a> {
return new a(jSONObject2.optInt("balance"),
new CatalogedGift(jSONObject2.getJSONObject("gift")));
}
public static class a {
public final int a;
public final CatalogedGift b;
public a(int i, CatalogedGift catalogedGift) {
this.a = i;
this.b = catalogedGift;
}
}
}
@@ -27,6 +27,15 @@ public class RecoloredDrawable extends Drawable implements Drawable.Callback {
onStateChange(new int[0]);
}
public RecoloredDrawable(Drawable drawable, int i) {
this(drawable, new ColorStateList(new int[][]{new int[0]}, new int[]{i}));
}
public RecoloredDrawable() {
this.c = 255;
this.d = 255;
}
public void a(int i) {
a(new ColorStateList(new int[][]{new int[0]}, new int[]{i}));
}
@@ -120,13 +129,4 @@ public class RecoloredDrawable extends Drawable implements Drawable.Callback {
public Drawable a() {
return this.drawable;
}
public RecoloredDrawable(Drawable drawable, int i) {
this(drawable, new ColorStateList(new int[][]{new int[0]}, new int[]{i}));
}
public RecoloredDrawable() {
this.c = 255;
this.d = 255;
}
}
@@ -21,6 +21,13 @@ public final class VerifyInfoHelper {
public static final VerifyInfoHelper h;
public static int devIcon = R.drawable.ic_favorite_16;
static {
h = new VerifyInfoHelper();
}
private VerifyInfoHelper() {
}
public static Integer enumSwitchMapping(VerifyInfoHelper.ColorTheme color) {
return switch (color) {
case normal -> 1;
@@ -30,18 +37,47 @@ public final class VerifyInfoHelper {
};
}
public enum ColorTheme {
white,
normal,
light,
ultraLight
public static Drawable b(VerifyInfoHelper verifyInfoHelper, boolean z, boolean z2, boolean dev, Context context, ColorTheme colorTheme, int i, Object obj) {
if ((i & 8) != 0) {
colorTheme = ColorTheme.normal;
}
return verifyInfoHelper.b(z, z2, dev, context, colorTheme);
}
static {
h = new VerifyInfoHelper();
public static Drawable b(VerifyInfoHelper verifyInfoHelper, VerifyInfo verifyInfo, Context context, ColorTheme colorTheme, int i, Object obj) {
return b(verifyInfoHelper, verifyInfo.u1(), verifyInfo.t1(), verifyInfo.dev(), context, colorTheme, i, obj);
}
private VerifyInfoHelper() {
public static Drawable b(VerifyInfoHelper verifyInfoHelper, boolean z, boolean z2, Context context, ColorTheme colorTheme, int i, Object obj) {
return b(verifyInfoHelper, z, z2, false, context, colorTheme, i, obj);
}
public static Drawable a(VerifyInfoHelper verifyInfoHelper, VerifyInfo verifyInfo, Context context, ColorTheme colorTheme, int i, Object obj) {
if ((i & 4) != 0) {
colorTheme = ColorTheme.normal;
}
return verifyInfoHelper.b(verifyInfo, context, colorTheme);
}
public static Drawable a(VerifyInfoHelper verifyInfoHelper, boolean z, boolean z2, boolean dev, Context context, ColorTheme colorTheme, int i, Object obj) {
if ((i & 8) != 0) {
colorTheme = ColorTheme.normal;
}
return verifyInfoHelper.a(z, z2, dev, context, colorTheme);
}
public static Drawable a(VerifyInfoHelper verifyInfoHelper, boolean z, boolean z2, Context context, ColorTheme colorTheme, int i, Object obj) {
return a(verifyInfoHelper, z, z2, false, context, colorTheme, i, obj);
}
public static void a(VerifyInfoHelper verifyInfoHelper, TextView textView, VerifyInfo verifyInfo, boolean z, ColorTheme colorTheme, int i, Object obj) {
if ((i & 4) != 0) {
z = false;
}
if ((i & 8) != 0) {
colorTheme = ColorTheme.normal;
}
verifyInfoHelper.a(textView, verifyInfo, z, colorTheme);
}
private int a() {
@@ -89,7 +125,6 @@ public final class VerifyInfoHelper {
return b(this, z, z2, false, context, null, 8, null);
}
public int b(ColorTheme colorTheme) {
return a(colorTheme);
}
@@ -104,7 +139,6 @@ public final class VerifyInfoHelper {
};
}
public Drawable b(Context context, VerifyInfo verifyInfo) {
if (verifyInfo.dev()) {
return new RecoloredDrawable(ContextCompat.getDrawable(context, devIcon), c(ColorTheme.normal));
@@ -123,21 +157,6 @@ public final class VerifyInfoHelper {
return b(verifyInfo.u1(), verifyInfo.t1(), verifyInfo.dev(), context, colorTheme);
}
public static Drawable b(VerifyInfoHelper verifyInfoHelper, boolean z, boolean z2, boolean dev, Context context, ColorTheme colorTheme, int i, Object obj) {
if ((i & 8) != 0) {
colorTheme = ColorTheme.normal;
}
return verifyInfoHelper.b(z, z2, dev, context, colorTheme);
}
public static Drawable b(VerifyInfoHelper verifyInfoHelper, VerifyInfo verifyInfo, Context context, ColorTheme colorTheme, int i, Object obj) {
return b(verifyInfoHelper, verifyInfo.u1(), verifyInfo.t1(), verifyInfo.dev(), context, colorTheme, i, obj);
}
public static Drawable b(VerifyInfoHelper verifyInfoHelper, boolean z, boolean z2, Context context, ColorTheme colorTheme, int i, Object obj) {
return b(verifyInfoHelper, z, z2, false, context, colorTheme, i, obj);
}
public Drawable a(Context context, VerifyInfo verifyInfo) {
if (verifyInfo.dev()) {
return new RecoloredDrawable(ContextCompat.getDrawable(context, devIcon), c(ColorTheme.normal));
@@ -181,28 +200,10 @@ public final class VerifyInfoHelper {
return new RecoloredDrawable(ContextCompat.getDrawable(context, i), c2);
}
public static Drawable a(VerifyInfoHelper verifyInfoHelper, VerifyInfo verifyInfo, Context context, ColorTheme colorTheme, int i, Object obj) {
if ((i & 4) != 0) {
colorTheme = ColorTheme.normal;
}
return verifyInfoHelper.b(verifyInfo, context, colorTheme);
}
public Drawable a(VerifyInfo verifyInfo, Context context, ColorTheme colorTheme) {
return a(verifyInfo.u1(), verifyInfo.t1(), verifyInfo.dev(), context, colorTheme);
}
public static Drawable a(VerifyInfoHelper verifyInfoHelper, boolean z, boolean z2, boolean dev, Context context, ColorTheme colorTheme, int i, Object obj) {
if ((i & 8) != 0) {
colorTheme = ColorTheme.normal;
}
return verifyInfoHelper.a(z, z2, dev, context, colorTheme);
}
public static Drawable a(VerifyInfoHelper verifyInfoHelper, boolean z, boolean z2, Context context, ColorTheme colorTheme, int i, Object obj) {
return a(verifyInfoHelper, z, z2, false, context, colorTheme, i, obj);
}
public Drawable a(boolean z, boolean z2, Context context, ColorTheme colorTheme) {
return a(z, z2, false, context, colorTheme);
}
@@ -230,16 +231,6 @@ public final class VerifyInfoHelper {
return new RecoloredDrawable(ContextCompat.getDrawable(context, i), c2);
}
public static void a(VerifyInfoHelper verifyInfoHelper, TextView textView, VerifyInfo verifyInfo, boolean z, ColorTheme colorTheme, int i, Object obj) {
if ((i & 4) != 0) {
z = false;
}
if ((i & 8) != 0) {
colorTheme = ColorTheme.normal;
}
verifyInfoHelper.a(textView, verifyInfo, z, colorTheme);
}
public void a(TextView textView, VerifyInfo verifyInfo, boolean z, ColorTheme colorTheme) {
Drawable drawable;
Context context = textView.getContext();
@@ -267,4 +258,11 @@ public final class VerifyInfoHelper {
}
ViewExtKt.p(imageView);
}
public enum ColorTheme {
white,
normal,
light,
ultraLight
}
}
@@ -31,30 +31,6 @@ public final class DialogGetMentionSuggestionCmd extends BaseImEngineCmd<Suggest
private final boolean e;
private final Object f;
public static final class a<T> implements Comparator<Member> {
List a;
a(List list) {
this.a = list;
}
@Override // java.util.Comparator
/* renamed from: a */
public int compare(Member member, Member member2) {
int indexOf = this.a.indexOf(member);
int indexOf2 = this.a.indexOf(member2);
int i = indexOf;
if (indexOf < 0) {
i = Integer.MAX_VALUE;
}
int i2 = indexOf2;
if (indexOf2 < 0) {
i2 = Integer.MAX_VALUE;
}
return Intrinsics.a(i, i2);
}
}
public DialogGetMentionSuggestionCmd(int i, String str, Source source, boolean z, Object obj) {
this.f2365b = i;
this.c = str;
@@ -150,7 +126,7 @@ public final class DialogGetMentionSuggestionCmd extends BaseImEngineCmd<Suggest
Collection<Member> a2;
Source source;
if (ImDialogsUtils.d(this.f2365b) != PeerType.CHAT) {
return new Suggestion((EntityValue) null, (ProfilesInfo) null);
return new Suggestion(null, null);
}
Member Z = imEnvironment.Z();
int d = imEnvironment.a0().n().d();
@@ -235,4 +211,28 @@ public final class DialogGetMentionSuggestionCmd extends BaseImEngineCmd<Suggest
public String toString() {
return "DialogGetMentionSuggestionCmd(dialogId=" + this.f2365b + ", query=" + this.c + ", source=" + this.d + ", isAwaitNetwork=" + this.e + ", changerTag=" + this.f + ")";
}
public static final class a<T> implements Comparator<Member> {
List a;
a(List list) {
this.a = list;
}
@Override // java.util.Comparator
/* renamed from: a */
public int compare(Member member, Member member2) {
int indexOf = this.a.indexOf(member);
int indexOf2 = this.a.indexOf(member2);
int i = indexOf;
if (indexOf < 0) {
i = Integer.MAX_VALUE;
}
int i2 = indexOf2;
if (indexOf2 < 0) {
i2 = Integer.MAX_VALUE;
}
return Intrinsics.a(i, i2);
}
}
}
@@ -19,7 +19,7 @@ import java.util.List;
public final class DialogActionsHelper {
public static final DialogActionsHelper a = new DialogActionsHelper();
public final List<DialogAction> a(ImConfig imConfig, Dialog dialog, ProfilesSimpleInfo profilesSimpleInfo) {
public List<DialogAction> a(ImConfig imConfig, Dialog dialog, ProfilesSimpleInfo profilesSimpleInfo) {
if (dialog != null && profilesSimpleInfo != null) {
long b2 = TimeProvider.f.b();
ChatSettings z1 = dialog.z1();
@@ -84,7 +84,7 @@ public final class DialogActionsHelper {
return new ArrayList<>();
}
public final List<DialogAction> a(Dialog dialog, ProfilesSimpleInfo profilesSimpleInfo) {
public List<DialogAction> a(Dialog dialog, ProfilesSimpleInfo profilesSimpleInfo) {
long b2 = TimeProvider.f.b();
Profile profile = profilesSimpleInfo.get(dialog.getId());
@@ -138,7 +138,7 @@ public final class DialogActionsHelper {
return arrayList;
}
public final boolean a(Dialog dialog) {
public boolean a(Dialog dialog) {
if (dialog.V1() || !dialog.y1()) {
return false;
}
@@ -16,11 +16,11 @@ import java.util.List;
public final class MsgActionHelper {
public static final MsgActionHelper a = new MsgActionHelper();
public final List<MsgAction> a(ImEngine imEngine, Dialog dialog, Collection<? extends Msg> collection) {
public List<MsgAction> a(ImEngine imEngine, Dialog dialog, Collection<? extends Msg> collection) {
return a(imEngine != null ? imEngine.g() : null, dialog, collection);
}
public final List<MsgAction> a(ImConfig imConfig, Dialog dialog, Collection<? extends Msg> collection) {
public List<MsgAction> a(ImConfig imConfig, Dialog dialog, Collection<? extends Msg> collection) {
if (imConfig != null && dialog != null && collection != null) {
MsgPermissionHelper.a aVar = new MsgPermissionHelper.a(imConfig, dialog, collection);
ArrayList<MsgAction> arrayList = new ArrayList<>();
@@ -74,11 +74,7 @@ public class VhBindArgs {
private boolean L() {
boolean var1;
if (this.K() <= this.m && !TimeProvider.f.c()) {
var1 = false;
} else {
var1 = true;
}
var1 = this.K() > this.m || TimeProvider.f.c();
return var1;
}
@@ -109,11 +105,7 @@ public class VhBindArgs {
public boolean B() {
AdapterEntry var1 = this.a;
boolean var2;
if (var1 != null && var1.c()) {
var2 = true;
} else {
var2 = false;
}
var2 = var1 != null && var1.c();
return var2;
}
@@ -121,11 +113,7 @@ public class VhBindArgs {
public boolean C() {
AdapterEntry var1 = this.a;
boolean var2;
if (var1 != null && var1.c() && this.a.c.getLocalId() == this.b.c.getLocalId()) {
var2 = true;
} else {
var2 = false;
}
var2 = var1 != null && var1.c() && this.a.c.getLocalId() == this.b.c.getLocalId();
return var2;
}
@@ -133,11 +121,7 @@ public class VhBindArgs {
public boolean D() {
AdapterEntry var1 = this.a;
boolean var2;
if (var1 != null && var1.a == 83) {
var2 = true;
} else {
var2 = false;
}
var2 = var1 != null && var1.a == 83;
return var2;
}
@@ -145,11 +129,7 @@ public class VhBindArgs {
public boolean E() {
Msg var1 = this.b.c;
boolean var2;
if (var1 instanceof MsgFromUser && ((MsgFromUser) var1).i2()) {
var2 = true;
} else {
var2 = false;
}
var2 = var1 instanceof MsgFromUser && ((MsgFromUser) var1).i2();
return var2;
}
@@ -157,11 +137,7 @@ public class VhBindArgs {
public boolean F() {
Msg var1 = this.b.c;
boolean var2;
if (var1 instanceof MsgFromUser && ((MsgFromUser) var1).F0()) {
var2 = true;
} else {
var2 = false;
}
var2 = var1 instanceof MsgFromUser && ((MsgFromUser) var1).F0();
return var2;
}
@@ -169,11 +145,7 @@ public class VhBindArgs {
public boolean G() {
AdapterEntry var1 = this.b;
boolean var2;
if (var1 != null && var1.a == 51) {
var2 = true;
} else {
var2 = false;
}
var2 = var1 != null && var1.a == 51;
return var2;
}
@@ -186,11 +158,7 @@ public class VhBindArgs {
long var1 = this.K();
long var3 = this.m;
boolean var5;
if (var1 > var3 && var1 < var3 * 2L) {
var5 = true;
} else {
var5 = false;
}
var5 = var1 > var3 && var1 < var3 * 2L;
return var5;
}
@@ -206,18 +174,10 @@ public class VhBindArgs {
MsgFromUser var7 = (MsgFromUser) var1;
Msg var3 = this.a.c;
boolean var4;
if (var3 != null && var3.d() == MsgSyncState.DONE) {
var4 = true;
} else {
var4 = false;
}
var4 = var3 != null && var3.d() == MsgSyncState.DONE;
boolean var5;
if (this.o == ImBgSyncState.CONNECTED) {
var5 = true;
} else {
var5 = false;
}
var5 = this.o == ImBgSyncState.CONNECTED;
boolean var6 = var2;
if (!var7.H0()) {
@@ -242,7 +202,7 @@ public class VhBindArgs {
byte var2 = 0;
int var3 = var2;
if (var1) {
AttachAudioMsg var4 = (AttachAudioMsg) ((MsgFromUser) this.b.c).c(AttachAudioMsg.class, false);
AttachAudioMsg var4 = ((MsgFromUser) this.b.c).c(AttachAudioMsg.class, false);
var3 = var2;
if (var4 != null) {
var3 = var4.f();
@@ -267,11 +227,7 @@ public class VhBindArgs {
public boolean c() {
Msg var1 = this.b.c;
boolean var2;
if (var1 instanceof MsgFromUser && ((MsgFromUser) var1).I0()) {
var2 = true;
} else {
var2 = false;
}
var2 = var1 instanceof MsgFromUser && ((MsgFromUser) var1).I0();
return var2;
}
@@ -279,22 +235,14 @@ public class VhBindArgs {
public boolean d() {
Msg var1 = this.b.c;
boolean var2;
if (var1 instanceof WithUserContent && ((WithUserContent) var1).D0() != null) {
var2 = true;
} else {
var2 = false;
}
var2 = var1 instanceof WithUserContent && ((WithUserContent) var1).D0() != null;
return var2;
}
public boolean e() {
boolean var1;
if (this.b.i > 0) {
var1 = true;
} else {
var1 = false;
}
var1 = this.b.i > 0;
return var1;
}
@@ -317,11 +265,7 @@ public class VhBindArgs {
public boolean g() {
Msg var1 = this.b.c;
boolean var2;
if (var1 instanceof MsgFromUser && ((MsgFromUser) var1).G0()) {
var2 = true;
} else {
var2 = false;
}
var2 = var1 instanceof MsgFromUser && ((MsgFromUser) var1).G0();
return var2;
}
@@ -329,33 +273,21 @@ public class VhBindArgs {
public boolean h() {
Msg var1 = this.b.c;
boolean var2;
if (var1 instanceof MsgFromUser && ((MsgFromUser) var1).Z1()) {
var2 = true;
} else {
var2 = false;
}
var2 = var1 instanceof MsgFromUser && ((MsgFromUser) var1).Z1();
return var2;
}
public boolean i() {
boolean var1;
if (this.j && !this.u() && !this.l()) {
var1 = true;
} else {
var1 = false;
}
var1 = this.j && !this.u() && !this.l();
return var1;
}
public boolean j() {
boolean var1;
if (!this.j || this.u() || this.B() && this.A() && !this.a.c.H1()) {
var1 = false;
} else {
var1 = true;
}
var1 = this.j && !this.u() && (!this.B() || !this.A() || this.a.c.H1());
return var1;
}
@@ -363,11 +295,7 @@ public class VhBindArgs {
public boolean k() {
Dialog var1 = this.e;
boolean var2;
if (var1 != null && var1.U1()) {
var2 = true;
} else {
var2 = false;
}
var2 = var1 != null && var1.U1();
return var2;
}
@@ -375,11 +303,7 @@ public class VhBindArgs {
public boolean l() {
Dialog var1 = this.e;
boolean var2;
if (var1 != null && var1.V1()) {
var2 = true;
} else {
var2 = false;
}
var2 = var1 != null && var1.V1();
return var2;
}
@@ -387,11 +311,7 @@ public class VhBindArgs {
public boolean m() {
Dialog var1 = this.e;
boolean var2;
if (var1 != null && var1.W1()) {
var2 = true;
} else {
var2 = false;
}
var2 = var1 != null && var1.W1();
return var2;
}
@@ -404,11 +324,7 @@ public class VhBindArgs {
public boolean o() {
AdapterEntry var1 = this.b;
boolean var2;
if (var1 != null && var1.a == 101) {
var2 = true;
} else {
var2 = false;
}
var2 = var1 != null && var1.a == 101;
return var2;
}
@@ -416,11 +332,7 @@ public class VhBindArgs {
public boolean p() {
Msg var1 = this.b.c;
boolean var2;
if (var1 != null && var1.G1()) {
var2 = true;
} else {
var2 = false;
}
var2 = var1 != null && var1.G1();
return var2;
}
@@ -443,11 +355,7 @@ public class VhBindArgs {
public boolean r() {
Msg var1 = this.b.c;
boolean var2;
if (var1 instanceof MsgFromUser && ((MsgFromUser) var1).e2()) {
var2 = true;
} else {
var2 = false;
}
var2 = var1 instanceof MsgFromUser && ((MsgFromUser) var1).e2();
return var2;
}
@@ -488,27 +396,19 @@ public class VhBindArgs {
public boolean v() {
IntSet var1 = this.r;
boolean var2;
if (var1 != null && var1.a(this.b.c.getLocalId())) {
var2 = true;
} else {
var2 = false;
}
var2 = var1 != null && var1.a(this.b.c.getLocalId());
return var2;
}
public boolean w() {
return this.z() ^ true;
return !this.z();
}
public boolean x() {
AdapterEntry var1 = this.c;
boolean var2;
if (var1 != null && var1.a == 100) {
var2 = true;
} else {
var2 = false;
}
var2 = var1 != null && var1.a == 100;
return var2;
}
@@ -516,11 +416,7 @@ public class VhBindArgs {
public boolean y() {
AdapterEntry var1 = this.c;
boolean var2;
if (var1 != null && var1.a == 96) {
var2 = true;
} else {
var2 = false;
}
var2 = var1 != null && var1.a == 96;
return var2;
}
@@ -528,11 +424,7 @@ public class VhBindArgs {
public boolean z() {
AdapterEntry var1 = this.c;
boolean var2;
if (var1 != null && var1.c() && this.c.c.getLocalId() == this.b.c.getLocalId()) {
var2 = true;
} else {
var2 = false;
}
var2 = var1 != null && var1.c() && this.c.c.getLocalId() == this.b.c.getLocalId();
return var2;
}
@@ -46,7 +46,7 @@ public final class MsgPartCallHolder extends MsgPartHolderBase<AttachCall> {
this.G = new StringBuilder();
}
private final void a(Msg var1) {
private void a(Msg var1) {
this.G.setLength(0);
MsgTimeFormatter var2 = this.F;
Context var3 = this.C;
@@ -55,7 +55,7 @@ public final class MsgPartCallHolder extends MsgPartHolderBase<AttachCall> {
this.H.setTimeText(this.G);
}
private final void a(boolean var1) {
private void a(boolean var1) {
MsgPartIconTwoRowView var2 = this.H;
int var3;
if (var1) {
@@ -67,7 +67,7 @@ public final class MsgPartCallHolder extends MsgPartHolderBase<AttachCall> {
var2.setIcon(var3);
}
private final void a(boolean var1, AttachCall var2) {
private void a(boolean var1, AttachCall var2) {
boolean var3 = !var1;
if (var2.h() == CallState.ERROR) {
this.H.setSubtitleText(m.vkim_msg_list_call_error);
@@ -56,46 +56,6 @@ public class VhMsg extends VhBase implements SwipeToReplyItemTouchCallback.b {
private static final int[][] j0;
private static final int[][] k0;
private static final int[][] l0;
private final MsgPartHolderBase B;
private final MsgPartHolderBindArgs C = new MsgPartHolderBindArgs();
private final Rect D = new Rect();
private final Rect E = new Rect();
private final Rect F = new Rect();
private final Rect G = new Rect();
private ColorDrawable H;
private final int I;
private final int J;
private final int K;
private final int L;
private final int M;
private Drawable N;
private Drawable O;
private BombView P;
private BombView.d Q;
private int R;
private int S;
private final DisplayNameFormatter T = new DisplayNameFormatter();
private final StringBuilder U = new StringBuilder();
private final StringBuilder V = new StringBuilder();
private final String W;
private final String X;
private final String Y;
private boolean Z;
private BubbleColors a0;
private final FluidHorizontalLayout b;
@ColorInt
private int b0;
private final AvatarView c;
private MsgListAdapterCallback c0;
private final Space d;
private Msg d0;
private final MsgBubbleView e;
private Dialog e0;
private final MsgStatusView f;
private int f0;
private final ImageView g;
private h g0 = new h();
private final Space h;
static {
int[] var0 = new int[]{0, 0, 0, 0};
@@ -119,18 +79,59 @@ public class VhMsg extends VhBase implements SwipeToReplyItemTouchCallback.b {
l0 = new int[][]{var0, {4, 4, 0, 0, 0, 2, 8, 0}, var1, var2, {4, 0, 0, 0, 0, 2, 8, 0}, {0, 0, 0, 0, 0, 2, 8, 0}, {4, 4, 0, 0, 0, 2, 8, 0}, {0, 0, 0, 0, 0, 0, 0, 0}};
}
private final MsgPartHolderBase B;
private final MsgPartHolderBindArgs C = new MsgPartHolderBindArgs();
private final Rect D = new Rect();
private final Rect E = new Rect();
private final Rect F = new Rect();
private final Rect G = new Rect();
private final int I;
private final int J;
private final int K;
private final int L;
private final int M;
private final DisplayNameFormatter T = new DisplayNameFormatter();
private final StringBuilder U = new StringBuilder();
private final StringBuilder V = new StringBuilder();
private final String W;
private final String X;
private final String Y;
private final FluidHorizontalLayout b;
private final AvatarView c;
private final Space d;
private final MsgBubbleView e;
private final MsgStatusView f;
private final ImageView g;
private final Space h;
private final ColorDrawable H;
private Drawable N;
private Drawable O;
private final BombView P;
private final BombView.d Q;
private final int R;
private final int S;
private boolean Z;
private BubbleColors a0;
@ColorInt
private int b0;
private MsgListAdapterCallback c0;
private Msg d0;
private Dialog e0;
private int f0;
private final h g0 = new h();
public VhMsg(View itemView, MsgPartHolderBase vhBase) {
super(itemView);
Context context = itemView.getContext();
LayoutInflater var4 = LayoutInflater.from(context);
this.b = (FluidHorizontalLayout) itemView;
this.c = (AvatarView) itemView.findViewById(com.vk.im.ui.h.avatar);
this.d = (Space) itemView.findViewById(com.vk.im.ui.h.avatar_space);
this.e = (MsgBubbleView) itemView.findViewById(com.vk.im.ui.h.bubble);
this.f = (MsgStatusView) itemView.findViewById(com.vk.im.ui.h.status);
this.g = (ImageView) itemView.findViewById(com.vk.im.ui.h.vkim_channel_share);
this.h = (Space) itemView.findViewById(com.vk.im.ui.h.status_space);
this.P = (BombView) itemView.findViewById(com.vk.im.ui.h.bomb);
this.c = itemView.findViewById(com.vk.im.ui.h.avatar);
this.d = itemView.findViewById(com.vk.im.ui.h.avatar_space);
this.e = itemView.findViewById(com.vk.im.ui.h.bubble);
this.f = itemView.findViewById(com.vk.im.ui.h.status);
this.g = itemView.findViewById(com.vk.im.ui.h.vkim_channel_share);
this.h = itemView.findViewById(com.vk.im.ui.h.status_space);
this.P = itemView.findViewById(com.vk.im.ui.h.bomb);
this.B = vhBase;
this.H = new ColorDrawable(context.getResources().getColor(com.vk.im.ui.d.msg_search_selection));
this.I = ContextExtKt.b(context, com.vk.im.ui.e.msg_bubble_max_width);
@@ -203,6 +204,10 @@ public class VhMsg extends VhBase implements SwipeToReplyItemTouchCallback.b {
};
}
public static VhMsg a(LayoutInflater var0, ViewGroup var1, MsgPartHolderBase var2) {
return new VhMsg(var0.inflate(j.vkim_msg_list_item_msg_from_user, var1, false), var2);
}
private int a(Style var1, Style var2, boolean var3) {
int var4;
if (var3) {
@@ -283,20 +288,15 @@ public class VhMsg extends VhBase implements SwipeToReplyItemTouchCallback.b {
case 103:
return VhMsg.Style.EMPTY;
default:
StringBuilder var3 = new StringBuilder();
var3.append("Unknown viewType: ");
var3.append(var1);
throw new IllegalArgumentException(var3.toString());
String var3 = "Unknown viewType: " +
var1;
throw new IllegalArgumentException(var3);
}
}
return VhMsg.Style.TWO_LINE;
}
public static VhMsg a(LayoutInflater var0, ViewGroup var1, MsgPartHolderBase var2) {
return new VhMsg(var0.inflate(j.vkim_msg_list_item_msg_from_user, var1, false), var2);
}
private void a(VhBindArgs args, Rect rect) {
Style var3 = this.a(args.b);
boolean var4 = args.b.f();
@@ -411,11 +411,7 @@ public class VhMsg extends VhBase implements SwipeToReplyItemTouchCallback.b {
Msg var10 = var5.c;
var9 = var6;
if (var10 != null) {
if (var10.v1() == args.g.t1()) {
var9 = true;
} else {
var9 = false;
}
var9 = var10.v1() == args.g.t1();
if (var10.O1()) {
int var12 = var10.d().ordinal();
@@ -433,11 +429,7 @@ public class VhMsg extends VhBase implements SwipeToReplyItemTouchCallback.b {
b = args.I();
}
} else {
if (var10.C1() <= args.i) {
var6 = true;
} else {
var6 = false;
}
var6 = var10.C1() <= args.i;
if (!var6 && !var9) {
var11 = MsgStatus.UNREAD;
@@ -575,18 +567,14 @@ public class VhMsg extends VhBase implements SwipeToReplyItemTouchCallback.b {
partArgs.o = args.n;
partArgs.s = args.v();
partArgs.t = args.q;
partArgs.u = var4.b() ^ true;
partArgs.u = !var4.b();
boolean var5;
if (var3.i > 0) {
var5 = true;
} else {
var5 = false;
}
var5 = var3.i > 0;
partArgs.v = var5;
partArgs.w = args.k;
partArgs.x = args.l;
partArgs.y = this.Z ^ true;
partArgs.y = !this.Z;
partArgs.z = args.s;
partArgs.A = args.t;
partArgs.l = this.b0;
@@ -671,7 +659,7 @@ public class VhMsg extends VhBase implements SwipeToReplyItemTouchCallback.b {
private void f(VhBindArgs args) {
Msg var2 = args.b.c;
if (var2 != null) {
this.P.setStateListener((BombView.d) null);
this.P.setStateListener(null);
if (var2.M1() && !var2.E1()) {
this.P.setVisibility(View.GONE);
} else {
@@ -810,24 +798,12 @@ public class VhMsg extends VhBase implements SwipeToReplyItemTouchCallback.b {
this.e.setFwdPadding(this.D);
this.e.setContentPadding(this.E);
boolean var7;
if (args.b.a == 83) {
var7 = true;
} else {
var7 = false;
}
var7 = args.b.a == 83;
boolean var5;
if (args.a.a == 83) {
var5 = true;
} else {
var5 = false;
}
var5 = args.a.a == 83;
if (!args.F() || !var7 && !var5) {
var5 = true;
} else {
var5 = false;
}
var5 = !args.F() || !var7 && !var5;
MsgBubbleView var8 = this.e;
boolean var6 = var4;
@@ -904,18 +880,10 @@ public class VhMsg extends VhBase implements SwipeToReplyItemTouchCallback.b {
return false;
} else {
boolean var5;
if (var2.a == 50) {
var5 = true;
} else {
var5 = false;
}
var5 = var2.a == 50;
boolean var6;
if (!args.z() && var2.i == 0) {
var6 = true;
} else {
var6 = false;
}
var6 = !args.z() && var2.i == 0;
if (var5 || var6 || args.y() || args.x()) {
var4 = true;
@@ -934,11 +902,7 @@ public class VhMsg extends VhBase implements SwipeToReplyItemTouchCallback.b {
private boolean u(int var1) {
boolean var2;
if (var1 != 2 && var1 != 3) {
var2 = false;
} else {
var2 = true;
}
var2 = var1 == 2 || var1 == 3;
return var2;
}
@@ -960,9 +924,7 @@ public class VhMsg extends VhBase implements SwipeToReplyItemTouchCallback.b {
Msg var1 = this.d0;
if (var1 != null) {
Dialog var2 = this.e0;
if (var2 != null && MsgPermissionHelper.b.a(var2, var1)) {
return true;
}
return var2 != null && MsgPermissionHelper.b.a(var2, var1);
}
}
return false;
@@ -997,11 +959,7 @@ public class VhMsg extends VhBase implements SwipeToReplyItemTouchCallback.b {
public void a(VhBindArgs args) {
boolean var2;
if (VKThemeHelper.l() == VKTheme.VKAPP_LIGHT) {
var2 = true;
} else {
var2 = false;
}
var2 = VKThemeHelper.l() == VKTheme.VKAPP_LIGHT;
this.Z = var2;
AdapterEntry var3 = args.b;
@@ -1062,11 +1020,7 @@ public class VhMsg extends VhBase implements SwipeToReplyItemTouchCallback.b {
public boolean f0() {
boolean var1;
if (this.f0 == 100) {
var1 = true;
} else {
var1 = false;
}
var1 = this.f0 == 100;
return var1;
}
@@ -1083,7 +1037,7 @@ public class VhMsg extends VhBase implements SwipeToReplyItemTouchCallback.b {
this.B.c(var1);
}
private static enum Style {
private enum Style {
BUTTON(6),
EMPTY(7),
FWD_SENDER(4),
@@ -1095,14 +1049,14 @@ public class VhMsg extends VhBase implements SwipeToReplyItemTouchCallback.b {
public final int index;
private Style(int var3) {
Style(int var3) {
this.index = var3;
}
}
private class h implements Functions<Unit> {
private int a;
private Runnable b;
private final int a;
private final Runnable b;
private h() {
this.a = Screen.a(12);
@@ -26,30 +26,23 @@ import com.vtosters.lite.R;
public final class MentionsController {
private final RichEditText a;
private final ImEngine mImEngine;
private final View j;
private final b k;
private boolean state;
private CoordinatorLayout mCoordinatorLayout;
private VkBottomSheetBehavior<RecyclerView> mBottomSheetBehavior;
private boolean e;
private DialogMentionComponent mDialogMentionComponent;
private MentionsManager mMentionsManager;
private final ImEngine mImEngine;
private int i;
private final View j;
private final b k;
public interface b {
boolean c();
boolean d();
}
private final DialogMentionComponent mDialogMentionComponent;
private final MentionsManager mMentionsManager;
private final int i;
public MentionsController(ImEngine imEngine, int i, View view, b bVar) {
this.mImEngine = imEngine;
this.i = i;
this.j = view;
this.k = bVar;
this.a = (RichEditText) this.j.findViewById(R.id.writebar_edit);
this.a = this.j.findViewById(R.id.writebar_edit);
this.mMentionsManager = new MentionsManager(this.a, new MentionSuggestionsSupplier() {
@Override
@@ -71,7 +64,7 @@ public final class MentionsController {
@Override
public void b() {
MentionsController.this.mDialogMentionComponent.a(0, (String) null);
MentionsController.this.mDialogMentionComponent.a(0, null);
MentionsController.this.g();
}
});
@@ -92,18 +85,18 @@ public final class MentionsController {
});
}
public final void g() {
public void g() {
this.e = false;
j();
}
private final void h() {
private void h() {
if (this.state) {
return;
}
View inflate = ((ViewStub) this.j.findViewById(R.id.mentions_container_stub)).inflate();
ViewGroup viewGroup = (ViewGroup) inflate.findViewById(R.id.mentions_container);
viewGroup.addView(this.mDialogMentionComponent.a(viewGroup, (Bundle) null));
ViewGroup viewGroup = inflate.findViewById(R.id.mentions_container);
viewGroup.addView(this.mDialogMentionComponent.a(viewGroup, null));
this.mCoordinatorLayout = inflate.findViewById(R.id.mentions_cl);
this.mBottomSheetBehavior = (VkBottomSheetBehavior<RecyclerView>) ((CoordinatorLayout.LayoutParams) viewGroup.getLayoutParams()).getBehavior();
this.mBottomSheetBehavior.a(new VkBottomSheetBehavior.b() {
@@ -120,12 +113,12 @@ public final class MentionsController {
this.state = true;
}
public final void i() {
public void i() {
this.e = true;
j();
}
public final void j() {
public void j() {
if (this.k.d()) {
Context context = this.j.getContext();
Activity f = ContextExtKt.f(context);
@@ -139,27 +132,33 @@ public final class MentionsController {
}
}
public final void a() {
public void a() {
this.mDialogMentionComponent.g();
}
public final void b() {
public void b() {
this.mDialogMentionComponent.h();
}
public final b c() {
public b c() {
return this.k;
}
public final int d() {
public int d() {
return this.i;
}
public final void e() {
public void e() {
this.mDialogMentionComponent.q();
}
public final void f() {
public void f() {
this.mDialogMentionComponent.r();
}
public interface b {
boolean c();
boolean d();
}
}
@@ -12,15 +12,15 @@ import android.view.ViewGroup;
import com.vk.im.ui.o;
public class StoryBorderView extends View {
private boolean B;
private final Paint a;
private final int g;
private final int h;
private boolean B;
private LinearGradient f15747b;
private int f15748c;
private int f15749d;
private int f15750e;
private int f15751f;
private final int g;
private final int h;
public StoryBorderView(Context context) {
this(context, null, 0, 6);
@@ -34,10 +34,32 @@ public class StoryBorderView extends View {
this(context, (i2 & 2) != 0 ? null : attributeSet, (i2 & 4) != 0 ? 0 : i);
}
public StoryBorderView(Context context, AttributeSet attributeSet, int i) {
super(context, attributeSet, i);
Paint paint = new Paint();
paint.setAntiAlias(true);
paint.setStyle(Paint.Style.STROKE);
this.a = paint;
TypedArray obtainStyledAttributes = context.obtainStyledAttributes(attributeSet, o.StoryBorderView);
setBorderColor(obtainStyledAttributes.getInt(o.StoryBorderView_vkim_borderColor, 0));
this.g = obtainStyledAttributes.getInt(o.StoryBorderView_vkim_borderGradientStartColor, 0);
this.h = obtainStyledAttributes.getInt(o.StoryBorderView_vkim_borderGradientEndColor, 0);
setBorderWidth(obtainStyledAttributes.getDimensionPixelSize(o.StoryBorderView_vkim_borderWidth, 0));
obtainStyledAttributes.recycle();
}
public int getBorderColor() {
return this.f15749d;
}
public void setBorderColor(int i) {
if (this.f15749d != i) {
this.f15749d = i;
this.a.setColor(i);
invalidate();
}
}
public int getBorderGradientEndColor() {
return this.h;
}
@@ -50,14 +72,33 @@ public class StoryBorderView extends View {
return this.f15750e;
}
public void setBorderWidth(int i) {
if (this.f15750e != i) {
this.f15750e = i;
this.a.setStrokeWidth(i);
invalidate();
}
}
public int getPadding() {
return this.f15751f;
}
public void setPadding(int i) {
if (this.f15751f != i) {
this.f15751f = i;
setPadding(i, i, i, i);
}
}
public int getViewSize() {
return this.f15748c;
}
public void setViewSize(int i) {
this.f15748c = i;
}
@Override
protected void onDraw(Canvas canvas) {
canvas.drawOval(getPaddingLeft(), getPaddingTop(), getWidth() - getPaddingRight(), getHeight() - getPaddingBottom(), this.a);
@@ -69,22 +110,6 @@ public class StoryBorderView extends View {
setMeasuredDimension(i3, i3);
}
public void setBorderColor(int i) {
if (this.f15749d != i) {
this.f15749d = i;
this.a.setColor(i);
invalidate();
}
}
public void setBorderWidth(int i) {
if (this.f15750e != i) {
this.f15750e = i;
this.a.setStrokeWidth(i);
invalidate();
}
}
@Override
public void setLayoutParams(ViewGroup.LayoutParams layoutParams) {
super.setLayoutParams(layoutParams);
@@ -108,29 +133,4 @@ public class StoryBorderView extends View {
invalidate();
}
}
public void setPadding(int i) {
if (this.f15751f != i) {
this.f15751f = i;
setPadding(i, i, i, i);
}
}
public void setViewSize(int i) {
this.f15748c = i;
}
public StoryBorderView(Context context, AttributeSet attributeSet, int i) {
super(context, attributeSet, i);
Paint paint = new Paint();
paint.setAntiAlias(true);
paint.setStyle(Paint.Style.STROKE);
this.a = paint;
TypedArray obtainStyledAttributes = context.obtainStyledAttributes(attributeSet, o.StoryBorderView);
setBorderColor(obtainStyledAttributes.getInt(o.StoryBorderView_vkim_borderColor, 0));
this.g = obtainStyledAttributes.getInt(o.StoryBorderView_vkim_borderGradientStartColor, 0);
this.h = obtainStyledAttributes.getInt(o.StoryBorderView_vkim_borderGradientEndColor, 0);
setBorderWidth(obtainStyledAttributes.getDimensionPixelSize(o.StoryBorderView_vkim_borderWidth, 0));
obtainStyledAttributes.recycle();
}
}
@@ -36,37 +36,37 @@ public final class CommunityBorderedImageView extends BorderedCircleImageView im
public CommunityBorderedImageView(Context context, AttributeSet attributeSet, int i) {
super(context, attributeSet, i);
this.g0 = VKThemeHelper.d((int) R.attr.accent);
this.h0 = ContextExtKt.a(context, (int) R.color.gray_200);
this.g0 = VKThemeHelper.d(R.attr.accent);
this.h0 = ContextExtKt.a(context, R.color.gray_200);
this.i0 = new PorterDuffColorFilter(this.g0, PorterDuff.Mode.SRC_IN);
this.j0 = new PorterDuffColorFilter(this.h0, PorterDuff.Mode.SRC_IN);
}
public final void c(int unread, int read) { // get unread and read resid
public void c(int unread, int read) { // get unread and read resid
this.unread = unread;
this.read = read;
this.T = BitmapFactory.decodeResource(getResources(), this.unread);
}
public final int getPrimaryColor() {
public int getPrimaryColor() {
return this.g0;
}
public final void setPrimaryColor(int i) {
public void setPrimaryColor(int i) {
this.g0 = i;
this.i0 = new PorterDuffColorFilter(i, PorterDuff.Mode.SRC_IN);
}
public final int getWasViewedColor() {
public int getWasViewedColor() {
return this.h0;
}
public final void setWasViewedColor(int i) {
public void setWasViewedColor(int i) {
this.h0 = i;
this.j0 = new PorterDuffColorFilter(i, PorterDuff.Mode.SRC_IN);
}
public final void o() {
public void o() {
this.f0 = false;
l();
}
@@ -79,7 +79,7 @@ public final class CommunityBorderedImageView extends BorderedCircleImageView im
}
}
public final void setStoryContainer(StoriesContainer storiesContainer) {
public void setStoryContainer(StoriesContainer storiesContainer) {
if (storiesContainer.L1()) {
this.f0 = true;
m();
@@ -30,14 +30,14 @@ public class TargetImageView extends VKMultiImageView {
private static final int I = Screen.a(2);
private final int B;
private final int C;
private final RectF f21629d;
private final Paint f21630e;
private final RectF g;
private final Paint h;
private Drawable D;
private String[] F;
private int G;
private final RectF f21629d;
private final Paint f21630e;
private Canvas f21631f;
private final RectF g;
private final Paint h;
public TargetImageView(Context context, Drawable d) {
this(context, null, 0, 6);
@@ -51,6 +51,43 @@ public class TargetImageView extends VKMultiImageView {
this(context, (i2 & 2) != 0 ? null : attributeSet, (i2 & 4) != 0 ? 0 : i);
}
public TargetImageView(Context context, AttributeSet attributeSet, int i) {
super(context, attributeSet, i);
this.f21629d = new RectF();
Paint paint = new Paint();
paint.setAntiAlias(true);
paint.setDither(true);
paint.setFilterBitmap(true);
this.f21630e = paint;
this.g = new RectF();
Paint paint2 = new Paint();
paint2.setAntiAlias(true);
paint2.setStrokeWidth(I);
paint2.setStyle(Paint.Style.STROKE);
this.h = paint2;
this.B = getAccentColor();
this.C = this.B;
Drawable c2 = ContextExtKt.c(context, R.drawable.ic_check_circle_composite_24_full);
if (c2 != null) {
this.D = c2;
this.F = new String[4];
int i2 = I * 2;
setPadding(i2, i2, i2, i2);
if (attributeSet != null) {
TypedArray obtainStyledAttributes = context.obtainStyledAttributes(attributeSet, a0.TargetImageView);
setSelected(obtainStyledAttributes.getBoolean(0, false));
obtainStyledAttributes.recycle();
}
Drawable drawable = ContextCompat.getDrawable(context, R.drawable.user_placeholder);
for (int i3 = 0; i3 <= 3; i3++) {
a();
DraweeHolder<GenericDraweeHierarchy> a3 = this.a.a(i3);
a3.b().e(drawable);
}
setScaleType(ScalingUtils.b.o);
}
}
private void e() {
int i = this.G;
for (int i2 = 0; i2 < i; i2++) {
@@ -251,41 +288,4 @@ public class TargetImageView extends VKMultiImageView {
drawable.setBounds(i - drawable.getIntrinsicWidth(), i2 - this.D.getIntrinsicHeight(), i, i2);
f();
}
public TargetImageView(Context context, AttributeSet attributeSet, int i) {
super(context, attributeSet, i);
this.f21629d = new RectF();
Paint paint = new Paint();
paint.setAntiAlias(true);
paint.setDither(true);
paint.setFilterBitmap(true);
this.f21630e = paint;
this.g = new RectF();
Paint paint2 = new Paint();
paint2.setAntiAlias(true);
paint2.setStrokeWidth(I);
paint2.setStyle(Paint.Style.STROKE);
this.h = paint2;
this.B = getAccentColor();
this.C = this.B;
Drawable c2 = ContextExtKt.c(context, R.drawable.ic_check_circle_composite_24_full);
if (c2 != null) {
this.D = c2;
this.F = new String[4];
int i2 = I * 2;
setPadding(i2, i2, i2, i2);
if (attributeSet != null) {
TypedArray obtainStyledAttributes = context.obtainStyledAttributes(attributeSet, a0.TargetImageView);
setSelected(obtainStyledAttributes.getBoolean(0, false));
obtainStyledAttributes.recycle();
}
Drawable drawable = ContextCompat.getDrawable(context, R.drawable.user_placeholder);
for (int i3 = 0; i3 <= 3; i3++) {
a();
DraweeHolder<GenericDraweeHierarchy> a3 = this.a.a(i3);
a3.b().e(drawable);
}
setScaleType(ScalingUtils.b.o);
}
}
}
@@ -104,6 +104,25 @@ public final class StickerDetailsAdapter extends RecyclerView.Adapter<RecyclerVi
}
}
private static final class d extends RecyclerView.ViewHolder {
private final VKStickerImageView mImage;
public d(ViewGroup viewGroup) {
super(new VKStickerImageView(viewGroup.getContext()));
this.mImage = (VKStickerImageView) itemView;
this.mImage.setAspectRatio(1.0f);
this.mImage.setClickable(true);
this.mImage.getHierarchy().a().setVisible(true, true);
this.mImage.getHierarchy().a(0);
this.mImage.setContentDescription(this.mImage.getContext().getString(R.string.stickers_accessibility_sticker));
}
public void a(StickerItem stickerItem) {
this.mImage.a(stickerItem.h(Screen.a(80)));
this.mImage.setTag(R.id.id, stickerItem.getId());
}
}
private final class c extends RecyclerView.ViewHolder {
private final VKImageView mImageBg;
private final VKImageView mPackImage;
@@ -149,23 +168,4 @@ public final class StickerDetailsAdapter extends RecyclerView.Adapter<RecyclerVi
this.mDescription.setText(stickerStockItem.C1());
}
}
private static final class d extends RecyclerView.ViewHolder {
private final VKStickerImageView mImage;
public d(ViewGroup viewGroup) {
super(new VKStickerImageView(viewGroup.getContext()));
this.mImage = (VKStickerImageView) itemView;
this.mImage.setAspectRatio(1.0f);
this.mImage.setClickable(true);
this.mImage.getHierarchy().a().setVisible(true, true);
this.mImage.getHierarchy().a(0);
this.mImage.setContentDescription(this.mImage.getContext().getString(R.string.stickers_accessibility_sticker));
}
public void a(StickerItem stickerItem) {
this.mImage.a(stickerItem.h(Screen.a(80)));
this.mImage.setTag(R.id.id, stickerItem.getId());
}
}
}
@@ -382,7 +382,7 @@ public class StoryCircleImageView extends BorderedCircleImageView implements The
return;
}
pipelineDraweeControllerBuilder.a((Supplier<DataSource<CloseableReference<CloseableImage>>>) () -> StoryCircleImageView.this.a(list));
pipelineDraweeControllerBuilder.a(() -> StoryCircleImageView.this.a(list));
return;
}
pipelineDraweeControllerBuilder.b(null);
@@ -35,16 +35,16 @@ public class BottomNavigationItemView extends FrameLayout implements MenuView.It
private final View mCounterContainer;
private final TextView mCounter;
private final View mDot;
private final int mMargin;
private final float mSmallScale;
private final ImageView mIcon;
private final ImageView mActionIcon;
private int mItemPos;
private MenuItemImpl mItemData;
private ColorStateList mColorStateList;
private final int mMargin;
private final float mSmallScale;
private boolean mShiftingModeEnabled;
private boolean mIconsModeEnabled;
private boolean mStaticModeEnabled;
private final ImageView mIcon;
private final ImageView mActionIcon;
public BottomNavigationItemView(@NonNull Context context) {
this(context, null);
@@ -101,6 +101,10 @@ public class BottomNavigationItemView extends FrameLayout implements MenuView.It
return this.mItemPos;
}
public void setItemPosition(int pos) {
this.mItemPos = pos;
}
@SuppressLint("RestrictedApi")
public void initialize(MenuItemImpl impl, int i) {
this.mItemData = impl;
@@ -310,10 +314,6 @@ public class BottomNavigationItemView extends FrameLayout implements MenuView.It
ViewCompat.setBackground(this, resId != 0 ? ContextCompat.getDrawable(this.getContext(), resId) : null);
}
public void setItemPosition(int pos) {
this.mItemPos = pos;
}
public void setShiftingMode(boolean var1) {
this.mShiftingModeEnabled = var1;
}
@@ -3,7 +3,7 @@ package ru.vtosters.hooks;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import ru.vtosters.lite.utils.NewsFeedFiltersUtils;
import ru.vtosters.lite.utils.newsfeed.NewsFeedFiltersUtils;
public class AdBlockHook {
public static JSONObject discoverInject(JSONObject json) throws JSONException {
@@ -11,11 +11,15 @@ public class AdBlockHook {
}
public static JSONArray feedInject(JSONArray items) {
return NewsFeedFiltersUtils.feedInject(items);
return NewsFeedFiltersUtils.feedInject(items, false);
}
public static JSONObject storiesads(JSONObject json, boolean isDeleteFix) throws JSONException {
return NewsFeedFiltersUtils.storiesads(json, isDeleteFix);
public static JSONArray wallGetById(JSONArray items) {
return NewsFeedFiltersUtils.feedInject(items, true);
}
public static JSONObject storiesads(JSONObject json, boolean isDeleteFix) {
return NewsFeedFiltersUtils.storiesAds(json, isDeleteFix);
}
}
@@ -3,10 +3,11 @@ package ru.vtosters.hooks;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import ru.vtosters.hooks.other.Preferences;
import ru.vtosters.lite.utils.FriendsCatalogUtils;
import ru.vtosters.lite.utils.NewsFeedFiltersUtils;
import ru.vtosters.lite.utils.OnlineBypass;
import ru.vtosters.lite.utils.SuperAppUtils;
import ru.vtosters.lite.utils.newsfeed.NewsFeedFiltersUtils;
import java.io.IOException;
import java.text.ParseException;
@@ -30,10 +31,10 @@ public class JsonInjectors {
}
public static JSONArray newsfeedlist(JSONArray items) throws JSONException {
return NewsFeedFiltersUtils.newsfeedlist(items);
return Preferences.getBoolValue("unlockCustomLists", false) ? NewsFeedFiltersUtils.setNewsfeedLists(items) : items;
}
public static JSONObject friends(JSONObject json) throws JSONException, ParseException, IOException {
return FriendsCatalogUtils.inject(json);
}
}
}
@@ -21,14 +21,15 @@ import ru.vtosters.lite.utils.AndroidUtils;
import ru.vtosters.lite.utils.LifecycleUtils;
import ru.vtosters.lite.utils.NavigatorUtils;
import ru.vtosters.lite.utils.VTVerifications;
import ru.vtosters.sponsorpost.utils.Updates;
import static ru.vtosters.hooks.other.Preferences.checkupdates;
import static ru.vtosters.lite.utils.CacheUtils.getInstance;
import static ru.vtosters.lite.utils.NewsFeedFiltersUtils.setupFilters;
public class MainActivityInjector {
public static void inject(Activity activity) {
SystemThemeChangerHook.themeOnStart(activity);
UsersList.getUsersList();
VTVerifications.load(activity);
@@ -36,10 +37,10 @@ public class MainActivityInjector {
VTExecutors.getSlowTasksScheduler().a(() -> {
getInstance().autoCleaningCache();
Updates.updateFilters();
Updates.updatePosts();
}); // slowTasksScheduler
setupFilters();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
NotificationChannels.createChannels();
}
@@ -2,17 +2,25 @@ package ru.vtosters.hooks;
import android.content.Context;
import android.os.PowerManager;
import android.util.Log;
import androidx.recyclerview.widget.RecyclerView;
import com.vk.core.preference.Preference;
import com.vk.discover.DiscoverItemDecorator;
import ru.vtosters.hooks.other.Preferences;
import ru.vtosters.lite.concurrent.VTExecutors;
import ru.vtosters.lite.utils.NetworkUtils;
import ru.vtosters.sponsorpost.services.PostService;
import ru.vtosters.sponsorpost.utils.PostsPreferences;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import static java.lang.Long.MAX_VALUE;
import static ru.vtosters.hooks.other.Preferences.*;
import static ru.vtosters.lite.utils.AndroidUtils.getGlobalContext;
import static ru.vtosters.lite.utils.AndroidUtils.sendToast;
public class NewsfeedHook {
public static long getUpdateNewsfeed(boolean refresh_timeout) {
@@ -22,8 +30,7 @@ public class NewsfeedHook {
return switch (getString("newsupdate")) {
case "no_update" -> MAX_VALUE;
case "imd_update" -> 10000L;
default ->
Preference.b().getLong(refresh_timeout ? "refresh_timeout_top" : "refresh_timeout_recent", 600000L);
default -> Preference.b().getLong(refresh_timeout ? "refresh_timeout_top" : "refresh_timeout_recent", 600000L);
};
}
@@ -53,41 +60,70 @@ public class NewsfeedHook {
}
public static String[] feedParams() {
HashSet<String> params = new HashSet<>();
params.add("post");
params.add("photo");
params.add("photo_tag");
List<String> params = List.of("post", "photo", "photo_tag", "friends_recomm", "app_widget", "promo_button", "authors_rec");
if (!friendsrecomm()) {
params.add("friends_recomm");
HashSet<String> filteredParams = new HashSet<>();
for (String param : params) {
if (!isDisabled(param)) {
filteredParams.add(param);
}
}
if (!ads()) {
params.add("app_widget");
params.add("promo_button");
}
return filteredParams.toArray(new String[0]);
}
if (!authorsrecomm()) {
params.add("authors_rec");
}
return params.toArray(new String[0]);
private static boolean isDisabled(String param) {
return switch (param) {
case "friends_recomm" -> friendsrecomm();
case "app_widget", "promo_button" -> ads();
case "authors_rec" -> authorsrecomm();
default -> false;
};
}
public static void adsParams(HashSet<String> hashSet) {
String[] adsParams = {"ads_disabled", "ads_app_slider", "ads_site_slider", "ads_app", "ads_site", "ads_post", "ads_app_video", "ads_post_pretty_cards", "ads_post_snippet_video"};
if (ads()) {
hashSet.add("ads_disabled");
hashSet.add(adsParams[0]);
hashSet.add(adsParams[1]);
} else {
hashSet.add("ads_app_slider");
hashSet.add("ads_site_slider");
Collections.addAll(hashSet, adsParams);
}
hashSet.add("ads_app");
hashSet.add("ads_site");
hashSet.add("ads_post");
hashSet.add("ads_app_video");
hashSet.add("ads_post_pretty_cards");
hashSet.add("ads_post_snippet_video");
if (Preferences.milkshake()) {
hashSet.remove(adsParams[1]);
}
}
public static void takeOwnerIdSponsorPost(int ownerid) {
if (NetworkUtils.isNetworkConnected() && PostsPreferences.isEnabled() && !Preferences.serverFeaturesDisable()) {
VTExecutors.getIoScheduler().a(() -> {
List<Long> postIds = PostService.getPostIdsByOwnerId((long) ownerid, 0L);
PostsPreferences.saveGroupSpecifiedPosts(postIds, (long) ownerid);
});
}
}
public static void takeOwnerIdPostIdSponsorPost(String[] strArr) {
long ownerid = Long.parseLong(strArr[0].split("_")[0]);
long postId = Long.parseLong(strArr[0].split("_")[1]);
if (PostsPreferences.isPostAd(ownerid, postId)) {
return;
}
if (NetworkUtils.isNetworkConnected() && PostsPreferences.isEnabled() && !Preferences.serverFeaturesDisable() && PostsPreferences.isGroupAd(ownerid)) {
VTExecutors.getIoScheduler().a(() -> {
boolean postIds = PostService.isPostAd(ownerid, postId);
if (postIds) {
PostsPreferences.saveAdPostInfo(ownerid, postId);
sendToast("Этот пост помечен как рекламный");
}
});
}
}
public static boolean isPowerSaveMode() {
@@ -8,9 +8,6 @@ import org.json.JSONObject;
import ru.vtosters.hooks.other.Preferences;
import ru.vtosters.lite.utils.AndroidUtils;
import java.io.IOException;
import java.text.ParseException;
import static ru.vtosters.hooks.other.Preferences.*;
import static ru.vtosters.lite.net.Request.makeRequest;
import static ru.vtosters.lite.proxy.ProxyUtils.getApi;
@@ -29,7 +29,6 @@ public class Preferences {
GmsHook.fixGapps();
ProxyUtils.setProxy();
NewsFeedFiltersUtils.setupFilters();
VTVerifications.load(application);
LifecycleUtils.registerActivities(application);
@@ -95,6 +95,7 @@ public class MusicCacheDb extends SQLiteOpenHelper implements AutoCloseable { //
}
return null;
}
@Override
public void onCreate(SQLiteDatabase db) {
db.execSQL(Constants.CREATE_QUERY);
@@ -104,11 +105,11 @@ public class MusicCacheDb extends SQLiteOpenHelper implements AutoCloseable { //
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
if (oldVersion < newVersion) {
List<MusicTrack> tracks = getTracksWithCursor(db.query(Constants.TABLE_NAME, null, null, null, null, null, null));
db.execSQL(Constants.DROP_QUERY);
onCreate(db);
for (MusicTrack track : tracks) {
ContentValues vals = new ContentValues();
vals.put(Constants.COLUMN_TRACK_ID, track.y1());
@@ -136,9 +137,9 @@ public class MusicCacheDb extends SQLiteOpenHelper implements AutoCloseable { //
vals.put(Constants.COLUMN_EXPLICIT, Boolean.compare(explicit, true));
vals.put(Constants.COLUMN_DURATION, duration);
vals.put(Constants.COLUMN_HAS_ARTWORK, Boolean.compare(hasArtwork, true));
long row = getWritableDatabase().insert(Constants.TABLE_NAME, null, vals);
if (AndroidUtils.isDebuggable()) Log.d("MusicCacheDb", "addTrack(): " + row);
}
@@ -8,7 +8,6 @@ import ru.vtosters.lite.music.downloader.M3UDownloader;
import ru.vtosters.lite.utils.IOUtils;
import java.io.File;
import java.text.Normalizer;
import java.util.stream.Collectors;
public class FFMpeg {
@@ -1,7 +1,6 @@
package ru.vtosters.lite.net;
import android.util.Base64;
import android.util.Log;
import java.io.*;
import java.net.*;
@@ -11,7 +11,6 @@ import ru.vtosters.lite.proxy.https.CustomHttps;
import ru.vtosters.lite.proxy.socks.CustomSocks;
import ru.vtosters.lite.proxy.socks.Zaborona;
import java.io.IOException;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
@@ -7,7 +7,6 @@ import org.json.JSONException;
import org.json.JSONObject;
import ru.vtosters.lite.utils.AccountManagerUtils;
import ru.vtosters.lite.utils.AndroidUtils;
import ru.vtosters.lite.utils.VTVerifications;
import java.util.HashMap;
@@ -18,8 +18,6 @@ import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import static ru.vtosters.hooks.other.Preferences.getBoolValue;
public class UsersList {
private static final String TAG = "UsersList";
private static final List<Integer> descriptionsList = new ArrayList<>();
@@ -3,7 +3,6 @@ package ru.vtosters.lite.ui.components;
import android.content.ComponentName;
import android.content.pm.PackageManager;
import android.util.Log;
import ru.vtosters.hooks.other.Preferences;
import ru.vtosters.lite.utils.AndroidUtils;
import java.util.Arrays;
@@ -5,7 +5,6 @@ import androidx.preference.Preference;
import com.vtosters.lite.R;
import ru.vtosters.hooks.other.Preferences;
import static ru.vtosters.hooks.other.Preferences.getBoolValue;
import static ru.vtosters.hooks.other.Preferences.offline;
public class ActivityFragment extends TrackedMaterialPreferenceToolbarFragment {
@@ -5,11 +5,8 @@ import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.os.Build;
import android.os.Bundle;
import android.util.TypedValue;
import android.view.View;
import android.view.WindowInsetsController;
import android.webkit.WebView;
import android.widget.RadioButton;
import android.widget.RadioGroup;
@@ -66,14 +63,6 @@ public class DataSettingsFragment extends TrackedMaterialPreferenceToolbarFragme
requireActivity().getWindow().setStatusBarColor(ThemesUtils.getBackgroundContent());
requireActivity().getWindow().setNavigationBarColor(ThemesUtils.getBackgroundContent());
if (!ThemesUtils.isDarkTheme()) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
requireActivity().getWindow().getInsetsController().setSystemBarsAppearance(WindowInsetsController.APPEARANCE_LIGHT_STATUS_BARS, WindowInsetsController.APPEARANCE_LIGHT_STATUS_BARS);
} else {
requireActivity().getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR & View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR);
}
}
PreferenceFragmentUtils.addPreferenceCategory(getPreferenceScreen(), AndroidUtils.getString("data"));
PreferenceFragmentUtils.addPreference(
@@ -3,7 +3,6 @@ package ru.vtosters.lite.ui.fragments;
import android.content.Context;
import android.os.Bundle;
import android.text.TextUtils;
import androidx.preference.Preference;
import com.vk.core.dialogs.alert.VkAlertDialog;
import com.vk.newsfeed.NewsfeedSettingsFragment;
import com.vk.newsfeed.controllers.NewsfeedController;
@@ -12,9 +11,9 @@ import com.vtosters.lite.ui.SummaryListPreference;
import ru.vtosters.hooks.other.Preferences;
import ru.vtosters.lite.ui.components.NewsfeedListManager;
import ru.vtosters.lite.utils.NavigatorUtils;
import ru.vtosters.lite.utils.NewsFeedFiltersUtils;
import java.util.Objects;
import java.util.Set;
import static ru.vtosters.lite.utils.AndroidUtils.sendToast;
@@ -31,14 +30,9 @@ public class FeedFragment extends TrackedMaterialPreferenceToolbarFragment {
NavigatorUtils.switchFragment(requireContext(), NewsfeedSettingsFragment.class);
return true;
});
findPreference("cringecopyright").setEnabled(!Preferences.copyright_post());
var findPreference = (SummaryListPreference) findPreference("newsfeed_order");
findPreference.setValue(NewsfeedController.e.k() ? "top" : "recent");
findPreference.setOnPreferenceChangeListener((preference, o) -> {
NewsfeedController.e.a(0);
NewsfeedController.e.a((Boolean) Objects.equals(o, "top"));
NewsfeedController.e.b(true);
findPreference("sponsorpost").setOnPreferenceClickListener(preference -> {
NavigatorUtils.switchFragment(requireContext(), SponsorPostFragment.class);
return true;
});
@@ -46,18 +40,12 @@ public class FeedFragment extends TrackedMaterialPreferenceToolbarFragment {
findPreference("sourcenamefilter").setSummary(count(Preferences.getString("sourcenamefilter")));
findPreference("linkfilter").setSummary(count(Preferences.getString("linkfilter")));
findPreference("spamfilters").setOnPreferenceClickListener(preference -> {
NewsFeedFiltersUtils.setupFilters();
return true;
});
findPreference("sourcenamefilter").setOnPreferenceClickListener(preference -> {
NewsFeedFiltersUtils.setupFilters();
return true;
});
findPreference("linkfilter").setOnPreferenceClickListener(preference -> {
NewsFeedFiltersUtils.setupFilters();
SummaryListPreference findPreference = (SummaryListPreference) findPreference("newsfeed_order");
findPreference.setValue(NewsfeedController.e.k() ? "top" : "recent");
findPreference.setOnPreferenceChangeListener((preference, o) -> {
NewsfeedController.e.a(0);
NewsfeedController.e.a((Boolean) Objects.equals(o, "top"));
NewsfeedController.e.b(true);
return true;
});
@@ -85,7 +73,7 @@ public class FeedFragment extends TrackedMaterialPreferenceToolbarFragment {
return true;
});
var str = Preferences.getPreferences().getString("news_feed_selected_items", "");
String str = Preferences.getPreferences().getString("news_feed_selected_items", "");
findPreference("newsfeedlistmanager").setSummary(
String.format(requireContext().getString(R.string.feed_hidden), (!TextUtils.isEmpty(str) ? str.split(",").length : 0))
);
@@ -95,12 +83,17 @@ public class FeedFragment extends TrackedMaterialPreferenceToolbarFragment {
return true;
});
boolean unlockCustomLists = Preferences.getBoolValue("unlockCustomLists", false);
findPreference("newsfeedlistmanager").setVisible(unlockCustomLists);
findPreference("newsfeedlistmanager_reset").setVisible(unlockCustomLists);
findPreference("feedcache").setVisible(!Preferences.getString("newsupdate").equals("no_update"));
}
private String count(String text) {
// count comma separated words in string
var count = text.split(", ").length;
int count = text.split(", ").length;
if (count < 1 || text.isEmpty()) {
return requireContext().getString(R.string.feed_no_elements);
@@ -117,7 +110,6 @@ public class FeedFragment extends TrackedMaterialPreferenceToolbarFragment {
.setPositiveButton(requireContext().getString(R.string.yes), (dialogInterface, i) -> {
Preferences.getPreferences().edit().remove(key).apply();
sendToast(requireContext().getString(R.string.elements_deleted_success));
NewsFeedFiltersUtils.setupFilters();
})
.setNegativeButton(requireContext().getString(R.string.cancel),
(dialogInterface, i) -> dialogInterface.dismiss())
@@ -125,15 +117,16 @@ public class FeedFragment extends TrackedMaterialPreferenceToolbarFragment {
}
private String countSet(String key) {
var set = Preferences.getPreferences().getStringSet(key, null);
Set<String> set = Preferences.getPreferences().getStringSet(key, null);
StringBuilder str = new StringBuilder();
if (set != null) {
for (var s : set) {
str.append(s).append(", ");
}
}
var count = str.toString().split(", ").length;
int count = str.toString().split(", ").length;
if (count < 1 || (str.length() == 0)) {
return requireContext().getString(R.string.feed_no_elements);
@@ -142,16 +135,8 @@ public class FeedFragment extends TrackedMaterialPreferenceToolbarFragment {
}
}
@Override
public boolean onPreferenceTreeClick(Preference preference) {
findPreference("cringecopyright").setEnabled(!Preferences.copyright_post());
NewsFeedFiltersUtils.setupFilters();
return super.onPreferenceTreeClick(preference);
}
@Override
public int T4() {
return R.string.vtlfeed;
}
}
}
@@ -2,9 +2,7 @@ package ru.vtosters.lite.ui.fragments;
import android.annotation.SuppressLint;
import android.content.Context;
import android.content.Intent;
import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.os.Bundle;
import android.util.TypedValue;
import android.widget.RadioButton;
@@ -16,8 +16,6 @@ import ru.vtosters.lite.ssfs.UsersList;
import ru.vtosters.lite.ui.activities.VKAdminTokenActivity;
import ru.vtosters.lite.utils.*;
import static ru.vtosters.hooks.other.Preferences.getBoolValue;
public class OtherFragment extends TrackedMaterialPreferenceToolbarFragment {
private static final int VK_ADMIN_TOKEN_REQUEST_CODE = 1;
@@ -3,11 +3,6 @@ package ru.vtosters.lite.ui.fragments;
import android.os.Bundle;
import com.vtosters.lite.R;
import java.io.IOException;
import static ru.vtosters.lite.proxy.RandomProxy.setupNewProxy;
import static ru.vtosters.lite.utils.AndroidUtils.sendToast;
public class ProxySettingsFragment extends TrackedMaterialPreferenceToolbarFragment {
@Override
public void onCreate(Bundle bundle) {
@@ -0,0 +1,97 @@
package ru.vtosters.lite.ui.fragments;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import ru.vtosters.hooks.other.ThemesUtils;
import ru.vtosters.lite.ui.PreferenceFragmentUtils;
import ru.vtosters.lite.utils.NetworkUtils;
import ru.vtosters.sponsorpost.data.Filter;
import ru.vtosters.sponsorpost.services.FilterService;
import ru.vtosters.sponsorpost.utils.FiltersPreferences;
import ru.vtosters.sponsorpost.utils.PostsPreferences;
import java.util.List;
import static ru.vtosters.sponsorpost.utils.FiltersPreferences.*;
public class SponsorPostFragment extends TrackedMaterialPreferenceToolbarFragment {
@Override
public void onCreate(Bundle bundle) {
super.onCreate(bundle);
addPreferencesFromResource(com.vtosters.lite.R.xml.empty);
requireActivity().getWindow().setStatusBarColor(ThemesUtils.getBackgroundContent());
requireActivity().getWindow().setNavigationBarColor(ThemesUtils.getBackgroundContent());
PreferenceFragmentUtils.addPreferenceCategory(getPreferenceScreen(), "Sponsor Post");
PreferenceFragmentUtils.addMaterialSwitchPreference(
getPreferenceScreen(),
"sponsorpost",
"Фильтр постов",
"Получать списки рекламных постов, которые не блокируются рекламными фильтрами",
null,
PostsPreferences.isEnabled(),
(preference, o) -> {
PostsPreferences.setEnabled((boolean) o);
return true;
}
);
requireActivity().runOnUiThread(() -> {
PreferenceFragmentUtils.addPreferenceCategory(getPreferenceScreen(), "Фильтры постов");
List<Filter> lists;
if (!NetworkUtils.isNetworkConnected() || NetworkUtils.isInternetSlow()) {
lists = FiltersPreferences.getAllDownloadedFilters();
} else {
lists = FilterService.getFilters(null);
}
if (lists.isEmpty()) {
PreferenceFragmentUtils.addPreference(
getPreferenceScreen(),
"",
"У вас не скачаны фильтры",
"Подключитесь к интернету и попробуйте войти ещё раз",
null,
null
);
} else {
for (var list : lists) {
PreferenceFragmentUtils.addMaterialSwitchPreference(
getPreferenceScreen(),
"",
list.getTitle(),
list.getSummary() + "\n\n" + "Версия фильтра: v" + list.getVersion(),
null,
getSavedKeyValue(list.getId()),
(preference, o) -> {
if ((boolean) o) {
saveFilter(list);
} else {
deleteFilter(list.getId());
}
return true;
}
);
}
PreferenceFragmentUtils.addPreference(
getPreferenceScreen(),
"",
"Исходники фильтров",
"Посмотреть исходники фильтров и их содержимое\n\nЕсли вы хотите помочь - вы можете предложить свои идеи для фильтров тут!",
null,
preference -> {
requireContext().startActivity(new Intent(Intent.ACTION_VIEW).setData(Uri.parse("https://github.com/vtosters/adlists")));
return false;
}
);
}
}
);
}
}
@@ -87,7 +87,7 @@ public class SystemInfo extends TrackedMaterialPreferenceToolbarFragment {
AndroidUtils.sendToast(requireContext().getString(R.string.copied_to_clipboard));
return false;
});
PreferenceFragmentUtils.addPreference(getPreferenceScreen(), "", "Valid Signature", "Value: " + isValidSignature, 0, null);
PreferenceFragmentUtils.addPreference(getPreferenceScreen(), "", "isTablet", "Value: " + isTablet, 0, null);
@@ -71,13 +71,6 @@ public class VTSettings extends TrackedMaterialPreferenceToolbarFragment {
return AndroidUtils.getString(strRes) + ": " + AndroidUtils.getString(R.string.vtlsettdisabled);
}
public static String getSSFSsumm() {
if (Preferences.hasSpecialVerif())
return AndroidUtils.getString(R.string.vtlssfssumm) + ": " + AndroidUtils.getString(R.string.vtlsettverifyes);
return AndroidUtils.getString(R.string.vtlssfssumm) + ": " + AndroidUtils.getString(R.string.vtlsettverifno);
}
public static String getTGSsumm() {
return AndroidUtils.getString(R.string.vtltgssumm) + ": " + TelegramStickersService.getInstance(AndroidUtils.getGlobalContext()).getActivePacksListReference().size();
}
@@ -1,7 +1,6 @@
package ru.vtosters.lite.ui.wallpapers;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.widget.Toast;
import androidx.annotation.Nullable;
@@ -19,7 +19,6 @@ import androidx.annotation.StringRes;
import androidx.core.app.NotificationManagerCompat;
import com.vk.core.util.ToastUtils;
import com.vtosters.lite.general.fragments.WebViewFragment;
import ru.vtosters.hooks.other.Preferences;
import java.io.File;
import java.io.FileOutputStream;
@@ -33,12 +32,6 @@ import java.util.Random;
public class AndroidUtils {
private static final String ALLOWED_CHARACTERS = "0123456789qwertyuiopasdfghjklzxcvbnm";
public enum ScreenSize {
small,
normal,
large,
xlarge
}
public static boolean isDebuggable() {
return 0 != (AndroidUtils.getGlobalContext().getApplicationInfo().flags & ApplicationInfo.FLAG_DEBUGGABLE);
@@ -224,4 +217,11 @@ public class AndroidUtils {
public static String upString(String s) {
return s.substring(0, 1).toUpperCase() + s.substring(1).toLowerCase();
}
public enum ScreenSize {
small,
normal,
large,
xlarge
}
}
@@ -1,526 +0,0 @@
package ru.vtosters.lite.utils;
import android.text.TextUtils;
import android.util.Log;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import ru.vtosters.hooks.other.Preferences;
import java.io.IOException;
import java.util.*;
import static ru.vtosters.hooks.other.Preferences.*;
import static ru.vtosters.lite.utils.AndroidUtils.getGlobalContext;
public class NewsFeedFiltersUtils {
public static List<String> mFilters = new ArrayList<>();
public static List<String> mFiltersNames = new ArrayList<>();
public static List<String> mFiltersLinks = new ArrayList<>();
public static void setupFilters() {
getFilter("refsfilter", "Referals.txt", mFilters);
getFilter("shortlinkfilter", "LinkShorter.txt", mFilters);
getFilter("default_ad_list", "StandartFilter.txt", mFilters);
getFilter("shitposting", "IDontWantToReadIt.txt", mFilters);
getFilter("cringecopyright", "CopyrightAds.txt", mFiltersLinks);
setCustomFilters(mFilters, getString("spamfilters"));
setCustomFilters(mFiltersNames, getString("sourcenamefilter"));
setCustomFilters(mFiltersLinks, getString("linkfilter"));
}
// Get needed filter list from assets
public static void getFilter(String boolname, String filename, List<String> list) {
if (getBoolValue(boolname, false)) {
try (Scanner scanner = new Scanner(getGlobalContext().getAssets().open(filename))) {
while (scanner.hasNextLine()) {
addNonEmptyLineToList(scanner.nextLine(), list);
}
} catch (IOException e) {
Log.d("NewsFeedFiltersUtils", e.getMessage());
}
}
}
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")) {
var copyHistoryNode = obj.optJSONArray("copy_history");
if (copyHistoryNode != null && copyHistoryNode.length() != 0) {
for (int i = 0; i < copyHistoryNode.length(); i++) {
var item = copyHistoryNode.optJSONObject(i);
var text = item.optString("text");
if (isBadNews(text)) {
if (dev())
Log.d("RepostFilter", "Fetched repost ad (isBadNews), owner id " + item.optString("owner_id") + ", text: " + text);
return true;
} else if (isAds(item, item.optString("post_type"))) {
if (dev())
Log.d("RepostFilter", "Fetched repost ad (ads), owner id " + item.optString("owner_id") + ", text: " + text);
return true;
}
if (mFiltersLinks != null && getBoolValue("cringerepost", false)) {
for (String filter : mFiltersLinks) {
if (text.contains(filter)) {
if (dev())
Log.d("RepostFilter", "Fetched repost ad, owner id " + item.optString("owner_id") + ", text: " + text);
return true;
}
}
}
}
}
}
return false;
}
public static boolean checkCopyright(JSONObject json) throws JSONException {
if (json.has("copyright")) {
if (copyright_post()) return true;
JSONObject copyright = json.optJSONObject("copyright");
String copyrightName = null;
String copyrightLink = null;
if (copyright != null) {
copyrightName = copyright.getString("name").toLowerCase();
copyrightLink = copyright.getString("link").toLowerCase();
}
if (mFiltersNames != null) {
for (String filter : mFiltersNames) {
if (copyrightName != null && copyrightName.contains(filter)) return true;
}
}
if (mFiltersLinks != null) {
for (String filter : mFiltersLinks) {
if (copyrightLink != null && copyrightLink.contains(filter)) return true;
}
}
}
return false;
}
public static boolean isBadNews(String text) {
var textInLowerCase = text.toLowerCase();
if (mFilters != null) {
for (String filter : mFilters) {
if (textInLowerCase.contains(filter)) {
if (dev())
Log.d("NewsfeedAdBlockV2", text);
return true;
}
}
}
return false;
}
public static boolean checkCaption(JSONObject postJson) {
if (postJson.has("caption")) {
if (captions()) return true;
var caption = postJson.optJSONObject("caption");
if (postsrecomm()) {
try {
if (caption != null) {
String type = caption.getString("type");
return type.equals("explorebait") || // Может быть интересно
type.equals("shared") || // Поделился записью
type.equals("digest") || // Рекомедации
type.equals("commented") || // Комментирует
type.equals("voted"); // Проголосовал в опросе
}
} catch (JSONException e) {
Log.d("checkCaption", "Caption error");
}
}
}
return false;
}
public static JSONArray newsfeedlist(JSONArray items) throws JSONException {
var selectedItems = Preferences.getPreferences().getString("news_feed_selected_items", "");
var filtersSet = Preferences.getPreferences().getStringSet("news_feed_items_set", null);
var mutableFiltersSet = new LinkedHashSet<String>();
if (filtersSet != null)
mutableFiltersSet.addAll(filtersSet);
for (int i = 0; i < items.length(); i++) {
var item = items.optJSONObject(i);
if (item == null) continue;
var id = item.optString("id");
var title = item.optString("title");
if (TextUtils.isEmpty(id) || TextUtils.isEmpty(title)
// these items not working
|| id.equals("kpop") || id.equals("foryou")
|| id.equals("qazaqstan") || id.equals("podcasts"))
continue;
mutableFiltersSet.add(id + "|" + title);
var hide = selectedItems.contains(id);
Log.d("NewsfeedList", "Added list " + id + " to feed");
item.put("is_hidden", hide)
.put("is_unavailable", hide);
Log.d("NewsfeedListInj", "Unlocked " + id + " in newsfeed list");
}
Preferences.getPreferences().edit().putStringSet("news_feed_items_set", mutableFiltersSet).apply();
return items;
}
public static Boolean discoverAdBlock(JSONObject jsonObject) {
if (jsonObject == null) return true;
try {
var type = jsonObject.optString("type");
var post = jsonObject.optJSONObject("post");
if (jsonObject.optString("template").contains("ads") || jsonObject.has("ads")) {
if (dev())
Log.d("NewsfeedAdBlockV2", "Removed post " + (post != null ? post.optInt("post_id") : 0) + " from discover, Reason: ads");
return false;
}
if (isAds(post, type)) {
return false;
}
if (authorsrecomm() && (type.equals("authors_rec")
|| type.startsWith("recommended_") && (type.endsWith("audios")
|| type.endsWith("artists")
|| type.endsWith("playlists")
|| type.endsWith("groups")))) {
if (dev())
Log.d("NewsfeedAdBlockV2", "Removed post " + (post != null ? post.optInt("post_id") : 0) + " from discover, Reason: authorsrecomm");
return false;
}
if (postsrecomm() && (type.equals("inline_user_rec") || type.equals("live_recommended"))) {
if (dev())
Log.d("NewsfeedAdBlockV2", "Removed post " + (post != null ? post.optInt("post_id") : 0) + " from discover, Reason: postsrecomm");
return false;
}
if (friendsrecomm() && (type.equals("user_rec") || type.equals("friends_recomm"))) {
if (dev())
Log.d("NewsfeedAdBlockV2", "Removed post " + (post != null ? post.optInt("post_id") : 0) + " from discover, Reason: friendsrecomm");
return false;
}
if (adsgroup() && (post != null ? post.optInt("marked_as_ads") : 0) == 1 && !isWhitelistedAd(post)) {
if (dev())
Log.d("NewsfeedAdBlockV2", "Removed post " + post.optInt("post_id") + " from discover, Reason: marked_as_ads is true");
return false;
}
if (post != null) {
if (isBadNews(post.optString("text")) && !isWhitelistedFilters(post)) {
if (dev())
Log.d("NewsfeedAdBlockV2", "Removed post " + post.optInt("post_id") + " from discover, Reason: text filters");
return false;
}
if (checkCopyright(post)) {
if (dev())
Log.d("NewsfeedAdBlockV2", "Removed post " + post.optInt("post_id") + " from discover, Reason: copyright filters");
return false;
}
if (checkCaption(post)) {
if (dev())
Log.d("NewsfeedAdBlockV2", "Removed post " + post.optInt("post_id") + " from discover, Reason: caption filters");
return false;
}
if (NewsFeedFiltersUtils.injectFiltersReposts(post) && !isWhitelistedFilters(post)) {
if (dev())
Log.d("NewsfeedAdBlockV2", "Removed post " + post.optInt("post_id") + " from discover, Reason: repost ad");
return false;
}
}
} catch (Exception e) {
Log.d("NewsfeedAdBlockV2", "discover: " + e.getMessage());
}
return true;
}
public static void parseStoriesItem(JSONObject item) throws JSONException {
var stories = item.optJSONArray("stories");
var newStories = new JSONArray();
if (stories == null) return;
for (int j = 0; j < stories.length(); j++) {
var story = stories.optJSONObject(j);
if (!story.optBoolean("is_ads") && !story.optBoolean("is_promo")) {
if (isStoryNotAd(story)) {
newStories.put(story);
}
} else {
if (dev())
Log.d("StoriesAds", "Fetched ad, owner id " + story.optString("owner_id") + ", caption " + story.optString("caption"));
}
}
item.put("stories", newStories);
}
private static Boolean isStoryNotAd(JSONObject json) {
return !getBoolValue("storiesGroupsAdBlock", false) || (json.has("link") ? isWhitelistedAdStories(json) : true);
}
public static Boolean isAds(JSONObject list, String type) {
if (list == null || type == null || !ads()) return false;
if (list.has("ads")
|| type.equals("ads")
|| type.equals("carousel")
|| type.equals("html5_ad")
|| type.equals("ads_easy_promote")) {
if (dev())
Log.d("NewsfeedAdBlockV2", "Removed post " + list.optInt("post_id") + " from feed, Reason: ads");
return true;
}
if (type.equals("promo_button")
|| type.equals("app_widget")
|| type.equals("app_video")
|| type.equals("app_slider")
|| type.equals("tags_suggestions")) {
if (dev())
Log.d("NewsfeedAdBlockV2", "Removed post " + list.optInt("post_id") + " from feed, Reason: promo");
return true;
}
return false;
}
public static Boolean isWhitelistedFilters(JSONObject list) {
var id = String.valueOf(list.optInt("owner_id"));
if (id.equals("0")) {
id = String.valueOf(list.optInt("source_id"));
}
if (id.equals("-189659924") || id.equals(String.valueOf(AccountManagerUtils.getUserId()))) {
return true;
}
var whitelist = Preferences.getPreferences().getStringSet(
"whitelisted_filters_groups",
Collections.emptySet()
);
return Preferences.getBoolValue("invertFilters", false) != whitelist.contains(id);
}
public static Boolean isWhitelistedAd(JSONObject list) {
var id = String.valueOf(list.optInt("owner_id"));
if (id.equals("0")) {
id = String.valueOf(list.optInt("source_id"));
}
var whitelist = Preferences.getPreferences().getStringSet(
"whitelisted_ad_groups",
Collections.emptySet()
);
return whitelist.contains(id);
}
public static Boolean isWhitelistedAdStories(JSONObject list) {
var id = String.valueOf(list.optInt("owner_id"));
var whitelist = Preferences.getPreferences().getStringSet(
"whitelisted_stories_ad",
Collections.emptySet()
);
return whitelist.contains(id);
}
public static Boolean hasMiniAppAds(JSONObject list) {
var attachments = list.optJSONArray("attachments");
if (attachments != null && getBoolValue("blockminiapps", false)) {
for (int j = 0; j < attachments.length(); j++) {
String type = attachments.optJSONObject(j).optString("type");
if (type.contains("mini_app")) return true;
}
}
return false;
}
public static JSONObject discoverInject(JSONObject json) throws JSONException {
var items = json.optJSONArray("items");
var newObj = new JSONArray();
for (int i = 0; i < (items != null ? items.length() : 0); i++) {
try {
JSONObject curr = items.getJSONObject(i);
if (!curr.optString("template").contains("info") && discoverAdBlock(curr)) {
newObj.put(items.optJSONObject(i));
}
} catch (Exception e) {
Log.d("NewsfeedAdBlockV2", "discover: " + e);
}
}
json.put("items", newObj);
return json;
}
public static JSONArray feedInject(JSONArray items) {
if (items.length() == 0) return items;
try {
var newItems = new JSONArray();
for (int j = 0; j < items.length(); j++) {
JSONObject list = items.optJSONObject(j);
if (list == null) continue;
String type = list.optString("type");
if (isAds(list, type)) {
continue;
}
if (authorsrecomm() && (type.equals("authors_rec")
|| type.startsWith("recommended_") && (type.endsWith("audios")
|| type.endsWith("artists")
|| type.endsWith("playlists")
|| type.endsWith("groups")))) {
if (dev())
Log.d("NewsfeedAdBlockV2", "Removed post " + list.optInt("post_id") + " from feed, Reason: authorsrecomm");
continue;
}
if (postsrecomm() && (type.equals("inline_user_rec") || type.equals("live_recommended"))) {
if (dev())
Log.d("NewsfeedAdBlockV2", "Removed post " + list.optInt("post_id") + " from feed, Reason: postsrecomm");
continue;
}
if (friendsrecomm() && (type.equals("user_rec") || type.equals("friends_recomm"))) {
if (dev())
Log.d("NewsfeedAdBlockV2", "Removed post " + list.optInt("post_id") + " from feed, Reason: friendsrecomm");
continue;
}
if (adsgroup() && list.optInt("marked_as_ads") == 1 && !isWhitelistedAd(list)) {
if (dev())
Log.d("NewsfeedAdBlockV2", "Removed post " + list.optInt("post_id") + " from feed, Reason: marked_as_ads is true");
continue;
}
if (isBadNews(list.optString("text")) && !isWhitelistedFilters(list)) {
if (dev())
Log.d("NewsfeedAdBlockV2", "Removed post " + list.optInt("post_id") + " from feed, Reason: text filters");
continue;
}
if (checkCopyright(list)) {
if (dev())
Log.d("NewsfeedAdBlockV2", "Removed post " + list.optInt("post_id") + " from feed, Reason: copyright filters");
continue;
}
if (checkCaption(list)) {
if (dev())
Log.d("NewsfeedAdBlockV2", "Removed post " + list.optInt("post_id") + " from feed, Reason: caption filters");
continue;
}
if (hasMiniAppAds(list) && !isWhitelistedFilters(list)) {
if (dev())
Log.d("NewsfeedAdBlockV2", "Removed post " + list.optInt("post_id") + " from feed, Reason: MiniApp filters");
continue;
}
try {
if (NewsFeedFiltersUtils.injectFiltersReposts(list) && !isWhitelistedFilters(list)) {
if (dev())
Log.d("NewsfeedAdBlockV2", "Removed post " + list.optInt("post_id") + " from feed, Reason: repost ad");
continue;
}
} catch (Exception ex) {
Log.d("RepostInj", ex.getMessage());
}
newItems.put(list);
}
return newItems;
} catch (Exception e) {
Log.d("NewsfeedAdBlockV2", e.getMessage());
}
return items;
}
public static JSONObject storiesads(JSONObject json, boolean isDeleteFix) throws JSONException {
if (!adsstories()) {
return json;
}
if (json.has("ads")) {
JSONObject ad = json.optJSONObject("ads");
if (isDeleteFix) {
if (ad != null) {
ad.optJSONObject("settings")
.put("stories_interval", 0)
.put("authors_interval", 0)
.put("time_interval", 0)
.put("stories_init", 0)
.put("authors_init", 0)
.put("time_init", 0);
}
if (dev()) Log.d("StoriesAds", "Set ads settings at zero values");
} else {
json.remove("ads");
if (dev()) Log.d("StoriesAds", "Removed ads block");
}
}
JSONArray items = json.optJSONArray("items");
if (items != null) {
for (int i = 0; i < items.length(); i++) {
JSONObject item = items.optJSONObject(i);
if (item != null) {
parseStoriesItem(item);
}
}
}
return json;
}
}
@@ -0,0 +1,444 @@
package ru.vtosters.lite.utils.newsfeed;
import android.text.TextUtils;
import android.util.Log;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import ru.vtosters.lite.utils.AccountManagerUtils;
import ru.vtosters.sponsorpost.utils.FiltersPreferences;
import ru.vtosters.sponsorpost.utils.PostsPreferences;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
import java.util.stream.Stream;
import static ru.vtosters.hooks.other.Preferences.*;
import static ru.vtosters.lite.utils.AndroidUtils.sendToast;
public class NewsFeedFiltersUtils {
private static final String[] CUSTOM_FILTERS = {"spamfilters", "sourcenamefilter", "linkfilter"};
private static final String[] EXCLUDED_ITEMS = {"kpop", "foryou", "qazaqstan", "podcasts"};
private static final Set<String> filters = new HashSet<>();
static {
updateFilters();
}
public static void updateFilters() {
filters.clear();
filters.addAll(FiltersPreferences.getFiltersLists());
for (String customFilter : CUSTOM_FILTERS) {
List<String> lists = List.of(getString(customFilter).toLowerCase().split("\\s*,\\s*"));
filters.addAll(lists);
}
}
public static boolean injectFiltersReposts(JSONObject obj) {
if (obj.has("copy_history")) {
JSONArray copyHistoryNode = obj.optJSONArray("copy_history");
if (copyHistoryNode != null && copyHistoryNode.length() != 0) {
return IntStream.range(0, copyHistoryNode.length())
.mapToObj(copyHistoryNode::optJSONObject)
.anyMatch(item -> {
String text = item.optString("text");
String postType = item.optString("post_type");
if (sponsorFilters(text)) {
logRemovedPost(item, "repost", "sponsorpost filters", false);
return true;
} else if (isAds(item, postType)) {
logRemovedPost(item, "repost", "ads", false);
return true;
}
return false;
});
}
}
return false;
}
public static boolean checkCopyright(JSONObject json) throws JSONException {
if (json.has("copyright")) {
if (copyright_post()) return true;
Set<String> list = filters.stream()
.filter(filter -> !filter.isEmpty())
.collect(Collectors.toSet());
if (!list.isEmpty()) {
JSONObject copyRight = json.optJSONObject("copyright");
if (copyRight != null) {
String name = copyRight.getString("name").toLowerCase();
String link = copyRight.getString("link").toLowerCase();
return list.stream().anyMatch(filter -> name.contains(filter.toLowerCase()) || link.contains(filter.toLowerCase()));
}
}
}
return false;
}
public static boolean checkCaption(JSONObject postJson) {
if (postJson.has("caption")) {
if (captions()) return true;
JSONObject caption = postJson.optJSONObject("caption");
if (postsrecomm() && caption != null) {
try {
String type = caption.getString("type");
Set<String> recommTypes = Set.of("explorebait", "shared", "digest", "commented", "voted");
return recommTypes.stream().anyMatch(type::equals);
} catch (JSONException e) {
Log.d("checkCaption", "Caption error");
}
}
}
return false;
}
public static JSONArray setNewsfeedLists(JSONArray items) throws JSONException {
String selectedItems = getPreferences().getString("news_feed_selected_items", "");
Set<String> filtersSet = getPreferences().getStringSet("news_feed_items_set", null);
LinkedHashSet<String> mutableFiltersSet = new LinkedHashSet<>();
if (filtersSet != null) {
mutableFiltersSet.addAll(filtersSet);
}
for (int i = 0; i < items.length(); i++) {
JSONObject item = items.optJSONObject(i);
if (item == null) {
continue;
}
String id = item.optString("id");
String title = item.optString("title");
if (TextUtils.isEmpty(id) || TextUtils.isEmpty(title) || isExcluded(id)) {
continue;
}
mutableFiltersSet.add(id + "|" + title);
boolean hide = selectedItems.contains(id);
Log.d("NewsfeedList", "Added list " + id + " to feed");
item.put("is_hidden", hide).put("is_unavailable", hide);
}
getPreferences().edit().putStringSet("news_feed_items_set", mutableFiltersSet).apply();
return items;
}
private static boolean isExcluded(String id) {
return Arrays.asList(EXCLUDED_ITEMS).contains(id);
}
public static Boolean discoverAdBlock(JSONObject jsonObject) {
if (jsonObject == null) return true;
try {
JSONObject post = jsonObject.optJSONObject("post");
boolean hasAds = jsonObject.optString("template").contains("ads");
boolean hasInfo = jsonObject.optString("template").contains("info");
if (hasAds || hasInfo || post == null) {
Log.d("NewsfeedAdBlockV2", "Removed " + (hasAds ? "ads" : "info") + " template in discover");
return false;
}
return needToSave(post, "discover", false);
} catch (Exception e) {
Log.d("NewsfeedAdBlockV2", "discover crash: " + e.getMessage());
}
return true;
}
public static JSONObject discoverInject(JSONObject json) throws JSONException {
JSONArray items = json.optJSONArray("items");
JSONArray newObj = new JSONArray();
for (int i = 0; i < (items != null ? items.length() : 0); i++) {
try {
JSONObject curr = items.getJSONObject(i);
if (discoverAdBlock(curr)) {
newObj.put(items.optJSONObject(i));
}
} catch (Exception e) {
Log.d("NewsfeedAdBlockV2", "discover: " + e);
}
}
json.put("items", newObj);
return json;
}
private static boolean needToSave(JSONObject post, String source, boolean needToShowToast) throws JSONException {
String type = post.optString("type");
if (isAds(post, type)) {
return false;
}
if (authorsrecomm() && (type.equals("authors_rec")
|| type.startsWith("recommended_") && (type.endsWith("audios")
|| type.endsWith("artists")
|| type.endsWith("playlists")
|| type.endsWith("groups")))) {
logRemovedPost(post, source, "authors", needToShowToast);
return false;
}
if (postsrecomm() && (type.equals("inline_user_rec") || type.equals("live_recommended"))) {
logRemovedPost(post, source, "postsrecomm", needToShowToast);
return false;
}
if (friendsrecomm() && (type.equals("user_rec") || type.equals("friends_recomm"))) {
logRemovedPost(post, source, "friendsrecomm", needToShowToast);
return false;
}
if (adsgroup() && post.optInt("marked_as_ads") == 1 && !isWhitelistedAd(post)) {
logRemovedPost(post, source, "marked_as_ads", needToShowToast);
return false;
}
if (PostsPreferences.isPostAd(getOwnerId(post), getPostId(post)) && !isWhitelistedAd(post)) {
logRemovedPost(post, source, "sponsorpost", needToShowToast);
return false;
}
if (sponsorFilters(post.optString("text")) && !isWhitelistedFilters(post)) {
logRemovedPost(post, source, "sponsorpost filter", needToShowToast);
return false;
}
if (checkCopyright(post)) {
logRemovedPost(post, source, "copyright filters", needToShowToast);
return false;
}
if (checkCaption(post)) {
logRemovedPost(post, source, "caption filters", needToShowToast);
return false;
}
if (hasMiniAppAds(post) && !isWhitelistedFilters(post)) {
logRemovedPost(post, source, "miniapps ban", needToShowToast);
return false;
}
if (NewsFeedFiltersUtils.injectFiltersReposts(post) && !isWhitelistedFilters(post)) {
logRemovedPost(post, source, "repost ad", needToShowToast);
return false;
}
return true;
}
public static JSONArray feedInject(JSONArray items, boolean needToShowToast) {
if (items.length() == 0) return items;
Stream<JSONObject> stream = IntStream.range(0, items.length())
.mapToObj(items::optJSONObject);
List<JSONObject> list = stream.filter(post -> {
try {
return post != null && needToSave(post, "feed", needToShowToast);
} catch (JSONException e) {
throw new RuntimeException(e);
}
})
.collect(Collectors.toList());
return new JSONArray(list);
}
private static void logRemovedPost(JSONObject json, String source, String reason, boolean needToShowToast) {
Log.d("NewsfeedAdBlockV2", "Removed post " + getPostId(json) + ", owner: " + getOwnerId(json) + " from " + source + ", Reason: " + reason);
if (needToShowToast) sendToast("Пост " + getOwnerId(json) + "_" + getPostId(json) + " заблокирован по причине: " + reason);
}
public static boolean sponsorFilters(String text) {
String textInLowerCase = text.toLowerCase();
Set<String> list = filters.stream()
.filter(adword -> !adword.isEmpty())
.collect(Collectors.toSet());
if (!list.isEmpty()) {
return list.stream().anyMatch(adword -> {
if (textInLowerCase.contains(adword.toLowerCase())) {
if (dev()) {
Log.d("NewsfeedAdBlockV2", text);
Log.d("NewsfeedAdBlockV2", "Block word: " + adword);
}
return true;
}
return false;
});
}
return false;
}
public static void parseStoriesItem(JSONObject item) throws JSONException {
JSONArray stories = item.optJSONArray("stories");
JSONArray newStories = new JSONArray();
if (stories == null) return;
for (int j = 0; j < stories.length(); j++) {
JSONObject story = stories.optJSONObject(j);
if (!story.optBoolean("is_ads") && !story.optBoolean("is_promo")) {
if (checkStoriesButtonLinks(story)) {
newStories.put(story);
}
} else {
Log.d("NewsfeedAdBlockV2", "Fetched stories ad, owner id " + story.optString("owner_id") + ", caption " + story.optString("caption"));
}
}
item.put("stories", newStories);
}
private static Boolean checkStoriesButtonLinks(JSONObject json) {
return !getBoolValue("storiesGroupsAdBlock", false) || (json.has("link") ? isWhitelistedAdStories(json) : true);
}
public static Boolean isAds(JSONObject list, String type) {
if (list == null || type == null || !ads()) return false;
Set<String> adsTypes = Set.of("ads", "carousel", "html5_ad", "ads_easy_promote");
Set<String> promoTypes = Set.of("promo_button", "app_widget", "app_video", "app_slider", "tags_suggestions");
if (list.has("ads") || adsTypes.stream().anyMatch(type::equals)) {
logRemovedPost(list, "feed", "ads", false);
return true;
}
if (promoTypes.stream().anyMatch(type::equals)) {
logRemovedPost(list, "feed", "promo", false);
return true;
}
return false;
}
private static int getOwnerId(JSONObject post) {
return post.optInt("owner_id") != 0 ? post.optInt("owner_id") : post.optInt("source_id");
}
private static int getPostId(JSONObject post) {
return post.optInt("post_id") != 0 ? post.optInt("post_id") : post.optInt("id");
}
public static Boolean isWhitelistedFilters(JSONObject list) {
String id = String.valueOf(getOwnerId(list));
if (id.equals("-189659924") || id.equals(String.valueOf(AccountManagerUtils.getUserId()))) {
return true;
}
Set<String> whitelist = getPreferences().getStringSet(
"whitelisted_filters_groups",
Collections.emptySet()
);
return getBoolValue("invertFilters", false) != whitelist.contains(id);
}
public static Boolean isWhitelistedAd(JSONObject list) {
String id = String.valueOf(getOwnerId(list));
Set<String> whitelist = getPreferences().getStringSet(
"whitelisted_ad_groups",
Collections.emptySet()
);
return whitelist.contains(id);
}
public static Boolean isWhitelistedAdStories(JSONObject list) {
String id = String.valueOf(getOwnerId(list));
Set<String> whitelist = getPreferences().getStringSet(
"whitelisted_stories_ad",
Collections.emptySet()
);
return whitelist.contains(id);
}
public static Boolean hasMiniAppAds(JSONObject list) {
JSONArray attachments = list.optJSONArray("attachments");
if (attachments != null && getBoolValue("blockminiapps", false)) {
return IntStream.range(0, attachments.length())
.mapToObj(attachments::optJSONObject)
.anyMatch(attachment -> attachment.optString("type").contains("mini_app"));
}
return false;
}
public static JSONObject storiesAds(JSONObject json, boolean isDeleteFix) {
if (!adsstories()) {
return json;
}
if (json.has("ads")) {
if (isDeleteFix) {
try {
resetAdsSettings(json.getJSONObject("ads"));
Log.d("NewsfeedAdBlockV2", "Set stories ads settings at zero values");
} catch (JSONException e) {
e.getStackTrace();
}
} else {
json.remove("ads");
Log.d("NewsfeedAdBlockV2", "Removed stories ads block");
}
}
try {
parseItemsStories(json.getJSONArray("items"));
} catch (JSONException e) {
e.getStackTrace();
}
return json;
}
private static void parseItemsStories(JSONArray items) throws JSONException {
for (int i = 0; i < items.length(); i++) {
parseStoriesItem(items.getJSONObject(i));
}
}
public static void resetAdsSettings(JSONObject ad) throws JSONException {
ad.getJSONObject("settings")
.put("stories_interval", 0)
.put("authors_interval", 0)
.put("time_interval", 0)
.put("stories_init", 0)
.put("authors_init", 0)
.put("time_init", 0);
}
}
@@ -0,0 +1,70 @@
package ru.vtosters.sponsorpost.data;
import org.json.JSONException;
import org.json.JSONObject;
public class Filter {
int id;
String title;
String summary;
String version;
String link;
public Filter(int id, String title, String summary, String version, String link) {
this.id = id;
this.title = title;
this.summary = summary;
this.version = version;
this.link = link;
}
public Filter(JSONObject jsonObject) throws NullPointerException, JSONException {
this(
jsonObject.getInt("id"),
jsonObject.getString("title"),
jsonObject.getString("summary"),
jsonObject.getString("version"),
jsonObject.getString("link")
);
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getSummary() {
return summary;
}
public void setSummary(String summary) {
this.summary = summary;
}
public String getVersion() {
return version;
}
public void setVersion(String version) {
this.version = version;
}
public String getLink() {
return link;
}
public void setLink(String link) {
this.link = link;
}
}
@@ -0,0 +1,59 @@
package ru.vtosters.sponsorpost.data;
import org.json.JSONException;
import org.json.JSONObject;
public class Post {
long postId;
long ownerId;
long postDate;
long postAdded;
public Post(long postId, long ownerId, long postDate, long postAdded) {
this.postId = postId;
this.ownerId = ownerId;
this.postDate = postDate;
this.postAdded = postAdded;
}
public Post(JSONObject jsonObject) throws NullPointerException, JSONException {
this(
jsonObject.getLong("postId"),
jsonObject.getLong("ownerId"),
jsonObject.getLong("postDate"),
jsonObject.getLong("postAdded")
);
}
public long getPostId() {
return postId;
}
public void setPostId(long postId) {
this.postId = postId;
}
public long getOwnerId() {
return ownerId;
}
public void setOwnerId(long ownerId) {
this.ownerId = ownerId;
}
public long getPostDate() {
return postDate;
}
public void setPostDate(long postDate) {
this.postDate = postDate;
}
public long getPostAdded() {
return postAdded;
}
public void setPostAdded(long postAdded) {
this.postAdded = postAdded;
}
}
@@ -0,0 +1,108 @@
package ru.vtosters.sponsorpost.services;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
import org.json.JSONArray;
import org.json.JSONException;
import ru.vtosters.lite.di.singleton.VtOkHttpClient;
import ru.vtosters.sponsorpost.data.Filter;
import ru.vtosters.sponsorpost.utils.ApiUtils;
import ru.vtosters.sponsorpost.utils.FiltersPreferences;
import ru.vtosters.sponsorpost.utils.GzipDecompressor;
import java.io.IOException;
import java.util.Arrays;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
public class FilterService {
private static final OkHttpClient client = VtOkHttpClient.getInstance();
public static List<Filter> getFilters(List<Integer> ids) {
// Retrieves a list of filters
// Construct the API request URL
String requestUrl = ApiUtils.getURL() + "/lists/get";
if (ids != null && !ids.isEmpty()) requestUrl = requestUrl + "?ids=" + ids.stream()
.map(Object::toString)
.collect(Collectors.joining(","));
// for filters updates
// Create a GET request to the API endpoint
Request request = new Request.a()
.b(requestUrl)
.a("Content-Type", "application/json")
.a("Accept-Encoding", "gzip")
.a();
try (Response response = client.a(request).execute()) {
// Check if the response is successful
if (response.h()) {
// Determine the response encoding
String encoding = response.a("Content-Encoding");
String resp;
if (encoding != null && encoding.equals("gzip")) {
// Decompress the response body
resp = GzipDecompressor.decompress(response.a().b());
} else {
// Retrieve the response body directly
resp = response.a().g();
}
// Parse the response body as a JSONArray and extract filter objects
return parseJSON(new JSONArray(resp));
} else {
if (!FiltersPreferences.getAllFilterIds().isEmpty()) {
return FiltersPreferences.getAllDownloadedFilters(); // check for offline server to get local filters
} else {
throw new RuntimeException("Failed to get filters: " + response.l());
}
}
} catch (IOException | JSONException e) {
if (!FiltersPreferences.getAllFilterIds().isEmpty()) {
return FiltersPreferences.getAllDownloadedFilters(); // check for offline server to get local filters
} else {
throw new RuntimeException(e);
}
}
}
public static Set<String> downloadFilter(String link) {
Request request = new Request.a()
.b(link)
.a();
try (Response response = client.a(request).execute()) {
if (response.h()) {
return stringToSet(response.a().g());
} else {
throw new RuntimeException("Failed to download filter: " + response.l());
}
} catch (IOException e) {
throw new RuntimeException(e);
}
}
public static Set<String> stringToSet(String input) {
return Arrays.stream(input.split("\n"))
.map(String::toLowerCase)
.collect(Collectors.toSet());
}
private static List<Filter> parseJSON(JSONArray jsonArray) throws JSONException {
return IntStream.range(0, jsonArray.length())
.mapToObj(i -> {
try {
return new Filter(jsonArray.getJSONObject(i));
} catch (JSONException e) {
throw new RuntimeException(e);
}
})
.collect(Collectors.toList());
}
}
@@ -0,0 +1,241 @@
package ru.vtosters.sponsorpost.services;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
import org.json.JSONArray;
import org.json.JSONException;
import ru.vtosters.sponsorpost.data.Post;
import ru.vtosters.sponsorpost.utils.ApiUtils;
import ru.vtosters.sponsorpost.utils.GzipDecompressor;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
public class PostService {
private static final OkHttpClient client = new OkHttpClient();
private static final String apiPath = ApiUtils.getURL() + "/posts";
public static List<Post> getPosts(Long date) {
String getFromDate;
// Get posts older than the specified date (if positive) or all posts (if zero or negative or empty)
if (date > 0) {
getFromDate = ("?date=" + date);
} else {
// No date parameter for retrieving all posts
getFromDate = "";
}
Request request = new Request.a()
.b(apiPath + "/get" + getFromDate)
.a("Content-Type", "application/json")
.a("Accept-Encoding", "gzip")
.a();
try (Response response = client.a(request).execute()) {
// Check if the response is successful
if (response.h()) {
// Determine the response encoding
String encoding = response.a("Content-Encoding");
// Handle GZIP-compressed responses
if (encoding != null && encoding.equals("gzip")) {
// Decompress the response body and parse JSON data
return parseJSONPosts(new JSONArray(GzipDecompressor.decompress(response.a().b())));
} else {
// Parse JSON data from the response body
return parseJSONPosts(new JSONArray(response.a().g()));
}
} else {
// Handle error response
throw new RuntimeException("Failed to get posts: " + response.l());
}
} catch (IOException | JSONException e) {
// Handle exceptions
throw new RuntimeException(e);
}
}
public static boolean isPostAd(long ownerId, long postId) {
// Checks if a specified post is an advertisement
// Merge into one post info
String post = ownerId + "_" + postId;
// Construct the API request URL
String requestUrl = apiPath + "/isPostAdvert?post=" + post;
// Create a GET request to the API endpoint
Request request = new Request.a()
.b(requestUrl)
.a("Content-Type", "application/json")
.a();
try (Response response = client.a(request).execute()) {
// Check if the response is successful
if (response.h()) {
// Determine the response encoding
String encoding = response.a("Content-Encoding");
String resp;
if (encoding != null && encoding.equals("gzip")) {
// Decompress the response body
resp = GzipDecompressor.decompress(response.a().b());
} else {
// Retrieve the response body directly
resp = response.a().g();
}
// Extract the boolean value indicating whether the post is an ad
return Boolean.parseBoolean(resp);
} else {
// Handle error response
throw new RuntimeException("Failed to check post for ad status: " + response.l());
}
} catch (IOException e) {
throw new RuntimeException(e);
}
}
public static List<String> getAllPostsIds() {
// Create a GET request for retrieving all post IDs
Request request = new Request.a()
.b(apiPath + "/getAllPostIds")
.a("Content-Type", "application/json")
.a("Accept-Encoding", "gzip")
.a();
try (Response response = client.a(request).execute()) {
// Check if the response is successful
if (response.h()) {
// Determine the response encoding
String encoding = response.a("Content-Encoding");
// Handle GZIP-compressed responses
if (encoding != null && encoding.equals("gzip")) {
// Decompress the response body and extract the first element as a list of post IDs
return new ArrayList<>(Collections.singleton(GzipDecompressor.decompress(response.a().b())));
} else {
// Extract the first element as a list of post IDs
return new ArrayList<>(Collections.singleton(response.a().g()));
}
} else {
// Handle error response
throw new RuntimeException("Failed to get posts IDs: " + response.l());
}
} catch (IOException e) {
// Handle exceptions
throw new RuntimeException(e);
}
}
public static List<Long> getPostIdsByOwnerId(Long ownerId, Long date) {
// Retrieve post IDs for a specific owner and date
// If date is positive, get posts older than the specified date
// Otherwise, get all posts for the owner
String getFromDate = date > 0 ? ("?date=" + date) : "";
// Construct the API request URL
String requestUrl = apiPath + "/getPostIdsByOwnerId" + "?ownerId=" + ownerId + getFromDate;
// Create a GET request to the API endpoint
Request request = new Request.a()
.b(requestUrl)
.a("Content-Type", "application/json")
.a("Accept-Encoding", "gzip")
.a();
try (Response response = client.a(request).execute()) {
// Check if the response is successful
if (response.h()) {
// Determine the response encoding
String encoding = response.a("Content-Encoding");
String resp;
if (encoding != null && encoding.equals("gzip")) {
// Decompress the response body
resp = GzipDecompressor.decompress(response.a().b());
} else {
// Retrieve the response body directly
resp = response.a().g();
}
// Parse the response body as a JSONArray and extract post IDs
return parseJSONIds(new JSONArray(resp));
} else {
// Handle error response
throw new RuntimeException("Failed to get postIdsByOwnerId: " + response.l());
}
} catch (IOException | JSONException e) {
// Handle exceptions
throw new RuntimeException(e);
}
}
public static List<Long> getOwnerIds() {
// Retrieves a list of owner IDs with ad posts
// Construct the API request URL
String requestUrl = apiPath + "/getOwnerIds";
// Create a GET request to the API endpoint
Request request = new Request.a()
.b(requestUrl)
.a("Content-Type", "application/json")
.a("Accept-Encoding", "gzip")
.a();
try (Response response = client.a(request).execute()) {
// Check if the response is successful
if (response.h()) {
// Determine the response encoding
String encoding = response.a("Content-Encoding");
String resp;
if (encoding != null && encoding.equals("gzip")) {
// Decompress the response body
resp = GzipDecompressor.decompress(response.a().b());
} else {
// Retrieve the response body directly
resp = response.a().g();
}
// Parse the response body as a JSONArray and extract owner IDs
return parseJSONIds(new JSONArray(resp));
} else {
// Handle error response
throw new RuntimeException("Failed to get ownersIds: " + response.l());
}
} catch (IOException | JSONException e) {
throw new RuntimeException(e);
}
}
private static List<Long> parseJSONIds(JSONArray jsonArray) {
return IntStream.range(0, jsonArray.length())
.mapToObj(index -> {
try {
return jsonArray.getLong(index);
} catch (JSONException e) {
throw new RuntimeException(e);
}
})
.collect(Collectors.toList());
}
private static List<Post> parseJSONPosts(JSONArray jsonArray) throws JSONException {
return IntStream.range(0, jsonArray.length())
.mapToObj(i -> {
try {
return new Post(jsonArray.getJSONObject(i));
} catch (JSONException e) {
throw new RuntimeException(e);
}
})
.collect(Collectors.toList());
}
}
@@ -0,0 +1,7 @@
package ru.vtosters.sponsorpost.utils;
public class ApiUtils {
public static String getURL() {
return "https://adlist.vtosters.app/v1";
}
}
@@ -0,0 +1,114 @@
package ru.vtosters.sponsorpost.utils;
import android.content.Context;
import android.content.SharedPreferences;
import ru.vtosters.lite.concurrent.VTExecutors;
import ru.vtosters.lite.utils.AndroidUtils;
import ru.vtosters.lite.utils.newsfeed.NewsFeedFiltersUtils;
import ru.vtosters.sponsorpost.data.Filter;
import ru.vtosters.sponsorpost.services.FilterService;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
public class FiltersPreferences {
private static final String PREF_KEY_ID = "id";
private static final String PREF_KEY_TITLE = "title";
private static final String PREF_KEY_SUMMARY = "summary";
private static final String PREF_KEY_VERSION = "version";
private static final String PREF_KEY_LINK = "link";
private static final String PREF_KEY_LIST = "list";
private static final SharedPreferences preferences;
static {
preferences = getPreferences();
}
private static SharedPreferences getPreferences() {
return AndroidUtils.getGlobalContext().getSharedPreferences("ru.vtosters.sponsorpost.filters.prefs", Context.MODE_PRIVATE);
}
public static void clearAll() {
preferences.edit().clear().apply();
}
public static boolean getSavedKeyValue(int id) {
return getFilter(id) != null;
}
public static void saveFilter(Filter filter) {
SharedPreferences.Editor editor = preferences.edit();
editor.putInt(getPrefKey(filter.getId(), PREF_KEY_ID), filter.getId());
editor.putString(getPrefKey(filter.getId(), PREF_KEY_TITLE), filter.getTitle());
editor.putString(getPrefKey(filter.getId(), PREF_KEY_SUMMARY), filter.getSummary());
editor.putString(getPrefKey(filter.getId(), PREF_KEY_VERSION), filter.getVersion());
editor.putString(getPrefKey(filter.getId(), PREF_KEY_LINK), filter.getLink());
editor.apply();
VTExecutors.getSlowTasksScheduler().a(() -> {
downloadFilter(filter);
NewsFeedFiltersUtils.updateFilters();
});
}
public static void downloadFilter(Filter filter) {
Set<String> list = FilterService.downloadFilter(filter.getLink());
preferences.edit()
.putStringSet("filter:" + filter.getId() + ":" + PREF_KEY_LIST, list)
.apply();
}
public static Set<String> getFiltersLists() {
return getAllFilterIds().stream()
.flatMap(id -> preferences.getStringSet(getPrefKey(id, PREF_KEY_LIST), new HashSet<>()).stream())
.collect(Collectors.toSet());
}
public static List<Filter> getAllDownloadedFilters() {
return getAllFilterIds().stream()
.map(FiltersPreferences::getFilter)
.collect(Collectors.toList());
}
public static Filter getFilter(int id) {
int filterId = preferences.getInt(getPrefKey(id, PREF_KEY_ID), -1);
if (filterId == -1) {
return null;
}
String title = preferences.getString(getPrefKey(id, PREF_KEY_TITLE), "");
String summary = preferences.getString(getPrefKey(id, PREF_KEY_SUMMARY), "");
String version = preferences.getString(getPrefKey(id, PREF_KEY_VERSION), "");
String link = preferences.getString(getPrefKey(id, PREF_KEY_LINK), "");
return new Filter(filterId, title, summary, version, link);
}
private static String getPrefKey(int id, String key) {
return "filter:" + id + ":" + key;
}
public static void deleteFilter(int id) {
SharedPreferences.Editor editor = preferences.edit();
preferences.getAll().keySet().stream()
.filter(key -> key.startsWith("filter:" + id + ":"))
.forEach(editor::remove);
editor.apply();
NewsFeedFiltersUtils.updateFilters();
}
public static List<Integer> getAllFilterIds() {
return preferences.getAll().entrySet().stream()
.filter(entry -> entry.getKey().matches("filter:.*:id"))
.map(entry -> (Integer) entry.getValue())
.collect(Collectors.toList());
}
}
@@ -0,0 +1,29 @@
package ru.vtosters.sponsorpost.utils;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.zip.GZIPInputStream;
public class GzipDecompressor {
public static String decompress(byte[] compressedData) {
if (compressedData == null || compressedData.length == 0) {
throw new IllegalArgumentException("Input compressedData cannot be null or empty");
}
try (GZIPInputStream gzipInputStream = new GZIPInputStream(new ByteArrayInputStream(compressedData));
ByteArrayOutputStream outputStream = new ByteArrayOutputStream()) {
byte[] buffer = new byte[1024];
int bytesRead;
while ((bytesRead = gzipInputStream.read(buffer)) != -1) {
outputStream.write(buffer, 0, bytesRead);
}
return outputStream.toString();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
@@ -0,0 +1,94 @@
package ru.vtosters.sponsorpost.utils;
import android.content.Context;
import android.content.SharedPreferences;
import android.util.Log;
import ru.vtosters.lite.utils.AndroidUtils;
import ru.vtosters.sponsorpost.data.Post;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
public class PostsPreferences {
private static final SharedPreferences preferences;
static {
preferences = getPreferences();
}
private static SharedPreferences getPreferences() {
return AndroidUtils.getGlobalContext().getSharedPreferences("ru.vtosters.sponsorpost.posts.prefs", Context.MODE_PRIVATE);
}
public static boolean isEnabled() {
return preferences.getBoolean("sponsorpost", true);
}
public static void setEnabled(boolean status) {
preferences.edit().putBoolean("sponsorpost", status).apply();
}
public static void savePosts(List<Post> posts) {
Set<String> stringSet = posts.stream()
.map(post -> post.getOwnerId() + "_" + post.getPostId())
.collect(Collectors.toSet());
preferences.edit()
.putStringSet("posts", stringSet)
.apply();
}
public static void saveGroupSpecifiedPosts(List<Long> postsIds, Long ownerId) {
Set<String> stringSet = postsIds.stream()
.map(post -> ownerId + "_" + post)
.collect(Collectors.toSet());
preferences.edit()
.putStringSet(ownerId + "_posts", stringSet)
.apply();
}
public static void saveGroupsIds(List<Long> ids) {
Set<String> stringSet = ids.stream().map(String::valueOf).collect(Collectors.toSet());
preferences.edit()
.putStringSet("groupIds", stringSet)
.apply();
}
public static void saveAdPostInfo(long ownerId, long postId) {
Set<String> currentStringSet = preferences.getStringSet("posts", new HashSet<>());
Set<String> newStringSet = new HashSet<>(currentStringSet);
newStringSet.add(ownerId + "_" + postId);
Log.d("SponsorPost", ownerId + "_" + postId);
preferences.edit()
.putStringSet("posts", newStringSet)
.apply();
}
public static boolean isGroupAd(long ownerId) {
Set<String> isGroupAd = preferences.getStringSet("groupIds", new HashSet<>());
if (!isGroupAd.isEmpty() && isEnabled()) {
return isGroupAd.contains(Long.toString(ownerId));
} else {
return false;
}
}
public static boolean isPostAd(long ownerId, long postId) {
if (isEnabled() && isGroupAd(ownerId)) {
Set<String> hasSpecifiedGroupPosts = preferences.getStringSet(ownerId + "_posts", new HashSet<>());
Set<String> hasPost = preferences.getStringSet("posts", new HashSet<>());
return hasPost.contains(ownerId + "_" + postId) || hasSpecifiedGroupPosts.contains(ownerId + "_" + postId);
} else {
return false;
}
}
}
@@ -0,0 +1,71 @@
package ru.vtosters.sponsorpost.utils;
import ru.vtosters.hooks.other.Preferences;
import ru.vtosters.lite.utils.NetworkUtils;
import ru.vtosters.sponsorpost.data.Filter;
import ru.vtosters.sponsorpost.data.Post;
import ru.vtosters.sponsorpost.services.FilterService;
import ru.vtosters.sponsorpost.services.PostService;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.TimeUnit;
public class Updates {
public static void updateFilters() {
List<Integer> savedFilterIds = FiltersPreferences.getAllFilterIds();
if (savedFilterIds.isEmpty() || Preferences.serverFeaturesDisable()) {
return;
}
List<Filter> filters = FilterService.getFilters(savedFilterIds);
List<Filter> localFilters = FiltersPreferences.getAllDownloadedFilters();
if (!filters.isEmpty()) {
FiltersPreferences.clearAll(); // removes deleted filters from server
for (Filter filter : filters) {
Filter localFilter = findLocalFilterById(localFilters, filter.getId());
if (localFilter == null) {
FiltersPreferences.saveFilter(filter);
} else {
String remoteVersion = filter.getVersion();
String localVersion = localFilter.getVersion();
if (Objects.equals(remoteVersion, localVersion)) {
FiltersPreferences.saveFilter(filter);
} else {
FiltersPreferences.saveFilter(localFilter);
}
}
}
}
}
private static Filter findLocalFilterById(List<Filter> localFilters, int id) {
for (Filter filter : localFilters) {
if (filter.getId() == id) {
return filter;
}
}
return null;
}
public static void updatePosts() {
long currentTime = System.currentTimeMillis();
long weekAgo = currentTime - TimeUnit.DAYS.toMillis(7);
if (PostsPreferences.isEnabled() && !Preferences.serverFeaturesDisable() && NetworkUtils.isNetworkConnected()) {
List<Post> posts = PostService.getPosts(weekAgo);
List<Long> groupIds = PostService.getOwnerIds();
if (!posts.isEmpty()) {
PostsPreferences.savePosts(posts);
}
if (!groupIds.isEmpty()) {
PostsPreferences.saveGroupsIds(groupIds);
}
}
}
}
-14
View File
@@ -1,14 +0,0 @@
appscent
//t.me/
vk.com
vk.ru
apps-cent
app-cent
appcent
?ref=
bitmain
cents-apps
cent-app
centapp
/?a=
minerx
-189
View File
@@ -1,189 +0,0 @@
Путин
Путин
Путину
Путину
Путина
Путина
Путинская
путинская
Байден
байден
Байдену
байдену
Обама
обама
Обаме
обаме
Обаму
обаму
Трамп
трамп
Трампу
трампу
Санкции
санкции
Санкций
санкций
Санкциями
санкциями
Россия
россия
россии
России
МИДУ РФ
миду рф
МИД РФ
мид рф
Мид РФ
Мид рф
Российской
российской
Украина
украина
Украине
украине
Украины
украины
военные
Военные
Специальная операция
Специальная Операция
специальная операция
специальная Операция
Спец. Операция
Спец. операция
спец. Операция
Спец Операция
спец операция
Спец операция
Военная операция
Военная Операция
военная Операция
военная операция
спецоперация
Спецоперация
спецоперации
Спецоперации
спецоперацию
Спецоперацию
вторжение
Вторжение
ЛНР
лнр
ДНР
днр
Донбасс
донбасс
Луганск
луганск
Луганская
луганская
Донецк
донецк
Донецкая
донецкая
Навальным
навальным
Навальный
навальный
Навального
навального
ВСУ
всу
ВС РФ
вс рф
ВС Украины
вс украины
Шойгу
шойгу
Зеленский
зеленский
Зеленским
зеленским
Зеленскому
зеленскому
Зеленского
зеленского
евросоюз
Евросоюз
евросоюзу
Евросоюзу
Войск
войск
армия
Армия
Войне
войне
войны
Войны
войн
Войн
солдат
Солдат
солдаты
Солдаты
Вооруженные
вооруженные
нато
НАТО
Нато
Песков
песков
Пескову
Пескова
пескова
пескову
Кремль
кремль
Кремлю
кремлю
денацификация
Денацификация
денацификацию
Денацификацию
нацис
Нацис
нациз
Нациз
Медведев
медведев
денацифицировать
Денацифицировать
фашис
Фашис
фашиз
Фашиз
США
сша
Киев
киев
Харьков
харьков
Харьковская
харьковская
«Z»
«V»
"з"
"в"
«з»
«в»
«z»
«v»
"З"
"В"
«З»
«В»
русня
Русня
хохол
Хохол
Хохлы
хохлы
ЛДНР
лднр
наказать Россию
наказать россию
наказать Русских
наказать русских
вооружение
Вооружение
-29
View File
@@ -1,29 +0,0 @@
bit.ly
gg.gg
clck.ru
cutt.ly
goo.su
goo.gl
t1p.de
Is.gd
ow.ly
bit.do
su.pr
mcaf.ee
cutt.us
bitly
okl.it
tinyurl
to.click
u.to
bc.vc
porl.me
bl.inc
utka.su
ccly.xyz
profile.me
prfl.me
adf.ly
shorturl.at
rb.gy
gestyy.com
-12
View File
@@ -1,12 +0,0 @@
ali.pub
alii.pub
lite.al
lite.bz
aliclick
dea.ls
prfl.me
go9.ru
s.click.aliexpress.com
ali.ski
fas.st
shp.pub
-100
View File
@@ -1,100 +0,0 @@
успей заказать
Успей заказать
антикризисная цена
элитные часы
стильные часы
cпocоб зaрaбoтать
цена всего
оформи кредит
Оформи кредит
успей купить
Успей купить
#реклама
#спонсор
#партнёр
#партнер
#промо
#promo
КЭШБЭК КАРТОЙ
Оформите карту
Партнёрский материал
партнёрский материал
Партнерский материал
партнёрский материал
Партнёрский пост
партнёрский пост
Партнерский пост
партнёрский пост
партнёрский_материал
партнёрский_материал
партнёрский_пост
партнёрский_пост
рекламный
Рекламный
смотри в источнике
Смотри в источнике
смотри в Источнике
Смотри в Источнике
в источнике👇
в источнике😳👇
в Источник
в источник
В источник
в источнике
в иcтoчнике
В иcтoчнике
в Иcтoчнике
в Источнике
В Источнике
в иcтoчник
В иcтoчник
в Иcтoчник
в Источник
В Источник
в закрепленном комментарии
в Закрепленном комментарии
в закрепленном Комментарии
В закрепленном комментарии
В Закрепленном комментарии
В закрепленном Комментарии
в комментариях
Успей подать заявку
Успей Подать Заявку
Успей подать Заявку
успей Подать Заявку
успей подать заявку
успей Подать заявку
ПОСМОТРЕТЬ ФУЛЛ
ПОСМОТРЕТЬ ИСТОЧНИК
посмотреть фулл
посмотреть источник
ТЫК 👉
тык 👉
ТЫК👉
тык👉
Успей подписаться
успей подписаться
успей Подписаться
Успей Подписаться
Смотри источник
Смотри Источник
смотри источник
Смотри ист
скорее подписывайся
cкорее подписывайся
пиши боту
ПИШИ БОТУ
Вступай скорее
Подписывайся на нас
Подписывайся скорее
Подписывайся cкорее
Промокоды сливают сами сотрудники заведений
Промокоды сливают сотрудники
напиши Нашему боту
пиши Нашему боту
Подписывайтесь👇
Подписывайся👇
ссылка в комментариях
👉https://
👉http://
Ссылка удалится через часов
+1 -1
View File
@@ -235,7 +235,7 @@
android:key="others"
android:title="@string/debug_other">
<com.vtosters.lite.ui.MaterialSwitchPreference
android:defaultValue="false"
android:defaultValue="true"
android:key="__dbg_no_ads"
android:title="@string/debug_no_ads_title"/>
<com.vtosters.lite.ui.MaterialSwitchPreference
+19 -41
View File
@@ -11,6 +11,9 @@
android:key="adsgroup"
android:summary="@string/vtldgadssummary"
android:title="@string/vtldgads"/>
<Preference
android:key="sponsorpost"
android:title="Настройки SponsorPost"/>
<Preference
android:key="whitelisted_ad_groups"
android:title="@string/whitelisted_ad_groups_title"/>
@@ -61,31 +64,6 @@
android:defaultValue=""
android:key="spamfilters"
android:title="@string/vtlownfilter"/>
<com.vtosters.lite.ui.MaterialSwitchPreference
android:defaultValue="false"
android:key="default_ad_list"
android:summary="@string/vtlsfiltersummary"
android:title="@string/vtlsfilter"/>
<com.vtosters.lite.ui.MaterialSwitchPreference
android:defaultValue="false"
android:key="shortlinkfilter"
android:summary="@string/vtlsfiltershortsummary"
android:title="@string/vtlsfiltershort"/>
<com.vtosters.lite.ui.MaterialSwitchPreference
android:defaultValue="false"
android:key="refsfilter"
android:summary="@string/vtlsfilterrefssummary"
android:title="@string/vtlsfilterrefs"/>
<com.vtosters.lite.ui.MaterialSwitchPreference
android:defaultValue="false"
android:key="shitposting"
android:summary="@string/shitpostingsummary"
android:title="@string/shitposting"/>
<com.vtosters.lite.ui.MaterialSwitchPreference
android:defaultValue="false"
android:key="cringerepost"
android:summary="@string/cringerepost_summ"
android:title="@string/cringerepost_title"/>
<Preference
android:key="whitelisted_filters_groups"
android:title="@string/whitelisted_filters_groups_title"/>
@@ -111,9 +89,9 @@
android:title="@string/vtllinkfilter"/>
<com.vtosters.lite.ui.MaterialSwitchPreference
android:defaultValue="false"
android:key="cringecopyright"
android:summary="@string/cringecopyright_summ"
android:title="@string/cringecopyright_title"/>
android:key="cringerepost"
android:summary="@string/cringerepost_summ"
android:title="@string/cringerepost_title"/>
<com.vtosters.lite.ui.MaterialSwitchPreference
android:defaultValue="false"
android:key="copyright_post"
@@ -122,9 +100,9 @@
</PreferenceCategory>
<PreferenceCategory android:title="@string/vtlfeedwork">
<Preference
android:key="officialnewssett"
android:summary="@string/officialnewssett_summary"
android:title="@string/officialnewssett"/>
android:enabled="false"
android:summary="@string/why_news_not_updated_summ"
android:title="@string/why_news_not_updated_title"/>
<com.vtosters.lite.ui.SummaryListPreference
android:defaultValue="order"
android:dialogTitle="@string/newsfeed_settings_order"
@@ -133,10 +111,10 @@
android:key="newsfeed_order"
android:textColor="?text_secondary"
android:title="@string/newsfeed_settings_order"/>
<!-- <Preference-->
<!-- android:enabled="false"-->
<!-- android:summary="@string/why_news_not_updated_summ"-->
<!-- android:title="@string/why_news_not_updated_title"/>-->
<Preference
android:key="officialnewssett"
android:summary="@string/officialnewssett_summary"
android:title="@string/officialnewssett"/>
<com.vtosters.lite.ui.SummaryListPreference
android:defaultValue="default"
android:dialogTitle="@string/feed_other_update_dialog_title"
@@ -144,6 +122,11 @@
android:entryValues="@array/newsupdate"
android:key="newsupdate"
android:title="@string/feed_other_update"/>
<com.vtosters.lite.ui.MaterialSwitchPreference
android:defaultValue="false"
android:key="unlockCustomLists"
android:summary="Разблокировать новостные списки как футбол или региональные новости в списке новостей"
android:title="Новостные списки"/>
<Preference
android:key="newsfeedlistmanager"
android:summary="@string/newsfeedlistmanager_summ"
@@ -151,15 +134,10 @@
<Preference
android:key="newsfeedlistmanager_reset"
android:title="@string/newsfeedlistmanager_reset_title"/>
<!-- <com.vtosters.lite.ui.MaterialSwitchPreference-->
<!-- android:defaultValue="false"-->
<!-- android:key="force_disable_psm"-->
<!-- android:summary="@string/force_disable_psm_summ"-->
<!-- android:title="@string/force_disable_psm_title"/>-->
<com.vtosters.lite.ui.MaterialSwitchPreference
android:defaultValue="true"
android:key="feedcache"
android:summary="@string/feed_other_cache_summary"
android:title="@string/vtlfeedcache"/>
</PreferenceCategory>
</PreferenceScreen>
</PreferenceScreen>
@@ -41,6 +41,8 @@
.line 21
invoke-virtual {p0, p5, p1}, Lcom/vk/api/base/ApiRequest;->b(Ljava/lang/String;I)Lcom/vk/api/base/ApiRequest;
invoke-static {p1}, Lru/vtosters/hooks/NewsfeedHook;->takeOwnerIdSponsorPost(I)V
const-string p1, "offset"
invoke-virtual {p0, p1, p2}, Lcom/vk/api/base/ApiRequest;->b(Ljava/lang/String;I)Lcom/vk/api/base/ApiRequest;
@@ -97,6 +99,8 @@
.line 4
invoke-virtual {p0, v0, p1}, Lcom/vk/api/base/ApiRequest;->b(Ljava/lang/String;I)Lcom/vk/api/base/ApiRequest;
invoke-static {p1}, Lru/vtosters/hooks/NewsfeedHook;->takeOwnerIdSponsorPost(I)V
.line 5
invoke-static {p2}, Landroid/text/TextUtils;->isEmpty(Ljava/lang/CharSequence;)Z
@@ -23,6 +23,8 @@
.line 1
invoke-direct {p0, v0}, Lcom/vk/api/base/ApiRequest;-><init>(Ljava/lang/String;)V
invoke-static {p1}, Lru/vtosters/hooks/NewsfeedHook;->takeOwnerIdPostIdSponsorPost([Ljava/lang/String;)V
const-string v0, ","
.line 2
@@ -75,7 +77,7 @@
}
.end annotation
invoke-static {p2}, Lru/vtosters/hooks/AdBlockHook;->feedInject(Lorg/json/JSONArray;)Lorg/json/JSONArray;
invoke-static {p2}, Lru/vtosters/hooks/AdBlockHook;->wallGetById(Lorg/json/JSONArray;)Lorg/json/JSONArray;
move-result-object p2