1
0
mirror of https://github.com/KokaKiwi/BarInsta synced 2024-11-15 19:27:31 +00:00

Convert some more classes to kotlin

This commit is contained in:
Ammar Githam 2021-05-22 20:10:53 +09:00
parent 746925e54d
commit 17fb608c34
19 changed files with 659 additions and 990 deletions

View File

@ -27,9 +27,6 @@ import static awais.instagrabber.utils.Utils.clipboardManager;
import static awais.instagrabber.utils.Utils.datetimeParser; import static awais.instagrabber.utils.Utils.datetimeParser;
import static awais.instagrabber.utils.Utils.settingsHelper; import static awais.instagrabber.utils.Utils.settingsHelper;
//import awaisomereport.LogCollector;
//import static awais.instagrabber.utils.Utils.logCollector;
public final class InstaGrabberApplication extends Application { public final class InstaGrabberApplication extends Application {
private static final String TAG = "InstaGrabberApplication"; private static final String TAG = "InstaGrabberApplication";

View File

@ -153,7 +153,7 @@ public class FormattedNumberTextView extends AppCompatTextView {
return; return;
} }
if (showAbbreviation) { if (showAbbreviation) {
setText(NumberUtils.abbreviate(number)); setText(NumberUtils.abbreviate(number, null));
return; return;
} }
setText(String.valueOf(number)); setText(String.valueOf(number));

View File

@ -16,6 +16,8 @@ import awais.instagrabber.utils.AppExecutors;
import awais.instagrabber.utils.Utils; import awais.instagrabber.utils.Utils;
import awais.instagrabber.utils.ViewUtils; import awais.instagrabber.utils.ViewUtils;
import static android.view.ViewGroup.LayoutParams.WRAP_CONTENT;
public class Tooltip extends AppCompatTextView { public class Tooltip extends AppCompatTextView {
private View anchor; private View anchor;
@ -40,8 +42,7 @@ public class Tooltip extends AppCompatTextView {
setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14); setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14);
setPadding(Utils.convertDpToPx(8), Utils.convertDpToPx(7), Utils.convertDpToPx(8), Utils.convertDpToPx(7)); setPadding(Utils.convertDpToPx(8), Utils.convertDpToPx(7), Utils.convertDpToPx(8), Utils.convertDpToPx(7));
setGravity(Gravity.CENTER_VERTICAL); setGravity(Gravity.CENTER_VERTICAL);
parentView.addView(this, ViewUtils.createFrame( parentView.addView(this, ViewUtils.createFrame(WRAP_CONTENT, WRAP_CONTENT, Gravity.START | Gravity.TOP, 5, 0, 5, 3));
ViewUtils.WRAP_CONTENT, ViewUtils.WRAP_CONTENT, Gravity.START | Gravity.TOP, 5, 0, 5, 3));
setVisibility(GONE); setVisibility(GONE);
} }

View File

