From 17fb608c341a949e3fa39a8d4219e9d8fa6065b4 Mon Sep 17 00:00:00 2001 From: Ammar Githam Date: Sat, 22 May 2021 20:10:53 +0900 Subject: [PATCH] Convert some more classes to kotlin --- .../instagrabber/InstaGrabberApplication.java | 5 +- .../customviews/FormattedNumberTextView.java | 2 +- .../instagrabber/customviews/Tooltip.java | 5 +- .../instagrabber/utils/CombinedDrawable.kt | 228 ++++++++---------- .../awais/instagrabber/utils/CookieUtils.kt | 213 ++++++++-------- .../utils/CubicInterpolation.java | 33 --- .../awais/instagrabber/utils/DataBox.java | 43 ---- .../instagrabber/utils/DeepLinkParser.kt | 74 ++---- .../awais/instagrabber/utils/LocaleUtils.kt | 156 ++++++------ .../instagrabber/utils/MediaUploadHelper.kt | 3 +- .../awais/instagrabber/utils/NullSafePair.kt | 87 ++----- .../awais/instagrabber/utils/NumberUtils.kt | 202 ++++++---------- .../utils/RankedRecipientsCache.kt | 90 ++----- .../instagrabber/utils/SerializablePair.kt | 25 +- .../instagrabber/utils/UpdateCheckCommon.kt | 70 +++--- .../instagrabber/utils/UserAgentUtils.kt | 155 ++++++------ .../awais/instagrabber/utils/ViewUtils.kt | 212 ++++++++-------- .../utils/extensions/AnyExtensions.kt | 12 + .../viewmodels/UserSearchViewModel.java | 4 +- 19 files changed, 644 insertions(+), 975 deletions(-) delete mode 100755 app/src/main/java/awais/instagrabber/utils/DataBox.java create mode 100644 app/src/main/java/awais/instagrabber/utils/extensions/AnyExtensions.kt diff --git a/app/src/main/java/awais/instagrabber/InstaGrabberApplication.java b/app/src/main/java/awais/instagrabber/InstaGrabberApplication.java index 8bdedbbd..97ed6040 100644 --- a/app/src/main/java/awais/instagrabber/InstaGrabberApplication.java +++ b/app/src/main/java/awais/instagrabber/InstaGrabberApplication.java @@ -27,9 +27,6 @@ import static awais.instagrabber.utils.Utils.clipboardManager; import static awais.instagrabber.utils.Utils.datetimeParser; import static awais.instagrabber.utils.Utils.settingsHelper; -//import awaisomereport.LogCollector; -//import static awais.instagrabber.utils.Utils.logCollector; - public final class InstaGrabberApplication extends Application { private static final String TAG = "InstaGrabberApplication"; @@ -56,7 +53,7 @@ public final class InstaGrabberApplication extends Application { Log.e(TAG, "Error", e); } } - + // final Set requestListeners = new HashSet<>(); // requestListeners.add(new RequestLoggingListener()); final ImagePipelineConfig imagePipelineConfig = ImagePipelineConfig diff --git a/app/src/main/java/awais/instagrabber/customviews/FormattedNumberTextView.java b/app/src/main/java/awais/instagrabber/customviews/FormattedNumberTextView.java index 99c2a216..06cdbf93 100644 --- a/app/src/main/java/awais/instagrabber/customviews/FormattedNumberTextView.java +++ b/app/src/main/java/awais/instagrabber/customviews/FormattedNumberTextView.java @@ -153,7 +153,7 @@ public class FormattedNumberTextView extends AppCompatTextView { return; } if (showAbbreviation) { - setText(NumberUtils.abbreviate(number)); + setText(NumberUtils.abbreviate(number, null)); return; } setText(String.valueOf(number)); diff --git a/app/src/main/java/awais/instagrabber/customviews/Tooltip.java b/app/src/main/java/awais/instagrabber/customviews/Tooltip.java index 5cde235b..709f23b4 100644 --- a/app/src/main/java/awais/instagrabber/customviews/Tooltip.java +++ b/app/src/main/java/awais/instagrabber/customviews/Tooltip.java @@ -16,6 +16,8 @@ import awais.instagrabber.utils.AppExecutors; import awais.instagrabber.utils.Utils; import awais.instagrabber.utils.ViewUtils; +import static android.view.ViewGroup.LayoutParams.WRAP_CONTENT; + public class Tooltip extends AppCompatTextView { private View anchor; @@ -40,8 +42,7 @@ public class Tooltip extends AppCompatTextView { setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14); setPadding(Utils.convertDpToPx(8), Utils.convertDpToPx(7), Utils.convertDpToPx(8), Utils.convertDpToPx(7)); setGravity(Gravity.CENTER_VERTICAL); - parentView.addView(this, ViewUtils.createFrame( - ViewUtils.WRAP_CONTENT, ViewUtils.WRAP_CONTENT, Gravity.START | Gravity.TOP, 5, 0, 5, 3)); + parentView.addView(this, ViewUtils.createFrame(WRAP_CONTENT, WRAP_CONTENT, Gravity.START | Gravity.TOP, 5, 0, 5, 3)); setVisibility(GONE); } diff --git a/app/src/main/java/awais/instagrabber/utils/CombinedDrawable.kt b/app/src/main/java/awais/instagrabber/utils/CombinedDrawable.kt index 6aa9b9b6..d02dcc4c 100644 --- a/app/src/main/java/awais/instagrabber/utils/CombinedDrawable.kt +++ b/app/src/main/java/awais/instagrabber/utils/CombinedDrawable.kt @@ -1,185 +1,157 @@ -package awais.instagrabber.utils;/* +/* * This is the source code of Telegram for Android v. 5.x.x. * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). - * + *

