diff --git a/TMessagesProj/build.gradle b/TMessagesProj/build.gradle
index f7d331b8b61..ee5a84d3754 100644
--- a/TMessagesProj/build.gradle
+++ b/TMessagesProj/build.gradle
@@ -36,6 +36,7 @@ dependencies {
implementation 'com.google.android.gms:play-services-wearable:18.0.0'
implementation 'com.google.android.gms:play-services-location:21.0.1'
implementation 'com.google.android.gms:play-services-wallet:19.1.0'
+ implementation 'com.google.android.gms:play-services-safetynet:18.0.1'
implementation 'com.googlecode.mp4parser:isoparser:1.0.6'
implementation 'com.stripe:stripe-android:2.0.2'
implementation 'com.google.mlkit:language-id:16.1.1'
diff --git a/TMessagesProj/config/debug/AndroidManifest.xml b/TMessagesProj/config/debug/AndroidManifest.xml
index 92a95c77883..b7f49c6f5da 100644
--- a/TMessagesProj/config/debug/AndroidManifest.xml
+++ b/TMessagesProj/config/debug/AndroidManifest.xml
@@ -18,7 +18,6 @@
readInt32(&error);
+ if ((flags & 2) != 0) {
+ otherwise_relogin_days = stream->readInt32(&error);
+ }
if ((flags & 1) != 0) {
tmp_sessions = stream->readInt32(&error);
}
+ if ((flags & 4) != 0) {
+ future_auth_token = std::unique_ptr(stream->readByteArray(&error));
+ }
user = std::unique_ptr(User::TLdeserialize(stream, stream->readUint32(&error), instanceNum, error));
}
diff --git a/TMessagesProj/jni/tgnet/ApiScheme.h b/TMessagesProj/jni/tgnet/ApiScheme.h
index 8f8a046e206..77a8da911a1 100644
--- a/TMessagesProj/jni/tgnet/ApiScheme.h
+++ b/TMessagesProj/jni/tgnet/ApiScheme.h
@@ -705,10 +705,12 @@ class TL_auth_authorizationSignUpRequired : public auth_Authorization {
class TL_auth_authorization : public auth_Authorization {
public:
- static const uint32_t constructor = 0x33fb7bb8;
+ static const uint32_t constructor = 0x2ea2c0d4;
int32_t flags;
int32_t tmp_sessions;
+ int32_t otherwise_relogin_days;
+ std::unique_ptr future_auth_token;
std::unique_ptr user;
void readParams(NativeByteBuffer *stream, int32_t instanceNum, bool &error);
diff --git a/TMessagesProj/jni/tgnet/ConnectionsManager.cpp b/TMessagesProj/jni/tgnet/ConnectionsManager.cpp
index a1a911edd8d..4e884a11851 100644
--- a/TMessagesProj/jni/tgnet/ConnectionsManager.cpp
+++ b/TMessagesProj/jni/tgnet/ConnectionsManager.cpp
@@ -891,10 +891,12 @@ void ConnectionsManager::onConnectionDataReceived(Connection *connection, Native
if (object != nullptr) {
if (datacenter->isHandshaking(connection->isMediaConnection)) {
+ if (LOGS_ENABLED) DEBUG_E("process handshake");
datacenter->processHandshakeResponse(connection->isMediaConnection, object, messageId);
} else {
- processServerResponse(object, messageId, 0, 0, connection, 0, 0);
- connection->addProcessedMessageId(messageId);
+ if (LOGS_ENABLED) DEBUG_E("connection(%p) received incorrect unencrypted message type", connection);
+ connection->reconnect();
+ return;
}
lastProtocolUsefullData = true;
connection->setHasUsefullData();
diff --git a/TMessagesProj/src/main/AndroidManifest.xml b/TMessagesProj/src/main/AndroidManifest.xml
index d350aa887d1..cd6a7009f5e 100644
--- a/TMessagesProj/src/main/AndroidManifest.xml
+++ b/TMessagesProj/src/main/AndroidManifest.xml
@@ -84,7 +84,9 @@
= 19) {
+ oldViewAnim.setUpdateListener(animation1 -> onChangeAnimationUpdate(changeInfo.oldHolder));
+ }
oldViewAnim
.setInterpolator(getChangeInterpolator())
.setListener(new AnimatorListenerAdapter() {
@@ -493,6 +509,9 @@ public void onAnimationEnd(Animator animator) {
if (animateByScale(newView) > 0) {
newViewAnimation.scaleX(1f).scaleY(1f);
}
+ if (Build.VERSION.SDK_INT >= 19) {
+ newViewAnimation.setUpdateListener(animation1 -> onChangeAnimationUpdate(changeInfo.newHolder));
+ }
newViewAnimation
.setListener(new AnimatorListenerAdapter() {
@Override
@@ -512,6 +531,8 @@ public void onAnimationEnd(Animator animator) {
dispatchChangeFinished(changeInfo.newHolder, false);
mChangeAnimations.remove(changeInfo.newHolder);
dispatchFinishedWhenDone();
+
+ afterAnimateChangeImpl(changeInfo.oldHolder, changeInfo.newHolder);
}
}).start();
}
diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/AndroidUtilities.java b/TMessagesProj/src/main/java/org/telegram/messenger/AndroidUtilities.java
index 7ab496f9dd1..639bd502aef 100644
--- a/TMessagesProj/src/main/java/org/telegram/messenger/AndroidUtilities.java
+++ b/TMessagesProj/src/main/java/org/telegram/messenger/AndroidUtilities.java
@@ -541,6 +541,27 @@ public static void recycleBitmap(Bitmap image) {
recycleBitmaps(Collections.singletonList(image));
}
+ public static boolean findClickableView(ViewGroup container, float x, float y) {
+ for (int i = 0; i < container.getChildCount(); i++) {
+ View child = container.getChildAt(i);
+ if (child.getVisibility() != View.VISIBLE) {
+ continue;
+ }
+ if (child.isClickable()) {
+ return true;
+ } else if (child instanceof ViewGroup && findClickableView((ViewGroup) child, x - child.getX(), y - child.getY())) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ public static void removeFromParent(View child) {
+ if (child.getParent() != null) {
+ ((ViewGroup) child.getParent()).removeView(child);
+ }
+ }
+
private static class LinkSpec {
String url;
int start;
@@ -2193,12 +2214,20 @@ public static String obtainLoginPhoneCall(String pattern) {
if (!hasCallPermissions) {
return null;
}
+ String order;
+ Bundle selectionArgs;
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
+ order = "date DESC";
+ } else {
+ order = "date DESC LIMIT 5";
+ }
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")) {
+ order
+ )) {
while (cursor.moveToNext()) {
String number = cursor.getString(0);
long date = cursor.getLong(1);
@@ -2926,7 +2955,9 @@ public static String formatFileSize(long size) {
}
public static String formatFileSize(long size, boolean removeZero) {
- if (size < 1024) {
+ if (size == 0) {
+ return String.format("%d KB", 0);
+ } else if (size < 1024) {
return String.format("%d B", size);
} else if (size < 1024 * 1024) {
float value = size / 1024.0f;
@@ -2935,7 +2966,7 @@ public static String formatFileSize(long size, boolean removeZero) {
} else {
return String.format("%.1f KB", value);
}
- } else if (size < 1024 * 1024 * 1024) {
+ } else if (size < 1000 * 1024 * 1024) {
float value = size / 1024.0f / 1024.0f;
if (removeZero && (value - (int) value) * 10 == 0) {
return String.format("%d MB", (int) value);
@@ -3633,7 +3664,7 @@ public static void showProxyAlert(Activity activity, final String address, final
lineView.setBackgroundColor(Theme.getColor(Theme.key_divider));
linearLayout.addView(lineView, new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, 1));
}
- for (int a = 0; a < 5; a++) {
+ for (int a = 0; a < 6; a++) {
String text = null;
String detail = null;
if (a == 0) {
@@ -3651,6 +3682,9 @@ public static void showProxyAlert(Activity activity, final String address, final
} else if (a == 4) {
text = password;
detail = LocaleController.getString("UseProxyPassword", R.string.UseProxyPassword);
+ } else if (a == 5) {
+ text = LocaleController.getString(R.string.Checking);
+ detail = LocaleController.getString(R.string.ProxyStatus);
}
if (TextUtils.isEmpty(text)) {
continue;
@@ -3660,8 +3694,22 @@ public static void showProxyAlert(Activity activity, final String address, final
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 == 2) {
- break;
+
+ if (a == 5) {
+ try {
+ ConnectionsManager.getInstance(UserConfig.selectedAccount).checkProxy(address, Integer.parseInt(port), user, password, secret, time -> AndroidUtilities.runOnUIThread(() -> {
+ if (time == -1) {
+ cell.getTextView().setText(LocaleController.getString(R.string.Unavailable));
+ cell.getTextView().setTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteRedText4));
+ } else {
+ cell.getTextView().setText(LocaleController.getString(R.string.Available) + ", " + LocaleController.formatString(R.string.Ping, time));
+ cell.getTextView().setTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteGreenText));
+ }
+ }));
+ } catch (NumberFormatException ignored) {
+ cell.getTextView().setText(LocaleController.getString(R.string.Unavailable));
+ cell.getTextView().setTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteRedText4));
+ }
}
}
@@ -4664,18 +4712,36 @@ public static CharSequence replaceCharSequence(String what, CharSequence from, C
return spannableStringBuilder;
}
+ public static CharSequence replaceMultipleCharSequence(String what, CharSequence from, CharSequence obj) {
+ SpannableStringBuilder spannableStringBuilder;
+ if (from instanceof SpannableStringBuilder) {
+ spannableStringBuilder = (SpannableStringBuilder) from;
+ } else {
+ spannableStringBuilder = new SpannableStringBuilder(from);
+ }
+ int index = TextUtils.indexOf(from, what);
+ while (index >= 0) {
+ spannableStringBuilder.replace(index, index + what.length(), obj);
+ index = TextUtils.indexOf(spannableStringBuilder, what);
+ }
+ return spannableStringBuilder;
+ }
+
public static Bitmap makeBlurBitmap(View view) {
+ return makeBlurBitmap(view, 6f, 7);
+ }
+ public static Bitmap makeBlurBitmap(View view, float downscale, int maxRadius) {
if (view == null) {
return null;
}
- int w = (int) (view.getWidth() / 6.0f);
- int h = (int) (view.getHeight() / 6.0f);
+ int w = (int) (view.getWidth() / downscale);
+ int h = (int) (view.getHeight() / downscale);
Bitmap bitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(bitmap);
- canvas.scale(1.0f / 6.0f, 1.0f / 6.0f);
+ canvas.scale(1.0f / downscale, 1.0f / downscale);
canvas.drawColor(Theme.getColor(Theme.key_windowBackgroundWhite));
view.draw(canvas);
- Utilities.stackBlurBitmap(bitmap, Math.max(7, Math.max(w, h) / 180));
+ Utilities.stackBlurBitmap(bitmap, Math.max(maxRadius, Math.max(w, h) / 180));
return bitmap;
}
@@ -4808,4 +4874,54 @@ public static int[] roundPercents(float[] percents, int[] output) {
return output;
}
+
+ public static boolean isRTL(CharSequence text) {
+ if (text == null || text.length() <= 0) {
+ return false;
+ }
+ char c;
+ for (int i = 0; i < text.length(); ++i) {
+ c = text.charAt(i);
+ if (c >= 0x590 && c <= 0x6ff) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ private static Pattern uriParse;
+ private static Pattern getURIParsePattern() {
+ if (uriParse == null) {
+ uriParse = Pattern.compile("^(([^:/?#]+):)?(//([^/?#]*))?([^?#]*)(\\?([^#]*))?(#(.*))?"); // RFC 3986 B
+ }
+ return uriParse;
+ }
+
+ public static String getHostAuthority(String uri) {
+ if (uri == null) {
+ return null;
+ }
+ // CVE-2017-13274
+ Matcher matcher = getURIParsePattern().matcher(uri);
+ if (matcher.matches()) {
+ String authority = matcher.group(4);
+ if (authority != null) {
+ authority = authority.toLowerCase();
+ }
+ return authority;
+ }
+ return null;
+ }
+
+ public static String getHostAuthority(Uri uri) {
+ if (uri == null) {
+ return null;
+ }
+ return getHostAuthority(uri.toString());
+ }
+
+ public static boolean intersect1d(int x1, int x2, int y1, int y2) {
+ return Math.max(x1, x2) >= Math.min(y1, y2) && Math.max(y1, y2) >= Math.min(x1, x2);
+ }
+
}
diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/ApplicationLoader.java b/TMessagesProj/src/main/java/org/telegram/messenger/ApplicationLoader.java
index d449fc06895..194ff0ca724 100644
--- a/TMessagesProj/src/main/java/org/telegram/messenger/ApplicationLoader.java
+++ b/TMessagesProj/src/main/java/org/telegram/messenger/ApplicationLoader.java
@@ -278,6 +278,7 @@ public void onActivityStarted(Activity activity) {
AndroidUtilities.runOnUIThread(ApplicationLoader::startPushService);
LauncherIconController.tryFixLauncherIconIfNeeded();
+ ProxyRotationController.init();
}
public static void startPushService() {
diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/AuthTokensHelper.java b/TMessagesProj/src/main/java/org/telegram/messenger/AuthTokensHelper.java
new file mode 100644
index 00000000000..045670cba4f
--- /dev/null
+++ b/TMessagesProj/src/main/java/org/telegram/messenger/AuthTokensHelper.java
@@ -0,0 +1,119 @@
+package org.telegram.messenger;
+
+import android.content.Context;
+import android.content.SharedPreferences;
+
+import com.google.android.exoplayer2.util.Log;
+
+import org.telegram.tgnet.SerializedData;
+import org.telegram.tgnet.TLRPC;
+
+import java.nio.charset.StandardCharsets;
+import java.util.ArrayList;
+
+public class AuthTokensHelper {
+
+ public static ArrayList getSavedLogOutTokens() {
+ SharedPreferences preferences = ApplicationLoader.applicationContext.getSharedPreferences("saved_tokens", Context.MODE_PRIVATE);
+ int count = preferences.getInt("count", 0);
+
+ if (count == 0) {
+ return null;
+ }
+
+ ArrayList tokens = new ArrayList<>();
+ for (int i = 0; i < count; i++) {
+ String value = preferences.getString("log_out_token_" + i, "");
+ SerializedData serializedData = new SerializedData(Utilities.hexToBytes(value));
+ TLRPC.TL_auth_loggedOut token = TLRPC.TL_auth_loggedOut.TLdeserialize(serializedData, serializedData.readInt32(true), true);
+ if (token != null) {
+ tokens.add(token);
+ }
+ }
+
+ return tokens;
+ }
+
+ public static void saveLogOutTokens(ArrayList tokens) {
+ SharedPreferences preferences = ApplicationLoader.applicationContext.getSharedPreferences("saved_tokens", Context.MODE_PRIVATE);
+ ArrayList activeTokens = new ArrayList<>();
+ preferences.edit().clear().apply();
+ int date = (int) (System.currentTimeMillis() / 1000L);
+ for (int i = 0; i < Math.min(20, tokens.size()); i++) {
+ activeTokens.add(tokens.get(i));
+ }
+ if (activeTokens.size() > 0) {
+ SharedPreferences.Editor editor = preferences.edit();
+ editor.putInt("count", activeTokens.size());
+ for (int i = 0; i < activeTokens.size(); i++) {
+ SerializedData data = new SerializedData(activeTokens.get(i).getObjectSize());
+ activeTokens.get(i).serializeToStream(data);
+ editor.putString("log_out_token_" + i, Utilities.bytesToHex(data.toByteArray()));
+ }
+ editor.apply();
+ // BackupAgent.requestBackup(ApplicationLoader.applicationContext);
+ }
+ }
+
+ public static ArrayList getSavedLogInTokens() {
+ SharedPreferences preferences = ApplicationLoader.applicationContext.getSharedPreferences("saved_tokens_login", Context.MODE_PRIVATE);
+ int count = preferences.getInt("count", 0);
+
+ if (count == 0) {
+ return null;
+ }
+
+ ArrayList tokens = new ArrayList<>();
+ for (int i = 0; i < count; i++) {
+ String value = preferences.getString("log_in_token_" + i, "");
+ SerializedData serializedData = new SerializedData(Utilities.hexToBytes(value));
+ TLRPC.auth_Authorization token = TLRPC.auth_Authorization.TLdeserialize(serializedData, serializedData.readInt32(true), true);
+ if (token instanceof TLRPC.TL_auth_authorization) {
+ tokens.add((TLRPC.TL_auth_authorization) token);
+ }
+ }
+
+ return tokens;
+ }
+
+ public static void saveLogInToken(TLRPC.TL_auth_authorization token) {
+ if (BuildVars.DEBUG_VERSION) {
+ FileLog.d("saveLogInToken " + new String(token.future_auth_token, StandardCharsets.UTF_8));
+ }
+ ArrayList tokens = getSavedLogInTokens();
+ if (tokens == null) {
+ tokens = new ArrayList<>();
+ }
+ tokens.add(0, token);
+ saveLogInTokens(tokens);
+ }
+
+ private static void saveLogInTokens(ArrayList tokens) {
+ SharedPreferences preferences = ApplicationLoader.applicationContext.getSharedPreferences("saved_tokens_login", Context.MODE_PRIVATE);
+ ArrayList activeTokens = new ArrayList<>();
+ preferences.edit().clear().apply();
+ for (int i = 0; i < Math.min(20, tokens.size()); i++) {
+ activeTokens.add(tokens.get(i));
+ }
+ if (activeTokens.size() > 0) {
+ SharedPreferences.Editor editor = preferences.edit();
+ editor.putInt("count", activeTokens.size());
+ for (int i = 0; i < activeTokens.size(); i++) {
+ SerializedData data = new SerializedData(activeTokens.get(i).getObjectSize());
+ activeTokens.get(i).serializeToStream(data);
+ editor.putString("log_in_token_" + i, Utilities.bytesToHex(data.toByteArray()));
+ }
+ editor.apply();
+ BackupAgent.requestBackup(ApplicationLoader.applicationContext);
+ }
+ }
+
+ public static void addLogOutToken(TLRPC.TL_auth_loggedOut response) {
+ SharedPreferences preferences = ApplicationLoader.applicationContext.getSharedPreferences("saved_tokens", Context.MODE_PRIVATE);
+ int count = preferences.getInt("count", 0);
+ SerializedData data = new SerializedData(response.getObjectSize());
+ response.serializeToStream(data);
+ preferences.edit().putString("log_out_token_" + count, Utilities.bytesToHex(data.toByteArray())).putInt("count", count + 1).apply();
+ BackupAgent.requestBackup(ApplicationLoader.applicationContext);
+ }
+}
diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/BackupAgent.java b/TMessagesProj/src/main/java/org/telegram/messenger/BackupAgent.java
new file mode 100644
index 00000000000..78ff6ee838f
--- /dev/null
+++ b/TMessagesProj/src/main/java/org/telegram/messenger/BackupAgent.java
@@ -0,0 +1,35 @@
+package org.telegram.messenger;
+
+import android.app.backup.BackupAgentHelper;
+import android.app.backup.BackupDataInput;
+import android.app.backup.BackupDataOutput;
+import android.app.backup.BackupManager;
+import android.app.backup.FullBackupDataOutput;
+import android.app.backup.RestoreObserver;
+import android.app.backup.SharedPreferencesBackupHelper;
+import android.content.Context;
+import android.os.ParcelFileDescriptor;
+import android.util.Log;
+
+import org.telegram.tgnet.TLRPC;
+
+import java.io.IOException;
+import java.util.ArrayList;
+
+public class BackupAgent extends BackupAgentHelper {
+
+ private static BackupManager backupManager;
+
+ @Override
+ public void onCreate() {
+ SharedPreferencesBackupHelper helper = new SharedPreferencesBackupHelper(this, "saved_tokens", "saved_tokens_login");
+ addHelper("prefs", helper);
+ }
+
+ public static void requestBackup(Context context) {
+ if (backupManager == null) {
+ backupManager = new BackupManager(context);
+ }
+ backupManager.dataChanged();
+ }
+}
diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/BillingController.java b/TMessagesProj/src/main/java/org/telegram/messenger/BillingController.java
index 23ed977fa61..1a568b401d6 100644
--- a/TMessagesProj/src/main/java/org/telegram/messenger/BillingController.java
+++ b/TMessagesProj/src/main/java/org/telegram/messenger/BillingController.java
@@ -54,6 +54,8 @@ public class BillingController implements PurchasesUpdatedListener, BillingClien
private Map> resultListeners = new HashMap<>();
private List requestingTokens = new ArrayList<>();
+ private String lastPremiumTransaction;
+ private String lastPremiumToken;
private Map currencyExpMap = new HashMap<>();
@@ -73,6 +75,14 @@ private BillingController(Context ctx) {
.build();
}
+ public String getLastPremiumTransaction() {
+ return lastPremiumTransaction;
+ }
+
+ public String getLastPremiumToken() {
+ return lastPremiumToken;
+ }
+
public String formatCurrency(long amount, String currency) {
return formatCurrency(amount, currency, getCurrencyExp(currency));
}
@@ -156,10 +166,10 @@ public void addResultListener(String productId, Consumer listener
}
public void launchBillingFlow(Activity activity, AccountInstance accountInstance, TLRPC.InputStorePaymentPurpose paymentPurpose, List productDetails) {
- launchBillingFlow(activity, accountInstance, paymentPurpose, productDetails, false);
+ launchBillingFlow(activity, accountInstance, paymentPurpose, productDetails, null, false);
}
- public void launchBillingFlow(Activity activity, AccountInstance accountInstance, TLRPC.InputStorePaymentPurpose paymentPurpose, List productDetails, boolean checkedConsume) {
+ public void launchBillingFlow(Activity activity, AccountInstance accountInstance, TLRPC.InputStorePaymentPurpose paymentPurpose, List productDetails, BillingFlowParams.SubscriptionUpdateParams subscriptionUpdateParams, boolean checkedConsume) {
if (!isReady() || activity == null) {
return;
}
@@ -167,7 +177,7 @@ public void launchBillingFlow(Activity activity, AccountInstance accountInstance
if (paymentPurpose instanceof TLRPC.TL_inputStorePaymentGiftPremium && !checkedConsume) {
queryPurchases(BillingClient.ProductType.INAPP, (billingResult, list) -> {
if (billingResult.getResponseCode() == BillingClient.BillingResponseCode.OK) {
- Runnable callback = () -> launchBillingFlow(activity, accountInstance, paymentPurpose, productDetails, true);
+ Runnable callback = () -> launchBillingFlow(activity, accountInstance, paymentPurpose, productDetails, subscriptionUpdateParams, true);
AtomicInteger productsToBeConsumed = new AtomicInteger(0);
List productsConsumed = new ArrayList<>();
@@ -205,9 +215,12 @@ public void launchBillingFlow(Activity activity, AccountInstance accountInstance
return;
}
- boolean ok = billingClient.launchBillingFlow(activity, BillingFlowParams.newBuilder()
- .setProductDetailsParamsList(productDetails)
- .build()).getResponseCode() == BillingClient.BillingResponseCode.OK;
+ BillingFlowParams.Builder flowParams = BillingFlowParams.newBuilder()
+ .setProductDetailsParamsList(productDetails);
+ if (subscriptionUpdateParams != null) {
+ flowParams.setSubscriptionUpdateParams(subscriptionUpdateParams);
+ }
+ boolean ok = billingClient.launchBillingFlow(activity, flowParams.build()).getResponseCode() == BillingClient.BillingResponseCode.OK;
if (ok) {
for (BillingFlowParams.ProductDetailsParams params : productDetails) {
@@ -240,7 +253,13 @@ public void onPurchasesUpdated(@NonNull BillingResult billingResult, @Nullable L
if (list == null) {
return;
}
+ lastPremiumTransaction = null;
for (Purchase purchase : list) {
+ if (purchase.getProducts().contains(PREMIUM_PRODUCT_ID)) {
+ lastPremiumTransaction = purchase.getOrderId();
+ lastPremiumToken = purchase.getPurchaseToken();
+ }
+
if (!requestingTokens.contains(purchase.getPurchaseToken())) {
for (int i = 0; i < UserConfig.MAX_ACCOUNT_COUNT; i++) {
AccountInstance acc = AccountInstance.getInstance(i);
diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/BuildVars.java b/TMessagesProj/src/main/java/org/telegram/messenger/BuildVars.java
index 194a65e389b..63052129fc6 100644
--- a/TMessagesProj/src/main/java/org/telegram/messenger/BuildVars.java
+++ b/TMessagesProj/src/main/java/org/telegram/messenger/BuildVars.java
@@ -24,11 +24,13 @@ public class BuildVars {
public static boolean USE_CLOUD_STRINGS = true;
public static boolean CHECK_UPDATES = true;
public static boolean NO_SCOPED_STORAGE = Build.VERSION.SDK_INT <= 29;
- public static int BUILD_VERSION = 3026;
- public static String BUILD_VERSION_STRING = "9.3.3";
+ public static int BUILD_VERSION = 3098;
+ public static String BUILD_VERSION_STRING = "9.4.0";
public static int APP_ID = 4;
public static String APP_HASH = "014b35b6184100b085b0d0572f9b5103";
+ // SafetyNet key for Google Identity SDK, set it to empty to disable
+ public static String SAFETYNET_KEY = "AIzaSyDqt8P-7F7CPCseMkOiVRgb1LY8RN1bvH8";
public static String SMS_HASH = isStandaloneApp() ? "w0lkcmTZkKh" : (DEBUG_VERSION ? "O2P2z+/jBpJ" : "oLeq9AcOZkT");
public static String PLAYSTORE_APP_URL = "https://play.google.com/store/apps/details?id=org.telegram.messenger";
public static String GOOGLE_AUTH_CLIENT_ID = "760348033671-81kmi3pi84p11ub8hp9a1funsv0rn2p9.apps.googleusercontent.com";
diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/ChatObject.java b/TMessagesProj/src/main/java/org/telegram/messenger/ChatObject.java
index bd471c81a02..65ab143c5ab 100644
--- a/TMessagesProj/src/main/java/org/telegram/messenger/ChatObject.java
+++ b/TMessagesProj/src/main/java/org/telegram/messenger/ChatObject.java
@@ -38,6 +38,7 @@ public class ChatObject {
public static final int CHAT_TYPE_CHANNEL = 2;
public static final int CHAT_TYPE_USER = 3;
public static final int CHAT_TYPE_MEGAGROUP = 4;
+ public static final int CHAT_TYPE_FORUM = 5;
public static final int ACTION_PIN = 0;
public static final int ACTION_CHANGE_INFO = 1;
@@ -46,6 +47,7 @@ public class ChatObject {
public static final int ACTION_ADD_ADMINS = 4;
public static final int ACTION_POST = 5;
public static final int ACTION_SEND = 6;
+ public static final int ACTION_SEND_TEXT = 22;
public static final int ACTION_SEND_MEDIA = 7;
public static final int ACTION_SEND_STICKERS = 8;
public static final int ACTION_EMBED_LINKS = 9;
@@ -56,6 +58,15 @@ public class ChatObject {
public static final int ACTION_MANAGE_CALLS = 14;
public static final int ACTION_MANAGE_TOPICS = 15;
+ public static final int ACTION_SEND_PHOTO = 16;
+ public static final int ACTION_SEND_VIDEO = 17;
+ public static final int ACTION_SEND_MUSIC = 18;
+ public static final int ACTION_SEND_DOCUMENTS = 19;
+ public static final int ACTION_SEND_VOICE = 20;
+ public static final int ACTION_SEND_ROUND = 21;
+ public static final int ACTION_SEND_PLAIN = 22;
+ public static final int ACTION_SEND_GIFS = 23;
+
public final static int VIDEO_FRAME_NO_FRAME = 0;
public final static int VIDEO_FRAME_REQUESTING = 1;
public final static int VIDEO_FRAME_HAS_FRAME = 2;
@@ -85,6 +96,61 @@ public static boolean isForum(int currentAccount, long dialogId) {
return false;
}
+ public static boolean canSendAnyMedia(TLRPC.Chat currentChat) {
+ return canSendPhoto(currentChat) || canSendVideo(currentChat) || canSendRoundVideo(currentChat)|| canSendVoice(currentChat) || canSendDocument(currentChat) || canSendMusic(currentChat) || canSendStickers(currentChat);
+ }
+
+ public static String getAllowedSendString(TLRPC.Chat chat) {
+ StringBuilder stringBuilder = new StringBuilder();
+ if (ChatObject.canSendPhoto(chat)) {
+ stringBuilder.append(LocaleController.getString("SendMediaPermissionPhotos", R.string.SendMediaPermissionPhotos));
+ }
+ if (ChatObject.canSendVideo(chat)) {
+ if (stringBuilder.length() > 0) {
+ stringBuilder.append(", ");
+ }
+ stringBuilder.append(LocaleController.getString("SendMediaPermissionVideos", R.string.SendMediaPermissionVideos));
+ }
+ if (ChatObject.canSendStickers(chat)) {
+ if (stringBuilder.length() > 0) {
+ stringBuilder.append(", ");
+ }
+ stringBuilder.append(LocaleController.getString("SendMediaPermissionStickersGifs", R.string.SendMediaPermissionStickersGifs));
+ }
+ if (ChatObject.canSendMusic(chat)) {
+ if (stringBuilder.length() > 0) {
+ stringBuilder.append(", ");
+ }
+ stringBuilder.append(LocaleController.getString("SendMediaPermissionMusic", R.string.SendMediaPermissionMusic));
+ }
+ if (ChatObject.canSendDocument(chat)) {
+ if (stringBuilder.length() > 0) {
+ stringBuilder.append(", ");
+ }
+ stringBuilder.append(LocaleController.getString("SendMediaPermissionFiles", R.string.SendMediaPermissionFiles));
+ }
+ if (ChatObject.canSendVoice(chat)) {
+ if (stringBuilder.length() > 0) {
+ stringBuilder.append(", ");
+ }
+ stringBuilder.append(LocaleController.getString("SendMediaPermissionVoice", R.string.SendMediaPermissionVoice));
+ }
+ if (ChatObject.canSendRoundVideo(chat)) {
+ if (stringBuilder.length() > 0) {
+ stringBuilder.append(", ");
+ }
+ stringBuilder.append(LocaleController.getString("SendMediaPermissionRound", R.string.SendMediaPermissionRound));
+ }
+ if (ChatObject.canSendEmbed(chat)) {
+ if (stringBuilder.length() > 0) {
+ stringBuilder.append(", ");
+ }
+ stringBuilder.append(LocaleController.getString("SendMediaEmbededLinks", R.string.SendMediaEmbededLinks));
+ }
+
+ return stringBuilder.toString();
+ }
+
public static class Call {
public final static int RECORD_TYPE_AUDIO = 0,
RECORD_TYPE_VIDEO_PORTAIT = 1,
@@ -1412,6 +1478,13 @@ private static boolean isBannableAction(int action) {
case ACTION_SEND_POLLS:
case ACTION_VIEW:
case ACTION_MANAGE_TOPICS:
+ case ACTION_SEND_PHOTO:
+ case ACTION_SEND_VIDEO:
+ case ACTION_SEND_MUSIC:
+ case ACTION_SEND_DOCUMENTS:
+ case ACTION_SEND_VOICE:
+ case ACTION_SEND_ROUND:
+ case ACTION_SEND_PLAIN:
return true;
}
return false;
@@ -1459,14 +1532,31 @@ private static boolean getBannedRight(TLRPC.TL_chatBannedRights rights, int acti
return rights.view_messages;
case ACTION_MANAGE_TOPICS:
return rights.manage_topics;
+ case ACTION_SEND_PHOTO:
+ return rights.send_photos;
+ case ACTION_SEND_VIDEO:
+ return rights.send_videos;
+ case ACTION_SEND_MUSIC:
+ return rights.send_audios;
+ case ACTION_SEND_DOCUMENTS:
+ return rights.send_docs;
+ case ACTION_SEND_VOICE:
+ return rights.send_voices;
+ case ACTION_SEND_ROUND:
+ return rights.send_roundvideos;
+ case ACTION_SEND_PLAIN:
+ return rights.send_plain;
}
return false;
}
public static boolean isActionBannedByDefault(TLRPC.Chat chat, int action) {
- if (getBannedRight(chat.banned_rights, action)) {
+ if (chat == null) {
return false;
}
+ if (getBannedRight(chat.banned_rights, action) && getBannedRight(chat.default_banned_rights, action)) {
+ return true;
+ }
return getBannedRight(chat.default_banned_rights, action);
}
@@ -1628,8 +1718,31 @@ public static boolean canSendEmbed(TLRPC.Chat chat) {
return canUserDoAction(chat, ACTION_EMBED_LINKS);
}
- public static boolean canSendMedia(TLRPC.Chat chat) {
- return canUserDoAction(chat, ACTION_SEND_MEDIA);
+ // public static boolean canSendMedia(TLRPC.Chat chat) {
+// return canUserDoAction(chat, ACTION_SEND_MEDIA);
+// }
+ public static boolean canSendPhoto(TLRPC.Chat chat) {
+ return canUserDoAction(chat, ACTION_SEND_PHOTO);
+ }
+
+ public static boolean canSendVideo(TLRPC.Chat chat) {
+ return canUserDoAction(chat, ACTION_SEND_VIDEO);
+ }
+
+ public static boolean canSendMusic(TLRPC.Chat chat) {
+ return canUserDoAction(chat, ACTION_SEND_MUSIC);
+ }
+
+ public static boolean canSendDocument(TLRPC.Chat chat) {
+ return canUserDoAction(chat, ACTION_SEND_DOCUMENTS);
+ }
+
+ public static boolean canSendVoice(TLRPC.Chat chat) {
+ return canUserDoAction(chat, ACTION_SEND_VOICE);
+ }
+
+ public static boolean canSendRoundVideo(TLRPC.Chat chat) {
+ return canUserDoAction(chat, ACTION_SEND_ROUND);
}
public static boolean canSendPolls(TLRPC.Chat chat) {
@@ -1640,6 +1753,10 @@ public static boolean canSendMessages(TLRPC.Chat chat) {
return canUserDoAction(chat, ACTION_SEND);
}
+ public static boolean canSendPlain(TLRPC.Chat chat) {
+ return canUserDoAction(chat, ACTION_SEND_PLAIN);
+ }
+
public static boolean canPost(TLRPC.Chat chat) {
return canUserDoAction(chat, ACTION_POST);
}
@@ -1760,6 +1877,13 @@ public static String getBannedRightsString(TLRPC.TL_chatBannedRights bannedRight
currentBannedRights += bannedRights.change_info ? 1 : 0;
currentBannedRights += bannedRights.pin_messages ? 1 : 0;
currentBannedRights += bannedRights.manage_topics ? 1 : 0;
+ currentBannedRights += bannedRights.send_photos ? 1 : 0;
+ currentBannedRights += bannedRights.send_videos ? 1 : 0;
+ currentBannedRights += bannedRights.send_roundvideos ? 1 : 0;
+ currentBannedRights += bannedRights.send_voices ? 1 : 0;
+ currentBannedRights += bannedRights.send_audios ? 1 : 0;
+ currentBannedRights += bannedRights.send_docs ? 1 : 0;
+ currentBannedRights += bannedRights.send_plain ? 1 : 0;
currentBannedRights += bannedRights.until_date;
return currentBannedRights;
}
@@ -1819,6 +1943,93 @@ public static boolean isPublic(TLRPC.Chat chat) {
return !TextUtils.isEmpty(getPublicUsername(chat));
}
+ public static String getRestrictedErrorText(TLRPC.Chat chat, int action) {
+ if (action == ACTION_SEND_GIFS) {
+ if (chat == null || ChatObject.isActionBannedByDefault(chat, action)) {
+ return LocaleController.getString("GlobalAttachGifRestricted", R.string.GlobalAttachGifRestricted);
+ } else if (AndroidUtilities.isBannedForever(chat.banned_rights)) {
+ return LocaleController.formatString("AttachGifRestrictedForever", R.string.AttachGifRestrictedForever);
+ } else {
+ return LocaleController.formatString("AttachGifRestricted", R.string.AttachGifRestricted, LocaleController.formatDateForBan(chat.banned_rights.until_date));
+ }
+ } else if (action == ACTION_SEND_STICKERS) {
+ if (chat == null || ChatObject.isActionBannedByDefault(chat, action)) {
+ return LocaleController.getString("GlobalAttachStickersRestricted", R.string.GlobalAttachStickersRestricted);
+ } else if (AndroidUtilities.isBannedForever(chat.banned_rights)) {
+ return LocaleController.formatString("AttachStickersRestrictedForever", R.string.AttachStickersRestrictedForever);
+ } else {
+ return LocaleController.formatString("AttachStickersRestricted", R.string.AttachStickersRestricted, LocaleController.formatDateForBan(chat.banned_rights.until_date));
+ }
+ } else if (action == ACTION_SEND_PHOTO) {
+ if (chat == null || ChatObject.isActionBannedByDefault(chat, action)) {
+ return LocaleController.getString("GlobalAttachPhotoRestricted", R.string.GlobalAttachPhotoRestricted);
+ } else if (AndroidUtilities.isBannedForever(chat.banned_rights)) {
+ return LocaleController.formatString("AttachPhotoRestrictedForever", R.string.AttachPhotoRestrictedForever);
+ } else {
+ return LocaleController.formatString("AttachPhotoRestricted", R.string.AttachPhotoRestricted, LocaleController.formatDateForBan(chat.banned_rights.until_date));
+ }
+ } else if (action == ACTION_SEND_VIDEO) {
+ if (chat == null || ChatObject.isActionBannedByDefault(chat, action)) {
+ return LocaleController.getString("GlobalAttachVideoRestricted", R.string.GlobalAttachVideoRestricted);
+ } else if (AndroidUtilities.isBannedForever(chat.banned_rights)) {
+ return LocaleController.formatString("AttachVideoRestrictedForever", R.string.AttachVideoRestrictedForever);
+ } else {
+ return LocaleController.formatString("AttachVideoRestricted", R.string.AttachVideoRestricted, LocaleController.formatDateForBan(chat.banned_rights.until_date));
+ }
+ } else if (action == ACTION_SEND_DOCUMENTS) {
+ if (chat == null || ChatObject.isActionBannedByDefault(chat, action)) {
+ return LocaleController.getString("GlobalAttachDocumentsRestricted", R.string.GlobalAttachDocumentsRestricted);
+ } else if (AndroidUtilities.isBannedForever(chat.banned_rights)) {
+ return LocaleController.formatString("AttachDocumentsRestrictedForever", R.string.AttachDocumentsRestrictedForever);
+ } else {
+ return LocaleController.formatString("AttachDocumentsRestricted", R.string.AttachDocumentsRestricted, LocaleController.formatDateForBan(chat.banned_rights.until_date));
+ }
+ } else if (action == ACTION_SEND_MEDIA) {
+ if (chat == null || ChatObject.isActionBannedByDefault(chat, action)) {
+ return LocaleController.getString("GlobalAttachMediaRestricted", R.string.GlobalAttachMediaRestricted);
+ } else if (AndroidUtilities.isBannedForever(chat.banned_rights)) {
+ return LocaleController.formatString("AttachMediaRestrictedForever", R.string.AttachMediaRestrictedForever);
+ } else {
+ return LocaleController.formatString("AttachMediaRestricted", R.string.AttachMediaRestricted, LocaleController.formatDateForBan(chat.banned_rights.until_date));
+ }
+ } else if (action == ACTION_SEND_MUSIC) {
+ if (chat == null || ChatObject.isActionBannedByDefault(chat, action)) {
+ return LocaleController.getString("GlobalAttachAudioRestricted", R.string.GlobalAttachAudioRestricted);
+ } else if (AndroidUtilities.isBannedForever(chat.banned_rights)) {
+ return LocaleController.formatString("AttachAudioRestrictedForever", R.string.AttachAudioRestrictedForever);
+ } else {
+ return LocaleController.formatString("AttachAudioRestricted", R.string.AttachAudioRestricted, LocaleController.formatDateForBan(chat.banned_rights.until_date));
+ }
+ } else if (action == ACTION_SEND_PLAIN) {
+ if (chat == null || ChatObject.isActionBannedByDefault(chat, action)) {
+ return LocaleController.getString("GlobalAttachPlainRestricted", R.string.GlobalAttachPlainRestricted);
+ } else if (AndroidUtilities.isBannedForever(chat.banned_rights)) {
+ return LocaleController.formatString("AttachPlainRestrictedForever", R.string.AttachPlainRestrictedForever);
+ } else {
+ return LocaleController.formatString("AttachPlainRestricted", R.string.AttachPlainRestricted, LocaleController.formatDateForBan(chat.banned_rights.until_date));
+ }
+ } else if (action == ACTION_SEND_ROUND) {
+ if (chat == null || ChatObject.isActionBannedByDefault(chat, action)) {
+ return LocaleController.getString("GlobalAttachRoundRestricted", R.string.GlobalAttachRoundRestricted);
+ } else if (AndroidUtilities.isBannedForever(chat.banned_rights)) {
+ return LocaleController.formatString("AttachRoundRestrictedForever", R.string.AttachRoundRestrictedForever);
+ } else {
+ return LocaleController.formatString("AttachRoundRestricted", R.string.AttachRoundRestricted, LocaleController.formatDateForBan(chat.banned_rights.until_date));
+ }
+ } else if (action == ACTION_SEND_VOICE) {
+ if (chat == null || ChatObject.isActionBannedByDefault(chat, action)) {
+ return LocaleController.getString("GlobalAttachVoiceRestricted", R.string.GlobalAttachVoiceRestricted);
+ } else if (AndroidUtilities.isBannedForever(chat.banned_rights)) {
+ return LocaleController.formatString("AttachVoiceRestrictedForever", R.string.AttachVoiceRestrictedForever);
+ } else {
+ return LocaleController.formatString("AttachVoiceRestricted", R.string.AttachVoiceRestricted, LocaleController.formatDateForBan(chat.banned_rights.until_date));
+ }
+ }
+
+ return "";
+ }
+
+
public static class VideoParticipant {
public TLRPC.TL_groupCallParticipant participant;
diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/ContactsController.java b/TMessagesProj/src/main/java/org/telegram/messenger/ContactsController.java
index 3a2020d4fdc..fd23f542132 100644
--- a/TMessagesProj/src/main/java/org/telegram/messenger/ContactsController.java
+++ b/TMessagesProj/src/main/java/org/telegram/messenger/ContactsController.java
@@ -762,7 +762,7 @@ public HashMap readContactsFromPhoneBook() {
String lookup_key = cur.getString(cur.getColumnIndex(ContactsContract.Contacts.LOOKUP_KEY));
String name = cur.getString(cur.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME));
String phone = null;
- if (contactsMap.get(lookup_key) != null || TextUtils.isEmpty(name)) {
+ if ((contactsMap != null && contactsMap.get(lookup_key) != null) || TextUtils.isEmpty(name)) {
continue;
}
pCur = cr.query(
diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/DatabaseMigrationHelper.java b/TMessagesProj/src/main/java/org/telegram/messenger/DatabaseMigrationHelper.java
index 1ecc488f48c..db5c54af32a 100644
--- a/TMessagesProj/src/main/java/org/telegram/messenger/DatabaseMigrationHelper.java
+++ b/TMessagesProj/src/main/java/org/telegram/messenger/DatabaseMigrationHelper.java
@@ -1218,6 +1218,12 @@ public static int migrate(MessagesStorage messagesStorage, int version) throws E
version = 111;
}
+ if (version == 111) {
+ database.executeFast("CREATE TABLE emoji_groups(type INTEGER PRIMARY KEY, data BLOB)").stepThis().dispose();
+ database.executeFast("PRAGMA user_version = 112").stepThis().dispose();
+ version = 112;
+ }
+
return version;
}
}
diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/DocumentObject.java b/TMessagesProj/src/main/java/org/telegram/messenger/DocumentObject.java
index cc2f161b153..b63fe281065 100644
--- a/TMessagesProj/src/main/java/org/telegram/messenger/DocumentObject.java
+++ b/TMessagesProj/src/main/java/org/telegram/messenger/DocumentObject.java
@@ -116,7 +116,10 @@ public static SvgHelper.SvgDrawable getSvgThumb(TLRPC.Document document, String
int w = 512, h = 512;
for (int a = 0, N = document.attributes.size(); a < N; a++) {
TLRPC.DocumentAttribute attribute = document.attributes.get(a);
- if (attribute instanceof TLRPC.TL_documentAttributeImageSize) {
+ if (
+ attribute instanceof TLRPC.TL_documentAttributeImageSize ||
+ attribute instanceof TLRPC.TL_documentAttributeVideo
+ ) {
w = attribute.w;
h = attribute.h;
break;
diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/Emoji.java b/TMessagesProj/src/main/java/org/telegram/messenger/Emoji.java
index d036520ee41..58fb9d41f87 100644
--- a/TMessagesProj/src/main/java/org/telegram/messenger/Emoji.java
+++ b/TMessagesProj/src/main/java/org/telegram/messenger/Emoji.java
@@ -64,6 +64,15 @@ public class Emoji {
public static float emojiDrawingYOffset;
public static boolean emojiDrawingUseAlpha = true;
+ private static String[] DEFAULT_RECENT = new String[]{
+ "\uD83D\uDE02", "\uD83D\uDE18", "\u2764", "\uD83D\uDE0D", "\uD83D\uDE0A", "\uD83D\uDE01",
+ "\uD83D\uDC4D", "\u263A", "\uD83D\uDE14", "\uD83D\uDE04", "\uD83D\uDE2D", "\uD83D\uDC8B",
+ "\uD83D\uDE12", "\uD83D\uDE33", "\uD83D\uDE1C", "\uD83D\uDE48", "\uD83D\uDE09", "\uD83D\uDE03",
+ "\uD83D\uDE22", "\uD83D\uDE1D", "\uD83D\uDE31", "\uD83D\uDE21", "\uD83D\uDE0F", "\uD83D\uDE1E",
+ "\uD83D\uDE05", "\uD83D\uDE1A", "\uD83D\uDE4A", "\uD83D\uDE0C", "\uD83D\uDE00", "\uD83D\uDE0B",
+ "\uD83D\uDE06", "\uD83D\uDC4C", "\uD83D\uDE10", "\uD83D\uDE15"
+ };
+
private final static int MAX_RECENT_EMOJI_COUNT = 48;
static {
@@ -663,6 +672,14 @@ public static void addRecentEmoji(String code) {
emojiUseHistory.put(code, ++count);
}
+ public static void removeRecentEmoji(String code) {
+ emojiUseHistory.remove(code);
+ recentEmoji.remove(code);
+ if (emojiUseHistory.isEmpty() || recentEmoji.isEmpty()) {
+ addRecentEmoji(DEFAULT_RECENT[0]);
+ }
+ }
+
public static void sortEmoji() {
recentEmoji.clear();
for (HashMap.Entry entry : emojiUseHistory.entrySet()) {
@@ -756,15 +773,8 @@ public static void loadRecentEmoji() {
}
if (emojiUseHistory.isEmpty()) {
if (!preferences.getBoolean("filled_default", false)) {
- String[] newRecent = new String[]{
- "\uD83D\uDE02", "\uD83D\uDE18", "\u2764", "\uD83D\uDE0D", "\uD83D\uDE0A", "\uD83D\uDE01",
- "\uD83D\uDC4D", "\u263A", "\uD83D\uDE14", "\uD83D\uDE04", "\uD83D\uDE2D", "\uD83D\uDC8B",
- "\uD83D\uDE12", "\uD83D\uDE33", "\uD83D\uDE1C", "\uD83D\uDE48", "\uD83D\uDE09", "\uD83D\uDE03",
- "\uD83D\uDE22", "\uD83D\uDE1D", "\uD83D\uDE31", "\uD83D\uDE21", "\uD83D\uDE0F", "\uD83D\uDE1E",
- "\uD83D\uDE05", "\uD83D\uDE1A", "\uD83D\uDE4A", "\uD83D\uDE0C", "\uD83D\uDE00", "\uD83D\uDE0B",
- "\uD83D\uDE06", "\uD83D\uDC4C", "\uD83D\uDE10", "\uD83D\uDE15"};
- for (int i = 0; i < newRecent.length; i++) {
- emojiUseHistory.put(newRecent[i], newRecent.length - i);
+ for (int i = 0; i < DEFAULT_RECENT.length; i++) {
+ emojiUseHistory.put(DEFAULT_RECENT[i], DEFAULT_RECENT.length - i);
}
preferences.edit().putBoolean("filled_default", true).commit();
saveRecentEmoji();
diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/Fetcher.java b/TMessagesProj/src/main/java/org/telegram/messenger/Fetcher.java
new file mode 100644
index 00000000000..44aa1f90aa1
--- /dev/null
+++ b/TMessagesProj/src/main/java/org/telegram/messenger/Fetcher.java
@@ -0,0 +1,132 @@
+package org.telegram.messenger;
+
+import android.util.Pair;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+
+public abstract class Fetcher {
+
+ protected void getRemote(int currentAccount, Args arguments, long hash, Utilities.Callback3 onResult) {
+ // Implement this function
+ }
+
+ // Not specifying getLocal and setLocal would mean that data is cached only in RAM
+ protected void getLocal(int currentAccount, Args arguments, Utilities.Callback2 onResult) {
+ // Implement this function
+ onResult.run(0L, null);
+ }
+
+ protected void setLocal(int currentAccount, Args arguments, R data, long hash) {
+ // Implement this function
+ }
+
+ private long requestRemotelyTimeout = 4 * 60 * 1000;
+
+ private HashMap, R> cachedResults;
+ private HashMap, ArrayList>> loadingCallbacks;
+ private HashMap, Long> lastRequestedRemotely;
+
+ public void fetch(int currentAccount, Args arguments, Utilities.Callback onResult) {
+ final Pair key = new Pair<>(currentAccount, arguments);
+
+ if (isLoading(key)) {
+ saveCallback(key, onResult);
+ return;
+ }
+
+ R cached = getCachedResult(key);
+ if (cached != null && !shouldRequest(key)) {
+ if (onResult != null) {
+ onResult.run(cached);
+ }
+ return;
+ }
+
+ saveCallback(key, onResult);
+ getLocal(currentAccount, arguments, (hash, data) -> {
+ if (shouldRequest(key)) {
+ saveLastRequested(key);
+ getRemote(currentAccount, arguments, hash, (notModified, remoteData, newHash) -> {
+ if (notModified) {
+ cacheResult(key, data);
+ callCallbacks(key, data);
+ } else {
+ if (remoteData != null) {
+ setLocal(currentAccount, arguments, remoteData, newHash);
+ cacheResult(key, remoteData);
+ }
+ callCallbacks(key, remoteData);
+ }
+ });
+ } else {
+ cacheResult(key, data);
+ callCallbacks(key, data);
+ }
+ });
+ }
+
+ private R getCachedResult(Pair key) {
+ if (cachedResults == null) {
+ return null;
+ }
+ return cachedResults.get(key);
+ }
+
+ private void cacheResult(Pair key, R result) {
+ if (cachedResults == null) {
+ cachedResults = new HashMap<>();
+ }
+ cachedResults.put(key, result);
+ }
+
+ private void saveLastRequested(Pair key) {
+ if (lastRequestedRemotely == null) {
+ lastRequestedRemotely = new HashMap<>();
+ }
+ lastRequestedRemotely.put(key, System.currentTimeMillis());
+ }
+
+ private boolean shouldRequest(Pair key) {
+ Long lastRequested = lastRequestedRemotely != null ? lastRequestedRemotely.get(key) : null;
+ return lastRequested == null || System.currentTimeMillis() - lastRequested >= requestRemotelyTimeout;
+ }
+
+ private boolean isLoading(Pair key) {
+ return loadingCallbacks != null && loadingCallbacks.get(key) != null;
+ }
+
+ private void saveCallback(Pair key, Utilities.Callback callback) {
+ if (callback == null) {
+ return;
+ }
+ if (loadingCallbacks == null) {
+ loadingCallbacks = new HashMap<>();
+ }
+ ArrayList> callbacks = loadingCallbacks.get(key);
+ if (callbacks == null) {
+ loadingCallbacks.put(key, callbacks = new ArrayList<>());
+ }
+ callbacks.add(callback);
+ }
+
+ private void callCallbacks(Pair key, R result) {
+ if (loadingCallbacks == null) {
+ return;
+ }
+
+ final ArrayList> callbacks = loadingCallbacks.get(key);
+ if (callbacks == null) {
+ return;
+ }
+
+ AndroidUtilities.runOnUIThread(() -> {
+ for (Utilities.Callback callback: callbacks) {
+ callback.run(result);
+ }
+ callbacks.clear();
+ });
+
+ loadingCallbacks.remove(key);
+ }
+}
\ No newline at end of file
diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/FileLoadOperation.java b/TMessagesProj/src/main/java/org/telegram/messenger/FileLoadOperation.java
index d96cc333933..9da5b22f6f1 100644
--- a/TMessagesProj/src/main/java/org/telegram/messenger/FileLoadOperation.java
+++ b/TMessagesProj/src/main/java/org/telegram/messenger/FileLoadOperation.java
@@ -1412,7 +1412,11 @@ private void onFinishLoadingFile(final boolean increment) {
} else if (currentType == ConnectionsManager.FileTypePhoto) {
StatsController.getInstance(currentAccount).incrementReceivedItemsCount(ApplicationLoader.getCurrentNetworkType(), StatsController.TYPE_PHOTOS, 1);
} else if (currentType == ConnectionsManager.FileTypeFile) {
- StatsController.getInstance(currentAccount).incrementReceivedItemsCount(ApplicationLoader.getCurrentNetworkType(), StatsController.TYPE_FILES, 1);
+ if (ext != null && (ext.toLowerCase().endsWith("mp3") || ext.toLowerCase().endsWith("m4a"))) {
+ StatsController.getInstance(currentAccount).incrementReceivedItemsCount(ApplicationLoader.getCurrentNetworkType(), StatsController.TYPE_MUSIC, 1);
+ } else {
+ StatsController.getInstance(currentAccount).incrementReceivedItemsCount(ApplicationLoader.getCurrentNetworkType(), StatsController.TYPE_FILES, 1);
+ }
}
}
delegate.didFinishLoadingFile(FileLoadOperation.this, cacheFileFinal);
@@ -2148,7 +2152,11 @@ protected void startDownloadRequest() {
} else if (currentType == ConnectionsManager.FileTypePhoto) {
StatsController.getInstance(currentAccount).incrementReceivedBytesCount(response.networkType, StatsController.TYPE_PHOTOS, response.getObjectSize() + 4);
} else if (currentType == ConnectionsManager.FileTypeFile) {
- StatsController.getInstance(currentAccount).incrementReceivedBytesCount(response.networkType, StatsController.TYPE_FILES, response.getObjectSize() + 4);
+ if (ext != null && (ext.toLowerCase().endsWith("mp3") || ext.toLowerCase().endsWith("m4a"))) {
+ StatsController.getInstance(currentAccount).incrementReceivedBytesCount(response.networkType, StatsController.TYPE_MUSIC, response.getObjectSize() + 4);
+ } else {
+ StatsController.getInstance(currentAccount).incrementReceivedBytesCount(response.networkType, StatsController.TYPE_FILES, response.getObjectSize() + 4);
+ }
}
}
processRequestResult(requestInfo, error);
diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/FileLoader.java b/TMessagesProj/src/main/java/org/telegram/messenger/FileLoader.java
index 9abfea23a92..c9febf7b8a1 100644
--- a/TMessagesProj/src/main/java/org/telegram/messenger/FileLoader.java
+++ b/TMessagesProj/src/main/java/org/telegram/messenger/FileLoader.java
@@ -45,7 +45,7 @@ public static FilePathDatabase.FileMeta getFileMetadataFromParent(int currentAcc
String str = (String) parentObject;
if (str.startsWith("sent_")) {
if (sentPattern == null) {
- sentPattern = Pattern.compile("sent_.*_([0-9]+)_([0-9]+)_([0-9]+)");
+ sentPattern = Pattern.compile("sent_.*_([0-9]+)_([0-9]+)_([0-9]+)_([0-9]+)");
}
try {
Matcher matcher = sentPattern.matcher(str);
@@ -54,6 +54,7 @@ public static FilePathDatabase.FileMeta getFileMetadataFromParent(int currentAcc
fileMeta.messageId = Integer.parseInt(matcher.group(1));
fileMeta.dialogId = Long.parseLong(matcher.group(2));
fileMeta.messageType = Integer.parseInt(matcher.group(3));
+ fileMeta.messageSize = Long.parseLong(matcher.group(4));
return fileMeta;
}
} catch (Exception e) {
@@ -66,11 +67,25 @@ public static FilePathDatabase.FileMeta getFileMetadataFromParent(int currentAcc
fileMeta.messageId = messageObject.getId();
fileMeta.dialogId = messageObject.getDialogId();
fileMeta.messageType = messageObject.type;
+ fileMeta.messageSize = messageObject.getSize();
return fileMeta;
}
return null;
}
+ public static TLRPC.VideoSize getVectorMarkupVideoSize(TLRPC.Photo photo) {
+ if (photo == null || photo.video_sizes == null) {
+ return null;
+ }
+ for (int i = 0; i < photo.video_sizes.size(); i++) {
+ TLRPC.VideoSize videoSize = photo.video_sizes.get(i);
+ if (videoSize instanceof TLRPC.TL_videoSizeEmojiMarkup || videoSize instanceof TLRPC.TL_videoSizeStickerMarkup) {
+ return videoSize;
+ }
+ }
+ return null;
+ }
+
private int getPriorityValue(int priorityType) {
if (priorityType == PRIORITY_STREAM) {
return Integer.MAX_VALUE;
@@ -732,7 +747,6 @@ private FileLoadOperation loadFileInternal(final TLRPC.Document document, final
storeDir = getDirectory(type);
boolean saveCustomPath = false;
-
if ((type == MEDIA_DIR_IMAGE || type == MEDIA_DIR_VIDEO) && canSaveToPublicStorage(parentObject)) {
File newDir;
if (type == MEDIA_DIR_IMAGE) {
@@ -856,16 +870,27 @@ private boolean canSaveAsFile(Object parentObject) {
}
private boolean canSaveToPublicStorage(Object parentObject) {
- if (SharedConfig.saveToGalleryFlags == 0 || BuildVars.NO_SCOPED_STORAGE) {
+ if (BuildVars.NO_SCOPED_STORAGE) {
return false;
}
- if (parentObject instanceof MessageObject) {
- MessageObject messageObject = (MessageObject) parentObject;
+ FilePathDatabase.FileMeta metadata = getFileMetadataFromParent(currentAccount, parentObject);
+ MessageObject messageObject = null;
+ if (metadata != null) {
int flag;
- long dialogId = messageObject.getDialogId();
- if (messageObject.isRoundVideo() || messageObject.isVoice() || messageObject.isAnyKindOfSticker() || getMessagesController().isChatNoForwards(getMessagesController().getChat(-dialogId)) || messageObject.messageOwner.noforwards || DialogObject.isEncryptedDialog(dialogId)) {
+ long dialogId = metadata.dialogId;
+ if (getMessagesController().isChatNoForwards(getMessagesController().getChat(-dialogId)) || DialogObject.isEncryptedDialog(dialogId)) {
return false;
}
+ if (parentObject instanceof MessageObject) {
+ messageObject = (MessageObject) parentObject;
+ if (messageObject.isRoundVideo() || messageObject.isVoice() || messageObject.isAnyKindOfSticker() || messageObject.messageOwner.noforwards) {
+ return false;
+ }
+ } else {
+ if (metadata.messageType == MessageObject.TYPE_ROUND_VIDEO || metadata.messageType == MessageObject.TYPE_STICKER || metadata.messageType == MessageObject.TYPE_VOICE) {
+ return false;
+ }
+ }
if (dialogId >= 0) {
flag = SharedConfig.SAVE_TO_GALLERY_FLAG_PEER;
} else {
@@ -876,7 +901,7 @@ private boolean canSaveToPublicStorage(Object parentObject) {
}
}
- if ((SharedConfig.saveToGalleryFlags & flag) != 0) {
+ if (SaveToGallerySettingsHelper.needSave(flag, metadata, messageObject, currentAccount)) {
return true;
}
}
@@ -1182,13 +1207,64 @@ public static TLRPC.PhotoSize getClosestPhotoSizeWithSize(ArrayList 100 && closestObject.location != null && closestObject.location.dc_id == Integer.MIN_VALUE || obj instanceof TLRPC.TL_photoCachedSize || side > lastSide && lastSide < currentSide) {
+ if (
+ closestObject == null ||
+ side > 100 && closestObject.location != null && closestObject.location.dc_id == Integer.MIN_VALUE ||
+ obj instanceof TLRPC.TL_photoCachedSize || side > lastSide && lastSide < currentSide
+ ) {
+ closestObject = obj;
+ lastSide = currentSide;
+ }
+ } else {
+ int currentSide = Math.max(obj.w, obj.h);
+ if (
+ closestObject == null ||
+ side > 100 && closestObject.location != null && closestObject.location.dc_id == Integer.MIN_VALUE ||
+ obj instanceof TLRPC.TL_photoCachedSize ||
+ currentSide <= side && lastSide < currentSide
+ ) {
+ closestObject = obj;
+ lastSide = currentSide;
+ }
+ }
+ }
+ return closestObject;
+ }
+
+ public static TLRPC.VideoSize getClosestVideoSizeWithSize(ArrayList sizes, int side) {
+ return getClosestVideoSizeWithSize(sizes, side, false);
+ }
+
+ public static TLRPC.VideoSize getClosestVideoSizeWithSize(ArrayList sizes, int side, boolean byMinSide) {
+ return getClosestVideoSizeWithSize(sizes, side, byMinSide, false);
+ }
+
+ public static TLRPC.VideoSize getClosestVideoSizeWithSize(ArrayList sizes, int side, boolean byMinSide, boolean ignoreStripped) {
+ if (sizes == null || sizes.isEmpty()) {
+ return null;
+ }
+ int lastSide = 0;
+ TLRPC.VideoSize closestObject = null;
+ for (int a = 0; a < sizes.size(); a++) {
+ TLRPC.VideoSize obj = sizes.get(a);
+ if (obj == null || obj instanceof TLRPC.TL_videoSizeEmojiMarkup || obj instanceof TLRPC.TL_videoSizeStickerMarkup) {
+ continue;
+ }
+ if (byMinSide) {
+ int currentSide = Math.min(obj.h, obj.w);
+ if (closestObject == null ||
+ side > 100 && closestObject.location != null && closestObject.location.dc_id == Integer.MIN_VALUE ||
+ side > lastSide && lastSide < currentSide) {
closestObject = obj;
lastSide = currentSide;
}
} else {
int currentSide = Math.max(obj.w, obj.h);
- if (closestObject == null || side > 100 && closestObject.location != null && closestObject.location.dc_id == Integer.MIN_VALUE || obj instanceof TLRPC.TL_photoCachedSize || currentSide <= side && lastSide < currentSide) {
+ if (
+ closestObject == null ||
+ side > 100 && closestObject.location != null && closestObject.location.dc_id == Integer.MIN_VALUE ||
+ currentSide <= side && lastSide < currentSide
+ ) {
closestObject = obj;
lastSide = currentSide;
}
diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/FilePathDatabase.java b/TMessagesProj/src/main/java/org/telegram/messenger/FilePathDatabase.java
index ad1e909f5d5..929c237d398 100644
--- a/TMessagesProj/src/main/java/org/telegram/messenger/FilePathDatabase.java
+++ b/TMessagesProj/src/main/java/org/telegram/messenger/FilePathDatabase.java
@@ -445,5 +445,6 @@ public static class FileMeta {
public long dialogId;
public int messageId;
public int messageType;
+ public long messageSize;
}
}
diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/FileUploadOperation.java b/TMessagesProj/src/main/java/org/telegram/messenger/FileUploadOperation.java
index f208907fe3f..f1574ff3620 100644
--- a/TMessagesProj/src/main/java/org/telegram/messenger/FileUploadOperation.java
+++ b/TMessagesProj/src/main/java/org/telegram/messenger/FileUploadOperation.java
@@ -535,7 +535,11 @@ private void startUploadRequest() {
} else if (currentType == ConnectionsManager.FileTypePhoto) {
StatsController.getInstance(currentAccount).incrementSentBytesCount(networkType, StatsController.TYPE_PHOTOS, requestSize);
} else if (currentType == ConnectionsManager.FileTypeFile) {
- StatsController.getInstance(currentAccount).incrementSentBytesCount(networkType, StatsController.TYPE_FILES, requestSize);
+ if (uploadingFilePath != null && (uploadingFilePath.toLowerCase().endsWith("mp3") || uploadingFilePath.toLowerCase().endsWith("m4a"))) {
+ StatsController.getInstance(currentAccount).incrementSentBytesCount(networkType, StatsController.TYPE_MUSIC, requestSize);
+ } else {
+ StatsController.getInstance(currentAccount).incrementSentBytesCount(networkType, StatsController.TYPE_FILES, requestSize);
+ }
}
if (currentRequestIv != null) {
freeRequestIvs.add(currentRequestIv);
@@ -590,7 +594,11 @@ private void startUploadRequest() {
} else if (currentType == ConnectionsManager.FileTypePhoto) {
StatsController.getInstance(currentAccount).incrementSentItemsCount(ApplicationLoader.getCurrentNetworkType(), StatsController.TYPE_PHOTOS, 1);
} else if (currentType == ConnectionsManager.FileTypeFile) {
- StatsController.getInstance(currentAccount).incrementSentItemsCount(ApplicationLoader.getCurrentNetworkType(), StatsController.TYPE_FILES, 1);
+ if (uploadingFilePath != null && (uploadingFilePath.toLowerCase().endsWith("mp3") || uploadingFilePath.toLowerCase().endsWith("m4a"))) {
+ StatsController.getInstance(currentAccount).incrementSentItemsCount(ApplicationLoader.getCurrentNetworkType(), StatsController.TYPE_MUSIC, 1);
+ } else {
+ StatsController.getInstance(currentAccount).incrementSentItemsCount(ApplicationLoader.getCurrentNetworkType(), StatsController.TYPE_FILES, 1);
+ }
}
} else if (currentUploadRequetsCount < maxRequestsCount) {
if (estimatedSize == 0 && !uploadFirstPartLater && !nextPartFirst) {
diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/ImageLoader.java b/TMessagesProj/src/main/java/org/telegram/messenger/ImageLoader.java
index d6d522523f0..1e8af90fb9f 100644
--- a/TMessagesProj/src/main/java/org/telegram/messenger/ImageLoader.java
+++ b/TMessagesProj/src/main/java/org/telegram/messenger/ImageLoader.java
@@ -74,6 +74,7 @@
import java.util.List;
import java.util.Locale;
import java.util.Map;
+import java.util.Objects;
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Stream;
import java.util.zip.GZIPInputStream;
@@ -86,6 +87,7 @@
* b - need blur image
* g - autoplay
* lastframe - return lastframe for Lottie animation
+ * lastreactframe - return lastframe for Lottie animation + some scale ReactionLastFrame magic
* firstframe - return firstframe for Lottie animation
*/
public class ImageLoader {
@@ -870,6 +872,7 @@ public void run() {
boolean precache = false;
boolean limitFps = false;
boolean lastFrameBitmap = false;
+ boolean lastFrameReactionScaleBitmap = false;
boolean firstFrameBitmap = false;
int autoRepeat = 1;
int[] colors = null;
@@ -896,6 +899,10 @@ public void run() {
if (cacheImage.filter.contains("lastframe")) {
lastFrameBitmap = true;
}
+ if (cacheImage.filter.contains("lastreactframe")) {
+ lastFrameBitmap = true;
+ lastFrameReactionScaleBitmap = true;
+ }
if (cacheImage.filter.contains("firstframe")) {
firstFrameBitmap = true;
}
@@ -964,13 +971,17 @@ public void run() {
precache = false;
}
BitmapsCache.CacheOptions cacheOptions = null;
- if (precache) {
+ if (precache || lastFrameBitmap || firstFrameBitmap) {
cacheOptions = new BitmapsCache.CacheOptions();
- if (cacheImage.filter != null && cacheImage.filter.contains("compress")) {
- cacheOptions.compressQuality = BitmapsCache.COMPRESS_QUALITY_DEFAULT;
- }
- if (cacheImage.filter != null && cacheImage.filter.contains("flbk")) {
- cacheOptions.fallback = true;
+ if (!lastFrameBitmap && !firstFrameBitmap) {
+ if (cacheImage.filter != null && cacheImage.filter.contains("compress")) {
+ cacheOptions.compressQuality = BitmapsCache.COMPRESS_QUALITY_DEFAULT;
+ }
+ if (cacheImage.filter != null && cacheImage.filter.contains("flbk")) {
+ cacheOptions.fallback = true;
+ }
+ } else {
+ cacheOptions.firstFrame = true;
}
}
if (compressed) {
@@ -980,7 +991,7 @@ public void run() {
}
}
if (lastFrameBitmap || firstFrameBitmap) {
- loadLastFrame(lottieDrawable, h, w, lastFrameBitmap);
+ loadLastFrame(lottieDrawable, h, w, lastFrameBitmap, lastFrameReactionScaleBitmap);
} else {
lottieDrawable.setAutoRepeat(autoRepeat);
onPostExecute(lottieDrawable);
@@ -995,6 +1006,8 @@ public void run() {
}
boolean limitFps = false;
boolean precache = false;
+ boolean fistFrame = false;
+ boolean notCreateStream = false;
if (cacheImage.filter != null) {
String[] args = cacheImage.filter.split("_");
if (args.length >= 2) {
@@ -1008,20 +1021,28 @@ public void run() {
if ("pcache".equals(args[i])) {
precache = true;
}
+ if ("firstframe".equals(args[i])) {
+ fistFrame = true;
+ }
+ if ("nostream".equals(args[i])) {
+ notCreateStream = true;
+ }
+ }
+ if (fistFrame) {
+ notCreateStream = true;
+ }
+ }
+ BitmapsCache.CacheOptions cacheOptions = null;
+ if (precache && !fistFrame) {
+ cacheOptions = new BitmapsCache.CacheOptions();
+ if (cacheImage.filter != null && cacheImage.filter.contains("compress")) {
+ cacheOptions.compressQuality = BitmapsCache.COMPRESS_QUALITY_DEFAULT;
}
}
if ((isAnimatedAvatar(cacheImage.filter) || AUTOPLAY_FILTER.equals(cacheImage.filter)) && !(cacheImage.imageLocation.document instanceof TLRPC.TL_documentEncrypted) && !precache) {
TLRPC.Document document = cacheImage.imageLocation.document instanceof TLRPC.Document ? cacheImage.imageLocation.document : null;
long size = document != null ? cacheImage.size : cacheImage.imageLocation.currentSize;
- BitmapsCache.CacheOptions cacheOptions = null;
- if (precache) {
- cacheOptions = new BitmapsCache.CacheOptions();
- if (cacheImage.filter != null && cacheImage.filter.contains("compress")) {
- cacheOptions.compressQuality = BitmapsCache.COMPRESS_QUALITY_DEFAULT;
- }
- }
- boolean notCreateStream = cacheImage.filter != null && cacheImage.filter.contains("nostream");
- fileDrawable = new AnimatedFileDrawable(cacheImage.finalFilePath, false, notCreateStream ? 0 : size, notCreateStream ? null : document, document == null && !notCreateStream ? cacheImage.imageLocation : null, cacheImage.parentObject, seekTo, cacheImage.currentAccount, false, cacheOptions);
+ fileDrawable = new AnimatedFileDrawable(cacheImage.finalFilePath, fistFrame, notCreateStream ? 0 : size, notCreateStream ? null : document, document == null && !notCreateStream ? cacheImage.imageLocation : null, cacheImage.parentObject, seekTo, cacheImage.currentAccount, false, cacheOptions);
fileDrawable.setIsWebmSticker(MessageObject.isWebM(document) || MessageObject.isVideoSticker(document) || isAnimatedAvatar(cacheImage.filter));
} else {
@@ -1036,21 +1057,25 @@ public void run() {
h = (int) (h_filter * AndroidUtilities.density);
}
}
- BitmapsCache.CacheOptions cacheOptions = null;
- if (precache) {
- cacheOptions = new BitmapsCache.CacheOptions();
- if (cacheImage.filter != null && cacheImage.filter.contains("compress")) {
- cacheOptions.compressQuality = BitmapsCache.COMPRESS_QUALITY_DEFAULT;
- }
- }
- boolean createDecoder = cacheImage.filter != null && ("d".equals(cacheImage.filter) || cacheImage.filter.contains("_d"));
- boolean notCreateStream = cacheImage.filter != null && cacheImage.filter.contains("nostream");
+ boolean createDecoder = fistFrame || (cacheImage.filter != null && ("d".equals(cacheImage.filter) || cacheImage.filter.contains("_d")));
fileDrawable = new AnimatedFileDrawable(cacheImage.finalFilePath, createDecoder, 0, notCreateStream ? null : cacheImage.imageLocation.document, null, null, seekTo, cacheImage.currentAccount, false, w, h, cacheOptions);
fileDrawable.setIsWebmSticker(MessageObject.isWebM(cacheImage.imageLocation.document) || MessageObject.isVideoSticker(cacheImage.imageLocation.document) || isAnimatedAvatar(cacheImage.filter));
}
- fileDrawable.setLimitFps(limitFps);
- Thread.interrupted();
- onPostExecute(fileDrawable);
+ if (fistFrame) {
+ Bitmap bitmap = fileDrawable.getFrameAtTime(0, false);
+
+ fileDrawable.recycle();
+ Thread.interrupted();
+ if (bitmap == null) {
+ onPostExecute(null);
+ } else {
+ onPostExecute(new BitmapDrawable(bitmap));
+ }
+ } else {
+ fileDrawable.setLimitFps(limitFps);
+ Thread.interrupted();
+ onPostExecute(fileDrawable);
+ }
} else {
Long mediaId = null;
boolean mediaIsVideo = false;
@@ -1548,10 +1573,10 @@ public void run() {
}
}
- private void loadLastFrame(RLottieDrawable lottieDrawable, int w, int h, boolean lastFrame) {
+ private void loadLastFrame(RLottieDrawable lottieDrawable, int w, int h, boolean lastFrame, boolean reaction) {
Bitmap bitmap;
Canvas canvas;
- if (lastFrame) {
+ if (lastFrame && reaction) {
bitmap = Bitmap.createBitmap((int) (w * ImageReceiver.ReactionLastFrame.LAST_FRAME_SCALE), (int) (h * ImageReceiver.ReactionLastFrame.LAST_FRAME_SCALE), Bitmap.Config.ARGB_8888);
canvas = new Canvas(bitmap);
canvas.scale(2f, 2f, w * ImageReceiver.ReactionLastFrame.LAST_FRAME_SCALE / 2f, h * ImageReceiver.ReactionLastFrame.LAST_FRAME_SCALE / 2f);
@@ -1560,32 +1585,29 @@ private void loadLastFrame(RLottieDrawable lottieDrawable, int w, int h, boolean
canvas = new Canvas(bitmap);
}
+ lottieDrawable.prepareForGenerateCache();
+ Bitmap currentBitmap = Bitmap.createBitmap(lottieDrawable.getIntrinsicWidth(), lottieDrawable.getIntrinsicHeight(), Bitmap.Config.ARGB_8888);
+ lottieDrawable.setGeneratingFrame(lastFrame ? lottieDrawable.getFramesCount() - 1 : 0);
+ lottieDrawable.getNextFrame(currentBitmap);
+ lottieDrawable.releaseForGenerateCache();
+ canvas.save();
+ if (!(lastFrame && reaction)) {
+ canvas.scale(currentBitmap.getWidth() / w, currentBitmap.getHeight() / h, w / 2f, h / 2f);
+ }
+ Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
+ paint.setFilterBitmap(true);
+ BitmapDrawable bitmapDrawable = null;
+ if (lastFrame && reaction) {
+ canvas.drawBitmap(currentBitmap, (bitmap.getWidth() - currentBitmap.getWidth()) / 2f, (bitmap.getHeight() - currentBitmap.getHeight()) / 2f, paint);
+ bitmapDrawable = new ImageReceiver.ReactionLastFrame(bitmap);
+ } else {
+ canvas.drawBitmap(currentBitmap, 0, 0, paint);
+ bitmapDrawable = new BitmapDrawable(bitmap);
+ }
- AndroidUtilities.runOnUIThread(() -> {
- lottieDrawable.setOnFrameReadyRunnable(() -> {
- lottieDrawable.setOnFrameReadyRunnable(null);
- BitmapDrawable bitmapDrawable = null;
- if (lottieDrawable.getBackgroundBitmap() != null || lottieDrawable.getRenderingBitmap() != null) {
- Bitmap currentBitmap = lottieDrawable.getBackgroundBitmap() != null ? lottieDrawable.getBackgroundBitmap() : lottieDrawable.getRenderingBitmap();
- canvas.save();
- if (!lastFrame) {
- canvas.scale(currentBitmap.getWidth() / w, currentBitmap.getHeight() / h, w / 2f, h / 2f);
- }
- Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
- paint.setFilterBitmap(true);
- if (lastFrame) {
- canvas.drawBitmap(currentBitmap, (bitmap.getWidth() - currentBitmap.getWidth()) / 2f, (bitmap.getHeight() - currentBitmap.getHeight()) / 2f, paint);
- bitmapDrawable = new ImageReceiver.ReactionLastFrame(bitmap);
- } else {
- canvas.drawBitmap(currentBitmap, 0, 0, paint);
- bitmapDrawable = new BitmapDrawable(bitmap);
- }
- }
- onPostExecute(bitmapDrawable);
- lottieDrawable.recycle();
- });
- lottieDrawable.setCurrentFrame(lastFrame ? lottieDrawable.getFramesCount() - 1 : 0, true, true);
- });
+ lottieDrawable.recycle();
+ currentBitmap.recycle();
+ onPostExecute(bitmapDrawable);
}
private void onPostExecute(final Drawable drawable) {
@@ -1736,7 +1758,7 @@ private class CacheImage {
public void addImageReceiver(ImageReceiver imageReceiver, String key, String filter, int type, int guid) {
int index = imageReceiverArray.indexOf(imageReceiver);
- if (index >= 0) {
+ if (index >= 0 && Objects.equals(imageReceiverArray.get(index).getImageKey(), key)) {
imageReceiverGuidsArray.set(index, guid);
return;
}
@@ -2040,11 +2062,14 @@ public void fileDidFailedUpload(final String location, final boolean isEncrypted
public void fileDidLoaded(final String location, final File finalFile, Object parentObject, final int type) {
fileProgresses.remove(location);
AndroidUtilities.runOnUIThread(() -> {
- if (SharedConfig.saveToGalleryFlags != 0 && finalFile != null && (location.endsWith(".mp4") || location.endsWith(".jpg"))) {
- if (parentObject instanceof MessageObject) {
- MessageObject messageObject = (MessageObject) parentObject;
-
- long dialogId = messageObject.getDialogId();
+ if (finalFile != null && (location.endsWith(".mp4") || location.endsWith(".jpg"))) {
+ FilePathDatabase.FileMeta meta = FileLoader.getFileMetadataFromParent(currentAccount, parentObject);
+ if (meta != null) {
+ MessageObject messageObject = null;
+ if (parentObject instanceof MessageObject) {
+ messageObject = (MessageObject) parentObject;
+ }
+ long dialogId = meta.dialogId;
int flag;
if (dialogId >= 0) {
flag = SharedConfig.SAVE_TO_GALLERY_FLAG_PEER;
@@ -2055,7 +2080,7 @@ public void fileDidLoaded(final String location, final File finalFile, Object pa
flag = SharedConfig.SAVE_TO_GALLERY_FLAG_GROUP;
}
}
- if ((SharedConfig.saveToGalleryFlags & flag) != 0) {
+ if (SaveToGallerySettingsHelper.needSave(flag, meta, messageObject, currentAccount)) {
AndroidUtilities.addMediaToGallery(finalFile.toString());
}
}
@@ -2656,6 +2681,7 @@ private void createLoadOperationForImageReceiver(final ImageReceiver imageReceiv
final boolean shouldGenerateQualityThumb = imageReceiver.isShouldGenerateQualityThumb();
final int currentAccount = imageReceiver.getCurrentAccount();
final boolean currentKeyQuality = type == ImageReceiver.TYPE_IMAGE && imageReceiver.isCurrentKeyQuality();
+
final Runnable loadOperationRunnable = () -> {
boolean added = false;
if (thumb != 2) {
@@ -3320,6 +3346,9 @@ private BitmapDrawable getFromLottieCache(String imageKey) {
}
private boolean useLottieMemCache(ImageLocation imageLocation, String key) {
+ if (key.endsWith("_firstframe") || key.endsWith("_lastframe")) {
+ return false;
+ }
return imageLocation != null && (MessageObject.isAnimatedStickerDocument(imageLocation.document, true) || imageLocation.imageType == FileLoader.IMAGE_TYPE_LOTTIE || MessageObject.isVideoSticker(imageLocation.document)) || isAnimatedAvatar(key);
}
diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/ImageLocation.java b/TMessagesProj/src/main/java/org/telegram/messenger/ImageLocation.java
index 47a415bcd2b..287a6d5bfeb 100644
--- a/TMessagesProj/src/main/java/org/telegram/messenger/ImageLocation.java
+++ b/TMessagesProj/src/main/java/org/telegram/messenger/ImageLocation.java
@@ -118,7 +118,8 @@ public static ImageLocation getForPhoto(TLRPC.PhotoSize photoSize, TLRPC.Photo p
public static final int TYPE_BIG = 0;
public static final int TYPE_SMALL = 1;
public static final int TYPE_STRIPPED = 2;
- public static final int TYPE_VIDEO_THUMB = 3;
+ public static final int TYPE_VIDEO_SMALL = 3;
+ public static final int TYPE_VIDEO_BIG = 4;
public static ImageLocation getForUserOrChat(TLObject object, int type) {
if (object instanceof TLRPC.User) {
@@ -133,19 +134,25 @@ public static ImageLocation getForUser(TLRPC.User user, int type) {
if (user == null || user.access_hash == 0 || user.photo == null) {
return null;
}
- if (type == TYPE_VIDEO_THUMB) {
+ if (type == TYPE_VIDEO_BIG || type == TYPE_VIDEO_SMALL) {
int currentAccount = UserConfig.selectedAccount;
if (MessagesController.getInstance(currentAccount).isPremiumUser(user) && user.photo.has_video) {
final TLRPC.UserFull userFull = MessagesController.getInstance(currentAccount).getUserFull(user.id);
if (userFull != null && userFull.profile_photo != null && userFull.profile_photo.video_sizes != null && !userFull.profile_photo.video_sizes.isEmpty()) {
- TLRPC.VideoSize videoSize = userFull.profile_photo.video_sizes.get(0);
- for (int i = 0; i < userFull.profile_photo.video_sizes.size(); i++) {
- if ("p".equals(userFull.profile_photo.video_sizes.get(i).type)) {
- videoSize = userFull.profile_photo.video_sizes.get(i);
- break;
+ if (type == TYPE_VIDEO_BIG) {
+ TLRPC.VideoSize videoSize = FileLoader.getClosestVideoSizeWithSize(userFull.profile_photo.video_sizes, 1000);
+ return ImageLocation.getForPhoto(videoSize, userFull.profile_photo);
+ } else {
+ TLRPC.VideoSize videoSize = FileLoader.getClosestVideoSizeWithSize(userFull.profile_photo.video_sizes, 100);
+ for (int i = 0; i < userFull.profile_photo.video_sizes.size(); i++) {
+ if ("p".equals(userFull.profile_photo.video_sizes.get(i).type)) {
+ videoSize = userFull.profile_photo.video_sizes.get(i);
+ break;
+ }
}
+ return ImageLocation.getForPhoto(videoSize, userFull.profile_photo);
}
- return ImageLocation.getForPhoto(videoSize, userFull.profile_photo);
+
}
}
return null;
diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/ImageReceiver.java b/TMessagesProj/src/main/java/org/telegram/messenger/ImageReceiver.java
index 0ef7415bc05..dbc57d4cd2d 100644
--- a/TMessagesProj/src/main/java/org/telegram/messenger/ImageReceiver.java
+++ b/TMessagesProj/src/main/java/org/telegram/messenger/ImageReceiver.java
@@ -33,12 +33,14 @@
import org.telegram.tgnet.TLObject;
import org.telegram.tgnet.TLRPC;
import org.telegram.ui.Components.AnimatedFileDrawable;
+import org.telegram.ui.Components.AttachableDrawable;
import org.telegram.ui.Components.AvatarDrawable;
import org.telegram.ui.Components.ClipRoundedDrawable;
import org.telegram.ui.Components.CubicBezierInterpolator;
import org.telegram.ui.Components.LoadingStickerDrawable;
import org.telegram.ui.Components.RLottieDrawable;
import org.telegram.ui.Components.RecyclableDrawable;
+import org.telegram.ui.Components.VectorAvatarThumbDrawable;
import java.util.ArrayList;
@@ -370,10 +372,10 @@ public void setForUserOrChat(TLObject object, Drawable avatarDrawable) {
setForUserOrChat(object, avatarDrawable, null);
}
public void setForUserOrChat(TLObject object, Drawable avatarDrawable, Object parentObject) {
- setForUserOrChat(object, avatarDrawable, null, false);
+ setForUserOrChat(object, avatarDrawable, parentObject, false, 0);
}
- public void setForUserOrChat(TLObject object, Drawable avatarDrawable, Object parentObject, boolean animationEnabled) {
+ public void setForUserOrChat(TLObject object, Drawable avatarDrawable, Object parentObject, boolean animationEnabled, int vectorType) {
if (parentObject == null) {
parentObject = object;
}
@@ -381,29 +383,46 @@ public void setForUserOrChat(TLObject object, Drawable avatarDrawable, Object pa
BitmapDrawable strippedBitmap = null;
boolean hasStripped = false;
ImageLocation videoLocation = null;
+ TLRPC.VideoSize vectorImageMarkup = null;
+ boolean isPremium = false;
if (object instanceof TLRPC.User) {
TLRPC.User user = (TLRPC.User) object;
+ isPremium = user.premium;
if (user.photo != null) {
strippedBitmap = user.photo.strippedBitmap;
hasStripped = user.photo.stripped_thumb != null;
- if (animationEnabled && MessagesController.getInstance(currentAccount).isPremiumUser(user) && user.photo.has_video && !SharedConfig.getLiteMode().enabled()) {
+ if (vectorType == VectorAvatarThumbDrawable.TYPE_STATIC) {
+ final TLRPC.UserFull userFull = MessagesController.getInstance(currentAccount).getUserFull(user.id);
+ if (userFull != null) {
+ TLRPC.Photo photo = user.photo.personal ? userFull.personal_photo : userFull.profile_photo;
+ if (photo != null) {
+ vectorImageMarkup = FileLoader.getVectorMarkupVideoSize(photo);
+ }
+ }
+ }
+ if (vectorImageMarkup == null && animationEnabled && MessagesController.getInstance(currentAccount).isPremiumUser(user) && user.photo.has_video && !SharedConfig.getLiteMode().enabled()) {
final TLRPC.UserFull userFull = MessagesController.getInstance(currentAccount).getUserFull(user.id);
if (userFull == null) {
MessagesController.getInstance(currentAccount).loadFullUser(user, currentGuid, false);
} else {
- TLRPC.Photo photo = userFull.profile_photo;
+ TLRPC.Photo photo = user.photo.personal ? userFull.personal_photo : userFull.profile_photo;
if (photo != null) {
- ArrayList videoSizes = photo.video_sizes;
- if (videoSizes != null && !videoSizes.isEmpty()) {
- TLRPC.VideoSize videoSize = videoSizes.get(0);
- for (int i = 0; i < videoSizes.size(); i++) {
- TLRPC.VideoSize videoSize1 = videoSizes.get(i);
- if ("p".equals(videoSize1.type)) {
- videoSize = videoSize1;
- break;
+ vectorImageMarkup = FileLoader.getVectorMarkupVideoSize(photo);
+ if (vectorImageMarkup == null) {
+ ArrayList videoSizes = photo.video_sizes;
+ if (videoSizes != null && !videoSizes.isEmpty()) {
+ TLRPC.VideoSize videoSize = FileLoader.getClosestVideoSizeWithSize(videoSizes, 100);
+ for (int i = 0; i < videoSizes.size(); i++) {
+ TLRPC.VideoSize videoSize1 = videoSizes.get(i);
+ if ("p".equals(videoSize1.type)) {
+ videoSize = videoSize1;
+ }
+ if (videoSize1 instanceof TLRPC.TL_videoSizeEmojiMarkup || videoSize1 instanceof TLRPC.TL_videoSizeStickerMarkup) {
+ vectorImageMarkup = videoSize1;
+ }
}
+ videoLocation = ImageLocation.getForPhoto(videoSize, photo);
}
- videoLocation = ImageLocation.getForPhoto(videoSize, photo);
}
}
}
@@ -416,18 +435,23 @@ public void setForUserOrChat(TLObject object, Drawable avatarDrawable, Object pa
hasStripped = chat.photo.stripped_thumb != null;
}
}
- ImageLocation location = ImageLocation.getForUserOrChat(object, ImageLocation.TYPE_SMALL);
- String filter = "50_50";
- if (videoLocation != null) {
- setImage(videoLocation, "avatar", location, filter, null, null, strippedBitmap, 0, null, parentObject, 0);
- animatedFileDrawableRepeatMaxCount = 3;
+ if (vectorImageMarkup != null && vectorType != 0) {
+ VectorAvatarThumbDrawable drawable = new VectorAvatarThumbDrawable(vectorImageMarkup, isPremium, vectorType);
+ setImageBitmap(drawable);
} else {
- if (strippedBitmap != null) {
- setImage(location, filter, strippedBitmap, null, parentObject, 0);
- } else if (hasStripped) {
- setImage(location, filter, ImageLocation.getForUserOrChat(object, ImageLocation.TYPE_STRIPPED), "50_50_b", avatarDrawable, parentObject, 0);
+ ImageLocation location = ImageLocation.getForUserOrChat(object, ImageLocation.TYPE_SMALL);
+ String filter = "50_50";
+ if (videoLocation != null) {
+ setImage(videoLocation, "avatar", location, filter, null, null, strippedBitmap, 0, null, parentObject, 0);
+ animatedFileDrawableRepeatMaxCount = 3;
} else {
- setImage(location, filter, avatarDrawable, null, parentObject, 0);
+ if (strippedBitmap != null) {
+ setImage(location, filter, strippedBitmap, null, parentObject, 0);
+ } else if (hasStripped) {
+ setImage(location, filter, ImageLocation.getForUserOrChat(object, ImageLocation.TYPE_STRIPPED), "50_50_b", avatarDrawable, parentObject, 0);
+ } else {
+ setImage(location, filter, avatarDrawable, null, parentObject, 0);
+ }
}
}
@@ -501,7 +525,7 @@ public void setImage(ImageLocation mediaLocation, String mediaFilter, ImageLocat
currentParentObject = null;
currentCacheType = 0;
roundPaint.setShader(null);
- staticThumbDrawable = thumb;
+ setStaticDrawable(thumb);
currentAlpha = 1.0f;
previousAlpha = 1f;
currentSize = 0;
@@ -653,7 +677,7 @@ public void setImage(ImageLocation mediaLocation, String mediaFilter, ImageLocat
currentExt = ext;
currentSize = size;
currentCacheType = cacheType;
- staticThumbDrawable = thumb;
+ setStaticDrawable(thumb);
imageShader = null;
composeShader = null;
thumbShader = null;
@@ -820,7 +844,8 @@ public void setImageBitmap(Drawable bitmap) {
}
thumbShader = null;
roundPaint.setShader(null);
- staticThumbDrawable = bitmap;
+ setStaticDrawable(bitmap);
+
updateDrawableRadius(bitmap);
currentMediaLocation = null;
currentMediaFilter = null;
@@ -870,6 +895,26 @@ public void setImageBitmap(Drawable bitmap) {
}
}
+ private void setStaticDrawable(Drawable bitmap) {
+ if (bitmap == staticThumbDrawable) {
+ return;
+ }
+ AttachableDrawable oldDrawable = null;
+ if (staticThumbDrawable instanceof AttachableDrawable) {
+ if (staticThumbDrawable.equals(bitmap)) {
+ return;
+ }
+ oldDrawable = (AttachableDrawable) staticThumbDrawable;
+ }
+ staticThumbDrawable = bitmap;
+ if (attachedToWindow && staticThumbDrawable instanceof AttachableDrawable) {
+ ((AttachableDrawable) staticThumbDrawable).onAttachedToWindow(this);
+ }
+ if (attachedToWindow && oldDrawable != null) {
+ oldDrawable.onDetachedFromWindow(this);
+ }
+ }
+
private void setDrawableShader(Drawable drawable, BitmapShader shader) {
if (drawable == currentThumbDrawable || drawable == staticThumbDrawable) {
thumbShader = shader;
@@ -965,9 +1010,12 @@ public void onDetachedFromWindow() {
NotificationCenter.getGlobalInstance().removeObserver(this, NotificationCenter.stopAllHeavyOperations);
NotificationCenter.getGlobalInstance().removeObserver(this, NotificationCenter.startAllHeavyOperations);
}
+ if (staticThumbDrawable instanceof AttachableDrawable) {
+ ((AttachableDrawable) staticThumbDrawable).onDetachedFromWindow(this);
+ }
if (staticThumbDrawable != null) {
- staticThumbDrawable = null;
+ setStaticDrawable(null);
thumbShader = null;
roundPaint.setShader(null);
}
@@ -1055,6 +1103,9 @@ public boolean onAttachedToWindow() {
if (NotificationCenter.getGlobalInstance().isAnimationInProgress()) {
didReceivedNotification(NotificationCenter.stopAllHeavyOperations, currentAccount, 512);
}
+ if (staticThumbDrawable instanceof AttachableDrawable) {
+ ((AttachableDrawable) staticThumbDrawable).onAttachedToWindow(this);
+ }
return false;
}
@@ -1888,6 +1939,9 @@ public boolean draw(Canvas canvas, BackgroundThreadDrawHolder backgroundThreadDr
checkAlphaAnimation(animationNotReady && crossfadeWithThumb, backgroundThreadDrawHolder);
result = true;
} else if (staticThumbDrawable != null) {
+ if (staticThumbDrawable instanceof VectorAvatarThumbDrawable) {
+ ((VectorAvatarThumbDrawable) staticThumbDrawable).setParent(this);
+ }
drawDrawable(canvas, staticThumbDrawable, (int) (overrideAlpha * 255), null, thumbOrientation, backgroundThreadDrawHolder);
checkAlphaAnimation(animationNotReady, backgroundThreadDrawHolder);
result = true;
@@ -2134,7 +2188,7 @@ public boolean hasImageLoaded() {
}
public boolean hasNotThumb() {
- return currentImageDrawable != null || currentMediaDrawable != null;
+ return currentImageDrawable != null || currentMediaDrawable != null || staticThumbDrawable instanceof VectorAvatarThumbDrawable;
}
public boolean hasStaticThumb() {
@@ -2872,7 +2926,7 @@ public void startCrossfadeFromStaticThumb(Drawable thumb) {
currentThumbDrawable = null;
thumbShader = null;
roundPaint.setShader(null);
- staticThumbDrawable = thumb;
+ setStaticDrawable(thumb);
crossfadeWithThumb = true;
currentAlpha = 0f;
updateDrawableRadius(staticThumbDrawable);
diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/LocaleController.java b/TMessagesProj/src/main/java/org/telegram/messenger/LocaleController.java
index 75decfcfafe..2c444dc42e2 100644
--- a/TMessagesProj/src/main/java/org/telegram/messenger/LocaleController.java
+++ b/TMessagesProj/src/main/java/org/telegram/messenger/LocaleController.java
@@ -442,7 +442,7 @@ public LocaleInfo getLanguageFromDict(String key) {
public LocaleInfo getBuiltinLanguageByPlural(String plural) {
Collection values = languagesDict.values();
for (LocaleInfo l : values)
- if (l.pathToFile != null && l.pathToFile.equals("remote") && l.pluralLangCode != null && l.pluralLangCode.equals(plural))
+ if (l.pathToFile != null && l.pathToFile.equals("remote") && !"en_raw".equals(l.shortName) && l.pluralLangCode != null && l.pluralLangCode.equals(plural))
return l;
return null;
}
diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/MediaController.java b/TMessagesProj/src/main/java/org/telegram/messenger/MediaController.java
index cacf807c91d..c6bee01153e 100644
--- a/TMessagesProj/src/main/java/org/telegram/messenger/MediaController.java
+++ b/TMessagesProj/src/main/java/org/telegram/messenger/MediaController.java
@@ -352,6 +352,7 @@ public static class PhotoEntry extends MediaEditState {
public boolean isChatPreviewSpoilerRevealed;
public boolean isAttachSpoilerRevealed;
+ public TLRPC.VideoSize emojiMarkup;
public PhotoEntry(int bucketId, int imageId, long dateTaken, String path, int orientation, boolean isVideo, int width, int height, long size) {
this.bucketId = bucketId;
diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/MediaDataController.java b/TMessagesProj/src/main/java/org/telegram/messenger/MediaDataController.java
index 4c8c272381c..5b060af5ab9 100644
--- a/TMessagesProj/src/main/java/org/telegram/messenger/MediaDataController.java
+++ b/TMessagesProj/src/main/java/org/telegram/messenger/MediaDataController.java
@@ -44,6 +44,8 @@
import androidx.core.content.pm.ShortcutManagerCompat;
import androidx.core.graphics.drawable.IconCompat;
+import com.android.billingclient.api.ProductDetails;
+
import org.telegram.SQLite.SQLiteCursor;
import org.telegram.SQLite.SQLiteDatabase;
import org.telegram.SQLite.SQLiteException;
@@ -71,6 +73,7 @@
import org.telegram.ui.Components.URLSpanReplacement;
import org.telegram.ui.Components.URLSpanUserMention;
import org.telegram.ui.LaunchActivity;
+import org.telegram.ui.PremiumPreviewFragment;
import java.io.File;
import java.util.ArrayList;
@@ -177,6 +180,8 @@ public MediaDataController(int num) {
loadStickersByEmojiOrName(AndroidUtilities.STICKERS_PLACEHOLDER_PACK_NAME, false, true);
loadEmojiThemes();
loadRecentAndTopReactions(false);
+ loadAvatarConstructor(false);
+ loadAvatarConstructor(true);
ringtoneDataStore = new RingtoneDataStore(currentAccount);
}
@@ -386,6 +391,70 @@ public TLRPC.TL_help_premiumPromo getPremiumPromo() {
return premiumPromo;
}
+ public Integer getPremiumHintAnnualDiscount(boolean checkTransaction) {
+ if (checkTransaction && (!BillingController.getInstance().isReady() || BillingController.getInstance().getLastPremiumTransaction() == null) || premiumPromo == null) {
+ return null;
+ }
+
+ boolean found = false;
+ int discount = 0;
+ double currentPrice = 0;
+ for (TLRPC.TL_premiumSubscriptionOption option : premiumPromo.period_options) {
+ if (checkTransaction ? option.current && Objects.equals(option.transaction.replaceAll(PremiumPreviewFragment.TRANSACTION_PATTERN, "$1"), BillingController.getInstance().getLastPremiumTransaction()) : option.months == 1) {
+ found = true;
+
+ if (!BuildVars.useInvoiceBilling() && BillingController.PREMIUM_PRODUCT_DETAILS != null) {
+ ProductDetails.SubscriptionOfferDetails offerDetails = null;
+ for (ProductDetails.SubscriptionOfferDetails details : BillingController.PREMIUM_PRODUCT_DETAILS.getSubscriptionOfferDetails()) {
+ String period = details.getPricingPhases().getPricingPhaseList().get(0).getBillingPeriod();
+ if (option.months == 12 ? period.equals("P1Y") : period.equals(String.format(Locale.ROOT, "P%dM", option.months))) {
+ offerDetails = details;
+ break;
+ }
+ }
+
+ if (offerDetails == null) {
+ currentPrice = (double) option.amount / option.months;
+ } else {
+ currentPrice = (double) offerDetails.getPricingPhases().getPricingPhaseList().get(0).getPriceAmountMicros() / option.months;
+ }
+ } else {
+ currentPrice = (double) option.amount / option.months;
+ }
+ }
+ }
+ for (TLRPC.TL_premiumSubscriptionOption option : premiumPromo.period_options) {
+ if (found && option.months == 12) {
+ double amount;
+ if (!BuildVars.useInvoiceBilling() && BillingController.PREMIUM_PRODUCT_DETAILS != null) {
+ ProductDetails.SubscriptionOfferDetails offerDetails = null;
+ for (ProductDetails.SubscriptionOfferDetails details : BillingController.PREMIUM_PRODUCT_DETAILS.getSubscriptionOfferDetails()) {
+ String period = details.getPricingPhases().getPricingPhaseList().get(0).getBillingPeriod();
+ if (option.months == 12 ? period.equals("P1Y") : period.equals(String.format(Locale.ROOT, "P%dM", option.months))) {
+ offerDetails = details;
+ break;
+ }
+ }
+
+ if (offerDetails == null) {
+ amount = (double) option.amount / option.months;
+ } else {
+ amount = (double) offerDetails.getPricingPhases().getPricingPhaseList().get(0).getPriceAmountMicros() / option.months;
+ }
+ } else {
+ amount = (double) option.amount / option.months;
+ }
+
+ discount = (int) ((1.0 - amount / currentPrice) * 100);
+ }
+ }
+ if (!found || discount <= 0) {
+ return null;
+ }
+
+ return discount;
+ }
+
public TLRPC.TL_attachMenuBots getAttachMenuBots() {
return attachMenuBots;
}
@@ -1109,7 +1178,7 @@ public TLRPC.TL_messages_stickerSet getStickerSet(TLRPC.InputStickerSet inputSti
}
return cacheSet;
}
- if (inputStickerSet instanceof TLRPC.TL_inputStickerSetID && hash != null) {
+ if (inputStickerSet instanceof TLRPC.TL_inputStickerSetID) {
getMessagesStorage().getStorageQueue().postRunnable(() -> {
TLRPC.TL_messages_stickerSet cachedSet = getCachedStickerSetInternal(inputStickerSet.id, hash);
AndroidUtilities.runOnUIThread(() -> {
@@ -1191,7 +1260,7 @@ private TLRPC.TL_messages_stickerSet getCachedStickerSetInternal(long id, Intege
if (data != null) {
set = TLRPC.TL_messages_stickerSet.TLdeserialize(data, data.readInt32(false), false);
int cachedHash = cursor.intValue(1);
- if (hash != null && hash != cachedHash) {
+ if (hash != null && hash != 0 && hash != cachedHash) {
return null;
}
}
@@ -3715,12 +3784,14 @@ public static int getMediaType(TLRPC.Message message) {
boolean isAnimated = false;
boolean isVideo = false;
boolean isVoice = false;
+ boolean isRound = false;
boolean isMusic = false;
boolean isSticker = false;
for (int a = 0; a < document.attributes.size(); a++) {
TLRPC.DocumentAttribute attribute = document.attributes.get(a);
if (attribute instanceof TLRPC.TL_documentAttributeVideo) {
+ isRound = attribute.round_message;
isVoice = attribute.round_message;
isVideo = !attribute.round_message;
} else if (attribute instanceof TLRPC.TL_documentAttributeAnimated) {
@@ -3732,7 +3803,7 @@ public static int getMediaType(TLRPC.Message message) {
isSticker = true;
}
}
- if (isVoice) {
+ if (isVoice || isRound) {
return MEDIA_AUDIO;
} else if (isVideo && !isAnimated && !isSticker) {
return MEDIA_PHOTOVIDEO;
@@ -3801,12 +3872,29 @@ private void processLoadedMedia(TLRPC.messages_Messages res, long dialogId, int
}
getFileLoader().checkMediaExistance(objects);
- AndroidUtilities.runOnUIThread(() -> {
- int totalCount = res.count;
- getMessagesController().putUsers(res.users, fromCache != 0);
- getMessagesController().putChats(res.chats, fromCache != 0);
- getNotificationCenter().postNotificationName(NotificationCenter.mediaDidLoad, dialogId, totalCount, objects, classGuid, type, topReached, min_id != 0, requestIndex);
- });
+ Runnable notify = () -> {
+ AndroidUtilities.runOnUIThread(() -> {
+ int totalCount = res.count;
+ getMessagesController().putUsers(res.users, fromCache != 0);
+ getMessagesController().putChats(res.chats, fromCache != 0);
+ getNotificationCenter().postNotificationName(NotificationCenter.mediaDidLoad, dialogId, totalCount, objects, classGuid, type, topReached, min_id != 0, requestIndex);
+ });
+ };
+
+ if (getMessagesController().getTranslateController().isFeatureAvailable()) {
+ getMessagesStorage().getStorageQueue().postRunnable(() -> {
+ for (int i = 0; i < objects.size(); ++i) {
+ MessageObject messageObject = objects.get(i);
+ TLRPC.Message message = getMessagesStorage().getMessageWithCustomParamsOnlyInternal(messageObject.getId(), messageObject.getDialogId());
+ messageObject.messageOwner.translatedToLanguage = message.translatedToLanguage;
+ messageObject.messageOwner.translatedText = message.translatedText;
+ messageObject.updateTranslation();
+ }
+ notify.run();
+ });
+ } else {
+ notify.run();
+ }
});
}
}
@@ -7071,14 +7159,14 @@ public void getAnimatedEmojiByKeywords(String query, Utilities.Callback ranges = Emoji.parseEmojis(keyword, emojiOnly);
+ if (emojiOnly[0] > 0) {
+ for (int i = 0; i < ranges.size(); ++i) {
+ String code = ranges.get(i).code.toString();
+ boolean foundDuplicate = false;
+ for (int j = 0; j < result.size(); ++j) {
+ if (TextUtils.equals(result.get(j).emoji, code)) {
+ foundDuplicate = true;
+ break;
+ }
+ }
+ if (!foundDuplicate) {
+ KeywordResult keywordResult = new KeywordResult();
+ keywordResult.emoji = code;
+ keywordResult.keyword = "";
+ result.add(keywordResult);
+ }
+ }
+ }
+ }
+
String key = keyword.toLowerCase();
for (int a = 0; a < 2; a++) {
if (a == 1) {
@@ -7734,4 +7845,60 @@ public static ArrayList loadReactionsFromPref(SharedPreferences
}
return objects;
}
+
+ public TLRPC.TL_emojiList profileAvatarConstructorDefault;
+ public TLRPC.TL_emojiList groupAvatarConstructorDefault;
+
+ private void loadAvatarConstructor(boolean profile) {
+ SharedPreferences preferences = ApplicationLoader.applicationContext.getSharedPreferences("avatar_constructor" + currentAccount, Context.MODE_PRIVATE);
+ String value;
+ long lastCheckTime;
+ if (profile) {
+ value = preferences.getString("profile", null);
+ lastCheckTime = preferences.getLong("profile_last_check", 0);
+ } else {
+ value = preferences.getString("group", null);
+ lastCheckTime = preferences.getLong("group_last_check", 0);
+ }
+
+
+ TLRPC.TL_emojiList emojiList = null;
+ if (value != null) {
+ SerializedData serializedData = new SerializedData(Utilities.hexToBytes(value));
+ try {
+ emojiList = (TLRPC.TL_emojiList) TLRPC.TL_emojiList.TLdeserialize(serializedData, serializedData.readInt32(true), true);
+ if (profile) {
+ profileAvatarConstructorDefault = emojiList;
+ } else {
+ groupAvatarConstructorDefault = emojiList;
+ }
+ } catch (Throwable e) {
+ FileLog.e(e);
+ }
+ }
+
+ if (emojiList == null || (System.currentTimeMillis() - lastCheckTime) > 24 * 60 * 60 * 1000 || BuildVars.DEBUG_PRIVATE_VERSION) {
+ TLRPC.TL_account_getDefaultProfilePhotoEmojis req = new TLRPC.TL_account_getDefaultProfilePhotoEmojis();
+ if (emojiList != null) {
+ req.hash = emojiList.hash;
+ }
+ getConnectionsManager().sendRequest(req, (response, error) -> AndroidUtilities.runOnUIThread(() -> {
+ if (response instanceof TLRPC.TL_emojiList) {
+ SerializedData data = new SerializedData(response.getObjectSize());
+ response.serializeToStream(data);
+ SharedPreferences.Editor editor = preferences.edit();
+ if (profile) {
+ profileAvatarConstructorDefault = (TLRPC.TL_emojiList) response;
+ editor.putString("profile", Utilities.bytesToHex(data.toByteArray()));
+ editor.putLong("profile_last_check", System.currentTimeMillis());
+ } else {
+ groupAvatarConstructorDefault = (TLRPC.TL_emojiList) response;
+ editor.putString("group", Utilities.bytesToHex(data.toByteArray()));
+ editor.putLong("group_last_check", System.currentTimeMillis());
+ }
+ editor.apply();
+ }
+ }));
+ }
+ }
}
diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/MessageCustomParamsHelper.java b/TMessagesProj/src/main/java/org/telegram/messenger/MessageCustomParamsHelper.java
index 44f57a0fbff..8077a925f1b 100644
--- a/TMessagesProj/src/main/java/org/telegram/messenger/MessageCustomParamsHelper.java
+++ b/TMessagesProj/src/main/java/org/telegram/messenger/MessageCustomParamsHelper.java
@@ -14,7 +14,10 @@ public static boolean isEmpty(TLRPC.Message message) {
!message.voiceTranscriptionRated &&
!message.voiceTranscriptionForce &&
message.voiceTranscriptionId == 0 &&
- !message.premiumEffectWasPlayed;
+ !message.premiumEffectWasPlayed &&
+ message.originalLanguage == null &&
+ message.translatedToLanguage == null &&
+ message.translatedText == null;
}
public static void copyParams(TLRPC.Message fromMessage, TLRPC.Message toMessage) {
@@ -25,6 +28,9 @@ public static void copyParams(TLRPC.Message fromMessage, TLRPC.Message toMessage
toMessage.voiceTranscriptionRated = fromMessage.voiceTranscriptionRated;
toMessage.voiceTranscriptionId = fromMessage.voiceTranscriptionId;
toMessage.premiumEffectWasPlayed = fromMessage.premiumEffectWasPlayed;
+ toMessage.originalLanguage = fromMessage.originalLanguage;
+ toMessage.translatedToLanguage = fromMessage.translatedToLanguage;
+ toMessage.translatedText = fromMessage.translatedText;
}
@@ -69,6 +75,10 @@ private Params_v1(TLRPC.Message message) {
this.message = message;
flags += message.voiceTranscription != null ? 1 : 0;
flags += message.voiceTranscriptionForce ? 2 : 0;
+
+ flags += message.originalLanguage != null ? 4 : 0;
+ flags += message.translatedToLanguage != null ? 8 : 0;
+ flags += message.translatedText != null ? 16 : 0;
}
@Override
@@ -85,6 +95,16 @@ public void serializeToStream(AbstractSerializedData stream) {
stream.writeInt64(message.voiceTranscriptionId);
stream.writeBool(message.premiumEffectWasPlayed);
+
+ if ((flags & 4) != 0) {
+ stream.writeString(message.originalLanguage);
+ }
+ if ((flags & 8) != 0) {
+ stream.writeString(message.translatedToLanguage);
+ }
+ if ((flags & 16) != 0) {
+ message.translatedText.serializeToStream(stream);
+ }
}
@Override
@@ -100,6 +120,16 @@ public void readParams(AbstractSerializedData stream, boolean exception) {
message.voiceTranscriptionId = stream.readInt64(exception);
message.premiumEffectWasPlayed = stream.readBool(exception);
+
+ if ((flags & 4) != 0) {
+ message.originalLanguage = stream.readString(exception);
+ }
+ if ((flags & 8) != 0) {
+ message.translatedToLanguage = stream.readString(exception);
+ }
+ if ((flags & 16) != 0) {
+ message.translatedText = TLRPC.TL_textWithEntities.TLdeserialize(stream, stream.readInt32(exception), exception);
+ }
}
}
diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/MessageObject.java b/TMessagesProj/src/main/java/org/telegram/messenger/MessageObject.java
index c3cbaf84444..f9197e24a88 100644
--- a/TMessagesProj/src/main/java/org/telegram/messenger/MessageObject.java
+++ b/TMessagesProj/src/main/java/org/telegram/messenger/MessageObject.java
@@ -56,6 +56,7 @@
import org.telegram.ui.Components.URLSpanReplacement;
import org.telegram.ui.Components.URLSpanUserMention;
import org.telegram.ui.Components.spoilers.SpoilerEffect;
+import org.w3c.dom.Text;
import java.io.BufferedReader;
import java.io.File;
@@ -114,6 +115,7 @@ public class MessageObject {
public Long emojiAnimatedStickerId;
public boolean isTopicMainMessage;
public boolean settingAvatar;
+ public TLRPC.VideoSize emojiMarkup;
private boolean emojiAnimatedStickerLoading;
public String emojiAnimatedStickerColor;
public CharSequence messageText;
@@ -222,7 +224,6 @@ public class MessageObject {
public int textHeight;
public boolean hasRtl;
public float textXOffset;
- public int linesCount;
public SendAnimationData sendAnimationData;
@@ -1170,6 +1171,7 @@ public MessageObject(int accountNum, TLRPC.Message message, MessageObject replyT
updateMessageText(users, chats, sUsers, sChats);
setType();
+ updateTranslation(false);
measureInlineBotButtons();
Calendar rightNow = new GregorianCalendar();
@@ -1191,7 +1193,7 @@ public MessageObject(int accountNum, TLRPC.Message message, MessageObject replyT
}
int[] emojiOnly = allowsBigEmoji() ? new int[1] : null;
messageText = Emoji.replaceEmoji(messageText, paint.getFontMetricsInt(), AndroidUtilities.dp(20), false, emojiOnly);
- messageText = replaceAnimatedEmoji(messageText, messageOwner.entities, paint.getFontMetricsInt());
+ messageText = replaceAnimatedEmoji(messageText, paint.getFontMetricsInt());
if (emojiOnly != null && emojiOnly[0] > 1) {
replaceEmojiToLottieFrame(messageText, emojiOnly);
}
@@ -2415,7 +2417,7 @@ public MessageObject(int accountNum, TLRPC.TL_channelAdminLogEvent event, ArrayL
int[] emojiOnly = allowsBigEmoji() ? new int[1] : null;
messageText = Emoji.replaceEmoji(messageText, paint.getFontMetricsInt(), AndroidUtilities.dp(20), false, emojiOnly);
- messageText = replaceAnimatedEmoji(messageText, messageOwner.entities, paint.getFontMetricsInt());
+ messageText = replaceAnimatedEmoji(messageText, paint.getFontMetricsInt());
if (emojiOnly != null && emojiOnly[0] > 1) {
replaceEmojiToLottieFrame(messageText, emojiOnly);
}
@@ -2511,7 +2513,38 @@ private String getUserName(TLObject object, ArrayList entit
return name;
}
+ public boolean updateTranslation() {
+ return updateTranslation(true);
+ }
+
+ public boolean translated = false;
+ public boolean updateTranslation(boolean force) {
+ boolean replyUpdated = replyMessageObject != null && replyMessageObject.updateTranslation(force);
+ if (
+ TranslateController.isTranslatable(this) &&
+ MessagesController.getInstance(currentAccount).getTranslateController().isTranslatingDialog(getDialogId()) &&
+ messageOwner != null &&
+ messageOwner.translatedText != null &&
+ TextUtils.equals(MessagesController.getInstance(currentAccount).getTranslateController().getDialogTranslateTo(getDialogId()), messageOwner.translatedToLanguage)
+ ) {
+ if (translated) {
+ return replyUpdated || false;
+ }
+ translated = true;
+ applyNewText(messageOwner.translatedText.text);
+ generateCaption();
+ return replyUpdated || true;
+ } else if (messageOwner != null && (force || translated)) {
+ translated = false;
+ applyNewText(messageOwner.message);
+ generateCaption();
+ return replyUpdated || true;
+ }
+ return replyUpdated || false;
+ }
+
public void applyNewText() {
+ translated = false;
applyNewText(messageOwner.message);
}
@@ -2524,6 +2557,7 @@ public void applyNewText(CharSequence text) {
fromUser = MessagesController.getInstance(currentAccount).getUser(messageOwner.from_id.user_id);
}
messageText = text;
+ ArrayList entities = translated && messageOwner.translatedText != null ? messageOwner.translatedText.entities : messageOwner.entities;
TextPaint paint;
if (getMedia(messageOwner) instanceof TLRPC.TL_messageMediaGame) {
paint = Theme.chat_msgGameTextPaint;
@@ -2532,7 +2566,7 @@ public void applyNewText(CharSequence text) {
}
int[] emojiOnly = allowsBigEmoji() ? new int[1] : null;
messageText = Emoji.replaceEmoji(messageText, paint.getFontMetricsInt(), AndroidUtilities.dp(20), false, emojiOnly);
- messageText = replaceAnimatedEmoji(messageText, messageOwner.entities, paint.getFontMetricsInt());
+ messageText = replaceAnimatedEmoji(messageText, entities, paint.getFontMetricsInt());
if (emojiOnly != null && emojiOnly[0] > 1) {
replaceEmojiToLottieFrame(messageText, emojiOnly);
}
@@ -2668,7 +2702,7 @@ public void generatePinMessageText(TLRPC.User fromUser, TLRPC.Chat chat) {
}
mess = Emoji.replaceEmoji(mess, Theme.chat_msgTextPaint.getFontMetricsInt(), AndroidUtilities.dp(20), false);
if (replyMessageObject != null && replyMessageObject.messageOwner != null) {
- mess = replaceAnimatedEmoji(mess, replyMessageObject.messageOwner.entities, Theme.chat_msgTextPaint.getFontMetricsInt());
+ mess = replyMessageObject.replaceAnimatedEmoji(mess, Theme.chat_msgTextPaint.getFontMetricsInt());
}
MediaDataController.addTextStyleRuns(replyMessageObject, (Spannable) mess);
if (ellipsize) {
@@ -3375,6 +3409,41 @@ private void updateMessageText(AbstractMap users, AbstractMap<
}
} else if (messageOwner.action instanceof TLRPC.TL_messageActionAttachMenuBotAllowed) {
messageText = LocaleController.getString(R.string.ActionAttachMenuBotAllowed);
+ } else if (messageOwner.action instanceof TLRPC.TL_messageActionRequestedPeer) {
+ TLRPC.Peer peer = ((TLRPC.TL_messageActionRequestedPeer) messageOwner.action).peer;
+ TLObject peerObject = null;
+ if (peer instanceof TLRPC.TL_peerUser) {
+ peerObject = MessagesController.getInstance(currentAccount).getUser(peer.user_id);
+ if (peerObject == null) {
+ peerObject = getUser(users, sUsers, peer.user_id);
+ }
+ } else if (peer instanceof TLRPC.TL_peerChat) {
+ peerObject = MessagesController.getInstance(currentAccount).getChat(peer.chat_id);
+ if (peerObject == null) {
+ peerObject = getChat(chats, sChats, peer.chat_id);
+ }
+ } else if (peer instanceof TLRPC.TL_peerChannel) {
+ peerObject = MessagesController.getInstance(currentAccount).getChat(peer.channel_id);
+ if (peerObject == null) {
+ peerObject = getChat(chats, sChats, peer.channel_id);
+ }
+ }
+ TLRPC.User bot = MessagesController.getInstance(currentAccount).getUser(getDialogId());
+ if (bot == null) {
+ bot = getUser(users, sUsers, getDialogId());
+ }
+ if (peerObject == null) {
+ if (peer instanceof TLRPC.TL_peerUser) {
+ messageText = LocaleController.getString(R.string.ActionRequestedPeerUser);
+ } else if (peer instanceof TLRPC.TL_peerChat) {
+ messageText = LocaleController.getString(R.string.ActionRequestedPeerChat);
+ } else {
+ messageText = LocaleController.getString(R.string.ActionRequestedPeerChannel);
+ }
+ } else {
+ messageText = replaceWithLink(LocaleController.getString(R.string.ActionRequestedPeer), "un1", peerObject);
+ }
+ messageText = replaceWithLink(messageText, "un2", bot);
} else if (messageOwner.action instanceof TLRPC.TL_messageActionSetMessagesTTL) {
TLRPC.TL_messageActionSetMessagesTTL action = (TLRPC.TL_messageActionSetMessagesTTL) messageOwner.action;
TLRPC.Chat chat = messageOwner.peer_id != null && messageOwner.peer_id.channel_id != 0 ? getChat(chats, sChats, messageOwner.peer_id.channel_id) : null;
@@ -3824,7 +3893,7 @@ public void setType() {
} else {
type = TYPE_ANIMATED_STICKER;
}
- } else if (!isDice() && emojiOnlyCount >= 1 && !hasUnwrappedEmoji) {
+ } else if (isMediaEmpty() && !isDice() && emojiOnlyCount >= 1 && !hasUnwrappedEmoji) {
type = TYPE_EMOJIS;
} else if (isMediaEmpty()) {
type = TYPE_TEXT;
@@ -3951,7 +4020,7 @@ public boolean checkLayout() {
}
int[] emojiOnly = allowsBigEmoji() ? new int[1] : null;
messageText = Emoji.replaceEmoji(messageText, paint.getFontMetricsInt(), AndroidUtilities.dp(20), false, emojiOnly);
- messageText = replaceAnimatedEmoji(messageText, messageOwner.entities, paint.getFontMetricsInt());
+ messageText = replaceAnimatedEmoji(messageText, paint.getFontMetricsInt());
if (emojiOnly != null && emojiOnly[0] > 1) {
replaceEmojiToLottieFrame(messageText, emojiOnly);
}
@@ -4546,22 +4615,30 @@ public boolean isVoiceTranscriptionOpen() {
);
}
+ private boolean captionTranslated;
+
public void generateCaption() {
- if (caption != null || isRoundVideo()) {
+ if (caption != null && translated == captionTranslated || isRoundVideo()) {
return;
}
+ String text = messageOwner.message;
+ ArrayList entities = messageOwner.entities;
if (hasExtendedMedia()) {
- messageOwner.message = messageOwner.media.description;
+ text = messageOwner.message = messageOwner.media.description;
+ }
+ if (captionTranslated = translated) {
+ text = messageOwner.translatedText.text;
+ entities = messageOwner.translatedText.entities;
}
- if (!isMediaEmpty() && !(getMedia(messageOwner) instanceof TLRPC.TL_messageMediaGame) && !TextUtils.isEmpty(messageOwner.message)) {
- caption = Emoji.replaceEmoji(messageOwner.message, Theme.chat_msgTextPaint.getFontMetricsInt(), AndroidUtilities.dp(20), false);
- caption = replaceAnimatedEmoji(caption, messageOwner.entities, Theme.chat_msgTextPaint.getFontMetricsInt());
+ if (!isMediaEmpty() && !(getMedia(messageOwner) instanceof TLRPC.TL_messageMediaGame) && !TextUtils.isEmpty(text)) {
+ caption = Emoji.replaceEmoji(text, Theme.chat_msgTextPaint.getFontMetricsInt(), AndroidUtilities.dp(20), false);
+ caption = replaceAnimatedEmoji(caption, Theme.chat_msgTextPaint.getFontMetricsInt());
boolean hasEntities;
if (messageOwner.send_state != MESSAGE_SEND_STATE_SENT) {
hasEntities = false;
} else {
- hasEntities = !messageOwner.entities.isEmpty();
+ hasEntities = !entities.isEmpty();
}
boolean useManualParse = !hasEntities && (
@@ -4819,7 +4896,17 @@ public boolean addEntitiesToText(CharSequence text, boolean photoViewer, boolean
entities.add(entityItalic);
return addEntitiesToText(text, entities, isOutOwner(), true, photoViewer, useManualParse);
} else {
- return addEntitiesToText(text, messageOwner.entities, isOutOwner(), true, photoViewer, useManualParse);
+ ArrayList entities;
+ if (translated) {
+ if (messageOwner.translatedText == null) {
+ entities = null;
+ } else {
+ entities = messageOwner.translatedText.entities;
+ }
+ } else {
+ entities = messageOwner.entities;
+ }
+ return addEntitiesToText(text, entities, isOutOwner(), true, photoViewer, useManualParse);
}
}
@@ -4847,6 +4934,11 @@ public void replaceEmojiToLottieFrame(CharSequence text, int[] emojiOnly) {
}
}
+ public Spannable replaceAnimatedEmoji(CharSequence text, Paint.FontMetricsInt fontMetricsInt) {
+ ArrayList entities = translated && messageOwner.translatedText != null ? messageOwner.translatedText.entities : messageOwner.entities;
+ return replaceAnimatedEmoji(text, entities, fontMetricsInt, false);
+ }
+
public static Spannable replaceAnimatedEmoji(CharSequence text, ArrayList entities, Paint.FontMetricsInt fontMetricsInt) {
return replaceAnimatedEmoji(text, entities, fontMetricsInt, false);
}
@@ -4866,8 +4958,7 @@ public static Spannable replaceAnimatedEmoji(CharSequence text, ArrayList 0;
- if (entities.isEmpty()) {
+ if (entities == null || entities.isEmpty()) {
return hasUrls;
}
@@ -5224,11 +5315,13 @@ public void generateLayout(TLRPC.User fromUser) {
textLayoutBlocks = new ArrayList<>();
textWidth = 0;
+ ArrayList entities = translated && messageOwner.translatedText != null ? messageOwner.translatedText.entities : messageOwner.entities;
+
boolean hasEntities;
if (messageOwner.send_state != MESSAGE_SEND_STATE_SENT) {
hasEntities = false;
} else {
- hasEntities = !messageOwner.entities.isEmpty();
+ hasEntities = !entities.isEmpty();
}
boolean useManualParse = !hasEntities && (
@@ -5305,7 +5398,7 @@ public void generateLayout(TLRPC.User fromUser) {
}
textHeight = textLayout.getHeight();
- linesCount = textLayout.getLineCount();
+ int linesCount = textLayout.getLineCount();
int linesPreBlock = totalAnimatedEmojiCount >= 50 ? LINES_PER_BLOCK_WITH_EMOJI : LINES_PER_BLOCK;
int blocksCount;
diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/MessagesController.java b/TMessagesProj/src/main/java/org/telegram/messenger/MessagesController.java
index 5606cce5fb1..3c04a5a1cb6 100644
--- a/TMessagesProj/src/main/java/org/telegram/messenger/MessagesController.java
+++ b/TMessagesProj/src/main/java/org/telegram/messenger/MessagesController.java
@@ -26,6 +26,7 @@
import android.telephony.TelephonyManager;
import android.text.TextUtils;
import android.util.Base64;
+import android.util.Log;
import android.util.SparseArray;
import android.util.SparseBooleanArray;
import android.util.SparseIntArray;
@@ -401,6 +402,8 @@ public class MessagesController extends BaseController implements NotificationCe
private LongSparseArray emojiStatusUntilValues = new LongSparseArray<>();
private TopicsController topicsController;
private CacheByChatsController cacheByChatsController;
+ private TranslateController translateController;
+ public boolean uploadMarkupVideo;
public void getNextReactionMention(long dialogId, int topicId, int count, Consumer callback) {
final MessagesStorage messagesStorage = getMessagesStorage();
@@ -590,6 +593,10 @@ public TopicsController getTopicsController() {
return topicsController;
}
+ public TranslateController getTranslateController() {
+ return translateController;
+ }
+
public boolean isForum(long dialogId) {
TLRPC.Chat chatLocal = getChat(-dialogId);
return chatLocal != null && chatLocal.forum;
@@ -1008,6 +1015,10 @@ public static MessagesController getInstance(int num) {
return localInstance;
}
+ public SharedPreferences getMainSettings() {
+ return mainPreferences;
+ }
+
public static SharedPreferences getNotificationsSettings(int account) {
return getInstance(account).notificationsPreferences;
}
@@ -1152,6 +1163,7 @@ public MessagesController(int num) {
telegramAntispamUserId = mainPreferences.getLong("telegramAntispamUserId", -1);
telegramAntispamGroupSizeMin = mainPreferences.getInt("telegramAntispamGroupSizeMin", 100);
hiddenMembersGroupSizeMin = mainPreferences.getInt("hiddenMembersGroupSizeMin", 100);
+ uploadMarkupVideo = mainPreferences.getBoolean("uploadMarkupVideo", true);
BuildVars.GOOGLE_AUTH_CLIENT_ID = mainPreferences.getString("googleAuthClientId", BuildVars.GOOGLE_AUTH_CLIENT_ID);
Set currencySet = mainPreferences.getStringSet("directPaymentsCurrency", null);
@@ -1290,6 +1302,7 @@ public MessagesController(int num) {
topicsController = new TopicsController(num);
cacheByChatsController = new CacheByChatsController(num);
+ translateController = new TranslateController(this);
}
@@ -1598,6 +1611,7 @@ protected void processLoadedDialogFilters(ArrayList filters, TLRPC
}
}
}
+ getTranslateController().checkDialogMessages(key);
} else {
currentDialog.pinned = newDialog.pinned;
currentDialog.pinnedNum = newDialog.pinnedNum;
@@ -1645,6 +1659,7 @@ protected void processLoadedDialogFilters(ArrayList filters, TLRPC
}
}
}
+ getTranslateController().checkDialogMessages(key);
}
} else {
// if (newMsg == null || newMsg.messageOwner.date > oldMsg.messageOwner.date) {
@@ -1682,6 +1697,7 @@ protected void processLoadedDialogFilters(ArrayList filters, TLRPC
}
}
}
+ getTranslateController().checkDialogMessages(key);
}
}
}
@@ -1802,13 +1818,29 @@ public void addFilter(DialogFilter filter, boolean atBegin) {
lockFiltersInternal();
}
+ public void updateEmojiStatus(TLRPC.EmojiStatus newStatus) {
+ TLRPC.TL_account_updateEmojiStatus req = new TLRPC.TL_account_updateEmojiStatus();
+ req.emoji_status = newStatus;
+ TLRPC.User user = getUserConfig().getCurrentUser();
+ if (user != null) {
+ user.emoji_status = req.emoji_status;
+ getNotificationCenter().postNotificationName(NotificationCenter.userEmojiStatusUpdated, user);
+ getMessagesController().updateEmojiStatusUntilUpdate(user.id, user.emoji_status);
+ }
+ getConnectionsManager().sendRequest(req, (res, err) -> {
+ if (!(res instanceof TLRPC.TL_boolTrue)) {
+ // TODO: reject
+ }
+ });
+ }
+
public void removeFilter(DialogFilter filter) {
dialogFilters.remove(filter);
dialogFiltersById.remove(filter.id);
getNotificationCenter().postNotificationName(NotificationCenter.dialogFiltersUpdated);
}
- private void loadAppConfig() {
+ public void loadAppConfig() {
if (loadingAppConfig) {
return;
}
@@ -1824,6 +1856,16 @@ private void loadAppConfig() {
for (int a = 0, N = object.value.size(); a < N; a++) {
TLRPC.TL_jsonObjectValue value = object.value.get(a);
switch (value.key) {
+ case "upload_markup_video": {
+ if (value.value instanceof TLRPC.TL_jsonBool) {
+ if (uploadMarkupVideo != ((TLRPC.TL_jsonBool) value.value).value) {
+ uploadMarkupVideo = ((TLRPC.TL_jsonBool) value.value).value;
+ editor.putBoolean("uploadMarkupVideo", uploadMarkupVideo);
+ changed = true;
+ }
+ }
+ break;
+ }
case "login_google_oauth_client_id": {
if (value.value instanceof TLRPC.TL_jsonString) {
String str = ((TLRPC.TL_jsonString) value.value).value;
@@ -3450,6 +3492,7 @@ public void cleanup() {
getLocationController().cleanup();
getMediaDataController().cleanup();
getColorPalette().cleanup();
+ getTranslateController().cleanup();
showFiltersTooltip = false;
@@ -4433,6 +4476,7 @@ public void loadFullChat(long chatId, int classGuid, boolean force) {
res.full_chat.inviterId = old.inviterId;
}
fullChats.put(chatId, res.full_chat);
+ getTranslateController().updateDialogFull(-chatId);
applyDialogNotificationsSettings(-chatId, 0, res.full_chat.notify_settings);
for (int a = 0; a < res.full_chat.bot_info.size(); a++) {
@@ -4530,6 +4574,7 @@ public void loadFullUser(final TLRPC.User user, int classGuid, boolean force) {
}
}
fullUsers.put(user.id, userFull);
+ getTranslateController().updateDialogFull(user.id);
loadingFullUsers.remove(user.id);
loadedFullUsers.put(user.id, System.currentTimeMillis());
String names = user.first_name + user.last_name + UserObject.getPublicUsername(user);
@@ -5269,7 +5314,7 @@ public void deleteUserPhoto(TLRPC.InputPhoto photo) {
if (photo == null) {
TLRPC.TL_photos_updateProfilePhoto req = new TLRPC.TL_photos_updateProfilePhoto();
req.id = new TLRPC.TL_inputPhotoEmpty();
- getUserConfig().getCurrentUser().photo = new TLRPC.TL_userProfilePhotoEmpty();
+ // getUserConfig().getCurrentUser().photo = new TLRPC.TL_userProfilePhotoEmpty();
TLRPC.User user = getUser(getUserConfig().getClientUserId());
if (user == null) {
user = getUserConfig().getCurrentUser();
@@ -5277,39 +5322,49 @@ public void deleteUserPhoto(TLRPC.InputPhoto photo) {
if (user == null) {
return;
}
- user.photo = getUserConfig().getCurrentUser().photo;
+ getMessagesStorage().clearUserPhoto(user.id, user.photo.photo_id);
+ // user.photo = getUserConfig().getCurrentUser().photo;
getNotificationCenter().postNotificationName(NotificationCenter.mainUserInfoChanged);
getNotificationCenter().postNotificationName(NotificationCenter.updateInterfaces, UPDATE_MASK_ALL);
+
getConnectionsManager().sendRequest(req, (response, error) -> {
if (error == null) {
- TLRPC.TL_photos_photo photos_photo = (TLRPC.TL_photos_photo) response;
- TLRPC.User user1 = getUser(getUserConfig().getClientUserId());
- if (user1 == null) {
- user1 = getUserConfig().getCurrentUser();
- putUser(user1, false);
- } else {
- getUserConfig().setCurrentUser(user1);
- }
- if (user1 == null) {
- return;
- }
- getMessagesStorage().clearUserPhotos(user1.id);
- ArrayList users = new ArrayList<>();
- users.add(user1);
- getMessagesStorage().putUsersAndChats(users, null, false, true);
- if (photos_photo.photo instanceof TLRPC.TL_photo) {
- user1.photo = new TLRPC.TL_userProfilePhoto();
- user1.photo.has_video = !photos_photo.photo.video_sizes.isEmpty();
- user1.photo.photo_id = photos_photo.photo.id;
- user1.photo.photo_small = FileLoader.getClosestPhotoSizeWithSize(photos_photo.photo.sizes, 150).location;
- user1.photo.photo_big = FileLoader.getClosestPhotoSizeWithSize(photos_photo.photo.sizes, 800).location;
- user1.photo.dc_id = photos_photo.photo.dc_id;
- } else {
- user1.photo = new TLRPC.TL_userProfilePhotoEmpty();
- }
AndroidUtilities.runOnUIThread(() -> {
+ TLRPC.TL_photos_photo photos_photo = (TLRPC.TL_photos_photo) response;
+ TLRPC.User user1 = getUser(getUserConfig().getClientUserId());
+ if (user1 == null) {
+ user1 = getUserConfig().getCurrentUser();
+ putUser(user1, false);
+ } else {
+ getUserConfig().setCurrentUser(user1);
+ }
+ if (user1 == null) {
+ return;
+ }
+ ArrayList users = new ArrayList<>();
+ users.add(user1);
+ getMessagesStorage().putUsersAndChats(users, null, false, true);
+ if (photos_photo.photo instanceof TLRPC.TL_photo) {
+ user1.photo = new TLRPC.TL_userProfilePhoto();
+ user1.photo.has_video = !photos_photo.photo.video_sizes.isEmpty();
+ user1.photo.photo_id = photos_photo.photo.id;
+ user1.photo.photo_small = FileLoader.getClosestPhotoSizeWithSize(photos_photo.photo.sizes, 150).location;
+ user1.photo.photo_big = FileLoader.getClosestPhotoSizeWithSize(photos_photo.photo.sizes, 800).location;
+ user1.photo.dc_id = photos_photo.photo.dc_id;
+ } else {
+ user1.photo = new TLRPC.TL_userProfilePhotoEmpty();
+ }
+
+ TLRPC.UserFull userFull = getUserFull(getUserConfig().getClientUserId());
+ userFull.profile_photo = photos_photo.photo;
+ getMessagesStorage().updateUserInfo(userFull, false);
+
+ getUserConfig().getCurrentUser().photo = user1.photo;
+ putUser(user1, false);
+
getNotificationCenter().postNotificationName(NotificationCenter.mainUserInfoChanged);
getNotificationCenter().postNotificationName(NotificationCenter.updateInterfaces, UPDATE_MASK_ALL);
+ getNotificationCenter().postNotificationName(NotificationCenter.updateInterfaces, UPDATE_MASK_AVATAR);
getUserConfig().saveConfig(true);
});
}
@@ -6336,6 +6391,7 @@ public void loadChannelParticipants(Long chatId) {
public void putChatFull(TLRPC.ChatFull chatFull) {
fullChats.put(chatFull.id, chatFull);
+ getTranslateController().updateDialogFull(-chatFull.id);
}
public void processChatInfo(long chatId, TLRPC.ChatFull info, ArrayList usersArr, boolean fromCache, boolean force, boolean byChannelUsers, ArrayList pinnedMessages, HashMap pinnedMessagesMap, int totalPinnedCount, boolean pinnedEndReached) {
@@ -6349,6 +6405,7 @@ public void processChatInfo(long chatId, TLRPC.ChatFull info, ArrayList 0 || isEncryptedChat || arr.size() == 1) {
PrintingUser pu = arr.get(0);
TLRPC.User user = getUser(pu.userId);
if (user == null) {
continue;
}
+ final boolean isGroup = key < 0 && !isEncryptedChat;
if (pu.action instanceof TLRPC.TL_sendMessageRecordAudioAction) {
- if (key < 0 && !isEncryptedChat) {
- newPrintingStrings.put(threadId, LocaleController.formatString("IsRecordingAudio", R.string.IsRecordingAudio, getUserNameForTyping(user)));
+ if (isGroup) {
+ text = LocaleController.formatString("IsRecordingAudio", R.string.IsRecordingAudio, getUserNameForTyping(user));
} else {
- newPrintingStrings.put(threadId, LocaleController.getString("RecordingAudio", R.string.RecordingAudio));
+ text = LocaleController.getString("RecordingAudio", R.string.RecordingAudio);
}
- newPrintingStringsTypes.put(threadId, 1);
+ type = 1;
} else if (pu.action instanceof TLRPC.TL_sendMessageRecordRoundAction) {
- if (key < 0 && !isEncryptedChat) {
- newPrintingStrings.put(threadId, LocaleController.formatString("IsRecordingRound", R.string.IsRecordingRound, getUserNameForTyping(user)));
+ if (isGroup) {
+ text = LocaleController.formatString("IsRecordingRound", R.string.IsRecordingRound, getUserNameForTyping(user));
} else {
- newPrintingStrings.put(threadId, LocaleController.getString("RecordingRound", R.string.RecordingRound));
+ text = LocaleController.getString("RecordingRound", R.string.RecordingRound);
}
- newPrintingStringsTypes.put(threadId, 4);
+ type = 4;
} else if (pu.action instanceof TLRPC.TL_sendMessageUploadRoundAction) {
- if (key < 0 && !isEncryptedChat) {
- newPrintingStrings.put(threadId, LocaleController.formatString("IsSendingVideo", R.string.IsSendingVideo, getUserNameForTyping(user)));
+ if (isGroup) {
+ text = LocaleController.formatString("IsSendingVideo", R.string.IsSendingVideo, getUserNameForTyping(user));
} else {
- newPrintingStrings.put(threadId, LocaleController.getString("SendingVideoStatus", R.string.SendingVideoStatus));
+ text = LocaleController.getString("SendingVideoStatus", R.string.SendingVideoStatus);
}
- newPrintingStringsTypes.put(threadId, 4);
+ type = 4;
} else if (pu.action instanceof TLRPC.TL_sendMessageUploadAudioAction) {
- if (key < 0 && !isEncryptedChat) {
- newPrintingStrings.put(threadId, LocaleController.formatString("IsSendingAudio", R.string.IsSendingAudio, getUserNameForTyping(user)));
+ if (isGroup) {
+ text = LocaleController.formatString("IsSendingAudio", R.string.IsSendingAudio, getUserNameForTyping(user));
} else {
- newPrintingStrings.put(threadId, LocaleController.getString("SendingAudio", R.string.SendingAudio));
+ text = LocaleController.getString("SendingAudio", R.string.SendingAudio);
}
- newPrintingStringsTypes.put(threadId, 2);
+ type = 2;
} else if (pu.action instanceof TLRPC.TL_sendMessageUploadVideoAction) {
- if (key < 0 && !isEncryptedChat) {
- newPrintingStrings.put(threadId, LocaleController.formatString("IsSendingVideo", R.string.IsSendingVideo, getUserNameForTyping(user)));
+ if (isGroup) {
+ text = LocaleController.formatString("IsSendingVideo", R.string.IsSendingVideo, getUserNameForTyping(user));
} else {
- newPrintingStrings.put(threadId, LocaleController.getString("SendingVideoStatus", R.string.SendingVideoStatus));
+ text = LocaleController.getString("SendingVideoStatus", R.string.SendingVideoStatus);
}
- newPrintingStringsTypes.put(threadId, 2);
+ type = 2;
} else if (pu.action instanceof TLRPC.TL_sendMessageRecordVideoAction) {
- if (key < 0 && !isEncryptedChat) {
- newPrintingStrings.put(threadId, LocaleController.formatString("IsRecordingVideo", R.string.IsRecordingVideo, getUserNameForTyping(user)));
+ if (isGroup) {
+ text = LocaleController.formatString("IsRecordingVideo", R.string.IsRecordingVideo, getUserNameForTyping(user));
} else {
- newPrintingStrings.put(threadId, LocaleController.getString("RecordingVideoStatus", R.string.RecordingVideoStatus));
+ text = LocaleController.getString("RecordingVideoStatus", R.string.RecordingVideoStatus);
}
- newPrintingStringsTypes.put(threadId, 2);
+ type = 2;
} else if (pu.action instanceof TLRPC.TL_sendMessageUploadDocumentAction) {
- if (key < 0 && !isEncryptedChat) {
- newPrintingStrings.put(threadId, LocaleController.formatString("IsSendingFile", R.string.IsSendingFile, getUserNameForTyping(user)));
+ if (isGroup) {
+ text = LocaleController.formatString("IsSendingFile", R.string.IsSendingFile, getUserNameForTyping(user));
} else {
- newPrintingStrings.put(threadId, LocaleController.getString("SendingFile", R.string.SendingFile));
+ text = LocaleController.getString("SendingFile", R.string.SendingFile);
}
- newPrintingStringsTypes.put(threadId, 2);
+ type = 2;
} else if (pu.action instanceof TLRPC.TL_sendMessageUploadPhotoAction) {
- if (key < 0 && !isEncryptedChat) {
- newPrintingStrings.put(threadId, LocaleController.formatString("IsSendingPhoto", R.string.IsSendingPhoto, getUserNameForTyping(user)));
+ if (isGroup) {
+ text = LocaleController.formatString("IsSendingPhoto", R.string.IsSendingPhoto, getUserNameForTyping(user));
} else {
- newPrintingStrings.put(threadId, LocaleController.getString("SendingPhoto", R.string.SendingPhoto));
+ text = LocaleController.getString("SendingPhoto", R.string.SendingPhoto);
}
- newPrintingStringsTypes.put(threadId, 2);
+ type = 2;
} else if (pu.action instanceof TLRPC.TL_sendMessageGamePlayAction) {
- if (key < 0 && !isEncryptedChat) {
- newPrintingStrings.put(threadId, LocaleController.formatString("IsSendingGame", R.string.IsSendingGame, getUserNameForTyping(user)));
+ if (isGroup) {
+ text = LocaleController.formatString("IsSendingGame", R.string.IsSendingGame, getUserNameForTyping(user));
} else {
- newPrintingStrings.put(threadId, LocaleController.getString("SendingGame", R.string.SendingGame));
+ text = LocaleController.getString("SendingGame", R.string.SendingGame);
}
- newPrintingStringsTypes.put(threadId, 3);
+ type = 3;
} else if (pu.action instanceof TLRPC.TL_sendMessageGeoLocationAction) {
- if (key < 0 && !isEncryptedChat) {
- newPrintingStrings.put(threadId, LocaleController.formatString("IsSelectingLocation", R.string.IsSelectingLocation, getUserNameForTyping(user)));
+ if (isGroup) {
+ text = LocaleController.formatString("IsSelectingLocation", R.string.IsSelectingLocation, getUserNameForTyping(user));
} else {
- newPrintingStrings.put(threadId, LocaleController.getString("SelectingLocation", R.string.SelectingLocation));
+ text = LocaleController.getString("SelectingLocation", R.string.SelectingLocation);
}
- newPrintingStringsTypes.put(threadId, 0);
+ type = 0;
} else if (pu.action instanceof TLRPC.TL_sendMessageChooseContactAction) {
- if (key < 0 && !isEncryptedChat) {
- newPrintingStrings.put(threadId, LocaleController.formatString("IsSelectingContact", R.string.IsSelectingContact, getUserNameForTyping(user)));
+ if (isGroup) {
+ text = LocaleController.formatString("IsSelectingContact", R.string.IsSelectingContact, getUserNameForTyping(user));
} else {
- newPrintingStrings.put(threadId, LocaleController.getString("SelectingContact", R.string.SelectingContact));
+ text = LocaleController.getString("SelectingContact", R.string.SelectingContact);
}
- newPrintingStringsTypes.put(threadId, 0);
+ type = 0;
} else if (pu.action instanceof TLRPC.TL_sendMessageEmojiInteractionSeen) {
- String emoji = ((TLRPC.TL_sendMessageEmojiInteractionSeen) pu.action).emoticon;
- String printingString;
- if (key < 0 && !isEncryptedChat) {
- printingString = LocaleController.formatString("IsEnjoyngAnimations", R.string.IsEnjoyngAnimations, getUserNameForTyping(user), emoji);
+ final String emoji = ((TLRPC.TL_sendMessageEmojiInteractionSeen) pu.action).emoticon;
+ if (isGroup) {
+ text = LocaleController.formatString("IsEnjoyngAnimations", R.string.IsEnjoyngAnimations, getUserNameForTyping(user), emoji);
} else {
- printingString = LocaleController.formatString("EnjoyngAnimations", R.string.EnjoyngAnimations, emoji);
+ text = LocaleController.formatString("EnjoyngAnimations", R.string.EnjoyngAnimations, emoji);
}
- newPrintingStrings.put(threadId, printingString);
- newPrintingStringsTypes.put(threadId, 5);
+ type = 5;
} else if (pu.action instanceof TLRPC.TL_sendMessageChooseStickerAction) {
- if (key < 0 && !isEncryptedChat) {
- newPrintingStrings.put(threadId, LocaleController.formatString("IsChoosingSticker", R.string.IsChoosingSticker, getUserNameForTyping(user)));
+ if (isGroup) {
+ text = LocaleController.formatString("IsChoosingSticker", R.string.IsChoosingSticker, getUserNameForTyping(user));
} else {
- newPrintingStrings.put(threadId, LocaleController.getString("ChoosingSticker", R.string.ChoosingSticker));
+ text = LocaleController.getString("ChoosingSticker", R.string.ChoosingSticker);
}
- newPrintingStringsTypes.put(threadId, 5);
+ type = 5;
} else {
- if (key < 0 && !isEncryptedChat) {
- newPrintingStrings.put(threadId, LocaleController.formatString("IsTypingGroup", R.string.IsTypingGroup, getUserNameForTyping(user)));
+ if (isGroup) {
+ text = LocaleController.formatString("IsTypingGroup", R.string.IsTypingGroup, getUserNameForTyping(user));
} else {
- newPrintingStrings.put(threadId, LocaleController.getString("Typing", R.string.Typing));
+ text = LocaleController.getString("Typing", R.string.Typing);
}
- newPrintingStringsTypes.put(threadId, 0);
+ type = 0;
}
} else {
int count = 0;
@@ -7188,22 +7248,30 @@ private void updatePrintingStrings() {
}
if (label.length() != 0) {
if (count == 1) {
- newPrintingStrings.put(threadId, LocaleController.formatString("IsTypingGroup", R.string.IsTypingGroup, label.toString()));
+ text = LocaleController.formatString("IsTypingGroup", R.string.IsTypingGroup, label.toString());
} else {
if (arr.size() > 2) {
String plural = LocaleController.getPluralString("AndMoreTypingGroup", arr.size() - 2);
try {
- newPrintingStrings.put(threadId, String.format(plural, label.toString(), arr.size() - 2));
+ text = String.format(plural, label.toString(), arr.size() - 2);
} catch (Exception e) {
- newPrintingStrings.put(threadId, "LOC_ERR: AndMoreTypingGroup");
+ text = "LOC_ERR: AndMoreTypingGroup";
}
} else {
- newPrintingStrings.put(threadId, LocaleController.formatString("AreTypingGroup", R.string.AreTypingGroup, label.toString()));
+ text = LocaleController.formatString("AreTypingGroup", R.string.AreTypingGroup, label.toString());
}
}
- newPrintingStringsTypes.put(threadId, 0);
+ type = 0;
}
}
+ if (text != null && ApplicationLoader.applicationContext != null) {
+ if (Theme.dialogs_messageNamePaint == null) {
+ Theme.createDialogsResources(ApplicationLoader.applicationContext);
+ }
+ text = Emoji.replaceEmoji(text, Theme.dialogs_messageNamePaint.getFontMetricsInt(), false);
+ newPrintingStrings.put(threadId, text);
+ newPrintingStringsTypes.put(threadId, type);
+ }
}
}
@@ -8085,7 +8153,7 @@ public void loadDialogs(final int folderId, int offset, int count, boolean fromC
getConnectionsManager().sendRequest(req, (response, error) -> {
if (error == null) {
TLRPC.messages_Dialogs dialogsRes = (TLRPC.messages_Dialogs) response;
- processLoadedDialogs(dialogsRes, null, folderId, 0, count, 0, false, false, false);
+ processLoadedDialogs(dialogsRes, null, null, folderId, 0, count, 0, false, false, false);
if (onEmptyCallback != null && dialogsRes.dialogs.isEmpty()) {
AndroidUtilities.runOnUIThread(onEmptyCallback);
}
@@ -8258,7 +8326,7 @@ protected void loadUnknownDialog(final TLRPC.InputPeer peer, long taskId) {
dialogs.messages.addAll(res.messages);
dialogs.users.addAll(res.users);
dialogs.chats.addAll(res.chats);
- processLoadedDialogs(dialogs, null, dialog.folder_id, 0, 1, DIALOGS_LOAD_TYPE_UNKNOWN, false, false, false);
+ processLoadedDialogs(dialogs, null, null, dialog.folder_id, 0, 1, DIALOGS_LOAD_TYPE_UNKNOWN, false, false, false);
}
}
if (newTaskId != 0) {
@@ -8544,6 +8612,7 @@ protected void completeDialogsReset(final TLRPC.messages_Dialogs dialogsRes, int
}
}
}
+ getTranslateController().checkDialogMessages(key);
}
allDialogs.clear();
@@ -8764,7 +8833,7 @@ private void migrateDialogs(int offset, int offsetDate, long offsetUser, long of
}
}
- processLoadedDialogs(dialogsRes, null, 0, offsetId, 0, 0, false, true, false);
+ processLoadedDialogs(dialogsRes, null, null, 0, offsetId, 0, 0, false, true, false);
} catch (Exception e) {
FileLog.e(e);
AndroidUtilities.runOnUIThread(() -> migratingDialogs = false);
@@ -8780,7 +8849,7 @@ private void migrateDialogs(int offset, int offsetDate, long offsetUser, long of
private int DIALOGS_LOAD_TYPE_CHANNEL = 2;
private int DIALOGS_LOAD_TYPE_UNKNOWN = 3;
- public void processLoadedDialogs(final TLRPC.messages_Dialogs dialogsRes, ArrayList encChats, int folderId, int offset, int count, int loadType, boolean resetEnd, boolean migrate, boolean fromCache) {
+ public void processLoadedDialogs(final TLRPC.messages_Dialogs dialogsRes, ArrayList encChats, ArrayList fullUsers, int folderId, int offset, int count, int loadType, boolean resetEnd, boolean migrate, boolean fromCache) {
Utilities.stageQueue.postRunnable(() -> {
if (!firstGettingTask) {
getNewDeleteTask(null, null);
@@ -8794,6 +8863,13 @@ public void processLoadedDialogs(final TLRPC.messages_Dialogs dialogsRes, ArrayL
if (loadType == DIALOGS_LOAD_TYPE_CACHE && dialogsRes.dialogs.size() == 0) {
AndroidUtilities.runOnUIThread(() -> {
putUsers(dialogsRes.users, true);
+ if (fullUsers != null) {
+ for (int i = 0; i < fullUsers.size(); i++) {
+ long did = fullUsers.get(i).id;
+ this.fullUsers.put(did, fullUsers.get(i));
+ getTranslateController().updateDialogFull(did);
+ }
+ }
loadingDialogs.put(folderId, false);
if (resetEnd) {
dialogsEndReached.put(folderId, false);
@@ -9040,6 +9116,13 @@ public void processLoadedDialogs(final TLRPC.messages_Dialogs dialogsRes, ArrayL
}
putUsers(dialogsRes.users, loadType == DIALOGS_LOAD_TYPE_CACHE);
putChats(dialogsRes.chats, loadType == DIALOGS_LOAD_TYPE_CACHE);
+ if (fullUsers != null) {
+ for (int i = 0; i < fullUsers.size(); i++) {
+ long did = fullUsers.get(i).id;
+ this.fullUsers.put(did, fullUsers.get(i));
+ getTranslateController().updateDialogFull(did);
+ }
+ }
if (encChats != null) {
for (int a = 0; a < encChats.size(); a++) {
@@ -9090,6 +9173,7 @@ public void processLoadedDialogs(final TLRPC.messages_Dialogs dialogsRes, ArrayL
}
}
}
+ getTranslateController().checkDialogMessages(key);
} else {
if (loadType != DIALOGS_LOAD_TYPE_CACHE) {
currentDialog.notify_settings = value.notify_settings;
@@ -9141,6 +9225,7 @@ public void processLoadedDialogs(final TLRPC.messages_Dialogs dialogsRes, ArrayL
}
}
}
+ getTranslateController().checkDialogMessages(key);
}
} else {
// if (newMsg == null && oldMs.getId() > 0 || newMsg != null && newMsg.messageOwner.date > oldMsg.messageOwner.date)
@@ -9178,6 +9263,7 @@ public void processLoadedDialogs(final TLRPC.messages_Dialogs dialogsRes, ArrayL
}
}
}
+ getTranslateController().checkDialogMessages(key);
}
}
}
@@ -9635,6 +9721,7 @@ public void processDialogsUpdate(final TLRPC.messages_Dialogs dialogsRes, ArrayL
FileLog.d("processDialogsUpdate new message not null");
}
}
+ getTranslateController().checkDialogMessages(key);
} else {
if (BuildVars.LOGS_ENABLED) {
FileLog.d("processDialogsUpdate dialog not null");
@@ -9694,6 +9781,7 @@ public void processDialogsUpdate(final TLRPC.messages_Dialogs dialogsRes, ArrayL
}
}
}
+ getTranslateController().checkDialogMessages(key);
}
if (fromCache && newMsgs == null) {
checkLastDialogMessage(value, null, 0);
@@ -9740,6 +9828,7 @@ public void processDialogsUpdate(final TLRPC.messages_Dialogs dialogsRes, ArrayL
}
}
}
+ getTranslateController().checkDialogMessages(key);
}
}
}
@@ -10268,7 +10357,7 @@ public int createChat(String title, ArrayList selectedContacts, String abo
if (type == ChatObject.CHAT_TYPE_CHAT && !forImport) {
TLRPC.TL_messages_createChat req = new TLRPC.TL_messages_createChat();
req.title = title;
- if (ttlPeriod > 0) {
+ if (ttlPeriod >= 0) {
req.ttl_period = ttlPeriod;
req.flags |= 1;
}
@@ -10299,16 +10388,17 @@ public int createChat(String title, ArrayList selectedContacts, String abo
}
});
}, ConnectionsManager.RequestFlagFailOnServerErrors);
- } else if (forImport || type == ChatObject.CHAT_TYPE_CHANNEL || type == ChatObject.CHAT_TYPE_MEGAGROUP) {
+ } else if (forImport || type == ChatObject.CHAT_TYPE_CHANNEL || type == ChatObject.CHAT_TYPE_MEGAGROUP || type == ChatObject.CHAT_TYPE_FORUM) {
TLRPC.TL_channels_createChannel req = new TLRPC.TL_channels_createChannel();
req.title = title;
req.about = about != null ? about : "";
req.for_import = forImport;
- if (forImport || type == ChatObject.CHAT_TYPE_MEGAGROUP) {
+ if (forImport || type == ChatObject.CHAT_TYPE_MEGAGROUP || type == ChatObject.CHAT_TYPE_FORUM) {
req.megagroup = true;
} else {
req.broadcast = true;
}
+ req.forum = type == ChatObject.CHAT_TYPE_FORUM;
if (location != null) {
req.geo_point = new TLRPC.TL_inputGeoPoint();
req.geo_point.lat = location.getLatitude();
@@ -10962,12 +11052,12 @@ public void changeChatTitle(long chatId, String title) {
}, ConnectionsManager.RequestFlagInvokeAfter);
}
- public void changeChatAvatar(long chatId, TLRPC.TL_inputChatPhoto oldPhoto, TLRPC.InputFile inputPhoto, TLRPC.InputFile inputVideo, double videoStartTimestamp, String videoPath, TLRPC.FileLocation smallSize, TLRPC.FileLocation bigSize, Runnable callback) {
+ public void changeChatAvatar(long chatId, TLRPC.TL_inputChatPhoto oldPhoto, TLRPC.InputFile inputPhoto, TLRPC.InputFile inputVideo, TLRPC.VideoSize emojiMarkup, double videoStartTimestamp, String videoPath, TLRPC.FileLocation smallSize, TLRPC.FileLocation bigSize, Runnable callback) {
TLObject request;
TLRPC.InputChatPhoto inputChatPhoto;
if (oldPhoto != null) {
inputChatPhoto = oldPhoto;
- } else if (inputPhoto != null || inputVideo != null) {
+ } else if (inputPhoto != null || inputVideo != null || emojiMarkup != null) {
TLRPC.TL_inputChatUploadedPhoto uploadedPhoto = new TLRPC.TL_inputChatUploadedPhoto();
if (inputPhoto != null) {
uploadedPhoto.file = inputPhoto;
@@ -10979,6 +11069,10 @@ public void changeChatAvatar(long chatId, TLRPC.TL_inputChatPhoto oldPhoto, TLRP
uploadedPhoto.video_start_ts = videoStartTimestamp;
uploadedPhoto.flags |= 4;
}
+ if (emojiMarkup != null) {
+ uploadedPhoto.video_emoji_markup = emojiMarkup;
+ uploadedPhoto.flags |= 8;
+ }
inputChatPhoto = uploadedPhoto;
} else {
inputChatPhoto = new TLRPC.TL_inputChatPhotoEmpty();
@@ -11039,6 +11133,7 @@ public void changeChatAvatar(long chatId, TLRPC.TL_inputChatPhoto oldPhoto, TLRP
File src = new File(videoPath);
src.renameTo(destFile);
}
+ getMessagesStorage().addDialogPhoto(-chatId, photo);
}
}
processUpdates(updates, false);
@@ -11047,6 +11142,7 @@ public void changeChatAvatar(long chatId, TLRPC.TL_inputChatPhoto oldPhoto, TLRP
callback.run();
}
getNotificationCenter().postNotificationName(NotificationCenter.updateInterfaces, MessagesController.UPDATE_MASK_AVATAR);
+ getNotificationCenter().postNotificationName(NotificationCenter.reloadDialogPhotos);
});
}, ConnectionsManager.RequestFlagInvokeAfter);
}
@@ -11076,13 +11172,8 @@ public void performLogout(int type) {
getConnectionsManager().cleanup(false);
AndroidUtilities.runOnUIThread(() -> {
if (response instanceof TLRPC.TL_auth_loggedOut) {
- TLRPC.TL_auth_loggedOut res = (TLRPC.TL_auth_loggedOut) response;
if (((TLRPC.TL_auth_loggedOut) response).future_auth_token != null) {
- SharedPreferences preferences = ApplicationLoader.applicationContext.getSharedPreferences("saved_tokens", Context.MODE_PRIVATE);
- int count = preferences.getInt("count", 0);
- SerializedData data = new SerializedData(response.getObjectSize());
- res.serializeToStream(data);
- preferences.edit().putString("log_out_token_" + count, Utilities.bytesToHex(data.toByteArray())).putInt("count", count + 1).apply();
+ AuthTokensHelper.addLogOutToken((TLRPC.TL_auth_loggedOut) response);
}
}
});
@@ -11125,44 +11216,6 @@ public void performLogout(int type) {
getContactsController().deleteUnknownAppAccounts();
}
- public static ArrayList getSavedLogOutTokens() {
- SharedPreferences preferences = ApplicationLoader.applicationContext.getSharedPreferences("saved_tokens", Context.MODE_PRIVATE);
- int count = preferences.getInt("count", 0);
- if (count == 0) {
- return null;
- }
-
- ArrayList tokens = new ArrayList<>();
- for (int i = 0; i < count; i++) {
- String value = preferences.getString("log_out_token_" + i, "");
- SerializedData serializedData = new SerializedData(Utilities.hexToBytes(value));
- TLRPC.TL_auth_loggedOut token = TLRPC.TL_auth_loggedOut.TLdeserialize(serializedData, serializedData.readInt32(true), true);
- if (token != null) {
- tokens.add(token);
- }
- }
- return tokens;
- }
-
- public static void saveLogOutTokens(ArrayList tokens) {
- SharedPreferences preferences = ApplicationLoader.applicationContext.getSharedPreferences("saved_tokens", Context.MODE_PRIVATE);
- ArrayList activeTokens = new ArrayList<>();
- preferences.edit().clear().apply();
- int date = (int) (System.currentTimeMillis() / 1000L);
- for (int i = 0; i < Math.min(20, tokens.size()); i++) {
- activeTokens.add(tokens.get(i));
- }
- if (activeTokens.size() > 0) {
- SharedPreferences.Editor editor = preferences.edit();
- editor.putInt("count", activeTokens.size());
- for (int i = 0; i < activeTokens.size(); i++) {
- SerializedData data = new SerializedData(activeTokens.get(i).getObjectSize());
- activeTokens.get(i).serializeToStream(data);
- editor.putString("log_out_token_" + i, Utilities.bytesToHex(data.toByteArray()));
- }
- editor.apply();
- }
- }
private boolean gettingAppChangelog;
@@ -11478,7 +11531,7 @@ protected void loadUnknownChannel(final TLRPC.Chat channel, long taskId) {
dialogs.messages.addAll(res.messages);
dialogs.users.addAll(res.users);
dialogs.chats.addAll(res.chats);
- processLoadedDialogs(dialogs, null, dialog.folder_id, 0, 1, DIALOGS_LOAD_TYPE_CHANNEL, false, false, false);
+ processLoadedDialogs(dialogs, null, null, dialog.folder_id, 0, 1, DIALOGS_LOAD_TYPE_CHANNEL, false, false, false);
}
}
if (newTaskId != 0) {
@@ -12458,6 +12511,7 @@ public void loadPinnedDialogs(final int folderId, long newDialogId, ArrayList updates, ArrayList> array;
if (editingMessages == null) {
@@ -15047,7 +15102,7 @@ public boolean processUpdateArray(ArrayList updates, ArrayList 0) {
+ if ((update.flags & 1) != 0) {
getTopicsController().applyPinnedOrder(update.channel_id, update.order);
} else {
getTopicsController().reloadTopics(update.channel_id, false);
@@ -16283,6 +16338,7 @@ public boolean updateInterfaceWithMessages(long dialogId, ArrayList chatsDict) {
if (sortingDialogFilter == null) {
continue;
}
- Collections.sort(allDialogs, dialogDateComparator);
+ try {
+ Collections.sort(allDialogs, dialogDateComparator);
+ } catch (Exception e) {
+ FileLog.e(e);
+ }
ArrayList dialogsByFilter = sortingDialogFilter.dialogs;
for (int a = 0, N = allDialogs.size(); a < N; a++) {
@@ -16973,6 +17038,73 @@ public void setChatReactions(long chatId, int type, List reactions) {
});
}
+ public boolean matchesAdminRights(TLRPC.Chat chat, TLRPC.User user, TLRPC.TL_chatAdminRights rights) {
+ if (rights == null) {
+ return true;
+ }
+ TLRPC.TL_chatAdminRights userRights = getChatAdminRightsCached(chat, user);
+ return (
+ (!rights.change_info || userRights != null && userRights.change_info) &&
+ (!rights.post_messages || userRights != null && userRights.post_messages) &&
+ (!rights.edit_messages || userRights != null && userRights.edit_messages) &&
+ (!rights.delete_messages || userRights != null && userRights.delete_messages) &&
+ (!rights.ban_users || userRights != null && userRights.ban_users) &&
+ (!rights.invite_users || userRights != null && userRights.invite_users) &&
+ (!rights.pin_messages || userRights != null && userRights.pin_messages) &&
+ (!rights.add_admins || userRights != null && userRights.add_admins) &&
+ (!rights.anonymous || userRights != null && userRights.anonymous) &&
+ (!rights.manage_call || userRights != null && userRights.manage_call) &&
+ (!rights.other || userRights != null && userRights.other) &&
+ (!rights.manage_topics || userRights != null && userRights.manage_topics)
+ );
+ }
+
+ public TLRPC.TL_chatAdminRights getChatAdminRightsCached(TLRPC.Chat chat, TLRPC.User user) {
+ if (chat == null || user == null) {
+ return null;
+ }
+ if (UserObject.isUserSelf(user)) {
+ return chat.admin_rights;
+ }
+ final TLRPC.ChatFull chatFull = getChatFull(chat.id);
+ if (chatFull == null || chatFull.participants == null || chatFull.participants.participants == null) {
+ return null;
+ }
+ final ArrayList participants = chatFull.participants.participants;
+
+ for (int i = 0; i < participants.size(); ++i) {
+ TLRPC.ChatParticipant participant = participants.get(i);
+ if (participant != null && participant.user_id == user.id) {
+ if (participant instanceof TLRPC.TL_chatChannelParticipant && ((TLRPC.TL_chatChannelParticipant) participant).channelParticipant != null) {
+ return ((TLRPC.TL_chatChannelParticipant) participant).channelParticipant.admin_rights;
+ }
+ return null;
+ }
+ }
+ return null;
+ }
+
+ public boolean isInChatCached(TLRPC.Chat chat, TLRPC.User user) {
+ if (chat == null || user == null) {
+ return false;
+ }
+ if (UserObject.isUserSelf(user)) {
+ return !ChatObject.isNotInChat(chat);
+ }
+ final TLRPC.ChatFull chatFull = getChatFull(chat.id);
+ if (chatFull == null || chatFull.participants == null || chatFull.participants.participants == null) {
+ return false;
+ }
+ final ArrayList participants = chatFull.participants.participants;
+ for (int i = 0; i < participants.size(); ++i) {
+ TLRPC.ChatParticipant participant = participants.get(i);
+ if (participant != null && participant.user_id == user.id) {
+ return true;
+ }
+ }
+ return false;
+ }
+
public void checkIsInChat(boolean tryCacheFirst, TLRPC.Chat chat, TLRPC.User user, IsInChatCheckedCallback callback) {
if (chat == null || user == null) {
if (callback != null) {
diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/MessagesStorage.java b/TMessagesProj/src/main/java/org/telegram/messenger/MessagesStorage.java
index c6a523a9191..e19fd6d6fbd 100644
--- a/TMessagesProj/src/main/java/org/telegram/messenger/MessagesStorage.java
+++ b/TMessagesProj/src/main/java/org/telegram/messenger/MessagesStorage.java
@@ -15,6 +15,7 @@
import android.text.Spanned;
import android.text.TextUtils;
import android.text.style.ForegroundColorSpan;
+import android.util.Log;
import android.util.Pair;
import android.util.SparseArray;
import android.util.SparseIntArray;
@@ -34,6 +35,7 @@
import org.telegram.tgnet.TLRPC;
import org.telegram.ui.ActionBar.Theme;
import org.telegram.ui.Adapters.DialogsSearchAdapter;
+import org.telegram.ui.DialogsActivity;
import org.telegram.ui.EditWidgetActivity;
import java.io.File;
@@ -93,7 +95,7 @@ public class MessagesStorage extends BaseController {
}
}
- private final static int LAST_DB_VERSION = 111;
+ private final static int LAST_DB_VERSION = 112;
private boolean databaseMigrationInProgress;
public boolean showClearDatabaseAlert;
private LongSparseIntArray dialogIsForum = new LongSparseIntArray();
@@ -447,6 +449,8 @@ public void openDatabase(int openTries) {
database.executeFast("CREATE TABLE reaction_mentions_topics(message_id INTEGER, state INTEGER, dialog_id INTEGER, topic_id INTEGER, PRIMARY KEY(message_id, dialog_id, topic_id))").stepThis().dispose();
database.executeFast("CREATE INDEX IF NOT EXISTS reaction_mentions_topics_did ON reaction_mentions_topics(dialog_id, topic_id);").stepThis().dispose();
+ database.executeFast("CREATE TABLE emoji_groups(type INTEGER PRIMARY KEY, data BLOB)").stepThis().dispose();
+
//version
database.executeFast("PRAGMA user_version = " + LAST_DB_VERSION).stepThis().dispose();
} else {
@@ -502,9 +506,9 @@ public void openDatabase(int openTries) {
}
} catch (Exception e) {
FileLog.e(e);
- if (BuildVars.DEBUG_PRIVATE_VERSION) {
- throw new RuntimeException(e);
- }
+// if (BuildVars.DEBUG_PRIVATE_VERSION) {
+// throw new RuntimeException(e);
+// }
if (openTries < 3 && e.getMessage() != null && e.getMessage().contains("malformed")) {
if (openTries == 2) {
cleanupInternal(true);
@@ -3917,68 +3921,82 @@ public void putDialogPhotos(long did, TLRPC.photos_Photos photos, ArrayList {
- SQLitePreparedStatement state = null;
- try {
- database.executeFast("DELETE FROM user_photos WHERE uid = " + did).stepThis().dispose();
- state = database.executeFast("REPLACE INTO user_photos VALUES(?, ?, ?)");
- for (int a = 0, N = photos.photos.size(); a < N; a++) {
- TLRPC.Photo photo = photos.photos.get(a);
- if (photo instanceof TLRPC.TL_photoEmpty) {
- continue;
- }
- if (photo.file_reference == null) {
- photo.file_reference = new byte[0];
- }
- state.requery();
- int size = photo.getObjectSize();
- if (messages != null) {
- size += messages.get(a).getObjectSize();
- }
- NativeByteBuffer data = new NativeByteBuffer(size);
- photo.serializeToStream(data);
- if (messages != null) {
- messages.get(a).serializeToStream(data);
- }
- state.bindLong(1, did);
- state.bindLong(2, photo.id);
- state.bindByteBuffer(3, data);
- state.step();
- data.reuse();
- }
- state.dispose();
- state = null;
- } catch (Exception e) {
- FileLog.e(e);
- } finally {
- if (state != null) {
- state.dispose();
- }
- }
+ putDialogPhotosInternal(did, photos, messages);
});
}
- public void addDialogPhoto(long did, TLRPC.Photo photo) {
- storageQueue.postRunnable(() -> {
- SQLitePreparedStatement state = null;
- try {
- state = database.executeFast("REPLACE INTO user_photos VALUES(?, ?, ?)");
-
+ private void putDialogPhotosInternal(long did, TLRPC.photos_Photos photos, ArrayList messages) {
+ SQLitePreparedStatement state = null;
+ try {
+ database.executeFast("DELETE FROM user_photos WHERE uid = " + did).stepThis().dispose();
+ state = database.executeFast("REPLACE INTO user_photos VALUES(?, ?, ?)");
+ for (int a = 0, N = photos.photos.size(); a < N; a++) {
+ TLRPC.Photo photo = photos.photos.get(a);
+ if (photo instanceof TLRPC.TL_photoEmpty || photo == null) {
+ continue;
+ }
+ if (photo.file_reference == null) {
+ photo.file_reference = new byte[0];
+ }
state.requery();
int size = photo.getObjectSize();
+ if (messages != null && messages.get(a) != null) {
+ size += messages.get(a).getObjectSize();
+ }
NativeByteBuffer data = new NativeByteBuffer(size);
photo.serializeToStream(data);
+ if (messages != null && messages.get(a) != null) {
+ messages.get(a).serializeToStream(data);
+ }
state.bindLong(1, did);
state.bindLong(2, photo.id);
state.bindByteBuffer(3, data);
state.step();
data.reuse();
+ }
+ state.dispose();
+ state = null;
+ } catch (Exception e) {
+ FileLog.e(e);
+ } finally {
+ if (state != null) {
state.dispose();
- state = null;
+ }
+ }
+ }
+
+ public void addDialogPhoto(long did, TLRPC.Photo photoToAdd) {
+ storageQueue.postRunnable(() -> {
+ SQLiteCursor cursor = null;
+ try {
+ cursor = database.queryFinalized(String.format(Locale.US, "SELECT data FROM user_photos WHERE uid = %d ORDER BY rowid ASC", did));
+
+ TLRPC.photos_Photos res = new TLRPC.TL_photos_photos();
+ ArrayList messages = new ArrayList<>();
+
+ while (cursor.next()) {
+ NativeByteBuffer data = cursor.byteBufferValue(0);
+ if (data != null) {
+ TLRPC.Photo photo = TLRPC.Photo.TLdeserialize(data, data.readInt32(false), false);
+ if (data.remaining() > 0) {
+ messages.add(TLRPC.Message.TLdeserialize(data, data.readInt32(false), false));
+ } else {
+ messages.add(null);
+ }
+ data.reuse();
+ res.photos.add(photo);
+ messages.add(null);
+ }
+ }
+ cursor.dispose();
+ cursor = null;
+ res.photos.add(0, photoToAdd);
+ putDialogPhotosInternal(did, res, messages);
} catch (Exception e) {
FileLog.e(e);
} finally {
- if (state != null) {
- state.dispose();
+ if (cursor != null) {
+ cursor.dispose();
}
}
});
@@ -4260,7 +4278,7 @@ public void updateMessageVoiceTranscriptionOpen(long dialogId, int msgId, TLRPC.
SQLitePreparedStatement state = null;
try {
database.beginTransaction();
- TLRPC.Message message = getMessageWithCustomParamsOnly(msgId, dialogId);
+ TLRPC.Message message = getMessageWithCustomParamsOnlyInternal(msgId, dialogId);
message.voiceTranscriptionOpen = saveFromMessage.voiceTranscriptionOpen;
message.voiceTranscriptionRated = saveFromMessage.voiceTranscriptionRated;
message.voiceTranscriptionFinal = saveFromMessage.voiceTranscriptionFinal;
@@ -4308,7 +4326,7 @@ public void updateMessageVoiceTranscription(long dialogId, int messageId, String
SQLitePreparedStatement state = null;
try {
database.beginTransaction();
- TLRPC.Message message = getMessageWithCustomParamsOnly(messageId, dialogId);
+ TLRPC.Message message = getMessageWithCustomParamsOnlyInternal(messageId, dialogId);
message.voiceTranscriptionFinal = isFinal;
message.voiceTranscriptionId = transcriptionId;
message.voiceTranscription = text;
@@ -4348,7 +4366,7 @@ public void updateMessageVoiceTranscription(long dialogId, int messageId, String
SQLitePreparedStatement state = null;
try {
database.beginTransaction();
- TLRPC.Message message = getMessageWithCustomParamsOnly(messageId, dialogId);
+ TLRPC.Message message = getMessageWithCustomParamsOnlyInternal(messageId, dialogId);
message.voiceTranscriptionOpen = saveFromMessage.voiceTranscriptionOpen;
message.voiceTranscriptionRated = saveFromMessage.voiceTranscriptionRated;
message.voiceTranscriptionFinal = saveFromMessage.voiceTranscriptionFinal;
@@ -4397,7 +4415,7 @@ public void updateMessageCustomParams(long dialogId, TLRPC.Message saveFromMessa
SQLitePreparedStatement state = null;
try {
database.beginTransaction();
- TLRPC.Message message = getMessageWithCustomParamsOnly(saveFromMessage.id, dialogId);
+ TLRPC.Message message = getMessageWithCustomParamsOnlyInternal(saveFromMessage.id, dialogId);
MessageCustomParamsHelper.copyParams(saveFromMessage, message);
for (int i = 0; i < 2; i++) {
@@ -4436,7 +4454,7 @@ public void updateMessageCustomParams(long dialogId, TLRPC.Message saveFromMessa
});
}
- private TLRPC.Message getMessageWithCustomParamsOnly(int messageId, long dialogId) {
+ public TLRPC.Message getMessageWithCustomParamsOnlyInternal(int messageId, long dialogId) {
TLRPC.Message message = new TLRPC.TL_message();
SQLiteCursor cursor = null;
try {
@@ -5838,6 +5856,29 @@ public void getBotCache(String key, RequestDelegate requestDelegate) {
});
}
+ public ArrayList loadUserInfos(HashSet uids) {
+ ArrayList arrayList = new ArrayList<>();
+ try {
+ String ids = TextUtils.join(",", uids);
+ SQLiteCursor cursor = database.queryFinalized("SELECT info, pinned FROM user_settings WHERE uid IN(" + ids + ")");
+ while (cursor.next()) {
+ NativeByteBuffer data = cursor.byteBufferValue(0);
+ if (data != null) {
+ TLRPC.UserFull info = TLRPC.UserFull.TLdeserialize(data, data.readInt32(false), false);
+ info.pinned_msg_id = cursor.intValue(1);
+ arrayList.add(info);
+ data.reuse();
+
+ }
+ }
+ cursor.dispose();
+ cursor = null;
+ } catch (Exception e) {
+ FileLog.e(e);
+ }
+ return arrayList;
+ }
+
public void loadUserInfo(TLRPC.User user, boolean force, int classGuid, int fromMessageId) {
if (user == null) {
return;
@@ -10705,7 +10746,7 @@ private void putMessagesInternal(ArrayList messages, boolean with
state_download.bindInteger(2, type);
state_download.bindInteger(3, message.date);
state_download.bindByteBuffer(4, data);
- state_download.bindString(5, "sent_" + (message.peer_id != null ? message.peer_id.channel_id : 0) + "_" + message.id + "_" + DialogObject.getPeerDialogId(message.peer_id) + "_" + messageObject.type);
+ state_download.bindString(5, "sent_" + (message.peer_id != null ? message.peer_id.channel_id : 0) + "_" + message.id + "_" + DialogObject.getPeerDialogId(message.peer_id) + "_" + messageObject.type + "_" + messageObject.getSize());
state_download.step();
data.reuse();
}
@@ -13715,6 +13756,7 @@ public void getDialogs(int folderId, int offset, int count, boolean loadDraftsPe
SQLiteCursor cursor = null;
try {
ArrayList usersToLoad = new ArrayList<>();
+ HashSet dialogUsers = new HashSet<>();
usersToLoad.add(getUserConfig().getClientUserId());
ArrayList chatsToLoad = new ArrayList<>();
ArrayList encryptedToLoad = new ArrayList<>();
@@ -13856,6 +13898,7 @@ public void getDialogs(int folderId, int offset, int count, boolean loadDraftsPe
if (!usersToLoad.contains(dialogId)) {
usersToLoad.add(dialogId);
}
+ dialogUsers.add(dialogId);
} else if (DialogObject.isChatDialog(dialogId)) {
if (!chatsToLoad.contains(-dialogId)) {
chatsToLoad.add(-dialogId);
@@ -13998,14 +14041,18 @@ public void getDialogs(int folderId, int offset, int count, boolean loadDraftsPe
if (!usersToLoad.isEmpty()) {
getUsersInternal(TextUtils.join(",", usersToLoad), dialogs.users);
}
- getMessagesController().processLoadedDialogs(dialogs, encryptedChats, folderId, offset, count, 1, false, false, true);
+ ArrayList fullUsers = null;
+ if (!dialogUsers.isEmpty()) {
+ fullUsers = loadUserInfos(dialogUsers);
+ }
+ getMessagesController().processLoadedDialogs(dialogs, encryptedChats, fullUsers, folderId, offset, count, 1, false, false, true);
} catch (Exception e) {
dialogs.dialogs.clear();
dialogs.users.clear();
dialogs.chats.clear();
encryptedChats.clear();
FileLog.e(e);
- getMessagesController().processLoadedDialogs(dialogs, encryptedChats, folderId, 0, 100, 1, true, false, true);
+ getMessagesController().processLoadedDialogs(dialogs, encryptedChats, null, folderId, 0, 100, 1, true, false, true);
checkMalformed(e);
} finally {
if (cursor != null) {
@@ -14040,6 +14087,41 @@ public static void createFirstHoles(long did, SQLitePreparedStatement state5, SQ
}
}
+ public void updateDialogData(TLRPC.Dialog dialog) {
+ if (dialog == null) {
+ return;
+ }
+ storageQueue.postRunnable(() -> {
+ SQLiteCursor cursor = null;
+ SQLitePreparedStatement state = null;
+ try {
+ cursor = database.queryFinalized("SELECT data FROM dialogs WHERE did = " + dialog.id);
+ if (!cursor.next()) {
+ return;
+ }
+
+ state = database.executeFast("UPDATE dialogs SET data = ? WHERE did = ?");
+ NativeByteBuffer data = new NativeByteBuffer(dialog.getObjectSize());
+ dialog.serializeToStream(data);
+ state.bindByteBuffer(1, data);
+ state.bindLong(2, dialog.id);
+ state.step();
+ state.dispose();
+ state = null;
+ data.reuse();
+ } catch (Exception e) {
+ FileLog.e(e);
+ } finally {
+ if (cursor != null) {
+ cursor.dispose();
+ }
+ if (state != null) {
+ state.dispose();
+ }
+ }
+ });
+ }
+
private void putDialogsInternal(TLRPC.messages_Dialogs dialogs, int check) {
SQLitePreparedStatement state_messages = null;
SQLitePreparedStatement state_dialogs = null;
@@ -14777,7 +14859,7 @@ public TLRPC.EncryptedChat getEncryptedChat(long chatId) {
}
- public void localSearch(int dialogsType, String query, ArrayList