@ -1,185 +1,157 @@
package awais.instagrabber.utils;/* /*
* This is the source code of Telegram for Android v. 5.x.x. * This is the source code of Telegram for Android v. 5.x.x.
* It is licensed under GNU GPL v. 2 or later. * It is licensed under GNU GPL v. 2 or later.
* You should have received a copy of the license in this archive (see LICENSE). * You should have received a copy of the license in this archive (see LICENSE).
* * <p>
* Copyright Nikolai Kudashov, 2013-2018. * Copyright Nikolai Kudashov, 2013-2018.
*/ */
package awais.instagrabber.utils
import android.graphics.Canvas; import android.graphics.Canvas
import android.graphics.ColorFilter; import android.graphics.ColorFilter
import android.graphics.drawable.Drawable; import android.graphics.PixelFormat
import android.graphics.drawable.Drawable
import androidx.annotation.NonNull; 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
public class CombinedDrawable extends Drawable implements Drawable.Callback { constructor(backgroundDrawable: Drawable, iconDrawable: Drawable?, leftOffset: Int, topOffset: Int) {
background = backgroundDrawable
private final Drawable background; icon = iconDrawable
private final Drawable icon; left = leftOffset
private int left; top = topOffset
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;
if (iconDrawable != null) { if (iconDrawable != null) {
iconDrawable.setCallback(this); iconDrawable.callback = this
} }
} }
public CombinedDrawable(Drawable backgroundDrawable, Drawable iconDrawable) { constructor(backgroundDrawable: Drawable, iconDrawable: Drawable?) {
background = backgroundDrawable; background = backgroundDrawable
icon = iconDrawable; icon = iconDrawable
if (iconDrawable != null) { if (iconDrawable != null) {
iconDrawable.setCallback(this); iconDrawable.callback = this
} }
} }
public void setIconSize(int width, int height) { fun setIconSize(width: Int, height: Int) {
iconWidth = width; iconWidth = width
iconHeight = height; iconHeight = height
} }
public void setCustomSize(int width, int height) { fun setCustomSize(width: Int, height: Int) {
backWidth = width; backWidth = width
backHeight = height; backHeight = height
} }
public void setIconOffset(int x, int y) { fun setIconOffset(x: Int, y: Int) {
offsetX = x; offsetX = x
offsetY = y; offsetY = y
} }
public Drawable getIcon() { fun setFullsize(value: Boolean) {
return icon; fullSize = value
} }
public Drawable getBackground() { override fun setColorFilter(colorFilter: ColorFilter?) {
return background; icon?.colorFilter = colorFilter
} }
public void setFullsize(boolean value) { override fun isStateful(): Boolean {
fullSize = value; return icon?.isStateful ?: false
} }
@Override override fun setState(stateSet: IntArray): Boolean {
public void setColorFilter(ColorFilter colorFilter) { icon?.state = stateSet
icon.setColorFilter(colorFilter); return true
} }
@Override override fun getState(): IntArray {
public boolean isStateful() { return icon?.state ?: super.getState()
return icon.isStateful();
} }
@Override override fun onStateChange(state: IntArray): Boolean {
public boolean setState(@NonNull int[] stateSet) { return true
icon.setState(stateSet);
return true;
} }
@NonNull override fun jumpToCurrentState() {
@Override icon?.jumpToCurrentState()
public int[] getState() {
return icon.getState();
} }
@Override override fun getConstantState(): ConstantState? {
protected boolean onStateChange(int[] state) { return icon?.constantState
return true;
} }
@Override override fun draw(canvas: Canvas) {
public void jumpToCurrentState() { background.bounds = bounds
icon.jumpToCurrentState(); background.draw(canvas)
} if (icon == null) return
@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) { if (fullSize) {
android.graphics.Rect bounds = getBounds(); val bounds = bounds
if (left != 0) { if (left != 0) {
icon.setBounds(bounds.left + left, bounds.top + top, bounds.right - left, bounds.bottom - top); icon.setBounds(bounds.left + left, bounds.top + top, bounds.right - left, bounds.bottom - top)
} else { } else {
icon.setBounds(bounds); icon.bounds = bounds
} }
} else { } else {
int x; val x: Int
int y; val y: Int
if (iconWidth != 0) { if (iconWidth != 0) {
x = getBounds().centerX() - iconWidth / 2 + left + offsetX; x = bounds.centerX() - iconWidth / 2 + left + offsetX
y = getBounds().centerY() - iconHeight / 2 + top + offsetY; y = bounds.centerY() - iconHeight / 2 + top + offsetY
icon.setBounds(x, y, x + iconWidth, y + iconHeight); icon.setBounds(x, y, x + iconWidth, y + iconHeight)
} else { } else {
x = getBounds().centerX() - icon.getIntrinsicWidth() / 2 + left; x = bounds.centerX() - icon.intrinsicWidth / 2 + left
y = getBounds().centerY() - icon.getIntrinsicHeight() / 2 + top; y = bounds.centerY() - icon.intrinsicHeight / 2 + top
icon.setBounds(x, y, x + icon.getIntrinsicWidth(), y + icon.getIntrinsicHeight()); icon.setBounds(x, y, x + icon.intrinsicWidth, y + icon.intrinsicHeight)
} }
} }
icon.draw(canvas); icon.draw(canvas)
}
} }
@Override override fun setAlpha(alpha: Int) {
public void setAlpha(int alpha) { icon?.alpha = alpha
icon.setAlpha(alpha); background.alpha = alpha
background.setAlpha(alpha);
} }
@Override override fun getIntrinsicWidth(): Int {
public int getIntrinsicWidth() { return if (backWidth != 0) backWidth else background.intrinsicWidth
return backWidth != 0 ? backWidth : background.getIntrinsicWidth();
} }
@Override override fun getIntrinsicHeight(): Int {
public int getIntrinsicHeight() { return if (backHeight != 0) backHeight else background.intrinsicHeight
return backHeight != 0 ? backHeight : background.getIntrinsicHeight();
} }
@Override override fun getMinimumWidth(): Int {
public int getMinimumWidth() { return if (backWidth != 0) backWidth else background.minimumWidth
return backWidth != 0 ? backWidth : background.getMinimumWidth();
} }
@Override override fun getMinimumHeight(): Int {
public int getMinimumHeight() { return if (backHeight != 0) backHeight else background.minimumHeight
return backHeight != 0 ? backHeight : background.getMinimumHeight();
} }
@Override override fun getOpacity(): Int {
public int getOpacity() { return icon?.opacity ?: PixelFormat.UNKNOWN
return icon.getOpacity();
} }
@Override override fun invalidateDrawable(who: Drawable) {
public void invalidateDrawable(@NonNull Drawable who) { invalidateSelf()
invalidateSelf();
} }
@Override override fun scheduleDrawable(who: Drawable, what: Runnable, `when`: Long) {
public void scheduleDrawable(@NonNull Drawable who, @NonNull Runnable what, long when) { scheduleSelf(what, `when`)
scheduleSelf(what, when);
} }
@Override override fun unscheduleDrawable(who: Drawable, what: Runnable) {
public void unscheduleDrawable(@NonNull Drawable who, @NonNull Runnable what) { unscheduleSelf(what)
unscheduleSelf(what);
} }
} }

View File

