mirror of https://github.com/NekoX-Dev/NekoX.git
534 lines
20 KiB
Java
534 lines
20 KiB
Java
/*
|
|
* This is the source code of Telegram for Android v. 1.4.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-2014.
|
|
*/
|
|
|
|
package org.telegram.android;
|
|
|
|
import android.app.Activity;
|
|
import android.app.AlertDialog;
|
|
import android.content.Context;
|
|
import android.content.DialogInterface;
|
|
import android.content.pm.ActivityInfo;
|
|
import android.content.res.Configuration;
|
|
import android.graphics.Point;
|
|
import android.graphics.Rect;
|
|
import android.graphics.Typeface;
|
|
import android.graphics.drawable.Drawable;
|
|
import android.os.Build;
|
|
import android.os.Environment;
|
|
import android.text.Spannable;
|
|
import android.text.SpannableStringBuilder;
|
|
import android.text.Spanned;
|
|
import android.util.StateSet;
|
|
import android.view.Display;
|
|
import android.view.Surface;
|
|
import android.view.View;
|
|
import android.view.WindowManager;
|
|
import android.view.inputmethod.InputMethodManager;
|
|
import android.widget.AbsListView;
|
|
import android.widget.EdgeEffect;
|
|
import android.widget.EditText;
|
|
import android.widget.ListView;
|
|
import android.widget.TextView;
|
|
|
|
import org.telegram.messenger.FileLog;
|
|
import org.telegram.messenger.R;
|
|
import org.telegram.messenger.TLRPC;
|
|
import org.telegram.messenger.ApplicationLoader;
|
|
import org.telegram.ui.Components.NumberPicker;
|
|
import org.telegram.ui.Components.TypefaceSpan;
|
|
|
|
import java.io.File;
|
|
import java.lang.reflect.Field;
|
|
import java.lang.reflect.Method;
|
|
import java.util.ArrayList;
|
|
import java.util.Hashtable;
|
|
|
|
public class AndroidUtilities {
|
|
|
|
private static final Hashtable<String, Typeface> typefaceCache = new Hashtable<>();
|
|
private static int prevOrientation = -10;
|
|
private static boolean waitingForSms = false;
|
|
private static final Object smsLock = new Object();
|
|
|
|
public static int statusBarHeight = 0;
|
|
public static float density = 1;
|
|
public static Point displaySize = new Point();
|
|
public static Integer photoSize = null;
|
|
private static Boolean isTablet = null;
|
|
|
|
static {
|
|
density = ApplicationLoader.applicationContext.getResources().getDisplayMetrics().density;
|
|
checkDisplaySize();
|
|
}
|
|
|
|
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;
|
|
int SCREEN_ORIENTATION_REVERSE_LANDSCAPE = 8;
|
|
int SCREEN_ORIENTATION_REVERSE_PORTRAIT = 9;
|
|
if (Build.VERSION.SDK_INT < 9) {
|
|
SCREEN_ORIENTATION_REVERSE_LANDSCAPE = ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE;
|
|
SCREEN_ORIENTATION_REVERSE_PORTRAIT = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT;
|
|
}
|
|
|
|
if (rotation == Surface.ROTATION_270) {
|
|
if (orientation == Configuration.ORIENTATION_PORTRAIT) {
|
|
activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
|
|
} else {
|
|
activity.setRequestedOrientation(SCREEN_ORIENTATION_REVERSE_LANDSCAPE);
|
|
}
|
|
} else if (rotation == Surface.ROTATION_90) {
|
|
if (orientation == Configuration.ORIENTATION_PORTRAIT) {
|
|
activity.setRequestedOrientation(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(SCREEN_ORIENTATION_REVERSE_LANDSCAPE);
|
|
} else {
|
|
activity.setRequestedOrientation(SCREEN_ORIENTATION_REVERSE_PORTRAIT);
|
|
}
|
|
}
|
|
}
|
|
} catch (Exception e) {
|
|
FileLog.e("tmessages", e);
|
|
}
|
|
}
|
|
|
|
public static void unlockOrientation(Activity activity) {
|
|
if (activity == null) {
|
|
return;
|
|
}
|
|
try {
|
|
if (prevOrientation != -10) {
|
|
activity.setRequestedOrientation(prevOrientation);
|
|
prevOrientation = -10;
|
|
}
|
|
} catch (Exception e) {
|
|
FileLog.e("tmessages", e);
|
|
}
|
|
}
|
|
|
|
public static Typeface getTypeface(String assetPath) {
|
|
synchronized (typefaceCache) {
|
|
if (!typefaceCache.containsKey(assetPath)) {
|
|
try {
|
|
Typeface t = Typeface.createFromAsset(ApplicationLoader.applicationContext.getAssets(), assetPath);
|
|
typefaceCache.put(assetPath, t);
|
|
} catch (Exception e) {
|
|
FileLog.e("Typefaces", "Could not get typeface '" + assetPath + "' because " + e.getMessage());
|
|
return null;
|
|
}
|
|
}
|
|
return typefaceCache.get(assetPath);
|
|
}
|
|
}
|
|
|
|
public static boolean isWaitingForSms() {
|
|
boolean value = false;
|
|
synchronized (smsLock) {
|
|
value = waitingForSms;
|
|
}
|
|
return value;
|
|
}
|
|
|
|
public static void setWaitingForSms(boolean value) {
|
|
synchronized (smsLock) {
|
|
waitingForSms = value;
|
|
}
|
|
}
|
|
|
|
public static void showKeyboard(View view) {
|
|
if (view == null) {
|
|
return;
|
|
}
|
|
InputMethodManager inputManager = (InputMethodManager)view.getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
|
|
inputManager.showSoftInput(view, InputMethodManager.SHOW_IMPLICIT);
|
|
|
|
((InputMethodManager) view.getContext().getSystemService(Context.INPUT_METHOD_SERVICE)).showSoftInput(view, 0);
|
|
}
|
|
|
|
public static boolean isKeyboardShowed(View view) {
|
|
if (view == null) {
|
|
return false;
|
|
}
|
|
InputMethodManager inputManager = (InputMethodManager) view.getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
|
|
return inputManager.isActive(view);
|
|
}
|
|
|
|
public static void hideKeyboard(View view) {
|
|
if (view == null) {
|
|
return;
|
|
}
|
|
InputMethodManager imm = (InputMethodManager) view.getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
|
|
if (!imm.isActive()) {
|
|
return;
|
|
}
|
|
imm.hideSoftInputFromWindow(view.getWindowToken(), 0);
|
|
}
|
|
|
|
public static File getCacheDir() {
|
|
String state = null;
|
|
try {
|
|
state = Environment.getExternalStorageState();
|
|
} catch (Exception e) {
|
|
FileLog.e("tmessages", e);
|
|
}
|
|
if (state == null || state.startsWith(Environment.MEDIA_MOUNTED)) {
|
|
try {
|
|
File file = ApplicationLoader.applicationContext.getExternalCacheDir();
|
|
if (file != null) {
|
|
return file;
|
|
}
|
|
} catch (Exception e) {
|
|
FileLog.e("tmessages", e);
|
|
}
|
|
}
|
|
try {
|
|
File file = ApplicationLoader.applicationContext.getCacheDir();
|
|
if (file != null) {
|
|
return file;
|
|
}
|
|
} catch (Exception e) {
|
|
FileLog.e("tmessages", e);
|
|
}
|
|
return new File("");
|
|
}
|
|
|
|
public static int dp(float value) {
|
|
return (int)Math.ceil(density * value);
|
|
}
|
|
|
|
public static float dpf2(float value) {
|
|
return density * value;
|
|
}
|
|
|
|
public static void checkDisplaySize() {
|
|
try {
|
|
WindowManager manager = (WindowManager)ApplicationLoader.applicationContext.getSystemService(Context.WINDOW_SERVICE);
|
|
if (manager != null) {
|
|
Display display = manager.getDefaultDisplay();
|
|
if (display != null) {
|
|
if(android.os.Build.VERSION.SDK_INT < 13) {
|
|
displaySize.set(display.getWidth(), display.getHeight());
|
|
} else {
|
|
display.getSize(displaySize);
|
|
}
|
|
FileLog.e("tmessages", "display size = " + displaySize.x + " " + displaySize.y);
|
|
}
|
|
}
|
|
} catch (Exception e) {
|
|
FileLog.e("tmessages", e);
|
|
}
|
|
}
|
|
|
|
public static long makeBroadcastId(int id) {
|
|
return 0x0000000100000000L | ((long)id & 0x00000000FFFFFFFFL);
|
|
}
|
|
|
|
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 (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) {
|
|
isTablet = ApplicationLoader.applicationContext.getResources().getBoolean(R.bool.isTablet);
|
|
}
|
|
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) {
|
|
if (Build.VERSION.SDK_INT >= 16) {
|
|
photoSize = 1280;
|
|
} else {
|
|
photoSize = 800;
|
|
}
|
|
}
|
|
return photoSize;
|
|
}
|
|
|
|
public static String formatTTLString(int ttl) {
|
|
if (ttl < 60) {
|
|
return LocaleController.formatPluralString("Seconds", ttl);
|
|
} else if (ttl < 60 * 60) {
|
|
return LocaleController.formatPluralString("Minutes", ttl / 60);
|
|
} else if (ttl < 60 * 60 * 24) {
|
|
return LocaleController.formatPluralString("Hours", ttl / 60 / 60);
|
|
} else if (ttl < 60 * 60 * 24 * 7) {
|
|
return LocaleController.formatPluralString("Days", ttl / 60 / 60 / 24);
|
|
} else {
|
|
int days = ttl / 60 / 60 / 24;
|
|
if (ttl % 7 == 0) {
|
|
return LocaleController.formatPluralString("Weeks", days / 7);
|
|
} else {
|
|
return String.format("%s %s", LocaleController.formatPluralString("Weeks", days / 7), LocaleController.formatPluralString("Days", days % 7));
|
|
}
|
|
}
|
|
}
|
|
|
|
public static AlertDialog.Builder buildTTLAlert(final Context context, final TLRPC.EncryptedChat encryptedChat) {
|
|
AlertDialog.Builder builder = new AlertDialog.Builder(context);
|
|
builder.setTitle(LocaleController.getString("MessageLifetime", R.string.MessageLifetime));
|
|
final NumberPicker numberPicker = new NumberPicker(context);
|
|
numberPicker.setMinValue(0);
|
|
numberPicker.setMaxValue(20);
|
|
if (encryptedChat.ttl > 0 && encryptedChat.ttl < 16) {
|
|
numberPicker.setValue(encryptedChat.ttl);
|
|
} else if (encryptedChat.ttl == 30) {
|
|
numberPicker.setValue(16);
|
|
} else if (encryptedChat.ttl == 60) {
|
|
numberPicker.setValue(17);
|
|
} else if (encryptedChat.ttl == 60 * 60) {
|
|
numberPicker.setValue(18);
|
|
} else if (encryptedChat.ttl == 60 * 60 * 24) {
|
|
numberPicker.setValue(19);
|
|
} else if (encryptedChat.ttl == 60 * 60 * 24 * 7) {
|
|
numberPicker.setValue(20);
|
|
} else if (encryptedChat.ttl == 0) {
|
|
numberPicker.setValue(0);
|
|
}
|
|
numberPicker.setFormatter(new NumberPicker.Formatter() {
|
|
@Override
|
|
public String format(int value) {
|
|
if (value == 0) {
|
|
return LocaleController.getString("ShortMessageLifetimeForever", R.string.ShortMessageLifetimeForever);
|
|
} else if (value >= 1 && value < 16) {
|
|
return AndroidUtilities.formatTTLString(value);
|
|
} else if (value == 16) {
|
|
return AndroidUtilities.formatTTLString(30);
|
|
} else if (value == 17) {
|
|
return AndroidUtilities.formatTTLString(60);
|
|
} else if (value == 18) {
|
|
return AndroidUtilities.formatTTLString(60 * 60);
|
|
} else if (value == 19) {
|
|
return AndroidUtilities.formatTTLString(60 * 60 * 24);
|
|
} else if (value == 20) {
|
|
return AndroidUtilities.formatTTLString(60 * 60 * 24 * 7);
|
|
}
|
|
return "";
|
|
}
|
|
});
|
|
builder.setView(numberPicker);
|
|
builder.setNegativeButton(LocaleController.getString("Done", R.string.Done), new DialogInterface.OnClickListener() {
|
|
@Override
|
|
public void onClick(DialogInterface dialog, int which) {
|
|
int oldValue = encryptedChat.ttl;
|
|
which = numberPicker.getValue();
|
|
if (which >= 0 && which < 16) {
|
|
encryptedChat.ttl = which;
|
|
} else if (which == 16) {
|
|
encryptedChat.ttl = 30;
|
|
} else if (which == 17) {
|
|
encryptedChat.ttl = 60;
|
|
} else if (which == 18) {
|
|
encryptedChat.ttl = 60 * 60;
|
|
} else if (which == 19) {
|
|
encryptedChat.ttl = 60 * 60 * 24;
|
|
} else if (which == 20) {
|
|
encryptedChat.ttl = 60 * 60 * 24 * 7;
|
|
}
|
|
if (oldValue != encryptedChat.ttl) {
|
|
SecretChatHelper.getInstance().sendTTLMessage(encryptedChat, null);
|
|
MessagesStorage.getInstance().updateEncryptedChatTTL(encryptedChat);
|
|
}
|
|
}
|
|
});
|
|
return builder;
|
|
}
|
|
|
|
public static void clearCursorDrawable(EditText editText) {
|
|
if (editText == null || Build.VERSION.SDK_INT < 12) {
|
|
return;
|
|
}
|
|
try {
|
|
Field mCursorDrawableRes = TextView.class.getDeclaredField("mCursorDrawableRes");
|
|
mCursorDrawableRes.setAccessible(true);
|
|
mCursorDrawableRes.setInt(editText, 0);
|
|
} catch (Exception e) {
|
|
FileLog.e("tmessages", e);
|
|
}
|
|
}
|
|
|
|
public static int getViewInset(View view) {
|
|
if (view == null || Build.VERSION.SDK_INT < 21) {
|
|
return 0;
|
|
}
|
|
try {
|
|
Field mAttachInfoField = View.class.getDeclaredField("mAttachInfo");
|
|
mAttachInfoField.setAccessible(true);
|
|
Object mAttachInfo = mAttachInfoField.get(view);
|
|
if (mAttachInfo != null) {
|
|
Field mStableInsetsField = mAttachInfo.getClass().getDeclaredField("mStableInsets");
|
|
mStableInsetsField.setAccessible(true);
|
|
Rect insets = (Rect)mStableInsetsField.get(mAttachInfo);
|
|
return insets.bottom;
|
|
}
|
|
} catch (Exception e) {
|
|
FileLog.e("tmessages", e);
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
public static int getCurrentActionBarHeight() {
|
|
if (isTablet()) {
|
|
return dp(64);
|
|
} else if (ApplicationLoader.applicationContext.getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE) {
|
|
return dp(48);
|
|
} else {
|
|
return dp(56);
|
|
}
|
|
}
|
|
|
|
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("tmessages", e);
|
|
}
|
|
}
|
|
} catch (Exception e) {
|
|
FileLog.e("tmessages", e);
|
|
}
|
|
return size;
|
|
}
|
|
|
|
public static void setListViewEdgeEffectColor(AbsListView listView, int color) {
|
|
if (Build.VERSION.SDK_INT >= 21) {
|
|
try {
|
|
Field field = AbsListView.class.getDeclaredField("mEdgeGlowTop");
|
|
field.setAccessible(true);
|
|
EdgeEffect mEdgeGlowTop = (EdgeEffect) field.get(listView);
|
|
if (mEdgeGlowTop != null) {
|
|
mEdgeGlowTop.setColor(color);
|
|
}
|
|
|
|
field = AbsListView.class.getDeclaredField("mEdgeGlowBottom");
|
|
field.setAccessible(true);
|
|
EdgeEffect mEdgeGlowBottom = (EdgeEffect) field.get(listView);
|
|
if (mEdgeGlowBottom != null) {
|
|
mEdgeGlowBottom.setColor(color);
|
|
}
|
|
} catch (Exception e) {
|
|
FileLog.e("tmessages", e);
|
|
}
|
|
}
|
|
}
|
|
|
|
public static void clearDrawableAnimation(View view) {
|
|
if (Build.VERSION.SDK_INT < 21 || view == null) {
|
|
return;
|
|
}
|
|
Drawable drawable = null;
|
|
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 Spannable replaceBold(String str) {
|
|
int start;
|
|
ArrayList<Integer> bolds = new ArrayList<>();
|
|
while ((start = str.indexOf("<b>")) != -1) {
|
|
int end = str.indexOf("</b>") - 3;
|
|
str = str.replaceFirst("<b>", "").replaceFirst("</b>", "");
|
|
bolds.add(start);
|
|
bolds.add(end);
|
|
}
|
|
SpannableStringBuilder stringBuilder = new SpannableStringBuilder(str);
|
|
for (int a = 0; a < bolds.size() / 2; a++) {
|
|
TypefaceSpan span = new TypefaceSpan(AndroidUtilities.getTypeface("fonts/rmedium.ttf"));
|
|
stringBuilder.setSpan(span, bolds.get(a * 2), bolds.get(a * 2 + 1), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
|
|
}
|
|
return stringBuilder;
|
|
}
|
|
}
|