NekoX/TMessagesProj/src/main/java/org/telegram/messenger/AndroidUtilities.java

4157 lines
174 KiB
Java
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*
* 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.
*/
package org.telegram.messenger;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.AnimatorSet;
import android.animation.ObjectAnimator;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.ContentResolver;
import android.content.ContentUris;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.ActivityInfo;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.Signature;
import android.content.res.AssetFileDescriptor;
import android.content.res.Configuration;
import android.database.Cursor;
import android.graphics.Bitmap;
import android.graphics.Color;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.Point;
import android.graphics.Rect;
import android.graphics.RectF;
import android.graphics.Typeface;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.os.Build;
import android.os.Environment;
import android.os.PowerManager;
import android.os.SystemClock;
import android.provider.CallLog;
import android.provider.DocumentsContract;
import android.provider.MediaStore;
import android.provider.Settings;
import android.telephony.TelephonyManager;
import android.text.Layout;
import android.text.Selection;
import android.text.Spannable;
import android.text.SpannableStringBuilder;
import android.text.Spanned;
import android.text.SpannedString;
import android.text.StaticLayout;
import android.text.TextPaint;
import android.text.TextUtils;
import android.text.method.LinkMovementMethod;
import android.text.style.URLSpan;
import android.text.util.Linkify;
import android.util.DisplayMetrics;
import android.util.Log;
import android.util.StateSet;
import android.util.TypedValue;
import android.view.ContextThemeWrapper;
import android.view.Display;
import android.view.Gravity;
import android.view.MotionEvent;
import android.view.Surface;
import android.view.View;
import android.view.ViewGroup;
import android.view.Window;
import android.view.WindowInsets;
import android.view.WindowManager;
import android.view.accessibility.AccessibilityEvent;
import android.view.accessibility.AccessibilityManager;
import android.view.animation.AccelerateInterpolator;
import android.view.animation.DecelerateInterpolator;
import android.view.animation.OvershootInterpolator;
import android.view.inputmethod.InputMethodManager;
import android.view.inputmethod.InputMethodSubtype;
import android.webkit.MimeTypeMap;
import android.widget.EdgeEffect;
import android.widget.HorizontalScrollView;
import android.widget.LinearLayout;
import android.widget.ListView;
import android.widget.ScrollView;
import android.widget.TextView;
import androidx.core.content.FileProvider;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import androidx.viewpager.widget.ViewPager;
import com.android.internal.telephony.ITelephony;
import org.telegram.PhoneFormat.PhoneFormat;
import org.telegram.messenger.browser.Browser;
import org.telegram.tgnet.ConnectionsManager;
import org.telegram.tgnet.RequestTimeDelegate;
import org.telegram.tgnet.TLObject;
import org.telegram.tgnet.TLRPC;
import org.telegram.ui.ActionBar.ActionBarLayout;
import org.telegram.ui.ActionBar.AlertDialog;
import org.telegram.ui.ActionBar.BaseFragment;
import org.telegram.ui.ActionBar.BottomSheet;
import org.telegram.ui.ActionBar.Theme;
import org.telegram.ui.Cells.TextDetailSettingsCell;
import org.telegram.ui.Components.BackgroundGradientDrawable;
import org.telegram.ui.Components.ForegroundColorSpanThemable;
import org.telegram.ui.Components.ForegroundDetector;
import org.telegram.ui.Components.LayoutHelper;
import org.telegram.ui.Components.PickerBottomLayout;
import org.telegram.ui.Components.RecyclerListView;
import org.telegram.ui.Components.ShareAlert;
import org.telegram.ui.Components.TypefaceSpan;
import org.telegram.ui.ThemePreviewActivity;
import org.telegram.ui.WallpapersListActivity;
import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.lang.ref.WeakReference;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.HashSet;
import java.util.Hashtable;
import java.util.List;
import java.util.Locale;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import cn.hutool.core.util.StrUtil;
import kotlin.Unit;
import tw.nekomimi.nekogram.BottomBuilder;
import tw.nekomimi.nekogram.NekoConfig;
import tw.nekomimi.nekogram.NekoXConfig;
import tw.nekomimi.nekogram.utils.AlertUtil;
import tw.nekomimi.nekogram.utils.EnvUtil;
import tw.nekomimi.nekogram.utils.FileUtil;
import tw.nekomimi.nekogram.utils.ProxyUtil;
import tw.nekomimi.nekogram.utils.UIUtil;
import static com.v2ray.ang.V2RayConfig.SSR_PROTOCOL;
import static com.v2ray.ang.V2RayConfig.SS_PROTOCOL;
import static com.v2ray.ang.V2RayConfig.TROJAN_PROTOCOL;
import static com.v2ray.ang.V2RayConfig.VMESS1_PROTOCOL;
import static com.v2ray.ang.V2RayConfig.VMESS_PROTOCOL;
public class AndroidUtilities {
private static final Hashtable<String, Typeface> typefaceCache = new Hashtable<>();
private static int prevOrientation = -10;
private static boolean waitingForSms = false;
private static boolean waitingForCall = false;
private static final Object smsLock = new Object();
private static final Object callLock = new Object();
public static int statusBarHeight = 0;
public static boolean firstConfigurationWas;
public static float density = 1;
public static Point displaySize = new Point();
public static float screenRefreshRate = 60;
public static int roundMessageSize;
public static int roundMessageInset;
public static boolean incorrectDisplaySizeFix;
public static Integer photoSize = null;
public static DisplayMetrics displayMetrics = new DisplayMetrics();
public static int leftBaseline;
public static boolean usingHardwareInput;
public static boolean isInMultiwindow;
public static DecelerateInterpolator decelerateInterpolator = new DecelerateInterpolator();
public static AccelerateInterpolator accelerateInterpolator = new AccelerateInterpolator();
public static OvershootInterpolator overshootInterpolator = new OvershootInterpolator();
private static Boolean isTablet = null;
private static int adjustOwnerClassGuid = 0;
private static Paint roundPaint;
private static RectF bitmapRect;
public static Pattern WEB_URL = null;
static {
try {
final String GOOD_IRI_CHAR = "a-zA-Z0-9\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF";
final Pattern IP_ADDRESS = Pattern.compile(
"((25[0-5]|2[0-4][0-9]|[0-1][0-9]{2}|[1-9][0-9]|[1-9])\\.(25[0-5]|2[0-4]"
+ "[0-9]|[0-1][0-9]{2}|[1-9][0-9]|[1-9]|0)\\.(25[0-5]|2[0-4][0-9]|[0-1]"
+ "[0-9]{2}|[1-9][0-9]|[1-9]|0)\\.(25[0-5]|2[0-4][0-9]|[0-1][0-9]{2}"
+ "|[1-9][0-9]|[0-9]))");
final String IRI = "[" + GOOD_IRI_CHAR + "]([" + GOOD_IRI_CHAR + "\\-]{0,61}[" + GOOD_IRI_CHAR + "]){0,1}";
final String GOOD_GTLD_CHAR = "a-zA-Z\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF";
final String GTLD = "[" + GOOD_GTLD_CHAR + "]{2,63}";
final String HOST_NAME = "(" + IRI + "\\.)+" + GTLD;
final Pattern DOMAIN_NAME = Pattern.compile("(" + HOST_NAME + "|" + IP_ADDRESS + ")");
WEB_URL = Pattern.compile(
"((?:(http|https|Http|Https|ton|tg):\\/\\/(?:(?:[a-zA-Z0-9\\$\\-\\_\\.\\+\\!\\*\\'\\(\\)"
+ "\\,\\;\\?\\&\\=]|(?:\\%[a-fA-F0-9]{2})){1,64}(?:\\:(?:[a-zA-Z0-9\\$\\-\\_"
+ "\\.\\+\\!\\*\\'\\(\\)\\,\\;\\?\\&\\=]|(?:\\%[a-fA-F0-9]{2})){1,25})?\\@)?)?"
+ "(?:" + DOMAIN_NAME + ")"
+ "(?:\\:\\d{1,5})?)" // plus option port number
+ "(\\/(?:(?:[" + GOOD_IRI_CHAR + "\\;\\/\\?\\:\\@\\&\\=\\#\\~" // plus option query params
+ "\\-\\.\\+\\!\\*\\'\\(\\)\\,\\_])|(?:\\%[a-fA-F0-9]{2}))*)?"
+ "(?:\\b|$)");
} catch (Exception e) {
FileLog.e(e);
}
}
static {
leftBaseline = isTablet() ? 80 : 72;
checkDisplaySize(ApplicationLoader.applicationContext, null);
}
private static int[] documentIcons = {
R.drawable.media_doc_blue,
R.drawable.media_doc_green,
R.drawable.media_doc_red,
R.drawable.media_doc_yellow
};
private static int[] documentMediaIcons = {
R.drawable.media_doc_blue_b,
R.drawable.media_doc_green_b,
R.drawable.media_doc_red_b,
R.drawable.media_doc_yellow_b
};
private static boolean containsUnsupportedCharacters(String text) {
if (text.contains("\u202C")) {
return true;
}
if (text.contains("\u202D")) {
return true;
}
if (text.contains("\u202E")) {
return true;
}
return false;
}
public static CharSequence ellipsizeCenterEnd(CharSequence str, String query, int availableWidth, TextPaint textPaint, int maxSymbols) {
try {
int lastIndex = str.length();
int startHighlightedIndex = str.toString().toLowerCase().indexOf(query);
if (lastIndex > maxSymbols) {
str = str.subSequence(Math.max(0, startHighlightedIndex - maxSymbols / 2), Math.min(lastIndex, startHighlightedIndex + maxSymbols / 2));
startHighlightedIndex -= Math.max(0, startHighlightedIndex - maxSymbols / 2);
lastIndex = str.length();
}
StaticLayout staticLayout = new StaticLayout(str, textPaint, Integer.MAX_VALUE, Layout.Alignment.ALIGN_NORMAL, 1.0f, 0.0f, false);
float endOfTextX = staticLayout.getLineWidth(0);
if (endOfTextX + textPaint.measureText("...") < availableWidth) {
return str;
}
int i = startHighlightedIndex + 1;
while (i < str.length() - 1 && !Character.isWhitespace(str.charAt(i))) {
i++;
}
int endHighlightedIndex = i;
float endOfHighlight = staticLayout.getPrimaryHorizontal(endHighlightedIndex);
if (staticLayout.isRtlCharAt(endHighlightedIndex)) {
endOfHighlight = endOfTextX - endOfHighlight;
}
if (endOfHighlight < availableWidth) {
return str;
}
float x = endOfHighlight - availableWidth + textPaint.measureText("...") * 2 + availableWidth * 0.1f;
if (str.length() - endHighlightedIndex > 20) {
x += availableWidth * 0.1f;
}
if (x > 0) {
int charOf = staticLayout.getOffsetForHorizontal(0, x);
int k = 0;
if (charOf > str.length() - 1) {
charOf = str.length() - 1;
}
while (!Character.isWhitespace(str.charAt(charOf)) && k < 10) {
k++;
charOf++;
if (charOf > str.length() - 1) {
charOf = staticLayout.getOffsetForHorizontal(0, x);
break;
}
}
CharSequence sub;
if (k >= 10) {
x = staticLayout.getPrimaryHorizontal(startHighlightedIndex + 1) - availableWidth * 0.3f;
sub = str.subSequence(staticLayout.getOffsetForHorizontal(0, x), str.length());
} else {
if (charOf > 0 && charOf < str.length() - 2 && Character.isWhitespace(str.charAt(charOf))) {
charOf++;
}
sub = str.subSequence(charOf, str.length());
}
return SpannableStringBuilder.valueOf("...").append(sub);
}
} catch (Exception e) {
FileLog.e(e);
}
return str;
}
public static CharSequence highlightText(CharSequence str, ArrayList<String> query) {
if (query == null) {
return null;
}
int emptyCount = 0;
for (int i = 0; i < query.size(); i++) {
CharSequence strTmp = highlightText(str, query.get(i));
if (strTmp != null) {
str = strTmp;
} else {
emptyCount++;
}
}
if (emptyCount == query.size()) {
return null;
}
return str;
}
public static CharSequence highlightText(CharSequence str, String query) {
if (TextUtils.isEmpty(query) || TextUtils.isEmpty(str)) {
return null;
}
String s = str.toString().toLowerCase();
SpannableStringBuilder spannableStringBuilder = SpannableStringBuilder.valueOf(str);
int i = s.indexOf(query);
while (i >= 0) {
try {
spannableStringBuilder.setSpan(new ForegroundColorSpanThemable(Theme.key_windowBackgroundWhiteBlueText4), i, Math.min(i + query.length(), str.length()), 0);
} catch (Exception e) {
FileLog.e(e);
}
i = s.indexOf(query, i + 1);
}
return spannableStringBuilder;
}
public static Activity findActivity(Context context) {
if (context instanceof Activity) {
return (Activity) context;
}
if (context instanceof ContextThemeWrapper) {
return findActivity(((ContextThemeWrapper) context).getBaseContext());
}
return null;
}
private static class LinkSpec {
String url;
int start;
int end;
}
private static String makeUrl(String url, String[] prefixes, Matcher matcher) {
boolean hasPrefix = false;
for (int i = 0; i < prefixes.length; i++) {
if (url.regionMatches(true, 0, prefixes[i], 0, prefixes[i].length())) {
hasPrefix = true;
if (!url.regionMatches(false, 0, prefixes[i], 0, prefixes[i].length())) {
url = prefixes[i] + url.substring(prefixes[i].length());
}
break;
}
}
if (!hasPrefix && prefixes.length > 0) {
url = prefixes[0] + url;
}
return url;
}
private static void gatherLinks(ArrayList<LinkSpec> links, Spannable s, Pattern pattern, String[] schemes, Linkify.MatchFilter matchFilter, boolean internalOnly) {
if (TextUtils.indexOf(s, '─') >= 0) {
s = new SpannableStringBuilder(s.toString().replace('─', ' '));
}
Matcher m = pattern.matcher(s);
while (m.find()) {
int start = m.start();
int end = m.end();
if (matchFilter == null || matchFilter.acceptMatch(s, start, end)) {
LinkSpec spec = new LinkSpec();
String url = makeUrl(m.group(0), schemes, m);
if (internalOnly && !Browser.isInternalUrl(url, true, null)) {
continue;
}
spec.url = url;
spec.start = start;
spec.end = end;
links.add(spec);
}
}
}
public static final Linkify.MatchFilter sUrlMatchFilter = (s, start, end) -> {
if (start == 0) {
return true;
}
if (s.charAt(start - 1) == '@') {
return false;
}
return true;
};
public static boolean addProxyLinks(Spannable text) {
if (text == null) return false;
final URLSpan[] old = text.getSpans(0, text.length(), URLSpan.class);
for (int i = old.length - 1; i >= 0; i--) {
String url = old[i].getURL();
if (url.startsWith("vmess") || url.startsWith("ss")) {
text.removeSpan(old[i]);
}
}
final ArrayList<LinkSpec> links = new ArrayList<>();
gatherLinks(links, text, LinkifyPort.PROXY_PATTERN, new String[]{VMESS_PROTOCOL, VMESS1_PROTOCOL, SS_PROTOCOL, SSR_PROTOCOL, TROJAN_PROTOCOL/*, RB_PROTOCOL*/}, sUrlMatchFilter, false);
pruneOverlaps(links);
if (links.size() == 0) {
return false;
}
for (int a = 0, N = links.size(); a < N; a++) {
LinkSpec link = links.get(a);
URLSpan[] oldSpans = text.getSpans(link.start, link.end, URLSpan.class);
if (oldSpans != null && oldSpans.length > 0) {
for (int b = 0; b < oldSpans.length; b++) {
text.removeSpan(oldSpans[b]);
}
}
text.setSpan(new URLSpan(link.url), link.start, link.end, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
}
return true;
}
public static boolean addLinks(Spannable text, int mask) {
return addLinks(text, mask, false);
}
public static boolean addLinks(Spannable text, int mask, boolean internalOnly) {
if (text == null || containsUnsupportedCharacters(text.toString()) || mask == 0) {
return false;
}
final URLSpan[] old = text.getSpans(0, text.length(), URLSpan.class);
for (int i = old.length - 1; i >= 0; i--) {
text.removeSpan(old[i]);
}
final ArrayList<LinkSpec> links = new ArrayList<>();
if (!internalOnly && (mask & Linkify.PHONE_NUMBERS) != 0) {
Linkify.addLinks(text, Linkify.PHONE_NUMBERS);
}
if ((mask & Linkify.WEB_URLS) != 0) {
gatherLinks(links, text, LinkifyPort.WEB_URL, new String[]{"http://", "https://", "ton://", "tg://"}, sUrlMatchFilter, internalOnly);
}
pruneOverlaps(links);
if (links.size() == 0) {
return false;
}
for (int a = 0, N = links.size(); a < N; a++) {
LinkSpec link = links.get(a);
URLSpan[] oldSpans = text.getSpans(link.start, link.end, URLSpan.class);
if (oldSpans != null && oldSpans.length > 0) {
for (URLSpan oldSpan : oldSpans) {
text.removeSpan(oldSpan);
}
}
text.setSpan(new URLSpan(link.url), link.start, link.end, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
}
return true;
}
private static void pruneOverlaps(ArrayList<LinkSpec> links) {
Comparator<LinkSpec> c = (a, b) -> {
if (a.start < b.start) {
return -1;
}
if (a.start > b.start) {
return 1;
}
if (a.end < b.end) {
return 1;
}
if (a.end > b.end) {
return -1;
}
return 0;
};
Collections.sort(links, c);
int len = links.size();
int i = 0;
while (i < len - 1) {
LinkSpec a = links.get(i);
LinkSpec b = links.get(i + 1);
int remove = -1;
if ((a.start <= b.start) && (a.end > b.start)) {
if (b.end <= a.end) {
remove = i + 1;
} else if ((a.end - a.start) > (b.end - b.start)) {
remove = i + 1;
} else if ((a.end - a.start) < (b.end - b.start)) {
remove = i;
}
if (remove != -1) {
links.remove(remove);
len--;
continue;
}
}
i++;
}
}
public static void fillStatusBarHeight(Context context) {
if (context == null || AndroidUtilities.statusBarHeight > 0) {
return;
}
int resourceId = context.getResources().getIdentifier("status_bar_height", "dimen", "android");
if (resourceId > 0) {
AndroidUtilities.statusBarHeight = context.getResources().getDimensionPixelSize(resourceId);
}
}
public static int getThumbForNameOrMime(String name, String mime, boolean media) {
if (name != null && name.length() != 0) {
int color = -1;
if (name.contains(".doc") || name.contains(".txt") || name.contains(".psd")) {
color = 0;
} else if (name.contains(".xls") || name.contains(".csv")) {
color = 1;
} else if (name.contains(".pdf") || name.contains(".ppt") || name.contains(".key")) {
color = 2;
} else if (name.contains(".zip") || name.contains(".rar") || name.contains(".ai") || name.contains(".mp3") || name.contains(".mov") || name.contains(".avi")) {
color = 3;
}
if (color == -1) {
int idx;
String ext = (idx = name.lastIndexOf('.')) == -1 ? "" : name.substring(idx + 1);
if (ext.length() != 0) {
color = ext.charAt(0) % documentIcons.length;
} else {
color = name.charAt(0) % documentIcons.length;
}
}
return media ? documentMediaIcons[color] : documentIcons[color];
}
return media ? documentMediaIcons[0] : documentIcons[0];
}
public static int calcBitmapColor(Bitmap bitmap) {
try {
Bitmap b = Bitmaps.createScaledBitmap(bitmap, 1, 1, true);
if (b != null) {
int bitmapColor = b.getPixel(0, 0);
if (bitmap != b) {
b.recycle();
}
return bitmapColor;
}
} catch (Exception e) {
FileLog.e(e);
}
return 0;
}
public static int[] calcDrawableColor(Drawable drawable) {
int bitmapColor = 0xff000000;
int[] result = new int[4];
try {
if (drawable instanceof BitmapDrawable) {
Bitmap bitmap = ((BitmapDrawable) drawable).getBitmap();
bitmapColor = calcBitmapColor(bitmap);
} else if (drawable instanceof ColorDrawable) {
bitmapColor = ((ColorDrawable) drawable).getColor();
} else if (drawable instanceof BackgroundGradientDrawable) {
int[] colors = ((BackgroundGradientDrawable) drawable).getColorsList();
if (colors != null) {
if (colors.length > 1) {
bitmapColor = getAverageColor(colors[0], colors[1]);
} else if (colors.length > 0) {
bitmapColor = colors[0];
}
}
}
} catch (Exception e) {
FileLog.e(e);
}
double[] hsv = rgbToHsv((bitmapColor >> 16) & 0xff, (bitmapColor >> 8) & 0xff, bitmapColor & 0xff);
hsv[1] = Math.min(1.0, hsv[1] + 0.05 + 0.1 * (1.0 - hsv[1]));
double v = Math.max(0, hsv[2] * 0.65);
int[] rgb = hsvToRgb(hsv[0], hsv[1], v);
result[0] = Color.argb(0x66, rgb[0], rgb[1], rgb[2]);
result[1] = Color.argb(0x88, rgb[0], rgb[1], rgb[2]);
double v2 = Math.max(0, hsv[2] * 0.72);
rgb = hsvToRgb(hsv[0], hsv[1], v2);
result[2] = Color.argb(0x66, rgb[0], rgb[1], rgb[2]);
result[3] = Color.argb(0x88, rgb[0], rgb[1], rgb[2]);
return result;
}
public static double[] rgbToHsv(int color) {
return rgbToHsv(Color.red(color), Color.green(color), Color.blue(color));
}
public static double[] rgbToHsv(int r, int g, int b) {
double rf = r / 255.0;
double gf = g / 255.0;
double bf = b / 255.0;
double max = (rf > gf && rf > bf) ? rf : Math.max(gf, bf);
double min = (rf < gf && rf < bf) ? rf : Math.min(gf, bf);
double h, s;
double d = max - min;
s = max == 0 ? 0 : d / max;
if (max == min) {
h = 0;
} else {
if (rf > gf && rf > bf) {
h = (gf - bf) / d + (gf < bf ? 6 : 0);
} else if (gf > bf) {
h = (bf - rf) / d + 2;
} else {
h = (rf - gf) / d + 4;
}
h /= 6;
}
return new double[]{h, s, max};
}
public static int hsvToColor(double h, double s, double v) {
int[] rgb = hsvToRgb(h, s, v);
return Color.argb(0xff, rgb[0], rgb[1], rgb[2]);
}
public static int[] hsvToRgb(double h, double s, double v) {
double r = 0, g = 0, b = 0;
double i = (int) Math.floor(h * 6);
double f = h * 6 - i;
double p = v * (1 - s);
double q = v * (1 - f * s);
double t = v * (1 - (1 - f) * s);
switch ((int) i % 6) {
case 0:
r = v;
g = t;
b = p;
break;
case 1:
r = q;
g = v;
b = p;
break;
case 2:
r = p;
g = v;
b = t;
break;
case 3:
r = p;
g = q;
b = v;
break;
case 4:
r = t;
g = p;
b = v;
break;
case 5:
r = v;
g = p;
b = q;
break;
}
return new int[]{(int) (r * 255), (int) (g * 255), (int) (b * 255)};
}
public static void requestAdjustResize(Activity activity, int classGuid) {
if (activity == null || isTablet()) {
return;
}
activity.getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE);
adjustOwnerClassGuid = classGuid;
}
public static void requestAdjustNothing(Activity activity, int classGuid) {
if (activity == null || isTablet()) {
return;
}
activity.getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_NOTHING);
adjustOwnerClassGuid = classGuid;
}
public static void setAdjustResizeToNothing(Activity activity, int classGuid) {
if (activity == null || isTablet()) {
return;
}
if (adjustOwnerClassGuid == 0 || adjustOwnerClassGuid == classGuid) {
activity.getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_NOTHING);
}
}
public static void removeAdjustResize(Activity activity, int classGuid) {
if (activity == null || isTablet()) {
return;
}
if (adjustOwnerClassGuid == classGuid) {
activity.getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_PAN);
}
}
public static void createEmptyFile(File f) {
try {
if (f.exists()) {
return;
}
FileWriter writer = new FileWriter(f);
writer.flush();
writer.close();
} catch (Throwable e) {
FileLog.e(e);
}
}
public static boolean isGoogleMapsInstalled(final BaseFragment fragment) {
return true;
}
public static int[] toIntArray(List<Integer> integers) {
int[] ret = new int[integers.size()];
for (int i = 0; i < ret.length; i++) {
ret[i] = integers.get(i);
}
return ret;
}
public static boolean isInternalUri(Uri uri) {
return isInternalUri(uri, 0);
}
public static boolean isInternalUri(int fd) {
return isInternalUri(null, fd);
}
private static boolean isInternalUri(Uri uri, int fd) {
String pathString;
if (uri != null) {
pathString = uri.getPath();
if (pathString == null) {
return false;
}
// Allow sending VoIP logs from cache/voip_logs
if (pathString.matches(Pattern.quote(new File(ApplicationLoader.applicationContext.getCacheDir(), "voip_logs").getAbsolutePath()) + "/\\d+\\.log")) {
return false;
}
int tries = 0;
while (true) {
if (pathString != null && pathString.length() > 4096) {
return true;
}
String newPath;
try {
newPath = Utilities.readlink(pathString);
} catch (Throwable e) {
return true;
}
if (newPath == null || newPath.equals(pathString)) {
break;
}
pathString = newPath;
tries++;
if (tries >= 10) {
return true;
}
}
} else {
pathString = "";
int tries = 0;
while (true) {
if (pathString != null && pathString.length() > 4096) {
return true;
}
String newPath;
try {
newPath = Utilities.readlinkFd(fd);
} catch (Throwable e) {
return true;
}
if (newPath == null || newPath.equals(pathString)) {
break;
}
pathString = newPath;
tries++;
if (tries >= 10) {
return true;
}
}
}
if (pathString != null) {
try {
String path = new File(pathString).getCanonicalPath();
if (path != null) {
pathString = path;
}
} catch (Exception e) {
pathString.replace("/./", "/");
//igonre
}
}
if (pathString.endsWith(".attheme")) {
return false;
}
return pathString != null && pathString.toLowerCase().contains("/data/data/" + ApplicationLoader.applicationContext.getPackageName());
}
@SuppressLint("WrongConstant")
public static void lockOrientation(Activity activity) {
if (activity == null || prevOrientation != -10) {
return;
}
try {
prevOrientation = activity.getRequestedOrientation();
WindowManager manager = (WindowManager) activity.getSystemService(Activity.WINDOW_SERVICE);
if (manager != null && manager.getDefaultDisplay() != null) {
int rotation = manager.getDefaultDisplay().getRotation();
int orientation = activity.getResources().getConfiguration().orientation;
if (rotation == Surface.ROTATION_270) {
if (orientation == Configuration.ORIENTATION_PORTRAIT) {
activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
} else {
activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE);
}
} else if (rotation == Surface.ROTATION_90) {
if (orientation == Configuration.ORIENTATION_PORTRAIT) {
activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT);
} else {
activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
}
} else if (rotation == Surface.ROTATION_0) {
if (orientation == Configuration.ORIENTATION_LANDSCAPE) {
activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
} else {
activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
}
} else {
if (orientation == Configuration.ORIENTATION_LANDSCAPE) {
activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE);
} else {
activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT);
}
}
}
} catch (Exception e) {
FileLog.e(e);
}
}
@SuppressLint("WrongConstant")
public static void unlockOrientation(Activity activity) {
if (activity == null) {
return;
}
try {
if (prevOrientation != -10) {
activity.setRequestedOrientation(prevOrientation);
prevOrientation = -10;
}
} catch (Exception e) {
FileLog.e(e);
}
}
private static class VcardData {
String name;
ArrayList<String> phones = new ArrayList<>();
StringBuilder vcard = new StringBuilder();
}
public static class VcardItem {
public ArrayList<String> vcardData = new ArrayList<>();
public String fullData = "";
public int type;
public boolean checked = true;
public String[] getRawValue() {
int idx = fullData.indexOf(':');
if (idx < 0) {
return new String[0];
}
String valueType = fullData.substring(0, idx);
String value = fullData.substring(idx + 1);
String nameEncoding = null;
String nameCharset = "UTF-8";
String[] params = valueType.split(";");
for (int a = 0; a < params.length; a++) {
String[] args2 = params[a].split("=");
if (args2.length != 2) {
continue;
}
if (args2[0].equals("CHARSET")) {
nameCharset = args2[1];
} else if (args2[0].equals("ENCODING")) {
nameEncoding = args2[1];
}
}
String[] args = value.split(";");
boolean added = false;
for (int a = 0; a < args.length; a++) {
if (TextUtils.isEmpty(args[a])) {
continue;
}
if (nameEncoding != null && nameEncoding.equalsIgnoreCase("QUOTED-PRINTABLE")) {
byte[] bytes = decodeQuotedPrintable(getStringBytes(args[a]));
if (bytes != null && bytes.length != 0) {
try {
args[a] = new String(bytes, nameCharset);
} catch (Exception ignore) {
}
}
}
}
return args;
}
public String getValue(boolean format) {
StringBuilder result = new StringBuilder();
int idx = fullData.indexOf(':');
if (idx < 0) {
return "";
}
if (result.length() > 0) {
result.append(", ");
}
String valueType = fullData.substring(0, idx);
String value = fullData.substring(idx + 1);
String nameEncoding = null;
String nameCharset = "UTF-8";
String[] params = valueType.split(";");
for (int a = 0; a < params.length; a++) {
String[] args2 = params[a].split("=");
if (args2.length != 2) {
continue;
}
if (args2[0].equals("CHARSET")) {
nameCharset = args2[1];
} else if (args2[0].equals("ENCODING")) {
nameEncoding = args2[1];
}
}
String[] args = value.split(";");
boolean added = false;
for (int a = 0; a < args.length; a++) {
if (TextUtils.isEmpty(args[a])) {
continue;
}
if (nameEncoding != null && nameEncoding.equalsIgnoreCase("QUOTED-PRINTABLE")) {
byte[] bytes = decodeQuotedPrintable(getStringBytes(args[a]));
if (bytes != null && bytes.length != 0) {
try {
args[a] = new String(bytes, nameCharset);
} catch (Exception ignore) {
}
}
}
if (added && result.length() > 0) {
result.append(" ");
}
result.append(args[a]);
if (!added) {
added = args[a].length() > 0;
}
}
if (format) {
if (type == 0) {
return PhoneFormat.getInstance().format(result.toString());
} else if (type == 5) {
String[] date = result.toString().split("T");
if (date.length > 0) {
date = date[0].split("-");
if (date.length == 3) {
Calendar calendar = Calendar.getInstance();
calendar.set(Calendar.YEAR, Utilities.parseInt(date[0]));
calendar.set(Calendar.MONTH, Utilities.parseInt(date[1]) - 1);
calendar.set(Calendar.DAY_OF_MONTH, Utilities.parseInt(date[2]));
return LocaleController.getInstance().formatterYearMax.format(calendar.getTime());
}
}
}
}
return result.toString();
}
public String getRawType(boolean first) {
int idx = fullData.indexOf(':');
if (idx < 0) {
return "";
}
String value = fullData.substring(0, idx);
if (type == 20) {
value = value.substring(2);
String[] args = value.split(";");
if (first) {
value = args[0];
} else if (args.length > 1) {
value = args[args.length - 1];
} else {
value = "";
}
} else {
String[] args = value.split(";");
for (int a = 0; a < args.length; a++) {
if (args[a].indexOf('=') >= 0) {
continue;
}
value = args[a];
}
return value;
}
return value;
}
public String getType() {
if (type == 5) {
return LocaleController.getString("ContactBirthday", R.string.ContactBirthday);
} else if (type == 6) {
if ("ORG".equalsIgnoreCase(getRawType(true))) {
return LocaleController.getString("ContactJob", R.string.ContactJob);
} else {
return LocaleController.getString("ContactJobTitle", R.string.ContactJobTitle);
}
}
int idx = fullData.indexOf(':');
if (idx < 0) {
return "";
}
String value = fullData.substring(0, idx);
if (type == 20) {
value = value.substring(2);
String[] args = value.split(";");
value = args[0];
} else {
String[] args = value.split(";");
for (int a = 0; a < args.length; a++) {
if (args[a].indexOf('=') >= 0) {
continue;
}
value = args[a];
}
if (value.startsWith("X-")) {
value = value.substring(2);
}
switch (value) {
case "PREF":
value = LocaleController.getString("PhoneMain", R.string.PhoneMain);
break;
case "HOME":
value = LocaleController.getString("PhoneHome", R.string.PhoneHome);
break;
case "MOBILE":
case "CELL":
value = LocaleController.getString("PhoneMobile", R.string.PhoneMobile);
break;
case "OTHER":
value = LocaleController.getString("PhoneOther", R.string.PhoneOther);
break;
case "WORK":
value = LocaleController.getString("PhoneWork", R.string.PhoneWork);
break;
}
}
value = value.substring(0, 1).toUpperCase() + value.substring(1).toLowerCase();
return value;
}
}
public static byte[] getStringBytes(String src) {
try {
return src.getBytes("UTF-8");
} catch (Exception ignore) {
}
return new byte[0];
}
public static ArrayList<TLRPC.User> loadVCardFromStream(Uri uri, int currentAccount, boolean asset, ArrayList<VcardItem> items, String name) {
ArrayList<TLRPC.User> result = null;
try {
InputStream stream;
if (asset) {
AssetFileDescriptor fd = ApplicationLoader.applicationContext.getContentResolver().openAssetFileDescriptor(uri, "r");
stream = fd.createInputStream();
} else {
ContentResolver cr = ApplicationLoader.applicationContext.getContentResolver();
stream = cr.openInputStream(uri);
}
ArrayList<VcardData> vcardDatas = new ArrayList<>();
VcardData currentData = null;
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(stream, "UTF-8"));
String line;
String originalLine;
String pendingLine = null;
boolean currentIsPhoto = false;
VcardItem currentItem = null;
while ((originalLine = line = bufferedReader.readLine()) != null) {
if (originalLine.startsWith("PHOTO")) {
currentIsPhoto = true;
continue;
} else {
if (originalLine.indexOf(':') >= 0) {
currentItem = null;
currentIsPhoto = false;
if (originalLine.startsWith("BEGIN:VCARD")) {
vcardDatas.add(currentData = new VcardData());
currentData.name = name;
} else if (originalLine.startsWith("END:VCARD")) {
} else if (items != null) {
if (originalLine.startsWith("TEL")) {
currentItem = new VcardItem();
currentItem.type = 0;
} else if (originalLine.startsWith("EMAIL")) {
currentItem = new VcardItem();
currentItem.type = 1;
} else if (originalLine.startsWith("ADR") || originalLine.startsWith("LABEL") || originalLine.startsWith("GEO")) {
currentItem = new VcardItem();
currentItem.type = 2;
} else if (originalLine.startsWith("URL")) {
currentItem = new VcardItem();
currentItem.type = 3;
} else if (originalLine.startsWith("NOTE")) {
currentItem = new VcardItem();
currentItem.type = 4;
} else if (originalLine.startsWith("BDAY")) {
currentItem = new VcardItem();
currentItem.type = 5;
} else if (originalLine.startsWith("ORG") || originalLine.startsWith("TITLE") || originalLine.startsWith("ROLE")) {
if (currentItem == null) {
currentItem = new VcardItem();
currentItem.type = 6;
}
} else if (originalLine.startsWith("X-ANDROID")) {
currentItem = new VcardItem();
currentItem.type = -1;
} else if (originalLine.startsWith("X-PHONETIC")) {
currentItem = null;
} else if (originalLine.startsWith("X-")) {
currentItem = new VcardItem();
currentItem.type = 20;
}
if (currentItem != null && currentItem.type >= 0) {
items.add(currentItem);
}
}
}
}
if (!currentIsPhoto && currentData != null) {
if (currentItem == null) {
if (currentData.vcard.length() > 0) {
currentData.vcard.append('\n');
}
currentData.vcard.append(originalLine);
} else {
currentItem.vcardData.add(originalLine);
}
}
if (pendingLine != null) {
pendingLine += line;
line = pendingLine;
pendingLine = null;
}
if (line.contains("=QUOTED-PRINTABLE") && line.endsWith("=")) {
pendingLine = line.substring(0, line.length() - 1);
continue;
}
if (!currentIsPhoto && currentData != null && currentItem != null) {
currentItem.fullData = line;
}
int idx = line.indexOf(":");
String[] args;
if (idx >= 0) {
args = new String[]{
line.substring(0, idx),
line.substring(idx + 1).trim()
};
} else {
args = new String[]{line.trim()};
}
if (args.length < 2 || currentData == null) {
continue;
}
if (args[0].startsWith("FN") || args[0].startsWith("ORG") && TextUtils.isEmpty(currentData.name)) {
String nameEncoding = null;
String nameCharset = null;
String[] params = args[0].split(";");
for (String param : params) {
String[] args2 = param.split("=");
if (args2.length != 2) {
continue;
}
if (args2[0].equals("CHARSET")) {
nameCharset = args2[1];
} else if (args2[0].equals("ENCODING")) {
nameEncoding = args2[1];
}
}
currentData.name = args[1];
if (nameEncoding != null && nameEncoding.equalsIgnoreCase("QUOTED-PRINTABLE")) {
byte[] bytes = decodeQuotedPrintable(getStringBytes(currentData.name));
if (bytes != null && bytes.length != 0) {
String decodedName = new String(bytes, nameCharset);
if (decodedName != null) {
currentData.name = decodedName;
}
}
}
} else if (args[0].startsWith("TEL")) {
currentData.phones.add(args[1]);
}
}
try {
bufferedReader.close();
stream.close();
} catch (Exception e) {
FileLog.e(e);
}
for (int a = 0; a < vcardDatas.size(); a++) {
VcardData vcardData = vcardDatas.get(a);
if (vcardData.name != null && !vcardData.phones.isEmpty()) {
if (result == null) {
result = new ArrayList<>();
}
String phoneToUse = vcardData.phones.get(0);
for (int b = 0; b < vcardData.phones.size(); b++) {
String phone = vcardData.phones.get(b);
String sphone = phone.substring(Math.max(0, phone.length() - 7));
if (ContactsController.getInstance(currentAccount).contactsByShortPhone.get(sphone) != null) {
phoneToUse = phone;
break;
}
}
TLRPC.User user = new TLRPC.TL_userContact_old2();
user.phone = phoneToUse;
user.first_name = vcardData.name;
user.last_name = "";
user.id = 0;
TLRPC.TL_restrictionReason reason = new TLRPC.TL_restrictionReason();
reason.text = vcardData.vcard.toString();
reason.platform = "";
reason.reason = "";
user.restriction_reason.add(reason);
result.add(user);
}
}
} catch (Throwable e) {
FileLog.e(e);
}
return result;
}
public static Typeface getTypeface(String assetPath) {
synchronized (typefaceCache) {
if (NekoConfig.typeface == 1 && Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
if (assetPath.contains("medium") && assetPath.contains("italic")) {
return Typeface.create("sans-serif-medium", Typeface.ITALIC);
}
if (assetPath.contains("medium")) {
return Typeface.create("sans-serif-medium", Typeface.NORMAL);
}
if (assetPath.contains("italic")) {
return Typeface.create((Typeface) null, Typeface.ITALIC);
}
if (assetPath.contains("mono")) {
return Typeface.MONOSPACE;
}
if (assetPath.contains("mw_bold")) {
return Typeface.create("serif", Typeface.BOLD);
}
//return Typeface.create((Typeface) null, Typeface.NORMAL);
}
if (!typefaceCache.containsKey(assetPath)) {
try {
Typeface t;
if (Build.VERSION.SDK_INT >= 26) {
Typeface.Builder builder = new Typeface.Builder(ApplicationLoader.applicationContext.getAssets(), assetPath);
if (assetPath.contains("medium")) {
builder.setWeight(700);
}
if (assetPath.contains("italic")) {
builder.setItalic(true);
}
t = builder.build();
} else {
t = Typeface.createFromAsset(ApplicationLoader.applicationContext.getAssets(), assetPath);
}
typefaceCache.put(assetPath, t);
} catch (Exception e) {
if (BuildVars.LOGS_ENABLED) {
FileLog.e("Could not get typeface '" + assetPath + "' because " + e.getMessage());
}
return null;
}
}
return typefaceCache.get(assetPath);
}
}
public static boolean isWaitingForSms() {
boolean value;
synchronized (smsLock) {
value = waitingForSms;
}
return value;
}
public static void setWaitingForSms(boolean value) {
}
public static int getShadowHeight() {
if (density >= 4.0f) {
return 3;
} else if (density >= 2.0f) {
return 2;
} else {
return 1;
}
}
public static boolean isWaitingForCall() {
boolean value;
synchronized (callLock) {
value = waitingForCall;
}
return value;
}
private static CallReceiver callReceiver;
public static void setWaitingForCall(boolean value) {
synchronized (callLock) {
try {
if (value) {
if (callReceiver == null) {
final IntentFilter filter = new IntentFilter(TelephonyManager.ACTION_PHONE_STATE_CHANGED);
ApplicationLoader.applicationContext.registerReceiver(callReceiver = new CallReceiver(), filter);
}
} else {
if (callReceiver != null) {
ApplicationLoader.applicationContext.unregisterReceiver(callReceiver);
callReceiver = null;
}
}
} catch (Exception ignore) {
}
waitingForCall = value;
}
}
public static boolean showKeyboard(View view) {
if (view == null) {
return false;
}
try {
InputMethodManager inputManager = (InputMethodManager) view.getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
return inputManager.showSoftInput(view, InputMethodManager.SHOW_IMPLICIT);
} catch (Exception e) {
FileLog.e(e);
}
return false;
}
public static String[] getCurrentKeyboardLanguage() {
try {
InputMethodManager inputManager = (InputMethodManager) ApplicationLoader.applicationContext.getSystemService(Context.INPUT_METHOD_SERVICE);
InputMethodSubtype inputMethodSubtype = inputManager.getCurrentInputMethodSubtype();
String locale = null;
if (inputMethodSubtype != null) {
if (Build.VERSION.SDK_INT >= 24) {
locale = inputMethodSubtype.getLanguageTag();
}
if (TextUtils.isEmpty(locale)) {
locale = inputMethodSubtype.getLocale();
}
} else {
inputMethodSubtype = inputManager.getLastInputMethodSubtype();
if (inputMethodSubtype != null) {
if (Build.VERSION.SDK_INT >= 24) {
locale = inputMethodSubtype.getLanguageTag();
}
if (TextUtils.isEmpty(locale)) {
locale = inputMethodSubtype.getLocale();
}
}
}
if (TextUtils.isEmpty(locale)) {
locale = LocaleController.getSystemLocaleStringIso639();
String locale2;
LocaleController.LocaleInfo localeInfo = LocaleController.getInstance().getCurrentLocaleInfo();
locale2 = localeInfo.getBaseLangCode();
if (TextUtils.isEmpty(locale2)) {
locale2 = localeInfo.getLangCode();
}
if (locale.contains(locale2) || locale2.contains(locale)) {
if (!locale.contains("en")) {
locale2 = "en";
} else {
locale2 = null;
}
}
if (!TextUtils.isEmpty(locale2)) {
return new String[]{locale.replace('_', '-'), locale2, "en"};
} else {
return new String[]{locale.replace('_', '-'), "en"};
}
} else {
return new String[]{locale.replace('_', '-'), "en"};
}
} catch (Exception ignore) {
}
return new String[]{"en"};
}
public static void hideKeyboard(View view) {
if (view == null) {
return;
}
try {
InputMethodManager imm = (InputMethodManager) view.getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
if (!imm.isActive()) {
return;
}
imm.hideSoftInputFromWindow(view.getWindowToken(), 0);
} catch (Exception e) {
FileLog.e(e);
}
}
public static ArrayList<File> getDataDirs() {
ArrayList<File> result = null;
if (Build.VERSION.SDK_INT >= 19) {
File[] dirs = ApplicationLoader.applicationContext.getExternalFilesDirs(null);
if (dirs != null) {
for (int a = 0; a < dirs.length; a++) {
if (dirs[a] == null) {
continue;
}
String path = dirs[a].getAbsolutePath();
if (result == null) {
result = new ArrayList<>();
}
result.add(dirs[a]);
}
}
}
if (result == null) {
result = new ArrayList<>();
}
if (result.isEmpty()) {
result.add(Environment.getExternalStorageDirectory());
}
return result;
}
public static ArrayList<File> getRootDirs() {
ArrayList<File> result = null;
if (Build.VERSION.SDK_INT >= 19) {
File[] dirs = ApplicationLoader.applicationContext.getExternalFilesDirs(null);
if (dirs != null) {
for (int a = 0; a < dirs.length; a++) {
if (dirs[a] == null) {
continue;
}
String path = dirs[a].getAbsolutePath();
int idx = path.indexOf("/Android");
if (idx >= 0) {
if (result == null) {
result = new ArrayList<>();
}
result.add(new File(path.substring(0, idx)));
}
}
}
}
if (result == null) {
result = new ArrayList<>();
}
return result;
}
public static File getCacheDir() {
try {
File file = new File(EnvUtil.getTelegramPath(), "caches");
FileUtil.initDir(file);
return file;
} catch (Throwable e) {
FileLog.e(e);
}
return new File(ApplicationLoader.getDataDirFixed(), "cache/media/caches");
}
public static int dp(float value) {
if (value == 0) {
return 0;
}
return (int) Math.ceil(density * value);
}
public static int dpr(float value) {
if (value == 0) {
return 0;
}
return Math.round(density * value);
}
public static int dp2(float value) {
if (value == 0) {
return 0;
}
return (int) Math.floor(density * value);
}
public static int compare(int lhs, int rhs) {
if (lhs == rhs) {
return 0;
} else if (lhs > rhs) {
return 1;
}
return -1;
}
public static float dpf2(float value) {
if (value == 0) {
return 0;
}
return density * value;
}
public static void checkDisplaySize(Context context, Configuration newConfiguration) {
try {
float oldDensity = density;
density = context.getResources().getDisplayMetrics().density;
float newDensity = density;
if (firstConfigurationWas && Math.abs(oldDensity - newDensity) > 0.001) {
Theme.reloadAllResources(context);
}
firstConfigurationWas = true;
Configuration configuration = newConfiguration;
if (configuration == null) {
configuration = context.getResources().getConfiguration();
}
usingHardwareInput = configuration.keyboard != Configuration.KEYBOARD_NOKEYS && configuration.hardKeyboardHidden == Configuration.HARDKEYBOARDHIDDEN_NO;
WindowManager manager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
if (manager != null) {
Display display = manager.getDefaultDisplay();
if (display != null) {
display.getMetrics(displayMetrics);
display.getSize(displaySize);
screenRefreshRate = display.getRefreshRate();
}
}
if (configuration.screenWidthDp != Configuration.SCREEN_WIDTH_DP_UNDEFINED) {
int newSize = (int) Math.ceil(configuration.screenWidthDp * density);
if (Math.abs(displaySize.x - newSize) > 3) {
displaySize.x = newSize;
}
}
if (configuration.screenHeightDp != Configuration.SCREEN_HEIGHT_DP_UNDEFINED) {
int newSize = (int) Math.ceil(configuration.screenHeightDp * density);
if (Math.abs(displaySize.y - newSize) > 3) {
displaySize.y = newSize;
}
}
if (roundMessageSize == 0) {
if (AndroidUtilities.isTablet()) {
roundMessageSize = (int) (AndroidUtilities.getMinTabletSide() * 0.6f);
} else {
roundMessageSize = (int) (Math.min(AndroidUtilities.displaySize.x, AndroidUtilities.displaySize.y) * 0.6f);
}
roundMessageInset = dp(2);
}
if (BuildVars.LOGS_ENABLED) {
FileLog.e("density = " + density + " display size = " + displaySize.x + " " + displaySize.y + " " + displayMetrics.xdpi + "x" + displayMetrics.ydpi);
}
} catch (Exception e) {
FileLog.e(e);
}
}
public static double fixLocationCoord(double value) {
return ((long) (value * 1000000)) / 1000000.0;
}
public static String formapMapUrl(boolean isSecretChat, double lat, double lon, int width, int height, boolean marker, int zoom) {
int scale = Math.min(2, (int) Math.ceil(AndroidUtilities.density));
int provider = 2;
if (isSecretChat) {
if (SharedConfig.mapPreviewType == 1) {
provider = 1;
}
} else {
if (NekoConfig.mapPreviewProvider == 1) {
provider = 1;
}
}
if (provider == 1 || provider == 3) {
String lang = null;
String[] availableLangs = new String[]{"ru_RU", "tr_TR"};
LocaleController.LocaleInfo localeInfo = LocaleController.getInstance().getCurrentLocaleInfo();
for (int a = 0; a < availableLangs.length; a++) {
if (availableLangs[a].toLowerCase().contains(localeInfo.shortName)) {
lang = availableLangs[a];
}
}
if (lang == null) {
lang = "en_US";
}
if (marker) {
return String.format(Locale.US, "https://static-maps.yandex.ru/1.x/?ll=%.6f,%.6f&z=%d&size=%d,%d&l=map&scale=%d&pt=%.6f,%.6f,vkbkm&lang=%s", lon, lat, zoom, width * scale, height * scale, scale, lon, lat, lang);
} else {
return String.format(Locale.US, "https://static-maps.yandex.ru/1.x/?ll=%.6f,%.6f&z=%d&size=%d,%d&l=map&scale=%d&lang=%s", lon, lat, zoom, width * scale, height * scale, scale, lang);
}
} else {
String k = "";
if (!TextUtils.isEmpty(k)) {
if (marker) {
return String.format(Locale.US, "https://maps.googleapis.com/maps/api/staticmap?center=%.6f,%.6f&zoom=%d&size=%dx%d&maptype=roadmap&scale=%d&markers=color:red%%7Csize:mid%%7C%.6f,%.6f&sensor=false&key=%s", lat, lon, zoom, width, height, scale, lat, lon, k);
} else {
return String.format(Locale.US, "https://maps.googleapis.com/maps/api/staticmap?center=%.6f,%.6f&zoom=%d&size=%dx%d&maptype=roadmap&scale=%d&key=%s", lat, lon, zoom, width, height, scale, k);
}
} else {
if (marker) {
return String.format(Locale.US, "https://maps.googleapis.com/maps/api/staticmap?center=%.6f,%.6f&zoom=%d&size=%dx%d&maptype=roadmap&scale=%d&markers=color:red%%7Csize:mid%%7C%.6f,%.6f&sensor=false", lat, lon, zoom, width, height, scale, lat, lon);
} else {
return String.format(Locale.US, "https://maps.googleapis.com/maps/api/staticmap?center=%.6f,%.6f&zoom=%d&size=%dx%d&maptype=roadmap&scale=%d", lat, lon, zoom, width, height, scale);
}
}
}
}
public static float getPixelsInCM(float cm, boolean isX) {
return (cm / 2.54f) * (isX ? displayMetrics.xdpi : displayMetrics.ydpi);
}
public static int getMyLayerVersion(int layer) {
return layer & 0xffff;
}
public static int getPeerLayerVersion(int layer) {
return (layer >> 16) & 0xffff;
}
public static int setMyLayerVersion(int layer, int version) {
return layer & 0xffff0000 | version;
}
public static int setPeerLayerVersion(int layer, int version) {
return layer & 0x0000ffff | (version << 16);
}
public static void runOnUIThread(Runnable runnable) {
runOnUIThread(runnable, 0);
}
public static void runOnUIThread(Runnable runnable, long delay) {
if (ApplicationLoader.applicationHandler == null) return;
if (delay == 0) {
ApplicationLoader.applicationHandler.post(runnable);
} else {
ApplicationLoader.applicationHandler.postDelayed(runnable, delay);
}
}
public static void cancelRunOnUIThread(Runnable runnable) {
ApplicationLoader.applicationHandler.removeCallbacks(runnable);
}
public static boolean isTablet() {
if (isTablet == null) switch (NekoConfig.tabletMode) {
case 0:
isTablet = ApplicationLoader.applicationContext.getResources().getBoolean(R.bool.isTablet);
break;
case 1:
isTablet = true;
break;
case 2:
isTablet = false;
break;
}
return isTablet;
}
public static boolean isSmallTablet() {
float minSide = Math.min(displaySize.x, displaySize.y) / density;
return minSide <= 700;
}
public static int getMinTabletSide() {
if (!isSmallTablet()) {
int smallSide = Math.min(displaySize.x, displaySize.y);
int leftSide = smallSide * 35 / 100;
if (leftSide < dp(320)) {
leftSide = dp(320);
}
return smallSide - leftSide;
} else {
int smallSide = Math.min(displaySize.x, displaySize.y);
int maxSide = Math.max(displaySize.x, displaySize.y);
int leftSide = maxSide * 35 / 100;
if (leftSide < dp(320)) {
leftSide = dp(320);
}
return Math.min(smallSide, maxSide - leftSide);
}
}
public static int getPhotoSize() {
if (photoSize == null) {
photoSize = 1280;
}
return photoSize;
}
/*public static void clearCursorDrawable(EditText editText) {
if (editText == null) {
return;
}
try {
Field mCursorDrawableRes = TextView.class.getDeclaredField("mCursorDrawableRes");
mCursorDrawableRes.setAccessible(true);
mCursorDrawableRes.setInt(editText, 0);
} catch (Exception e) {
FileLog.e(e);
}
}*/
private static Runnable unregisterRunnable;
private static boolean hasCallPermissions = Build.VERSION.SDK_INT >= 23;
@SuppressWarnings("unchecked")
public static void endIncomingCall() {
if (!hasCallPermissions) {
return;
}
try {
TelephonyManager tm = (TelephonyManager) ApplicationLoader.applicationContext.getSystemService(Context.TELEPHONY_SERVICE);
Class c = Class.forName(tm.getClass().getName());
Method m = c.getDeclaredMethod("getITelephony");
m.setAccessible(true);
ITelephony telephonyService = (ITelephony) m.invoke(tm);
telephonyService = (ITelephony) m.invoke(tm);
telephonyService.silenceRinger();
telephonyService.endCall();
} catch (Throwable e) {
FileLog.e(e);
}
}
public static String obtainLoginPhoneCall(String pattern) {
if (!hasCallPermissions) {
return null;
}
try (Cursor cursor = ApplicationLoader.applicationContext.getContentResolver().query(
CallLog.Calls.CONTENT_URI,
new String[]{CallLog.Calls.NUMBER, CallLog.Calls.DATE},
CallLog.Calls.TYPE + " IN (" + CallLog.Calls.MISSED_TYPE + "," + CallLog.Calls.INCOMING_TYPE + "," + CallLog.Calls.REJECTED_TYPE + ")",
null,
"date DESC LIMIT 5")) {
while (cursor.moveToNext()) {
String number = cursor.getString(0);
long date = cursor.getLong(1);
if (BuildVars.LOGS_ENABLED) {
FileLog.e("number = " + number);
}
if (Math.abs(System.currentTimeMillis() - date) >= 60 * 60 * 1000) {
continue;
}
if (checkPhonePattern(pattern, number)) {
return number;
}
}
} catch (Exception e) {
FileLog.e(e);
}
return null;
}
public static boolean checkPhonePattern(String pattern, String phone) {
if (TextUtils.isEmpty(pattern) || pattern.equals("*")) {
return true;
}
String[] args = pattern.split("\\*");
phone = PhoneFormat.stripExceptNumbers(phone);
int checkStart = 0;
int index;
for (int a = 0; a < args.length; a++) {
String arg = args[a];
if (!TextUtils.isEmpty(arg)) {
if ((index = phone.indexOf(arg, checkStart)) == -1) {
return false;
}
checkStart = index + arg.length();
}
}
return true;
}
private static Field mAttachInfoField;
private static Field mStableInsetsField;
public static int getViewInset(View view) {
if (view == null || Build.VERSION.SDK_INT < 21 || view.getHeight() == AndroidUtilities.displaySize.y || view.getHeight() == AndroidUtilities.displaySize.y - statusBarHeight) {
return 0;
}
try {
if (Build.VERSION.SDK_INT >= 23) {
WindowInsets insets = view.getRootWindowInsets();
return insets != null ? insets.getStableInsetBottom() : 0;
} else {
if (mAttachInfoField == null) {
mAttachInfoField = View.class.getDeclaredField("mAttachInfo");
mAttachInfoField.setAccessible(true);
}
Object mAttachInfo = mAttachInfoField.get(view);
if (mAttachInfo != null) {
if (mStableInsetsField == null) {
mStableInsetsField = mAttachInfo.getClass().getDeclaredField("mStableInsets");
mStableInsetsField.setAccessible(true);
}
Rect insets = (Rect) mStableInsetsField.get(mAttachInfo);
return insets.bottom;
}
}
} catch (Exception ignored) {
}
return 0;
}
public static Point getRealScreenSize() {
Point size = new Point();
try {
WindowManager windowManager = (WindowManager) ApplicationLoader.applicationContext.getSystemService(Context.WINDOW_SERVICE);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
windowManager.getDefaultDisplay().getRealSize(size);
} else {
try {
Method mGetRawW = Display.class.getMethod("getRawWidth");
Method mGetRawH = Display.class.getMethod("getRawHeight");
size.set((Integer) mGetRawW.invoke(windowManager.getDefaultDisplay()), (Integer) mGetRawH.invoke(windowManager.getDefaultDisplay()));
} catch (Exception e) {
size.set(windowManager.getDefaultDisplay().getWidth(), windowManager.getDefaultDisplay().getHeight());
FileLog.e(e);
}
}
} catch (Exception e) {
FileLog.e(e);
}
return size;
}
public static void setEnabled(View view, boolean enabled) {
if (view == null) {
return;
}
view.setEnabled(enabled);
if (view instanceof ViewGroup) {
ViewGroup viewGroup = (ViewGroup) view;
for (int i = 0; i < viewGroup.getChildCount(); i++) {
setEnabled(viewGroup.getChildAt(i), enabled);
}
}
}
public static CharSequence getTrimmedString(CharSequence src) {
if (src == null || src.length() == 0) {
return src;
}
while (src.length() > 0 && (src.charAt(0) == '\n' || src.charAt(0) == ' ')) {
src = src.subSequence(1, src.length());
}
while (src.length() > 0 && (src.charAt(src.length() - 1) == '\n' || src.charAt(src.length() - 1) == ' ')) {
src = src.subSequence(0, src.length() - 1);
}
return src;
}
public static void setViewPagerEdgeEffectColor(ViewPager viewPager, int color) {
if (Build.VERSION.SDK_INT >= 21) {
try {
Field field = ViewPager.class.getDeclaredField("mLeftEdge");
field.setAccessible(true);
EdgeEffect mLeftEdge = (EdgeEffect) field.get(viewPager);
if (mLeftEdge != null) {
mLeftEdge.setColor(color);
}
field = ViewPager.class.getDeclaredField("mRightEdge");
field.setAccessible(true);
EdgeEffect mRightEdge = (EdgeEffect) field.get(viewPager);
if (mRightEdge != null) {
mRightEdge.setColor(color);
}
} catch (Exception ignore) {
}
}
}
public static void setScrollViewEdgeEffectColor(HorizontalScrollView scrollView, int color) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
scrollView.setEdgeEffectColor(color);
} else if (Build.VERSION.SDK_INT >= 21) {
try {
Field field = HorizontalScrollView.class.getDeclaredField("mEdgeGlowLeft");
field.setAccessible(true);
EdgeEffect mEdgeGlowTop = (EdgeEffect) field.get(scrollView);
if (mEdgeGlowTop != null) {
mEdgeGlowTop.setColor(color);
}
field = HorizontalScrollView.class.getDeclaredField("mEdgeGlowRight");
field.setAccessible(true);
EdgeEffect mEdgeGlowBottom = (EdgeEffect) field.get(scrollView);
if (mEdgeGlowBottom != null) {
mEdgeGlowBottom.setColor(color);
}
} catch (Exception e) {
FileLog.e(e);
}
}
}
public static void setScrollViewEdgeEffectColor(ScrollView scrollView, int color) {
if (Build.VERSION.SDK_INT >= 29) {
scrollView.setTopEdgeEffectColor(color);
scrollView.setBottomEdgeEffectColor(color);
} else if (Build.VERSION.SDK_INT >= 21) {
try {
Field field = ScrollView.class.getDeclaredField("mEdgeGlowTop");
field.setAccessible(true);
EdgeEffect mEdgeGlowTop = (EdgeEffect) field.get(scrollView);
if (mEdgeGlowTop != null) {
mEdgeGlowTop.setColor(color);
}
field = ScrollView.class.getDeclaredField("mEdgeGlowBottom");
field.setAccessible(true);
EdgeEffect mEdgeGlowBottom = (EdgeEffect) field.get(scrollView);
if (mEdgeGlowBottom != null) {
mEdgeGlowBottom.setColor(color);
}
} catch (Exception ignore) {
}
}
}
@SuppressLint("NewApi")
public static void clearDrawableAnimation(View view) {
if (Build.VERSION.SDK_INT < 21 || view == null) {
return;
}
Drawable drawable;
if (view instanceof ListView) {
drawable = ((ListView) view).getSelector();
if (drawable != null) {
drawable.setState(StateSet.NOTHING);
}
} else {
drawable = view.getBackground();
if (drawable != null) {
drawable.setState(StateSet.NOTHING);
drawable.jumpToCurrentState();
}
}
}
public static final int FLAG_TAG_BR = 1;
public static final int FLAG_TAG_BOLD = 2;
public static final int FLAG_TAG_COLOR = 4;
public static final int FLAG_TAG_URL = 8;
public static final int FLAG_TAG_ALL = FLAG_TAG_BR | FLAG_TAG_BOLD | FLAG_TAG_URL;
public static SpannableStringBuilder replaceTags(String str) {
return replaceTags(str, FLAG_TAG_ALL);
}
public static SpannableStringBuilder replaceTags(String str, int flag, Object... args) {
try {
int start;
int end;
StringBuilder stringBuilder = new StringBuilder(str);
if ((flag & FLAG_TAG_BR) != 0) {
while ((start = stringBuilder.indexOf("<br>")) != -1) {
stringBuilder.replace(start, start + 4, "\n");
}
while ((start = stringBuilder.indexOf("<br/>")) != -1) {
stringBuilder.replace(start, start + 5, "\n");
}
}
ArrayList<Integer> bolds = new ArrayList<>();
if ((flag & FLAG_TAG_BOLD) != 0) {
while ((start = stringBuilder.indexOf("<b>")) != -1) {
stringBuilder.replace(start, start + 3, "");
end = stringBuilder.indexOf("</b>");
if (end == -1) {
end = stringBuilder.indexOf("<b>");
}
stringBuilder.replace(end, end + 4, "");
bolds.add(start);
bolds.add(end);
}
while ((start = stringBuilder.indexOf("**")) != -1) {
stringBuilder.replace(start, start + 2, "");
end = stringBuilder.indexOf("**");
if (end >= 0) {
stringBuilder.replace(end, end + 2, "");
bolds.add(start);
bolds.add(end);
}
}
}
if ((flag & FLAG_TAG_URL) != 0) {
while ((start = stringBuilder.indexOf("**")) != -1) {
stringBuilder.replace(start, start + 2, "");
end = stringBuilder.indexOf("**");
if (end >= 0) {
stringBuilder.replace(end, end + 2, "");
bolds.add(start);
bolds.add(end);
}
}
}
SpannableStringBuilder spannableStringBuilder = new SpannableStringBuilder(stringBuilder);
for (int a = 0; a < bolds.size() / 2; a++) {
spannableStringBuilder.setSpan(new TypefaceSpan(AndroidUtilities.getTypeface("fonts/rmedium.ttf")), bolds.get(a * 2), bolds.get(a * 2 + 1), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
}
return spannableStringBuilder;
} catch (Exception e) {
FileLog.e(e);
}
return new SpannableStringBuilder(str);
}
public static class LinkMovementMethodMy extends LinkMovementMethod {
@Override
public boolean onTouchEvent(TextView widget, Spannable buffer, MotionEvent event) {
try {
boolean result = super.onTouchEvent(widget, buffer, event);
if (event.getAction() == MotionEvent.ACTION_UP || event.getAction() == MotionEvent.ACTION_CANCEL) {
Selection.removeSelection(buffer);
}
return result;
} catch (Exception e) {
FileLog.e(e);
}
return false;
}
}
public static boolean needShowPasscode() {
return needShowPasscode(false);
}
public static boolean needShowPasscode(boolean reset) {
boolean wasInBackground = ForegroundDetector.getInstance().isWasInBackground(reset);
if (reset) {
ForegroundDetector.getInstance().resetBackgroundVar();
}
int uptime = (int) (SystemClock.elapsedRealtime() / 1000);
if (BuildVars.LOGS_ENABLED && reset && SharedConfig.passcodeHash.length() > 0) {
FileLog.d("wasInBackground = " + wasInBackground + " appLocked = " + SharedConfig.appLocked + " autoLockIn = " + SharedConfig.autoLockIn + " lastPauseTime = " + SharedConfig.lastPauseTime + " uptime = " + uptime);
}
return SharedConfig.passcodeHash.length() > 0 && wasInBackground &&
(SharedConfig.appLocked ||
SharedConfig.autoLockIn != 0 && SharedConfig.lastPauseTime != 0 && !SharedConfig.appLocked && (SharedConfig.lastPauseTime + SharedConfig.autoLockIn) <= uptime ||
uptime + 5 < SharedConfig.lastPauseTime);
}
public static void shakeView(final View view, final float x, final int num) {
if (view == null) {
return;
}
if (num == 6) {
view.setTranslationX(0);
return;
}
AnimatorSet animatorSet = new AnimatorSet();
animatorSet.playTogether(ObjectAnimator.ofFloat(view, "translationX", dp(x)));
animatorSet.setDuration(50);
animatorSet.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
shakeView(view, num == 5 ? 0 : -x, num + 1);
}
});
animatorSet.start();
}
/*public static String ellipsize(String text, int maxLines, int maxWidth, TextPaint paint) {
if (text == null || paint == null) {
return null;
}
int count;
int offset = 0;
StringBuilder result = null;
TextView
for (int a = 0; a < maxLines; a++) {
count = paint.breakText(text, true, maxWidth, null);
if (a != maxLines - 1) {
if (result == null) {
result = new StringBuilder(count * maxLines + 1);
}
boolean foundSpace = false;
for (int c = count - 1; c >= offset; c--) {
if (text.charAt(c) == ' ') {
foundSpace = true;
result.append(text.substring(offset, c - 1));
offset = c - 1;
}
}
if (!foundSpace) {
offset = count;
}
text = text.substring(0, offset);
} else if (maxLines == 1) {
return text.substring(0, count);
} else {
result.append(text.substring(0, count));
}
}
return result.toString();
}*/
/*public static void turnOffHardwareAcceleration(Window window) {
if (window == null || Build.MODEL == null) {
return;
}
if (Build.MODEL.contains("GT-S5301") ||
Build.MODEL.contains("GT-S5303") ||
Build.MODEL.contains("GT-B5330") ||
Build.MODEL.contains("GT-S5302") ||
Build.MODEL.contains("GT-S6012B") ||
Build.MODEL.contains("MegaFon_SP-AI")) {
window.clearFlags(WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED);
}
}*/
public static void startAppCenter(Activity context) {
}
private static long lastUpdateCheckTime;
public static void checkForUpdates() {
}
public static void addToClipboard(CharSequence str) {
try {
android.content.ClipboardManager clipboard = (android.content.ClipboardManager) ApplicationLoader.applicationContext.getSystemService(Context.CLIPBOARD_SERVICE);
android.content.ClipData clip = android.content.ClipData.newPlainText("label", str);
clipboard.setPrimaryClip(clip);
} catch (Exception e) {
FileLog.e(e);
}
}
public static void addMediaToGallery(String fromPath) {
if (fromPath == null) {
return;
}
File f = new File(fromPath);
Uri contentUri = Uri.fromFile(f);
addMediaToGallery(contentUri);
}
public static void addMediaToGallery(Uri uri) {
if (uri == null) {
return;
}
try {
Intent mediaScanIntent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);
mediaScanIntent.setData(uri);
ApplicationLoader.applicationContext.sendBroadcast(mediaScanIntent);
} catch (Exception e) {
FileLog.e(e);
}
}
private static File getAlbumDir(boolean secretChat) {
if (secretChat || Build.VERSION.SDK_INT >= 23 && ApplicationLoader.applicationContext.checkSelfPermission(android.Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
return FileLoader.getDirectory(FileLoader.MEDIA_DIR_CACHE);
}
File storageDir = null;
if (Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState())) {
storageDir = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES), "NekoX");
if (!storageDir.mkdirs()) {
if (!storageDir.exists()) {
if (BuildVars.LOGS_ENABLED) {
FileLog.d("failed to create directory");
}
return null;
}
}
} else {
if (BuildVars.LOGS_ENABLED) {
FileLog.d("External storage is not mounted READ/WRITE.");
}
}
return storageDir;
}
@SuppressLint("NewApi")
public static String getPath(final Uri uri) {
try {
final boolean isKitKat = Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT;
if (isKitKat && DocumentsContract.isDocumentUri(ApplicationLoader.applicationContext, uri)) {
if (isExternalStorageDocument(uri)) {
final String docId = DocumentsContract.getDocumentId(uri);
final String[] split = docId.split(":");
final String type = split[0];
if ("primary".equalsIgnoreCase(type)) {
return Environment.getExternalStorageDirectory() + "/" + split[1];
}
} else if (isDownloadsDocument(uri)) {
final String id = DocumentsContract.getDocumentId(uri);
final Uri contentUri = ContentUris.withAppendedId(Uri.parse("content://downloads/public_downloads"), Long.valueOf(id));
return getDataColumn(ApplicationLoader.applicationContext, contentUri, null, null);
} else if (isMediaDocument(uri)) {
final String docId = DocumentsContract.getDocumentId(uri);
final String[] split = docId.split(":");
final String type = split[0];
Uri contentUri = null;
switch (type) {
case "image":
contentUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
break;
case "video":
contentUri = MediaStore.Video.Media.EXTERNAL_CONTENT_URI;
break;
case "audio":
contentUri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;
break;
}
final String selection = "_id=?";
final String[] selectionArgs = new String[]{
split[1]
};
return getDataColumn(ApplicationLoader.applicationContext, contentUri, selection, selectionArgs);
}
} else if ("content".equalsIgnoreCase(uri.getScheme())) {
return getDataColumn(ApplicationLoader.applicationContext, uri, null, null);
} else if ("file".equalsIgnoreCase(uri.getScheme())) {
return uri.getPath();
}
} catch (Exception e) {
FileLog.e(e);
}
return null;
}
public static String getDataColumn(Context context, Uri uri, String selection, String[] selectionArgs) {
final String column = "_data";
final String[] projection = {
column
};
try (Cursor cursor = context.getContentResolver().query(uri, projection, selection, selectionArgs, null)) {
if (cursor != null && cursor.moveToFirst()) {
final int column_index = cursor.getColumnIndexOrThrow(column);
String value = cursor.getString(column_index);
if (value.startsWith("content://") || !value.startsWith("/") && !value.startsWith("file://")) {
return null;
}
return value;
}
} catch (Exception ignore) {
}
return null;
}
public static boolean isExternalStorageDocument(Uri uri) {
return "com.android.externalstorage.documents".equals(uri.getAuthority());
}
public static boolean isDownloadsDocument(Uri uri) {
return "com.android.providers.downloads.documents".equals(uri.getAuthority());
}
public static boolean isMediaDocument(Uri uri) {
return "com.android.providers.media.documents".equals(uri.getAuthority());
}
public static File generatePicturePath() {
return generatePicturePath(false, null);
}
public static File generatePicturePath(boolean secretChat, String ext) {
try {
File storageDir = getAlbumDir(secretChat);
Date date = new Date();
date.setTime(System.currentTimeMillis() + Utilities.random.nextInt(1000) + 1);
String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss_SSS", Locale.US).format(date);
return new File(storageDir, "IMG_" + timeStamp + "." + (TextUtils.isEmpty(ext) ? "jpg" : ext));
} catch (Exception e) {
FileLog.e(e);
}
return null;
}
public static CharSequence generateSearchName(String name, String name2, String q) {
if (name == null && name2 == null || TextUtils.isEmpty(q)) {
return "";
}
SpannableStringBuilder builder = new SpannableStringBuilder();
String wholeString = name;
if (wholeString == null || wholeString.length() == 0) {
wholeString = name2;
} else if (name2 != null && name2.length() != 0) {
wholeString += " " + name2;
}
wholeString = wholeString.trim();
String lower = " " + wholeString.toLowerCase();
int index;
int lastIndex = 0;
while ((index = lower.indexOf(" " + q, lastIndex)) != -1) {
int idx = index - (index == 0 ? 0 : 1);
int end = q.length() + (index == 0 ? 0 : 1) + idx;
if (lastIndex != 0 && lastIndex != idx + 1) {
builder.append(wholeString.substring(lastIndex, idx));
} else if (lastIndex == 0 && idx != 0) {
builder.append(wholeString.substring(0, idx));
}
String query = wholeString.substring(idx, Math.min(wholeString.length(), end));
if (query.startsWith(" ")) {
builder.append(" ");
}
query = query.trim();
int start = builder.length();
builder.append(query);
builder.setSpan(new ForegroundColorSpanThemable(Theme.key_windowBackgroundWhiteBlueText4), start, start + query.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
lastIndex = end;
}
if (lastIndex != -1 && lastIndex < wholeString.length()) {
builder.append(wholeString.substring(lastIndex));
}
return builder;
}
public static boolean isAirplaneModeOn() {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN_MR1) {
return Settings.System.getInt(ApplicationLoader.applicationContext.getContentResolver(), Settings.System.AIRPLANE_MODE_ON, 0) != 0;
} else {
return Settings.Global.getInt(ApplicationLoader.applicationContext.getContentResolver(), Settings.Global.AIRPLANE_MODE_ON, 0) != 0;
}
}
public static File generateVideoPath() {
return generateVideoPath(false);
}
public static File generateVideoPath(boolean secretChat) {
try {
File storageDir = getAlbumDir(secretChat);
Date date = new Date();
date.setTime(System.currentTimeMillis() + Utilities.random.nextInt(1000) + 1);
String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss_SSS", Locale.US).format(date);
return new File(storageDir, "VID_" + timeStamp + ".mp4");
} catch (Exception e) {
FileLog.e(e);
}
return null;
}
public static String formatFileSize(long size) {
return formatFileSize(size, false);
}
public static String formatFileSize(long size, boolean removeZero) {
if (size < 1024) {
return String.format("%d B", size);
} else if (size < 1024 * 1024) {
float value = size / 1024.0f;
if (removeZero && (value - (int) value) * 10 == 0) {
return String.format("%d KB", (int) value);
} else {
return String.format("%.1f KB", value);
}
} else if (size < 1024 * 1024 * 1024) {
float value = size / 1024.0f / 1024.0f;
if (removeZero && (value - (int) value) * 10 == 0) {
return String.format("%d MB", (int) value);
} else {
return String.format("%.1f MB", value);
}
} else {
float value = size / 1024.0f / 1024.0f / 1024.0f;
if (removeZero && (value - (int) value) * 10 == 0) {
return String.format("%d GB", (int) value);
} else {
return String.format("%.1f GB", value);
}
}
}
public static String formatShortDuration(int duration) {
return formatDuration(duration, false);
}
public static String formatLongDuration(int duration) {
return formatDuration(duration, true);
}
public static String formatDuration(int duration, boolean isLong) {
int h = duration / 3600;
int m = duration / 60 % 60;
int s = duration % 60;
if (h == 0) {
if (isLong) {
return String.format(Locale.US, "%02d:%02d", m, s);
} else {
return String.format(Locale.US, "%d:%02d", m, s);
}
} else {
return String.format(Locale.US, "%d:%02d:%02d", h, m, s);
}
}
public static String formatDurationNoHours(int duration, boolean isLong) {
int m = duration / 60;
int s = duration % 60;
if (isLong) {
return String.format(Locale.US, "%02d:%02d", m, s);
} else {
return String.format(Locale.US, "%d:%02d", m, s);
}
}
public static String formatShortDuration(int progress, int duration) {
return formatDuration(progress, duration, false);
}
public static String formatLongDuration(int progress, int duration) {
return formatDuration(progress, duration, true);
}
public static String formatDuration(int progress, int duration, boolean isLong) {
int h = duration / 3600;
int m = duration / 60 % 60;
int s = duration % 60;
int ph = progress / 3600;
int pm = progress / 60 % 60;
int ps = progress % 60;
if (duration == 0) {
if (ph == 0) {
if (isLong) {
return String.format(Locale.US, "%02d:%02d / -:--", pm, ps);
} else {
return String.format(Locale.US, "%d:%02d / -:--", pm, ps);
}
} else {
return String.format(Locale.US, "%d:%02d:%02d / -:--", ph, pm, ps);
}
} else {
if (ph == 0 && h == 0) {
if (isLong) {
return String.format(Locale.US, "%02d:%02d / %02d:%02d", pm, ps, m, s);
} else {
return String.format(Locale.US, "%d:%02d / %d:%02d", pm, ps, m, s);
}
} else {
return String.format(Locale.US, "%d:%02d:%02d / %d:%02d:%02d", ph, pm, ps, h, m, s);
}
}
}
public static String formatVideoDuration(int progress, int duration) {
int h = duration / 3600;
int m = duration / 60 % 60;
int s = duration % 60;
int ph = progress / 3600;
int pm = progress / 60 % 60;
int ps = progress % 60;
if (ph == 0 && h == 0) {
return String.format(Locale.US, "%02d:%02d / %02d:%02d", pm, ps, m, s);
} else {
if (h == 0) {
return String.format(Locale.US, "%d:%02d:%02d / %02d:%02d", ph, pm, ps, m, s);
} else if (ph == 0) {
return String.format(Locale.US, "%02d:%02d / %d:%02d:%02d", pm, ps, h, m, s);
} else {
return String.format(Locale.US, "%d:%02d:%02d / %d:%02d:%02d", ph, pm, ps, h, m, s);
}
}
}
public static String formatCount(int count) {
if (count < 1000) return Integer.toString(count);
ArrayList<String> strings = new ArrayList<>();
while (count != 0) {
int mod = count % 1000;
count /= 1000;
if (count > 0) {
strings.add(String.format(Locale.ENGLISH, "%03d", mod));
} else {
strings.add(Integer.toString(mod));
}
}
StringBuilder stringBuilder = new StringBuilder();
for (int i = strings.size() - 1; i >= 0; i--) {
stringBuilder.append(strings.get(i));
if (i != 0) {
stringBuilder.append(",");
}
}
return stringBuilder.toString();
}
public static final String[] numbersSignatureArray = {"", "K", "M", "G", "T", "P"};
public static String formatWholeNumber(int v, int dif) {
if (v == 0) {
return "0";
}
float num_ = v;
int count = 0;
if (dif == 0) dif = v;
if (dif < 1000) {
return AndroidUtilities.formatCount(v);
}
while (dif >= 1000 && count < numbersSignatureArray.length - 1) {
dif /= 1000;
num_ /= 1000;
count++;
}
if (num_ < 0.1) {
return "0";
} else {
if ((num_ * 10) == (int) (num_ * 10)) {
return String.format(Locale.ENGLISH, "%s%s", AndroidUtilities.formatCount((int) num_), numbersSignatureArray[count]);
} else {
return String.format(Locale.ENGLISH, "%.1f%s", (int) (num_ * 10) / 10f, numbersSignatureArray[count]);
}
}
}
public static byte[] decodeQuotedPrintable(final byte[] bytes) {
if (bytes == null) {
return null;
}
final ByteArrayOutputStream buffer = new ByteArrayOutputStream();
for (int i = 0; i < bytes.length; i++) {
final int b = bytes[i];
if (b == '=') {
try {
final int u = Character.digit((char) bytes[++i], 16);
final int l = Character.digit((char) bytes[++i], 16);
buffer.write((char) ((u << 4) + l));
} catch (Exception e) {
FileLog.e(e);
return null;
}
} else {
buffer.write(b);
}
}
byte[] array = buffer.toByteArray();
try {
buffer.close();
} catch (Exception e) {
FileLog.e(e);
}
return array;
}
public static boolean copyFile(InputStream sourceFile, File destFile) throws IOException {
OutputStream out = new FileOutputStream(destFile);
byte[] buf = new byte[4096];
int len;
while ((len = sourceFile.read(buf)) > 0) {
Thread.yield();
out.write(buf, 0, len);
}
out.close();
return true;
}
public static boolean copyFile(File sourceFile, File destFile) throws IOException {
if (sourceFile.equals(destFile)) {
return true;
}
if (!destFile.exists()) {
destFile.createNewFile();
}
try (FileInputStream source = new FileInputStream(sourceFile); FileOutputStream destination = new FileOutputStream(destFile)) {
destination.getChannel().transferFrom(source.getChannel(), 0, source.getChannel().size());
} catch (Exception e) {
FileLog.e(e);
return false;
}
return true;
}
public static byte[] calcAuthKeyHash(byte[] auth_key) {
byte[] sha1 = Utilities.computeSHA1(auth_key);
byte[] key_hash = new byte[16];
System.arraycopy(sha1, 0, key_hash, 0, 16);
return key_hash;
}
public static void openDocument(MessageObject message, Activity activity, BaseFragment parentFragment) {
if (message == null) {
return;
}
TLRPC.Document document = message.getDocument();
if (document == null) {
return;
}
File f = null;
String fileName = message.messageOwner.media != null ? FileLoader.getAttachFileName(document) : "";
if (message.messageOwner.attachPath != null && message.messageOwner.attachPath.length() != 0) {
f = new File(message.messageOwner.attachPath);
}
if (f == null || f != null && !f.exists()) {
f = FileLoader.getPathToMessage(message.messageOwner);
}
if (f != null && f.exists()) {
if (parentFragment != null && f.getName().toLowerCase().endsWith("attheme")) {
Theme.ThemeInfo themeInfo = Theme.applyThemeFile(f, message.getDocumentName(), null, true);
if (themeInfo != null) {
parentFragment.presentFragment(new ThemePreviewActivity(themeInfo));
} else {
AlertDialog.Builder builder = new AlertDialog.Builder(activity);
builder.setTitle(LocaleController.getString("NekoX", R.string.NekoX));
builder.setMessage(LocaleController.getString("IncorrectTheme", R.string.IncorrectTheme));
builder.setPositiveButton(LocaleController.getString("OK", R.string.OK), null);
parentFragment.showDialog(builder.create());
}
} else {
String realMimeType = null;
try {
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
MimeTypeMap myMime = MimeTypeMap.getSingleton();
int idx = fileName.lastIndexOf('.');
if (idx != -1) {
String ext = fileName.substring(idx + 1);
realMimeType = myMime.getMimeTypeFromExtension(ext.toLowerCase());
if (realMimeType == null) {
realMimeType = document.mime_type;
if (realMimeType == null || realMimeType.length() == 0) {
realMimeType = null;
}
}
}
if (Build.VERSION.SDK_INT >= 24) {
intent.setDataAndType(FileProvider.getUriForFile(activity, BuildConfig.APPLICATION_ID + ".provider", f), realMimeType != null ? realMimeType : "*/*");
} else {
intent.setDataAndType(Uri.fromFile(f), realMimeType != null ? realMimeType : "*/*");
}
if (realMimeType != null) {
try {
activity.startActivityForResult(intent, 500);
} catch (Exception e) {
if (Build.VERSION.SDK_INT >= 24) {
intent.setDataAndType(FileProvider.getUriForFile(activity, BuildConfig.APPLICATION_ID + ".provider", f), "*/*");
} else {
intent.setDataAndType(Uri.fromFile(f), "*/*");
}
activity.startActivityForResult(intent, 500);
}
} else {
activity.startActivityForResult(intent, 500);
}
} catch (Exception e) {
if (activity == null) {
return;
}
AlertDialog.Builder builder = new AlertDialog.Builder(activity);
builder.setTitle(LocaleController.getString("NekoX", R.string.NekoX));
builder.setPositiveButton(LocaleController.getString("OK", R.string.OK), null);
builder.setMessage(LocaleController.formatString("NoHandleAppInstalled", R.string.NoHandleAppInstalled, message.getDocument().mime_type));
if (parentFragment != null) {
parentFragment.showDialog(builder.create());
} else {
builder.show();
}
}
}
}
}
public static boolean openForView(MessageObject message, final Activity activity) {
File f = null;
String fileName = message.getFileName();
if (message.messageOwner.attachPath != null && message.messageOwner.attachPath.length() != 0) {
f = new File(message.messageOwner.attachPath);
}
if (f == null || !f.exists()) {
f = FileLoader.getPathToMessage(message.messageOwner);
}
if (f != null && f.exists()) {
String realMimeType = null;
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
MimeTypeMap myMime = MimeTypeMap.getSingleton();
int idx = fileName.lastIndexOf('.');
if (idx != -1) {
String ext = fileName.substring(idx + 1);
realMimeType = myMime.getMimeTypeFromExtension(ext.toLowerCase());
if (realMimeType == null) {
if (message.type == 9 || message.type == 0) {
realMimeType = message.getDocument().mime_type;
}
if (realMimeType == null || realMimeType.length() == 0) {
realMimeType = null;
}
}
}
if (Build.VERSION.SDK_INT >= 26 && realMimeType != null && realMimeType.equals("application/vnd.android.package-archive") && !ApplicationLoader.applicationContext.getPackageManager().canRequestPackageInstalls()) {
BottomBuilder builder = new BottomBuilder(activity);
builder.addTitle(LocaleController.getString("ApkRestricted", R.string.ApkRestricted));
builder.addItem(LocaleController.getString("PermissionOpenSettings", R.string.PermissionOpenSettings), R.drawable.baseline_settings_24, (i) -> {
try {
activity.startActivity(new Intent(Settings.ACTION_MANAGE_UNKNOWN_APP_SOURCES, Uri.parse("package:" + activity.getPackageName())));
} catch (Exception e) {
FileLog.e(e);
}
return Unit.INSTANCE;
});
builder.addCancelItem();
builder.show();
return true;
}
if (Build.VERSION.SDK_INT >= 24) {
intent.setDataAndType(FileProvider.getUriForFile(activity, BuildConfig.APPLICATION_ID + ".provider", f), realMimeType != null ? realMimeType : "text/plain");
} else {
intent.setDataAndType(Uri.fromFile(f), realMimeType != null ? realMimeType : "text/plain");
}
if (realMimeType != null) {
try {
activity.startActivityForResult(intent, 500);
} catch (Exception e) {
if (Build.VERSION.SDK_INT >= 24) {
intent.setDataAndType(FileProvider.getUriForFile(activity, BuildConfig.APPLICATION_ID + ".provider", f), "text/plain");
} else {
intent.setDataAndType(Uri.fromFile(f), "text/plain");
}
activity.startActivityForResult(intent, 500);
}
} else {
activity.startActivityForResult(intent, 500);
}
return true;
}
return false;
}
public static CharSequence replaceNewLines(CharSequence original) {
if (original instanceof StringBuilder) {
StringBuilder stringBuilder = (StringBuilder) original;
for (int a = 0, N = original.length(); a < N; a++) {
if (original.charAt(a) == '\n') {
stringBuilder.setCharAt(a, ' ');
}
}
} else if (original instanceof SpannableStringBuilder) {
SpannableStringBuilder stringBuilder = (SpannableStringBuilder) original;
for (int a = 0, N = original.length(); a < N; a++) {
if (original.charAt(a) == '\n') {
stringBuilder.replace(a, a + 1, " ");
}
}
}
return original.toString().replace('\n', ' ');
}
public static boolean openForView(TLObject media, Activity activity) {
if (media == null || activity == null) {
return false;
}
String fileName = FileLoader.getAttachFileName(media);
File f = FileLoader.getPathToAttach(media, true);
if (f != null && f.exists()) {
String realMimeType = null;
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
MimeTypeMap myMime = MimeTypeMap.getSingleton();
int idx = fileName.lastIndexOf('.');
if (idx != -1) {
String ext = fileName.substring(idx + 1);
realMimeType = myMime.getMimeTypeFromExtension(ext.toLowerCase());
if (realMimeType == null) {
if (media instanceof TLRPC.TL_document) {
realMimeType = ((TLRPC.TL_document) media).mime_type;
}
if (realMimeType == null || realMimeType.length() == 0) {
realMimeType = null;
}
}
}
if (Build.VERSION.SDK_INT >= 24) {
intent.setDataAndType(FileProvider.getUriForFile(activity, BuildConfig.APPLICATION_ID + ".provider", f), realMimeType != null ? realMimeType : "text/plain");
} else {
intent.setDataAndType(Uri.fromFile(f), realMimeType != null ? realMimeType : "text/plain");
}
if (realMimeType != null) {
try {
activity.startActivityForResult(intent, 500);
} catch (Exception e) {
if (Build.VERSION.SDK_INT >= 24) {
intent.setDataAndType(FileProvider.getUriForFile(activity, BuildConfig.APPLICATION_ID + ".provider", f), "text/plain");
} else {
intent.setDataAndType(Uri.fromFile(f), "text/plain");
}
activity.startActivityForResult(intent, 500);
}
} else {
activity.startActivityForResult(intent, 500);
}
return true;
} else {
return false;
}
}
public static boolean isBannedForever(TLRPC.TL_chatBannedRights rights) {
return rights == null || Math.abs(rights.until_date - System.currentTimeMillis() / 1000) > 5 * 365 * 24 * 60 * 60;
}
public static void setRectToRect(Matrix matrix, RectF src, RectF dst, int rotation, boolean translate) {
float tx, sx;
float ty, sy;
boolean xLarger = false;
if (rotation == 90 || rotation == 270) {
sx = dst.height() / src.width();
sy = dst.width() / src.height();
} else {
sx = dst.width() / src.width();
sy = dst.height() / src.height();
}
if (sx < sy) {
sx = sy;
xLarger = true;
} else {
sy = sx;
}
if (translate) {
matrix.setTranslate(dst.left, dst.top);
}
if (rotation == 90) {
matrix.preRotate(90);
matrix.preTranslate(0, -dst.width());
} else if (rotation == 180) {
matrix.preRotate(180);
matrix.preTranslate(-dst.width(), -dst.height());
} else if (rotation == 270) {
matrix.preRotate(270);
matrix.preTranslate(-dst.height(), 0);
}
if (translate) {
tx = -src.left * sx;
ty = -src.top * sy;
} else {
tx = dst.left - src.left * sx;
ty = dst.top - src.top * sy;
}
float diff;
if (xLarger) {
diff = dst.width() - src.width() * sy;
} else {
diff = dst.height() - src.height() * sy;
}
diff = diff / 2.0f;
if (xLarger) {
tx += diff;
} else {
ty += diff;
}
matrix.preScale(sx, sy);
if (translate) {
matrix.preTranslate(tx, ty);
}
}
public static boolean handleProxyIntent(Activity activity, Intent intent) {
if (intent == null) {
return false;
}
if ((intent.getFlags() & Intent.FLAG_ACTIVITY_LAUNCHED_FROM_HISTORY) != 0) {
return false;
}
Uri data = intent.getData();
if (data == null) return false;
String link = data.toString();
if (link.startsWith("tg://proxy") ||
link.startsWith("tg://socks") ||
link.startsWith("http://t.me/proxy?") ||
link.startsWith("http://t.me/socks?") ||
link.startsWith("https://t.me/proxy?") ||
link.startsWith("https://t.me/socks?") ||
link.startsWith(VMESS_PROTOCOL) ||
link.startsWith(VMESS1_PROTOCOL) ||
link.startsWith(SS_PROTOCOL) ||
link.startsWith(SSR_PROTOCOL) ||
link.startsWith(TROJAN_PROTOCOL)/*||
data.startsWith(RB_PROTOCOL)*/) {
return ProxyUtil.importProxy(activity, link);
}
return false;
}
public static boolean shouldEnableAnimation() {
if (Build.VERSION.SDK_INT < 26 || Build.VERSION.SDK_INT >= 28) {
return true;
}
PowerManager powerManager = (PowerManager) ApplicationLoader.applicationContext.getSystemService(Context.POWER_SERVICE);
if (powerManager.isPowerSaveMode()) {
return false;
}
float scale = Settings.Global.getFloat(ApplicationLoader.applicationContext.getContentResolver(), Settings.Global.ANIMATOR_DURATION_SCALE, 1.0f);
if (scale <= 0.0f) {
return false;
}
return true;
}
public static void showProxyAlert(Context activity, final String address, final String port, final String user, final String password, final String secret, final String remarks) {
BottomSheet.Builder builder = new BottomSheet.Builder(activity);
final Runnable dismissRunnable = builder.getDismissRunnable();
builder.setApplyTopPadding(false);
builder.setApplyBottomPadding(false);
LinearLayout linearLayout = new LinearLayout(activity);
builder.setCustomView(linearLayout);
linearLayout.setOrientation(LinearLayout.VERTICAL);
if (!TextUtils.isEmpty(secret)) {
TextView titleTextView = new TextView(activity);
titleTextView.setText(LocaleController.getString("UseProxyTelegramInfo2", R.string.UseProxyTelegramInfo2));
titleTextView.setTextColor(Theme.getColor(Theme.key_dialogTextGray4));
titleTextView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14);
titleTextView.setGravity(Gravity.TOP | Gravity.CENTER_HORIZONTAL);
linearLayout.addView(titleTextView, LayoutHelper.createLinear(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, (LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.TOP, 17, 8, 17, 8));
View lineView = new View(activity);
lineView.setBackgroundColor(Theme.getColor(Theme.key_divider));
linearLayout.addView(lineView, new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, 1));
}
for (int a = 0; a < 6; a++) {
String text = null;
String detail = null;
if (a == 0) {
text = address;
detail = LocaleController.getString("UseProxyAddress", R.string.UseProxyAddress);
} else if (a == 1) {
text = "" + port;
detail = LocaleController.getString("UseProxyPort", R.string.UseProxyPort);
} else if (a == 2) {
text = secret;
detail = LocaleController.getString("UseProxySecret", R.string.UseProxySecret);
} else if (a == 3) {
text = user;
detail = LocaleController.getString("UseProxyUsername", R.string.UseProxyUsername);
} else if (a == 4) {
text = password;
detail = LocaleController.getString("UseProxyPassword", R.string.UseProxyPassword);
} else {
text = LocaleController.getString("Checking", R.string.Checking);
detail = LocaleController.getString("Checking", R.string.Checking);
}
if (TextUtils.isEmpty(text)) {
continue;
}
TextDetailSettingsCell cell = new TextDetailSettingsCell(activity);
cell.setTextAndValue(text, detail, true);
cell.getTextView().setTextColor(Theme.getColor(Theme.key_dialogTextBlack));
cell.getValueTextView().setTextColor(Theme.getColor(Theme.key_dialogTextGray3));
linearLayout.addView(cell, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT));
if (a == 5) {
ConnectionsManager.getInstance(UserConfig.selectedAccount).checkProxy(address, Utilities.parseInt(port), user, password, secret, time -> AndroidUtilities.runOnUIThread(() -> {
String colorKey;
if (time != -1) {
cell.setTextAndValue(LocaleController.getString("Available", R.string.Available), LocaleController.formatString("Ping", R.string.Ping, time), true);
colorKey = Theme.key_windowBackgroundWhiteGreenText;
} else {
cell.setTextAndValue(LocaleController.getString("Unavailable", R.string.Unavailable), LocaleController.getString("Unavailable", R.string.Unavailable), true);
colorKey = Theme.key_windowBackgroundWhiteRedText4;
}
cell.getValueTextView().setTextColor(Theme.getColor(colorKey));
}));
}
}
PickerBottomLayout pickerBottomLayout = new PickerBottomLayout(activity, false);
pickerBottomLayout.setBackgroundColor(Theme.getColor(Theme.key_dialogBackground));
linearLayout.addView(pickerBottomLayout, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 48, Gravity.LEFT | Gravity.BOTTOM));
pickerBottomLayout.cancelButton.setPadding(AndroidUtilities.dp(18), 0, AndroidUtilities.dp(18), 0);
pickerBottomLayout.cancelButton.setTextColor(Theme.getColor(Theme.key_dialogTextBlue2));
pickerBottomLayout.cancelButton.setText(LocaleController.getString("Cancel", R.string.Cancel).toUpperCase());
pickerBottomLayout.cancelButton.setOnClickListener(view -> dismissRunnable.run());
pickerBottomLayout.doneButtonTextView.setTextColor(Theme.getColor(Theme.key_dialogTextBlue2));
pickerBottomLayout.doneButton.setPadding(AndroidUtilities.dp(18), 0, AndroidUtilities.dp(18), 0);
pickerBottomLayout.doneButtonBadgeTextView.setVisibility(View.GONE);
pickerBottomLayout.middleButtonTextView.setText(LocaleController.getString("Save", R.string.Save).toUpperCase());
pickerBottomLayout.middleButton.setVisibility(View.VISIBLE);
pickerBottomLayout.middleButton.setOnClickListener((it) -> {
int p = Utilities.parseInt(port);
SharedConfig.ProxyInfo info;
if (TextUtils.isEmpty(secret)) {
info = new SharedConfig.ProxyInfo(address, p, user, password, "");
} else {
info = new SharedConfig.ProxyInfo(address, p, "", "", secret);
}
info.setRemarks(remarks);
SharedConfig.addProxy(info);
NotificationCenter.getGlobalInstance().postNotificationName(NotificationCenter.proxySettingsChanged);
dismissRunnable.run();
});
pickerBottomLayout.doneButtonTextView.setText(LocaleController.getString("ConnectingConnectProxy", R.string.ConnectingConnectProxy).toUpperCase());
pickerBottomLayout.doneButton.setOnClickListener(v -> {
int p = Utilities.parseInt(port);
SharedConfig.ProxyInfo info;
if (TextUtils.isEmpty(secret)) {
info = new SharedConfig.ProxyInfo(address, p, user, password, "");
} else {
info = new SharedConfig.ProxyInfo(address, p, "", "", secret);
}
info.setRemarks(remarks);
SharedConfig.setCurrentProxy(SharedConfig.addProxy(info));
NotificationCenter.getGlobalInstance().postNotificationName(NotificationCenter.proxySettingsChanged);
dismissRunnable.run();
});
builder.show();
}
public static void showVmessAlert(Context activity, final SharedConfig.VmessProxy info) {
BottomSheet.Builder builder = new BottomSheet.Builder(activity);
final Runnable dismissRunnable = builder.getDismissRunnable();
builder.setApplyTopPadding(false);
builder.setApplyBottomPadding(false);
LinearLayout linearLayout = new LinearLayout(activity);
builder.setCustomView(linearLayout);
linearLayout.setOrientation(LinearLayout.VERTICAL);
for (int a = 0; a < 8; a++) {
String text = null;
String detail = null;
if (a == 0) {
text = info.bean.getAddress();
detail = LocaleController.getString("UseProxyAddress", R.string.UseProxyAddress);
} else if (a == 1) {
text = "" + info.bean.getPort();
detail = LocaleController.getString("UseProxyPort", R.string.UseProxyPort);
} else if (a == 2) {
text = info.bean.getId();
detail = LocaleController.getString("VmessUserId", R.string.VmessUserId);
} else if (a == 3) {
text = info.bean.getSecurity();
if ("none".equals(text)) continue;
detail = LocaleController.getString("VmessSecurity", R.string.VmessSecurity);
} else if (a == 4) {
text = info.bean.getNetwork() + (StrUtil.isBlank(info.bean.getStreamSecurity()) ? "" : ", tls");
detail = LocaleController.getString("VmessNetwork", R.string.VmessNetwork);
} else if (a == 5) {
text = info.bean.getHeaderType();
if ("none".equals(text)) continue;
detail = LocaleController.getString("VmessHeadType", R.string.VmessHeadType);
} else if (a == 6) {
text = info.bean.getRequestHost();
detail = LocaleController.getString("VmessRequestHost", R.string.VmessRequestHost);
} else {
text = LocaleController.getString("Checking", R.string.Checking);
detail = LocaleController.getString("Checking", R.string.Checking);
}
if (TextUtils.isEmpty(text)) {
continue;
}
TextDetailSettingsCell cell = new TextDetailSettingsCell(activity);
cell.setTextAndValue(text, detail, true);
cell.getTextView().setTextColor(Theme.getColor(Theme.key_dialogTextBlack));
cell.getValueTextView().setTextColor(Theme.getColor(Theme.key_dialogTextGray3));
linearLayout.addView(cell, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT));
AtomicInteger count = new AtomicInteger();
if (a == 7) {
RequestTimeDelegate callback = new RequestTimeDelegate() {
@Override
public void run(long time) {
int c = count.getAndIncrement();
String colorKey;
if (time != -1) {
info.stop();
cell.setTextAndValue(LocaleController.getString("Available", R.string.Available), LocaleController.formatString("Ping", R.string.Ping, time), true);
colorKey = Theme.key_windowBackgroundWhiteGreenText;
} else if (c < 2) {
ConnectionsManager.getInstance(UserConfig.selectedAccount).checkProxy(info.address, info.port, "", "", "", t -> AndroidUtilities.runOnUIThread(() -> run(t), 500));
colorKey = Theme.key_windowBackgroundWhiteGreenText;
} else {
info.stop();
cell.setTextAndValue(LocaleController.getString("Unavailable", R.string.Unavailable), LocaleController.getString("Unavailable", R.string.Unavailable), true);
colorKey = Theme.key_windowBackgroundWhiteRedText4;
}
cell.getValueTextView().setTextColor(Theme.getColor(colorKey));
}
};
UIUtil.runOnIoDispatcher(() -> {
try {
info.start();
ConnectionsManager.getInstance(UserConfig.selectedAccount).checkProxy(info.address, info.port, "", "", "", time -> AndroidUtilities.runOnUIThread(() -> callback.run(time)));
} catch (Exception e) {
FileLog.e(e);
AlertUtil.showToast(e);
}
});
}
}
PickerBottomLayout pickerBottomLayout = new PickerBottomLayout(activity, false);
pickerBottomLayout.setBackgroundColor(Theme.getColor(Theme.key_dialogBackground));
linearLayout.addView(pickerBottomLayout, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 48, Gravity.LEFT | Gravity.BOTTOM));
pickerBottomLayout.cancelButton.setPadding(AndroidUtilities.dp(18), 0, AndroidUtilities.dp(18), 0);
pickerBottomLayout.cancelButton.setTextColor(Theme.getColor(Theme.key_dialogTextBlue2));
pickerBottomLayout.cancelButton.setText(LocaleController.getString("Cancel", R.string.Cancel).toUpperCase());
pickerBottomLayout.cancelButton.setOnClickListener(view -> {
info.stop();
dismissRunnable.run();
});
pickerBottomLayout.doneButtonTextView.setTextColor(Theme.getColor(Theme.key_dialogTextBlue2));
pickerBottomLayout.doneButton.setPadding(AndroidUtilities.dp(18), 0, AndroidUtilities.dp(18), 0);
pickerBottomLayout.doneButtonBadgeTextView.setVisibility(View.GONE);
pickerBottomLayout.middleButtonTextView.setText(LocaleController.getString("Save", R.string.Save).toUpperCase());
pickerBottomLayout.middleButton.setVisibility(View.VISIBLE);
pickerBottomLayout.middleButton.setOnClickListener((it) -> {
SharedConfig.addProxy(info);
NotificationCenter.getGlobalInstance().postNotificationName(NotificationCenter.proxySettingsChanged);
dismissRunnable.run();
});
pickerBottomLayout.doneButtonTextView.setText(LocaleController.getString("ConnectingConnectProxy", R.string.ConnectingConnectProxy).toUpperCase());
pickerBottomLayout.doneButton.setOnClickListener(v -> {
SharedConfig.setCurrentProxy(SharedConfig.addProxy(info));
NotificationCenter.getGlobalInstance().postNotificationName(NotificationCenter.proxySettingsChanged);
dismissRunnable.run();
});
builder.show();
}
public static void showTrojanAlert(Context activity, final SharedConfig.VmessProxy info) {
BottomSheet.Builder builder = new BottomSheet.Builder(activity);
final Runnable dismissRunnable = builder.getDismissRunnable();
builder.setApplyTopPadding(false);
builder.setApplyBottomPadding(false);
LinearLayout linearLayout = new LinearLayout(activity);
builder.setCustomView(linearLayout);
linearLayout.setOrientation(LinearLayout.VERTICAL);
for (int a = 0; a < 4; a++) {
String text = null;
String detail = null;
if (a == 0) {
text = info.bean.getAddress();
detail = LocaleController.getString("UseProxyAddress", R.string.UseProxyAddress);
} else if (a == 1) {
text = "" + info.bean.getPort();
detail = LocaleController.getString("UseProxyPort", R.string.UseProxyPort);
} else if (a == 2) {
text = info.bean.getId();
detail = LocaleController.getString("SSPassword", R.string.SSPassword);
} else {
text = LocaleController.getString("Checking", R.string.Checking);
detail = LocaleController.getString("Checking", R.string.Checking);
}
if (TextUtils.isEmpty(text)) {
continue;
}
TextDetailSettingsCell cell = new TextDetailSettingsCell(activity);
cell.setTextAndValue(text, detail, true);
cell.getTextView().setTextColor(Theme.getColor(Theme.key_dialogTextBlack));
cell.getValueTextView().setTextColor(Theme.getColor(Theme.key_dialogTextGray3));
linearLayout.addView(cell, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT));
AtomicInteger count = new AtomicInteger();
if (a == 3) {
RequestTimeDelegate callback = new RequestTimeDelegate() {
@Override
public void run(long time) {
int c = count.getAndIncrement();
String colorKey;
if (time != -1) {
info.stop();
cell.setTextAndValue(LocaleController.getString("Available", R.string.Available), LocaleController.formatString("Ping", R.string.Ping, time), true);
colorKey = Theme.key_windowBackgroundWhiteGreenText;
} else if (c < 2) {
ConnectionsManager.getInstance(UserConfig.selectedAccount).checkProxy(info.address, info.port, "", "", "", t -> AndroidUtilities.runOnUIThread(() -> run(t), 500));
colorKey = Theme.key_windowBackgroundWhiteGreenText;
} else {
info.stop();
cell.setTextAndValue(LocaleController.getString("Unavailable", R.string.Unavailable), LocaleController.getString("Unavailable", R.string.Unavailable), true);
colorKey = Theme.key_windowBackgroundWhiteRedText4;
}
cell.getValueTextView().setTextColor(Theme.getColor(colorKey));
}
};
UIUtil.runOnIoDispatcher(() -> {
try {
info.start();
ConnectionsManager.getInstance(UserConfig.selectedAccount).checkProxy(info.address, info.port, "", "", "", time -> AndroidUtilities.runOnUIThread(() -> callback.run(time)));
} catch (Exception e) {
FileLog.e(e);
AlertUtil.showToast(e);
}
});
}
}
PickerBottomLayout pickerBottomLayout = new PickerBottomLayout(activity, false);
pickerBottomLayout.setBackgroundColor(Theme.getColor(Theme.key_dialogBackground));
linearLayout.addView(pickerBottomLayout, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 48, Gravity.LEFT | Gravity.BOTTOM));
pickerBottomLayout.cancelButton.setPadding(AndroidUtilities.dp(18), 0, AndroidUtilities.dp(18), 0);
pickerBottomLayout.cancelButton.setTextColor(Theme.getColor(Theme.key_dialogTextBlue2));
pickerBottomLayout.cancelButton.setText(LocaleController.getString("Cancel", R.string.Cancel).toUpperCase());
pickerBottomLayout.cancelButton.setOnClickListener(view -> {
info.stop();
dismissRunnable.run();
});
pickerBottomLayout.doneButtonTextView.setTextColor(Theme.getColor(Theme.key_dialogTextBlue2));
pickerBottomLayout.doneButton.setPadding(AndroidUtilities.dp(18), 0, AndroidUtilities.dp(18), 0);
pickerBottomLayout.doneButtonBadgeTextView.setVisibility(View.GONE);
pickerBottomLayout.middleButtonTextView.setText(LocaleController.getString("Save", R.string.Save).toUpperCase());
pickerBottomLayout.middleButton.setVisibility(View.VISIBLE);
pickerBottomLayout.middleButton.setOnClickListener((it) -> {
SharedConfig.addProxy(info);
NotificationCenter.getGlobalInstance().postNotificationName(NotificationCenter.proxySettingsChanged);
dismissRunnable.run();
});
pickerBottomLayout.doneButtonTextView.setText(LocaleController.getString("ConnectingConnectProxy", R.string.ConnectingConnectProxy).toUpperCase());
pickerBottomLayout.doneButton.setOnClickListener(v -> {
SharedConfig.setCurrentProxy(SharedConfig.addProxy(info));
NotificationCenter.getGlobalInstance().postNotificationName(NotificationCenter.proxySettingsChanged);
dismissRunnable.run();
});
builder.show();
}
public static void showShadowsocksAlert(Context activity, final SharedConfig.ShadowsocksProxy info) {
try {
BottomSheet.Builder builder = new BottomSheet.Builder(activity);
final Runnable dismissRunnable = builder.getDismissRunnable();
builder.setApplyTopPadding(false);
builder.setApplyBottomPadding(false);
LinearLayout linearLayout = new LinearLayout(activity);
builder.setCustomView(linearLayout);
linearLayout.setOrientation(LinearLayout.VERTICAL);
for (int a = 0; a < 5; a++) {
String text = null;
String detail = null;
if (a == 0) {
text = info.bean.getHost();
detail = LocaleController.getString("UseProxyAddress", R.string.UseProxyAddress);
} else if (a == 1) {
text = "" + info.bean.getRemotePort();
detail = LocaleController.getString("UseProxyPort", R.string.UseProxyPort);
} else if (a == 2) {
text = info.bean.getPassword();
detail = LocaleController.getString("UseProxyPassword", R.string.UseProxyPassword);
} else if (a == 3) {
text = info.bean.getMethod();
detail = LocaleController.getString("SSMethod", R.string.SSMethod);
} else {
text = LocaleController.getString("Checking", R.string.Checking);
detail = LocaleController.getString("Checking", R.string.Checking);
}
if (TextUtils.isEmpty(text)) {
continue;
}
TextDetailSettingsCell cell = new TextDetailSettingsCell(activity);
cell.setTextAndValue(text, detail, true);
cell.getTextView().setTextColor(Theme.getColor(Theme.key_dialogTextBlack));
cell.getValueTextView().setTextColor(Theme.getColor(Theme.key_dialogTextGray3));
linearLayout.addView(cell, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT));
AtomicInteger count = new AtomicInteger();
if (a == 4) {
RequestTimeDelegate callback = new RequestTimeDelegate() {
@Override
public void run(long time) {
int c = count.getAndIncrement();
String colorKey;
if (time != -1) {
info.stop();
cell.setTextAndValue(LocaleController.getString("Available", R.string.Available), LocaleController.formatString("Ping", R.string.Ping, time), true);
colorKey = Theme.key_windowBackgroundWhiteGreenText;
} else if (c < 2) {
ConnectionsManager.getInstance(UserConfig.selectedAccount).checkProxy(info.address, info.port, "", "", "", t -> AndroidUtilities.runOnUIThread(() -> run(t), 500));
colorKey = Theme.key_windowBackgroundWhiteGreenText;
} else {
info.stop();
cell.setTextAndValue(LocaleController.getString("Unavailable", R.string.Unavailable), LocaleController.getString("Unavailable", R.string.Unavailable), true);
colorKey = Theme.key_windowBackgroundWhiteRedText4;
}
cell.getValueTextView().setTextColor(Theme.getColor(colorKey));
}
};
UIUtil.runOnIoDispatcher(() -> {
try {
info.start();
ConnectionsManager.getInstance(UserConfig.selectedAccount).checkProxy(info.address, info.port, "", "", "", time -> AndroidUtilities.runOnUIThread(() -> callback.run(time)));
} catch (Exception e) {
FileLog.e(e);
AlertUtil.showToast(e);
}
});
}
}
PickerBottomLayout pickerBottomLayout = new PickerBottomLayout(activity, false);
pickerBottomLayout.setBackgroundColor(Theme.getColor(Theme.key_dialogBackground));
linearLayout.addView(pickerBottomLayout, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 48, Gravity.LEFT | Gravity.BOTTOM));
pickerBottomLayout.cancelButton.setPadding(AndroidUtilities.dp(18), 0, AndroidUtilities.dp(18), 0);
pickerBottomLayout.cancelButton.setTextColor(Theme.getColor(Theme.key_dialogTextBlue2));
pickerBottomLayout.cancelButton.setText(LocaleController.getString("Cancel", R.string.Cancel).toUpperCase());
pickerBottomLayout.cancelButton.setOnClickListener(view -> {
info.stop();
dismissRunnable.run();
});
pickerBottomLayout.doneButtonTextView.setTextColor(Theme.getColor(Theme.key_dialogTextBlue2));
pickerBottomLayout.doneButton.setPadding(AndroidUtilities.dp(18), 0, AndroidUtilities.dp(18), 0);
pickerBottomLayout.doneButtonBadgeTextView.setVisibility(View.GONE);
pickerBottomLayout.middleButtonTextView.setText(LocaleController.getString("Save", R.string.Save).toUpperCase());
pickerBottomLayout.middleButton.setVisibility(View.VISIBLE);
pickerBottomLayout.middleButton.setOnClickListener((it) -> {
SharedConfig.addProxy(info);
NotificationCenter.getGlobalInstance().postNotificationName(NotificationCenter.proxySettingsChanged);
dismissRunnable.run();
});
pickerBottomLayout.doneButtonTextView.setText(LocaleController.getString("ConnectingConnectProxy", R.string.ConnectingConnectProxy).toUpperCase());
pickerBottomLayout.doneButton.setOnClickListener(v -> {
SharedConfig.setCurrentProxy(SharedConfig.addProxy(info));
NotificationCenter.getGlobalInstance().postNotificationName(NotificationCenter.proxySettingsChanged);
dismissRunnable.run();
});
builder.show();
} catch (Exception e) {
FileLog.e(e);
AlertUtil.showToast(e);
}
}
public static void showShadowsocksRAlert(Context activity, final SharedConfig.ShadowsocksRProxy info) {
BottomSheet.Builder builder = new BottomSheet.Builder(activity);
final Runnable dismissRunnable = builder.getDismissRunnable();
builder.setApplyTopPadding(false);
builder.setApplyBottomPadding(false);
LinearLayout linearLayout = new LinearLayout(activity);
builder.setCustomView(linearLayout);
linearLayout.setOrientation(LinearLayout.VERTICAL);
for (int a = 0; a < 7; a++) {
String text = null;
String detail = null;
if (a == 0) {
text = info.bean.getHost();
detail = LocaleController.getString("UseProxyAddress", R.string.UseProxyAddress);
} else if (a == 1) {
text = "" + info.bean.getRemotePort();
detail = LocaleController.getString("UseProxyPort", R.string.UseProxyPort);
} else if (a == 2) {
text = info.bean.getPassword();
detail = LocaleController.getString("SSPassword", R.string.SSPassword);
} else if (a == 3) {
text = info.bean.getMethod();
detail = LocaleController.getString("SSMethod", R.string.SSMethod);
} else if (a == 4) {
text = info.bean.getProtocol();
if (!StrUtil.isBlank(info.bean.getProtocol_param())) {
text += ", " + info.bean.getProtocol_param();
}
detail = LocaleController.getString("SSRProtocol", R.string.SSRProtocol);
} else if (a == 5) {
text = info.bean.getObfs();
if (!StrUtil.isBlank(info.bean.getObfs_param())) {
text += ", " + info.bean.getObfs_param();
}
detail = LocaleController.getString("SSRObfs", R.string.SSRObfs);
} else {
text = LocaleController.getString("Checking", R.string.Checking);
detail = LocaleController.getString("Checking", R.string.Checking);
}
if (TextUtils.isEmpty(text)) {
continue;
}
TextDetailSettingsCell cell = new TextDetailSettingsCell(activity);
cell.setTextAndValue(text, detail, true);
cell.getTextView().setTextColor(Theme.getColor(Theme.key_dialogTextBlack));
cell.getValueTextView().setTextColor(Theme.getColor(Theme.key_dialogTextGray3));
linearLayout.addView(cell, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT));
AtomicInteger count = new AtomicInteger();
if (a == 6) {
RequestTimeDelegate callback = new RequestTimeDelegate() {
@Override
public void run(long time) {
int c = count.getAndIncrement();
String colorKey;
if (time != -1) {
info.stop();
cell.setTextAndValue(LocaleController.getString("Available", R.string.Available), LocaleController.formatString("Ping", R.string.Ping, time), true);
colorKey = Theme.key_windowBackgroundWhiteGreenText;
} else if (c < 2) {
ConnectionsManager.getInstance(UserConfig.selectedAccount).checkProxy(info.address, info.port, "", "", "", t -> AndroidUtilities.runOnUIThread(() -> run(t), 500));
colorKey = Theme.key_windowBackgroundWhiteGreenText;
} else {
info.stop();
cell.setTextAndValue(LocaleController.getString("Unavailable", R.string.Unavailable), LocaleController.getString("Unavailable", R.string.Unavailable), true);
colorKey = Theme.key_windowBackgroundWhiteRedText4;
}
cell.getValueTextView().setTextColor(Theme.getColor(colorKey));
}
};
UIUtil.runOnIoDispatcher(() -> {
try {
info.start();
ConnectionsManager.getInstance(UserConfig.selectedAccount).checkProxy(info.address, info.port, "", "", "", time -> AndroidUtilities.runOnUIThread(() -> callback.run(time)));
} catch (Exception e) {
FileLog.e(e);
AlertUtil.showToast(e);
}
});
}
}
PickerBottomLayout pickerBottomLayout = new PickerBottomLayout(activity, false);
pickerBottomLayout.setBackgroundColor(Theme.getColor(Theme.key_dialogBackground));
linearLayout.addView(pickerBottomLayout, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 48, Gravity.LEFT | Gravity.BOTTOM));
pickerBottomLayout.cancelButton.setPadding(AndroidUtilities.dp(18), 0, AndroidUtilities.dp(18), 0);
pickerBottomLayout.cancelButton.setTextColor(Theme.getColor(Theme.key_dialogTextBlue2));
pickerBottomLayout.cancelButton.setText(LocaleController.getString("Cancel", R.string.Cancel).toUpperCase());
pickerBottomLayout.cancelButton.setOnClickListener(view -> {
info.stop();
dismissRunnable.run();
});
pickerBottomLayout.doneButtonTextView.setTextColor(Theme.getColor(Theme.key_dialogTextBlue2));
pickerBottomLayout.doneButton.setPadding(AndroidUtilities.dp(18), 0, AndroidUtilities.dp(18), 0);
pickerBottomLayout.doneButtonBadgeTextView.setVisibility(View.GONE);
pickerBottomLayout.middleButtonTextView.setText(LocaleController.getString("Save", R.string.Save).toUpperCase());
pickerBottomLayout.middleButton.setVisibility(View.VISIBLE);
pickerBottomLayout.middleButton.setOnClickListener((it) -> {
SharedConfig.addProxy(info);
NotificationCenter.getGlobalInstance().postNotificationName(NotificationCenter.proxySettingsChanged);
dismissRunnable.run();
});
pickerBottomLayout.doneButtonTextView.setText(LocaleController.getString("ConnectingConnectProxy", R.string.ConnectingConnectProxy).toUpperCase());
pickerBottomLayout.doneButton.setOnClickListener(v -> {
SharedConfig.setCurrentProxy(SharedConfig.addProxy(info));
NotificationCenter.getGlobalInstance().postNotificationName(NotificationCenter.proxySettingsChanged);
dismissRunnable.run();
});
builder.show();
}
@SuppressLint("PrivateApi")
public static String getSystemProperty(String key) {
try {
Class props = Class.forName("android.os.SystemProperties");
return (String) props.getMethod("get", String.class).invoke(null, key);
} catch (Exception ignore) {
}
return null;
}
public static void fixGoogleMapsBug() {/* //https://issuetracker.google.com/issues/154855417#comment301
SharedPreferences googleBug = ApplicationLoader.applicationContext.getSharedPreferences("google_bug_154855417", Context.MODE_PRIVATE);
if (!googleBug.contains("fixed")) {
File corruptedZoomTables = new File(ApplicationLoader.getFilesDirFixed(), "ZoomTables.data");
corruptedZoomTables.delete();
googleBug.edit().putBoolean("fixed", true).apply();
}*/
}
public static CharSequence concat(CharSequence... text) {
if (text.length == 0) {
return "";
}
if (text.length == 1) {
return text[0];
}
boolean spanned = false;
for (CharSequence piece : text) {
if (piece instanceof Spanned) {
spanned = true;
break;
}
}
if (spanned) {
final SpannableStringBuilder ssb = new SpannableStringBuilder();
for (CharSequence piece : text) {
// If a piece is null, we append the string "null" for compatibility with the
// behavior of StringBuilder and the behavior of the concat() method in earlier
// versions of Android.
ssb.append(piece == null ? "null" : piece);
}
return new SpannedString(ssb);
} else {
final StringBuilder sb = new StringBuilder();
for (CharSequence piece : text) {
sb.append(piece);
}
return sb.toString();
}
}
public static float[] RGBtoHSB(int r, int g, int b) {
float hue, saturation, brightness;
float[] hsbvals = new float[3];
int cmax = Math.max(r, g);
if (b > cmax) {
cmax = b;
}
int cmin = Math.min(r, g);
if (b < cmin) {
cmin = b;
}
brightness = ((float) cmax) / 255.0f;
if (cmax != 0) {
saturation = ((float) (cmax - cmin)) / ((float) cmax);
} else {
saturation = 0;
}
if (saturation == 0) {
hue = 0;
} else {
float redc = ((float) (cmax - r)) / ((float) (cmax - cmin));
float greenc = ((float) (cmax - g)) / ((float) (cmax - cmin));
float bluec = ((float) (cmax - b)) / ((float) (cmax - cmin));
if (r == cmax) {
hue = bluec - greenc;
} else if (g == cmax) {
hue = 2.0f + redc - bluec;
} else {
hue = 4.0f + greenc - redc;
}
hue = hue / 6.0f;
if (hue < 0) {
hue = hue + 1.0f;
}
}
hsbvals[0] = hue;
hsbvals[1] = saturation;
hsbvals[2] = brightness;
return hsbvals;
}
public static int HSBtoRGB(float hue, float saturation, float brightness) {
int r = 0, g = 0, b = 0;
if (saturation == 0) {
r = g = b = (int) (brightness * 255.0f + 0.5f);
} else {
float h = (hue - (float) Math.floor(hue)) * 6.0f;
float f = h - (float) java.lang.Math.floor(h);
float p = brightness * (1.0f - saturation);
float q = brightness * (1.0f - saturation * f);
float t = brightness * (1.0f - (saturation * (1.0f - f)));
switch ((int) h) {
case 0:
r = (int) (brightness * 255.0f + 0.5f);
g = (int) (t * 255.0f + 0.5f);
b = (int) (p * 255.0f + 0.5f);
break;
case 1:
r = (int) (q * 255.0f + 0.5f);
g = (int) (brightness * 255.0f + 0.5f);
b = (int) (p * 255.0f + 0.5f);
break;
case 2:
r = (int) (p * 255.0f + 0.5f);
g = (int) (brightness * 255.0f + 0.5f);
b = (int) (t * 255.0f + 0.5f);
break;
case 3:
r = (int) (p * 255.0f + 0.5f);
g = (int) (q * 255.0f + 0.5f);
b = (int) (brightness * 255.0f + 0.5f);
break;
case 4:
r = (int) (t * 255.0f + 0.5f);
g = (int) (p * 255.0f + 0.5f);
b = (int) (brightness * 255.0f + 0.5f);
break;
case 5:
r = (int) (brightness * 255.0f + 0.5f);
g = (int) (p * 255.0f + 0.5f);
b = (int) (q * 255.0f + 0.5f);
break;
}
}
return 0xff000000 | ((r & 0xff) << 16) | ((g & 0xff) << 8) | (b & 0xff);
}
public static float computePerceivedBrightness(int color) {
return (Color.red(color) * 0.2126f + Color.green(color) * 0.7152f + Color.blue(color) * 0.0722f) / 255f;
}
public static int getPatternColor(int color) {
float[] hsb = RGBtoHSB(Color.red(color), Color.green(color), Color.blue(color));
if (hsb[1] > 0.0f || (hsb[2] < 1.0f && hsb[2] > 0.0f)) {
hsb[1] = Math.min(1.0f, hsb[1] + 0.05f + 0.1f * (1.0f - hsb[1]));
}
if (hsb[2] > 0.5f) {
hsb[2] = Math.max(0.0f, hsb[2] * 0.65f);
} else {
hsb[2] = Math.max(0.0f, Math.min(1.0f, 1.0f - hsb[2] * 0.65f));
}
return HSBtoRGB(hsb[0], hsb[1], hsb[2]) & 0x66ffffff;
}
public static int getPatternSideColor(int color) {
float[] hsb = RGBtoHSB(Color.red(color), Color.green(color), Color.blue(color));
hsb[1] = Math.min(1.0f, hsb[1] + 0.05f);
if (hsb[2] > 0.5f) {
hsb[2] = Math.max(0.0f, hsb[2] * 0.90f);
} else {
hsb[2] = Math.max(0.0f, hsb[2] * 0.90f);
}
return HSBtoRGB(hsb[0], hsb[1], hsb[2]) | 0xff000000;
}
public static int getWallpaperRotation(int angle, boolean iOS) {
if (iOS) {
angle += 180;
} else {
angle -= 180;
}
while (angle >= 360) {
angle -= 360;
}
while (angle < 0) {
angle += 360;
}
return angle;
}
public static String getWallPaperUrl(Object object) {
String link;
if (object instanceof TLRPC.TL_wallPaper) {
TLRPC.TL_wallPaper wallPaper = (TLRPC.TL_wallPaper) object;
link = "https://" + MessagesController.getInstance(UserConfig.selectedAccount).linkPrefix + "/bg/" + wallPaper.slug;
StringBuilder modes = new StringBuilder();
if (wallPaper.settings != null) {
if (wallPaper.settings.blur) {
modes.append("blur");
}
if (wallPaper.settings.motion) {
if (modes.length() > 0) {
modes.append("+");
}
modes.append("motion");
}
}
if (modes.length() > 0) {
link += "?mode=" + modes.toString();
}
} else if (object instanceof WallpapersListActivity.ColorWallpaper) {
WallpapersListActivity.ColorWallpaper wallPaper = (WallpapersListActivity.ColorWallpaper) object;
link = wallPaper.getUrl();
} else {
link = null;
}
return link;
}
public static float distanceInfluenceForSnapDuration(float f) {
f -= 0.5F;
f *= 0.47123894F;
return (float) Math.sin(f);
}
public static void makeAccessibilityAnnouncement(CharSequence what) {
AccessibilityManager am = (AccessibilityManager) ApplicationLoader.applicationContext.getSystemService(Context.ACCESSIBILITY_SERVICE);
if (am.isEnabled()) {
AccessibilityEvent ev = AccessibilityEvent.obtain();
ev.setEventType(AccessibilityEvent.TYPE_ANNOUNCEMENT);
ev.getText().add(what);
am.sendAccessibilityEvent(ev);
}
}
public static int getOffsetColor(int color1, int color2, float offset, float alpha) {
int rF = Color.red(color2);
int gF = Color.green(color2);
int bF = Color.blue(color2);
int aF = Color.alpha(color2);
int rS = Color.red(color1);
int gS = Color.green(color1);
int bS = Color.blue(color1);
int aS = Color.alpha(color1);
return Color.argb((int) ((aS + (aF - aS) * offset) * alpha), (int) (rS + (rF - rS) * offset), (int) (gS + (gF - gS) * offset), (int) (bS + (bF - bS) * offset));
}
public static int indexOfIgnoreCase(final String origin, final String searchStr) {
if (searchStr.isEmpty() || origin.isEmpty()) {
return origin.indexOf(searchStr);
}
for (int i = 0; i < origin.length(); i++) {
if (i + searchStr.length() > origin.length()) {
return -1;
}
int j = 0;
int ii = i;
while (ii < origin.length() && j < searchStr.length()) {
char c = Character.toLowerCase(origin.charAt(ii));
char c2 = Character.toLowerCase(searchStr.charAt(j));
if (c != c2) {
break;
}
j++;
ii++;
}
if (j == searchStr.length()) {
return i;
}
}
return -1;
}
public static float lerp(float a, float b, float f) {
return a + f * (b - a);
}
public static float lerp(float[] ab, float f) {
return lerp(ab[0], ab[1], f);
}
private static WeakReference<BaseFragment> flagSecureFragment;
public static boolean hasFlagSecureFragment() {
return flagSecureFragment != null;
}
public static void setFlagSecure(BaseFragment parentFragment, boolean set) {
if (parentFragment == null || parentFragment.getParentActivity() == null) {
return;
}
if (set && !NekoXConfig.disableFlagSecure) {
try {
parentFragment.getParentActivity().getWindow().setFlags(WindowManager.LayoutParams.FLAG_SECURE, WindowManager.LayoutParams.FLAG_SECURE);
flagSecureFragment = new WeakReference<>(parentFragment);
} catch (Exception ignore) {
}
} else if (flagSecureFragment != null && flagSecureFragment.get() == parentFragment) {
try {
parentFragment.getParentActivity().getWindow().clearFlags(WindowManager.LayoutParams.FLAG_SECURE);
} catch (Exception ignore) {
}
flagSecureFragment = null;
}
}
public static void openSharing(BaseFragment fragment, String url) {
if (fragment == null || fragment.getParentActivity() == null) {
return;
}
fragment.showDialog(new ShareAlert(fragment.getParentActivity(), null, url, false, url, false));
}
public static boolean allowScreenCapture() {
return SharedConfig.passcodeHash.length() == 0 || SharedConfig.allowScreenCapture;
}
public static File getSharingDirectory() {
return new File(FileLoader.getDirectory(FileLoader.MEDIA_DIR_CACHE), "sharing/");
}
public static String getCertificateSHA256Fingerprint() {
PackageManager pm = ApplicationLoader.applicationContext.getPackageManager();
String packageName = ApplicationLoader.applicationContext.getPackageName();
try {
PackageInfo packageInfo = pm.getPackageInfo(packageName, PackageManager.GET_SIGNATURES);
Signature[] signatures = packageInfo.signatures;
byte[] cert = signatures[0].toByteArray();
InputStream input = new ByteArrayInputStream(cert);
CertificateFactory cf = CertificateFactory.getInstance("X509");
X509Certificate c = (X509Certificate) cf.generateCertificate(input);
return Utilities.bytesToHex(Utilities.computeSHA256(c.getEncoded()));
} catch (Throwable ignore) {
}
return "";
}
private static char[] characters = new char[]{' ', '!', '"', '#', '%', '&', '\'', '(', ')', '*', ',', '-', '.', '/', ':', ';', '?', '@', '[', '\\', ']', '_', '{', '}', '¡', '§', '«', '¶', '·', '»', '¿', ';', '·', '՚', '՛', '՜', '՝', '՞', '՟', '։', '֊', '־', '׀', '׃', '׆', '׳', '״', '؉', '؊', '،', '؍', '؛', '؞', '؟', '٪', '٫', '٬', '٭', '۔', '܀', '܁', '܂', '܃', '܄', '܅', '܆', '܇', '܈', '܉', '܊', '܋', '܌', '܍', '߷', '߸', '߹', '࠰', '࠱', '࠲', '࠳', '࠴', '࠵', '࠶', '࠷', '࠸', '࠹', '࠺', '࠻', '࠼', '࠽', '࠾', '࡞', '।', '॥', '॰', '৽', '੶', '૰', '౷', '಄', '෴', '๏', '๚', '๛', '༄', '༅', '༆', '༇', '༈', '༉', '༊', '་', '༌', '།', '༎', '༏', '༐', '༑', '༒', '༔', '༺', '༻', '༼', '༽', '྅', '࿐', '࿑', '࿒', '࿓', '࿔', '࿙', '࿚', '၊', '။', '၌', '၍', '၎', '၏', '჻', '፠', '፡', '።', '፣', '፤', '፥', '፦', '፧', '፨', '', '', '᚛', '᚜', '᛫', '', '', '', '᜶', '។', '៕', '៖', '៘', '៙', '៚', '᠀', '᠁', '᠂', '', '᠄', '᠅', '᠆', '᠇', '᠈', '', '᠊', '᥄', '᥅', '᨞', '᨟', '᪠', '᪡', '᪢', '᪣', '᪤', '᪥', '᪦', '᪨', '᪩', '᪪', '᪫', '᪬', '᪭', '᭚', '᭛', '᭜', '᭝', '᭞', '᭟', '᭠', '᯼', '᯽', '᯾', '᯿', '᰻', '᰼', '᰽', '᰾', '᰿', '᱾', '᱿', '᳀', '᳁', '᳂', '᳃', '᳄', '᳅', '᳆', '᳇', '᳓', '', '', '', '', '—', '―', '‖', '‗', '', '', '', '', '“', '”', '„', '‟', '†', '‡', '•', '‣', '', '‥', '…', '‧', '‰', '‱', '', '″', '‴', '', '‶', '‷', '‸', '', '', '※', '‼', '‽', '‾', '‿', '⁀', '', '⁂', '', '⁅', '⁆', '⁇', '⁈', '⁉', '⁊', '⁋', '⁌', '⁍', '', '⁏', '⁐', '⁑', '', '⁔', '⁕', '⁖', '⁗', '⁘', '⁙', '', '⁛', '⁜', '⁝', '⁞', '⁽', '⁾', '₍', '₎', '⌈', '⌉', '⌊', '⌋', '〈', '〉', '', '', '❪', '❫', '❬', '❭', '', '', '❰', '❱', '', '', '', '', '⟅', '⟆', '⟦', '⟧', '⟨', '⟩', '⟪', '⟫', '⟬', '⟭', '⟮', '⟯', '⦃', '⦄', '⦅', '⦆', '⦇', '⦈', '⦉', '⦊', '⦋', '⦌', '⦍', '⦎', '⦏', '⦐', '⦑', '⦒', '⦓', '⦔', '⦕', '⦖', '⦗', '⦘', '⧘', '⧙', '⧚', '⧛', '⧼', '⧽', '⳹', '⳺', '⳻', '⳼', '⳾', '⳿', '⵰', '⸀', '⸁', '⸂', '⸃', '⸄', '⸅', '⸆', '⸇', '⸈', '⸉', '⸊', '⸋', '⸌', '⸍', '⸎', '⸏', '⸐', '⸑', '⸒', '⸓', '⸔', '⸕', '⸖', '⸗', '⸘', '⸙', '⸚', '⸛', '⸜', '⸝', '⸞', '⸟', '⸠', '⸡', '⸢', '⸣', '⸤', '⸥', '⸦', '⸧', '⸨', '⸩', '⸪', '⸫', '⸬', '⸭', '⸮', '⸰', '⸱', '⸲', '⸳', '⸴', '⸵', '⸶', '⸷', '⸸', '⸹', '⸺', '⸻', '⸼', '⸽', '⸾', '⸿', '', '⹁', '⹂', '⹃', '⹄', '⹅', '⹆', '⹇', '⹈', '⹉', '⹊', '⹋', '⹌', '⹍', '⹎', '⹏', '、', '。', '〃', '〈', '〉', '《', '》', '「', '」', '『', '』', '【', '】', '', '', '〖', '〗', '〘', '〙', '〚', '〛', '〜', '〝', '〞', '〟', '〰', '〽', '', '・', '꓾', '', '꘍', '', '꘏', '꙳', '꙾', '꛲', '꛳', '꛴', '꛵', '꛶', '꛷', '꡴', '꡵', '꡶', '꡷', '꣎', '꣏', '꣸', '꣹', '꣺', '꣼', '꤮', '꤯', '꥟', '꧁', '꧂', '꧃', '꧄', '꧅', '꧆', '꧇', '꧈', '꧉', '꧊', '꧋', '꧌', '꧍', '꧞', '꧟', '꩜', '꩝', '꩞', '꩟', '꫞', '꫟', '꫰', '꫱', '꯫', '', '﴿', '︐', '︑', '︒', '︓', '︔', '︕', '︖', '︗', '︘', '︙', '', '︱', '︲', '︳', '︴', '︵', '︶', '︷', '︸', '︹', '︺', '︻', '︼', '︽', '︾', '︿', '﹀', '﹁', '﹂', '﹃', '﹄', '﹅', '﹆', '﹇', '﹈', '﹉', '﹊', '﹋', '﹌', '', '', '', '﹐', '﹑', '﹒', '﹔', '﹕', '﹖', '﹗', '', '﹙', '﹚', '﹛', '﹜', '﹝', '﹞', '﹟', '﹠', '﹡', '﹣', '', '﹪', '﹫', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '_', '', '', '⦅', '⦆', '。', '「', '」', '、', '・'};
//private static String[] longCharacters = new String[] {"𐄀", "𐄁", "𐄂", "𐎟", "𐏐", "𐕯", "𐡗", "𐤟", "𐤿", "𐩐", "𐩑", "𐩒", "𐩓", "𐩔", "𐩕", "𐩖", "𐩗", "𐩘", "𐩿", "𐫰", "𐫱", "𐫲", "𐫳", "𐫴", "𐫵", "𐫶", "𐬹", "𐬺", "𐬻", "𐬼", "𐬽", "𐬾", "𐬿", "𐮙", "𐮚", "𐮛", "𐮜", "𐽕", "𐽖", "𐽗", "𐽘", "𐽙", "𑁇", "𑁈", "𑁉", "𑁊", "𑁋", "𑁌", "𑁍", "𑂻", "𑂼", "𑂾", "𑂿", "𑃀", "𑃁", "𑅀", "𑅁", "𑅂", "𑅃", "𑅴", "𑅵", "𑇅", "𑇆", "𑇇", "𑇈", "𑇍", "𑇛", "𑇝", "𑇞", "𑇟", "𑈸", "𑈹", "𑈺", "𑈻", "𑈼", "𑈽", "𑊩", "𑑋", "𑑌", "𑑍", "𑑎", "𑑏", "𑑛", "𑑝", "𑓆", "𑗁", "𑗂", "𑗃", "𑗄", "𑗅", "𑗆", "𑗇", "𑗈", "𑗉", "𑗊", "𑗋", "𑗌", "𑗍", "𑗎", "𑗏", "𑗐", "𑗑", "𑗒", "𑗓", "𑗔", "𑗕", "𑗖", "𑗗", "𑙁", "𑙂", "𑙃", "𑙠", "𑙡", "𑙢", "𑙣", "𑙤", "𑙥", "𑙦", "𑙧", "𑙨", "𑙩", "𑙪", "𑙫", "𑙬", "𑜼", "𑜽", "𑜾", "𑠻", "𑧢", "𑨿", "𑩀", "𑩁", "𑩂", "𑩃", "𑩄", "𑩅", "𑩆", "𑪚", "𑪛", "𑪜", "𑪞", "𑪟", "𑪠", "𑪡", "𑪢", "𑱁", "𑱂", "𑱃", "𑱄", "𑱅", "𑱰", "𑱱", "𑻷", "𑻸", "𑿿", "𒑰", "𒑱", "𒑲", "𒑳", "𒑴", "𖩮", "𖩯", "𖫵", "𖬷", "𖬸", "𖬹", "𖬺", "𖬻", "𖭄", "𖺗", "𖺘", "𖺙", "𖺚", "𖿢", "𛲟", "𝪇", "𝪈", "𝪉", "𝪊", "𝪋", "𞥞", "𞥟"};
private static HashSet<Character> charactersMap;
public static boolean isPunctuationCharacter(char ch) {
if (charactersMap == null) {
charactersMap = new HashSet<>();
for (int a = 0; a < characters.length; a++) {
charactersMap.add(characters[a]);
}
}
//int len = longCharacters[0].length();
return charactersMap.contains(ch);
}
public static int getColorDistance(int color1, int color2) {
int r1 = Color.red(color1);
int g1 = Color.green(color1);
int b1 = Color.blue(color1);
int r2 = Color.red(color2);
int g2 = Color.green(color2);
int b2 = Color.blue(color2);
int rMean = (r1 + r2) / 2;
int r = r1 - r2;
int g = g1 - g2;
int b = b1 - b2;
return (((512 + rMean) * r * r) >> 8) + (4 * g * g) + (((767 - rMean) * b * b) >> 8);
}
public static int getAverageColor(int color1, int color2) {
int r1 = Color.red(color1);
int r2 = Color.red(color2);
int g1 = Color.green(color1);
int g2 = Color.green(color2);
int b1 = Color.blue(color1);
int b2 = Color.blue(color2);
return Color.argb(255, (r1 / 2 + r2 / 2), (g1 / 2 + g2 / 2), (b1 / 2 + b2 / 2));
}
public static void setLightStatusBar(Window window, boolean enable) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
final View decorView = window.getDecorView();
int flags = decorView.getSystemUiVisibility();
if (!SharedConfig.noStatusBar && NekoConfig.transparentStatusBar) {
window.setStatusBarColor(Color.TRANSPARENT);
}
if (enable) {
if ((flags & View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR) == 0) {
flags |= View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR;
decorView.setSystemUiVisibility(flags);
if (!SharedConfig.noStatusBar && !NekoConfig.transparentStatusBar) {
window.setStatusBarColor(0x0f000000);
}
}
} else {
if ((flags & View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR) != 0) {
flags &= ~View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR;
decorView.setSystemUiVisibility(flags);
if (!SharedConfig.noStatusBar && !NekoConfig.transparentStatusBar) {
window.setStatusBarColor(0x33000000);
}
}
}
}
}
public static void setLightNavigationBar(Window window, boolean enable) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
final View decorView = window.getDecorView();
int flags = decorView.getSystemUiVisibility();
if (enable) {
flags |= View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR;
} else {
flags &= ~View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR;
}
decorView.setSystemUiVisibility(flags);
}
}
public static boolean checkHostForPunycode(String url) {
boolean hasLatin = false;
boolean hasNonLatin = false;
try {
for (int a = 0, N = url.length(); a < N; a++) {
char ch = url.charAt(a);
if (ch == '.' || ch == '-' || ch == '/' || ch == '+' || ch >= '0' && ch <= '9') {
continue;
}
if (ch >= 'a' && ch <= 'z' || ch >= 'A' && ch <= 'Z') {
hasLatin = true;
} else {
hasNonLatin = true;
}
if (hasLatin && hasNonLatin) {
break;
}
}
} catch (Exception e) {
FileLog.e(e);
}
return hasLatin && hasNonLatin;
}
public static boolean shouldShowUrlInAlert(String url) {
try {
Uri uri = Uri.parse(url);
url = uri.getHost();
return checkHostForPunycode(url);
} catch (Exception e) {
FileLog.e(e);
}
return false;
}
public static void scrollToFragmentRow(ActionBarLayout parentLayout, String rowName) {
if (parentLayout == null || rowName == null) {
return;
}
BaseFragment openingFragment = parentLayout.fragmentsStack.get(parentLayout.fragmentsStack.size() - 1);
try {
Field listViewField = openingFragment.getClass().getDeclaredField("listView");
listViewField.setAccessible(true);
RecyclerListView listView = (RecyclerListView) listViewField.get(openingFragment);
RecyclerListView.IntReturnCallback callback = () -> {
int position = -1;
try {
Field rowField = openingFragment.getClass().getDeclaredField(rowName);
rowField.setAccessible(true);
LinearLayoutManager layoutManager = (LinearLayoutManager) listView.getLayoutManager();
position = rowField.getInt(openingFragment);
layoutManager.scrollToPositionWithOffset(position, AndroidUtilities.dp(60));
rowField.setAccessible(false);
return position;
} catch (Throwable ignore) {
}
return position;
};
listView.highlightRow(callback);
listViewField.setAccessible(false);
} catch (Throwable ignore) {
}
}
public static boolean checkInlinePermissions(Context context) {
if (Build.VERSION.SDK_INT < 23 || Settings.canDrawOverlays(context)) {
return true;
}
return false;
}
public static void updateVisibleRows(RecyclerListView listView) {
if (listView == null) {
return;
}
RecyclerView.Adapter adapter = listView.getAdapter();
if (adapter == null) {
return;
}
for (int i = 0; i < listView.getChildCount(); i++) {
View child = listView.getChildAt(i);
int p = listView.getChildAdapterPosition(child);
if (p >= 0) {
RecyclerView.ViewHolder holder = listView.getChildViewHolder(child);
if (holder == null || holder.shouldIgnore()) {
continue;
}
adapter.onBindViewHolder(holder, p);
}
}
}
public static void updateViewVisibilityAnimated(View view, boolean show) {
updateViewVisibilityAnimated(view, show, 1f, true);
}
public static void updateViewVisibilityAnimated(View view, boolean show, float scaleFactor, boolean animated) {
if (view.getParent() == null) {
animated = false;
}
if (show && view.getTag() == null) {
view.animate().setListener(null).cancel();
if (animated) {
if (view.getVisibility() != View.VISIBLE) {
view.setVisibility(View.VISIBLE);
view.setAlpha(0f);
view.setScaleX(scaleFactor);
view.setScaleY(scaleFactor);
}
view.animate().alpha(1f).scaleY(1f).scaleX(1f).setDuration(150).start();
} else {
view.setVisibility(View.VISIBLE);
view.setAlpha(1f);
view.setScaleX(1f);
view.setScaleY(1f);
}
view.setTag(1);
} else {
view.animate().setListener(null).cancel();
if (animated) {
view.animate().alpha(1f).scaleY(1f).scaleX(1f).setDuration(150).start();
view.animate().alpha(0).scaleY(scaleFactor).scaleX(scaleFactor).setListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
view.setVisibility(View.GONE);
}
}).setDuration(150).start();
} else {
view.setVisibility(View.GONE);
}
view.setTag(null);
}
}
}