@ -1,107 +1,90 @@
package awais.instagrabber.utils; @file:JvmName("CookieUtils")
import android.content.Context; package awais.instagrabber.utils
import android.util.Log;
import android.webkit.CookieManager;
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; private const val TAG = "CookieUtils"
import java.net.CookieStore; private val COOKIE_MANAGER = CookieManager.getInstance()
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;
import awais.instagrabber.BuildConfig; @JvmField
import awais.instagrabber.db.datasources.AccountDataSource; val NET_COOKIE_MANAGER = java.net.CookieManager(null, CookiePolicy.ACCEPT_ALL)
import awais.instagrabber.db.repositories.AccountRepository;
import awais.instagrabber.db.repositories.RepositoryCallback;
//import awaisomereport.LogCollector;
public final class CookieUtils { fun setupCookies(cookieRaw: String) {
private static final String TAG = CookieUtils.class.getSimpleName(); val cookieStore = NET_COOKIE_MANAGER.cookieStore
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)) { if (cookieStore == null || TextUtils.isEmpty(cookieRaw)) {
return; return
} }
if (cookieRaw.equals("LOGOUT")) { if (cookieRaw == "LOGOUT") {
cookieStore.removeAll(); cookieStore.removeAll()
return; return
} }
try { try {
final URI uri1 = new URI("https://instagram.com"); val uri1 = URI("https://instagram.com")
final URI uri2 = new URI("https://instagram.com/"); val uri2 = URI("https://instagram.com/")
final URI uri3 = new URI("https://i.instagram.com/"); val uri3 = URI("https://i.instagram.com/")
for (final String cookie : cookieRaw.split("; ")) { for (cookie in cookieRaw.split("; ")) {
final String[] strings = cookie.split("=", 2); val strings = cookie.split("=", limit = 2)
final HttpCookie httpCookie = new HttpCookie(strings[0].trim(), strings[1].trim()); val httpCookie = HttpCookie(strings[0].trim { it <= ' ' }, strings[1].trim { it <= ' ' })
httpCookie.setDomain(".instagram.com"); httpCookie.domain = ".instagram.com"
httpCookie.setPath("/"); httpCookie.path = "/"
httpCookie.setVersion(0); httpCookie.version = 0
cookieStore.add(uri1, httpCookie); cookieStore.add(uri1, httpCookie)
cookieStore.add(uri2, httpCookie); cookieStore.add(uri2, httpCookie)
cookieStore.add(uri3, httpCookie); cookieStore.add(uri3, httpCookie)
} }
} catch (final URISyntaxException e) { } catch (e: URISyntaxException) {
// if (Utils.logCollector != null) Log.e(TAG, "", e)
// Utils.logCollector.appendException(e, LogCollector.LogFile.UTILS, "setupCookies");
if (BuildConfig.DEBUG) Log.e(TAG, "", e);
} }
} }
public static void removeAllAccounts(final Context context, final RepositoryCallback<Void> callback) { fun removeAllAccounts(context: Context?, callback: RepositoryCallback<Void?>?) {
final CookieStore cookieStore = NET_COOKIE_MANAGER.getCookieStore(); val cookieStore = NET_COOKIE_MANAGER.cookieStore ?: return
if (cookieStore == null) return; cookieStore.removeAll()
cookieStore.removeAll();
try { try {
AccountRepository.getInstance(AccountDataSource.getInstance(context)) AccountRepository.getInstance(AccountDataSource.getInstance(context!!))
.deleteAllAccounts(callback); .deleteAllAccounts(callback)
} catch (Exception e) { } catch (e: Exception) {
Log.e(TAG, "setupCookies", e); Log.e(TAG, "setupCookies", e)
} }
} }
public static long getUserIdFromCookie(final String cookies) { fun getUserIdFromCookie(cookies: String?): Long {
final String dsUserId = getCookieValue(cookies, "ds_user_id"); val dsUserId = getCookieValue(cookies, "ds_user_id") ?: return 0
if (dsUserId == null) {
return 0;
}
try { try {
return Long.parseLong(dsUserId); return dsUserId.toLong()
} catch (NumberFormatException e) { } catch (e: NumberFormatException) {
Log.e(TAG, "getUserIdFromCookie: ", e); Log.e(TAG, "getUserIdFromCookie: ", e)
} }
return 0; return 0
} }
@Nullable fun getCsrfTokenFromCookie(cookies: String?): String? {
public static String getCsrfTokenFromCookie(final String cookies) { return getCookieValue(cookies, "csrftoken")
return getCookieValue(cookies, "csrftoken");
} }
@Nullable private fun getCookieValue(cookies: String?, name: String): String? {
private static String getCookieValue(final String cookies, final String name) { if (cookies == null) return null
if (cookies == null) return null; val pattern = Pattern.compile("$name=(.+?);")
final Pattern pattern = Pattern.compile(name + "=(.+?);"); val matcher = pattern.matcher(cookies)
final Matcher matcher = pattern.matcher(cookies); return if (matcher.find()) {
if (matcher.find()) { matcher.group(1)
return matcher.group(1); } else null
}
return null;
} }
@Nullable fun getCookie(webViewUrl: String?): String? {
public static String getCookie(@Nullable final String webViewUrl) { val domains: List<String> = listOfNotNull(
final List<String> domains = new ArrayList<>(Arrays.asList( if (!TextUtils.isEmpty(webViewUrl)) webViewUrl else null,
"https://instagram.com", "https://instagram.com",
"https://instagram.com/", "https://instagram.com/",
"http://instagram.com", "http://instagram.com",
@ -109,31 +92,23 @@ public final class CookieUtils {
"https://www.instagram.com", "https://www.instagram.com",
"https://www.instagram.com/", "https://www.instagram.com/",
"http://www.instagram.com", "http://www.instagram.com",
"http://www.instagram.com/" "http://www.instagram.com/",
)); )
if (!TextUtils.isEmpty(webViewUrl)) { return getLongestCookie(domains)
domains.add(0, webViewUrl);
} }
return getLongestCookie(domains); private fun getLongestCookie(domains: List<String>): String? {
} var longestLength = 0
var longestCookie: String? = null
@Nullable for (domain in domains) {
private static String getLongestCookie(final List<String> domains) { val cookie = COOKIE_MANAGER.getCookie(domain)
int longestLength = 0;
String longestCookie = null;
for (final String domain : domains) {
final String cookie = COOKIE_MANAGER.getCookie(domain);
if (cookie != null) { if (cookie != null) {
final int cookieLength = cookie.length(); val cookieLength = cookie.length
if (cookieLength > longestLength) { if (cookieLength > longestLength) {
longestCookie = cookie; longestCookie = cookie
longestLength = cookieLength; longestLength = cookieLength
} }
} }
} }
return longestCookie
return longestCookie;
}
} }

View File

@ -8,29 +8,6 @@ public class CubicInterpolation {
private final int tangentFactor; private final int tangentFactor;
private final int length; 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) { public CubicInterpolation(final float[] array, final int cubicTension) {
this.array = Arrays.copyOf(array, array.length); this.array = Arrays.copyOf(array, array.length);
this.length = 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]; 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) { private float getClippedInput(int i) {
if (i >= 0 && i < length) { if (i >= 0 && i < length) {
return array[i]; return array[i];

View File

@ -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));
}
}

View File

