diff --git a/app/src/main/java/ru/vtosters/lite/hooks/AdBlockHook.java b/app/src/main/java/ru/vtosters/lite/hooks/AdBlockHook.java index 8fea29341..8a1eef738 100644 --- a/app/src/main/java/ru/vtosters/lite/hooks/AdBlockHook.java +++ b/app/src/main/java/ru/vtosters/lite/hooks/AdBlockHook.java @@ -339,7 +339,10 @@ public class AdBlockHook { return true; } - var whitelist = AndroidUtils.getDefaultPrefs().getStringSet("whitelisted_filters_groups", Collections.synchronizedSet(new LinkedHashSet<>())); + var whitelist = AndroidUtils.getDefaultPrefs().getStringSet( + "whitelisted_filters_groups", + Collections.emptySet() + ); return whitelist.contains(id); } @@ -351,7 +354,10 @@ public class AdBlockHook { id = String.valueOf(list.optInt("source_id")); } - var whitelist = AndroidUtils.getDefaultPrefs().getStringSet("whitelisted_ad_groups", Collections.synchronizedSet(new LinkedHashSet<>())); + var whitelist = AndroidUtils.getDefaultPrefs().getStringSet( + "whitelisted_ad_groups", + Collections.emptySet() + ); return whitelist.contains(id); } diff --git a/app/src/main/java/ru/vtosters/lite/hooks/JsonInjectors.java b/app/src/main/java/ru/vtosters/lite/hooks/JsonInjectors.java index c2dc406cd..ca2f34ecb 100644 --- a/app/src/main/java/ru/vtosters/lite/hooks/JsonInjectors.java +++ b/app/src/main/java/ru/vtosters/lite/hooks/JsonInjectors.java @@ -336,36 +336,34 @@ public class JsonInjectors { public static JSONArray newsfeedlist(JSONArray items) throws JSONException { var selectedItems = getDefaultPrefs().getString("news_feed_selected_items", ""); var filtersSet = getDefaultPrefs().getStringSet("news_feed_items_set", null); - var mutableFiltersSet = Collections.synchronizedSet(new LinkedHashSet()); + var mutableFiltersSet = new LinkedHashSet(); if (filtersSet != null) mutableFiltersSet.addAll(filtersSet); - synchronized (mutableFiltersSet) { - for (int i = 0; i < items.length(); i++) { - var item = items.optJSONObject(i); - if (item == null) continue; + for (int i = 0; i < items.length(); i++) { + var item = items.optJSONObject(i); + if (item == null) continue; - var id = item.optString("id"); - var title = item.optString("title"); + var id = item.optString("id"); + var title = item.optString("title"); - if (TextUtils.isEmpty(id) || TextUtils.isEmpty(title) - // this items not working - || id.equals("kpop") || id.equals("foryou") - || id.equals("qazaqstan") || id.equals("podcasts")) - continue; + if (TextUtils.isEmpty(id) || TextUtils.isEmpty(title) + // this items not working + || id.equals("kpop") || id.equals("foryou") + || id.equals("qazaqstan") || id.equals("podcasts")) + continue; - mutableFiltersSet.add(id + "|" + title); + mutableFiltersSet.add(id + "|" + title); - var hide = selectedItems.contains(id); + var hide = selectedItems.contains(id); - Log.d("NewsfeedList", "Added list " + id + " to feed"); - item.put("is_hidden", hide) - .put("is_unavailable", hide); - if (dev()) Log.d("NewsfeedListInj", "Unlocked " + id + " in newsfeed list"); - } - getDefaultPrefs().edit().putStringSet("news_feed_items_set", mutableFiltersSet) - .apply(); + Log.d("NewsfeedList", "Added list " + id + " to feed"); + item.put("is_hidden", hide) + .put("is_unavailable", hide); + if (dev()) Log.d("NewsfeedListInj", "Unlocked " + id + " in newsfeed list"); } + getDefaultPrefs().edit().putStringSet("news_feed_items_set", mutableFiltersSet) + .apply(); return items; } diff --git a/app/src/main/java/ru/vtosters/lite/hooks/NewsfeedHook.java b/app/src/main/java/ru/vtosters/lite/hooks/NewsfeedHook.java index 13df0be47..f15bf848c 100644 --- a/app/src/main/java/ru/vtosters/lite/hooks/NewsfeedHook.java +++ b/app/src/main/java/ru/vtosters/lite/hooks/NewsfeedHook.java @@ -70,19 +70,25 @@ public class NewsfeedHook { } public static boolean isWhitelistedFilter(ExtendedCommunityProfile eup) { - return getDefaultPrefs().getStringSet("whitelisted_filters_groups", Collections.synchronizedSet(new LinkedHashSet<>())).contains(String.valueOf(AccountManagerUtils.getUserID(eup))); + return getDefaultPrefs().getStringSet( + "whitelisted_filters_groups", Collections.emptySet() + ).contains(String.valueOf(AccountManagerUtils.getUserID(eup))); } public static boolean isWhitelistedAd(ExtendedCommunityProfile eup) { - return getDefaultPrefs().getStringSet("whitelisted_ad_groups", Collections.synchronizedSet(new LinkedHashSet<>())).contains(String.valueOf(AccountManagerUtils.getUserID(eup))); + return getDefaultPrefs().getStringSet( + "whitelisted_ad_groups", + Collections.emptySet() + ).contains(String.valueOf(AccountManagerUtils.getUserID(eup))); } public static void setWhitelistedFilter(ExtendedCommunityProfile eup, boolean needWhitelist) { - var mutableAdsSet = Collections.synchronizedSet(new LinkedHashSet()); var id = String.valueOf(AccountManagerUtils.getUserID(eup)); - mutableAdsSet.addAll(getDefaultPrefs().getStringSet("whitelisted_filters_groups", mutableAdsSet)); - + var mutableAdsSet = new LinkedHashSet<>(getDefaultPrefs().getStringSet( + "whitelisted_filters_groups", + Collections.emptySet()) + ); if (needWhitelist) { mutableAdsSet.add(id); } else { @@ -93,10 +99,11 @@ public class NewsfeedHook { } public static void setWhitelistedAd(ExtendedCommunityProfile eup, boolean needWhitelist) { - var mutableAdsSet = Collections.synchronizedSet(new LinkedHashSet()); var id = String.valueOf(AccountManagerUtils.getUserID(eup)); - mutableAdsSet.addAll(getDefaultPrefs().getStringSet("whitelisted_ad_groups", mutableAdsSet)); + var mutableAdsSet = new LinkedHashSet<>(getDefaultPrefs().getStringSet( + "whitelisted_ad_groups", + Collections.emptySet())); if (needWhitelist) { mutableAdsSet.add(id); diff --git a/app/src/main/java/ru/vtosters/lite/music/M3UDownloader.java b/app/src/main/java/ru/vtosters/lite/music/M3UDownloader.java index 79cbf02fb..480467915 100644 --- a/app/src/main/java/ru/vtosters/lite/music/M3UDownloader.java +++ b/app/src/main/java/ru/vtosters/lite/music/M3UDownloader.java @@ -60,7 +60,7 @@ public class M3UDownloader implements ITrackDownloader { VKM3UParser parser = new VKM3UParser(payload); List tses = parser.getTransportStreams(); AtomicInteger progress = new AtomicInteger(0); - List> futures = new ArrayList<>(); + List> futures = new ArrayList<>(tses.size()); var tsesDir = new File(outDir, String.valueOf(track.d)); tsesDir.mkdirs(); diff --git a/app/src/main/java/ru/vtosters/lite/translators/BaseTranslator.java b/app/src/main/java/ru/vtosters/lite/translators/BaseTranslator.java index fde294298..9d089e215 100644 --- a/app/src/main/java/ru/vtosters/lite/translators/BaseTranslator.java +++ b/app/src/main/java/ru/vtosters/lite/translators/BaseTranslator.java @@ -14,7 +14,12 @@ public abstract class BaseTranslator { private static final int YANDEX = 0; private static final int GOOGLE = 1; private static final int DEEPL = 2; - private final LruCache cache = new LruCache<>(200); + private final LruCache cache = new LruCache<>(200) { + @Override + protected String create(@NonNull String text) { + return translate(text, getToLanguage()); + } + }; public static String getToLanguage() { var lang = preferences.getString("lang_target", "system"); @@ -43,11 +48,8 @@ public abstract class BaseTranslator { @NonNull public final String getTranslation(String text) { - var val = cache.get(text); - if (val != null) - return val; - var translation = translate(text, getToLanguage()); - cache.put(text, translation); - return translation; + String v = cache.get(text); + assert v != null; + return v; } } diff --git a/app/src/main/java/ru/vtosters/lite/translators/DeepLTranslator.java b/app/src/main/java/ru/vtosters/lite/translators/DeepLTranslator.java index c93532280..d9c0e2262 100644 --- a/app/src/main/java/ru/vtosters/lite/translators/DeepLTranslator.java +++ b/app/src/main/java/ru/vtosters/lite/translators/DeepLTranslator.java @@ -10,7 +10,6 @@ import org.json.JSONObject; import java.nio.charset.StandardCharsets; import java.util.UUID; import java.util.concurrent.ThreadLocalRandom; -import java.util.concurrent.atomic.AtomicLong; import java.util.regex.Pattern; import okhttp3.MediaType; @@ -49,14 +48,17 @@ public class DeepLTranslator extends BaseTranslator { private static DeepLTranslator instance; public static DeepLTranslator getInstance() { - if (instance == null) - instance = new DeepLTranslator(); - return instance; + // Race safe when the new object does not contain the state of the previous one + DeepLTranslator translator = instance; + if (translator == null) { + return instance = new DeepLTranslator(); + } + return translator; } private static Long getTimestamp(int iNumber) { var now = System.currentTimeMillis(); - return Long.valueOf((((long) iNumber) + now) - (now % ((long) iNumber))); + return (((long) iNumber) + now) - (now % ((long) iNumber)); } @NonNull @@ -73,16 +75,16 @@ public class DeepLTranslator extends BaseTranslator { i++; } - var id = new AtomicLong(ThreadLocalRandom.current().nextLong(Long.parseLong("10000000000"))); + var id = ThreadLocalRandom.current().nextLong(1, 10000000000L); var requestBody = String.format(REQUEST_BODY_FORMAT, - id.incrementAndGet(), + id, text, tl, getTimestamp(i) ); - requestBody = (id.get() + 3) % 13 == 0 || (id.get() + 5) % 29 == 0 + requestBody = (id + 3) % 13 == 0 || (id + 5) % 29 == 0 ? requestBody.replace("hod\":\"", "hod\" : \"") : requestBody.replace("hod\":\"", "hod\": \""); diff --git a/app/src/main/java/ru/vtosters/lite/translators/GoogleTranslator.java b/app/src/main/java/ru/vtosters/lite/translators/GoogleTranslator.java index f0bc87787..fec710ddf 100644 --- a/app/src/main/java/ru/vtosters/lite/translators/GoogleTranslator.java +++ b/app/src/main/java/ru/vtosters/lite/translators/GoogleTranslator.java @@ -38,9 +38,11 @@ public class GoogleTranslator extends BaseTranslator { private static GoogleTranslator instance; public static GoogleTranslator getInstance() { - if (instance == null) - instance = new GoogleTranslator(); - return instance; + // Race safe when the new object does not contain the state of the previous one + GoogleTranslator translator = instance; + if (translator == null) + return instance = new GoogleTranslator(); + return translator; } @NonNull diff --git a/app/src/main/java/ru/vtosters/lite/translators/YandexTranslator.java b/app/src/main/java/ru/vtosters/lite/translators/YandexTranslator.java index b1de3b144..7192727c0 100644 --- a/app/src/main/java/ru/vtosters/lite/translators/YandexTranslator.java +++ b/app/src/main/java/ru/vtosters/lite/translators/YandexTranslator.java @@ -22,9 +22,11 @@ public class YandexTranslator extends BaseTranslator { private static YandexTranslator instance; public static YandexTranslator getInstance() { - if (instance == null) - instance = new YandexTranslator(); - return instance; + // Race safe when the new object does not contain the state of the previous one + YandexTranslator translator = instance; + if (translator == null) + return instance = new YandexTranslator(); + return translator; } @NonNull diff --git a/app/src/main/java/ru/vtosters/lite/ui/dialogs/Translate.java b/app/src/main/java/ru/vtosters/lite/ui/dialogs/Translate.java index e6fc542d5..5260a1760 100644 --- a/app/src/main/java/ru/vtosters/lite/ui/dialogs/Translate.java +++ b/app/src/main/java/ru/vtosters/lite/ui/dialogs/Translate.java @@ -11,21 +11,30 @@ import android.util.Log; import com.vk.core.dialogs.alert.VkAlertDialog; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.Executor; +import java.util.concurrent.Executors; + import ru.vtosters.lite.translators.BaseTranslator; import ru.vtosters.lite.utils.AndroidUtils; public class Translate { + private static final Executor ASYNC_EXECUTOR + = Executors.newSingleThreadExecutor(); + private static final Executor MAIN_EXECUTOR + = new DelegateExecutor(); + public static void showTranslatedText(Context context, String text) { - new Thread(() -> { + BaseTranslator translator = BaseTranslator.getInstance(); + if (translator == null) return; + ASYNC_EXECUTOR.execute(() -> { try { - var translation = BaseTranslator.getInstance().getTranslation(text); - new Handler(Looper.getMainLooper()).post(() -> { - showDialog(context, translation); - }); + var translation = translator.getTranslation(text); + MAIN_EXECUTOR.execute(() -> showDialog(context, translation)); } catch (Exception e) { Log.e("Translate", e + ""); } - }).start(); + }); } private static void showDialog(Context context, String text) { @@ -42,4 +51,13 @@ public class Translate { }) .show(); } + + private static class DelegateExecutor implements Executor { + private final Handler handler = new Handler(Looper.getMainLooper()); + + @Override + public void execute(Runnable command) { + handler.post(command); + } + } }