* Copyright Nikolai Kudashov, 2013-2018. */ - -import android.graphics.Canvas; -import android.graphics.ColorFilter; -import android.graphics.drawable.Drawable; - -import androidx.annotation.NonNull; - -public class CombinedDrawable extends Drawable implements Drawable.Callback { - - private final Drawable background; - private final Drawable icon; - private int left; - private int top; - private int iconWidth; - private int iconHeight; - private int backWidth; - private int backHeight; - private int offsetX; - private int offsetY; - private boolean fullSize; - - public CombinedDrawable(Drawable backgroundDrawable, Drawable iconDrawable, int leftOffset, int topOffset) { - background = backgroundDrawable; - icon = iconDrawable; - left = leftOffset; - top = topOffset; +package awais.instagrabber.utils + +import android.graphics.Canvas +import android.graphics.ColorFilter +import android.graphics.PixelFormat +import android.graphics.drawable.Drawable + +class CombinedDrawable : Drawable, Drawable.Callback { + val background: Drawable + val icon: Drawable? + private var left = 0 + private var top = 0 + private var iconWidth = 0 + private var iconHeight = 0 + private var backWidth = 0 + private var backHeight = 0 + private var offsetX = 0 + private var offsetY = 0 + private var fullSize = false + + constructor(backgroundDrawable: Drawable, iconDrawable: Drawable?, leftOffset: Int, topOffset: Int) { + background = backgroundDrawable + icon = iconDrawable + left = leftOffset + top = topOffset if (iconDrawable != null) { - iconDrawable.setCallback(this); + iconDrawable.callback = this } } - public CombinedDrawable(Drawable backgroundDrawable, Drawable iconDrawable) { - background = backgroundDrawable; - icon = iconDrawable; + constructor(backgroundDrawable: Drawable, iconDrawable: Drawable?) { + background = backgroundDrawable + icon = iconDrawable if (iconDrawable != null) { - iconDrawable.setCallback(this); + iconDrawable.callback = this } } - public void setIconSize(int width, int height) { - iconWidth = width; - iconHeight = height; - } - - public void setCustomSize(int width, int height) { - backWidth = width; - backHeight = height; + fun setIconSize(width: Int, height: Int) { + iconWidth = width + iconHeight = height } - public void setIconOffset(int x, int y) { - offsetX = x; - offsetY = y; + fun setCustomSize(width: Int, height: Int) { + backWidth = width + backHeight = height } - public Drawable getIcon() { - return icon; + fun setIconOffset(x: Int, y: Int) { + offsetX = x + offsetY = y } - public Drawable getBackground() { - return background; + fun setFullsize(value: Boolean) { + fullSize = value } - public void setFullsize(boolean value) { - fullSize = value; + override fun setColorFilter(colorFilter: ColorFilter?) { + icon?.colorFilter = colorFilter } - @Override - public void setColorFilter(ColorFilter colorFilter) { - icon.setColorFilter(colorFilter); + override fun isStateful(): Boolean { + return icon?.isStateful ?: false } - @Override - public boolean isStateful() { - return icon.isStateful(); + override fun setState(stateSet: IntArray): Boolean { + icon?.state = stateSet + return true } - @Override - public boolean setState(@NonNull int[] stateSet) { - icon.setState(stateSet); - return true; + override fun getState(): IntArray { + return icon?.state ?: super.getState() } - @NonNull - @Override - public int[] getState() { - return icon.getState(); + override fun onStateChange(state: IntArray): Boolean { + return true } - @Override - protected boolean onStateChange(int[] state) { - return true; + override fun jumpToCurrentState() { + icon?.jumpToCurrentState() } - @Override - public void jumpToCurrentState() { - icon.jumpToCurrentState(); + override fun getConstantState(): ConstantState? { + return icon?.constantState } - @Override - public ConstantState getConstantState() { - return icon.getConstantState(); - } - - @Override - public void draw(@NonNull Canvas canvas) { - background.setBounds(getBounds()); - background.draw(canvas); - if (icon != null) { - if (fullSize) { - android.graphics.Rect bounds = getBounds(); - if (left != 0) { - icon.setBounds(bounds.left + left, bounds.top + top, bounds.right - left, bounds.bottom - top); - } else { - icon.setBounds(bounds); - } + override fun draw(canvas: Canvas) { + background.bounds = bounds + background.draw(canvas) + if (icon == null) return + if (fullSize) { + val bounds = bounds + if (left != 0) { + icon.setBounds(bounds.left + left, bounds.top + top, bounds.right - left, bounds.bottom - top) + } else { + icon.bounds = bounds + } + } else { + val x: Int + val y: Int + if (iconWidth != 0) { + x = bounds.centerX() - iconWidth / 2 + left + offsetX + y = bounds.centerY() - iconHeight / 2 + top + offsetY + icon.setBounds(x, y, x + iconWidth, y + iconHeight) } else { - int x; - int y; - if (iconWidth != 0) { - x = getBounds().centerX() - iconWidth / 2 + left + offsetX; - y = getBounds().centerY() - iconHeight / 2 + top + offsetY; - icon.setBounds(x, y, x + iconWidth, y + iconHeight); - } else { - x = getBounds().centerX() - icon.getIntrinsicWidth() / 2 + left; - y = getBounds().centerY() - icon.getIntrinsicHeight() / 2 + top; - icon.setBounds(x, y, x + icon.getIntrinsicWidth(), y + icon.getIntrinsicHeight()); - } + x = bounds.centerX() - icon.intrinsicWidth / 2 + left + y = bounds.centerY() - icon.intrinsicHeight / 2 + top + icon.setBounds(x, y, x + icon.intrinsicWidth, y + icon.intrinsicHeight) } - icon.draw(canvas); } + icon.draw(canvas) } - @Override - public void setAlpha(int alpha) { - icon.setAlpha(alpha); - background.setAlpha(alpha); + override fun setAlpha(alpha: Int) { + icon?.alpha = alpha + background.alpha = alpha } - @Override - public int getIntrinsicWidth() { - return backWidth != 0 ? backWidth : background.getIntrinsicWidth(); + override fun getIntrinsicWidth(): Int { + return if (backWidth != 0) backWidth else background.intrinsicWidth } - @Override - public int getIntrinsicHeight() { - return backHeight != 0 ? backHeight : background.getIntrinsicHeight(); + override fun getIntrinsicHeight(): Int { + return if (backHeight != 0) backHeight else background.intrinsicHeight } - @Override - public int getMinimumWidth() { - return backWidth != 0 ? backWidth : background.getMinimumWidth(); + override fun getMinimumWidth(): Int { + return if (backWidth != 0) backWidth else background.minimumWidth } - @Override - public int getMinimumHeight() { - return backHeight != 0 ? backHeight : background.getMinimumHeight(); + override fun getMinimumHeight(): Int { + return if (backHeight != 0) backHeight else background.minimumHeight } - @Override - public int getOpacity() { - return icon.getOpacity(); + override fun getOpacity(): Int { + return icon?.opacity ?: PixelFormat.UNKNOWN } - @Override - public void invalidateDrawable(@NonNull Drawable who) { - invalidateSelf(); + override fun invalidateDrawable(who: Drawable) { + invalidateSelf() } - @Override - public void scheduleDrawable(@NonNull Drawable who, @NonNull Runnable what, long when) { - scheduleSelf(what, when); + override fun scheduleDrawable(who: Drawable, what: Runnable, `when`: Long) { + scheduleSelf(what, `when`) } - @Override - public void unscheduleDrawable(@NonNull Drawable who, @NonNull Runnable what) { - unscheduleSelf(what); + override fun unscheduleDrawable(who: Drawable, what: Runnable) { + unscheduleSelf(what) } -} +} \ No newline at end of file diff --git a/app/src/main/java/awais/instagrabber/utils/CookieUtils.kt b/app/src/main/java/awais/instagrabber/utils/CookieUtils.kt index 76bb55cd..2c1f6ae8 100644 --- a/app/src/main/java/awais/instagrabber/utils/CookieUtils.kt +++ b/app/src/main/java/awais/instagrabber/utils/CookieUtils.kt @@ -1,139 +1,114 @@ -package awais.instagrabber.utils; +@file:JvmName("CookieUtils") -import android.content.Context; -import android.util.Log; -import android.webkit.CookieManager; +package awais.instagrabber.utils -import androidx.annotation.Nullable; +import android.content.Context +import android.util.Log +import android.webkit.CookieManager +import awais.instagrabber.db.datasources.AccountDataSource +import awais.instagrabber.db.repositories.AccountRepository +import awais.instagrabber.db.repositories.RepositoryCallback +import java.net.CookiePolicy +import java.net.HttpCookie +import java.net.URI +import java.net.URISyntaxException +import java.util.regex.Pattern -import java.net.CookiePolicy; -import java.net.CookieStore; -import java.net.HttpCookie; -import java.net.URI; -import java.net.URISyntaxException; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; -import java.util.regex.Matcher; -import java.util.regex.Pattern; +private const val TAG = "CookieUtils" +private val COOKIE_MANAGER = CookieManager.getInstance() -import awais.instagrabber.BuildConfig; -import awais.instagrabber.db.datasources.AccountDataSource; -import awais.instagrabber.db.repositories.AccountRepository; -import awais.instagrabber.db.repositories.RepositoryCallback; -//import awaisomereport.LogCollector; +@JvmField +val NET_COOKIE_MANAGER = java.net.CookieManager(null, CookiePolicy.ACCEPT_ALL) -public final class CookieUtils { - private static final String TAG = CookieUtils.class.getSimpleName(); - public static final CookieManager COOKIE_MANAGER = CookieManager.getInstance(); - public static final java.net.CookieManager NET_COOKIE_MANAGER = new java.net.CookieManager(null, CookiePolicy.ACCEPT_ALL); - - public static void setupCookies(final String cookieRaw) { - final CookieStore cookieStore = NET_COOKIE_MANAGER.getCookieStore(); - if (cookieStore == null || TextUtils.isEmpty(cookieRaw)) { - return; - } - if (cookieRaw.equals("LOGOUT")) { - cookieStore.removeAll(); - return; - } - try { - final URI uri1 = new URI("https://instagram.com"); - final URI uri2 = new URI("https://instagram.com/"); - final URI uri3 = new URI("https://i.instagram.com/"); - for (final String cookie : cookieRaw.split("; ")) { - final String[] strings = cookie.split("=", 2); - final HttpCookie httpCookie = new HttpCookie(strings[0].trim(), strings[1].trim()); - httpCookie.setDomain(".instagram.com"); - httpCookie.setPath("/"); - httpCookie.setVersion(0); - cookieStore.add(uri1, httpCookie); - cookieStore.add(uri2, httpCookie); - cookieStore.add(uri3, httpCookie); - } - } catch (final URISyntaxException e) { -// if (Utils.logCollector != null) -// Utils.logCollector.appendException(e, LogCollector.LogFile.UTILS, "setupCookies"); - if (BuildConfig.DEBUG) Log.e(TAG, "", e); - } +fun setupCookies(cookieRaw: String) { + val cookieStore = NET_COOKIE_MANAGER.cookieStore + if (cookieStore == null || TextUtils.isEmpty(cookieRaw)) { + return } - - public static void removeAllAccounts(final Context context, final RepositoryCallback callback) { - final CookieStore cookieStore = NET_COOKIE_MANAGER.getCookieStore(); - if (cookieStore == null) return; - cookieStore.removeAll(); - try { - AccountRepository.getInstance(AccountDataSource.getInstance(context)) - .deleteAllAccounts(callback); - } catch (Exception e) { - Log.e(TAG, "setupCookies", e); - } + if (cookieRaw == "LOGOUT") { + cookieStore.removeAll() + return } - - public static long getUserIdFromCookie(final String cookies) { - final String dsUserId = getCookieValue(cookies, "ds_user_id"); - if (dsUserId == null) { - return 0; + try { + val uri1 = URI("https://instagram.com") + val uri2 = URI("https://instagram.com/") + val uri3 = URI("https://i.instagram.com/") + for (cookie in cookieRaw.split("; ")) { + val strings = cookie.split("=", limit = 2) + val httpCookie = HttpCookie(strings[0].trim { it <= ' ' }, strings[1].trim { it <= ' ' }) + httpCookie.domain = ".instagram.com" + httpCookie.path = "/" + httpCookie.version = 0 + cookieStore.add(uri1, httpCookie) + cookieStore.add(uri2, httpCookie) + cookieStore.add(uri3, httpCookie) } - try { - return Long.parseLong(dsUserId); - } catch (NumberFormatException e) { - Log.e(TAG, "getUserIdFromCookie: ", e); - } - return 0; + } catch (e: URISyntaxException) { + Log.e(TAG, "", e) } +} - @Nullable - public static String getCsrfTokenFromCookie(final String cookies) { - return getCookieValue(cookies, "csrftoken"); +fun removeAllAccounts(context: Context?, callback: RepositoryCallback?) { + val cookieStore = NET_COOKIE_MANAGER.cookieStore ?: return + cookieStore.removeAll() + try { + AccountRepository.getInstance(AccountDataSource.getInstance(context!!)) + .deleteAllAccounts(callback) + } catch (e: Exception) { + Log.e(TAG, "setupCookies", e) } +} - @Nullable - private static String getCookieValue(final String cookies, final String name) { - if (cookies == null) return null; - final Pattern pattern = Pattern.compile(name + "=(.+?);"); - final Matcher matcher = pattern.matcher(cookies); - if (matcher.find()) { - return matcher.group(1); - } - return null; +fun getUserIdFromCookie(cookies: String?): Long { + val dsUserId = getCookieValue(cookies, "ds_user_id") ?: return 0 + try { + return dsUserId.toLong() + } catch (e: NumberFormatException) { + Log.e(TAG, "getUserIdFromCookie: ", e) } + return 0 +} - @Nullable - public static String getCookie(@Nullable final String webViewUrl) { - final List domains = new ArrayList<>(Arrays.asList( - "https://instagram.com", - "https://instagram.com/", - "http://instagram.com", - "http://instagram.com", - "https://www.instagram.com", - "https://www.instagram.com/", - "http://www.instagram.com", - "http://www.instagram.com/" - )); - if (!TextUtils.isEmpty(webViewUrl)) { - domains.add(0, webViewUrl); - } +fun getCsrfTokenFromCookie(cookies: String?): String? { + return getCookieValue(cookies, "csrftoken") +} - return getLongestCookie(domains); - } +private fun getCookieValue(cookies: String?, name: String): String? { + if (cookies == null) return null + val pattern = Pattern.compile("$name=(.+?);") + val matcher = pattern.matcher(cookies) + return if (matcher.find()) { + matcher.group(1) + } else null +} - @Nullable - private static String getLongestCookie(final List domains) { - int longestLength = 0; - String longestCookie = null; +fun getCookie(webViewUrl: String?): String? { + val domains: List = listOfNotNull( + if (!TextUtils.isEmpty(webViewUrl)) webViewUrl else null, + "https://instagram.com", + "https://instagram.com/", + "http://instagram.com", + "http://instagram.com", + "https://www.instagram.com", + "https://www.instagram.com/", + "http://www.instagram.com", + "http://www.instagram.com/", + ) + return getLongestCookie(domains) +} - for (final String domain : domains) { - final String cookie = COOKIE_MANAGER.getCookie(domain); - if (cookie != null) { - final int cookieLength = cookie.length(); - if (cookieLength > longestLength) { - longestCookie = cookie; - longestLength = cookieLength; - } +private fun getLongestCookie(domains: List): String? { + var longestLength = 0 + var longestCookie: String? = null + for (domain in domains) { + val cookie = COOKIE_MANAGER.getCookie(domain) + if (cookie != null) { + val cookieLength = cookie.length + if (cookieLength > longestLength) { + longestCookie = cookie + longestLength = cookieLength } } - - return longestCookie; } -} + return longestCookie +} \ No newline at end of file diff --git a/app/src/main/java/awais/instagrabber/utils/CubicInterpolation.java b/app/src/main/java/awais/instagrabber/utils/CubicInterpolation.java index f5ff6510..ef059147 100644 --- a/app/src/main/java/awais/instagrabber/utils/CubicInterpolation.java +++ b/app/src/main/java/awais/instagrabber/utils/CubicInterpolation.java @@ -8,29 +8,6 @@ public class CubicInterpolation { private final int tangentFactor; private final int length; - // constructor: (array, config) -> - // @array = array.slice 0 #copy the array - // @length = @array.length #cache length - - // class CubicInterpolator extends AbstractInterpolator - // constructor: (array, config)-> - // #clamp cubic tension to [0,1] range - // @tangentFactor = 1 - Math.max 0, Math.min 1, config.cubicTension - // super - // - // # Cardinal spline with tension 0.5) - // getTangent: (k) -> @tangentFactor*(@getClippedInput(k + 1) - @getClippedInput(k - 1))/2 - // - // interpolate: (t) -> - // k = Math.floor t - // m = [(@getTangent k), (@getTangent k+1)] #get tangents - // p = [(@getClippedInput k), (@getClippedInput k+1)] #get points - // #Translate t to interpolate between k and k+1 - // t -= k - // t2 = t*t #t^2 - // t3 = t*t2 #t^3 - // #Apply cubic hermite spline formula - // return (2*t3 - 3*t2 + 1)*p[0] + (t3 - 2*t2 + t)*m[0] + (-2*t3 + 3*t2)*p[1] + (t3 - t2)*m[1] public CubicInterpolation(final float[] array, final int cubicTension) { this.array = Arrays.copyOf(array, array.length); this.length = array.length; @@ -55,16 +32,6 @@ public class CubicInterpolation { return (2 * t3 - 3 * t2 + 1) * p[0] + (t3 - 2 * t2 + t1) * m[0] + (-2 * t3 + 3 * t2) * p[1] + (t3 - t2) * m[1]; } - // getClippedInput: (i) -> - // #Normal behavior for indexes within bounds - // if 0 <= i < @length - // @array[i] - // else - // @clipHelper i - // - // clipHelperClamp: (i) -> @array[clipClamp i, @length] - // clipClamp = (i, n) -> Math.max 0, Math.min i, n - 1 - private float getClippedInput(int i) { if (i >= 0 && i < length) { return array[i]; diff --git a/app/src/main/java/awais/instagrabber/utils/DataBox.java b/app/src/main/java/awais/instagrabber/utils/DataBox.java deleted file mode 100755 index 23f5d889..00000000 --- a/app/src/main/java/awais/instagrabber/utils/DataBox.java +++ /dev/null @@ -1,43 +0,0 @@ -package awais.instagrabber.utils; - -import android.content.Context; -import android.database.sqlite.SQLiteDatabase; -import android.database.sqlite.SQLiteOpenHelper; -import android.util.Log; - -import androidx.annotation.NonNull; -import androidx.annotation.Nullable; - -public final class DataBox extends SQLiteOpenHelper { - private static final String TAG = "DataBox"; - - private static DataBox sInstance; - - private final static int VERSION = 3; - - public static synchronized DataBox getInstance(final Context context) { - if (sInstance == null) sInstance = new DataBox(context.getApplicationContext()); - return sInstance; - } - - private DataBox(@Nullable final Context context) { - super(context, "cookiebox.db", null, VERSION); - } - - @Override - public void onCreate(@NonNull final SQLiteDatabase db) { - Log.i(TAG, "Creating tables..."); - Log.i(TAG, "Tables created!"); - } - - @Override - public void onUpgrade(final SQLiteDatabase db, final int oldVersion, final int newVersion) { - Log.i(TAG, String.format("Updating DB from v%d to v%d", oldVersion, newVersion)); - // switch without break, so that all migrations from a previous version to new are run - switch (oldVersion) { - case 1: - case 2: - } - Log.i(TAG, String.format("DB update from v%d to v%d completed!", oldVersion, newVersion)); - } -} \ No newline at end of file diff --git a/app/src/main/java/awais/instagrabber/utils/DeepLinkParser.kt b/app/src/main/java/awais/instagrabber/utils/DeepLinkParser.kt index 0ef240e4..7dee2dd7 100644 --- a/app/src/main/java/awais/instagrabber/utils/DeepLinkParser.kt +++ b/app/src/main/java/awais/instagrabber/utils/DeepLinkParser.kt @@ -1,67 +1,29 @@ -package awais.instagrabber.utils; +package awais.instagrabber.utils -import androidx.annotation.NonNull; -import androidx.annotation.Nullable; +import java.util.regex.Pattern -import com.google.common.collect.ImmutableMap; +object DeepLinkParser { + private val TYPE_PATTERN_MAP: Map = mapOf( + DeepLink.Type.USER to DeepLinkPattern("instagram://user?username="), + ) -import java.util.Map; -import java.util.regex.Pattern; - -public final class DeepLinkParser { - private static final Map TYPE_PATTERN_MAP = ImmutableMap - .builder() - .put(DeepLink.Type.USER, new DeepLinkPattern("instagram://user?username=")) - .build(); - - @Nullable - public static DeepLink parse(@NonNull final String text) { - for (final Map.Entry entry : TYPE_PATTERN_MAP.entrySet()) { - if (text.startsWith(entry.getValue().getPatternText())) { - final String value = entry.getValue().getPattern().matcher(text).replaceAll(""); - return new DeepLink(entry.getKey(), value); + @JvmStatic + fun parse(text: String): DeepLink? { + for ((key, value) in TYPE_PATTERN_MAP) { + if (text.startsWith(value.patternText)) { + return DeepLink(key, value.pattern.matcher(text).replaceAll("")) } } - return null; + return null } - public static class DeepLinkPattern { - private final String patternText; - private final Pattern pattern; - - public DeepLinkPattern(final String patternText) { - this.patternText = patternText; - pattern = Pattern.compile(patternText, Pattern.LITERAL); - } - - public String getPatternText() { - return patternText; - } - - public Pattern getPattern() { - return pattern; - } + data class DeepLinkPattern(val patternText: String) { + val pattern: Pattern = Pattern.compile(patternText, Pattern.LITERAL) } - public static class DeepLink { - private final Type type; - private final String value; - - public DeepLink(final Type type, final String value) { - this.type = type; - this.value = value; - } - - public Type getType() { - return type; - } - - public String getValue() { - return value; - } - - public enum Type { - USER, + data class DeepLink(val type: Type, val value: String) { + enum class Type { + USER } } -} +} \ No newline at end of file diff --git a/app/src/main/java/awais/instagrabber/utils/LocaleUtils.kt b/app/src/main/java/awais/instagrabber/utils/LocaleUtils.kt index 7b623bc5..7ff7d87b 100755 --- a/app/src/main/java/awais/instagrabber/utils/LocaleUtils.kt +++ b/app/src/main/java/awais/instagrabber/utils/LocaleUtils.kt @@ -1,91 +1,83 @@ -package awais.instagrabber.utils; +package awais.instagrabber.utils -import android.content.Context; -import android.content.res.Configuration; -import android.content.res.Resources; -import android.view.ContextThemeWrapper; - -import androidx.annotation.Nullable; - -import java.util.Locale; - -import awais.instagrabber.fragments.settings.PreferenceKeys; +import android.content.Context +import android.content.res.Configuration +import android.view.ContextThemeWrapper +import awais.instagrabber.fragments.settings.PreferenceKeys +import java.util.* // taken from my app TESV Console Codes -public final class LocaleUtils { - private static Locale defaultLocale, currentLocale; - - public static void setLocale(Context baseContext) { - if (defaultLocale == null) defaultLocale = Locale.getDefault(); - - if (baseContext instanceof ContextThemeWrapper) - baseContext = ((ContextThemeWrapper) baseContext).getBaseContext(); - - if (Utils.settingsHelper == null) - Utils.settingsHelper = new SettingsHelper(baseContext); - - final String appLanguageSettings = Utils.settingsHelper.getString(PreferenceKeys.APP_LANGUAGE); - final String lang = LocaleUtils.getCorrespondingLanguageCode(appLanguageSettings); - - currentLocale = TextUtils.isEmpty(lang) ? defaultLocale : - (lang.contains("_") ? new Locale(lang.split("_")[0], lang.split("_")[1]) : new Locale(lang)); - Locale.setDefault(currentLocale); - - final Resources res = baseContext.getResources(); - final Configuration config = res.getConfiguration(); - - config.locale = currentLocale; - config.setLocale(currentLocale); - config.setLayoutDirection(currentLocale); - - res.updateConfiguration(config, res.getDisplayMetrics()); - } - - public static Locale getCurrentLocale() { - return currentLocale; - } - - public static void updateConfig(final ContextThemeWrapper wrapper) { - if (currentLocale != null) { - final Configuration configuration = new Configuration(); - configuration.locale = currentLocale; - configuration.setLocale(currentLocale); - wrapper.applyOverrideConfiguration(configuration); +object LocaleUtils { + private var defaultLocale: Locale? = null + + @JvmStatic + var currentLocale: Locale? = null + private set + + @JvmStatic + fun setLocale(baseContext: Context) { + var baseContext1 = baseContext + if (defaultLocale == null) defaultLocale = Locale.getDefault() + if (baseContext1 is ContextThemeWrapper) baseContext1 = baseContext1.baseContext + if (Utils.settingsHelper == null) Utils.settingsHelper = SettingsHelper(baseContext1) + val appLanguageSettings = Utils.settingsHelper.getString(PreferenceKeys.APP_LANGUAGE) + val lang = getCorrespondingLanguageCode(appLanguageSettings) + currentLocale = when { + TextUtils.isEmpty(lang) -> defaultLocale + lang!!.contains("_") -> { + val split = lang.split("_") + Locale(split[0], split[1]) + } + else -> Locale(lang) + } + currentLocale?.let { + Locale.setDefault(it) + val res = baseContext1.resources + val config = res.configuration + // config.locale = currentLocale + config.setLocale(it) + config.setLayoutDirection(it) + res.updateConfiguration(config, res.displayMetrics) } } - @Nullable - public static String getCorrespondingLanguageCode(final String appLanguageSettings) { - if (TextUtils.isEmpty(appLanguageSettings)) return null; + @JvmStatic + fun updateConfig(wrapper: ContextThemeWrapper) { + if (currentLocale == null) return + val configuration = Configuration() + // configuration.locale = currentLocale + configuration.setLocale(currentLocale) + wrapper.applyOverrideConfiguration(configuration) + } - final int appLanguageIndex = Integer.parseInt(appLanguageSettings); - switch (appLanguageIndex) { - case 1: return "en"; - case 2: return "fr"; - case 3: return "es"; - case 4: return "zh_CN"; - case 5: return "in"; - case 6: return "it"; - case 7: return "de"; - case 8: return "pl"; - case 9: return "tr"; - case 10: return "pt"; - case 11: return "fa"; - case 12: return "mk"; - case 13: return "vi"; - case 14: return "zh_TW"; - case 15: return "ca"; - case 16: return "ru"; - case 17: return "hi"; - case 18: return "nl"; - case 19: return "sk"; - case 20: return "ja"; - case 21: return "el"; - case 22: return "eu"; - case 23: return "sv"; - case 24: return "ko"; + fun getCorrespondingLanguageCode(appLanguageSettings: String): String? { + if (TextUtils.isEmpty(appLanguageSettings)) return null + when (appLanguageSettings.toInt()) { + 1 -> return "en" + 2 -> return "fr" + 3 -> return "es" + 4 -> return "zh_CN" + 5 -> return "in" + 6 -> return "it" + 7 -> return "de" + 8 -> return "pl" + 9 -> return "tr" + 10 -> return "pt" + 11 -> return "fa" + 12 -> return "mk" + 13 -> return "vi" + 14 -> return "zh_TW" + 15 -> return "ca" + 16 -> return "ru" + 17 -> return "hi" + 18 -> return "nl" + 19 -> return "sk" + 20 -> return "ja" + 21 -> return "el" + 22 -> return "eu" + 23 -> return "sv" + 24 -> return "ko" } - - return null; + return null } -} +} \ No newline at end of file diff --git a/app/src/main/java/awais/instagrabber/utils/MediaUploadHelper.kt b/app/src/main/java/awais/instagrabber/utils/MediaUploadHelper.kt index 2b5baddf..2b6825d1 100644 --- a/app/src/main/java/awais/instagrabber/utils/MediaUploadHelper.kt +++ b/app/src/main/java/awais/instagrabber/utils/MediaUploadHelper.kt @@ -7,6 +7,7 @@ import awais.instagrabber.models.UploadVideoOptions import awais.instagrabber.models.enums.MediaItemType import org.json.JSONObject import java.util.* +import kotlin.random.Random private const val LOWER = 1000000000L @@ -109,7 +110,7 @@ fun generateUploadId(): String { } fun generateName(uploadId: String): String { - val random = NumberUtils.random(LOWER, UPPER + 1) + val random = Random.nextLong(LOWER, UPPER + 1) return "${uploadId}_0_$random" } diff --git a/app/src/main/java/awais/instagrabber/utils/NullSafePair.kt b/app/src/main/java/awais/instagrabber/utils/NullSafePair.kt index 43c5a7d4..e0dd253c 100644 --- a/app/src/main/java/awais/instagrabber/utils/NullSafePair.kt +++ b/app/src/main/java/awais/instagrabber/utils/NullSafePair.kt @@ -1,4 +1,4 @@ -package awais.instagrabber.utils; +package awais.instagrabber.utils /* * Copyright (C) 2009 The Android Open Source Project @@ -15,77 +15,28 @@ package awais.instagrabber.utils; * See the License for the specific language governing permissions and * limitations under the License. */ - - -import androidx.annotation.NonNull; -import androidx.annotation.Nullable; -import androidx.core.util.ObjectsCompat; - /** * Container to ease passing around a tuple of two objects. This object provides a sensible * implementation of equals(), returning true if equals() is true on each of the contained * objects. */ -public class NullSafePair { - public final @NonNull - F first; - public final @NonNull - S second; - - /** - * Constructor for a Pair. - * - * @param first the first object in the Pair - * @param second the second object in the pair - */ - public NullSafePair(@NonNull F first, @NonNull S second) { - this.first = first; - this.second = second; - } - - /** - * Checks the two objects for equality by delegating to their respective - * {@link Object#equals(Object)} methods. - * - * @param o the {@link androidx.core.util.Pair} to which this one is to be checked for equality - * @return true if the underlying objects of the Pair are both considered - * equal - */ - @Override - public boolean equals(Object o) { - if (!(o instanceof androidx.core.util.Pair)) { - return false; +/** + * Constructor for a Pair. + * + * @param first the first object in the Pair + * @param second the second object in the pair + */ +data class NullSafePair(@JvmField val first: F, @JvmField val second: S) { + companion object { + /** + * Convenience method for creating an appropriately typed pair. + * + * @param a the first object in the Pair + * @param b the second object in the pair + * @return a Pair that is templatized with the types of a and b + */ + fun create(a: A, b: B): NullSafePair { + return NullSafePair(a, b) } - androidx.core.util.Pair p = (androidx.core.util.Pair) o; - return ObjectsCompat.equals(p.first, first) && ObjectsCompat.equals(p.second, second); - } - - /** - * Compute a hash code using the hash codes of the underlying objects - * - * @return a hashcode of the Pair - */ - @Override - public int hashCode() { - return first.hashCode() ^ second.hashCode(); - } - - @NonNull - @Override - public String toString() { - return "Pair{" + first + " " + second + "}"; - } - - /** - * Convenience method for creating an appropriately typed pair. - * - * @param a the first object in the Pair - * @param b the second object in the pair - * @return a Pair that is templatized with the types of a and b - */ - @NonNull - public static androidx.core.util.Pair create(@Nullable A a, @Nullable B b) { - return new androidx.core.util.Pair(a, b); } -} - +} \ No newline at end of file diff --git a/app/src/main/java/awais/instagrabber/utils/NumberUtils.kt b/app/src/main/java/awais/instagrabber/utils/NumberUtils.kt index 5ad9ceea..ab475350 100644 --- a/app/src/main/java/awais/instagrabber/utils/NumberUtils.kt +++ b/app/src/main/java/awais/instagrabber/utils/NumberUtils.kt @@ -1,149 +1,87 @@ -package awais.instagrabber.utils; +@file:JvmName("NumberUtils") -import androidx.annotation.NonNull; -import androidx.annotation.Nullable; +package awais.instagrabber.utils -import java.util.Locale; -import java.util.Random; +import java.util.* +import kotlin.math.ln +import kotlin.math.pow -public final class NumberUtils { - // @NonNull - // public static String millisToString(final long timeMs) { - // final long totalSeconds = timeMs / 1000; - // - // final long seconds = totalSeconds % 60; - // final long minutes = totalSeconds / 60 % 60; - // final long hours = totalSeconds / 3600; - // - // final String strSec = Long.toString(seconds); - // final String strMin = Long.toString(minutes); - // - // final String strRetSec = strSec.length() > 1 ? strSec : "0" + seconds; - // final String strRetMin = strMin.length() > 1 ? strMin : "0" + minutes; - // - // final String retMinSec = strRetMin + ':' + strRetSec; - // - // if (hours > 0) - // return Long.toString(hours) + ':' + retMinSec; - // return retMinSec; - // } - - public static int getResultingHeight(final int requiredWidth, final int height, final int width) { - return requiredWidth * height / width; - } - - public static int getResultingWidth(final int requiredHeight, final int height, final int width) { - return requiredHeight * width / height; - } +fun getResultingHeight(requiredWidth: Int, height: Int, width: Int): Int { + return requiredWidth * height / width +} - public static long random(long origin, long bound) { - final Random random = new Random(); - long r = random.nextLong(); - long n = bound - origin, m = n - 1; - if ((n & m) == 0L) // power of two - r = (r & m) + origin; - else if (n > 0L) { // reject over-represented candidates - //noinspection StatementWithEmptyBody - for (long u = r >>> 1; // ensure non-negative - u + m - (r = u % n) < 0L; // rejection check - u = random.nextLong() >>> 1) // retry - ; - r += origin; - } else { // range not representable as long - while (r < origin || r >= bound) - r = random.nextLong(); - } - return r; - } +fun getResultingWidth(requiredHeight: Int, height: Int, width: Int): Int { + return requiredHeight * width / height +} - @NonNull - public static NullSafePair calculateWidthHeight(final int height, final int width, final int maxHeight, final int maxWidth) { - if (width > maxWidth) { - int tempHeight = getResultingHeight(maxWidth, height, width); - int tempWidth = maxWidth; - if (tempHeight > maxHeight) { - tempWidth = getResultingWidth(maxHeight, tempHeight, tempWidth); - tempHeight = maxHeight; +// TODO Replace all usages with kotlin Random.nextLong() once converted to kotlin +fun random(origin: Long, bound: Long): Long { + val random = Random() + var r = random.nextLong() + val n = bound - origin + val m = n - 1 + when { + n and m == 0L -> r = (r and m) + origin // power of two + n > 0L -> { + // reject over-represented candidates + var u = r ushr 1 // ensure non-negative + while (u + m - u % n.also { r = it } < 0L) { // rejection check + // retry + u = random.nextLong() ushr 1 } - return new NullSafePair<>(tempWidth, tempHeight); + r += origin } - if ((height < maxHeight && width < maxWidth) || (height > maxHeight)) { - int tempWidth = getResultingWidth(maxHeight, height, width); - int tempHeight = maxHeight; - if (tempWidth > maxWidth) { - tempHeight = getResultingHeight(maxWidth, tempHeight, tempWidth); - tempWidth = maxWidth; - } - return new NullSafePair<>(tempWidth, tempHeight); + else -> { + // range not representable as long + while (r < origin || r >= bound) r = random.nextLong() } - return new NullSafePair<>(width, height); } + return r +} - public static float roundFloat2Decimals(final float value) { - return ((int) ((value + (value >= 0 ? 1 : -1) * 0.005f) * 100)) / 100f; - } - - @NonNull - public static String abbreviate(final long number) { - return abbreviate(number, null); - } - - - @NonNull - public static String abbreviate(final long number, @Nullable final AbbreviateOptions options) { - // adapted from https://stackoverflow.com/a/9769590/1436766 - int threshold = 1000; - boolean addSpace = false; - if (options != null) { - threshold = options.getThreshold(); - addSpace = options.addSpaceBeforePrefix(); +fun calculateWidthHeight(height: Int, width: Int, maxHeight: Int, maxWidth: Int): NullSafePair { + if (width > maxWidth) { + var tempHeight = getResultingHeight(maxWidth, height, width) + var tempWidth = maxWidth + if (tempHeight > maxHeight) { + tempWidth = getResultingWidth(maxHeight, tempHeight, tempWidth) + tempHeight = maxHeight } - if (number < threshold) return "" + number; - int exp = (int) (Math.log(number) / Math.log(threshold)); - return String.format(Locale.US, - "%.1f%s%c", - number / Math.pow(threshold, exp), - addSpace ? " " : "", - "kMGTPE".charAt(exp - 1)); + return NullSafePair(tempWidth, tempHeight) } - - public static final class AbbreviateOptions { - private final int threshold; - private final boolean addSpaceBeforePrefix; - - public static final class Builder { - - private int threshold = 1000; - private boolean addSpaceBeforePrefix = false; - - public Builder setThreshold(final int threshold) { - this.threshold = threshold; - return this; - } - - public Builder setAddSpaceBeforePrefix(final boolean addSpaceBeforePrefix) { - this.addSpaceBeforePrefix = addSpaceBeforePrefix; - return this; - } - - @NonNull - public AbbreviateOptions build() { - return new AbbreviateOptions(threshold, addSpaceBeforePrefix); - } - - } - - private AbbreviateOptions(final int threshold, final boolean addSpaceBeforePrefix) { - this.threshold = threshold; - this.addSpaceBeforePrefix = addSpaceBeforePrefix; + if (height < maxHeight && width < maxWidth || height > maxHeight) { + var tempWidth = getResultingWidth(maxHeight, height, width) + var tempHeight = maxHeight + if (tempWidth > maxWidth) { + tempHeight = getResultingHeight(maxWidth, tempHeight, tempWidth) + tempWidth = maxWidth } + return NullSafePair(tempWidth, tempHeight) + } + return NullSafePair(width, height) +} - public int getThreshold() { - return threshold; - } +fun roundFloat2Decimals(value: Float): Float { + return ((value + (if (value >= 0) 1 else -1) * 0.005f) * 100).toInt() / 100f +} - public boolean addSpaceBeforePrefix() { - return addSpaceBeforePrefix; - } +fun abbreviate(number: Long, options: AbbreviateOptions? = null): String { + // adapted from https://stackoverflow.com/a/9769590/1436766 + var threshold = 1000 + var addSpace = false + if (options != null) { + threshold = options.threshold + addSpace = options.addSpaceBeforePrefix } + if (number < threshold) return "" + number + val exp = (ln(number.toDouble()) / ln(threshold.toDouble())).toInt() + return String.format( + Locale.US, + "%.1f%s%c", + number / threshold.toDouble().pow(exp.toDouble()), + if (addSpace) " " else "", + "kMGTPE"[exp - 1] + ) } + +data class AbbreviateOptions(val threshold: Int = 1000, val addSpaceBeforePrefix: Boolean = false) \ No newline at end of file diff --git a/app/src/main/java/awais/instagrabber/utils/RankedRecipientsCache.kt b/app/src/main/java/awais/instagrabber/utils/RankedRecipientsCache.kt index 72263971..29a28ba1 100644 --- a/app/src/main/java/awais/instagrabber/utils/RankedRecipientsCache.kt +++ b/app/src/main/java/awais/instagrabber/utils/RankedRecipientsCache.kt @@ -1,69 +1,27 @@ -package awais.instagrabber.utils; - -import java.time.LocalDateTime; -import java.time.temporal.ChronoUnit; -import java.util.Collections; -import java.util.List; - -import awais.instagrabber.repositories.responses.directmessages.RankedRecipient; -import awais.instagrabber.repositories.responses.directmessages.RankedRecipientsResponse; - -public class RankedRecipientsCache { - private static final Object LOCK = new Object(); - - private static RankedRecipientsCache instance; - - public static RankedRecipientsCache getInstance() { - if (instance == null) { - synchronized (LOCK) { - if (instance == null) { - instance = new RankedRecipientsCache(); - } - } - } - return instance; - } - - private LocalDateTime lastUpdatedOn; - private RankedRecipientsResponse response; - private boolean updateInitiated = false; - private boolean failed = false; - - private RankedRecipientsCache() {} - - public List getRankedRecipients() { - if (response != null) { - return response.getRankedRecipients(); +package awais.instagrabber.utils + +import awais.instagrabber.repositories.responses.directmessages.RankedRecipient +import awais.instagrabber.repositories.responses.directmessages.RankedRecipientsResponse +import java.time.LocalDateTime +import java.time.temporal.ChronoUnit + +object RankedRecipientsCache { + private var lastUpdatedOn: LocalDateTime? = null + var isUpdateInitiated = false + var isFailed = false + val rankedRecipients: List + get() = response?.rankedRecipients ?: emptyList() + + var response: RankedRecipientsResponse? = null + set(value) { + field = value + lastUpdatedOn = LocalDateTime.now() } - return Collections.emptyList(); - } - public void setRankedRecipientsResponse(final RankedRecipientsResponse response) { - this.response = response; - lastUpdatedOn = LocalDateTime.now(); - } - - public boolean isExpired() { - if (lastUpdatedOn == null || response == null) { - return true; + val isExpired: Boolean + get() { + if (lastUpdatedOn == null || response == null) return true + val expiresInSecs = response!!.expires + return LocalDateTime.now().isAfter(lastUpdatedOn!!.plus(expiresInSecs, ChronoUnit.SECONDS)) } - final long expiresInSecs = response.getExpires(); - return LocalDateTime.now().isAfter(lastUpdatedOn.plus(expiresInSecs, ChronoUnit.SECONDS)); - } - - public boolean isUpdateInitiated() { - return updateInitiated; - } - - public void setUpdateInitiated(final boolean updateInitiated) { - this.updateInitiated = updateInitiated; - } - - public boolean isFailed() { - return failed; - } - - public void setFailed(final boolean failed) { - this.failed = failed; - } -} +} \ No newline at end of file diff --git a/app/src/main/java/awais/instagrabber/utils/SerializablePair.kt b/app/src/main/java/awais/instagrabber/utils/SerializablePair.kt index bd300536..eb8ad6f2 100644 --- a/app/src/main/java/awais/instagrabber/utils/SerializablePair.kt +++ b/app/src/main/java/awais/instagrabber/utils/SerializablePair.kt @@ -1,17 +1,12 @@ -package awais.instagrabber.utils; +package awais.instagrabber.utils -import android.util.Pair; +import android.util.Pair +import java.io.Serializable -import java.io.Serializable; - -public class SerializablePair extends Pair implements Serializable { - /** - * Constructor for a Pair. - * - * @param first the first object in the Pair - * @param second the second object in the pair - */ - public SerializablePair(final F first, final S second) { - super(first, second); - } -} +/** + * Constructor for a Pair. + * + * @param first the first object in the Pair + * @param second the second object in the pair + */ +data class SerializablePair(@JvmField val first: F, @JvmField val second: S) : Pair(first, second), Serializable \ No newline at end of file diff --git a/app/src/main/java/awais/instagrabber/utils/UpdateCheckCommon.kt b/app/src/main/java/awais/instagrabber/utils/UpdateCheckCommon.kt index a4f4b255..926125ed 100644 --- a/app/src/main/java/awais/instagrabber/utils/UpdateCheckCommon.kt +++ b/app/src/main/java/awais/instagrabber/utils/UpdateCheckCommon.kt @@ -1,38 +1,36 @@ -package awais.instagrabber.utils; - -import android.content.Context; -import android.content.DialogInterface; - -import androidx.annotation.NonNull; - -import com.google.android.material.dialog.MaterialAlertDialogBuilder; - -import awais.instagrabber.BuildConfig; -import awais.instagrabber.R; - -import static awais.instagrabber.utils.Utils.settingsHelper; - -public final class UpdateCheckCommon { - - public static boolean shouldShowUpdateDialog(final boolean force, - @NonNull final String version) { - final String skippedVersion = settingsHelper.getString(Constants.SKIPPED_VERSION); - return force || (!BuildConfig.DEBUG && !skippedVersion.equals(version)); - } +@file:JvmName("UpdateCheckCommon") + +package awais.instagrabber.utils + +import android.content.Context +import android.content.DialogInterface +import awais.instagrabber.BuildConfig +import awais.instagrabber.R +import awais.instagrabber.utils.AppExecutors.mainThread +import com.google.android.material.dialog.MaterialAlertDialogBuilder + +fun shouldShowUpdateDialog( + force: Boolean, + version: String +): Boolean { + val skippedVersion = Utils.settingsHelper.getString(Constants.SKIPPED_VERSION) + return force || !BuildConfig.DEBUG && skippedVersion != version +} - public static void showUpdateDialog(@NonNull final Context context, - @NonNull final String version, - @NonNull final DialogInterface.OnClickListener onDownloadClickListener) { - AppExecutors.INSTANCE.getMainThread().execute(() -> { - new MaterialAlertDialogBuilder(context) - .setTitle(context.getString(R.string.update_available, version)) - .setNeutralButton(R.string.skip_update, (dialog, which) -> { - settingsHelper.putString(Constants.SKIPPED_VERSION, version); - dialog.dismiss(); - }) - .setPositiveButton(R.string.action_download, onDownloadClickListener) - .setNegativeButton(R.string.cancel, null) - .show(); - }); +fun showUpdateDialog( + context: Context, + version: String, + onDownloadClickListener: DialogInterface.OnClickListener +) { + mainThread.execute { + MaterialAlertDialogBuilder(context).apply { + setTitle(context.getString(R.string.update_available, version)) + setNeutralButton(R.string.skip_update) { dialog: DialogInterface, which: Int -> + Utils.settingsHelper.putString(Constants.SKIPPED_VERSION, version) + dialog.dismiss() + } + setPositiveButton(R.string.action_download, onDownloadClickListener) + setNegativeButton(R.string.cancel, null) + }.show() } -} +} \ No newline at end of file diff --git a/app/src/main/java/awais/instagrabber/utils/UserAgentUtils.kt b/app/src/main/java/awais/instagrabber/utils/UserAgentUtils.kt index d8fc3837..6fcf616f 100644 --- a/app/src/main/java/awais/instagrabber/utils/UserAgentUtils.kt +++ b/app/src/main/java/awais/instagrabber/utils/UserAgentUtils.kt @@ -1,85 +1,82 @@ -package awais.instagrabber.utils; +@file:JvmName("UserAgentUtils") -import androidx.annotation.NonNull; +package awais.instagrabber.utils -public class UserAgentUtils { +/* GraphQL user agents (which are just standard browser UA"s). + * Go to https://www.whatismybrowser.com/guides/the-latest-user-agent/ to update it + * Windows first (Assume win64 not wow64): Chrome, Firefox, Edge + * Then macOS: Chrome, Firefox, Safari + */ +@JvmField +val browsers = arrayOf( + "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.212 Safari/537.36", + "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:88.0) Gecko/20100101 Firefox/88.0", + "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.212 Safari/537.36 Edg/90.0.818.62", + "Mozilla/5.0 (Macintosh; Intel Mac OS X 11_3_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.212 Safari/537.36", + "Mozilla/5.0 (Macintosh; Intel Mac OS X 11.3; rv:88.0) Gecko/20100101 Firefox/88.0", + "Mozilla/5.0 (Macintosh; Intel Mac OS X 11_3_1) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/14.1 Safari/605.1.15" +) - /* GraphQL user agents (which are just standard browser UA"s). - * Go to https://www.whatismybrowser.com/guides/the-latest-user-agent/ to update it - * Windows first (Assume win64 not wow64): Chrome, Firefox, Edge - * Then macOS: Chrome, Firefox, Safari - */ - public static final String[] browsers = { - "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.212 Safari/537.36", - "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:88.0) Gecko/20100101 Firefox/88.0", - "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.212 Safari/537.36 Edg/90.0.818.62", - "Mozilla/5.0 (Macintosh; Intel Mac OS X 11_3_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.212 Safari/537.36", - "Mozilla/5.0 (Macintosh; Intel Mac OS X 11.3; rv:88.0) Gecko/20100101 Firefox/88.0", - "Mozilla/5.0 (Macintosh; Intel Mac OS X 11_3_1) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/14.1 Safari/605.1.15" - }; - // use APKpure, assume arm64-v8a - private static final String igVersion = "188.0.0.35.124"; - private static final String igVersionCode = "292080186"; - // you can pick *any* device as long as you LEAVE OUT the resolution for maximum download quality - public static final String[] devices = { - // https://github.com/dilame/instagram-private-api/blob/master/src/samples/devices.json - "25/7.1.1; 440dpi; 2880x5884; Xiaomi; Mi Note 3; jason; qcom", - "23/6.0.1; 480dpi; 2880x5884; Xiaomi; Redmi Note 3; kenzo; qcom", - "23/6.0; 480dpi; 2880x5884; Xiaomi; Redmi Note 4; nikel; mt6797", - "24/7.0; 480dpi; 2880x5884; Xiaomi/xiaomi; Redmi Note 4; mido; qcom", - "23/6.0; 480dpi; 2880x5884; Xiaomi; Redmi Note 4X; nikel; mt6797", - "27/8.1.0; 440dpi; 2880x5884; Xiaomi/xiaomi; Redmi Note 5; whyred; qcom", - "23/6.0.1; 480dpi; 2880x5884; Xiaomi; Redmi 4; markw; qcom", - "27/8.1.0; 440dpi; 2880x5884; Xiaomi/xiaomi; Redmi 5 Plus; vince; qcom", - "25/7.1.2; 440dpi; 2880x5884; Xiaomi/xiaomi; Redmi 5 Plus; vince; qcom", - "26/8.0.0; 480dpi; 2880x5884; Xiaomi; MI 5; gemini; qcom", - "27/8.1.0; 480dpi; 2880x5884; Xiaomi/xiaomi; Mi A1; tissot_sprout; qcom", - "26/8.0.0; 480dpi; 2880x5884; Xiaomi; MI 6; sagit; qcom", - "25/7.1.1; 440dpi; 2880x5884; Xiaomi; MI MAX 2; oxygen; qcom", - "24/7.0; 480dpi; 2880x5884; Xiaomi; MI 5s; capricorn; qcom", - "26/8.0.0; 480dpi; 2880x5884; samsung; SM-A520F; a5y17lte; samsungexynos7880", - "26/8.0.0; 480dpi; 2880x5884; samsung; SM-G950F; dreamlte; samsungexynos8895", - "26/8.0.0; 640dpi; 2880x5884; samsung; SM-G950F; dreamlte; samsungexynos8895", - "26/8.0.0; 420dpi; 2880x5884; samsung; SM-G955F; dream2lte; samsungexynos8895", - "26/8.0.0; 560dpi; 2880x5884; samsung; SM-G955F; dream2lte; samsungexynos8895", - "24/7.0; 480dpi; 2880x5884; samsung; SM-A510F; a5xelte; samsungexynos7580", - "26/8.0.0; 480dpi; 2880x5884; samsung; SM-G930F; herolte; samsungexynos8890", - "26/8.0.0; 480dpi; 2880x5884; samsung; SM-G935F; hero2lte; samsungexynos8890", - "26/8.0.0; 420dpi; 2880x5884; samsung; SM-G965F; star2lte; samsungexynos9810", - "26/8.0.0; 480dpi; 2880x5884; samsung; SM-A530F; jackpotlte; samsungexynos7885", - "24/7.0; 640dpi; 2880x5884; samsung; SM-G925F; zerolte; samsungexynos7420", - "26/8.0.0; 420dpi; 2880x5884; samsung; SM-A720F; a7y17lte; samsungexynos7880", - "24/7.0; 640dpi; 2880x5884; samsung; SM-G920F; zeroflte; samsungexynos7420", - "24/7.0; 420dpi; 2880x5884; samsung; SM-J730FM; j7y17lte; samsungexynos7870", - "26/8.0.0; 480dpi; 2880x5884; samsung; SM-G960F; starlte; samsungexynos9810", - "26/8.0.0; 420dpi; 2880x5884; samsung; SM-N950F; greatlte; samsungexynos8895", - "26/8.0.0; 420dpi; 2880x5884; samsung; SM-A730F; jackpot2lte; samsungexynos7885", - "26/8.0.0; 420dpi; 2880x5884; samsung; SM-A605FN; a6plte; qcom", - "26/8.0.0; 480dpi; 2880x5884; HUAWEI/HONOR; STF-L09; HWSTF; hi3660", - "27/8.1.0; 480dpi; 2880x5884; HUAWEI/HONOR; COL-L29; HWCOL; kirin970", - "26/8.0.0; 480dpi; 2880x5884; HUAWEI/HONOR; LLD-L31; HWLLD-H; hi6250", - "26/8.0.0; 480dpi; 2880x5884; HUAWEI; ANE-LX1; HWANE; hi6250", - "26/8.0.0; 480dpi; 2880x5884; HUAWEI; FIG-LX1; HWFIG-H; hi6250", - "27/8.1.0; 480dpi; 2880x5884; HUAWEI/HONOR; COL-L29; HWCOL; kirin970", - "26/8.0.0; 480dpi; 2880x5884; HUAWEI/HONOR; BND-L21; HWBND-H; hi6250", - "23/6.0.1; 420dpi; 2880x5884; LeMobile/LeEco; Le X527; le_s2_ww; qcom", - // https://github.com/mimmi20/BrowserDetector/tree/master - "28/9; 560dpi; 2880x5884; samsung; SM-N960F; crownlte; samsungexynos9810", - // mgp25 - "23/6.0.1; 640dpi; 2880x5884; LGE/lge; RS988; h1; h1", - "24/7.0; 640dpi; 2880x5884; HUAWEI; LON-L29; HWLON; hi3660", - "23/6.0.1; 640dpi; 2880x5884; ZTE; ZTE A2017U; ailsa_ii; qcom", - "23/6.0.1; 640dpi; 2880x5884; samsung; SM-G935F; hero2lte; samsungexynos8890", - "23/6.0.1; 640dpi; 2880x5884; samsung; SM-G930F; herolte; samsungexynos8890" - }; +// use APKpure, assume arm64-v8a +private const val igVersion = "188.0.0.35.124" +private const val igVersionCode = "292080186" - @NonNull - public static String generateBrowserUA(final int code) { - return browsers[code]; - } +// you can pick *any* device as long as you LEAVE OUT the resolution for maximum download quality +// https://github.com/dilame/instagram-private-api/blob/master/src/samples/devices.json +@JvmField +val devices = arrayOf( + "25/7.1.1; 440dpi; 2880x5884; Xiaomi; Mi Note 3; jason; qcom", + "23/6.0.1; 480dpi; 2880x5884; Xiaomi; Redmi Note 3; kenzo; qcom", + "23/6.0; 480dpi; 2880x5884; Xiaomi; Redmi Note 4; nikel; mt6797", + "24/7.0; 480dpi; 2880x5884; Xiaomi/xiaomi; Redmi Note 4; mido; qcom", + "23/6.0; 480dpi; 2880x5884; Xiaomi; Redmi Note 4X; nikel; mt6797", + "27/8.1.0; 440dpi; 2880x5884; Xiaomi/xiaomi; Redmi Note 5; whyred; qcom", + "23/6.0.1; 480dpi; 2880x5884; Xiaomi; Redmi 4; markw; qcom", + "27/8.1.0; 440dpi; 2880x5884; Xiaomi/xiaomi; Redmi 5 Plus; vince; qcom", + "25/7.1.2; 440dpi; 2880x5884; Xiaomi/xiaomi; Redmi 5 Plus; vince; qcom", + "26/8.0.0; 480dpi; 2880x5884; Xiaomi; MI 5; gemini; qcom", + "27/8.1.0; 480dpi; 2880x5884; Xiaomi/xiaomi; Mi A1; tissot_sprout; qcom", + "26/8.0.0; 480dpi; 2880x5884; Xiaomi; MI 6; sagit; qcom", + "25/7.1.1; 440dpi; 2880x5884; Xiaomi; MI MAX 2; oxygen; qcom", + "24/7.0; 480dpi; 2880x5884; Xiaomi; MI 5s; capricorn; qcom", + "26/8.0.0; 480dpi; 2880x5884; samsung; SM-A520F; a5y17lte; samsungexynos7880", + "26/8.0.0; 480dpi; 2880x5884; samsung; SM-G950F; dreamlte; samsungexynos8895", + "26/8.0.0; 640dpi; 2880x5884; samsung; SM-G950F; dreamlte; samsungexynos8895", + "26/8.0.0; 420dpi; 2880x5884; samsung; SM-G955F; dream2lte; samsungexynos8895", + "26/8.0.0; 560dpi; 2880x5884; samsung; SM-G955F; dream2lte; samsungexynos8895", + "24/7.0; 480dpi; 2880x5884; samsung; SM-A510F; a5xelte; samsungexynos7580", + "26/8.0.0; 480dpi; 2880x5884; samsung; SM-G930F; herolte; samsungexynos8890", + "26/8.0.0; 480dpi; 2880x5884; samsung; SM-G935F; hero2lte; samsungexynos8890", + "26/8.0.0; 420dpi; 2880x5884; samsung; SM-G965F; star2lte; samsungexynos9810", + "26/8.0.0; 480dpi; 2880x5884; samsung; SM-A530F; jackpotlte; samsungexynos7885", + "24/7.0; 640dpi; 2880x5884; samsung; SM-G925F; zerolte; samsungexynos7420", + "26/8.0.0; 420dpi; 2880x5884; samsung; SM-A720F; a7y17lte; samsungexynos7880", + "24/7.0; 640dpi; 2880x5884; samsung; SM-G920F; zeroflte; samsungexynos7420", + "24/7.0; 420dpi; 2880x5884; samsung; SM-J730FM; j7y17lte; samsungexynos7870", + "26/8.0.0; 480dpi; 2880x5884; samsung; SM-G960F; starlte; samsungexynos9810", + "26/8.0.0; 420dpi; 2880x5884; samsung; SM-N950F; greatlte; samsungexynos8895", + "26/8.0.0; 420dpi; 2880x5884; samsung; SM-A730F; jackpot2lte; samsungexynos7885", + "26/8.0.0; 420dpi; 2880x5884; samsung; SM-A605FN; a6plte; qcom", + "26/8.0.0; 480dpi; 2880x5884; HUAWEI/HONOR; STF-L09; HWSTF; hi3660", + "27/8.1.0; 480dpi; 2880x5884; HUAWEI/HONOR; COL-L29; HWCOL; kirin970", + "26/8.0.0; 480dpi; 2880x5884; HUAWEI/HONOR; LLD-L31; HWLLD-H; hi6250", + "26/8.0.0; 480dpi; 2880x5884; HUAWEI; ANE-LX1; HWANE; hi6250", + "26/8.0.0; 480dpi; 2880x5884; HUAWEI; FIG-LX1; HWFIG-H; hi6250", + "27/8.1.0; 480dpi; 2880x5884; HUAWEI/HONOR; COL-L29; HWCOL; kirin970", + "26/8.0.0; 480dpi; 2880x5884; HUAWEI/HONOR; BND-L21; HWBND-H; hi6250", + "23/6.0.1; 420dpi; 2880x5884; LeMobile/LeEco; Le X527; le_s2_ww; qcom", // https://github.com/mimmi20/BrowserDetector/tree/master + "28/9; 560dpi; 2880x5884; samsung; SM-N960F; crownlte; samsungexynos9810", // mgp25 + "23/6.0.1; 640dpi; 2880x5884; LGE/lge; RS988; h1; h1", + "24/7.0; 640dpi; 2880x5884; HUAWEI; LON-L29; HWLON; hi3660", + "23/6.0.1; 640dpi; 2880x5884; ZTE; ZTE A2017U; ailsa_ii; qcom", + "23/6.0.1; 640dpi; 2880x5884; samsung; SM-G935F; hero2lte; samsungexynos8890", + "23/6.0.1; 640dpi; 2880x5884; samsung; SM-G930F; herolte; samsungexynos8890" +) - @NonNull - public static String generateAppUA(final int code, final String lang) { - return "Instagram " + igVersion + " Android (" + devices[code] + "; " + lang + "; " + igVersionCode + ")"; - } +fun generateBrowserUA(code: Int): String { + return browsers[code] } + +fun generateAppUA(code: Int, lang: String): String { + return "Instagram " + igVersion + " Android (" + devices[code] + "; " + lang + "; " + igVersionCode + ")" +} \ No newline at end of file diff --git a/app/src/main/java/awais/instagrabber/utils/ViewUtils.kt b/app/src/main/java/awais/instagrabber/utils/ViewUtils.kt index c2c91e61..d479cf94 100644 --- a/app/src/main/java/awais/instagrabber/utils/ViewUtils.kt +++ b/app/src/main/java/awais/instagrabber/utils/ViewUtils.kt @@ -1,121 +1,117 @@ -package awais.instagrabber.utils; - -import android.annotation.SuppressLint; -import android.content.Context; -import android.graphics.drawable.Drawable; -import android.graphics.drawable.GradientDrawable; -import android.graphics.drawable.ShapeDrawable; -import android.graphics.drawable.shapes.RoundRectShape; -import android.os.Build; -import android.view.View; -import android.view.ViewGroup; -import android.widget.FrameLayout; -import android.widget.TextView; - -import androidx.annotation.ColorInt; -import androidx.annotation.NonNull; -import androidx.annotation.Nullable; -import androidx.core.content.res.ResourcesCompat; -import androidx.core.util.Pair; -import androidx.dynamicanimation.animation.FloatPropertyCompat; -import androidx.dynamicanimation.animation.SpringAnimation; - -import org.jetbrains.annotations.NotNull; - -import kotlin.jvm.internal.Intrinsics; - -public final class ViewUtils { - - public static final int MATCH_PARENT = -1; - public static final int WRAP_CONTENT = -2; - - public static Drawable createRoundRectDrawableWithIcon(final Context context, int rad, int iconRes) { - ShapeDrawable defaultDrawable = new ShapeDrawable(new RoundRectShape(new float[]{rad, rad, rad, rad, rad, rad, rad, rad}, null, null)); - defaultDrawable.getPaint().setColor(0xffffffff); - final Drawable d = ResourcesCompat.getDrawable(context.getResources(), iconRes, null); - if (d == null) return null; - Drawable drawable = d.mutate(); - return new CombinedDrawable(defaultDrawable, drawable); - } +@file:JvmName("ViewUtils") + +package awais.instagrabber.utils + +import android.annotation.SuppressLint +import android.content.Context +import android.graphics.drawable.Drawable +import android.graphics.drawable.GradientDrawable +import android.graphics.drawable.ShapeDrawable +import android.graphics.drawable.shapes.RoundRectShape +import android.os.Build +import android.view.View +import android.view.ViewGroup +import android.widget.FrameLayout +import android.widget.TextView +import androidx.annotation.ColorInt +import androidx.core.content.res.ResourcesCompat +import androidx.core.util.Pair +import androidx.dynamicanimation.animation.FloatPropertyCompat +import androidx.dynamicanimation.animation.SpringAnimation +import kotlin.jvm.internal.Intrinsics + +fun createRoundRectDrawableWithIcon(context: Context, rad: Int, iconRes: Int): Drawable? { + val defaultDrawable = ShapeDrawable(RoundRectShape(FloatArray(8) { rad.toFloat() }, null, null)) + defaultDrawable.paint.color = -0x1 + val d = ResourcesCompat.getDrawable(context.resources, iconRes, null) ?: return null + val drawable = d.mutate() + return CombinedDrawable(defaultDrawable, drawable) +} - public static Drawable createRoundRectDrawable(int rad, int defaultColor) { - ShapeDrawable defaultDrawable = new ShapeDrawable(new RoundRectShape(new float[]{rad, rad, rad, rad, rad, rad, rad, rad}, null, null)); - defaultDrawable.getPaint().setColor(defaultColor); - return defaultDrawable; - } +fun createRoundRectDrawable(rad: Int, defaultColor: Int): Drawable { + val defaultDrawable = ShapeDrawable(RoundRectShape(FloatArray(8) { rad.toFloat() }, null, null)) + defaultDrawable.paint.color = defaultColor + return defaultDrawable +} - public static FrameLayout.LayoutParams createFrame(int width, - float height, - int gravity, - float leftMargin, - float topMargin, - float rightMargin, - float bottomMargin) { - FrameLayout.LayoutParams layoutParams = new FrameLayout.LayoutParams(getSize(width), getSize(height), gravity); - layoutParams.setMargins(Utils.convertDpToPx(leftMargin), Utils.convertDpToPx(topMargin), Utils.convertDpToPx(rightMargin), - Utils.convertDpToPx(bottomMargin)); - return layoutParams; - } +fun createFrame( + width: Int, + height: Float, + gravity: Int, + leftMargin: Float, + topMargin: Float, + rightMargin: Float, + bottomMargin: Float +): FrameLayout.LayoutParams { + val layoutParams = FrameLayout.LayoutParams(getSize(width.toFloat()), getSize(height), gravity) + layoutParams.setMargins( + Utils.convertDpToPx(leftMargin), Utils.convertDpToPx(topMargin), Utils.convertDpToPx(rightMargin), + Utils.convertDpToPx(bottomMargin) + ) + return layoutParams +} - public static GradientDrawable createGradientDrawable(final GradientDrawable.Orientation orientation, - @ColorInt final int[] colors) { - final GradientDrawable drawable = new GradientDrawable(orientation, colors); - drawable.setShape(GradientDrawable.RECTANGLE); - return drawable; - } +fun createGradientDrawable( + orientation: GradientDrawable.Orientation?, + @ColorInt colors: IntArray? +): GradientDrawable { + val drawable = GradientDrawable(orientation, colors) + drawable.shape = GradientDrawable.RECTANGLE + return drawable +} - private static int getSize(float size) { - return (int) (size < 0 ? size : Utils.convertDpToPx(size)); - } +private fun getSize(size: Float): Int { + return if (size < 0) size.toInt() else Utils.convertDpToPx(size) +} - public static Pair measure(@NonNull final View view, @NonNull final View parent) { - view.measure( - View.MeasureSpec.makeMeasureSpec(parent.getWidth(), View.MeasureSpec.UNSPECIFIED), - View.MeasureSpec.makeMeasureSpec(parent.getHeight(), View.MeasureSpec.UNSPECIFIED) - ); - return new Pair<>(view.getMeasuredHeight(), view.getMeasuredWidth()); - } +fun measure(view: View, parent: View): Pair { + view.measure( + View.MeasureSpec.makeMeasureSpec(parent.width, View.MeasureSpec.UNSPECIFIED), + View.MeasureSpec.makeMeasureSpec(parent.height, View.MeasureSpec.UNSPECIFIED) + ) + return Pair(view.measuredHeight, view.measuredWidth) +} - public static float getTextViewValueWidth(final TextView textView, final String text) { - return textView.getPaint().measureText(text); - } +fun getTextViewValueWidth(textView: TextView, text: String?): Float { + return textView.paint.measureText(text) +} - /** - * Creates [SpringAnimation] for object. - * If finalPosition is not [Float.NaN] then create [SpringAnimation] with - * [SpringForce.mFinalPosition]. - * - * @param object Object - * @param property object's property to be animated. - * @param finalPosition [SpringForce.mFinalPosition] Final position of spring. - * @return [SpringAnimation] - */ - @NonNull - public static SpringAnimation springAnimationOf(final Object object, - final FloatPropertyCompat property, - @Nullable final Float finalPosition) { - return finalPosition == null ? new SpringAnimation(object, property) : new SpringAnimation(object, property, finalPosition); - } +/** + * Creates [SpringAnimation] for object. + * If finalPosition is not [Float.NaN] then create [SpringAnimation] with + * [SpringForce.mFinalPosition]. + * + * @param object Object + * @param property object's property to be animated. + * @param finalPosition [SpringForce.mFinalPosition] Final position of spring. + * @return [SpringAnimation] + */ +fun springAnimationOf( + `object`: Any?, + property: FloatPropertyCompat?, + finalPosition: Float? +): SpringAnimation { + return finalPosition?.let { SpringAnimation(`object`, property, it) } ?: SpringAnimation(`object`, property) +} - public static void suppressLayoutCompat(@NotNull ViewGroup $this$suppressLayoutCompat, boolean suppress) { - Intrinsics.checkNotNullParameter($this$suppressLayoutCompat, "$this$suppressLayoutCompat"); - if (Build.VERSION.SDK_INT >= 29) { - $this$suppressLayoutCompat.suppressLayout(suppress); - } else { - hiddenSuppressLayout($this$suppressLayoutCompat, suppress); - } +fun suppressLayoutCompat(`$this$suppressLayoutCompat`: ViewGroup, suppress: Boolean) { + Intrinsics.checkNotNullParameter(`$this$suppressLayoutCompat`, "\$this\$suppressLayoutCompat") + if (Build.VERSION.SDK_INT >= 29) { + `$this$suppressLayoutCompat`.suppressLayout(suppress) + } else { + hiddenSuppressLayout(`$this$suppressLayoutCompat`, suppress) } +} - private static boolean tryHiddenSuppressLayout = true; +private var tryHiddenSuppressLayout = true - @SuppressLint({"NewApi"}) - private static void hiddenSuppressLayout(ViewGroup group, boolean suppress) { - if (tryHiddenSuppressLayout) { - try { - group.suppressLayout(suppress); - } catch (NoSuchMethodError var3) { - tryHiddenSuppressLayout = false; - } +@SuppressLint("NewApi") +private fun hiddenSuppressLayout(group: ViewGroup, suppress: Boolean) { + if (tryHiddenSuppressLayout) { + try { + group.suppressLayout(suppress) + } catch (var3: NoSuchMethodError) { + tryHiddenSuppressLayout = false } } -} +} \ No newline at end of file diff --git a/app/src/main/java/awais/instagrabber/utils/extensions/AnyExtensions.kt b/app/src/main/java/awais/instagrabber/utils/extensions/AnyExtensions.kt new file mode 100644 index 00000000..cd902ab1 --- /dev/null +++ b/app/src/main/java/awais/instagrabber/utils/extensions/AnyExtensions.kt @@ -0,0 +1,12 @@ +package awais.instagrabber.utils.extensions + +val Any.TAG: String + get() { + return if (!javaClass.isAnonymousClass) { + val name = javaClass.simpleName + if (name.length <= 23) name else name.substring(0, 23) // first 23 chars + } else { + val name = javaClass.name + if (name.length <= 23) name else name.substring(name.length - 23, name.length) // last 23 chars + } + } \ No newline at end of file diff --git a/app/src/main/java/awais/instagrabber/viewmodels/UserSearchViewModel.java b/app/src/main/java/awais/instagrabber/viewmodels/UserSearchViewModel.java index 1e77c960..dc8f2c6f 100644 --- a/app/src/main/java/awais/instagrabber/viewmodels/UserSearchViewModel.java +++ b/app/src/main/java/awais/instagrabber/viewmodels/UserSearchViewModel.java @@ -73,7 +73,7 @@ public class UserSearchViewModel extends ViewModel { } userService = UserService.getInstance(); directMessagesService = DirectMessagesService.getInstance(csrfToken, viewerId, deviceUuid); - rankedRecipientsCache = RankedRecipientsCache.getInstance(); + rankedRecipientsCache = RankedRecipientsCache.INSTANCE; if ((rankedRecipientsCache.isFailed() || rankedRecipientsCache.isExpired()) && !rankedRecipientsCache.isUpdateInitiated()) { updateRankedRecipientCache(); } @@ -113,7 +113,7 @@ public class UserSearchViewModel extends ViewModel { continueSearchIfRequired(); return; } - rankedRecipientsCache.setRankedRecipientsResponse(response.body()); + rankedRecipientsCache.setResponse(response.body()); rankedRecipientsCache.setUpdateInitiated(false); continueSearchIfRequired(); }