@ -1,67 +1,29 @@
package awais.instagrabber.utils; package awais.instagrabber.utils
import androidx.annotation.NonNull; import java.util.regex.Pattern
import androidx.annotation.Nullable;
import com.google.common.collect.ImmutableMap; object DeepLinkParser {
private val TYPE_PATTERN_MAP: Map<DeepLink.Type, DeepLinkPattern> = mapOf(
DeepLink.Type.USER to DeepLinkPattern("instagram://user?username="),
)
import java.util.Map; @JvmStatic
import java.util.regex.Pattern; fun parse(text: String): DeepLink? {
for ((key, value) in TYPE_PATTERN_MAP) {
public final class DeepLinkParser { if (text.startsWith(value.patternText)) {
private static final Map<DeepLink.Type, DeepLinkPattern> TYPE_PATTERN_MAP = ImmutableMap return DeepLink(key, value.pattern.matcher(text).replaceAll(""))
.<DeepLink.Type, DeepLinkPattern>builder()
.put(DeepLink.Type.USER, new DeepLinkPattern("instagram://user?username="))
.build();
@Nullable
public static DeepLink parse(@NonNull final String text) {
for (final Map.Entry<DeepLink.Type, DeepLinkPattern> 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);
} }
} }
return null; return null
} }
public static class DeepLinkPattern { data class DeepLinkPattern(val patternText: String) {
private final String patternText; val pattern: Pattern = Pattern.compile(patternText, Pattern.LITERAL)
private final Pattern pattern;
public DeepLinkPattern(final String patternText) {
this.patternText = patternText;
pattern = Pattern.compile(patternText, Pattern.LITERAL);
} }
public String getPatternText() { data class DeepLink(val type: Type, val value: String) {
return patternText; enum class Type {
} USER
public Pattern getPattern() {
return pattern;
}
}
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,
} }
} }
} }

View File

@ -1,91 +1,83 @@
package awais.instagrabber.utils; package awais.instagrabber.utils
import android.content.Context; import android.content.Context
import android.content.res.Configuration; import android.content.res.Configuration
import android.content.res.Resources; import android.view.ContextThemeWrapper
import android.view.ContextThemeWrapper; import awais.instagrabber.fragments.settings.PreferenceKeys
import java.util.*
import androidx.annotation.Nullable;
import java.util.Locale;
import awais.instagrabber.fragments.settings.PreferenceKeys;
// taken from my app TESV Console Codes // taken from my app TESV Console Codes
public final class LocaleUtils { object LocaleUtils {
private static Locale defaultLocale, currentLocale; private var defaultLocale: Locale? = null
public static void setLocale(Context baseContext) { @JvmStatic
if (defaultLocale == null) defaultLocale = Locale.getDefault(); var currentLocale: Locale? = null
private set
if (baseContext instanceof ContextThemeWrapper) @JvmStatic
baseContext = ((ContextThemeWrapper) baseContext).getBaseContext(); fun setLocale(baseContext: Context) {
var baseContext1 = baseContext
if (Utils.settingsHelper == null) if (defaultLocale == null) defaultLocale = Locale.getDefault()
Utils.settingsHelper = new SettingsHelper(baseContext); if (baseContext1 is ContextThemeWrapper) baseContext1 = baseContext1.baseContext
if (Utils.settingsHelper == null) Utils.settingsHelper = SettingsHelper(baseContext1)
final String appLanguageSettings = Utils.settingsHelper.getString(PreferenceKeys.APP_LANGUAGE); val appLanguageSettings = Utils.settingsHelper.getString(PreferenceKeys.APP_LANGUAGE)
final String lang = LocaleUtils.getCorrespondingLanguageCode(appLanguageSettings); val lang = getCorrespondingLanguageCode(appLanguageSettings)
currentLocale = when {
currentLocale = TextUtils.isEmpty(lang) ? defaultLocale : TextUtils.isEmpty(lang) -> defaultLocale
(lang.contains("_") ? new Locale(lang.split("_")[0], lang.split("_")[1]) : new Locale(lang)); lang!!.contains("_") -> {
Locale.setDefault(currentLocale); val split = lang.split("_")
Locale(split[0], split[1])
final Resources res = baseContext.getResources();
final Configuration config = res.getConfiguration();
config.locale = currentLocale;
config.setLocale(currentLocale);
config.setLayoutDirection(currentLocale);
res.updateConfiguration(config, res.getDisplayMetrics());
} }
else -> Locale(lang)
public static Locale getCurrentLocale() {
return currentLocale;
} }
currentLocale?.let {
public static void updateConfig(final ContextThemeWrapper wrapper) { Locale.setDefault(it)
if (currentLocale != null) { val res = baseContext1.resources
final Configuration configuration = new Configuration(); val config = res.configuration
configuration.locale = currentLocale; // config.locale = currentLocale
configuration.setLocale(currentLocale); config.setLocale(it)
wrapper.applyOverrideConfiguration(configuration); config.setLayoutDirection(it)
res.updateConfiguration(config, res.displayMetrics)
} }
} }
@Nullable @JvmStatic
public static String getCorrespondingLanguageCode(final String appLanguageSettings) { fun updateConfig(wrapper: ContextThemeWrapper) {
if (TextUtils.isEmpty(appLanguageSettings)) return null; if (currentLocale == null) return
val configuration = Configuration()
final int appLanguageIndex = Integer.parseInt(appLanguageSettings); // configuration.locale = currentLocale
switch (appLanguageIndex) { configuration.setLocale(currentLocale)
case 1: return "en"; wrapper.applyOverrideConfiguration(configuration)
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";
} }
return null; 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
} }
} }

View File

