Compare commits
20
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7e5b3fe233 | ||
|
|
4abd0eec6c | ||
|
|
cf17ed64c7 | ||
|
|
a2dd7c1e06 | ||
|
|
021fe66bec | ||
|
|
1b3896f4ca | ||
|
|
fc9ccf66d1 | ||
|
|
d205f2894b | ||
|
|
7afc04b2b2 | ||
|
|
584ee96ee0 | ||
|
|
66f7ea1b79 | ||
|
|
7b0a83458b | ||
|
|
cdaf7909d4 | ||
|
|
c70ab388c1 | ||
|
|
50c66c2703 | ||
|
|
357e520bb0 | ||
|
|
6379ce5741 | ||
|
|
02807739a1 | ||
|
|
40635ab75a | ||
|
|
32e1bfe6fd |
@@ -37,7 +37,7 @@
|
|||||||
|
|
||||||
* Стабильные сборки находятся в [Releases](https://github.com/vtosters/lite/releases)
|
* Стабильные сборки находятся в [Releases](https://github.com/vtosters/lite/releases)
|
||||||
|
|
||||||
Зеркало на нашем [<img src="https://gitea.com/assets/img/logo.svg" align="center" width="20" height="20"/> Git](https://git.maki.su/gdlbo/lite)
|
Зеркало на нашем [<img src="https://gitea.com/assets/img/logo.svg" align="center" width="20" height="20"/> Git](https://git.maki.su/vtosters/lite)
|
||||||
|
|
||||||
### Быстрая навигация
|
### Быстрая навигация
|
||||||
|
|
||||||
|
|||||||
@@ -84,6 +84,12 @@ android {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
task testClasses {
|
||||||
|
doLast {
|
||||||
|
println 'This is a dummy testClasses task'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
implementation 'com.microsoft.appcenter:appcenter-analytics:5.0.1'
|
implementation 'com.microsoft.appcenter:appcenter-analytics:5.0.1'
|
||||||
implementation 'com.microsoft.appcenter:appcenter-crashes:5.0.1'
|
implementation 'com.microsoft.appcenter:appcenter-crashes:5.0.1'
|
||||||
|
|||||||
@@ -36,10 +36,8 @@ public class TelegramStickersPack extends CustomStickersPack {
|
|||||||
public HashMap<String, List<Integer>> emojis = new HashMap<>();
|
public HashMap<String, List<Integer>> emojis = new HashMap<>();
|
||||||
|
|
||||||
public TelegramStickersPack(String id) {
|
public TelegramStickersPack(String id) {
|
||||||
final var idLowerCase = id.toLowerCase();
|
this.id=this.title=id;
|
||||||
this.id = idLowerCase;
|
this.hash=id.hashCode();
|
||||||
this.hash = idLowerCase.hashCode();
|
|
||||||
title = id;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public JSONObject encodeEmojis() throws JSONException {
|
public JSONObject encodeEmojis() throws JSONException {
|
||||||
@@ -103,7 +101,7 @@ public class TelegramStickersPack extends CustomStickersPack {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean equals(Object obj) {
|
public boolean equals(Object obj) {
|
||||||
return obj instanceof TelegramStickersPack && ((TelegramStickersPack) obj).id.equalsIgnoreCase(id);
|
return obj instanceof TelegramStickersPack && ((TelegramStickersPack) obj).id.equals(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import android.util.Log;
|
|||||||
import com.aefyr.tsg.g2.sql.TelegramStickersDbHelper;
|
import com.aefyr.tsg.g2.sql.TelegramStickersDbHelper;
|
||||||
import com.aefyr.tsg.g2.stickersgrabber.TelegramStickersGrabber;
|
import com.aefyr.tsg.g2.stickersgrabber.TelegramStickersGrabber;
|
||||||
import com.aefyr.tsg.g2.stickersgrabber.TelegramStickersPackInfo;
|
import com.aefyr.tsg.g2.stickersgrabber.TelegramStickersPackInfo;
|
||||||
|
import ru.vtosters.lite.ui.fragments.VTSettings;
|
||||||
import ru.vtosters.lite.ui.fragments.tgstickers.StickersFragment;
|
import ru.vtosters.lite.ui.fragments.tgstickers.StickersFragment;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
@@ -152,6 +153,7 @@ public class TelegramStickersService {
|
|||||||
|
|
||||||
private void notifyActivePacksListChanged() {
|
private void notifyActivePacksListChanged() {
|
||||||
getGlobalContext().sendBroadcast(new Intent(StickersFragment.ACTION_RELOAD));
|
getGlobalContext().sendBroadcast(new Intent(StickersFragment.ACTION_RELOAD));
|
||||||
|
getGlobalContext().sendBroadcast(new Intent(VTSettings.ACTION_INVALIDATE_TGS_COUNT));
|
||||||
if (listeners.isEmpty())
|
if (listeners.isEmpty())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@@ -222,7 +224,7 @@ public class TelegramStickersService {
|
|||||||
final TelegramStickersPack newPack = pack;
|
final TelegramStickersPack newPack = pack;
|
||||||
final boolean isUpdate = update;
|
final boolean isUpdate = update;
|
||||||
|
|
||||||
currentlyDownloading.add(id.toLowerCase());
|
currentlyDownloading.add(id);
|
||||||
notificationsHelper.packStartedDownloading(newPack);
|
notificationsHelper.packStartedDownloading(newPack);
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import android.app.Activity;
|
|||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.os.Build;
|
import android.os.Build;
|
||||||
import b.h.g.k.VKProgressDialog;
|
import b.h.g.k.VKProgressDialog;
|
||||||
|
import com.aefyr.tsg.g2.TelegramStickersService;
|
||||||
import com.vk.core.dialogs.alert.VkAlertDialog;
|
import com.vk.core.dialogs.alert.VkAlertDialog;
|
||||||
import com.vtosters.lite.R;
|
import com.vtosters.lite.R;
|
||||||
import ru.vtosters.hooks.other.Preferences;
|
import ru.vtosters.hooks.other.Preferences;
|
||||||
@@ -65,6 +66,8 @@ public class MainActivityInjector {
|
|||||||
InstallGMS.alert(activity);
|
InstallGMS.alert(activity);
|
||||||
DisableBattery.alert(activity);
|
DisableBattery.alert(activity);
|
||||||
// VKIDProtection.alert(activity);
|
// VKIDProtection.alert(activity);
|
||||||
|
//needs to show selected tgs pack count in settings after cold launch
|
||||||
|
TelegramStickersService.getInstance(activity);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void updateBinsAndTmpArchive(Activity activity) {
|
private static void updateBinsAndTmpArchive(Activity activity) {
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ public class VKUIHook {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private static void applyVKUIStyles(WebView webView) {
|
private static void applyVKUIStyles(WebView webView) {
|
||||||
if (getBoolValue("VKUI_INJ", true) && !webView.getUrl().contains("static.vk.com/memories")) {
|
if (getBoolValue("VKUI_INJ", true) && webView != null && webView.getUrl() != null && !webView.getUrl().contains("static.vk.com/memories")) {
|
||||||
if (!WebViewColoringUtils.isLoaded) {
|
if (!WebViewColoringUtils.isLoaded) {
|
||||||
WebViewColoringUtils.load();
|
WebViewColoringUtils.load();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -28,6 +28,7 @@ import com.vtosters.lite.data.ThemeTracker;
|
|||||||
import ru.vtosters.lite.deviceinfo.OEMDetector;
|
import ru.vtosters.lite.deviceinfo.OEMDetector;
|
||||||
import ru.vtosters.lite.themes.ThemesCore;
|
import ru.vtosters.lite.themes.ThemesCore;
|
||||||
import ru.vtosters.lite.themes.ThemesHacks;
|
import ru.vtosters.lite.themes.ThemesHacks;
|
||||||
|
import ru.vtosters.lite.themes.ThemesManager;
|
||||||
import ru.vtosters.lite.ui.wallpapers.WallpapersHooks;
|
import ru.vtosters.lite.ui.wallpapers.WallpapersHooks;
|
||||||
import ru.vtosters.lite.utils.LifecycleUtils;
|
import ru.vtosters.lite.utils.LifecycleUtils;
|
||||||
import ru.vtosters.lite.utils.WebViewColoringUtils;
|
import ru.vtosters.lite.utils.WebViewColoringUtils;
|
||||||
@@ -59,7 +60,7 @@ public class ThemesUtils {
|
|||||||
activity = LifecycleUtils.getCurrentActivity();
|
activity = LifecycleUtils.getCurrentActivity();
|
||||||
}
|
}
|
||||||
VKThemeHelper.theme(theme, activity, fl);
|
VKThemeHelper.theme(theme, activity, fl);
|
||||||
if (isMonetTheme()) ThemesCore.clear();
|
if (isMonetTheme() || ThemesManager.canApplyCustomAccent()) ThemesCore.clear();
|
||||||
if (restartActivity) activity.recreate();
|
if (restartActivity) activity.recreate();
|
||||||
ThemeTracker.a();
|
ThemeTracker.a();
|
||||||
WebViewColoringUtils.isLoaded = false;
|
WebViewColoringUtils.isLoaded = false;
|
||||||
|
|||||||
+14
-1
@@ -6,12 +6,14 @@ import com.vk.dto.music.MusicTrack;
|
|||||||
import org.json.JSONArray;
|
import org.json.JSONArray;
|
||||||
import org.json.JSONException;
|
import org.json.JSONException;
|
||||||
import org.json.JSONObject;
|
import org.json.JSONObject;
|
||||||
|
import ru.vtosters.hooks.other.Preferences;
|
||||||
import ru.vtosters.lite.music.cache.CacheDatabaseDelegate;
|
import ru.vtosters.lite.music.cache.CacheDatabaseDelegate;
|
||||||
import ru.vtosters.lite.music.cache.FileCacheImplementation;
|
import ru.vtosters.lite.music.cache.FileCacheImplementation;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.net.MalformedURLException;
|
import java.net.MalformedURLException;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
public class TracklistHelper {
|
public class TracklistHelper {
|
||||||
@@ -20,9 +22,18 @@ public class TracklistHelper {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static List<MusicTrack> getTracks() {
|
public static List<MusicTrack> getTracks() {
|
||||||
return CacheDatabaseDelegate.getTracks();
|
List<MusicTrack> tracks = CacheDatabaseDelegate.getTracks();
|
||||||
|
|
||||||
|
boolean doNotinvertOrder = Preferences.getBoolValue("invertCachedTracks", false);
|
||||||
|
|
||||||
|
if (!doNotinvertOrder) {
|
||||||
|
Collections.reverse(tracks);
|
||||||
|
}
|
||||||
|
|
||||||
|
return tracks;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public static List<MusicTrack> getTracks(String id) {
|
public static List<MusicTrack> getTracks(String id) {
|
||||||
return CacheDatabaseDelegate.getTracksByAlbum(id);
|
return CacheDatabaseDelegate.getTracksByAlbum(id);
|
||||||
}
|
}
|
||||||
@@ -33,9 +44,11 @@ public class TracklistHelper {
|
|||||||
|
|
||||||
public static JSONArray tracksToIds(List<MusicTrack> tracks) {
|
public static JSONArray tracksToIds(List<MusicTrack> tracks) {
|
||||||
var arr = new JSONArray();
|
var arr = new JSONArray();
|
||||||
|
|
||||||
for (MusicTrack track : tracks) {
|
for (MusicTrack track : tracks) {
|
||||||
arr.put(track.y1());
|
arr.put(track.y1());
|
||||||
}
|
}
|
||||||
|
|
||||||
return arr;
|
return arr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -11,15 +11,15 @@ public class ImBanner {
|
|||||||
private static final String TAG = "ImBanner";
|
private static final String TAG = "ImBanner";
|
||||||
|
|
||||||
public static JSONObject convertToBanner(JSONObject original) {
|
public static JSONObject convertToBanner(JSONObject original) {
|
||||||
final String PEER = "peer";
|
String PEER = "peer";
|
||||||
final String ID = "id";
|
String ID = "id";
|
||||||
final String PICTURE = "picture";
|
String PICTURE = "picture";
|
||||||
final String TEXT = "text";
|
String TEXT = "text";
|
||||||
final String LINK = "link";
|
String LINK = "link";
|
||||||
final String LINK_TEXT = "link_text";
|
String LINK_TEXT = "link_text";
|
||||||
final String NAME = "name";
|
String NAME = "name";
|
||||||
final String BUTTONS = "buttons";
|
String BUTTONS = "buttons";
|
||||||
final String ICON = "icon";
|
String ICON = "icon";
|
||||||
|
|
||||||
Optional<JSONObject> user = Optional.ofNullable(original.optJSONObject(PEER));
|
Optional<JSONObject> user = Optional.ofNullable(original.optJSONObject(PEER));
|
||||||
int userId = user.map(u -> u.optInt(ID)).orElse(0);
|
int userId = user.map(u -> u.optInt(ID)).orElse(0);
|
||||||
|
|||||||
@@ -166,26 +166,25 @@ public class ThemesCore {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static boolean hasThemedAttr(Context context, int attrID) {
|
public static boolean hasThemedAttr(Context context, int attrID) {
|
||||||
if (ThemesUtils.isMonetTheme()) {
|
if (Preferences.getBoolValue("logColors", false)) {
|
||||||
if (Preferences.getBoolValue("logColors", false)) {
|
try {
|
||||||
try {
|
Log.d(TAG, "Requesting color by attr " + context.getResources().getResourceName(attrID));
|
||||||
Log.d(TAG, "Requesting color by attr " + context.getResources().getResourceName(attrID));
|
} catch (Exception ignored) {
|
||||||
} catch (Exception ignored) {
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ThemesUtils.isMonetTheme() || ThemesManager.canApplyCustomAccent()) {
|
||||||
if (isCachedAccents()) {
|
if (isCachedAccents()) {
|
||||||
if (ThemesUtils.isDarkTheme()) {
|
boolean isDark = ThemesUtils.isDarkTheme();
|
||||||
return (themedColors.get(attrID) != 0 && ACCENT_THEME_ONLY_DARK.get(attrID, true) && (
|
boolean isMilkshake = ThemesUtils.isMilkshake();
|
||||||
ThemesUtils.isMilkshake() ?
|
SparseBooleanArray themeOnlyMap = isDark ? ACCENT_THEME_ONLY_DARK : ACCENT_THEME_ONLY_LIGHT;
|
||||||
ACCENT_THEME_ONLY_MILK_DARK.get(attrID, true) :
|
SparseBooleanArray milkshakeMap = isDark ? ACCENT_THEME_ONLY_MILK_DARK : ACCENT_THEME_ONLY_MILK_LIGHT;
|
||||||
ACCENT_THEME_ONLY_NOMILK_DARK.get(attrID, true)));
|
SparseBooleanArray noMilkshakeMap = isDark ? ACCENT_THEME_ONLY_NOMILK_DARK : ACCENT_THEME_ONLY_NOMILK_LIGHT;
|
||||||
} else {
|
|
||||||
return (themedColors.get(attrID) != 0 && ACCENT_THEME_ONLY_LIGHT.get(attrID, true) && (
|
return (themedColors.get(attrID) != 0 && themeOnlyMap.get(attrID, true) && (
|
||||||
ThemesUtils.isMilkshake() ?
|
isMilkshake ?
|
||||||
ACCENT_THEME_ONLY_MILK_LIGHT.get(attrID, true) :
|
milkshakeMap.get(attrID, true) :
|
||||||
ACCENT_THEME_ONLY_NOMILK_LIGHT.get(attrID, true)));
|
noMilkshakeMap.get(attrID, true)));
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
return themedColors.get(attrID) != 0;
|
return themedColors.get(attrID) != 0;
|
||||||
}
|
}
|
||||||
@@ -194,7 +193,6 @@ public class ThemesCore {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public static void clear() {
|
public static void clear() {
|
||||||
cachedAccents = false;
|
cachedAccents = false;
|
||||||
themedColors.clear();
|
themedColors.clear();
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ public class ThemesHacks {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static int getHackedColor(@NonNull Context context, @ColorRes int color) {
|
public static int getHackedColor(@NonNull Context context, @ColorRes int color) {
|
||||||
if (ThemesUtils.isMonetTheme()) {
|
if (ThemesUtils.isMonetTheme() || ThemesManager.canApplyCustomAccent()) {
|
||||||
if (Preferences.getBoolValue("logColors", false)) {
|
if (Preferences.getBoolValue("logColors", false)) {
|
||||||
try {
|
try {
|
||||||
Log.d("ThemesCore", "Requesting color by color " + context.getResources().getResourceName(color));
|
Log.d("ThemesCore", "Requesting color by color " + context.getResources().getResourceName(color));
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ import java.util.zip.ZipOutputStream;
|
|||||||
|
|
||||||
public class ThemesManager {
|
public class ThemesManager {
|
||||||
|
|
||||||
private final static int[] ACCENT_COLORS = {
|
private static final int[] ACCENT_COLORS = {
|
||||||
R.color.vk_sky_300,
|
R.color.vk_sky_300,
|
||||||
R.color.sky_300,
|
R.color.sky_300,
|
||||||
R.color.viewer_retry_button_text_color,
|
R.color.viewer_retry_button_text_color,
|
||||||
@@ -96,7 +96,7 @@ public class ThemesManager {
|
|||||||
R.color.header_blue_opacity40
|
R.color.header_blue_opacity40
|
||||||
};
|
};
|
||||||
// modify it if "doNotCompress" in apktool.yml has been edited
|
// modify it if "doNotCompress" in apktool.yml has been edited
|
||||||
private final static String[] DO_NOT_COMPRESS = {
|
private static final String[] DO_NOT_COMPRESS = {
|
||||||
".png",
|
".png",
|
||||||
".jpg",
|
".jpg",
|
||||||
".mp3",
|
".mp3",
|
||||||
@@ -124,14 +124,13 @@ public class ThemesManager {
|
|||||||
ResourcesLoader.load(app, modApk.getAbsolutePath(), false);
|
ResourcesLoader.load(app, modApk.getAbsolutePath(), false);
|
||||||
}
|
}
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
Log.e("ThemesManager", e.getMessage());
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// validate modded apk before loading
|
// validate modded apk before loading
|
||||||
private static void validateModApk()
|
private static void validateModApk() throws IOException {
|
||||||
throws IOException {
|
var apk = new ZipFile(modApk);
|
||||||
final var apk = new ZipFile(modApk);
|
|
||||||
apk.close();
|
apk.close();
|
||||||
|
|
||||||
validated = true;
|
validated = true;
|
||||||
@@ -153,23 +152,18 @@ public class ThemesManager {
|
|||||||
return validated && modApk.exists() && ThemesUtils.getReservedAccent() != Color.TRANSPARENT;
|
return validated && modApk.exists() && ThemesUtils.getReservedAccent() != Color.TRANSPARENT;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void generateModApk(int accentColor)
|
public static void generateModApk(int accentColor) throws Throwable {
|
||||||
throws Throwable {
|
try (var apk = new ZipFile(baseApkPath)) {
|
||||||
try (
|
var arscEntry = apk.getEntry("resources.arsc");
|
||||||
final var apk = new ZipFile(baseApkPath)
|
var arscBis = new BufferedInputStream(apk.getInputStream(arscEntry));
|
||||||
) {
|
var arsc = BinaryResourceFile.fromInputStream(arscBis);
|
||||||
final var arscEntry = apk.getEntry("resources.arsc");
|
|
||||||
final var arscBis = new BufferedInputStream(apk.getInputStream(arscEntry));
|
|
||||||
final var arsc = BinaryResourceFile.fromInputStream(arscBis);
|
|
||||||
ArscEditor.changeColors(arsc, ACCENT_COLORS, accentColor);
|
ArscEditor.changeColors(arsc, ACCENT_COLORS, accentColor);
|
||||||
|
|
||||||
try (
|
try (var zos = new ZipOutputStream(new BufferedOutputStream(new FileOutputStream(modApk)))) {
|
||||||
final var zos = new ZipOutputStream(new BufferedOutputStream(new FileOutputStream(modApk)))
|
var arscBuff = arsc.toByteArray();
|
||||||
) {
|
var newArscEntry = new ZipEntry("resources.arsc");
|
||||||
final var arscBuff = arsc.toByteArray();
|
|
||||||
final var newArscEntry = new ZipEntry("resources.arsc");
|
|
||||||
|
|
||||||
final var crc = new CRC32();
|
var crc = new CRC32();
|
||||||
crc.update(arscBuff);
|
crc.update(arscBuff);
|
||||||
|
|
||||||
newArscEntry.setSize(arscBuff.length);
|
newArscEntry.setSize(arscBuff.length);
|
||||||
@@ -180,10 +174,10 @@ public class ThemesManager {
|
|||||||
zos.write(arscBuff);
|
zos.write(arscBuff);
|
||||||
zos.closeEntry();
|
zos.closeEntry();
|
||||||
|
|
||||||
final var entries = apk.entries();
|
var entries = apk.entries();
|
||||||
while (entries.hasMoreElements()) {
|
while (entries.hasMoreElements()) {
|
||||||
final var entry = entries.nextElement();
|
var entry = entries.nextElement();
|
||||||
final var name = entry.getName();
|
var name = entry.getName();
|
||||||
|
|
||||||
if (!name.startsWith("res/") && !name.startsWith("assets/") || name.equals("resources.arsc"))
|
if (!name.startsWith("res/") && !name.startsWith("assets/") || name.equals("resources.arsc"))
|
||||||
continue;
|
continue;
|
||||||
@@ -196,8 +190,8 @@ public class ThemesManager {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
final var entryBis = new BufferedInputStream(apk.getInputStream(entry));
|
var entryBis = new BufferedInputStream(apk.getInputStream(entry));
|
||||||
final var newEntry = new ZipEntry(name);
|
var newEntry = new ZipEntry(name);
|
||||||
|
|
||||||
if (doNotCompress) {
|
if (doNotCompress) {
|
||||||
newEntry.setMethod(ZipEntry.STORED);
|
newEntry.setMethod(ZipEntry.STORED);
|
||||||
|
|||||||
@@ -1,59 +1,44 @@
|
|||||||
package ru.vtosters.lite.themes.loaders;
|
package ru.vtosters.lite.themes.loaders;
|
||||||
|
|
||||||
|
import android.annotation.SuppressLint;
|
||||||
import android.content.res.AssetManager;
|
import android.content.res.AssetManager;
|
||||||
|
import android.util.Log;
|
||||||
import ru.vtosters.lite.utils.ReflectionUtils;
|
import ru.vtosters.lite.utils.ReflectionUtils;
|
||||||
|
|
||||||
import java.lang.reflect.InvocationTargetException;
|
import java.lang.reflect.InvocationTargetException;
|
||||||
import java.lang.reflect.Method;
|
import java.lang.reflect.Method;
|
||||||
|
|
||||||
|
@SuppressLint("PrivateApi")
|
||||||
public class AssetManagerHelper {
|
public class AssetManagerHelper {
|
||||||
|
public static String getApkPath(Object assetManager, String packagename) throws InvocationTargetException, IllegalAccessException, ClassNotFoundException, NoSuchMethodException {
|
||||||
|
Object[] apkAssetsArr = (Object[]) ReflectionUtils.findMethod(Class.forName("android.content.res.ApkAssets"), "getAssetPath").invoke(assetManager);
|
||||||
// methods
|
|
||||||
private final static Method getAssetPathMtd;
|
|
||||||
private final static Method getApkAssetsMtd;
|
|
||||||
private final static Method addAssetPathMtd;
|
|
||||||
private final static Method addAssetPathAsSharedLibraryMtd;
|
|
||||||
private final static Method addOverlayPathMtd;
|
|
||||||
|
|
||||||
static {
|
|
||||||
try {
|
|
||||||
getAssetPathMtd = ReflectionUtils.findMethod(Class.forName("android.content.res.ApkAssets"), "getAssetPath");
|
|
||||||
getApkAssetsMtd = ReflectionUtils.findMethod(AssetManager.class, "getApkAssets");
|
|
||||||
addAssetPathMtd = AssetManager.class.getMethod("addAssetPath", String.class);
|
|
||||||
addAssetPathAsSharedLibraryMtd = AssetManager.class.getMethod("addAssetPathAsSharedLibrary", String.class);
|
|
||||||
addOverlayPathMtd = AssetManager.class.getMethod("addOverlayPath", String.class);
|
|
||||||
} catch (ClassNotFoundException | NoSuchMethodException e) {
|
|
||||||
throw new RuntimeException();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static String getApkPath(Object assetManager, String packagename)
|
|
||||||
throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, IllegalAccessException {
|
|
||||||
Object[] apkAssetsArr = (Object[]) getAssetPathMtd.invoke(assetManager);
|
|
||||||
// By default, base apk is the last element of array if is not, for execution speed, we should iterate array from the end to the beginning
|
// By default, base apk is the last element of array if is not, for execution speed, we should iterate array from the end to the beginning
|
||||||
for (int i = apkAssetsArr.length - 1; i >= 0; i--) {
|
for (int i = apkAssetsArr.length - 1; i >= 0; i--) {
|
||||||
final String pathname = (String) getApkAssetsMtd.invoke(apkAssetsArr[i]);
|
String pathname = (String) ReflectionUtils.findMethod(AssetManager.class, "getApkAssets").invoke(apkAssetsArr[i]);
|
||||||
if (pathname.contains(packagename)) return pathname;
|
if (pathname != null && pathname.contains(packagename)) return pathname;
|
||||||
}
|
}
|
||||||
|
|
||||||
throw new NullPointerException();
|
throw new NullPointerException();
|
||||||
}
|
}
|
||||||
|
|
||||||
//region Uses for adding own assets or getting existing cookies
|
//region Uses for adding own assets or getting existing cookies
|
||||||
public static int addAssetPath(AssetManager manager, String path)
|
public static void addAssetPath(AssetManager manager, String path) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
|
||||||
throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
|
manager.getClass().getMethod("addAssetPath", String.class).invoke(manager, path);
|
||||||
return (int) addAssetPathMtd.invoke(manager, path);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static int addAssetPathAsSharedLibrary(AssetManager manager, String path)
|
public static int addAssetPathAsSharedLibrary(AssetManager manager, String path) {
|
||||||
throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
|
try {
|
||||||
return (int) addAssetPathAsSharedLibraryMtd.invoke(manager, path);
|
return (int) AssetManager.class.getMethod("addAssetPathAsSharedLibrary", String.class).invoke(manager, path);
|
||||||
|
} catch (IllegalAccessException | InvocationTargetException | NoSuchMethodException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static int addOverlayPath(AssetManager manager, String path)
|
public static int addOverlayPath(AssetManager manager, String path) {
|
||||||
throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
|
try {
|
||||||
return (int) addOverlayPathMtd.invoke(manager, path);
|
return (int) AssetManager.class.getMethod("addOverlayPath", String.class).invoke(manager, path);
|
||||||
|
} catch (IllegalAccessException | InvocationTargetException | NoSuchMethodException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
//endregion
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
package ru.vtosters.lite.themes.loaders;
|
package ru.vtosters.lite.themes.loaders;
|
||||||
|
|
||||||
|
import android.annotation.SuppressLint;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.pm.ApplicationInfo;
|
import android.content.pm.ApplicationInfo;
|
||||||
import android.content.res.AssetManager;
|
import android.content.res.AssetManager;
|
||||||
@@ -13,17 +14,19 @@ import ru.vtosters.lite.utils.ReflectionUtils;
|
|||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.lang.ref.WeakReference;
|
import java.lang.ref.WeakReference;
|
||||||
|
import java.lang.reflect.Array;
|
||||||
import java.lang.reflect.Field;
|
import java.lang.reflect.Field;
|
||||||
|
import java.lang.reflect.InvocationTargetException;
|
||||||
import java.lang.reflect.Method;
|
import java.lang.reflect.Method;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
|
@SuppressLint("PrivateApi")
|
||||||
public class ResourcesLoader {
|
public class ResourcesLoader {
|
||||||
|
|
||||||
private static Collection<WeakReference<Resources>> sResourceReferences = null;
|
private static Collection<WeakReference<Resources>> sResourceReferences = null;
|
||||||
private static Object sCurrentActivityThread = null;
|
private static Object sCurrentActivityThread = null;
|
||||||
private static AssetManager sAssetManager = null;
|
|
||||||
|
|
||||||
// methods
|
// methods
|
||||||
private static Method ensureStringBlocksMtd = null;
|
private static Method ensureStringBlocksMtd = null;
|
||||||
@@ -42,7 +45,7 @@ public class ResourcesLoader {
|
|||||||
static {
|
static {
|
||||||
try {
|
try {
|
||||||
// API version 8 has PackageInfo, 10 has LoadedApk. Needs to check 9
|
// API version 8 has PackageInfo, 10 has LoadedApk. Needs to check 9
|
||||||
final Class<?> activityThreadClz = Class.forName("android.app.ActivityThread");
|
Class<?> activityThreadClz = Class.forName("android.app.ActivityThread");
|
||||||
Class<?> loadedApkClz;
|
Class<?> loadedApkClz;
|
||||||
try {
|
try {
|
||||||
loadedApkClz = Class.forName("android.app.LoadedApk");
|
loadedApkClz = Class.forName("android.app.LoadedApk");
|
||||||
@@ -87,43 +90,40 @@ public class ResourcesLoader {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void init(Context context)
|
public static void init(Context context) throws Exception {
|
||||||
throws Exception {
|
|
||||||
sCurrentActivityThread = ReflectionUtils.getActivityThread(context, null);
|
sCurrentActivityThread = ReflectionUtils.getActivityThread(context, null);
|
||||||
|
|
||||||
//pre-N
|
//pre-N
|
||||||
// Find the singleton instance of ResourcesManager
|
// Find the singleton instance of ResourcesManager
|
||||||
final Class<?> resourcesManagerClass = Class.forName("android.app.ResourcesManager");
|
Class<?> resourcesManagerClass = Class.forName("android.app.ResourcesManager");
|
||||||
final Method mGetInstance = ReflectionUtils.findMethod(resourcesManagerClass, "getInstance");
|
Method mGetInstance = ReflectionUtils.findMethod(resourcesManagerClass, "getInstance");
|
||||||
final Object resourcesManager = mGetInstance.invoke(null);
|
Object resourcesManager = mGetInstance.invoke(null);
|
||||||
try {
|
try {
|
||||||
Field fMActiveResources = ReflectionUtils.findField(resourcesManagerClass, "mActiveResources");
|
Field fMActiveResources = ReflectionUtils.findField(resourcesManagerClass, "mActiveResources");
|
||||||
final ArrayMap<?, WeakReference<Resources>> activeResources19 =
|
ArrayMap<?, WeakReference<Resources>> activeResources19 =
|
||||||
(ArrayMap<?, WeakReference<Resources>>) fMActiveResources.get(resourcesManager);
|
(ArrayMap<?, WeakReference<Resources>>) fMActiveResources.get(resourcesManager);
|
||||||
sResourceReferences = activeResources19.values();
|
sResourceReferences = activeResources19.values();
|
||||||
} catch (NoSuchFieldException ignore) {
|
} catch (NoSuchFieldException ignore) {
|
||||||
// N moved the resources to mResourceReferences
|
// N moved the resources to mResourceReferences
|
||||||
final Field mResourceReferences = ReflectionUtils.findField(resourcesManagerClass, "mResourceReferences");
|
Field mResourceReferences = ReflectionUtils.findField(resourcesManagerClass, "mResourceReferences");
|
||||||
sResourceReferences = (Collection<WeakReference<Resources>>) mResourceReferences.get(resourcesManager);
|
sResourceReferences = (Collection<WeakReference<Resources>>) mResourceReferences.get(resourcesManager);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void load(Context context, String resPath, boolean reinject)
|
public static void load(Context context, String resPath, boolean reinject) throws IllegalAccessException, InstantiationException, InvocationTargetException, NoSuchFieldException, NoSuchMethodException {
|
||||||
throws Exception {
|
ApplicationInfo appInfo = context.getApplicationInfo();
|
||||||
final ApplicationInfo appInfo = context.getApplicationInfo();
|
|
||||||
|
|
||||||
final Field[] packagesFlds = Build.VERSION.SDK_INT < Build.VERSION_CODES.O_MR1
|
Field[] packagesFlds = Build.VERSION.SDK_INT < Build.VERSION_CODES.O_MR1
|
||||||
? new Field[]{packagesFld, resourcePackagesFld}
|
? new Field[]{packagesFld, resourcePackagesFld}
|
||||||
: new Field[]{packagesFld};
|
: new Field[]{packagesFld};
|
||||||
for (var fld : packagesFlds) {
|
for (var fld : packagesFlds) {
|
||||||
final var value = fld.get(sCurrentActivityThread);
|
var value = fld.get(sCurrentActivityThread);
|
||||||
|
|
||||||
for (var entry
|
for (var entry : ((Map<String, WeakReference<?>>) value).entrySet()) {
|
||||||
: ((Map<String, WeakReference<?>>) value).entrySet()) {
|
var loadedApk = entry.getValue().get();
|
||||||
final var loadedApk = entry.getValue().get();
|
|
||||||
if (loadedApk == null) continue;
|
if (loadedApk == null) continue;
|
||||||
|
|
||||||
final var resDirPath = (String) resDirFld.get(loadedApk);
|
var resDirPath = (String) resDirFld.get(loadedApk);
|
||||||
if (appInfo.sourceDir.equals(resDirPath))
|
if (appInfo.sourceDir.equals(resDirPath))
|
||||||
resDirFld.set(loadedApk, resPath);
|
resDirFld.set(loadedApk, resPath);
|
||||||
}
|
}
|
||||||
@@ -134,10 +134,10 @@ public class ResourcesLoader {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
sAssetManager = AssetManager.class.newInstance();
|
|
||||||
// Create a new AssetManager instance and point it to the resources installed under
|
// Create a new AssetManager instance and point it to the resources installed under
|
||||||
if (AssetManagerHelper.addAssetPath(sAssetManager, resPath) == 0)
|
AssetManager sAssetManager = AssetManager.class.newInstance();
|
||||||
throw new IllegalStateException("Could not create new AssetManager");
|
|
||||||
|
AssetManagerHelper.addAssetPath(sAssetManager, resPath);
|
||||||
|
|
||||||
// Add SharedLibraries to AssetManager for resolve system resources not found issue
|
// Add SharedLibraries to AssetManager for resolve system resources not found issue
|
||||||
// This influence SharedLibrary Package ID
|
// This influence SharedLibrary Package ID
|
||||||
@@ -157,7 +157,7 @@ public class ResourcesLoader {
|
|||||||
ensureStringBlocksMtd.invoke(sAssetManager);
|
ensureStringBlocksMtd.invoke(sAssetManager);
|
||||||
}
|
}
|
||||||
for (var wr : sResourceReferences) {
|
for (var wr : sResourceReferences) {
|
||||||
final var resources = wr.get();
|
var resources = wr.get();
|
||||||
if (resources == null) continue;
|
if (resources == null) continue;
|
||||||
|
|
||||||
// Set the AssetManager of the Resources instance to our brand new one
|
// Set the AssetManager of the Resources instance to our brand new one
|
||||||
@@ -166,9 +166,9 @@ public class ResourcesLoader {
|
|||||||
assetsFld.set(resources, sAssetManager);
|
assetsFld.set(resources, sAssetManager);
|
||||||
} catch (Throwable ignore) {
|
} catch (Throwable ignore) {
|
||||||
// N
|
// N
|
||||||
final var resourceImpl = resourcesImplFld.get(resources);
|
var resourceImpl = resourcesImplFld.get(resources);
|
||||||
// for Huawei HwResourcesImpl
|
// for Huawei HwResourcesImpl
|
||||||
final Field implAssets = ReflectionUtils.findField(resourceImpl, "mAssets");
|
Field implAssets = ReflectionUtils.findField(resourceImpl, "mAssets");
|
||||||
implAssets.set(resourceImpl, sAssetManager);
|
implAssets.set(resourceImpl, sAssetManager);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -196,13 +196,13 @@ public class ResourcesLoader {
|
|||||||
|
|
||||||
private static void installResourceInsuranceHacks(Context context, String patchedResApkPath) {
|
private static void installResourceInsuranceHacks(Context context, String patchedResApkPath) {
|
||||||
try {
|
try {
|
||||||
final Object activityThread = ReflectionUtils.getActivityThread(context, null);
|
Object activityThread = ReflectionUtils.getActivityThread(context, null);
|
||||||
final Field mHField = ReflectionUtils.findField(activityThread, "mH");
|
Field mHField = ReflectionUtils.findField(activityThread, "mH");
|
||||||
final Handler mH = (Handler) mHField.get(activityThread);
|
Handler mH = (Handler) mHField.get(activityThread);
|
||||||
final Field mCallbackField = ReflectionUtils.findField(Handler.class, "mCallback");
|
Field mCallbackField = ReflectionUtils.findField(Handler.class, "mCallback");
|
||||||
final Handler.Callback originCallback = (Handler.Callback) mCallbackField.get(mH);
|
Handler.Callback originCallback = (Handler.Callback) mCallbackField.get(mH);
|
||||||
if (!(originCallback instanceof ResourceInsuranceHandlerCallback)) {
|
if (!(originCallback instanceof ResourceInsuranceHandlerCallback)) {
|
||||||
final ResourceInsuranceHandlerCallback hackCallback = new ResourceInsuranceHandlerCallback(
|
ResourceInsuranceHandlerCallback hackCallback = new ResourceInsuranceHandlerCallback(
|
||||||
context, patchedResApkPath, originCallback, mH.getClass());
|
context, patchedResApkPath, originCallback, mH.getClass());
|
||||||
mCallbackField.set(mH, hackCallback);
|
mCallbackField.set(mH, hackCallback);
|
||||||
} else {
|
} else {
|
||||||
@@ -250,9 +250,9 @@ public class ResourcesLoader {
|
|||||||
Log.w("ResourcesLoader", "try to clear typedArray cache!");
|
Log.w("ResourcesLoader", "try to clear typedArray cache!");
|
||||||
// Clear typedArray cache.
|
// Clear typedArray cache.
|
||||||
try {
|
try {
|
||||||
final Field typedArrayPoolField = ReflectionUtils.findField(Resources.class, "mTypedArrayPool");
|
Field typedArrayPoolField = ReflectionUtils.findField(Resources.class, "mTypedArrayPool");
|
||||||
final Object origTypedArrayPool = typedArrayPoolField.get(resources);
|
Object origTypedArrayPool = typedArrayPoolField.get(resources);
|
||||||
final Method acquireMethod = ReflectionUtils.findMethod(origTypedArrayPool, "acquire");
|
Method acquireMethod = ReflectionUtils.findMethod(origTypedArrayPool, "acquire");
|
||||||
while (true) {
|
while (true) {
|
||||||
if (acquireMethod.invoke(origTypedArrayPool) == null) {
|
if (acquireMethod.invoke(origTypedArrayPool) == null) {
|
||||||
break;
|
break;
|
||||||
@@ -268,9 +268,8 @@ public class ResourcesLoader {
|
|||||||
applicationInfo.sharedLibraryFiles != null;
|
applicationInfo.sharedLibraryFiles != null;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static final class ResourceInsuranceHandlerCallback implements Handler.Callback {
|
private static class ResourceInsuranceHandlerCallback implements Handler.Callback {
|
||||||
private static final String LAUNCH_ACTIVITY_LIFECYCLE_ITEM_CLASSNAME = "android.app.servertransaction.LaunchActivityItem";
|
private static final String LAUNCH_ACTIVITY_LIFECYCLE_ITEM_CLASSNAME = "android.app.servertransaction.LaunchActivityItem";
|
||||||
|
|
||||||
private final Context mContext;
|
private final Context mContext;
|
||||||
private final String mPatchResApkPath;
|
private final String mPatchResApkPath;
|
||||||
private final Handler.Callback mOriginalCallback;
|
private final Handler.Callback mOriginalCallback;
|
||||||
@@ -319,48 +318,56 @@ public class ResourcesLoader {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
private boolean hackMessage(Message msg) {
|
// A method to check if the message requires re-injecting patched resources
|
||||||
boolean shouldReInjectPatchedResources = false;
|
private boolean shouldReInjectPatchedResources(Message msg) {
|
||||||
if (!isPatchedResModifiedAfterLastLoad(mPatchResApkPath)) {
|
if (!isPatchedResModifiedAfterLastLoad(mPatchResApkPath)) {
|
||||||
shouldReInjectPatchedResources = false;
|
return false;
|
||||||
} else {
|
}
|
||||||
if (msg.what == LAUNCH_ACTIVITY || msg.what == RELAUNCH_ACTIVITY) {
|
if (msg.what == LAUNCH_ACTIVITY || msg.what == RELAUNCH_ACTIVITY) {
|
||||||
shouldReInjectPatchedResources = true;
|
return true;
|
||||||
} else if (msg.what == EXECUTE_TRANSACTION) {
|
}
|
||||||
do {
|
// If the message is executing a transaction, check the callbacks
|
||||||
if (mSkipInterceptExecuteTransaction) {
|
if (msg.what == EXECUTE_TRANSACTION) {
|
||||||
break;
|
// Skip the logic if the method is not found or an error occurs
|
||||||
}
|
if (mSkipInterceptExecuteTransaction) {
|
||||||
final Object transaction = msg.obj;
|
return false;
|
||||||
if (transaction == null) {
|
}
|
||||||
Log.w("ResourcesLoader", "transaction is null, skip rest insurance logic.");
|
// Get the transaction object from the message
|
||||||
break;
|
Object transaction = msg.obj;
|
||||||
}
|
if (transaction == null) {
|
||||||
if (mGetCallbacksMethod == null) {
|
Log.w("ResourcesLoader", "transaction is null, skip rest insurance logic.");
|
||||||
try {
|
return false;
|
||||||
mGetCallbacksMethod = ReflectionUtils.findMethod(transaction, "getCallbacks");
|
}
|
||||||
} catch (Throwable ignored) {
|
// Get the getCallbacks method from the transaction class
|
||||||
// Ignored.
|
if (mGetCallbacksMethod == null) {
|
||||||
}
|
try {
|
||||||
}
|
mGetCallbacksMethod = ReflectionUtils.findMethod(transaction, "getCallbacks");
|
||||||
if (mGetCallbacksMethod == null) {
|
} catch (Throwable ignored) {
|
||||||
Log.e("ResourcesLoader", "fail to find getLifecycleStateRequest method, skip rest insurance logic.");
|
// Ignored.
|
||||||
mSkipInterceptExecuteTransaction = true;
|
}
|
||||||
break;
|
}
|
||||||
}
|
if (mGetCallbacksMethod == null) {
|
||||||
try {
|
Log.e("ResourcesLoader", "fail to find getCallbacks method, skip rest insurance logic.");
|
||||||
final List<Object> req = (List<Object>) mGetCallbacksMethod.invoke(transaction);
|
mSkipInterceptExecuteTransaction = true;
|
||||||
if (req != null && req.size() > 0) {
|
return false;
|
||||||
final Object cb = req.get(0);
|
}
|
||||||
shouldReInjectPatchedResources = cb != null && cb.getClass().getName().equals(LAUNCH_ACTIVITY_LIFECYCLE_ITEM_CLASSNAME);
|
try {
|
||||||
}
|
List<Object> callbacks = (List<Object>) mGetCallbacksMethod.invoke(transaction);
|
||||||
} catch (Throwable ignored) {
|
if (callbacks != null && !callbacks.isEmpty()) {
|
||||||
Log.e("ResourcesLoader", "fail to call getLifecycleStateRequest method, skip rest insurance logic.");
|
Object cb = callbacks.get(0);
|
||||||
}
|
return cb != null && cb.getClass().getName().equals(LAUNCH_ACTIVITY_LIFECYCLE_ITEM_CLASSNAME);
|
||||||
} while (false);
|
}
|
||||||
|
} catch (Throwable ignored) {
|
||||||
|
Log.e("ResourcesLoader", "fail to call getCallbacks method, skip rest insurance logic.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (shouldReInjectPatchedResources) {
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// A method to hack the message and re-inject patched resources if needed
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
private boolean hackMessage(Message msg) {
|
||||||
|
if (shouldReInjectPatchedResources(msg)) {
|
||||||
try {
|
try {
|
||||||
load(mContext, mPatchResApkPath, true);
|
load(mContext, mPatchResApkPath, true);
|
||||||
} catch (Throwable thr) {
|
} catch (Throwable thr) {
|
||||||
|
|||||||
@@ -23,8 +23,8 @@ import static ru.vtosters.lite.utils.AndroidUtils.getGlobalContext;
|
|||||||
|
|
||||||
public class PalettesManager {
|
public class PalettesManager {
|
||||||
|
|
||||||
private final static File PALETTES_DIR = new File(Environment.getExternalStorageDirectory(), "VTL/palettes");
|
private static final File PALETTES_DIR = new File(Environment.getExternalStorageDirectory(), "VTL/palettes");
|
||||||
private final static String ASSETS_DIR = "vtl_themes/palettes/";
|
private static final String ASSETS_DIR = "vtl_themes/palettes/";
|
||||||
|
|
||||||
private static PalettesManager sInstance;
|
private static PalettesManager sInstance;
|
||||||
|
|
||||||
@@ -51,17 +51,17 @@ public class PalettesManager {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
final var palettes = PALETTES_DIR.listFiles((dir, name) -> name.endsWith(".json"));
|
var palettes = PALETTES_DIR.listFiles((dir, name) -> name.endsWith(".json"));
|
||||||
if (palettes == null || palettes.length == 0)
|
if (palettes == null || palettes.length == 0)
|
||||||
copyPaletteFromAssets();
|
copyPaletteFromAssets();
|
||||||
parsePalettes();
|
parsePalettes();
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean copyPaletteFromAssets() {
|
private void copyPaletteFromAssets() {
|
||||||
try {
|
try {
|
||||||
final var manager = AndroidUtils.getGlobalContext().getAssets();
|
var manager = AndroidUtils.getGlobalContext().getAssets();
|
||||||
final var assets = manager.list(ASSETS_DIR);
|
var assets = manager.list(ASSETS_DIR);
|
||||||
if (assets == null || assets.length == 0) return false;
|
if (assets == null || assets.length == 0) return;
|
||||||
for (var asset : assets) {
|
for (var asset : assets) {
|
||||||
try {
|
try {
|
||||||
IOUtils.copy(manager.open(ASSETS_DIR + asset), new File(PALETTES_DIR, asset));
|
IOUtils.copy(manager.open(ASSETS_DIR + asset), new File(PALETTES_DIR, asset));
|
||||||
@@ -69,11 +69,9 @@ public class PalettesManager {
|
|||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return true;
|
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void parsePalettes() {
|
private void parsePalettes() {
|
||||||
|
|||||||
@@ -8,15 +8,15 @@ public class ArscEditor {
|
|||||||
|
|
||||||
public static void changeColors(BinaryResourceFile arsc, int[] colorIds, int color) {
|
public static void changeColors(BinaryResourceFile arsc, int[] colorIds, int color) {
|
||||||
for (var chunk : arsc.getChunks()) {
|
for (var chunk : arsc.getChunks()) {
|
||||||
final var resTableChunk = (ResourceTableChunk) chunk;
|
var resTableChunk = (ResourceTableChunk) chunk;
|
||||||
for (var packageChunk : resTableChunk.getPackages()) {
|
for (var packageChunk : resTableChunk.getPackages()) {
|
||||||
for (var typeChunk : packageChunk.getTypeChunks("color")) {
|
for (var typeChunk : packageChunk.getTypeChunks("color")) {
|
||||||
for (var entry : typeChunk.getEntries().entrySet()) {
|
for (var entry : typeChunk.getEntries().entrySet()) {
|
||||||
final var value = entry.getValue();
|
var value = entry.getValue();
|
||||||
if (value.isComplex()) continue;
|
if (value.isComplex()) continue;
|
||||||
final var binValue = value.value();
|
var binValue = value.value();
|
||||||
if (!isColorResourceValue(binValue)) continue;
|
if (!isColorResourceValue(binValue)) continue;
|
||||||
final var resId = packageChunk.getId() << 24 | typeChunk.getId() << 16 | entry.getKey();
|
var resId = packageChunk.getId() << 24 | typeChunk.getId() << 16 | entry.getKey();
|
||||||
for (var colodId : colorIds) {
|
for (var colodId : colorIds) {
|
||||||
if (resId == colodId) {
|
if (resId == colodId) {
|
||||||
binValue.data = color;
|
binValue.data = color;
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ import android.widget.TextView;
|
|||||||
import com.vk.core.drawable.RecoloredDrawable;
|
import com.vk.core.drawable.RecoloredDrawable;
|
||||||
import ru.vtosters.hooks.other.ThemesUtils;
|
import ru.vtosters.hooks.other.ThemesUtils;
|
||||||
import ru.vtosters.lite.themes.ColorReferences;
|
import ru.vtosters.lite.themes.ColorReferences;
|
||||||
|
import ru.vtosters.lite.themes.ThemesManager;
|
||||||
import ru.vtosters.lite.utils.AndroidUtils;
|
import ru.vtosters.lite.utils.AndroidUtils;
|
||||||
|
|
||||||
public class RecolorUtils {
|
public class RecolorUtils {
|
||||||
@@ -43,7 +44,7 @@ public class RecolorUtils {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static int recolorHexColor(int i) {
|
public static int recolorHexColor(int i) {
|
||||||
if (!ThemesUtils.isMonetTheme()) return i;
|
if (!ThemesUtils.isMonetTheme() || !ThemesManager.canApplyCustomAccent()) return i;
|
||||||
var accented = ColorReferences.isAccentedColor(i);
|
var accented = ColorReferences.isAccentedColor(i);
|
||||||
var mutedaccented = ColorReferences.isMutedAccentedColor(i);
|
var mutedaccented = ColorReferences.isMutedAccentedColor(i);
|
||||||
return (accented || mutedaccented) ? (accented ? ThemesUtils.getAccentColor() : ThemesUtils.getMutedAccentColor()) : i;
|
return (accented || mutedaccented) ? (accented ? ThemesUtils.getAccentColor() : ThemesUtils.getMutedAccentColor()) : i;
|
||||||
|
|||||||
@@ -301,7 +301,7 @@ public class PreferenceFragmentUtils {
|
|||||||
return addPreference(screen, key, title, null, null, preference -> {
|
return addPreference(screen, key, title, null, null, preference -> {
|
||||||
LinearLayout linearLayout = new LinearLayout(screen.getContext());
|
LinearLayout linearLayout = new LinearLayout(screen.getContext());
|
||||||
|
|
||||||
final EditText editText = new EditText(screen.getContext());
|
EditText editText = new EditText(screen.getContext());
|
||||||
editText.setText(PreferenceManager.getDefaultSharedPreferences(screen.getContext()).getString(key, ""));
|
editText.setText(PreferenceManager.getDefaultSharedPreferences(screen.getContext()).getString(key, ""));
|
||||||
editText.setHint(title);
|
editText.setHint(title);
|
||||||
editText.setTextColor(ThemesUtils.getTextAttr());
|
editText.setTextColor(ThemesUtils.getTextAttr());
|
||||||
|
|||||||
@@ -36,7 +36,7 @@ public class CategorizedAdapter<T> extends RecyclerView.Adapter<CategorizedAdapt
|
|||||||
private final List<T> mSelectedItems;
|
private final List<T> mSelectedItems;
|
||||||
private final List<T> mDisabledItems;
|
private final List<T> mDisabledItems;
|
||||||
private final List<T> mUnmovedItems;
|
private final List<T> mUnmovedItems;
|
||||||
final private List<T> mExceptions = new ArrayList<>();
|
private final List<T> mExceptions = new ArrayList<>();
|
||||||
private final IViewHolderBinder mBinder;
|
private final IViewHolderBinder mBinder;
|
||||||
|
|
||||||
// Min and max counts
|
// Min and max counts
|
||||||
@@ -50,7 +50,8 @@ public class CategorizedAdapter<T> extends RecyclerView.Adapter<CategorizedAdapt
|
|||||||
this.mBinder = binder;
|
this.mBinder = binder;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setExceptions(T... exceptions) {
|
@SafeVarargs
|
||||||
|
public final void setExceptions(T... exceptions) {
|
||||||
mExceptions.clear();
|
mExceptions.clear();
|
||||||
mExceptions.addAll(Arrays.asList(exceptions));
|
mExceptions.addAll(Arrays.asList(exceptions));
|
||||||
}
|
}
|
||||||
@@ -186,11 +187,16 @@ public class CategorizedAdapter<T> extends RecyclerView.Adapter<CategorizedAdapt
|
|||||||
&& mSelectedItems.size() == mMinSelectedItems))
|
&& mSelectedItems.size() == mMinSelectedItems))
|
||||||
return false;
|
return false;
|
||||||
if (getItemViewType(toPosition) == CATEGORY_TITLE) {
|
if (getItemViewType(toPosition) == CATEGORY_TITLE) {
|
||||||
if (mExceptions.size() > 0) {
|
if (!mExceptions.isEmpty()) {
|
||||||
|
boolean except = false;
|
||||||
int q = 0;
|
int q = 0;
|
||||||
for (var ex : mExceptions)
|
for (var ex : mExceptions) {
|
||||||
if (mSelectedItems.contains(ex)) ++q;
|
var i = mSelectedItems.indexOf(ex);
|
||||||
if (q == 1) return false;
|
if (i == -1) continue;
|
||||||
|
if (i + 1 == fromPosition) except = true;
|
||||||
|
++q;
|
||||||
|
}
|
||||||
|
if (except && q == 1) return false;
|
||||||
}
|
}
|
||||||
mDisabledItems.add(0, mSelectedItems.remove(fromPosition - 1));
|
mDisabledItems.add(0, mSelectedItems.remove(fromPosition - 1));
|
||||||
} else Collections.swap(mSelectedItems, fromPosition - 1, toPosition - 1);
|
} else Collections.swap(mSelectedItems, fromPosition - 1, toPosition - 1);
|
||||||
@@ -218,7 +224,6 @@ public class CategorizedAdapter<T> extends RecyclerView.Adapter<CategorizedAdapt
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static class CategorizedViewHolder extends RecyclerView.ViewHolder {
|
public static class CategorizedViewHolder extends RecyclerView.ViewHolder {
|
||||||
|
|
||||||
private final LinearLayout mMovingItemContainer;
|
private final LinearLayout mMovingItemContainer;
|
||||||
private final ImageView mIcon;
|
private final ImageView mIcon;
|
||||||
private final TextView mName;
|
private final TextView mName;
|
||||||
|
|||||||
@@ -18,7 +18,6 @@ import ru.vtosters.hooks.other.ThemesUtils;
|
|||||||
import ru.vtosters.lite.utils.AndroidUtils;
|
import ru.vtosters.lite.utils.AndroidUtils;
|
||||||
|
|
||||||
public class MessagesPreviewAdapter extends RecyclerView.Adapter<MessagesPreviewAdapter.MessagePreviewViewHolder> {
|
public class MessagesPreviewAdapter extends RecyclerView.Adapter<MessagesPreviewAdapter.MessagePreviewViewHolder> {
|
||||||
|
|
||||||
private final String[] mMessages;
|
private final String[] mMessages;
|
||||||
|
|
||||||
public MessagesPreviewAdapter(String... messages) {
|
public MessagesPreviewAdapter(String... messages) {
|
||||||
@@ -35,9 +34,9 @@ public class MessagesPreviewAdapter extends RecyclerView.Adapter<MessagesPreview
|
|||||||
public MessagePreviewViewHolder onCreateViewHolder(@NonNull ViewGroup viewGroup, int viewType) {
|
public MessagePreviewViewHolder onCreateViewHolder(@NonNull ViewGroup viewGroup, int viewType) {
|
||||||
Context context = viewGroup.getContext();
|
Context context = viewGroup.getContext();
|
||||||
|
|
||||||
final var inflater = LayoutInflater.from(context);
|
var inflater = LayoutInflater.from(context);
|
||||||
|
|
||||||
final var bubbleFluidLayout = (BubbleFluidLayout) inflater.inflate(R.layout.vkim_msg_list_item_msg_from_user, viewGroup, false);
|
var bubbleFluidLayout = (BubbleFluidLayout) inflater.inflate(R.layout.vkim_msg_list_item_msg_from_user, viewGroup, false);
|
||||||
bubbleFluidLayout.setPadding(0, AndroidUtils.dp2px(4), 0, 0);
|
bubbleFluidLayout.setPadding(0, AndroidUtils.dp2px(4), 0, 0);
|
||||||
bubbleFluidLayout.setGravity(viewType);
|
bubbleFluidLayout.setGravity(viewType);
|
||||||
|
|
||||||
@@ -47,7 +46,7 @@ public class MessagesPreviewAdapter extends RecyclerView.Adapter<MessagesPreview
|
|||||||
bubbleFluidLayout.findViewById(R.id.status).setVisibility(View.GONE);
|
bubbleFluidLayout.findViewById(R.id.status).setVisibility(View.GONE);
|
||||||
bubbleFluidLayout.findViewById(R.id.status_space).setVisibility(View.GONE);
|
bubbleFluidLayout.findViewById(R.id.status_space).setVisibility(View.GONE);
|
||||||
|
|
||||||
final var messageBubbleView = (MsgBubbleView) bubbleFluidLayout.findViewById(R.id.bubble);
|
var messageBubbleView = (MsgBubbleView) bubbleFluidLayout.findViewById(R.id.bubble);
|
||||||
messageBubbleView.setContentPaddingLeft(AndroidUtils.dp2px(10));
|
messageBubbleView.setContentPaddingLeft(AndroidUtils.dp2px(10));
|
||||||
messageBubbleView.setContentPaddingTop(AndroidUtils.dp2px(4));
|
messageBubbleView.setContentPaddingTop(AndroidUtils.dp2px(4));
|
||||||
messageBubbleView.setContentPaddingRight(AndroidUtils.dp2px(4));
|
messageBubbleView.setContentPaddingRight(AndroidUtils.dp2px(4));
|
||||||
@@ -59,10 +58,10 @@ public class MessagesPreviewAdapter extends RecyclerView.Adapter<MessagesPreview
|
|||||||
}
|
}
|
||||||
bubbleFluidLayout.setLayoutDirection(viewType);
|
bubbleFluidLayout.setLayoutDirection(viewType);
|
||||||
|
|
||||||
final var msgTextView = inflater.inflate(R.layout.vkim_msg_part_text, viewGroup, false);
|
var msgTextView = inflater.inflate(R.layout.vkim_msg_part_text, viewGroup, false);
|
||||||
msgTextView.setId(R.id.msg_text);
|
msgTextView.setId(R.id.msg_text);
|
||||||
|
|
||||||
final var msgBubbleView = (MsgBubbleView) bubbleFluidLayout.findViewById(R.id.bubble);
|
var msgBubbleView = (MsgBubbleView) bubbleFluidLayout.findViewById(R.id.bubble);
|
||||||
msgBubbleView.setContentView(msgTextView);
|
msgBubbleView.setContentView(msgTextView);
|
||||||
|
|
||||||
return new MessagePreviewViewHolder(bubbleFluidLayout);
|
return new MessagePreviewViewHolder(bubbleFluidLayout);
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
package ru.vtosters.lite.ui.adapters;
|
package ru.vtosters.lite.ui.adapters;
|
||||||
|
|
||||||
import android.annotation.SuppressLint;
|
import android.annotation.SuppressLint;
|
||||||
|
import android.content.Intent;
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
@@ -28,6 +29,7 @@ import ru.vtosters.hooks.SwitchHook;
|
|||||||
import ru.vtosters.lite.tgs.TGPref;
|
import ru.vtosters.lite.tgs.TGPref;
|
||||||
import ru.vtosters.lite.tgs.TGRoot;
|
import ru.vtosters.lite.tgs.TGRoot;
|
||||||
import ru.vtosters.lite.ui.components.IItemMovingListener;
|
import ru.vtosters.lite.ui.components.IItemMovingListener;
|
||||||
|
import ru.vtosters.lite.ui.fragments.VTSettings;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
@@ -138,7 +140,11 @@ public class StickerPackAdapter extends RecyclerView.Adapter<StickerPackAdapter.
|
|||||||
});
|
});
|
||||||
mName.setText(pack.title);
|
mName.setText(pack.title);
|
||||||
mSwitch.setChecked(pack.enabled);
|
mSwitch.setChecked(pack.enabled);
|
||||||
mSwitch.setOnCheckedChangeListener((buttonView, isChecked) -> sService.setPackEnabled(pack, isChecked, true));
|
mSwitch.setOnCheckedChangeListener((buttonView, isChecked) -> {
|
||||||
|
sService.setPackEnabled(pack, isChecked, false);
|
||||||
|
buttonView.getContext().sendBroadcast(new Intent(VTSettings.ACTION_INVALIDATE_TGS_COUNT));
|
||||||
|
});
|
||||||
|
|
||||||
mStickersCount.setText(pack.stickersCount + " " + mStickersCount.getContext().getString(R.string.stickerscount));
|
mStickersCount.setText(pack.stickersCount + " " + mStickersCount.getContext().getString(R.string.stickerscount));
|
||||||
|
|
||||||
SwitchHook.setSwitchCompatColors(mSwitch, mSwitch.getContext());
|
SwitchHook.setSwitchCompatColors(mSwitch, mSwitch.getContext());
|
||||||
|
|||||||
@@ -17,8 +17,8 @@ public class DisableBattery {
|
|||||||
public static void alert(Activity activity) {
|
public static void alert(Activity activity) {
|
||||||
if (!(OEMDetector.isOEM() && Build.VERSION.SDK_INT >= 23 && Preferences.getBoolValue("showDoze", true)))
|
if (!(OEMDetector.isOEM() && Build.VERSION.SDK_INT >= 23 && Preferences.getBoolValue("showDoze", true)))
|
||||||
return;
|
return;
|
||||||
final String packName = activity.getPackageName();
|
String packName = activity.getPackageName();
|
||||||
final PowerManager manager = (PowerManager) activity.getSystemService(Context.POWER_SERVICE);
|
PowerManager manager = (PowerManager) activity.getSystemService(Context.POWER_SERVICE);
|
||||||
if (manager.isIgnoringBatteryOptimizations(packName)) return;
|
if (manager.isIgnoringBatteryOptimizations(packName)) return;
|
||||||
new VkAlertDialog.Builder(activity)
|
new VkAlertDialog.Builder(activity)
|
||||||
.setTitle(R.string.batteryissuetitle)
|
.setTitle(R.string.batteryissuetitle)
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
package ru.vtosters.lite.ui.dialogs;
|
package ru.vtosters.lite.ui.dialogs;
|
||||||
|
|
||||||
|
import android.annotation.SuppressLint;
|
||||||
import android.app.Activity;
|
import android.app.Activity;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.widget.LinearLayout;
|
import android.widget.LinearLayout;
|
||||||
@@ -41,6 +42,7 @@ public class OTADialog extends ModalBottomSheetWrapper<OTADialog> implements OTA
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@SuppressLint("SetTextI18n")
|
||||||
private View makeUpdateInfoView(String changelog) {
|
private View makeUpdateInfoView(String changelog) {
|
||||||
LinearLayout container = new LinearLayout(mActivity);
|
LinearLayout container = new LinearLayout(mActivity);
|
||||||
TextView changelogView = new TextView(mActivity);
|
TextView changelogView = new TextView(mActivity);
|
||||||
|
|||||||
@@ -123,6 +123,8 @@ public class MediaFragment extends TrackedMaterialPreferenceToolbarFragment {
|
|||||||
return true;
|
return true;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
findPreference("invertCachedTracks").setVisible(CacheDatabaseDelegate.hasTracks());
|
||||||
|
|
||||||
if (!LibVKXClient.isVkxInstalled()) {
|
if (!LibVKXClient.isVkxInstalled()) {
|
||||||
findPreference("vkx_sett").setVisible(false);
|
findPreference("vkx_sett").setVisible(false);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,13 +1,15 @@
|
|||||||
package ru.vtosters.lite.ui.fragments;
|
package ru.vtosters.lite.ui.fragments;
|
||||||
|
|
||||||
|
import android.content.BroadcastReceiver;
|
||||||
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
|
import android.content.IntentFilter;
|
||||||
import android.graphics.drawable.Drawable;
|
import android.graphics.drawable.Drawable;
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
import android.os.Build;
|
import android.os.Build;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import androidx.annotation.StringRes;
|
import androidx.annotation.StringRes;
|
||||||
import androidx.preference.Preference;
|
import androidx.preference.Preference;
|
||||||
import com.aefyr.tsg.g2.TelegramStickersPack;
|
|
||||||
import com.aefyr.tsg.g2.TelegramStickersService;
|
import com.aefyr.tsg.g2.TelegramStickersService;
|
||||||
import com.vk.about.AboutAppFragment;
|
import com.vk.about.AboutAppFragment;
|
||||||
import com.vk.balance.BalanceFragment;
|
import com.vk.balance.BalanceFragment;
|
||||||
@@ -42,7 +44,19 @@ import ru.vtosters.lite.utils.*;
|
|||||||
|
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
|
|
||||||
public class VTSettings extends TrackedMaterialPreferenceToolbarFragment implements TelegramStickersService.StickersEventsListener {
|
public class VTSettings extends TrackedMaterialPreferenceToolbarFragment {
|
||||||
|
|
||||||
|
final static public String ACTION_INVALIDATE_TGS_COUNT="com.vtosters.lite.intent.action.INVALIDATE_TGS_COUNT";
|
||||||
|
|
||||||
|
final BroadcastReceiver mTgsReceiver=new BroadcastReceiver()
|
||||||
|
{
|
||||||
|
@Override
|
||||||
|
public void onReceive(Context context, Intent intent)
|
||||||
|
{
|
||||||
|
if(ACTION_INVALIDATE_TGS_COUNT.equals(intent.getAction()))
|
||||||
|
findPreference("tgs_stickers").setSummary(getTGSsumm());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
public static String getValAsString(@StringRes int strRes, Boolean value) {
|
public static String getValAsString(@StringRes int strRes, Boolean value) {
|
||||||
if (value) {
|
if (value) {
|
||||||
@@ -76,42 +90,12 @@ public class VTSettings extends TrackedMaterialPreferenceToolbarFragment impleme
|
|||||||
ThemesUtils.setTheme(isDarkTheme ? ThemesUtils.getDarkTheme() : ThemesUtils.getLightTheme(), requireActivity(), true);
|
ThemesUtils.setTheme(isDarkTheme ? ThemesUtils.getDarkTheme() : ThemesUtils.getLightTheme(), requireActivity(), true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onPackAdded(TelegramStickersPack pack, int atIndex) {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onPackRemoved(TelegramStickersPack pack, int atIndex) {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onPackChanged(TelegramStickersPack pack, int atIndex) {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onPackDownloadError(TelegramStickersPack pack, Exception error) {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onActivePacksListChanged() {
|
|
||||||
findPreference("tgs_stickers").setSummary(getTGSsumm());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onInactivePacksListChanged() {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@SuppressWarnings("ConstantConditions")
|
@SuppressWarnings("ConstantConditions")
|
||||||
@Override
|
@Override
|
||||||
public void onCreate(Bundle bundle) {
|
public void onCreate(Bundle bundle) {
|
||||||
super.onCreate(bundle);
|
super.onCreate(bundle);
|
||||||
|
|
||||||
TelegramStickersService.getInstance(requireContext()).addStickersEventsListener(this);
|
requireContext().registerReceiver(mTgsReceiver,new IntentFilter(ACTION_INVALIDATE_TGS_COUNT));
|
||||||
|
|
||||||
this.addPreferencesFromResource(R.xml.empty);
|
this.addPreferencesFromResource(R.xml.empty);
|
||||||
|
|
||||||
@@ -590,18 +574,14 @@ public class VTSettings extends TrackedMaterialPreferenceToolbarFragment impleme
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onResume() {
|
public void onDestroy()
|
||||||
super.onResume();
|
{
|
||||||
|
requireContext().unregisterReceiver(mTgsReceiver);
|
||||||
|
super.onDestroy();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int T4() {
|
public int T4() {
|
||||||
return R.string.notification_settings;
|
return R.string.notification_settings;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onDestroyView() {
|
|
||||||
super.onDestroyView();
|
|
||||||
TelegramStickersService.getInstance(requireContext()).removeStickersEventsListener(this);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
+162
-169
@@ -20,7 +20,6 @@ import androidx.recyclerview.widget.RecyclerView;
|
|||||||
import androidx.recyclerview.widget.StaggeredGridLayoutManager;
|
import androidx.recyclerview.widget.StaggeredGridLayoutManager;
|
||||||
import com.aefyr.tsg.g2.TelegramStickersService;
|
import com.aefyr.tsg.g2.TelegramStickersService;
|
||||||
import com.aefyr.tsg.g2.stickersgrabber.TelegramStickersGrabber;
|
import com.aefyr.tsg.g2.stickersgrabber.TelegramStickersGrabber;
|
||||||
import com.google.android.material.floatingactionbutton.FloatingActionButton;
|
|
||||||
import com.vk.core.dialogs.alert.VkAlertDialog;
|
import com.vk.core.dialogs.alert.VkAlertDialog;
|
||||||
import com.vtosters.lite.R;
|
import com.vtosters.lite.R;
|
||||||
import ru.vtosters.hooks.other.ThemesUtils;
|
import ru.vtosters.hooks.other.ThemesUtils;
|
||||||
@@ -36,55 +35,58 @@ import java.io.File;
|
|||||||
public class StickersFragment extends BaseToolbarFragment {
|
public class StickersFragment extends BaseToolbarFragment {
|
||||||
public final static String ACTION_RELOAD = "com.vtosters.lite.action.RELOAD_TGS_LIST";
|
public final static String ACTION_RELOAD = "com.vtosters.lite.action.RELOAD_TGS_LIST";
|
||||||
|
|
||||||
private final static int TYPE_DIRECT = 0, TYPE_SOCKS = 2;
|
final static int TYPE_DIRECT = 0;
|
||||||
public int from;
|
final static int TYPE_SOCKS = 2;
|
||||||
public int to;
|
|
||||||
private TelegramStickersGrabber mGrabber;
|
TelegramStickersGrabber mGrabber;
|
||||||
private TelegramStickersService mService;
|
StickerPackAdapter mAdapter;
|
||||||
private StickerPackAdapter mAdapter;
|
boolean movePending = false;
|
||||||
private boolean movePending = false;
|
int from,to;
|
||||||
private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
|
final BroadcastReceiver mReceiver=new BroadcastReceiver() {
|
||||||
@SuppressLint("NotifyDataSetChanged")
|
@SuppressLint("NotifyDataSetChanged")
|
||||||
@Override
|
@Override
|
||||||
public void onReceive(Context context, Intent intent) {
|
public void onReceive(Context context, Intent intent) {
|
||||||
if (intent.getAction().equals(ACTION_RELOAD)) {
|
if (!intent.getAction().equals(ACTION_RELOAD)||mAdapter==null)return;
|
||||||
if (mAdapter != null) {
|
try
|
||||||
try {
|
{
|
||||||
if (movePending) {
|
if(movePending)
|
||||||
movePending = false;
|
{
|
||||||
mAdapter.notifyItemMoved(from, to);
|
movePending=false;
|
||||||
from = -1;
|
mAdapter.notifyItemMoved(from, to);
|
||||||
to = -1;
|
from=to=-1;
|
||||||
} else {
|
|
||||||
mAdapter.notifyDataSetChanged();
|
|
||||||
}
|
|
||||||
} catch (Exception e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
else mAdapter.notifyDataSetChanged();
|
||||||
}
|
}
|
||||||
|
catch(Exception e)
|
||||||
|
{ e.printStackTrace(); }
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onCreateMenu(Menu menu) {
|
protected void onCreateMenu(Menu menu)
|
||||||
MenuItem item = menu.add(0, 0, 0, "");
|
{
|
||||||
item.setIcon(ThemesUtils.recolorDrawable(AndroidUtils.getGlobalContext().getDrawable(R.drawable.ic_settings_outline_28)))
|
menu.add(0, 0, 0, "")
|
||||||
.setShowAsAction(MenuItem.SHOW_AS_ACTION_ALWAYS);
|
.setIcon(ThemesUtils.recolorDrawable(requireContext().getDrawable(R.drawable.ic_add_outline_28)))
|
||||||
|
.setShowAsAction(MenuItem.SHOW_AS_ACTION_ALWAYS);
|
||||||
|
menu.add(0,1,0,"")
|
||||||
|
.setIcon(R.drawable.ic_settings_outline_28)
|
||||||
|
.setShowAsAction(MenuItem.SHOW_AS_ACTION_ALWAYS);
|
||||||
super.onCreateMenu(menu);
|
super.onCreateMenu(menu);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean onOptionsItemSelected(MenuItem arg0) {
|
public boolean onOptionsItemSelected(MenuItem item)
|
||||||
openMenu(null);
|
{
|
||||||
|
switch (item.getItemId())
|
||||||
|
{
|
||||||
|
case 0 -> addTgsPack();
|
||||||
|
case 1 -> openMenu(null);
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void openMenu(String toast) {
|
private void openMenu(String toast) {
|
||||||
if (toast != null) {
|
if(toast!=null)Toast.makeText(requireContext(),toast,Toast.LENGTH_SHORT).show();
|
||||||
Toast.makeText(requireContext(), toast, Toast.LENGTH_SHORT).show();
|
|
||||||
}
|
|
||||||
NavigatorUtils.switchFragment(requireContext(), StickersPreferencesFragment.class);
|
NavigatorUtils.switchFragment(requireContext(), StickersPreferencesFragment.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -93,41 +95,29 @@ public class StickersFragment extends BaseToolbarFragment {
|
|||||||
super.onCreate(savedInstanceState);
|
super.onCreate(savedInstanceState);
|
||||||
requireContext().registerReceiver(mReceiver, new IntentFilter(ACTION_RELOAD));
|
requireContext().registerReceiver(mReceiver, new IntentFilter(ACTION_RELOAD));
|
||||||
|
|
||||||
mGrabber = new TelegramStickersGrabber(TGPref.getTGBotKey());
|
mGrabber=new TelegramStickersGrabber(TGPref.getTGBotKey());
|
||||||
mService = TelegramStickersService.getInstance(requireContext());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public View onCreateContent(@NonNull LayoutInflater inflater, @Nullable Bundle bundle) {
|
public View onCreateContent(@NonNull LayoutInflater inflater, @Nullable Bundle bundle) {
|
||||||
setTitle(R.string.vtltgs);
|
setTitle(R.string.vtltgs);
|
||||||
|
|
||||||
FrameLayout layout = new FrameLayout(requireContext());
|
final var container=new FrameLayout(requireContext());
|
||||||
|
final var recycler=new RecyclerView(requireContext());
|
||||||
|
|
||||||
mAdapter = new StickerPackAdapter();
|
mAdapter=new StickerPackAdapter();
|
||||||
RecyclerView mRecycler = new RecyclerView(requireContext());
|
recycler.setAdapter(mAdapter);
|
||||||
|
|
||||||
StickerTouchHelperCallback callback = new StickerTouchHelperCallback(mAdapter);
|
final var callback=new StickerTouchHelperCallback(mAdapter);
|
||||||
ItemTouchHelper touchHelper = new ItemTouchHelper(callback);
|
final var touchHelper=new ItemTouchHelper(callback);
|
||||||
touchHelper.attachToRecyclerView(mRecycler);
|
touchHelper.attachToRecyclerView(recycler);
|
||||||
|
|
||||||
mRecycler.setAdapter(mAdapter);
|
recycler.setLayoutManager(new StaggeredGridLayoutManager(2,StaggeredGridLayoutManager.VERTICAL));
|
||||||
mRecycler.setLayoutManager(new StaggeredGridLayoutManager(2, StaggeredGridLayoutManager.VERTICAL));
|
container.addView(recycler,new ViewGroup.LayoutParams(-1,-1));
|
||||||
layout.addView(mRecycler, new ViewGroup.LayoutParams(-1, -1));
|
|
||||||
|
|
||||||
FloatingActionButton mAddStickerPack = new FloatingActionButton(requireContext());
|
return container;
|
||||||
mAddStickerPack.setImageResource(R.drawable.ic_add_24);
|
|
||||||
mAddStickerPack.setBackgroundTintList(ThemesUtils.getAccenedColorStateList());
|
|
||||||
mAddStickerPack.setOnClickListener(v2 -> fabClick());
|
|
||||||
|
|
||||||
FrameLayout.LayoutParams params = new FrameLayout.LayoutParams(-2, -2);
|
|
||||||
params.gravity = Gravity.BOTTOM | Gravity.CENTER_HORIZONTAL;
|
|
||||||
params.setMargins(0, 0, 0, AndroidUtils.dp2px(12f));
|
|
||||||
layout.addView(mAddStickerPack, params);
|
|
||||||
|
|
||||||
return layout;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onViewCreated(View arg0, Bundle arg1) {
|
public void onViewCreated(View arg0, Bundle arg1) {
|
||||||
super.onViewCreated(arg0, arg1);
|
super.onViewCreated(arg0, arg1);
|
||||||
@@ -139,70 +129,79 @@ public class StickersFragment extends BaseToolbarFragment {
|
|||||||
requireContext().unregisterReceiver(mReceiver);
|
requireContext().unregisterReceiver(mReceiver);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void fabClick() {
|
private void addTgsPack()
|
||||||
int method = TGPref.getTGConnectMethod();
|
{
|
||||||
if (method == -1) {
|
final var method=TGPref.getTGConnectMethod();
|
||||||
openMenu(requireContext().getString(R.string.stickersconnection));
|
if(method!=-1)
|
||||||
return;
|
{
|
||||||
}
|
initGrabber();
|
||||||
|
switch(method)
|
||||||
|
{
|
||||||
|
case TYPE_SOCKS ->
|
||||||
|
{
|
||||||
|
if (TGPref.getTGProxyIP()==null)openMenu(requireContext().getString(R.string.stickersproxy1));
|
||||||
|
}
|
||||||
|
case TYPE_DIRECT ->
|
||||||
|
{
|
||||||
|
initGrabber();
|
||||||
|
final Runnable lambda = () ->
|
||||||
|
{
|
||||||
|
final var container=new LinearLayout(requireContext());
|
||||||
|
|
||||||
initGrabber();
|
final var input=new EditText(requireContext());
|
||||||
if (method == TYPE_SOCKS) {
|
final var inputLP = new ViewGroup.MarginLayoutParams(-1,-2);
|
||||||
if (TGPref.getTGProxyIP() == null) {
|
inputLP.setMargins(
|
||||||
openMenu(requireContext().getString(R.string.stickersproxy1));
|
AndroidUtils.dp2px(24.f),
|
||||||
|
0,
|
||||||
|
AndroidUtils.dp2px(24.f),
|
||||||
|
0);
|
||||||
|
container.addView(input,inputLP);
|
||||||
|
|
||||||
|
new VkAlertDialog.Builder(requireContext())
|
||||||
|
.setTitle(R.string.stickershelp1)
|
||||||
|
// .setMessage(R.string.stickershelp2)
|
||||||
|
.setView(container)
|
||||||
|
.setPositiveButton(android.R.string.ok, (dialog, which) ->
|
||||||
|
{
|
||||||
|
var packId=input.getText().toString();
|
||||||
|
if (packId.startsWith("https://"))
|
||||||
|
packId=packId.substring(packId.lastIndexOf('/')+1);
|
||||||
|
TelegramStickersService.getInstance(requireContext())
|
||||||
|
.requestPackDownload(
|
||||||
|
packId,
|
||||||
|
new File(requireContext().getFilesDir(),"VT-Stickers/"+packId));
|
||||||
|
})
|
||||||
|
.setNeutralButton(android.R.string.cancel,(dialog, which) -> dialog.dismiss())
|
||||||
|
.show();
|
||||||
|
};
|
||||||
|
|
||||||
|
if(TGPref.getTGBotKey()==null)enterBotKey(() -> checkApiKey(lambda));
|
||||||
|
else checkApiKey(lambda);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else if (method == TYPE_DIRECT) {
|
|
||||||
final Runnable callback = () -> {
|
|
||||||
LinearLayout linearLayout = new LinearLayout(requireContext());
|
|
||||||
|
|
||||||
final EditText editText = new EditText(requireContext());
|
|
||||||
editText.setHintTextColor(ThemesUtils.getSTextAttr());
|
|
||||||
editText.setBackgroundTintList(ThemesUtils.getAccenedColorStateList());
|
|
||||||
|
|
||||||
linearLayout.addView(editText);
|
|
||||||
editText.getLayoutParams().width = ViewGroup.LayoutParams.MATCH_PARENT;
|
|
||||||
ViewGroup.MarginLayoutParams margin = ((ViewGroup.MarginLayoutParams) editText.getLayoutParams());
|
|
||||||
margin.setMargins(AndroidUtils.dp2px(24f), 0, AndroidUtils.dp2px(24f), 0);
|
|
||||||
editText.setLayoutParams(margin);
|
|
||||||
|
|
||||||
new VkAlertDialog.Builder(requireContext())
|
|
||||||
.setTitle(requireContext().getString(R.string.stickershelp1))
|
|
||||||
.setMessage(requireContext().getString(R.string.stickershelp2))
|
|
||||||
.setView(linearLayout)
|
|
||||||
.setPositiveButton(android.R.string.ok, (dialog, which) -> {
|
|
||||||
String pack = editText.getText().toString();
|
|
||||||
if (!pack.startsWith("https://")) {
|
|
||||||
pack = "https://" + pack;
|
|
||||||
} else if (!pack.contains("addstickers")) {
|
|
||||||
AndroidUtils.sendToast(AndroidUtils.getString("invalid_pack_link"));
|
|
||||||
}
|
|
||||||
pack = parsePack(pack);
|
|
||||||
mService.requestPackDownload(pack, new File(requireContext().getFilesDir(), new File("VT-Stickers", pack).getAbsolutePath()));
|
|
||||||
})
|
|
||||||
.setNeutralButton(android.R.string.cancel,
|
|
||||||
(dialog, which) -> dialog.dismiss()
|
|
||||||
)
|
|
||||||
.show();
|
|
||||||
};
|
|
||||||
if (TGPref.getTGBotKey() == null) enterBotKey(() -> checkApiKey(callback));
|
|
||||||
else checkApiKey(callback);
|
|
||||||
}
|
}
|
||||||
|
else openMenu(requireContext().getString(R.string.stickersconnection));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void initGrabber() {
|
private void initGrabber() {
|
||||||
int method = TGPref.getTGConnectMethod();
|
switch(TGPref.getTGConnectMethod())
|
||||||
if (method == TYPE_DIRECT) {
|
{
|
||||||
TelegramStickersGrabber.USE_PROXY = false;
|
case TYPE_DIRECT ->
|
||||||
mGrabber.resetProxy();
|
{
|
||||||
} else if (method == TYPE_SOCKS) {
|
TelegramStickersGrabber.USE_PROXY=false;
|
||||||
if (TGPref.getTGProxyIP() != null) {
|
mGrabber.resetProxy();
|
||||||
TelegramStickersGrabber.USE_PROXY = true;
|
}
|
||||||
TelegramStickersGrabber.PROXY_IP = TGPref.getTGProxyIP();
|
case TYPE_SOCKS ->
|
||||||
TelegramStickersGrabber.PROXY_PORT = TGPref.getTGProxyPort();
|
{
|
||||||
if (TGPref.isTGProxyPassEnabled()) {
|
if(TGPref.getTGProxyIP()==null)break;
|
||||||
TelegramStickersGrabber.HAS_PASS = true;
|
TelegramStickersGrabber.USE_PROXY=true;
|
||||||
TelegramStickersGrabber.PROXY_USER = TGPref.getTGProxyUser();
|
TelegramStickersGrabber.PROXY_IP=TGPref.getTGProxyIP();
|
||||||
TelegramStickersGrabber.PROXY_PASS = TGPref.getTGProxyPass();
|
TelegramStickersGrabber.PROXY_PORT=TGPref.getTGProxyPort();
|
||||||
|
if (TGPref.isTGProxyPassEnabled())
|
||||||
|
{
|
||||||
|
TelegramStickersGrabber.HAS_PASS=true;
|
||||||
|
TelegramStickersGrabber.PROXY_USER=TGPref.getTGProxyUser();
|
||||||
|
TelegramStickersGrabber.PROXY_PASS=TGPref.getTGProxyPass();
|
||||||
}
|
}
|
||||||
mGrabber.enableProxy();
|
mGrabber.enableProxy();
|
||||||
}
|
}
|
||||||
@@ -210,42 +209,42 @@ public class StickersFragment extends BaseToolbarFragment {
|
|||||||
TelegramStickersGrabber.updateURLs();
|
TelegramStickersGrabber.updateURLs();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void enterBotKey(Runnable r) {
|
private void enterBotKey(Runnable callback)
|
||||||
LinearLayout linearLayout = new LinearLayout(requireContext());
|
{
|
||||||
|
final var container=new LinearLayout(requireContext());
|
||||||
|
|
||||||
final EditText editText = new EditText(requireContext());
|
final var input=new EditText(requireContext());
|
||||||
editText.setHintTextColor(ThemesUtils.getSTextAttr());
|
final var inputLP=new ViewGroup.MarginLayoutParams(-1,-2);
|
||||||
editText.setBackgroundTintList(ThemesUtils.getAccenedColorStateList());
|
inputLP.setMargins(
|
||||||
|
AndroidUtils.dp2px(24.f),
|
||||||
linearLayout.addView(editText);
|
0,
|
||||||
editText.getLayoutParams().width = ViewGroup.LayoutParams.MATCH_PARENT;
|
AndroidUtils.dp2px(24.f),
|
||||||
ViewGroup.MarginLayoutParams margin = ((ViewGroup.MarginLayoutParams) editText.getLayoutParams());
|
0);
|
||||||
margin.setMargins(AndroidUtils.dp2px(24f), 0, AndroidUtils.dp2px(24f), 0);
|
container.addView(input,inputLP);
|
||||||
editText.setLayoutParams(margin);
|
|
||||||
|
|
||||||
new VkAlertDialog.Builder(requireContext())
|
new VkAlertDialog.Builder(requireContext())
|
||||||
.setTitle(requireContext().getString(R.string.stickersapi5))
|
.setTitle(requireContext().getString(R.string.stickersapi5))
|
||||||
.setMessage(requireContext().getString(R.string.stickersapi6))
|
.setMessage(requireContext().getString(R.string.stickersapi6))
|
||||||
.setView(linearLayout)
|
.setView(container)
|
||||||
.setPositiveButton(android.R.string.ok, (dialog, which) -> {
|
.setPositiveButton(android.R.string.ok,(dialog, which) ->
|
||||||
TGPref.setTGBotKey(editText.getText().toString());
|
{
|
||||||
if (r != null) r.run();
|
TGPref.setTGBotKey(input.getText().toString());
|
||||||
|
if(callback!=null)callback.run();
|
||||||
})
|
})
|
||||||
.setNegativeButton(android.R.string.cancel,
|
.setNegativeButton(android.R.string.cancel,(dialog, which) -> dialog.dismiss())
|
||||||
(dialog, which) -> dialog.dismiss()
|
|
||||||
)
|
|
||||||
.setNeutralButton(requireContext().getString(R.string.stickersapi7),
|
.setNeutralButton(requireContext().getString(R.string.stickersapi7),
|
||||||
(dialog, which) -> new VkAlertDialog.Builder(requireContext())
|
(dialog, which) ->
|
||||||
.setTitle(requireContext().getString(R.string.stickersapi8))
|
new VkAlertDialog.Builder(requireContext())
|
||||||
.setMessage(requireContext().getString(R.string.stickersapi9) +
|
.setTitle(requireContext().getString(R.string.stickersapi8))
|
||||||
requireContext().getString(R.string.stickersapi10))
|
.setMessage(requireContext().getString(R.string.stickersapi9) +
|
||||||
.setNeutralButton(AndroidUtils.getString("open_bot"), (dl, i) -> {
|
requireContext().getString(R.string.stickersapi10))
|
||||||
var intent = new Intent(Intent.ACTION_VIEW, Uri.parse("https://t.me/botfather"));
|
.setNeutralButton(AndroidUtils.getString("open_bot"),(dl, i) -> {
|
||||||
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
final var intent=new Intent(Intent.ACTION_VIEW,Uri.parse("https://t.me/botfather"))
|
||||||
requireActivity().startActivity(intent);
|
.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||||
})
|
requireActivity().startActivity(intent);
|
||||||
.setPositiveButton(android.R.string.ok, null)
|
})
|
||||||
.show()
|
.setPositiveButton(android.R.string.ok, null)
|
||||||
|
.show()
|
||||||
)
|
)
|
||||||
.show();
|
.show();
|
||||||
}
|
}
|
||||||
@@ -253,45 +252,39 @@ public class StickersFragment extends BaseToolbarFragment {
|
|||||||
private void checkApiKey(Runnable callback) {
|
private void checkApiKey(Runnable callback) {
|
||||||
mGrabber.setBotApiKey(TGPref.getTGBotKey());
|
mGrabber.setBotApiKey(TGPref.getTGBotKey());
|
||||||
|
|
||||||
var context = requireContext();
|
final var dialog=new ProgressDialog(requireContext());
|
||||||
|
dialog.setProgressStyle(ProgressDialog.STYLE_SPINNER);
|
||||||
|
dialog.setMessage(requireContext().getString(R.string.stickersapi1));
|
||||||
|
dialog.show();
|
||||||
|
|
||||||
final ProgressDialog progressDialog = new ProgressDialog(context);
|
mGrabber.checkKey(new TelegramStickersGrabber.KeyCheckListener()
|
||||||
progressDialog.setProgressStyle(ProgressDialog.STYLE_SPINNER);
|
{
|
||||||
progressDialog.setMessage(requireContext().getString(R.string.stickersapi1));
|
|
||||||
progressDialog.show();
|
|
||||||
|
|
||||||
mGrabber.checkKey(new TelegramStickersGrabber.KeyCheckListener() {
|
|
||||||
@Override
|
@Override
|
||||||
public void onKeyChecked(boolean ok) {
|
public void onKeyChecked(boolean ok)
|
||||||
progressDialog.dismiss();
|
{
|
||||||
if (!ok) {
|
dialog.dismiss();
|
||||||
Toast.makeText(context, requireContext().getString(R.string.stickersapi2), Toast.LENGTH_SHORT).show();
|
if (!ok)
|
||||||
|
{
|
||||||
|
Toast.makeText(requireContext(), requireContext().getString(R.string.stickersapi2),Toast.LENGTH_SHORT).show();
|
||||||
TGPref.setTGBotKey(null);
|
TGPref.setTGBotKey(null);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
mService.setBotKey(TGPref.getTGBotKey());
|
TelegramStickersService.getInstance(requireContext())
|
||||||
|
.setBotKey(TGPref.getTGBotKey());
|
||||||
|
|
||||||
if (callback != null) callback.run();
|
if (callback!=null)callback.run();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onNetError() {
|
public void onNetError()
|
||||||
progressDialog.dismiss();
|
{
|
||||||
new VkAlertDialog.Builder(context)
|
dialog.dismiss();
|
||||||
|
new VkAlertDialog.Builder(requireContext())
|
||||||
.setMessage(requireContext().getString(R.string.stickersapi3))
|
.setMessage(requireContext().getString(R.string.stickersapi3))
|
||||||
.setNegativeButton(android.R.string.cancel, null)
|
.setNegativeButton(android.R.string.cancel, null)
|
||||||
.setPositiveButton(requireContext().getString(R.string.stickersapi4), (arg0, arg1) -> checkApiKey(callback))
|
.setPositiveButton(requireContext().getString(R.string.stickersapi4),(di,which) -> checkApiKey(callback))
|
||||||
.show();
|
.show();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private String parsePack(String pack) {
|
|
||||||
if (pack.startsWith("https://t.me/addstickers/")) {
|
|
||||||
pack = pack.substring(25);
|
|
||||||
} else if (pack.startsWith("https://telegram.me/addstickers/")) {
|
|
||||||
pack = pack.substring(32);
|
|
||||||
}
|
|
||||||
return pack;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
@@ -37,16 +37,16 @@ public class AlphaView extends SliderViewBase implements ColorObserver {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected Bitmap makeBitmap(int w, int h) {
|
protected Bitmap makeBitmap(int w, int h) {
|
||||||
final boolean isWide = w > h;
|
boolean isWide = w > h;
|
||||||
final int n = Math.max(w, h);
|
int n = Math.max(w, h);
|
||||||
int color = observableColor.getColor();
|
int color = observableColor.getColor();
|
||||||
int[] colors = new int[n];
|
int[] colors = new int[n];
|
||||||
for (int i = 0; i < n; ++i) {
|
for (int i = 0; i < n; ++i) {
|
||||||
float alpha = isWide ? (float) i / n : 1 - (float) i / n;
|
float alpha = isWide ? (float) i / n : 1 - (float) i / n;
|
||||||
colors[i] = color & 0xffffff | (int) (alpha * 0xff) << 24;
|
colors[i] = color & 0xffffff | (int) (alpha * 0xff) << 24;
|
||||||
}
|
}
|
||||||
final int bmpWidth = isWide ? w : 1;
|
int bmpWidth = isWide ? w : 1;
|
||||||
final int bmpHeight = isWide ? 1 : h;
|
int bmpHeight = isWide ? 1 : h;
|
||||||
return Bitmap.createBitmap(colors, bmpWidth, bmpHeight, Bitmap.Config.ARGB_8888);
|
return Bitmap.createBitmap(colors, bmpWidth, bmpHeight, Bitmap.Config.ARGB_8888);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -18,13 +18,12 @@ class HexEdit {
|
|||||||
new HexFilter()
|
new HexFilter()
|
||||||
};
|
};
|
||||||
|
|
||||||
public static void setUpListeners(final EditText hexEdit, final ObservableColor observableColor) {
|
public static void setUpListeners(EditText hexEdit, ObservableColor observableColor) {
|
||||||
|
|
||||||
class MultiObserver implements ColorObserver, TextWatcher {
|
class MultiObserver implements ColorObserver, TextWatcher {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void updateColor(ObservableColor observableColor) {
|
public void updateColor(ObservableColor observableColor) {
|
||||||
final String colorString = formatColor(observableColor.getColor());
|
String colorString = formatColor(observableColor.getColor());
|
||||||
// Prevent onTextChanged getting called when we update text programmatically
|
// Prevent onTextChanged getting called when we update text programmatically
|
||||||
hexEdit.removeTextChangedListener(this);
|
hexEdit.removeTextChangedListener(this);
|
||||||
hexEdit.setText(colorString);
|
hexEdit.setText(colorString);
|
||||||
@@ -57,7 +56,7 @@ class HexEdit {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
final MultiObserver multiObserver = new MultiObserver();
|
MultiObserver multiObserver = new MultiObserver();
|
||||||
hexEdit.addTextChangedListener(multiObserver);
|
hexEdit.addTextChangedListener(multiObserver);
|
||||||
observableColor.addObserver(multiObserver);
|
observableColor.addObserver(multiObserver);
|
||||||
setShowAlphaDigits(hexEdit, true);
|
setShowAlphaDigits(hexEdit, true);
|
||||||
@@ -71,14 +70,13 @@ class HexEdit {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void setShowAlphaDigits(final EditText hexEdit, boolean showAlphaDigits) {
|
public static void setShowAlphaDigits(EditText hexEdit, boolean showAlphaDigits) {
|
||||||
hexEdit.setFilters(showAlphaDigits ? withAlphaDigits : withoutAlphaDigits);
|
hexEdit.setFilters(showAlphaDigits ? withAlphaDigits : withoutAlphaDigits);
|
||||||
hexEdit.setText(hexEdit.getText()); // trigger a reformat of text
|
hexEdit.setText(hexEdit.getText()); // trigger a reformat of text
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private static class ColorPasteLengthFilter implements InputFilter {
|
private static class ColorPasteLengthFilter implements InputFilter {
|
||||||
|
|
||||||
private static final int MAX_LENGTH = 6;
|
private static final int MAX_LENGTH = 6;
|
||||||
private static final int PASTED_LEN = 8;
|
private static final int PASTED_LEN = 8;
|
||||||
private final InputFilter sixDigitFilter = new InputFilter.LengthFilter(MAX_LENGTH);
|
private final InputFilter sixDigitFilter = new InputFilter.LengthFilter(MAX_LENGTH);
|
||||||
@@ -86,8 +84,8 @@ class HexEdit {
|
|||||||
public CharSequence filter(CharSequence source, int start, int end, Spanned dest, int dstart, int dend) {
|
public CharSequence filter(CharSequence source, int start, int end, Spanned dest, int dstart, int dend) {
|
||||||
// If 8 digits have been pasted, replacing all source, trim alpha digits.
|
// If 8 digits have been pasted, replacing all source, trim alpha digits.
|
||||||
// Otherwise standard LengthFilter behavior.
|
// Otherwise standard LengthFilter behavior.
|
||||||
final int srcLength = end - start;
|
int srcLength = end - start;
|
||||||
final int dstSelLength = dend - dstart;
|
int dstSelLength = dend - dstart;
|
||||||
if (srcLength == PASTED_LEN && dstSelLength == dest.length()) {
|
if (srcLength == PASTED_LEN && dstSelLength == dest.length()) {
|
||||||
// Discard alpha digits:
|
// Discard alpha digits:
|
||||||
return source.subSequence(PASTED_LEN - MAX_LENGTH, PASTED_LEN);
|
return source.subSequence(PASTED_LEN - MAX_LENGTH, PASTED_LEN);
|
||||||
@@ -98,7 +96,6 @@ class HexEdit {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private static class HexFilter implements InputFilter {
|
private static class HexFilter implements InputFilter {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public CharSequence filter(CharSequence source, int start, int end, Spanned dest, int dstart, int dend) {
|
public CharSequence filter(CharSequence source, int start, int end, Spanned dest, int dstart, int dend) {
|
||||||
boolean state = true;
|
boolean state = true;
|
||||||
|
|||||||
@@ -57,9 +57,9 @@ public class HueSatView extends SquareView implements ColorObserver {
|
|||||||
float[] hsv = new float[]{0f, 0f, 1f};
|
float[] hsv = new float[]{0f, 0f, 1f};
|
||||||
for (int y = 0; y < radiusPx; ++y) {
|
for (int y = 0; y < radiusPx; ++y) {
|
||||||
for (int x = 0; x < radiusPx; ++x) {
|
for (int x = 0; x < radiusPx; ++x) {
|
||||||
final int i = x + y * radiusPx;
|
int i = x + y * radiusPx;
|
||||||
final float sat = satForPos(x, y, radiusPx);
|
float sat = satForPos(x, y, radiusPx);
|
||||||
final float arcBleed = 2f / radiusPx; // extend curved edge pixels just outside clip area.
|
float arcBleed = 2f / radiusPx; // extend curved edge pixels just outside clip area.
|
||||||
if (sat <= 1 + arcBleed) {
|
if (sat <= 1 + arcBleed) {
|
||||||
hsv[0] = hueForPos(x, y, radiusPx);
|
hsv[0] = hueForPos(x, y, radiusPx);
|
||||||
hsv[1] = sat;
|
hsv[1] = sat;
|
||||||
@@ -71,35 +71,35 @@ public class HueSatView extends SquareView implements ColorObserver {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private static float hueForPos(float x, float y, float radiusPx) {
|
private static float hueForPos(float x, float y, float radiusPx) {
|
||||||
final double r = radiusPx - 1; // gives values 0...1 inclusive
|
double r = radiusPx - 1; // gives values 0...1 inclusive
|
||||||
final double dx = (r - x) / r;
|
double dx = (r - x) / r;
|
||||||
final double dy = (r - y) / r;
|
double dy = (r - y) / r;
|
||||||
final double angle = Math.atan2(dy, dx);
|
double angle = Math.atan2(dy, dx);
|
||||||
final double hue = 360 * angle / (Math.PI / 2);
|
double hue = 360 * angle / (Math.PI / 2);
|
||||||
return (float) hue;
|
return (float) hue;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static float satForPos(float x, float y, float radiusPx) {
|
private static float satForPos(float x, float y, float radiusPx) {
|
||||||
final double r = radiusPx - 1; // gives values 0...1 inclusive
|
double r = radiusPx - 1; // gives values 0...1 inclusive
|
||||||
final double dx = (r - x) / r;
|
double dx = (r - x) / r;
|
||||||
final double dy = (r - y) / r;
|
double dy = (r - y) / r;
|
||||||
final double sat = dx * dx + dy * dy; // leave it squared -- exaggerates pale colors
|
double sat = dx * dx + dy * dy; // leave it squared -- exaggerates pale colors
|
||||||
return (float) sat;
|
return (float) sat;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void setPointer(PointF pointer, float hue, float sat, float radiusPx) {
|
private static void setPointer(PointF pointer, float hue, float sat, float radiusPx) {
|
||||||
final float r = radiusPx - 1; // for values 0...1 inclusive
|
float r = radiusPx - 1; // for values 0...1 inclusive
|
||||||
final double distance = r * Math.sqrt(sat);
|
double distance = r * Math.sqrt(sat);
|
||||||
final double angle = hue / 360 * Math.PI / 2;
|
double angle = hue / 360 * Math.PI / 2;
|
||||||
final double dx = distance * Math.cos(angle);
|
double dx = distance * Math.cos(angle);
|
||||||
final double dy = distance * Math.sin(angle);
|
double dy = distance * Math.sin(angle);
|
||||||
pointer.set(r - (float) dx, r - (float) dy);
|
pointer.set(r - (float) dx, r - (float) dy);
|
||||||
}
|
}
|
||||||
|
|
||||||
private int optimalBitmapSize() {
|
private int optimalBitmapSize() {
|
||||||
final int scale = 2;
|
int scale = 2;
|
||||||
final int maxBitmapSize = 128;
|
int maxBitmapSize = 128;
|
||||||
final DisplayMetrics dm = getResources().getDisplayMetrics();
|
DisplayMetrics dm = getResources().getDisplayMetrics();
|
||||||
return Math.min(maxBitmapSize, Math.min(dm.widthPixels, dm.heightPixels) / scale);
|
return Math.min(maxBitmapSize, Math.min(dm.widthPixels, dm.heightPixels) / scale);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -159,9 +159,9 @@ public class HueSatView extends SquareView implements ColorObserver {
|
|||||||
private boolean clamp(PointF pointer, float x, float y, boolean rejectOutside) {
|
private boolean clamp(PointF pointer, float x, float y, boolean rejectOutside) {
|
||||||
x = Math.min(x, w);
|
x = Math.min(x, w);
|
||||||
y = Math.min(y, h);
|
y = Math.min(y, h);
|
||||||
final float dx = w - x;
|
float dx = w - x;
|
||||||
final float dy = h - y;
|
float dy = h - y;
|
||||||
final float r = (float) Math.sqrt(dx * dx + dy * dy);
|
float r = (float) Math.sqrt(dx * dx + dy * dy);
|
||||||
boolean outside = r > w;
|
boolean outside = r > w;
|
||||||
if (!outside || !rejectOutside) {
|
if (!outside || !rejectOutside) {
|
||||||
if (outside) {
|
if (outside) {
|
||||||
|
|||||||
@@ -6,7 +6,6 @@ import android.view.MotionEvent;
|
|||||||
import android.view.View;
|
import android.view.View;
|
||||||
|
|
||||||
public abstract class SliderViewBase extends View {
|
public abstract class SliderViewBase extends View {
|
||||||
|
|
||||||
private final Paint borderPaint;
|
private final Paint borderPaint;
|
||||||
private final Paint checkerPaint;
|
private final Paint checkerPaint;
|
||||||
private final Rect viewRect = new Rect();
|
private final Rect viewRect = new Rect();
|
||||||
|
|||||||
@@ -18,10 +18,10 @@ class SquareView extends View {
|
|||||||
@Override
|
@Override
|
||||||
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
|
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
|
||||||
// Constrain to square
|
// Constrain to square
|
||||||
final int w = MeasureSpec.getSize(widthMeasureSpec);
|
int w = MeasureSpec.getSize(widthMeasureSpec);
|
||||||
final int h = MeasureSpec.getSize(heightMeasureSpec);
|
int h = MeasureSpec.getSize(heightMeasureSpec);
|
||||||
final int modeW = MeasureSpec.getMode(widthMeasureSpec);
|
int modeW = MeasureSpec.getMode(widthMeasureSpec);
|
||||||
final int modeH = MeasureSpec.getMode(heightMeasureSpec);
|
int modeH = MeasureSpec.getMode(heightMeasureSpec);
|
||||||
int size = minSizePx;
|
int size = minSizePx;
|
||||||
if (modeW == MeasureSpec.UNSPECIFIED) {
|
if (modeW == MeasureSpec.UNSPECIFIED) {
|
||||||
size = h;
|
size = h;
|
||||||
|
|||||||
@@ -8,7 +8,6 @@ import android.graphics.RectF;
|
|||||||
import ru.vtosters.lite.utils.AndroidUtils;
|
import ru.vtosters.lite.utils.AndroidUtils;
|
||||||
|
|
||||||
public class SwatchView extends SquareView implements ColorObserver {
|
public class SwatchView extends SquareView implements ColorObserver {
|
||||||
|
|
||||||
private final Paint borderPaint;
|
private final Paint borderPaint;
|
||||||
private final Path borderPath;
|
private final Path borderPath;
|
||||||
private final Paint checkerPaint;
|
private final Paint checkerPaint;
|
||||||
@@ -46,14 +45,14 @@ public class SwatchView extends SquareView implements ColorObserver {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private static void cornerArc(Path path, float cx, float cy, float r, float startAngle, float sweepAngle) {
|
private static void cornerArc(Path path, float cx, float cy, float r, float startAngle, float sweepAngle) {
|
||||||
final RectF ovalRect = new RectF(-r, -r, r, r);
|
RectF ovalRect = new RectF(-r, -r, r, r);
|
||||||
ovalRect.offset(cx, cy);
|
ovalRect.offset(cx, cy);
|
||||||
path.arcTo(ovalRect, startAngle, sweepAngle);
|
path.arcTo(ovalRect, startAngle, sweepAngle);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void mainArc(Path path, float viewSize, float margin, float startAngle, float sweepAngle) {
|
private static void mainArc(Path path, float viewSize, float margin, float startAngle, float sweepAngle) {
|
||||||
float r = viewSize + margin;
|
float r = viewSize + margin;
|
||||||
final RectF ovalRect = new RectF(-r, -r, r, r);
|
RectF ovalRect = new RectF(-r, -r, r, r);
|
||||||
ovalRect.offset(viewSize, viewSize);
|
ovalRect.offset(viewSize, viewSize);
|
||||||
path.arcTo(ovalRect, startAngle, sweepAngle);
|
path.arcTo(ovalRect, startAngle, sweepAngle);
|
||||||
}
|
}
|
||||||
@@ -77,23 +76,23 @@ public class SwatchView extends SquareView implements ColorObserver {
|
|||||||
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
|
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
|
||||||
// We expect to be stacked behind a square HueSatView and fill the top left corner.
|
// We expect to be stacked behind a square HueSatView and fill the top left corner.
|
||||||
|
|
||||||
final float inset = borderPaint.getStrokeWidth() / 2;
|
float inset = borderPaint.getStrokeWidth() / 2;
|
||||||
final float r = Math.min(w, h);
|
float r = Math.min(w, h);
|
||||||
|
|
||||||
// Trim the corners of the swatch is where it is radialMarginPx thick.
|
// Trim the corners of the swatch is where it is radialMarginPx thick.
|
||||||
// find how long the outeredges are:
|
// find how long the outeredges are:
|
||||||
final float margin = radialMarginPx;
|
float margin = radialMarginPx;
|
||||||
final float diagonal = r + 2 * margin;
|
float diagonal = r + 2 * margin;
|
||||||
final float opp = (float) Math.sqrt(diagonal * diagonal - r * r);
|
float opp = (float) Math.sqrt(diagonal * diagonal - r * r);
|
||||||
final float edgeLen = r - opp;
|
float edgeLen = r - opp;
|
||||||
|
|
||||||
// Arc angles for drawing CCW
|
// Arc angles for drawing CCW
|
||||||
final float outerAngle = (float) Math.toDegrees(Math.atan2(opp, r));
|
float outerAngle = (float) Math.toDegrees(Math.atan2(opp, r));
|
||||||
final float startAngle = 270 - outerAngle;
|
float startAngle = 270 - outerAngle;
|
||||||
// Sweep angle for each half of the swatch:
|
// Sweep angle for each half of the swatch:
|
||||||
final float sweepAngle = outerAngle - 45;
|
float sweepAngle = outerAngle - 45;
|
||||||
// Sweep angle for the smooth corners:
|
// Sweep angle for the smooth corners:
|
||||||
final float cornerSweepAngle = 90 - outerAngle;
|
float cornerSweepAngle = 90 - outerAngle;
|
||||||
|
|
||||||
// Outer border:
|
// Outer border:
|
||||||
beginBorder(borderPath, inset, edgeLen, margin, cornerSweepAngle);
|
beginBorder(borderPath, inset, edgeLen, margin, cornerSweepAngle);
|
||||||
|
|||||||
@@ -5,7 +5,6 @@ import android.graphics.Bitmap;
|
|||||||
import android.graphics.Color;
|
import android.graphics.Color;
|
||||||
|
|
||||||
public class ValueView extends SliderViewBase implements ColorObserver {
|
public class ValueView extends SliderViewBase implements ColorObserver {
|
||||||
|
|
||||||
private ObservableColor observableColor = new ObservableColor(0);
|
private ObservableColor observableColor = new ObservableColor(0);
|
||||||
|
|
||||||
public ValueView(Context context) {
|
public ValueView(Context context) {
|
||||||
@@ -37,8 +36,8 @@ public class ValueView extends SliderViewBase implements ColorObserver {
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected Bitmap makeBitmap(int w, int h) {
|
protected Bitmap makeBitmap(int w, int h) {
|
||||||
final boolean isWide = w > h;
|
boolean isWide = w > h;
|
||||||
final int n = Math.max(w, h);
|
int n = Math.max(w, h);
|
||||||
int[] colors = new int[n];
|
int[] colors = new int[n];
|
||||||
|
|
||||||
float[] hsv = new float[]{0, 0, 0};
|
float[] hsv = new float[]{0, 0, 0};
|
||||||
@@ -48,8 +47,8 @@ public class ValueView extends SliderViewBase implements ColorObserver {
|
|||||||
hsv[2] = isWide ? (float) i / n : 1 - (float) i / n;
|
hsv[2] = isWide ? (float) i / n : 1 - (float) i / n;
|
||||||
colors[i] = Color.HSVToColor(hsv);
|
colors[i] = Color.HSVToColor(hsv);
|
||||||
}
|
}
|
||||||
final int bmpWidth = isWide ? w : 1;
|
int bmpWidth = isWide ? w : 1;
|
||||||
final int bmpHeight = isWide ? 1 : h;
|
int bmpHeight = isWide ? 1 : h;
|
||||||
return Bitmap.createBitmap(colors, bmpWidth, bmpHeight, Bitmap.Config.ARGB_8888);
|
return Bitmap.createBitmap(colors, bmpWidth, bmpHeight, Bitmap.Config.ARGB_8888);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -46,7 +46,7 @@ public class AndroidUtils {
|
|||||||
@NonNull
|
@NonNull
|
||||||
public static Context getGlobalContext() {
|
public static Context getGlobalContext() {
|
||||||
try {
|
try {
|
||||||
final Method getInitialApplicationMtd = ReflectionUtils.findMethod(Class.forName("android.app.AppGlobals"), "getInitialApplication");
|
Method getInitialApplicationMtd = ReflectionUtils.findMethod(Class.forName("android.app.AppGlobals"), "getInitialApplication");
|
||||||
return (Context) getInitialApplicationMtd.invoke(null);
|
return (Context) getInitialApplicationMtd.invoke(null);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
Log.d("GlobalContext", "Error while fetching context via refl");
|
Log.d("GlobalContext", "Error while fetching context via refl");
|
||||||
@@ -186,8 +186,8 @@ public class AndroidUtils {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private static String getRandomString(int sizeOfRandomString) {
|
private static String getRandomString(int sizeOfRandomString) {
|
||||||
final Random random = new Random();
|
Random random = new Random();
|
||||||
final StringBuilder sb = new StringBuilder(sizeOfRandomString);
|
StringBuilder sb = new StringBuilder(sizeOfRandomString);
|
||||||
for (int i = 0; i < sizeOfRandomString; ++i)
|
for (int i = 0; i < sizeOfRandomString; ++i)
|
||||||
sb.append(ALLOWED_CHARACTERS.charAt(random.nextInt(ALLOWED_CHARACTERS.length())));
|
sb.append(ALLOWED_CHARACTERS.charAt(random.nextInt(ALLOWED_CHARACTERS.length())));
|
||||||
return sb.toString();
|
return sb.toString();
|
||||||
@@ -221,7 +221,6 @@ public class AndroidUtils {
|
|||||||
long lastUpdateTime = context.getPackageManager().getPackageInfo(context.getPackageName(), 0).lastUpdateTime;
|
long lastUpdateTime = context.getPackageManager().getPackageInfo(context.getPackageName(), 0).lastUpdateTime;
|
||||||
return firstInstallTime == lastUpdateTime;
|
return firstInstallTime == lastUpdateTime;
|
||||||
} catch (PackageManager.NameNotFoundException e) {
|
} catch (PackageManager.NameNotFoundException e) {
|
||||||
e.printStackTrace();
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ public class CrashReporter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static void init(Activity activity) {
|
public static void init(Activity activity) {
|
||||||
final var defaultUncaughtExceptionHandler = Thread.getDefaultUncaughtExceptionHandler();
|
var defaultUncaughtExceptionHandler = Thread.getDefaultUncaughtExceptionHandler();
|
||||||
Thread.setDefaultUncaughtExceptionHandler((thread, th) -> CrashReporter.start(defaultUncaughtExceptionHandler, thread, th, activity));
|
Thread.setDefaultUncaughtExceptionHandler((thread, th) -> CrashReporter.start(defaultUncaughtExceptionHandler, thread, th, activity));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -76,9 +76,8 @@ public class CrashReporter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private static boolean isFoxbinInstalled() {
|
private static boolean isFoxbinInstalled() {
|
||||||
var pm = getGlobalContext().getPackageManager();
|
|
||||||
try {
|
try {
|
||||||
pm.getPackageInfo("com.f0x1d.dogbin", 0);
|
getGlobalContext().getPackageManager().getPackageInfo("com.f0x1d.dogbin", 0);
|
||||||
return true;
|
return true;
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
return false;
|
return false;
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ import java.security.NoSuchAlgorithmException;
|
|||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
|
||||||
public class IOUtils {
|
public class IOUtils {
|
||||||
public static final int BUFFER_SIZE = 8192;
|
public static int BUFFER_SIZE = 8192;
|
||||||
|
|
||||||
public static byte[] decodeStream(InputStream encIs, byte[] aesKey)
|
public static byte[] decodeStream(InputStream encIs, byte[] aesKey)
|
||||||
throws NoSuchPaddingException, NoSuchAlgorithmException, InvalidAlgorithmParameterException, InvalidKeyException, IOException {
|
throws NoSuchPaddingException, NoSuchAlgorithmException, InvalidAlgorithmParameterException, InvalidKeyException, IOException {
|
||||||
@@ -51,11 +51,11 @@ public class IOUtils {
|
|||||||
return new String(readFully(is), StandardCharsets.UTF_8);
|
return new String(readFully(is), StandardCharsets.UTF_8);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static byte[] readFully(final InputStream is)
|
public static byte[] readFully(InputStream is)
|
||||||
throws IOException {
|
throws IOException {
|
||||||
final var bos = new ByteArrayOutputStream();
|
var bos = new ByteArrayOutputStream();
|
||||||
try (bos) {
|
try (bos) {
|
||||||
final byte[] buff = new byte[BUFFER_SIZE];
|
byte[] buff = new byte[BUFFER_SIZE];
|
||||||
int len;
|
int len;
|
||||||
while ((len = is.read(buff)) > 0)
|
while ((len = is.read(buff)) > 0)
|
||||||
bos.write(buff, 0, len);
|
bos.write(buff, 0, len);
|
||||||
@@ -63,7 +63,7 @@ public class IOUtils {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static byte[] readFully(final File in)
|
public static byte[] readFully(File in)
|
||||||
throws IOException {
|
throws IOException {
|
||||||
return readFully(new FileInputStream(in));
|
return readFully(new FileInputStream(in));
|
||||||
}
|
}
|
||||||
@@ -80,25 +80,25 @@ public class IOUtils {
|
|||||||
fos.close();
|
fos.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void copy(final InputStream is, final OutputStream os)
|
public static void copy(InputStream is, OutputStream os)
|
||||||
throws IOException {
|
throws IOException {
|
||||||
final byte[] buff = new byte[BUFFER_SIZE];
|
byte[] buff = new byte[BUFFER_SIZE];
|
||||||
int len;
|
int len;
|
||||||
while ((len = is.read(buff)) > 0)
|
while ((len = is.read(buff)) > 0)
|
||||||
os.write(buff, 0, len);
|
os.write(buff, 0, len);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void copy(final byte[] buffer, final File out)
|
public static void copy(byte[] buffer, File out)
|
||||||
throws IOException {
|
throws IOException {
|
||||||
copy(new ByteArrayInputStream(buffer), new FileOutputStream(out));
|
copy(new ByteArrayInputStream(buffer), new FileOutputStream(out));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void copy(final InputStream is, final File out)
|
public static void copy(InputStream is, File out)
|
||||||
throws IOException {
|
throws IOException {
|
||||||
copy(is, new FileOutputStream(out));
|
copy(is, new FileOutputStream(out));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void copy(final File in, final File out)
|
public static void copy(File in, File out)
|
||||||
throws IOException {
|
throws IOException {
|
||||||
copy(new FileInputStream(in), new FileOutputStream(out));
|
copy(new FileInputStream(in), new FileOutputStream(out));
|
||||||
}
|
}
|
||||||
@@ -119,7 +119,7 @@ public class IOUtils {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static long getDirSize(File dir) {
|
public static long getDirSize(File dir) {
|
||||||
final var arr = dir.listFiles();
|
var arr = dir.listFiles();
|
||||||
if (arr == null || arr.length == 0)
|
if (arr == null || arr.length == 0)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
|||||||
@@ -242,13 +242,13 @@ public class NewsFeedFiltersUtils {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (checkCopyright(post) && !isWhitelistedFilters(post)) {
|
if (checkCopyright(post)) {
|
||||||
if (dev())
|
if (dev())
|
||||||
Log.d("NewsfeedAdBlockV2", "Removed post " + post.optInt("post_id") + " from discover, Reason: copyright filters");
|
Log.d("NewsfeedAdBlockV2", "Removed post " + post.optInt("post_id") + " from discover, Reason: copyright filters");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (checkCaption(post) && !isWhitelistedFilters(post)) {
|
if (checkCaption(post)) {
|
||||||
if (dev())
|
if (dev())
|
||||||
Log.d("NewsfeedAdBlockV2", "Removed post " + post.optInt("post_id") + " from discover, Reason: caption filters");
|
Log.d("NewsfeedAdBlockV2", "Removed post " + post.optInt("post_id") + " from discover, Reason: caption filters");
|
||||||
return false;
|
return false;
|
||||||
@@ -448,13 +448,13 @@ public class NewsFeedFiltersUtils {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (checkCopyright(list) && !isWhitelistedFilters(list)) {
|
if (checkCopyright(list)) {
|
||||||
if (dev())
|
if (dev())
|
||||||
Log.d("NewsfeedAdBlockV2", "Removed post " + list.optInt("post_id") + " from feed, Reason: copyright filters");
|
Log.d("NewsfeedAdBlockV2", "Removed post " + list.optInt("post_id") + " from feed, Reason: copyright filters");
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (checkCaption(list) && !isWhitelistedFilters(list)) {
|
if (checkCaption(list)) {
|
||||||
if (dev())
|
if (dev())
|
||||||
Log.d("NewsfeedAdBlockV2", "Removed post " + list.optInt("post_id") + " from feed, Reason: caption filters");
|
Log.d("NewsfeedAdBlockV2", "Removed post " + list.optInt("post_id") + " from feed, Reason: caption filters");
|
||||||
continue;
|
continue;
|
||||||
|
|||||||
@@ -19,8 +19,8 @@ public class SuperAppUtils {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static JSONObject superapp(JSONObject json) throws JSONException {
|
public static JSONObject superapp(JSONObject json) throws JSONException {
|
||||||
var superApps = Preferences.getPreferences().getString("superapp_items",
|
var superApps = Preferences.getPreferences().getString("superapp_items", "menu,miniapps,vkpay_slim,greeting,promo,holiday,weather,sport,games,informer,food,event,music,vk_run").split(",");
|
||||||
"menu,miniapps,vkpay_slim,greeting,promo,holiday,weather,sport,games,informer,food,event,music,vk_run").split(",");
|
|
||||||
if (superApps.length == 0) return json;
|
if (superApps.length == 0) return json;
|
||||||
|
|
||||||
var oldItems = json.optJSONArray("items");
|
var oldItems = json.optJSONArray("items");
|
||||||
@@ -31,7 +31,24 @@ public class SuperAppUtils {
|
|||||||
var type = item.optString("type");
|
var type = item.optString("type");
|
||||||
for (String superApp : superApps) {
|
for (String superApp : superApps) {
|
||||||
if (type.equals(superApp))
|
if (type.equals(superApp))
|
||||||
newItems.put(item);
|
if (superApp.equals("menu")) { // superapp menu fix
|
||||||
|
String menuitems = "groups,audios,stickers,podcasts,shopping,lives,videos,games,vk_calls,vk_pay,ads_easy_promote,classifieds,events";
|
||||||
|
JSONObject menuItem = new JSONObject();
|
||||||
|
JSONArray menuItems = new JSONArray();
|
||||||
|
|
||||||
|
generateMenuItems(menuitems, menuItems);
|
||||||
|
|
||||||
|
JSONObject object = new JSONObject();
|
||||||
|
object.put("count", menuitems.split(",").length);
|
||||||
|
object.put("items", menuItems);
|
||||||
|
|
||||||
|
menuItem.put("type", "menu");
|
||||||
|
menuItem.put("object", object);
|
||||||
|
|
||||||
|
newItems.put(menuItem);
|
||||||
|
} else {
|
||||||
|
newItems.put(item);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (int i = 0; i < superApps.length; i++) {
|
for (int i = 0; i < superApps.length; i++) {
|
||||||
@@ -46,4 +63,16 @@ public class SuperAppUtils {
|
|||||||
|
|
||||||
return json.putOpt("items", newItems);
|
return json.putOpt("items", newItems);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static void generateMenuItems(String str, JSONArray jsonArray) throws JSONException {
|
||||||
|
String[] strings = str.split(",");
|
||||||
|
|
||||||
|
for (String string : strings) {
|
||||||
|
JSONObject jsonObject = new JSONObject();
|
||||||
|
|
||||||
|
jsonObject.put("name", string);
|
||||||
|
|
||||||
|
jsonArray.put(jsonObject);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,6 +17,9 @@ import java.text.SimpleDateFormat;
|
|||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
|
|
||||||
|
import static android.os.Environment.DIRECTORY_DOWNLOADS;
|
||||||
|
import static android.os.Environment.getExternalStoragePublicDirectory;
|
||||||
|
|
||||||
public class VKAccountDB {
|
public class VKAccountDB {
|
||||||
private static SQLiteOpenHelper getDatabase() {
|
private static SQLiteOpenHelper getDatabase() {
|
||||||
return new UsersDbHelper(AndroidUtils.getGlobalContext());
|
return new UsersDbHelper(AndroidUtils.getGlobalContext());
|
||||||
@@ -70,11 +73,11 @@ public class VKAccountDB {
|
|||||||
|
|
||||||
var db = getDatabase().getReadableDatabase();
|
var db = getDatabase().getReadableDatabase();
|
||||||
var dateFormat = new SimpleDateFormat("yyyy-MM-dd.HH-mm-ss", Locale.getDefault());
|
var dateFormat = new SimpleDateFormat("yyyy-MM-dd.HH-mm-ss", Locale.getDefault());
|
||||||
var file = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS) + "/VTLBackups/saved_accounts_" + dateFormat.format(new Date()) + ".vtl");
|
var dir = new File(getExternalStoragePublicDirectory(DIRECTORY_DOWNLOADS), "/VTLBackups/");
|
||||||
|
var file = new File(dir, "saved_accounts_" + dateFormat.format(new Date()) + ".vtl");
|
||||||
|
|
||||||
InputStream inputStream;
|
try (InputStream inputStream = new FileInputStream(db.getPath())){
|
||||||
try {
|
dir.mkdirs();
|
||||||
inputStream = new FileInputStream(db.getPath());
|
|
||||||
|
|
||||||
FileOutputStream outputStream = new FileOutputStream(file);
|
FileOutputStream outputStream = new FileOutputStream(file);
|
||||||
byte[] buff = new byte[1024];
|
byte[] buff = new byte[1024];
|
||||||
@@ -86,7 +89,6 @@ public class VKAccountDB {
|
|||||||
|
|
||||||
AndroidUtils.sendToast(AndroidUtils.getString("accounts_saved_by_path") + " " + file.getPath());
|
AndroidUtils.sendToast(AndroidUtils.getString("accounts_saved_by_path") + " " + file.getPath());
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
e.printStackTrace();
|
|
||||||
AndroidUtils.sendToast(AndroidUtils.getString("error_saving_file"));
|
AndroidUtils.sendToast(AndroidUtils.getString("error_saving_file"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -56,8 +56,7 @@ public class VTVerifications {
|
|||||||
.apply();
|
.apply();
|
||||||
isLoaded = true;
|
isLoaded = true;
|
||||||
Log.d("VTVerifications", "load from network");
|
Log.d("VTVerifications", "load from network");
|
||||||
} catch (Exception e) {
|
} catch (Exception ignored) {
|
||||||
e.printStackTrace();
|
|
||||||
if (prefs.contains("ids")) {
|
if (prefs.contains("ids")) {
|
||||||
parseJson(prefs.getString("ids", "[]"));
|
parseJson(prefs.getString("ids", "[]"));
|
||||||
Log.d("VTVerifications", "load from memory. Something went wrong with parsing");
|
Log.d("VTVerifications", "load from memory. Something went wrong with parsing");
|
||||||
@@ -92,7 +91,7 @@ public class VTVerifications {
|
|||||||
processIds(json.optJSONArray("404"), sDevelopers);
|
processIds(json.optJSONArray("404"), sDevelopers);
|
||||||
processIds(json.optJSONArray("1337"), sServiceAccounts);
|
processIds(json.optJSONArray("1337"), sServiceAccounts);
|
||||||
} catch (JSONException e) {
|
} catch (JSONException e) {
|
||||||
e.printStackTrace();
|
// ignored
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -100,8 +99,13 @@ public class VTVerifications {
|
|||||||
if (jsonIds == null || jsonIds.length() == 0)
|
if (jsonIds == null || jsonIds.length() == 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
for (int i = 0; i < jsonIds.length(); i++)
|
for (int i = 0; i < jsonIds.length(); i++) {
|
||||||
member.add(jsonIds.optInt(i));
|
try {
|
||||||
|
member.add(jsonIds.optInt(i));
|
||||||
|
} catch (Exception ignored) {
|
||||||
|
// ignored
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean isPrometheus(int id) {
|
public static boolean isPrometheus(int id) {
|
||||||
|
|||||||
@@ -7032,4 +7032,7 @@
|
|||||||
<string name="clear_all_cache">Ачысціць ўвесь кэш?</string>
|
<string name="clear_all_cache">Ачысціць ўвесь кэш?</string>
|
||||||
<string name="cache_size">Памер прыкладання</string>
|
<string name="cache_size">Памер прыкладання</string>
|
||||||
<string name="cache_size_summ">Вага кэша прыкладання</string>
|
<string name="cache_size_summ">Вага кэша прыкладання</string>
|
||||||
|
|
||||||
|
<string name="invertcached_title">Інвертаваць cпіс</string>
|
||||||
|
<string name="invertcached_summ">Інвертаваць cпіс кэшаваных трэкаў</string>
|
||||||
</resources>
|
</resources>
|
||||||
@@ -6414,4 +6414,7 @@
|
|||||||
<string name="clear_all_cache">Очистить весь кеш?</string>
|
<string name="clear_all_cache">Очистить весь кеш?</string>
|
||||||
<string name="cache_size">Размер приложения</string>
|
<string name="cache_size">Размер приложения</string>
|
||||||
<string name="cache_size_summ">Вес кеша приложения</string>
|
<string name="cache_size_summ">Вес кеша приложения</string>
|
||||||
|
|
||||||
|
<string name="invertcached_title">Инвертировать список</string>
|
||||||
|
<string name="invertcached_summ">Инвертировать список кешированных треков</string>
|
||||||
</resources>
|
</resources>
|
||||||
@@ -6339,4 +6339,7 @@
|
|||||||
<string name="clear_all_cache">Очистити весь кеш?</string>
|
<string name="clear_all_cache">Очистити весь кеш?</string>
|
||||||
<string name="cache_size">Розмір програми</string>
|
<string name="cache_size">Розмір програми</string>
|
||||||
<string name="cache_size_summ">Вага кеша додатки</string>
|
<string name="cache_size_summ">Вага кеша додатки</string>
|
||||||
|
|
||||||
|
<string name="invertcached_title">Інвертувати список</string>
|
||||||
|
<string name="invertcached_summ">Інвертувати список кешованих треків</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
|||||||
@@ -6552,4 +6552,7 @@ May look like a fake leaving the online"</string>
|
|||||||
<string name="clear_all_cache">Clear all cache?</string>
|
<string name="clear_all_cache">Clear all cache?</string>
|
||||||
<string name="cache_size">App size</string>
|
<string name="cache_size">App size</string>
|
||||||
<string name="cache_size_summ">Cache size</string>
|
<string name="cache_size_summ">Cache size</string>
|
||||||
|
|
||||||
|
<string name="invertcached_title">Invert list</string>
|
||||||
|
<string name="invertcached_summ">Invert cached track list</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
|||||||
@@ -18,6 +18,11 @@
|
|||||||
<Preference
|
<Preference
|
||||||
android:key="cached_tracks"
|
android:key="cached_tracks"
|
||||||
android:title="@string/cached_tracks_title"/>
|
android:title="@string/cached_tracks_title"/>
|
||||||
|
<com.vtosters.lite.ui.MaterialSwitchPreference
|
||||||
|
android:defaultValue="false"
|
||||||
|
android:key="invertCachedTracks"
|
||||||
|
android:summary="@string/invertcached_summ"
|
||||||
|
android:title="@string/invertcached_title"/>
|
||||||
<com.vtosters.lite.ui.MaterialSwitchPreference
|
<com.vtosters.lite.ui.MaterialSwitchPreference
|
||||||
android:defaultValue="false"
|
android:defaultValue="false"
|
||||||
android:key="autocache"
|
android:key="autocache"
|
||||||
|
|||||||
+20
-20
@@ -222,41 +222,41 @@
|
|||||||
|
|
||||||
.line 14
|
.line 14
|
||||||
:cond_0
|
:cond_0
|
||||||
new-instance v0, Lcom/vk/api/audio/AudioSendStartEvent;
|
# new-instance v0, Lcom/vk/api/audio/AudioSendStartEvent;
|
||||||
|
|
||||||
invoke-virtual {p1}, Lcom/vk/dto/music/MusicTrack;->y1()Ljava/lang/String;
|
# invoke-virtual {p1}, Lcom/vk/dto/music/MusicTrack;->y1()Ljava/lang/String;
|
||||||
|
|
||||||
move-result-object p1
|
# move-result-object p1
|
||||||
|
|
||||||
sget-object v2, Lcom/vk/api/base/ApiConfig;->d:Lcom/vk/api/base/ApiConfig$a;
|
# sget-object v2, Lcom/vk/api/base/ApiConfig;->d:Lcom/vk/api/base/ApiConfig$a;
|
||||||
|
|
||||||
invoke-interface {v2}, Lcom/vk/api/base/ApiConfig$a;->O1()Ljava/lang/String;
|
# invoke-interface {v2}, Lcom/vk/api/base/ApiConfig$a;->O1()Ljava/lang/String;
|
||||||
|
|
||||||
move-result-object v2
|
# move-result-object v2
|
||||||
|
|
||||||
invoke-direct {v0, p1, v2}, Lcom/vk/api/audio/AudioSendStartEvent;-><init>(Ljava/lang/String;Ljava/lang/String;)V
|
# invoke-direct {v0, p1, v2}, Lcom/vk/api/audio/AudioSendStartEvent;-><init>(Ljava/lang/String;Ljava/lang/String;)V
|
||||||
|
|
||||||
const/4 p1, 0x0
|
# const/4 p1, 0x0
|
||||||
|
|
||||||
.line 15
|
# .line 15
|
||||||
invoke-static {v0, p1, v1, p1}, Lcom/vk/api/base/ApiRequest;->d(Lcom/vk/api/base/ApiRequest;Lcom/vk/api/base/ApiThreadHolder;ILjava/lang/Object;)Lio/reactivex/Observable;
|
# invoke-static {v0, p1, v1, p1}, Lcom/vk/api/base/ApiRequest;->d(Lcom/vk/api/base/ApiRequest;Lcom/vk/api/base/ApiThreadHolder;ILjava/lang/Object;)Lio/reactivex/Observable;
|
||||||
|
|
||||||
move-result-object p1
|
# move-result-object p1
|
||||||
|
|
||||||
.line 16
|
# .line 16
|
||||||
new-instance v0, Lcom/vk/music/notifications/restriction/MusicRestrictionModelImpl$d;
|
# new-instance v0, Lcom/vk/music/notifications/restriction/MusicRestrictionModelImpl$d;
|
||||||
|
|
||||||
invoke-direct {v0, p0}, Lcom/vk/music/notifications/restriction/MusicRestrictionModelImpl$d;-><init>(Lcom/vk/music/notifications/restriction/MusicRestrictionModelImpl;)V
|
# invoke-direct {v0, p0}, Lcom/vk/music/notifications/restriction/MusicRestrictionModelImpl$d;-><init>(Lcom/vk/music/notifications/restriction/MusicRestrictionModelImpl;)V
|
||||||
|
|
||||||
.line 17
|
# .line 17
|
||||||
sget-object v1, Lcom/vk/music/notifications/restriction/MusicRestrictionModelImpl$e;->a:Lcom/vk/music/notifications/restriction/MusicRestrictionModelImpl$e;
|
# sget-object v1, Lcom/vk/music/notifications/restriction/MusicRestrictionModelImpl$e;->a:Lcom/vk/music/notifications/restriction/MusicRestrictionModelImpl$e;
|
||||||
|
|
||||||
.line 18
|
# .line 18
|
||||||
invoke-virtual {p1, v0, v1}, Lio/reactivex/Observable;->a(Lio/reactivex/functions/Consumer;Lio/reactivex/functions/Consumer;)Lio/reactivex/disposables/Disposable;
|
# invoke-virtual {p1, v0, v1}, Lio/reactivex/Observable;->a(Lio/reactivex/functions/Consumer;Lio/reactivex/functions/Consumer;)Lio/reactivex/disposables/Disposable;
|
||||||
|
|
||||||
move-result-object p1
|
# move-result-object p1
|
||||||
|
|
||||||
iput-object p1, p0, Lcom/vk/music/notifications/restriction/MusicRestrictionModelImpl;->a:Lio/reactivex/disposables/Disposable;
|
# iput-object p1, p0, Lcom/vk/music/notifications/restriction/MusicRestrictionModelImpl;->a:Lio/reactivex/disposables/Disposable;
|
||||||
|
|
||||||
return-void
|
return-void
|
||||||
.end method
|
.end method
|
||||||
|
|||||||
Reference in New Issue
Block a user