@ -7,6 +7,7 @@ import awais.instagrabber.models.UploadVideoOptions
import awais.instagrabber.models.enums.MediaItemType import awais.instagrabber.models.enums.MediaItemType
import org.json.JSONObject import org.json.JSONObject
import java.util.* import java.util.*
import kotlin.random.Random
private const val LOWER = 1000000000L private const val LOWER = 1000000000L
@ -109,7 +110,7 @@ fun generateUploadId(): String {
} }
fun generateName(uploadId: String): String { fun generateName(uploadId: String): String {
val random = NumberUtils.random(LOWER, UPPER + 1) val random = Random.nextLong(LOWER, UPPER + 1)
return "${uploadId}_0_$random" return "${uploadId}_0_$random"
} }

View File

@ -1,4 +1,4 @@
package awais.instagrabber.utils; package awais.instagrabber.utils
/* /*
* Copyright (C) 2009 The Android Open Source Project * Copyright (C) 2009 The Android Open Source Project
@ -15,67 +15,19 @@ package awais.instagrabber.utils;
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * 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 * 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 * implementation of equals(), returning true if equals() is true on each of the contained
* objects. * objects.
*/ */
public class NullSafePair<F, S> {
public final @NonNull
F first;
public final @NonNull
S second;
/** /**
* Constructor for a Pair. * Constructor for a Pair.
* *
* @param first the first object in the Pair * @param first the first object in the Pair
* @param second the second object in the pair * @param second the second object in the pair
*/ */
public NullSafePair(@NonNull F first, @NonNull S second) { data class NullSafePair<F, S>(@JvmField val first: F, @JvmField val second: S) {
this.first = first; companion object {
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;
}
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. * Convenience method for creating an appropriately typed pair.
* *
@ -83,9 +35,8 @@ public class NullSafePair<F, S> {
* @param b the second 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 * @return a Pair that is templatized with the types of a and b
*/ */
@NonNull fun <A, B> create(a: A, b: B): NullSafePair<A, B> {
public static <A, B> androidx.core.util.Pair<A, B> create(@Nullable A a, @Nullable B b) { return NullSafePair(a, b)
return new androidx.core.util.Pair<A, B>(a, b); }
} }
} }

View File

@ -1,149 +1,87 @@
package awais.instagrabber.utils; @file:JvmName("NumberUtils")
import androidx.annotation.NonNull; package awais.instagrabber.utils
import androidx.annotation.Nullable;
import java.util.Locale; import java.util.*
import java.util.Random; import kotlin.math.ln
import kotlin.math.pow
public final class NumberUtils { fun getResultingHeight(requiredWidth: Int, height: Int, width: Int): Int {
// @NonNull return requiredWidth * height / width
// 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) { fun getResultingWidth(requiredHeight: Int, height: Int, width: Int): Int {
return requiredHeight * width / height; return requiredHeight * width / height
} }
public static long random(long origin, long bound) { // TODO Replace all usages with kotlin Random.nextLong() once converted to kotlin
final Random random = new Random(); fun random(origin: Long, bound: Long): Long {
long r = random.nextLong(); val random = Random()
long n = bound - origin, m = n - 1; var r = random.nextLong()
if ((n & m) == 0L) // power of two val n = bound - origin
r = (r & m) + origin; val m = n - 1
else if (n > 0L) { // reject over-represented candidates when {
//noinspection StatementWithEmptyBody n and m == 0L -> r = (r and m) + origin // power of two
for (long u = r >>> 1; // ensure non-negative n > 0L -> {
u + m - (r = u % n) < 0L; // rejection check // reject over-represented candidates
u = random.nextLong() >>> 1) // retry var u = r ushr 1 // ensure non-negative
; while (u + m - u % n.also { r = it } < 0L) { // rejection check
r += origin; // retry
} else { // range not representable as long u = random.nextLong() ushr 1
while (r < origin || r >= bound)
r = random.nextLong();
} }
return r; r += origin
}
else -> {
// range not representable as long
while (r < origin || r >= bound) r = random.nextLong()
}
}
return r
} }
@NonNull fun calculateWidthHeight(height: Int, width: Int, maxHeight: Int, maxWidth: Int): NullSafePair<Int, Int> {
public static NullSafePair<Integer, Integer> calculateWidthHeight(final int height, final int width, final int maxHeight, final int maxWidth) {
if (width > maxWidth) { if (width > maxWidth) {
int tempHeight = getResultingHeight(maxWidth, height, width); var tempHeight = getResultingHeight(maxWidth, height, width)
int tempWidth = maxWidth; var tempWidth = maxWidth
if (tempHeight > maxHeight) { if (tempHeight > maxHeight) {
tempWidth = getResultingWidth(maxHeight, tempHeight, tempWidth); tempWidth = getResultingWidth(maxHeight, tempHeight, tempWidth)
tempHeight = maxHeight; tempHeight = maxHeight
} }
return new NullSafePair<>(tempWidth, tempHeight); return NullSafePair(tempWidth, tempHeight)
} }
if ((height < maxHeight && width < maxWidth) || (height > maxHeight)) { if (height < maxHeight && width < maxWidth || height > maxHeight) {
int tempWidth = getResultingWidth(maxHeight, height, width); var tempWidth = getResultingWidth(maxHeight, height, width)
int tempHeight = maxHeight; var tempHeight = maxHeight
if (tempWidth > maxWidth) { if (tempWidth > maxWidth) {
tempHeight = getResultingHeight(maxWidth, tempHeight, tempWidth); tempHeight = getResultingHeight(maxWidth, tempHeight, tempWidth)
tempWidth = maxWidth; tempWidth = maxWidth
} }
return new NullSafePair<>(tempWidth, tempHeight); return NullSafePair(tempWidth, tempHeight)
} }
return new NullSafePair<>(width, height); return NullSafePair(width, height)
} }
public static float roundFloat2Decimals(final float value) { fun roundFloat2Decimals(value: Float): Float {
return ((int) ((value + (value >= 0 ? 1 : -1) * 0.005f) * 100)) / 100f; return ((value + (if (value >= 0) 1 else -1) * 0.005f) * 100).toInt() / 100f
} }
@NonNull fun abbreviate(number: Long, options: AbbreviateOptions? = null): String {
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 // adapted from https://stackoverflow.com/a/9769590/1436766
int threshold = 1000; var threshold = 1000
boolean addSpace = false; var addSpace = false
if (options != null) { if (options != null) {
threshold = options.getThreshold(); threshold = options.threshold
addSpace = options.addSpaceBeforePrefix(); addSpace = options.addSpaceBeforePrefix
} }
if (number < threshold) return "" + number; if (number < threshold) return "" + number
int exp = (int) (Math.log(number) / Math.log(threshold)); val exp = (ln(number.toDouble()) / ln(threshold.toDouble())).toInt()
return String.format(Locale.US, return String.format(
Locale.US,
"%.1f%s%c", "%.1f%s%c",
number / Math.pow(threshold, exp), number / threshold.toDouble().pow(exp.toDouble()),
addSpace ? " " : "", if (addSpace) " " else "",
"kMGTPE".charAt(exp - 1)); "kMGTPE"[exp - 1]
)
} }
public static final class AbbreviateOptions { data class AbbreviateOptions(val threshold: Int = 1000, val addSpaceBeforePrefix: Boolean = false)
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;
}
public int getThreshold() {
return threshold;
}
public boolean addSpaceBeforePrefix() {
return addSpaceBeforePrefix;
}
}
}

View File

@ -1,69 +1,27 @@
package awais.instagrabber.utils; package awais.instagrabber.utils
import java.time.LocalDateTime; import awais.instagrabber.repositories.responses.directmessages.RankedRecipient
import java.time.temporal.ChronoUnit; import awais.instagrabber.repositories.responses.directmessages.RankedRecipientsResponse
import java.util.Collections; import java.time.LocalDateTime
import java.util.List; import java.time.temporal.ChronoUnit
import awais.instagrabber.repositories.responses.directmessages.RankedRecipient; object RankedRecipientsCache {
import awais.instagrabber.repositories.responses.directmessages.RankedRecipientsResponse; private var lastUpdatedOn: LocalDateTime? = null
var isUpdateInitiated = false
var isFailed = false
val rankedRecipients: List<RankedRecipient>
get() = response?.rankedRecipients ?: emptyList()
public class RankedRecipientsCache { var response: RankedRecipientsResponse? = null
private static final Object LOCK = new Object(); set(value) {
field = value
private static RankedRecipientsCache instance; lastUpdatedOn = LocalDateTime.now()
public static RankedRecipientsCache getInstance() {
if (instance == null) {
synchronized (LOCK) {
if (instance == null) {
instance = new RankedRecipientsCache();
}
}
}
return instance;
} }
private LocalDateTime lastUpdatedOn; val isExpired: Boolean
private RankedRecipientsResponse response; get() {
private boolean updateInitiated = false; if (lastUpdatedOn == null || response == null) return true
private boolean failed = false; val expiresInSecs = response!!.expires
return LocalDateTime.now().isAfter(lastUpdatedOn!!.plus(expiresInSecs, ChronoUnit.SECONDS))
private RankedRecipientsCache() {}
public List<RankedRecipient> getRankedRecipients() {
if (response != null) {
return response.getRankedRecipients();
}
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;
}
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;
} }
} }

View File

@ -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<F, S> extends Pair<F, S> implements Serializable {
/** /**
* Constructor for a Pair. * Constructor for a Pair.
* *
* @param first the first object in the Pair * @param first the first object in the Pair
* @param second the second object in the pair * @param second the second object in the pair
*/ */
public SerializablePair(final F first, final S second) { data class SerializablePair<F, S>(@JvmField val first: F, @JvmField val second: S) : Pair<F, S>(first, second), Serializable
super(first, second);
}
}

View File

@ -1,38 +1,36 @@
package awais.instagrabber.utils; @file:JvmName("UpdateCheckCommon")
import android.content.Context; package awais.instagrabber.utils
import android.content.DialogInterface;
import androidx.annotation.NonNull; 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
import com.google.android.material.dialog.MaterialAlertDialogBuilder; fun shouldShowUpdateDialog(
force: Boolean,
import awais.instagrabber.BuildConfig; version: String
import awais.instagrabber.R; ): Boolean {
val skippedVersion = Utils.settingsHelper.getString(Constants.SKIPPED_VERSION)
import static awais.instagrabber.utils.Utils.settingsHelper; return force || !BuildConfig.DEBUG && skippedVersion != version
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));
} }
public static void showUpdateDialog(@NonNull final Context context, fun showUpdateDialog(
@NonNull final String version, context: Context,
@NonNull final DialogInterface.OnClickListener onDownloadClickListener) { version: String,
AppExecutors.INSTANCE.getMainThread().execute(() -> { onDownloadClickListener: DialogInterface.OnClickListener
new MaterialAlertDialogBuilder(context) ) {
.setTitle(context.getString(R.string.update_available, version)) mainThread.execute {
.setNeutralButton(R.string.skip_update, (dialog, which) -> { MaterialAlertDialogBuilder(context).apply {
settingsHelper.putString(Constants.SKIPPED_VERSION, version); setTitle(context.getString(R.string.update_available, version))
dialog.dismiss(); setNeutralButton(R.string.skip_update) { dialog: DialogInterface, which: Int ->
}) Utils.settingsHelper.putString(Constants.SKIPPED_VERSION, version)
.setPositiveButton(R.string.action_download, onDownloadClickListener) dialog.dismiss()
.setNegativeButton(R.string.cancel, null) }
.show(); setPositiveButton(R.string.action_download, onDownloadClickListener)
}); setNegativeButton(R.string.cancel, null)
}.show()
} }
} }

View File

@ -1,28 +1,30 @@
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). /* GraphQL user agents (which are just standard browser UA"s).
* Go to https://www.whatismybrowser.com/guides/the-latest-user-agent/ to update it * Go to https://www.whatismybrowser.com/guides/the-latest-user-agent/ to update it
* Windows first (Assume win64 not wow64): Chrome, Firefox, Edge * Windows first (Assume win64 not wow64): Chrome, Firefox, Edge
* Then macOS: Chrome, Firefox, Safari * Then macOS: Chrome, Firefox, Safari
*/ */
public static final String[] browsers = { @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) 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; 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 (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_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; 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" "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 // use APKpure, assume arm64-v8a
private static final String igVersion = "188.0.0.35.124"; private const val igVersion = "188.0.0.35.124"
private static final String igVersionCode = "292080186"; private const val igVersionCode = "292080186"
// you can pick *any* device as long as you LEAVE OUT the resolution for maximum download quality // 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 // 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", "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.1; 480dpi; 2880x5884; Xiaomi; Redmi Note 3; kenzo; qcom",
"23/6.0; 480dpi; 2880x5884; Xiaomi; Redmi Note 4; nikel; mt6797", "23/6.0; 480dpi; 2880x5884; Xiaomi; Redmi Note 4; nikel; mt6797",
@ -62,24 +64,19 @@ public class UserAgentUtils {
"26/8.0.0; 480dpi; 2880x5884; HUAWEI; FIG-LX1; HWFIG-H; 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", "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", "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", "23/6.0.1; 420dpi; 2880x5884; LeMobile/LeEco; Le X527; le_s2_ww; qcom", // https://github.com/mimmi20/BrowserDetector/tree/master
// https://github.com/mimmi20/BrowserDetector/tree/master "28/9; 560dpi; 2880x5884; samsung; SM-N960F; crownlte; samsungexynos9810", // mgp25
"28/9; 560dpi; 2880x5884; samsung; SM-N960F; crownlte; samsungexynos9810",
// mgp25
"23/6.0.1; 640dpi; 2880x5884; LGE/lge; RS988; h1; h1", "23/6.0.1; 640dpi; 2880x5884; LGE/lge; RS988; h1; h1",
"24/7.0; 640dpi; 2880x5884; HUAWEI; LON-L29; HWLON; hi3660", "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; 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-G935F; hero2lte; samsungexynos8890",
"23/6.0.1; 640dpi; 2880x5884; samsung; SM-G930F; herolte; samsungexynos8890" "23/6.0.1; 640dpi; 2880x5884; samsung; SM-G930F; herolte; samsungexynos8890"
}; )
@NonNull fun generateBrowserUA(code: Int): String {
public static String generateBrowserUA(final int code) { return browsers[code]
return browsers[code];
} }
@NonNull fun generateAppUA(code: Int, lang: String): String {
public static String generateAppUA(final int code, final String lang) { return "Instagram " + igVersion + " Android (" + devices[code] + "; " + lang + "; " + igVersionCode + ")"
return "Instagram " + igVersion + " Android (" + devices[code] + "; " + lang + "; " + igVersionCode + ")";
}
} }

View File

@ -1,83 +1,79 @@
package awais.instagrabber.utils; @file:JvmName("ViewUtils")
import android.annotation.SuppressLint; package awais.instagrabber.utils
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 android.annotation.SuppressLint
import androidx.annotation.NonNull; import android.content.Context
import androidx.annotation.Nullable; import android.graphics.drawable.Drawable
import androidx.core.content.res.ResourcesCompat; import android.graphics.drawable.GradientDrawable
import androidx.core.util.Pair; import android.graphics.drawable.ShapeDrawable
import androidx.dynamicanimation.animation.FloatPropertyCompat; import android.graphics.drawable.shapes.RoundRectShape
import androidx.dynamicanimation.animation.SpringAnimation; 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
import org.jetbrains.annotations.NotNull; fun createRoundRectDrawableWithIcon(context: Context, rad: Int, iconRes: Int): Drawable? {
val defaultDrawable = ShapeDrawable(RoundRectShape(FloatArray(8) { rad.toFloat() }, null, null))
import kotlin.jvm.internal.Intrinsics; defaultDrawable.paint.color = -0x1
val d = ResourcesCompat.getDrawable(context.resources, iconRes, null) ?: return null
public final class ViewUtils { val drawable = d.mutate()
return CombinedDrawable(defaultDrawable, drawable)
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);
} }
public static Drawable createRoundRectDrawable(int rad, int defaultColor) { fun createRoundRectDrawable(rad: Int, defaultColor: Int): Drawable {
ShapeDrawable defaultDrawable = new ShapeDrawable(new RoundRectShape(new float[]{rad, rad, rad, rad, rad, rad, rad, rad}, null, null)); val defaultDrawable = ShapeDrawable(RoundRectShape(FloatArray(8) { rad.toFloat() }, null, null))
defaultDrawable.getPaint().setColor(defaultColor); defaultDrawable.paint.color = defaultColor
return defaultDrawable; return defaultDrawable
} }
public static FrameLayout.LayoutParams createFrame(int width, fun createFrame(
float height, width: Int,
int gravity, height: Float,
float leftMargin, gravity: Int,
float topMargin, leftMargin: Float,
float rightMargin, topMargin: Float,
float bottomMargin) { rightMargin: Float,
FrameLayout.LayoutParams layoutParams = new FrameLayout.LayoutParams(getSize(width), getSize(height), gravity); bottomMargin: Float
layoutParams.setMargins(Utils.convertDpToPx(leftMargin), Utils.convertDpToPx(topMargin), Utils.convertDpToPx(rightMargin), ): FrameLayout.LayoutParams {
Utils.convertDpToPx(bottomMargin)); val layoutParams = FrameLayout.LayoutParams(getSize(width.toFloat()), getSize(height), gravity)
return layoutParams; layoutParams.setMargins(
Utils.convertDpToPx(leftMargin), Utils.convertDpToPx(topMargin), Utils.convertDpToPx(rightMargin),
Utils.convertDpToPx(bottomMargin)
)
return layoutParams
} }
public static GradientDrawable createGradientDrawable(final GradientDrawable.Orientation orientation, fun createGradientDrawable(
@ColorInt final int[] colors) { orientation: GradientDrawable.Orientation?,
final GradientDrawable drawable = new GradientDrawable(orientation, colors); @ColorInt colors: IntArray?
drawable.setShape(GradientDrawable.RECTANGLE); ): GradientDrawable {
return drawable; val drawable = GradientDrawable(orientation, colors)
drawable.shape = GradientDrawable.RECTANGLE
return drawable
} }
private static int getSize(float size) { private fun getSize(size: Float): Int {
return (int) (size < 0 ? size : Utils.convertDpToPx(size)); return if (size < 0) size.toInt() else Utils.convertDpToPx(size)
} }
public static Pair<Integer, Integer> measure(@NonNull final View view, @NonNull final View parent) { fun measure(view: View, parent: View): Pair<Int, Int> {
view.measure( view.measure(
View.MeasureSpec.makeMeasureSpec(parent.getWidth(), View.MeasureSpec.UNSPECIFIED), View.MeasureSpec.makeMeasureSpec(parent.width, View.MeasureSpec.UNSPECIFIED),
View.MeasureSpec.makeMeasureSpec(parent.getHeight(), View.MeasureSpec.UNSPECIFIED) View.MeasureSpec.makeMeasureSpec(parent.height, View.MeasureSpec.UNSPECIFIED)
); )
return new Pair<>(view.getMeasuredHeight(), view.getMeasuredWidth()); return Pair(view.measuredHeight, view.measuredWidth)
} }
public static float getTextViewValueWidth(final TextView textView, final String text) { fun getTextViewValueWidth(textView: TextView, text: String?): Float {
return textView.getPaint().measureText(text); return textView.paint.measureText(text)
} }
/** /**
@ -90,32 +86,32 @@ public final class ViewUtils {
* @param finalPosition [SpringForce.mFinalPosition] Final position of spring. * @param finalPosition [SpringForce.mFinalPosition] Final position of spring.
* @return [SpringAnimation] * @return [SpringAnimation]
*/ */
@NonNull fun springAnimationOf(
public static SpringAnimation springAnimationOf(final Object object, `object`: Any?,
final FloatPropertyCompat<Object> property, property: FloatPropertyCompat<Any?>?,
@Nullable final Float finalPosition) { finalPosition: Float?
return finalPosition == null ? new SpringAnimation(object, property) : new SpringAnimation(object, property, finalPosition); ): SpringAnimation {
return finalPosition?.let { SpringAnimation(`object`, property, it) } ?: SpringAnimation(`object`, property)
} }
public static void suppressLayoutCompat(@NotNull ViewGroup $this$suppressLayoutCompat, boolean suppress) { fun suppressLayoutCompat(`$this$suppressLayoutCompat`: ViewGroup, suppress: Boolean) {
Intrinsics.checkNotNullParameter($this$suppressLayoutCompat, "$this$suppressLayoutCompat"); Intrinsics.checkNotNullParameter(`$this$suppressLayoutCompat`, "\$this\$suppressLayoutCompat")
if (Build.VERSION.SDK_INT >= 29) { if (Build.VERSION.SDK_INT >= 29) {
$this$suppressLayoutCompat.suppressLayout(suppress); `$this$suppressLayoutCompat`.suppressLayout(suppress)
} else { } else {
hiddenSuppressLayout($this$suppressLayoutCompat, suppress); hiddenSuppressLayout(`$this$suppressLayoutCompat`, suppress)
} }
} }
private static boolean tryHiddenSuppressLayout = true; private var tryHiddenSuppressLayout = true
@SuppressLint({"NewApi"}) @SuppressLint("NewApi")
private static void hiddenSuppressLayout(ViewGroup group, boolean suppress) { private fun hiddenSuppressLayout(group: ViewGroup, suppress: Boolean) {
if (tryHiddenSuppressLayout) { if (tryHiddenSuppressLayout) {
try { try {
group.suppressLayout(suppress); group.suppressLayout(suppress)
} catch (NoSuchMethodError var3) { } catch (var3: NoSuchMethodError) {
tryHiddenSuppressLayout = false; tryHiddenSuppressLayout = false
}
} }
} }
} }

View File

@ -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
}
}

View File

@ -73,7 +73,7 @@ public class UserSearchViewModel extends ViewModel {
} }
userService = UserService.getInstance(); userService = UserService.getInstance();
directMessagesService = DirectMessagesService.getInstance(csrfToken, viewerId, deviceUuid); directMessagesService = DirectMessagesService.getInstance(csrfToken, viewerId, deviceUuid);
rankedRecipientsCache = RankedRecipientsCache.getInstance(); rankedRecipientsCache = RankedRecipientsCache.INSTANCE;
if ((rankedRecipientsCache.isFailed() || rankedRecipientsCache.isExpired()) && !rankedRecipientsCache.isUpdateInitiated()) { if ((rankedRecipientsCache.isFailed() || rankedRecipientsCache.isExpired()) && !rankedRecipientsCache.isUpdateInitiated()) {
updateRankedRecipientCache(); updateRankedRecipientCache();
} }
@ -113,7 +113,7 @@ public class UserSearchViewModel extends ViewModel {
continueSearchIfRequired(); continueSearchIfRequired();
return; return;
} }
rankedRecipientsCache.setRankedRecipientsResponse(response.body()); rankedRecipientsCache.setResponse(response.body());
rankedRecipientsCache.setUpdateInitiated(false); rankedRecipientsCache.setUpdateInitiated(false);
continueSearchIfRequired(); continueSearchIfRequired();
} }