diff --git a/TMessagesProj/build.gradle b/TMessagesProj/build.gradle index 529001fe5..dbbc38ccb 100644 --- a/TMessagesProj/build.gradle +++ b/TMessagesProj/build.gradle @@ -3,15 +3,15 @@ import cn.hutool.core.util.RuntimeUtil apply plugin: "com.android.application" apply plugin: "kotlin-android" -def verName = "8.5.1" -def verCode = 570 +def verName = "8.5.2-rc01" +def verCode = 575 if (System.getenv("DEBUG_BUILD") == "true") { verName += "-" + RuntimeUtil.execForStr("git log --pretty=format:'%h' -n 1").trim() } -def officialVer = "8.5.1" -def officialCode = 2551 +def officialVer = "8.5.2" +def officialCode = 2563 def serviceAccountCredentialsFile = rootProject.file("service_account_credentials.json") diff --git a/TMessagesProj/jni/gifvideo.cpp b/TMessagesProj/jni/gifvideo.cpp index 44919d3c3..8fabd4974 100644 --- a/TMessagesProj/jni/gifvideo.cpp +++ b/TMessagesProj/jni/gifvideo.cpp @@ -1179,9 +1179,9 @@ static inline void writeFrameToBitmap(JNIEnv *env, VideoInfo *info, jintArray da void *pixels; if (AndroidBitmap_lockPixels(env, bitmap, &pixels) >= 0) { if (info->sws_ctx == nullptr) { - if (info->frame->format > AV_PIX_FMT_NONE && info->frame->format < AV_PIX_FMT_NB && !info->frame->format == AV_PIX_FMT_YUVA420P) { + if (info->frame->format > AV_PIX_FMT_NONE && info->frame->format < AV_PIX_FMT_NB && info->frame->format != AV_PIX_FMT_YUVA420P) { info->sws_ctx = sws_getContext(info->frame->width, info->frame->height, (AVPixelFormat) info->frame->format, bitmapWidth, bitmapHeight, AV_PIX_FMT_RGBA, SWS_BILINEAR, NULL, NULL, NULL); - } else if (info->video_dec_ctx->pix_fmt > AV_PIX_FMT_NONE && info->video_dec_ctx->pix_fmt < AV_PIX_FMT_NB && !info->frame->format == AV_PIX_FMT_YUVA420P) { + } else if (info->video_dec_ctx->pix_fmt > AV_PIX_FMT_NONE && info->video_dec_ctx->pix_fmt < AV_PIX_FMT_NB && info->frame->format != AV_PIX_FMT_YUVA420P) { info->sws_ctx = sws_getContext(info->video_dec_ctx->width, info->video_dec_ctx->height, info->video_dec_ctx->pix_fmt, bitmapWidth, bitmapHeight, AV_PIX_FMT_RGBA, SWS_BILINEAR, NULL, NULL, NULL); } } @@ -1203,8 +1203,7 @@ static inline void writeFrameToBitmap(JNIEnv *env, VideoInfo *info, jintArray da uint8_t __attribute__ ((aligned (16))) *dst_data[1]; dst_data[0] = (uint8_t *) pixels; info->dst_linesize[0] = stride; - sws_scale(info->sws_ctx, info->frame->data, info->frame->linesize, 0, - info->frame->height, dst_data, info->dst_linesize); + sws_scale(info->sws_ctx, info->frame->data, info->frame->linesize, 0, info->frame->height, dst_data, info->dst_linesize); } } AndroidBitmap_unlockPixels(env, bitmap); diff --git a/TMessagesProj/src/gservcies/java/org/telegram/messenger/GcmPushListenerService.java b/TMessagesProj/src/gservcies/java/org/telegram/messenger/GcmPushListenerService.java index 99f310efb..96d2a44d0 100644 --- a/TMessagesProj/src/gservcies/java/org/telegram/messenger/GcmPushListenerService.java +++ b/TMessagesProj/src/gservcies/java/org/telegram/messenger/GcmPushListenerService.java @@ -1070,6 +1070,7 @@ public class GcmPushListenerService extends FirebaseMessagingService { messageOwner.from_scheduled = scheduled; MessageObject messageObject = new MessageObject(currentAccount, messageOwner, messageText, name, userName, localMessage, channel, supergroup, edited); + messageObject.isReactionPush = loc_key.startsWith("REACT_") || loc_key.startsWith("CHAT_REACT_"); ArrayList arrayList = new ArrayList<>(); arrayList.add(messageObject); canRelease = false; diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/AndroidUtilities.java b/TMessagesProj/src/main/java/org/telegram/messenger/AndroidUtilities.java index 3ca4d26fb..6e4d8b0a0 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/AndroidUtilities.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/AndroidUtilities.java @@ -802,7 +802,7 @@ public class AndroidUtilities { writer.flush(); writer.close(); } catch (Throwable e) { - FileLog.e(e); + FileLog.e(e, false); } } diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/AnimatedFileDrawableStream.java b/TMessagesProj/src/main/java/org/telegram/messenger/AnimatedFileDrawableStream.java index 7a29311ec..f112cd774 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/AnimatedFileDrawableStream.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/AnimatedFileDrawableStream.java @@ -77,7 +77,7 @@ public class AnimatedFileDrawableStream implements FileLoadOperationStream { } lastOffset = offset + availableLength; } catch (Exception e) { - FileLog.e(e); + FileLog.e(e, false); } return availableLength; } diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/ApplicationLoader.java b/TMessagesProj/src/main/java/org/telegram/messenger/ApplicationLoader.java index 71739fb49..d59ed923d 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/ApplicationLoader.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/ApplicationLoader.java @@ -21,6 +21,8 @@ import android.content.SharedPreferences; import android.content.pm.ApplicationInfo; import android.content.res.Configuration; import android.net.ConnectivityManager; +import android.net.Network; +import android.net.NetworkCapabilities; import android.net.NetworkInfo; import android.os.Build; import android.os.Handler; @@ -29,6 +31,9 @@ import android.os.SystemClock; import android.telephony.TelephonyManager; import android.util.Log; +import androidx.annotation.NonNull; +import androidx.multidex.MultiDex; + import androidx.multidex.MultiDex; import org.telegram.messenger.voip.VideoCapturerDevice; @@ -60,6 +65,8 @@ public class ApplicationLoader extends Application { private static ConnectivityManager connectivityManager; private static volatile boolean applicationInited = false; + private static long lastNetworkCheckTypeTime; + private static int lastKnownNetworkType = -1; public static long startTime; @@ -457,6 +464,20 @@ public class ApplicationLoader extends Application { connectivityManager = (ConnectivityManager) ApplicationLoader.applicationContext.getSystemService(Context.CONNECTIVITY_SERVICE); } currentNetworkInfo = connectivityManager.getActiveNetworkInfo(); + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { + connectivityManager.registerDefaultNetworkCallback(new ConnectivityManager.NetworkCallback() { + @Override + public void onAvailable(@NonNull Network network) { + lastKnownNetworkType = -1; + } + + @Override + public void onCapabilitiesChanged(@NonNull Network network, @NonNull NetworkCapabilities networkCapabilities) { + super.onCapabilitiesChanged(network, networkCapabilities); + lastKnownNetworkType = -1; + } + }); + } } catch (Throwable ignore) { } @@ -526,11 +547,16 @@ public class ApplicationLoader extends Application { return StatsController.TYPE_MOBILE; } if (currentNetworkInfo.getType() == ConnectivityManager.TYPE_WIFI || currentNetworkInfo.getType() == ConnectivityManager.TYPE_ETHERNET) { - if (connectivityManager.isActiveNetworkMetered()) { - return StatsController.TYPE_MOBILE; - } else { - return StatsController.TYPE_WIFI; + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N && (lastKnownNetworkType == StatsController.TYPE_MOBILE || lastKnownNetworkType == StatsController.TYPE_WIFI) && System.currentTimeMillis() - lastNetworkCheckTypeTime < 5000) { + return lastKnownNetworkType; } + if (connectivityManager.isActiveNetworkMetered()) { + lastKnownNetworkType = StatsController.TYPE_MOBILE; + } else { + lastKnownNetworkType = StatsController.TYPE_WIFI; + } + lastNetworkCheckTypeTime = System.currentTimeMillis(); + return lastKnownNetworkType; } if (currentNetworkInfo.isRoaming()) { return StatsController.TYPE_ROAMING; diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/FileLoader.java b/TMessagesProj/src/main/java/org/telegram/messenger/FileLoader.java index 10b8f2db1..e6826ecdd 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/FileLoader.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/FileLoader.java @@ -1124,6 +1124,9 @@ public class FileLoader extends BaseController { } public static String getDocumentFileName(TLRPC.Document document) { + if (document.file_name_fixed != null) { + return document.file_name_fixed; + } String fileName = null; if (document != null) { if (document.file_name != null) { diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/ImageLoader.java b/TMessagesProj/src/main/java/org/telegram/messenger/ImageLoader.java index 80a34802b..411ceb47c 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/ImageLoader.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/ImageLoader.java @@ -51,6 +51,7 @@ import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.InputStream; import java.io.InputStreamReader; +import java.io.InterruptedIOException; import java.io.RandomAccessFile; import java.net.HttpURLConnection; import java.net.SocketException; @@ -537,7 +538,7 @@ public class ImageLoader { } else if (e instanceof FileNotFoundException) { canRetry = false; sentLogs = false; - } else if (e instanceof InterruptedException) { + } else if (e instanceof InterruptedIOException) { sentLogs = false; } FileLog.e(e, sentLogs); diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/ImageReceiver.java b/TMessagesProj/src/main/java/org/telegram/messenger/ImageReceiver.java index 3f854b4fc..e950029b1 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/ImageReceiver.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/ImageReceiver.java @@ -418,6 +418,7 @@ public class ImageReceiver implements NotificationCenter.NotificationCenterDeleg currentExt = ext; currentParentObject = null; currentCacheType = 0; + roundPaint.setShader(null); staticThumbDrawable = thumb; currentAlpha = 1.0f; previousAlpha = 1f; @@ -573,6 +574,7 @@ public class ImageReceiver implements NotificationCenter.NotificationCenterDeleg mediaShader = null; legacyShader = null; legacyCanvas = null; + roundPaint.setShader(null); if (legacyBitmap != null) { legacyBitmap.recycle(); legacyBitmap = null; @@ -725,6 +727,7 @@ public class ImageReceiver implements NotificationCenter.NotificationCenterDeleg fileDrawable.setAllowDecodeSingleFrame(true); } thumbShader = null; + roundPaint.setShader(null); staticThumbDrawable = bitmap; updateDrawableRadius(bitmap); currentMediaLocation = null; @@ -869,6 +872,7 @@ public class ImageReceiver implements NotificationCenter.NotificationCenterDeleg if (staticThumbDrawable != null) { staticThumbDrawable = null; thumbShader = null; + roundPaint.setShader(null); } clearImage(); if (isPressed == 0) { @@ -1009,9 +1013,6 @@ public class ImageReceiver implements NotificationCenter.NotificationCenterDeleg bitmapW = bitmapDrawable.getIntrinsicWidth(); bitmapH = bitmapDrawable.getIntrinsicHeight(); } - if (parentView != null) { - parentView.invalidate(); - } } else { Bitmap bitmap = bitmapDrawable.getBitmap(); if (bitmap != null && bitmap.isRecycled()) { @@ -2412,6 +2413,7 @@ public class ImageReceiver implements NotificationCenter.NotificationCenterDeleg currentThumbKey = null; currentThumbDrawable = null; thumbShader = null; + roundPaint.setShader(null); staticThumbDrawable = new BitmapDrawable(null, thumb); crossfadeWithThumb = true; currentAlpha = 0f; diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/MediaController.java b/TMessagesProj/src/main/java/org/telegram/messenger/MediaController.java index 99544f5a9..ade5f0c09 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/MediaController.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/MediaController.java @@ -3718,6 +3718,7 @@ public class MediaController implements AudioManager.OnAudioFocusChangeListener, } if (sourceFile.exists()) { saveFileInternal(isMusic ? 3 : 2, sourceFile, name); + copiedFiles++; } } } else { @@ -3768,6 +3769,7 @@ public class MediaController implements AudioManager.OnAudioFocusChangeListener, } if (sourceFile.exists()) { copyFile(sourceFile, destFile, message.getMimeType()); + copiedFiles++; } } } @@ -3864,7 +3866,6 @@ public class MediaController implements AudioManager.OnAudioFocusChangeListener, finishedProgress += 100.0f / messageObjects.size(); final int progress = (int) (finishedProgress); AndroidUtilities.runOnUIThread(() -> SaveToDownloadReceiver.updateNotification(notificationId, progress)); - copiedFiles++; return true; } } catch (Exception e) { diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/MessageObject.java b/TMessagesProj/src/main/java/org/telegram/messenger/MessageObject.java index b48a0ace8..a35dc058e 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/MessageObject.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/MessageObject.java @@ -102,6 +102,7 @@ public class MessageObject { public long reactionsLastCheckTime; public String customName; public boolean reactionsChanged; + public boolean isReactionPush; private int isRoundVideoCached; public long eventId; public int contentType; @@ -5104,7 +5105,7 @@ public class MessageObject { } public static boolean canAutoplayAnimatedSticker(TLRPC.Document document) { - return isAnimatedStickerDocument(document, true) && SharedConfig.getDevicePerformanceClass() != SharedConfig.PERFORMANCE_CLASS_LOW; + return (isAnimatedStickerDocument(document, true) || isVideoStickerDocument(document)) && SharedConfig.getDevicePerformanceClass() != SharedConfig.PERFORMANCE_CLASS_LOW; } public static boolean isMaskDocument(TLRPC.Document document) { @@ -6374,7 +6375,7 @@ public class MessageObject { return !isEditing() && !isSponsored() && isSent() && messageOwner.action == null; } - public boolean selectReaction(String reaction, boolean fromDoubleTap) { + public boolean selectReaction(String reaction, boolean big, boolean fromDoubleTap) { if (messageOwner.reactions == null) { messageOwner.reactions = new TLRPC.TL_messageReactions(); messageOwner.reactions.can_see_list = isFromGroup() || isFromUser(); @@ -6391,6 +6392,10 @@ public class MessageObject { } } + if (choosenReaction != null && choosenReaction == newReaction && big) { + return true; + } + if (choosenReaction != null && (choosenReaction == newReaction || fromDoubleTap)) { choosenReaction.chosen = false; choosenReaction.count--; diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/MessagesController.java b/TMessagesProj/src/main/java/org/telegram/messenger/MessagesController.java index edec1c8ae..19407a0bb 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/MessagesController.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/MessagesController.java @@ -14283,7 +14283,7 @@ public class MessagesController extends BaseController implements NotificationCe return true; } - private void checkUnreadReactions(long dialogId, SparseBooleanArray unreadReactions) { + public void checkUnreadReactions(long dialogId, SparseBooleanArray unreadReactions) { getMessagesStorage().getStorageQueue().postRunnable(() -> { boolean needReload = false; boolean changed = false; @@ -14350,6 +14350,7 @@ public class MessagesController extends BaseController implements NotificationCe AndroidUtilities.runOnUIThread(() -> { TLRPC.Dialog dialog = dialogs_dict.get(dialogId); if (dialog == null) { + getMessagesStorage().updateDialogUnreadReactions(dialogId, count, false); return; } dialog.unread_reactions_count = count; @@ -14363,6 +14364,7 @@ public class MessagesController extends BaseController implements NotificationCe AndroidUtilities.runOnUIThread(() -> { TLRPC.Dialog dialog = dialogs_dict.get(dialogId); if (dialog == null) { + getMessagesStorage().updateDialogUnreadReactions(dialogId, finalNewUnreadCount, true); return; } dialog.unread_reactions_count += finalNewUnreadCount; diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/MessagesStorage.java b/TMessagesProj/src/main/java/org/telegram/messenger/MessagesStorage.java index 9659dbf59..c03975d35 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/MessagesStorage.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/MessagesStorage.java @@ -139,18 +139,38 @@ public class MessagesStorage extends BaseController { state.dispose(); data.reuse(); } catch (Exception e) { - e.printStackTrace(); + FileLog.e(e); } - } - - getMessagesStorage().getDatabase().executeFast("UPDATE reaction_mentions SET state = 0 WHERE uid = %d AND "); } catch (SQLiteException e) { - e.printStackTrace(); + FileLog.e(e); } } + public void updateDialogUnreadReactions(long dialogId, int newUnreadCount, boolean increment) { + storageQueue.postRunnable(() -> { + try { + int oldUnreadRactions = 0; + if (increment) { + SQLiteCursor cursor = database.queryFinalized("SELECT unread_reactions FROM dialogs WHERE did = " + dialogId); + if (cursor.next()) { + oldUnreadRactions = Math.max(0, cursor.intValue(0)); + } + cursor.dispose(); + } + oldUnreadRactions += newUnreadCount; + SQLitePreparedStatement state = getMessagesStorage().getDatabase().executeFast("UPDATE dialogs SET unread_reactions = ? WHERE did = ?"); + state.bindInteger(1, oldUnreadRactions); + state.bindLong(2, dialogId); + state.step(); + state.dispose(); + } catch (SQLiteException e) { + e.printStackTrace(); + } + }); + } + public interface IntCallback { void run(int param); } @@ -199,7 +219,7 @@ public class MessagesStorage extends BaseController { private CountDownLatch openSync = new CountDownLatch(1); private static SparseArray Instance = new SparseArray(); - private final static int LAST_DB_VERSION = 89; + private final static int LAST_DB_VERSION = 90; private boolean databaseMigrationInProgress; public static MessagesStorage getInstance(int num) { @@ -443,7 +463,7 @@ public class MessagesStorage extends BaseController { database.executeFast("INSERT INTO params VALUES(1, 0, 0, 0, 0, 0, 0, NULL)").stepThis().dispose(); database.executeFast("CREATE TABLE media_v4(mid INTEGER, uid INTEGER, date INTEGER, type INTEGER, data BLOB, PRIMARY KEY(mid, uid, type))").stepThis().dispose(); - database.executeFast("CREATE INDEX IF NOT EXISTS uid_mid_type_date_idx_media_v3 ON media_v4(uid, mid, type, date);").stepThis().dispose(); + database.executeFast("CREATE INDEX IF NOT EXISTS uid_mid_type_date_idx_media_v4 ON media_v4(uid, mid, type, date);").stepThis().dispose(); database.executeFast("CREATE TABLE bot_keyboard(uid INTEGER PRIMARY KEY, mid INTEGER, info BLOB)").stepThis().dispose(); database.executeFast("CREATE INDEX IF NOT EXISTS bot_keyboard_idx_mid_v2 ON bot_keyboard(mid, uid);").stepThis().dispose(); @@ -505,7 +525,9 @@ public class MessagesStorage extends BaseController { database.executeFast("CREATE INDEX IF NOT EXISTS polls_id_v2 ON polls_v2(id);").stepThis().dispose(); database.executeFast("CREATE TABLE reactions(data BLOB, hash INTEGER, date INTEGER);").stepThis().dispose(); - database.executeFast("CREATE TABLE reaction_mentions(message_id INTEGER PRIMARY KEY, state INTEGER, dialog_id INTEGER);").stepThis().dispose(); + database.executeFast("CREATE TABLE reaction_mentions(message_id INTEGER, state INTEGER, dialog_id INTEGER, PRIMARY KEY(message_id, dialog_id))").stepThis().dispose(); + database.executeFast("CREATE INDEX IF NOT EXISTS reaction_mentions_did ON reaction_mentions(dialog_id);").stepThis().dispose(); + //version database.executeFast("PRAGMA user_version = " + LAST_DB_VERSION).stepThis().dispose(); } else { @@ -1651,11 +1673,18 @@ public class MessagesStorage extends BaseController { version = 88; } - if (version == 88) { + if (version == 88 || version == 89) { + long time = System.currentTimeMillis(); database.executeFast("DROP TABLE IF EXISTS reaction_mentions;").stepThis().dispose(); - database.executeFast("CREATE TABLE reaction_mentions(message_id INTEGER PRIMARY KEY, state INTEGER, dialog_id INTEGER);").stepThis().dispose(); - database.executeFast("PRAGMA user_version = 89").stepThis().dispose(); - version = 89; + database.executeFast("CREATE TABLE IF NOT EXISTS reaction_mentions(message_id INTEGER, state INTEGER, dialog_id INTEGER, PRIMARY KEY(dialog_id, message_id));").stepThis().dispose(); + database.executeFast("CREATE INDEX IF NOT EXISTS reaction_mentions_did ON reaction_mentions(dialog_id);").stepThis().dispose(); + + database.executeFast("DROP INDEX IF EXISTS uid_mid_type_date_idx_media_v3").stepThis().dispose(); + database.executeFast("CREATE INDEX IF NOT EXISTS uid_mid_type_date_idx_media_v4 ON media_v4(uid, mid, type, date);").stepThis().dispose(); + + database.executeFast("PRAGMA user_version = 90").stepThis().dispose(); + + version = 90; } FileLog.d("MessagesStorage db migration finished"); @@ -10306,6 +10335,7 @@ public class MessagesStorage extends BaseController { state.dispose(); } } + long time = System.currentTimeMillis(); database.executeFast(String.format(Locale.US, "DELETE FROM media_v4 WHERE mid IN(%s) AND uid = %d", ids, did)).stepThis().dispose(); } database.executeFast(String.format(Locale.US, "DELETE FROM messages_seq WHERE mid IN(%s)", ids)).stepThis().dispose(); diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/NotificationsController.java b/TMessagesProj/src/main/java/org/telegram/messenger/NotificationsController.java index f8ec306c1..7836a49cb 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/NotificationsController.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/NotificationsController.java @@ -56,6 +56,9 @@ import androidx.core.content.LocusIdCompat; import androidx.core.content.pm.ShortcutInfoCompat; import androidx.core.content.pm.ShortcutManagerCompat; import androidx.core.graphics.drawable.IconCompat; +import android.text.TextUtils; +import android.util.SparseArray; +import android.util.SparseBooleanArray; import org.telegram.messenger.support.LongSparseIntArray; import org.telegram.tgnet.ConnectionsManager; @@ -733,6 +736,9 @@ public class NotificationsController extends BaseController { break; } MessageObject oldMessage = sparseArray.get(messageObject.getId()); + if (oldMessage != null && oldMessage.isReactionPush) { + oldMessage = null; + } if (oldMessage != null) { updated = true; sparseArray.put(messageObject.getId(), messageObject); @@ -893,6 +899,11 @@ public class NotificationsController extends BaseController { pushDialogsOverrideMention.put(originalDialogId, current == null ? 1 : current + 1); } } + if (messageObject.isReactionPush) { + SparseBooleanArray sparseBooleanArray = new SparseBooleanArray(); + sparseBooleanArray.put(mid, true); + getMessagesController().checkUnreadReactions(dialogId, sparseBooleanArray); + } } if (added) { @@ -935,9 +946,6 @@ public class NotificationsController extends BaseController { boolean canAddValue; if (notifyOverride == -1) { canAddValue = isGlobalNotificationsEnabled(dialog_id, isChannel); - /*if (BuildVars.DEBUG_PRIVATE_VERSION && BuildVars.LOGS_ENABLED) { - FileLog.d("global notify settings for " + dialog_id + " = " + canAddValue); - }*/ } else { canAddValue = notifyOverride != 2; } @@ -3980,6 +3988,7 @@ public class NotificationsController extends BaseController { arrayList.add(messageObject); } + LongSparseArray oldIdsWear = new LongSparseArray<>(); for (int i = 0; i < wearNotificationsIds.size(); i++) { oldIdsWear.put(wearNotificationsIds.keyAt(i), wearNotificationsIds.valueAt(i)); @@ -4044,7 +4053,13 @@ public class NotificationsController extends BaseController { } MessageObject lastMessageObject = messageObjects.get(0); - int maxDate = lastMessageObject.messageOwner.date; + int maxDate = 0; + for (int i = 0; i < messageObjects.size(); i++) { + if (maxDate < messageObjects.get(i).messageOwner.date) { + maxDate = messageObjects.get(i).messageOwner.date; + + } + } TLRPC.Chat chat = null; TLRPC.User user = null; boolean isChannel = false; diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/SharedConfig.java b/TMessagesProj/src/main/java/org/telegram/messenger/SharedConfig.java index 2d52d15d4..c326a8e6d 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/SharedConfig.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/SharedConfig.java @@ -128,7 +128,7 @@ public class SharedConfig { public static boolean chatBubbles = Build.VERSION.SDK_INT >= 30; public static boolean autoplayGifs = true; public static boolean autoplayVideo = true; - public static boolean raiseToSpeak = true; + public static boolean raiseToSpeak = false; public static boolean customTabs = true; public static boolean directShare = true; public static boolean inappCamera = true; @@ -1195,7 +1195,7 @@ public class SharedConfig { autoplayGifs = preferences.getBoolean("autoplay_gif", true); autoplayVideo = preferences.getBoolean("autoplay_video", true); mapPreviewType = preferences.getInt("mapPreviewType", 2); - raiseToSpeak = preferences.getBoolean("raise_to_speak", true); + raiseToSpeak = preferences.getBoolean("raise_to_speak", false); customTabs = preferences.getBoolean("custom_tabs", true); directShare = preferences.getBoolean("direct_share", true); shuffleMusic = preferences.getBoolean("shuffleMusic", false); diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/browser/Browser.java b/TMessagesProj/src/main/java/org/telegram/messenger/browser/Browser.java index 2d739ecd4..b6bde5a59 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/browser/Browser.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/browser/Browser.java @@ -173,10 +173,21 @@ public class Browser { } public static boolean isTelegraphUrl(String url, boolean equals) { + return isTelegraphUrl(url, equals, false); + } + public static boolean isTelegraphUrl(String url, boolean equals, boolean forceHttps) { if (equals) { return url.equals("telegra.ph") || url.equals("te.legra.ph") || url.equals("graph.org"); } - return url.matches("^(https?://)?(te\\.?legra\\.ph|graph\\.org).*"); // telegra.ph, te.legra.ph, graph.org + return url.matches("^(https" + (forceHttps ? "" : "?") + "://)?(te\\.?legra\\.ph|graph\\.org).*"); // telegra.ph, te.legra.ph, graph.org + } + + public static boolean urlMustNotHaveConfirmation(String url) { + return ( + isTelegraphUrl(url, false, true) || + url.matches("^(https://)?t\\.me/iv\\??.*") || // t.me/iv? + url.matches("^(https://)?telegram\\.org/(blog|tour)/?.*") // telegram.org/blog, telegram.org/tour + ); } public static void openUrl(final Context context, Uri uri, final boolean allowCustom, boolean tryTelegraph) { diff --git a/TMessagesProj/src/main/java/org/telegram/tgnet/TLRPC.java b/TMessagesProj/src/main/java/org/telegram/tgnet/TLRPC.java index 776d3060e..68011ebe5 100644 --- a/TMessagesProj/src/main/java/org/telegram/tgnet/TLRPC.java +++ b/TMessagesProj/src/main/java/org/telegram/tgnet/TLRPC.java @@ -14,6 +14,7 @@ import android.text.TextUtils; import org.osmdroid.util.TileSystemWebMercator; +import org.telegram.messenger.FileLoader; import org.telegram.messenger.FileLog; import org.telegram.messenger.ImageLoader; import org.telegram.messenger.Utilities; @@ -24222,6 +24223,7 @@ public class TLRPC { public byte[] key; public byte[] iv; public ArrayList attributes = new ArrayList<>(); + public String file_name_fixed; //custom public static Document TLdeserialize(AbstractSerializedData stream, int constructor, boolean exception) { Document result = null; @@ -24259,6 +24261,7 @@ public class TLRPC { } if (result != null) { result.readParams(stream, exception); + result.file_name_fixed = FileLoader.getDocumentFileName(result); } return result; } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/ActionBarMenuSubItem.java b/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/ActionBarMenuSubItem.java index d1fa554a9..ba346334f 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/ActionBarMenuSubItem.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/ActionBarMenuSubItem.java @@ -14,8 +14,6 @@ import android.widget.TextView; import org.telegram.messenger.AndroidUtilities; import org.telegram.messenger.LocaleController; -import org.telegram.messenger.R; -import org.telegram.ui.Components.CheckBox; import org.telegram.ui.Components.CheckBox2; import org.telegram.ui.Components.LayoutHelper; @@ -128,6 +126,7 @@ public class ActionBarMenuSubItem extends FrameLayout { textView.setLines(2); textView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14); textView.setSingleLine(false); + textView.setGravity(Gravity.CENTER_VERTICAL); } public void setTextAndIcon(CharSequence text, int icon, Drawable iconDrawable) { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/AlertDialog.java b/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/AlertDialog.java index e9320cb5e..a621cc2a5 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/AlertDialog.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/AlertDialog.java @@ -872,6 +872,9 @@ public class AlertDialog extends Dialog implements Drawable.Callback { if (dimEnabled) { params.dimAmount = 0.6f; params.flags |= WindowManager.LayoutParams.FLAG_DIM_BEHIND; + } else { + params.dimAmount = 0f; + params.flags ^= WindowManager.LayoutParams.FLAG_DIM_BEHIND; } lastScreenWidth = AndroidUtilities.displaySize.x; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/FloatingToolbar.java b/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/FloatingToolbar.java index 10bc7efbb..c04edc056 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/FloatingToolbar.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/FloatingToolbar.java @@ -842,12 +842,7 @@ public final class FloatingToolbar { if (menuItemButton instanceof LinearLayout) { ((LinearLayout) menuItemButton).setGravity(Gravity.CENTER); } - if (isFirstItem) { - menuItemButton.setPaddingRelative((int) (1.5 * menuItemButton.getPaddingStart()), menuItemButton.getPaddingTop(), menuItemButton.getPaddingEnd(), menuItemButton.getPaddingBottom()); - } - if (isLastItem) { - menuItemButton.setPaddingRelative(menuItemButton.getPaddingStart(), menuItemButton.getPaddingTop(), (int) (1.5 * menuItemButton.getPaddingEnd()), menuItemButton.getPaddingBottom()); - } + menuItemButton.setPaddingRelative((int) ((isFirstItem ? 1.5 : 1) * menuItemButton.getPaddingStart()), menuItemButton.getPaddingTop(), (int) ((isLastItem ? 1.5 : 1) * menuItemButton.getPaddingEnd()), menuItemButton.getPaddingBottom()); menuItemButton.measure(MeasureSpec.UNSPECIFIED, MeasureSpec.UNSPECIFIED); final int menuItemButtonWidth = Math.min(menuItemButton.getMeasuredWidth(), toolbarWidth); final boolean canFitWithOverflow = menuItemButtonWidth <= availableWidth - mOverflowButtonSize.getWidth(); @@ -873,6 +868,10 @@ public final class FloatingToolbar { return remainingMenuItems; } + private void updateMainPanelItemsSelectors() { + + } + @SuppressWarnings("unchecked") private void layoutOverflowPanelItems(List menuItems) { ArrayAdapter overflowPanelAdapter = (ArrayAdapter) mOverflowPanel.getAdapter(); @@ -1216,8 +1215,8 @@ public final class FloatingToolbar { } else if (currentStyle == STYLE_THEME) { textView.setTextColor(getThemedColor(Theme.key_windowBackgroundWhiteBlackText)); } - if (first) { - menuItemButton.setBackgroundDrawable(Theme.createRadSelectorDrawable(selectorColor, first ? 6 : 0, 0, 0, first ? 6 : 0)); + if (first || last) { + menuItemButton.setBackgroundDrawable(Theme.createRadSelectorDrawable(selectorColor, first ? 6 : 0, last ? 6 : 0, last ? 6 : 0, first ? 6 : 0)); } else { menuItemButton.setBackgroundDrawable(Theme.getSelectorDrawable(selectorColor, false)); } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/Theme.java b/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/Theme.java index aaf919d89..d8b821162 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/Theme.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/Theme.java @@ -101,6 +101,7 @@ import org.telegram.ui.Components.ChatThemeBottomSheet; import org.telegram.ui.Components.ChoosingStickerStatusDrawable; import org.telegram.ui.Components.CombinedDrawable; import org.telegram.ui.Components.FragmentContextViewWavesDrawable; +import org.telegram.ui.Components.LinkPath; import org.telegram.ui.Components.MotionBackgroundDrawable; import org.telegram.ui.Components.MsgClockDrawable; import org.telegram.ui.Components.PathAnimator; @@ -1526,9 +1527,129 @@ public class Theme { if (backgroundRotation != 45) { currentColors.put(key_chat_wallpaper_gradient_rotation, backgroundRotation); } + + if (!isDarkTheme) { + int outBubble; + if (isDarkTheme) { + outBubble = averageColor(currentColors, key_chat_outBubbleGradient1, key_chat_outBubbleGradient2, key_chat_outBubbleGradient3); + } else if (currentColors.containsKey(key_chat_outBubble)) { + outBubble = currentColors.get(key_chat_outBubble); + } else { + outBubble = getColor(key_chat_outBubble); + } + int inBubbleSelected; + if (currentColors.containsKey(key_chat_inBubbleSelected)) { + inBubbleSelected = currentColors.get(key_chat_inBubbleSelected); + } else { + inBubbleSelected = getColor(key_chat_inBubbleSelected); + } + int gradientAverageColor = 0; + if (isDarkTheme) { + gradientAverageColor = outBubble; + } + if (gradientAverageColor == 0) { + gradientAverageColor = averageColor(currentColors, key_chat_wallpaper_gradient_to1, key_chat_wallpaper_gradient_to2, key_chat_wallpaper_gradient_to3); + } + if (gradientAverageColor == 0) { + gradientAverageColor = averageColor(currentColors, key_chat_wallpaper); + } + int selectedBackground = currentColors.containsKey(key_chat_selectedBackground) ? currentColors.get(key_chat_selectedBackground) : getColor(key_chat_selectedBackground); + selectedBackground = applyHue(selectedBackground, gradientAverageColor); + selectedBackground = darkenColor(selectedBackground, .1f); + selectedBackground = Color.argb((int) (Color.alpha(selectedBackground) * 0.8f), Color.red(selectedBackground), Color.green(selectedBackground), Color.blue(selectedBackground)); + currentColors.put(key_chat_selectedBackground, selectedBackground); + int outBubbleOverlay = bubbleSelectedOverlay(outBubble); + currentColors.put(key_chat_outBubbleGradientSelectedOverlay, outBubbleOverlay); + + inBubbleSelected = applyHue(inBubbleSelected, gradientAverageColor); + inBubbleSelected = shiftHSV(inBubbleSelected, 0, .04f, 0); + currentColors.put(key_chat_inBubbleSelected, inBubbleSelected); + + final String[] inTextSelectedKeys = new String[] { + key_chat_inTimeSelectedText, key_chat_inAdminSelectedText, key_chat_inAudioDurationSelectedText, + key_chat_inAudioPerformerSelectedText, key_chat_inFileInfoSelectedText, key_chat_inContactPhoneSelectedText, + key_chat_inPreviewInstantSelectedText, key_chat_inVenueInfoSelectedText, key_chat_inReplyMediaMessageSelectedText + }; + for (String inTextSelectedKey : inTextSelectedKeys) { + int color = currentColors.containsKey(inTextSelectedKey) ? currentColors.get(inTextSelectedKey) : getColor(inTextSelectedKey); + currentColors.put(inTextSelectedKey, applyHue(color, gradientAverageColor)); + } + + int outTimeSelected = currentColors.containsKey(key_chat_outTimeSelectedText) ? currentColors.get(key_chat_outTimeSelectedText) : getColor(key_chat_outTimeSelectedText); + double contrast = ColorUtils.calculateContrast(outTimeSelected, mix(outBubble, outBubbleOverlay)); + currentColors.put(key_chat_outTimeSelectedText, shiftHSV(outTimeSelected, .02f, .01f, contrast < 1.9d ? -.1f : 0f)); +// currentColors.put(key_chat_outTimeSelectedText, applyHue(outTimeSelected, gradientAverageColor)); + } + return !isMyMessagesGradientColorsNear; } + private float[] tempHSV = new float[3]; + private int bubbleSelectedOverlay(int bubble) { + Color.colorToHSV(bubble, tempHSV); + if (tempHSV[1] > 0) { + tempHSV[1] = Math.max(0, Math.min(1, tempHSV[1] + .6f)); + tempHSV[2] = Math.max(0, Math.min(1, tempHSV[2] - .05f)); + } else { + tempHSV[2] = Math.max(0, Math.min(1, tempHSV[2] - .6f)); + } + return Color.HSVToColor(30, tempHSV); + } + private int applyHue(int base, int colorWithHue) { + Color.colorToHSV(colorWithHue, tempHSV); + float h = tempHSV[0]; + Color.colorToHSV(base, tempHSV); + tempHSV[0] = h; + return Color.HSVToColor(Color.alpha(base), tempHSV); + } + private int shiftHSV(int color, float hue, float sat, float val) { + Color.colorToHSV(color, tempHSV); + tempHSV[0] += hue; + tempHSV[1] += sat; + tempHSV[2] += val; + return Color.HSVToColor(Color.alpha(color), tempHSV); + } + private int darkenColor(int color, float subtractValue) { + Color.colorToHSV(color, tempHSV); + tempHSV[2] = Math.max(0, Math.min(1, tempHSV[2] - subtractValue)); + return Color.HSVToColor(Color.alpha(color), tempHSV); + } + private int mix(int y, int x) { + float ax = Color.alpha(x) / 255f, + ay = Color.alpha(y) / 255f, + az = (ax + ay * (1 - ax)); + if (az == 0f) + return 0; + return Color.argb( + (int) (az * 255), + (int) ((Color.red(x) * ax + Color.red(y) * ay * (1 - ax)) / az), + (int) ((Color.green(x) * ax + Color.green(y) * ay * (1 - ax)) / az), + (int) ((Color.blue(x) * ax + Color.blue(y) * ay * (1 - ax)) / az) + ); + } + private int averageColor(HashMap colors, int alpha, String ...keys) { + int r = 0, g = 0, b = 0, c = 0; + for (int i = 0; i < keys.length; ++i) { + if (!colors.containsKey(keys[i])) { + continue; + } + try { + int color = colors.get(keys[i]); + r += Color.red(color); + g += Color.green(color); + b += Color.blue(color); + c++; + } catch (Exception ignore) {} + } + if (c == 0) { + return 0; + } + return Color.argb(alpha, r / c, g / c, b / c); + } + private int averageColor(HashMap colors, String ...keys) { + return averageColor(colors, 255, keys); + } + public File getPathToWallpaper() { if (id < 100) { return !TextUtils.isEmpty(patternSlug) ? new File(ApplicationLoader.getFilesDirFixed(), String.format(Locale.US, "%s_%d_%s_v5.jpg", parentTheme.getKey(), id, patternSlug)) : null; @@ -2385,6 +2506,9 @@ public class Theme { return null; } ThemeAccent accent = themeAccentsMap.get(currentAccentId); + if (accent == null) { + return null; + } if (createNew) { int id = ++lastAccentId; ThemeAccent themeAccent = new ThemeAccent(); @@ -2675,6 +2799,7 @@ public class Theme { public static Paint dialogs_errorPaint; public static Paint dialogs_countGrayPaint; public static Paint dialogs_actionMessagePaint; + public static Paint dialogs_reactionsCountPaint; public static TextPaint[] dialogs_namePaint; public static TextPaint[] dialogs_nameEncryptedPaint; public static TextPaint dialogs_searchNamePaint; @@ -2949,6 +3074,7 @@ public class Theme { public static final String key_dialogEmptyImage = "dialogEmptyImage"; public static final String key_dialogEmptyText = "dialogEmptyText"; public static final String key_dialogSwipeRemove = "dialogSwipeRemove"; + public static final String key_dialogReactionMentionBackground = "dialogReactionMentionBackground"; public static final String key_windowBackgroundWhite = "windowBackgroundWhite"; public static final String key_windowBackgroundUnchecked = "windowBackgroundUnchecked"; @@ -3831,6 +3957,8 @@ public class Theme { defaultColors.put(key_dialogEmptyImage, 0xff9fa4a8); defaultColors.put(key_dialogEmptyText, 0xff8c9094); defaultColors.put(key_dialogSwipeRemove, 0xffe56555); + defaultColors.put(key_dialogSwipeRemove, 0xffe56555); + defaultColors.put(key_dialogReactionMentionBackground, 0xffF05459); defaultColors.put(key_windowBackgroundWhite, 0xffffffff); defaultColors.put(key_windowBackgroundUnchecked, 0xff9da7b1); @@ -4702,6 +4830,7 @@ public class Theme { fallbackKeys.put(key_chat_outReactionButtonText, key_chat_outPreviewInstantText); fallbackKeys.put(key_chat_inReactionButtonTextSelected, key_windowBackgroundWhite); fallbackKeys.put(key_chat_outReactionButtonTextSelected, key_windowBackgroundWhite); + fallbackKeys.put(key_dialogReactionMentionBackground, key_voipgroup_mutedByAdminGradient2); themeAccentExclusionKeys.addAll(Arrays.asList(keys_avatar_background)); themeAccentExclusionKeys.addAll(Arrays.asList(keys_avatar_nameInMessage)); @@ -8019,6 +8148,7 @@ public class Theme { checkboxSquare_backgroundPaint = new Paint(Paint.ANTI_ALIAS_FLAG); linkSelectionPaint = new Paint(); + linkSelectionPaint.setPathEffect(LinkPath.roundedEffect); Resources resources = context.getResources(); @@ -8133,9 +8263,8 @@ public class Theme { if (dialogs_countTextPaint == null) { dialogs_countTextPaint = new TextPaint(TextPaint.ANTI_ALIAS_FLAG); dialogs_countTextPaint.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf")); - dialogs_countPaint = new Paint(Paint.ANTI_ALIAS_FLAG); - + dialogs_reactionsCountPaint = new Paint(Paint.ANTI_ALIAS_FLAG); dialogs_onlineCirclePaint = new Paint(Paint.ANTI_ALIAS_FLAG); } @@ -8253,6 +8382,7 @@ public class Theme { dialogs_archiveTextPaint.setColor(getColor(key_chats_archiveText)); dialogs_archiveTextPaintSmall.setColor(getColor(key_chats_archiveText)); dialogs_countPaint.setColor(getColor(key_chats_unreadCounter)); + dialogs_reactionsCountPaint.setColor(getColor(key_dialogReactionMentionBackground)); dialogs_countGrayPaint.setColor(getColor(key_chats_unreadCounterMuted)); dialogs_actionMessagePaint.setColor(getColor(key_chats_actionMessage)); dialogs_errorPaint.setColor(getColor(key_chats_sentError)); @@ -8340,7 +8470,9 @@ public class Theme { chat_locationTitlePaint.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf")); chat_locationAddressPaint = new TextPaint(Paint.ANTI_ALIAS_FLAG); chat_urlPaint = new Paint(); + chat_urlPaint.setPathEffect(LinkPath.roundedEffect); chat_textSearchSelectionPaint = new Paint(); + chat_textSearchSelectionPaint.setPathEffect(LinkPath.roundedEffect); chat_radialProgressPaint = new Paint(Paint.ANTI_ALIAS_FLAG); chat_radialProgressPaint.setStrokeCap(Paint.Cap.ROUND); chat_radialProgressPaint.setStyle(Paint.Style.STROKE); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Adapters/SearchAdapterHelper.java b/TMessagesProj/src/main/java/org/telegram/ui/Adapters/SearchAdapterHelper.java index d8d71eaf4..e0376f6c3 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Adapters/SearchAdapterHelper.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Adapters/SearchAdapterHelper.java @@ -177,7 +177,7 @@ public class SearchAdapterHelper { if (query.length() > 0) { TLRPC.TL_contacts_search req = new TLRPC.TL_contacts_search(); req.q = query; - req.limit = 10; + req.limit = 20; requests.add(new Pair<>(req, (response, error) -> { if (delegate.canApplySearchResults(searchId)) { if (error == null) { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ArticleViewer.java b/TMessagesProj/src/main/java/org/telegram/ui/ArticleViewer.java index 8a133e14c..7905919c0 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ArticleViewer.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ArticleViewer.java @@ -413,7 +413,6 @@ public class ArticleViewer implements NotificationCenter.NotificationCenterDeleg searchPath.setCurrentLayout(textLayout, result.index, 0); searchPath.setBaselineShift(0); textLayout.getSelectionPath(result.index, result.index + searchText.length(), searchPath); - searchPath.onPathEnd(); searchPath.setAllowReset(true); } } else { @@ -1162,13 +1161,16 @@ public class ArticleViewer implements NotificationCenter.NotificationCenterDeleg float lightness = (0.2126f * Color.red(color2) + 0.7152f * Color.green(color2) + 0.0722f * Color.blue(color2)) / 255.0f; webpageSearchPaint.setColor(lightness <= 0.705f ? 0xffd1982e : 0xffffe669); webpageUrlPaint.setColor(Theme.getColor(Theme.key_windowBackgroundWhiteLinkSelection) & 0x33ffffff); + webpageUrlPaint.setPathEffect(LinkPath.roundedEffect); urlPaint.setColor(Theme.getColor(Theme.key_windowBackgroundWhiteLinkSelection) & 0x33ffffff); + urlPaint.setPathEffect(LinkPath.roundedEffect); tableHalfLinePaint.setColor(Theme.getColor(Theme.key_windowBackgroundWhiteInputField)); tableLinePaint.setColor(Theme.getColor(Theme.key_windowBackgroundWhiteInputField)); photoBackgroundPaint.setColor(0x0f000000); dividerPaint.setColor(Theme.getColor(Theme.key_divider)); webpageMarkPaint.setColor(Theme.getColor(Theme.key_windowBackgroundWhiteLinkSelection) & 0x33ffffff); + webpageMarkPaint.setPathEffect(LinkPath.roundedEffect); int color = Theme.getColor(Theme.key_switchTrack); int r = Color.red(color); @@ -2577,7 +2579,6 @@ public class ArticleViewer implements NotificationCenter.NotificationCenterDeleg int shift = innerSpans[a].getTextPaint() != null ? innerSpans[a].getTextPaint().baselineShift : 0; textPath.setBaselineShift(shift != 0 ? shift + AndroidUtilities.dp(shift > 0 ? 5 : -2) : 0); result.getSelectionPath(start, end, textPath); - textPath.onPathEnd(); } textPath.setAllowReset(true); } @@ -2596,7 +2597,6 @@ public class ArticleViewer implements NotificationCenter.NotificationCenterDeleg int shift = innerSpans[a].getTextPaint() != null ? innerSpans[a].getTextPaint().baselineShift : 0; markPath.setBaselineShift(shift != 0 ? shift + AndroidUtilities.dp(shift > 0 ? 5 : -2) : 0); result.getSelectionPath(start, end, markPath); - markPath.onPathEnd(); } markPath.setAllowReset(true); } @@ -2685,7 +2685,6 @@ public class ArticleViewer implements NotificationCenter.NotificationCenterDeleg int shift = pressedLink.getTextPaint() != null ? pressedLink.getTextPaint().baselineShift : 0; urlPath.setBaselineShift(shift != 0 ? shift + AndroidUtilities.dp(shift > 0 ? 5 : -2) : 0); layout.getSelectionPath(pressedStart, pressedEnd, urlPath); - urlPath.onPathEnd(); parentView.invalidate(); } catch (Exception e) { FileLog.e(e); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/CameraScanActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/CameraScanActivity.java index 2c59da7b6..340ce4e65 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/CameraScanActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/CameraScanActivity.java @@ -442,7 +442,6 @@ public class CameraScanActivity extends BaseFragment implements Camera.PreviewCa int shift = getText() != null ? getPaint().baselineShift : 0; textPath.setBaselineShift(shift != 0 ? shift + AndroidUtilities.dp(shift > 0 ? 5 : -2) : 0); getLayout().getSelectionPath(start, end, textPath); - textPath.onPathEnd(); } textPath.setAllowReset(true); } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/AboutLinkCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/AboutLinkCell.java index 99df643a4..547d3d32d 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/AboutLinkCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/AboutLinkCell.java @@ -354,12 +354,16 @@ public class AboutLinkCell extends FrameLayout { } checkTextLayout(lastMaxWidth, true); updateHeight(); + int wasValueVisibility = valueTextView.getVisibility(); if (TextUtils.isEmpty(value)) { valueTextView.setVisibility(GONE); } else { valueTextView.setText(value); valueTextView.setVisibility(VISIBLE); } + if (wasValueVisibility != valueTextView.getVisibility()) { + checkTextLayout(lastMaxWidth, true); + } requestLayout(); } @@ -420,7 +424,6 @@ public class AboutLinkCell extends FrameLayout { urlPathOffset.set(textX, textY); urlPath.setCurrentLayout(textLayout, start, 0); textLayout.getSelectionPath(start, buffer.getSpanEnd(pressedLink), urlPath); - urlPath.onPathEnd(); } catch (Exception e) { FileLog.e(e); } @@ -560,9 +563,12 @@ public class AboutLinkCell extends FrameLayout { } } + private int fromHeight() { + return Math.min(COLLAPSED_HEIGHT + (valueTextView.getVisibility() == View.VISIBLE ? AndroidUtilities.dp(20) : 0), textHeight()); + } private int updateHeight() { int textHeight = textHeight(); - float fromHeight = Math.min(COLLAPSED_HEIGHT, textHeight); + float fromHeight = fromHeight(); int height = shouldExpand ? (int) AndroidUtilities.lerp(fromHeight, textHeight, expandT) : textHeight; setHeight(height); return height; @@ -619,7 +625,7 @@ public class AboutLinkCell extends FrameLayout { private void checkTextLayout(int maxWidth, boolean force) { if (stringBuilder != null && (maxWidth != lastMaxWidth || force)) { textLayout = makeTextLayout(stringBuilder, maxWidth); - shouldExpand = textLayout.getLineCount() >= 4 && valueTextView.getVisibility() != View.VISIBLE; + shouldExpand = textLayout.getLineCount() >= 4; // && valueTextView.getVisibility() != View.VISIBLE; if (textLayout.getLineCount() >= 3 && shouldExpand) { int end = Math.max(textLayout.getLineStart(2), textLayout.getLineEnd(2)); @@ -659,8 +665,15 @@ public class AboutLinkCell extends FrameLayout { container.setMinimumHeight(textHeight()); - if (shouldExpand) { - setShowMoreMarginBottom(textHeight() - AndroidUtilities.dp(8) - textLayout.getLineBottom(textLayout.getLineCount() - 1) - showMoreTextBackgroundView.getPaddingBottom()); + if (shouldExpand && firstThreeLinesLayout != null) { + setShowMoreMarginBottom( + fromHeight() + -AndroidUtilities.dp(8) + -firstThreeLinesLayout.getLineBottom(firstThreeLinesLayout.getLineCount() - 1) + -showMoreTextBackgroundView.getPaddingBottom() + -showMoreTextView.getPaddingBottom() + -(showMoreTextView.getLayout() == null ? 0 : showMoreTextView.getLayout().getHeight() - showMoreTextView.getLayout().getLineBottom(showMoreTextView.getLineCount() - 1)) + ); } } showMoreTextView.setVisibility(shouldExpand ? View.VISIBLE : View.GONE); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/BotHelpCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/BotHelpCell.java index 6ab55cd4a..8128e5b5c 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/BotHelpCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/BotHelpCell.java @@ -151,7 +151,6 @@ public class BotHelpCell extends View { int start = buffer.getSpanStart(pressedLink); urlPath.setCurrentLayout(textLayout, start, 0); textLayout.getSelectionPath(start, buffer.getSpanEnd(pressedLink), urlPath); - urlPath.onPathEnd(); } catch (Exception e) { FileLog.e(e); } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/ChatActionCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/ChatActionCell.java index 0d6a16e08..7c8fa4458 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/ChatActionCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/ChatActionCell.java @@ -179,10 +179,10 @@ public class ChatActionCell extends BaseCell implements DownloadController.FileD } else { newText = LocaleController.formatDateChat(date); } + customDate = date; if (customText != null && TextUtils.equals(newText, customText)) { return; } - customDate = date; customText = newText; updateTextInternal(inLayout); } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/ChatMessageCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/ChatMessageCell.java index be9277e3f..bb7a3a4bb 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/ChatMessageCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/ChatMessageCell.java @@ -400,6 +400,10 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate } default void invalidateBlur() { } + + default boolean canDrawOutboundsContent() { + return true; + } } private final static int DOCUMENT_ATTACH_TYPE_NONE = 0; @@ -1201,7 +1205,6 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate pos[1] -= block.charactersOffset; path.setCurrentLayout(block.textLayout, pos[0], 0); block.textLayout.getSelectionPath(pos[0], pos[1], path); - path.onPathEnd(); if (pos[1] >= block.charactersEnd) { for (int a = blockNum + 1; a < currentMessageObject.textLayoutBlocks.size(); a++) { MessageObject.TextLayoutBlock nextBlock = currentMessageObject.textLayoutBlocks.get(a); @@ -1218,7 +1221,6 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate path.setCurrentLayout(nextBlock.textLayout, 0, nextBlock.textYOffset - block.textYOffset); int p1 = pos[1] + block.charactersOffset - nextBlock.charactersOffset; nextBlock.textLayout.getSelectionPath(0, p1, path); - path.onPathEnd(); if (p1 < nextBlock.charactersEnd - 1) { break; } @@ -1243,7 +1245,6 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate int p1 = pos[1] + block.charactersOffset - nextBlock.charactersOffset; path.setCurrentLayout(nextBlock.textLayout, p0, offsetY); nextBlock.textLayout.getSelectionPath(p0, p1, path); - path.onPathEnd(); if (p0 > nextBlock.charactersOffset) { break; } @@ -1308,7 +1309,6 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate int[] pos = getRealSpanStartAndEnd(buffer, pressedLink); path.setCurrentLayout(captionLayout, pos[0], 0); captionLayout.getSelectionPath(pos[0], pos[1], path); - path.onPathEnd(); } catch (Exception e) { FileLog.e(e); } @@ -1371,7 +1371,6 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate int[] pos = getRealSpanStartAndEnd(buffer, pressedLink); path.setCurrentLayout(descriptionLayout, pos[0], 0); descriptionLayout.getSelectionPath(pos[0], pos[1], path); - path.onPathEnd(); } catch (Exception e) { FileLog.e(e); } @@ -1454,7 +1453,6 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate int[] pos = getRealSpanStartAndEnd(buffer, pressedLink); path.setCurrentLayout(descriptionLayout, pos[0], 0); descriptionLayout.getSelectionPath(pos[0], pos[1], path); - path.onPathEnd(); } catch (Exception e) { FileLog.e(e); } @@ -2890,7 +2888,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate parentHeight = parentH; backgroundHeight = parentH; - if (currentMessageObject != null && (hasGradientService() && currentMessageObject.shouldDrawWithoutBackground() || drawSideButton != 0 || !botButtons.isEmpty()) || currentBackgroundDrawable != null && currentBackgroundDrawable.getGradientShader() != null) { + if (currentMessageObject != null && (hasGradientService() && currentMessageObject.shouldDrawWithoutBackground()) || currentBackgroundDrawable != null && currentBackgroundDrawable.getGradientShader() != null) { invalidate(); } } @@ -2905,7 +2903,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate this.parentViewTopOffset = parentOffset; parentHeight = parent; } - if (currentMessageObject != null && (hasGradientService() && currentMessageObject.shouldDrawWithoutBackground() || drawSideButton != 0 || !botButtons.isEmpty())) { + if (currentMessageObject != null && (hasGradientService() && currentMessageObject.shouldDrawWithoutBackground())) { invalidate(); } @@ -4014,6 +4012,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate int duration; boolean smallImage; String type; + final int smallImageSide = AndroidUtilities.dp(48), smallSideMargin = AndroidUtilities.dp(10); if (hasLinkPreview) { TLRPC.TL_webPage webPage = (TLRPC.TL_webPage) messageObject.messageOwner.media.webpage; site_name = webPage.site_name; @@ -4039,9 +4038,10 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate boolean isSmallImageType = "app".equals(type) || "profile".equals(type) || "article".equals(type) || "telegram_bot".equals(type) || "telegram_user".equals(type) || "telegram_channel".equals(type) || - "telegram_megagroup".equals(type) || "telegram_voicechat".equals(type); + "telegram_megagroup".equals(type) || "telegram_voicechat".equals(type) || + "telegram_livestream".equals(type); smallImage = !slideshow && (!drawInstantView || drawInstantViewType == 1 || drawInstantViewType == 9 || drawInstantViewType == 11 || drawInstantViewType == 13) && document == null && isSmallImageType; - isSmallImage = smallImage && (drawInstantViewType == 13 || description != null) && type != null && currentMessageObject.photoThumbs != null; + isSmallImage = smallImage && type != null && currentMessageObject.photoThumbs != null; } else if (hasInvoicePreview) { TLRPC.TL_messageMediaInvoice invoice = (TLRPC.TL_messageMediaInvoice) messageObject.messageOwner.media; site_name = messageObject.messageOwner.media.title; @@ -4094,17 +4094,37 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate if (site_name != null) { try { int width = (int) Math.ceil(Theme.chat_replyNamePaint.measureText(site_name) + 1); - if (!isSmallImage || description == null) { + int restLines = 0; + if (!isSmallImage) { siteNameLayout = new StaticLayout(site_name, Theme.chat_replyNamePaint, Math.min(width, linkPreviewMaxWidth), Layout.Alignment.ALIGN_NORMAL, 1.0f, 0.0f, false); } else { - siteNameLayout = generateStaticLayout(site_name, Theme.chat_replyNamePaint, linkPreviewMaxWidth, linkPreviewMaxWidth - AndroidUtilities.dp(48 + 4), restLinesCount, 1); + restLines = restLinesCount; + siteNameLayout = generateStaticLayout(site_name, Theme.chat_replyNamePaint, linkPreviewMaxWidth, linkPreviewMaxWidth - smallImageSide - smallSideMargin, restLinesCount, 1); restLinesCount -= siteNameLayout.getLineCount(); } siteNameRtl = Math.max(siteNameLayout.getLineLeft(0), 0) != 0; int height = siteNameLayout.getLineBottom(siteNameLayout.getLineCount() - 1); linkPreviewHeight += height; totalHeight += height; - siteNameWidth = width = siteNameLayout.getWidth(); + int layoutWidth = 0; + for (int a = 0; a < siteNameLayout.getLineCount(); ++a) { + int lineLeft = (int) Math.max(0, siteNameLayout.getLineLeft(a)); + int lineWidth; + if (lineLeft != 0) { + lineWidth = siteNameLayout.getWidth() - lineLeft; + } else { + int max = linkPreviewMaxWidth; + if (a < restLines || lineLeft != 0 && isSmallImage) { + max -= smallImageSide + smallSideMargin; + } + lineWidth = (int) Math.min(max, Math.ceil(siteNameLayout.getLineWidth(a))); + } + if (a < restLines || lineLeft != 0 && isSmallImage) { + lineWidth += smallImageSide + smallSideMargin; + } + layoutWidth = Math.max(layoutWidth, lineWidth); + } + siteNameWidth = width = layoutWidth; maxChildWidth = Math.max(maxChildWidth, width + additinalWidth); maxWebWidth = Math.max(maxWebWidth, width + additinalWidth); } catch (Exception e) { @@ -4122,11 +4142,11 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate } int restLines = 0; CharSequence emojiTitle = Emoji.replaceEmoji(title, Theme.chat_replyNamePaint.getFontMetricsInt(), AndroidUtilities.dp(14), false); - if (!isSmallImage || description == null) { + if (!isSmallImage) { titleLayout = StaticLayoutEx.createStaticLayout(emojiTitle, Theme.chat_replyNamePaint, linkPreviewMaxWidth, Layout.Alignment.ALIGN_NORMAL, 1.0f, AndroidUtilities.dp(1), false, TextUtils.TruncateAt.END, linkPreviewMaxWidth, 4); } else { restLines = restLinesCount; - titleLayout = generateStaticLayout(emojiTitle, Theme.chat_replyNamePaint, linkPreviewMaxWidth, linkPreviewMaxWidth - AndroidUtilities.dp(48 + 4), restLinesCount, 4); + titleLayout = generateStaticLayout(emojiTitle, Theme.chat_replyNamePaint, linkPreviewMaxWidth, linkPreviewMaxWidth - smallImageSide - smallSideMargin, restLinesCount, 4); restLinesCount -= titleLayout.getLineCount(); } int height = titleLayout.getLineBottom(titleLayout.getLineCount() - 1); @@ -4148,12 +4168,12 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate } else { int max = linkPreviewMaxWidth; if (a < restLines || lineLeft != 0 && isSmallImage) { - max -= AndroidUtilities.dp(48 + 4); + max -= smallImageSide + smallSideMargin; } width = (int) Math.min(max, Math.ceil(titleLayout.getLineWidth(a))); } if (a < restLines || lineLeft != 0 && isSmallImage) { - width += AndroidUtilities.dp(48 + 4); + width += smallImageSide + smallSideMargin; } maxChildWidth = Math.max(maxChildWidth, width + additinalWidth); maxWebWidth = Math.max(maxWebWidth, width + additinalWidth); @@ -4176,7 +4196,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate if (restLinesCount == 3 && (!isSmallImage || description == null)) { authorLayout = new StaticLayout(author, Theme.chat_replyNamePaint, linkPreviewMaxWidth, Layout.Alignment.ALIGN_NORMAL, 1.0f, 0.0f, false); } else { - authorLayout = generateStaticLayout(author, Theme.chat_replyNamePaint, linkPreviewMaxWidth, linkPreviewMaxWidth - AndroidUtilities.dp(48 + 4), restLinesCount, 1); + authorLayout = generateStaticLayout(author, Theme.chat_replyNamePaint, linkPreviewMaxWidth, linkPreviewMaxWidth - smallImageSide - smallSideMargin, restLinesCount, 1); restLinesCount -= authorLayout.getLineCount(); } int height = authorLayout.getLineBottom(authorLayout.getLineCount() - 1); @@ -4212,7 +4232,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate descriptionLayout = StaticLayoutEx.createStaticLayout(messageObject.linkDescription, Theme.chat_replyTextPaint, linkPreviewMaxWidth, Layout.Alignment.ALIGN_NORMAL, 1.0f, AndroidUtilities.dp(1), false, TextUtils.TruncateAt.END, linkPreviewMaxWidth, allowAllLines ? 100 : 6); } else { restLines = restLinesCount; - descriptionLayout = generateStaticLayout(messageObject.linkDescription, Theme.chat_replyTextPaint, linkPreviewMaxWidth, linkPreviewMaxWidth - AndroidUtilities.dp(48 + 4), restLinesCount, allowAllLines ? 100 : 6); + descriptionLayout = generateStaticLayout(messageObject.linkDescription, Theme.chat_replyTextPaint, linkPreviewMaxWidth, linkPreviewMaxWidth - smallImageSide - smallSideMargin, restLinesCount, allowAllLines ? 100 : 6); } int height = descriptionLayout.getLineBottom(descriptionLayout.getLineCount() - 1); linkPreviewHeight += height; @@ -4249,7 +4269,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate } } if (a < restLines || restLines != 0 && lineLeft != 0 && isSmallImage) { - width += AndroidUtilities.dp(48 + 4); + width += smallImageSide + smallSideMargin; } if (maxWebWidth < width + additinalWidth) { if (titleIsRTL) { @@ -4271,7 +4291,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate smallImage = false; isSmallImage = false; } - int maxPhotoWidth = smallImage ? AndroidUtilities.dp(48) : linkPreviewMaxWidth; + int maxPhotoWidth = smallImage ? smallImageSide : linkPreviewMaxWidth; if (document != null) { if (MessageObject.isRoundVideoDocument(document)) { @@ -4618,7 +4638,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate } } else if (documentAttachType == DOCUMENT_ATTACH_TYPE_STICKER) { boolean isWebpSticker = messageObject.isSticker(); - if (SharedConfig.loopStickers || isWebpSticker) { + if (SharedConfig.loopStickers || (isWebpSticker && !messageObject.isVideoSticker())) { photoImage.setAutoRepeat(1); } else { currentPhotoFilter = String.format(Locale.US, "%d_%d_nr_%s", w, h, messageObject.toString()); @@ -5681,7 +5701,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate filter = String.format(Locale.US, "%d_%d_nr_%s" + messageObject.emojiAnimatedStickerColor, w, h, messageObject.toString()); photoImage.setAutoRepeat(shouldRepeatSticker ? 2 : 3); parentObject = MessageObject.getInputStickerSet(messageObject.emojiAnimatedSticker); - } else if (SharedConfig.loopStickers || isWebpSticker) { + } else if (SharedConfig.loopStickers || (isWebpSticker && !messageObject.isVideoSticker())) { filter = String.format(Locale.US, "%d_%d", w, h); photoImage.setAutoRepeat(1); } else { @@ -5721,7 +5741,8 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate if (!reactionsLayoutInBubble.isSmall) { reactionsLayoutInBubble.measure(maxWidth); reactionsLayoutInBubble.drawServiceShaderBackground = true; - additionHeight += reactionsLayoutInBubble.height + AndroidUtilities.dp(8); + reactionsLayoutInBubble.totalHeight = reactionsLayoutInBubble.height + AndroidUtilities.dp(8); + additionHeight += reactionsLayoutInBubble.totalHeight; reactionsLayoutInBubble.positionOffsetY += AndroidUtilities.dp(4); } } else { @@ -7200,11 +7221,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate if (drawPhotoImage) { currentPhotoObject = FileLoader.getClosestPhotoSizeWithSize(messageObject.photoThumbs, 320); - if (currentMessageObject.strippedThumb == null) { - currentPhotoObjectThumb = FileLoader.getClosestPhotoSizeWithSize(messageObject.photoThumbs, 40); - } else { - currentPhotoObjectThumbStripped = currentMessageObject.strippedThumb; - } + currentPhotoObjectThumb = FileLoader.getClosestPhotoSizeWithSize(messageObject.photoThumbs, 40); if ((DownloadController.getInstance(currentAccount).getAutodownloadMask() & DownloadController.AUTODOWNLOAD_TYPE_PHOTO) == 0) { currentPhotoObject = null; @@ -7213,6 +7230,9 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate currentPhotoObject = null; photoImage.setNeedsQualityThumb(true); photoImage.setShouldGenerateQualityThumb(true); + } else if (currentMessageObject.strippedThumb != null) { + currentPhotoObjectThumb = null; + currentPhotoObjectThumbStripped = currentMessageObject.strippedThumb; } currentPhotoFilter = "86_86_b"; photoImage.setImage(ImageLocation.getForObject(currentPhotoObject, messageObject.photoThumbsObject), "86_86", ImageLocation.getForObject(currentPhotoObjectThumb, messageObject.photoThumbsObject), currentPhotoFilter, currentPhotoObjectThumbStripped, 0, null, messageObject, 1); @@ -7302,7 +7322,6 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate LinkPath path = obtainNewUrlPath(true); path.setCurrentLayout(captionLayout, start, 0); captionLayout.getSelectionPath(start, end, path); - path.onPathEnd(); } catch (Exception e) { FileLog.e(e); } @@ -7317,7 +7336,6 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate LinkPath path = obtainNewUrlPath(true); path.setCurrentLayout(block.textLayout, start, 0); block.textLayout.getSelectionPath(start, end, path); - path.onPathEnd(); if (end >= block.charactersOffset + length) { for (int a = c + 1; a < messageObject.textLayoutBlocks.size(); a++) { MessageObject.TextLayoutBlock nextBlock = messageObject.textLayoutBlocks.get(a); @@ -7325,7 +7343,6 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate path = obtainNewUrlPath(true); path.setCurrentLayout(nextBlock.textLayout, 0, nextBlock.height); nextBlock.textLayout.getSelectionPath(0, end - nextBlock.charactersOffset, path); - path.onPathEnd(); if (end < block.charactersOffset + length - 1) { break; } @@ -8686,7 +8703,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate linkPreviewY += currentMessageObject.textHeight + AndroidUtilities.dp(4); } - if (drawPhotoImage && drawInstantView && drawInstantViewType != 9 && drawInstantViewType != 13 && drawInstantViewType != 1 || drawInstantViewType == 6 && imageBackgroundColor != 0) { + if (drawPhotoImage && drawInstantView && drawInstantViewType != 9 && drawInstantViewType != 13 && drawInstantViewType != 11 && drawInstantViewType != 1 || drawInstantViewType == 6 && imageBackgroundColor != 0) { if (linkPreviewY != startY) { linkPreviewY += AndroidUtilities.dp(2); } @@ -8838,7 +8855,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate imageDrawn = true; drawTime = true; } else { - if (delegate == null || delegate.getPinchToZoomHelper() == null || !delegate.getPinchToZoomHelper().isInOverlayModeFor(this) && drawInstantViewType != 11) { + if (delegate == null || delegate.getPinchToZoomHelper() == null || !delegate.getPinchToZoomHelper().isInOverlayModeFor(this)) { if (alpha != 1f) { photoImage.setAlpha(alpha); imageDrawn = photoImage.draw(canvas); @@ -11122,7 +11139,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate canvas.restore(); } - if (!clipToGroupBounds) { + if (delegate == null || delegate.canDrawOutboundsContent()) { drawOutboundsContent(canvas); } @@ -11602,6 +11619,10 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate } } + public boolean hasOutboundsContent() { + return (!transitionParams.transitionBotButtons.isEmpty() && transitionParams.animateBotButtonsChanged) || !botButtons.isEmpty() || drawSideButton != 0; + } + public void drawOutboundsContent(Canvas canvas) { if (!transitionParams.transitionBotButtons.isEmpty() && transitionParams.animateBotButtonsChanged) { drawBotButtons(canvas, transitionParams.transitionBotButtons, 1f - transitionParams.animateChangeProgress); @@ -11615,12 +11636,12 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate private void drawSideButton(Canvas canvas) { if (drawSideButton != 0) { if (currentMessageObject.isOutOwner()) { - sideStartX = getCurrentBackgroundLeft() - AndroidUtilities.dp(8 + 32); + sideStartX = transitionParams.lastBackgroundLeft - AndroidUtilities.dp(8 + 32); if (currentMessagesGroup != null) { sideStartX += currentMessagesGroup.transitionParams.offsetLeft - animationOffsetX; } } else { - sideStartX = currentBackgroundDrawable.getBounds().right + AndroidUtilities.dp(8); + sideStartX = transitionParams.lastBackgroundRight + AndroidUtilities.dp(8); if (currentMessagesGroup != null) { sideStartX += currentMessagesGroup.transitionParams.offsetRight - animationOffsetX; } @@ -14891,7 +14912,13 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate } accessibilityText = sb; } - info.setText(accessibilityText); + + if (Build.VERSION.SDK_INT < Build.VERSION_CODES.N) { + info.setContentDescription(accessibilityText.toString()); + } else { + info.setText(accessibilityText); + } + info.setEnabled(true); if (Build.VERSION.SDK_INT >= 19) { AccessibilityNodeInfo.CollectionItemInfo itemInfo = info.getCollectionItemInfo(); @@ -14939,7 +14966,28 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate seekBarAccessibilityDelegate.onInitializeAccessibilityNodeInfoInternal(info); } - int i = 0; + int i; + if (Build.VERSION.SDK_INT < Build.VERSION_CODES.N) { + if (currentMessageObject.messageText instanceof Spannable) { + Spannable buffer = (Spannable) currentMessageObject.messageText; + CharacterStyle[] links = buffer.getSpans(0, buffer.length(), ClickableSpan.class); + i = 0; + for (CharacterStyle link : links) { + info.addChild(ChatMessageCell.this, LINK_IDS_START + i); + i++; + } + } + if (currentMessageObject.caption instanceof Spannable && captionLayout != null) { + Spannable buffer = (Spannable) currentMessageObject.caption; + CharacterStyle[] links = buffer.getSpans(0, buffer.length(), ClickableSpan.class); + i = 0; + for (CharacterStyle link : links) { + info.addChild(ChatMessageCell.this, LINK_CAPTION_IDS_START + i); + i++; + } + } + } + i = 0; for (BotButton button : botButtons) { info.addChild(ChatMessageCell.this, BOT_BUTTONS_START + i); i++; @@ -15495,6 +15543,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate public int lastTimeX; public int animateFromTimeX; public boolean shouldAnimateTimeX; + public int lastBackgroundLeft, lastBackgroundRight; public boolean animateDrawingTimeAlpha; @@ -15560,7 +15609,9 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate lastDrawingCaptionLayout = captionLayout; lastDrawBotButtons.clear(); - lastDrawBotButtons.addAll(botButtons); + if (!botButtons.isEmpty()) { + lastDrawBotButtons.addAll(botButtons); + } if (commentLayout != null) { lastCommentsCount = getRepliesCount(); @@ -15606,6 +15657,8 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate lastForwardNameX = forwardNameX; lastForwardedNamesOffset = namesOffset; lastForwardNameWidth = forwardedNameWidth; + lastBackgroundLeft = getCurrentBackgroundLeft(); + lastBackgroundRight = currentBackgroundDrawable.getBounds().right; reactionsLayoutInBubble.recordDrawingState(); } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/ContextLinkCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/ContextLinkCell.java index e9fac8723..af1c53c74 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/ContextLinkCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/ContextLinkCell.java @@ -359,8 +359,7 @@ public class ContextLinkCell extends FrameLayout implements DownloadController.F linkImageView.setImage(ImageLocation.getForDocument(currentPhotoObject, documentAttach), currentPhotoFilter, ImageLocation.getForPhoto(currentPhotoObjectThumb, photoAttach), currentPhotoFilterThumb, currentPhotoObject.size, ext, parentObject, 0); } } else { - linkImageView.setImage(ImageLocation.getForPhoto(currentPhotoObject, photoAttach), currentPhotoFilter, ImageLocation.getForPhoto(currentPhotoObjectThumb, photoAttach), currentPhotoFilterThumb, currentPhotoObject.size, ext, parentObject, 0); - } + linkImageView.setImage(ImageLocation.getForPhoto(currentPhotoObject, photoAttach), currentPhotoFilter, ImageLocation.getForPhoto(currentPhotoObjectThumb, photoAttach), currentPhotoFilterThumb, currentPhotoObject.size, ext, parentObject, 0); } } } else if (webFile != null) { linkImageView.setImage(ImageLocation.getForWebFile(webFile), currentPhotoFilter, ImageLocation.getForPhoto(currentPhotoObjectThumb, photoAttach), currentPhotoFilterThumb, -1, ext, parentObject, 1); @@ -580,9 +579,8 @@ public class ContextLinkCell extends FrameLayout implements DownloadController.F @Override protected void onDetachedFromWindow() { super.onDetachedFromWindow(); - if (drawLinkImageView) { - linkImageView.onDetachedFromWindow(); - } + linkImageView.onDetachedFromWindow(); + radialProgress.onDetachedFromWindow(); DownloadController.getInstance(currentAccount).removeLoadingFileObserver(this); } @@ -590,10 +588,8 @@ public class ContextLinkCell extends FrameLayout implements DownloadController.F @Override protected void onAttachedToWindow() { super.onAttachedToWindow(); - if (drawLinkImageView) { - if (linkImageView.onAttachedToWindow()) { - updateButtonState(false, false); - } + if (linkImageView.onAttachedToWindow()) { + updateButtonState(false, false); } radialProgress.onAttachedToWindow(); } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/DialogCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/DialogCell.java index e35e34e78..32c951f01 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/DialogCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/DialogCell.java @@ -27,8 +27,10 @@ import android.text.Spanned; import android.text.StaticLayout; import android.text.TextPaint; import android.text.TextUtils; +import android.text.style.CharacterStyle; import android.text.style.ClickableSpan; import android.text.style.ReplacementSpan; +import android.text.style.StyleSpan; import android.view.HapticFeedbackConstants; import android.view.accessibility.AccessibilityEvent; import android.view.accessibility.AccessibilityNodeInfo; @@ -1335,6 +1337,7 @@ public class DialogCell extends BaseCell { drawCount = false; drawMention = false; } + drawReactionMention = false; } else { if (clearingDialog) { drawCount = false; @@ -1636,7 +1639,7 @@ public class DialogCell extends BaseCell { int w = AndroidUtilities.dp(24); messageWidth -= w; if (!LocaleController.isRTL) { - reactionMentionLeft = getMeasuredWidth() - AndroidUtilities.dp(32) - (mentionWidth != 0 ? (mentionWidth + AndroidUtilities.dp(20)) : 0) - (countWidth != 0 ? countWidth + AndroidUtilities.dp(18) : 0); + reactionMentionLeft = getMeasuredWidth() - AndroidUtilities.dp(32) - (mentionWidth != 0 ? (mentionWidth + AndroidUtilities.dp(18)) : 0) - (countWidth != 0 ? countWidth + AndroidUtilities.dp(18) : 0); } else { reactionMentionLeft = AndroidUtilities.dp(20) + (countWidth != 0 ? countWidth + AndroidUtilities.dp(18) : 0); messageLeft += w; @@ -1714,12 +1717,13 @@ public class DialogCell extends BaseCell { } else { messageStringFinal = messageString; } - // Removing links to get rid of underlining + // Removing links and bold spans to get rid of underlining and boldness if (messageStringFinal instanceof Spannable) { Spannable messageStringSpannable = (Spannable) messageStringFinal; - ClickableSpan[] spans = messageStringSpannable.getSpans(0, messageStringSpannable.length(), ClickableSpan.class); - for (ClickableSpan span : spans) { - messageStringSpannable.removeSpan(span); + for (CharacterStyle span : messageStringSpannable.getSpans(0, messageStringSpannable.length(), CharacterStyle.class)) { + if (span instanceof ClickableSpan || (span instanceof StyleSpan && ((StyleSpan) span).getStyle() == android.graphics.Typeface.BOLD)) { + messageStringSpannable.removeSpan(span); + } } } @@ -2079,6 +2083,7 @@ public class DialogCell extends BaseCell { if (dialog instanceof TLRPC.TL_dialogFolder) { unreadCount = MessagesStorage.getInstance(currentAccount).getArchiveUnreadCount(); mentionCount = 0; + reactionMentionCount = 0; } else { unreadCount = dialog.unread_count; mentionCount = dialog.unread_mentions_count; @@ -2100,6 +2105,7 @@ public class DialogCell extends BaseCell { } else { unreadCount = 0; mentionCount = 0; + reactionMentionCount = 0; currentEditDate = 0; lastMessageDate = 0; clearingDialog = false; @@ -2162,20 +2168,23 @@ public class DialogCell extends BaseCell { TLRPC.Dialog dialog = MessagesController.getInstance(currentAccount).dialogs_dict.get(currentDialogId); int newCount; int newMentionCount; + int newReactionCout = 0; if (dialog instanceof TLRPC.TL_dialogFolder) { newCount = MessagesStorage.getInstance(currentAccount).getArchiveUnreadCount(); newMentionCount = 0; } else if (dialog != null) { newCount = dialog.unread_count; newMentionCount = dialog.unread_mentions_count; + newReactionCout = dialog.unread_reactions_count; } else { newCount = 0; newMentionCount = 0; } - if (dialog != null && (unreadCount != newCount || markUnread != dialog.unread_mark || mentionCount != newMentionCount)) { + if (dialog != null && (unreadCount != newCount || markUnread != dialog.unread_mark || mentionCount != newMentionCount || reactionMentionCount != newReactionCout)) { unreadCount = newCount; mentionCount = newMentionCount; markUnread = dialog.unread_mark; + reactionMentionCount = newReactionCout; continueUpdate = true; } } @@ -2936,11 +2945,11 @@ public class DialogCell extends BaseCell { if (drawReactionMention || reactionsMentionsChangeProgress != 1f) { - Theme.dialogs_countPaint.setAlpha((int) ((1.0f - reorderIconProgress) * 255)); + Theme.dialogs_reactionsCountPaint.setAlpha((int) ((1.0f - reorderIconProgress) * 255)); int x = reactionMentionLeft - AndroidUtilities.dp(5.5f); rect.set(x, countTop, x + AndroidUtilities.dp(23), countTop + AndroidUtilities.dp(23)); - Paint paint = dialogMuted && folderId != 0 ? Theme.dialogs_countGrayPaint : Theme.dialogs_countPaint; + Paint paint = Theme.dialogs_reactionsCountPaint; canvas.save(); if (reactionsMentionsChangeProgress != 1f) { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/ShareDialogCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/ShareDialogCell.java index c8adae174..4a038a467 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/ShareDialogCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/ShareDialogCell.java @@ -90,6 +90,8 @@ public class ShareDialogCell extends FrameLayout { invalidate(); }); addView(checkBox, LayoutHelper.createFrame(24, 24, Gravity.CENTER_HORIZONTAL | Gravity.TOP, 19, currentType == TYPE_CREATE ? -40 : 42, 0, 0)); + + setBackground(Theme.createRadSelectorDrawable(Theme.getColor(Theme.key_listSelector), AndroidUtilities.dp(2), AndroidUtilities.dp(2))); } @Override @@ -196,6 +198,7 @@ public class ShareDialogCell extends FrameLayout { Theme.checkboxSquare_checkPaint.setColor(getThemedColor(Theme.key_dialogRoundCheckBox)); Theme.checkboxSquare_checkPaint.setAlpha((int) (checkBox.getProgress() * 255)); canvas.drawCircle(cx, cy, AndroidUtilities.dp(currentType == TYPE_CREATE ? 24 : 28), Theme.checkboxSquare_checkPaint); + super.onDraw(canvas); } private int getThemedColor(String key) { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/SharedLinkCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/SharedLinkCell.java index a6773b456..44b737e47 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/SharedLinkCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/SharedLinkCell.java @@ -584,7 +584,6 @@ public class SharedLinkCell extends FrameLayout { try { urlPath.setCurrentLayout(layout, 0, 0); layout.getSelectionPath(0, layout.getText().length(), urlPath); - urlPath.onPathEnd(); } catch (Exception e) { FileLog.e(e); } @@ -813,7 +812,9 @@ public class SharedLinkCell extends FrameLayout { } canvas.save(); canvas.clipPath(path, Region.Op.DIFFERENCE); - if (pressedLink == a) canvas.drawPath(urlPath, Theme.linkSelectionPaint); + if (pressedLink == a) { + canvas.drawPath(urlPath, Theme.linkSelectionPaint); + } layout.draw(canvas); canvas.restore(); @@ -824,7 +825,9 @@ public class SharedLinkCell extends FrameLayout { spoilers.get(0).getRipplePath(path); canvas.clipPath(path); - if (pressedLink == a) canvas.drawPath(urlPath, Theme.linkSelectionPaint); + if (pressedLink == a) { + canvas.drawPath(urlPath, Theme.linkSelectionPaint); + } layout.draw(canvas); canvas.restore(); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/StickerEmojiCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/StickerEmojiCell.java index d4ed11216..d929030c7 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/StickerEmojiCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/StickerEmojiCell.java @@ -138,7 +138,7 @@ public class StickerEmojiCell extends FrameLayout { sticker = document; parentObject = parent; boolean isVideoSticker = MessageObject.isVideoSticker(document); - TLRPC.PhotoSize thumb = isVideoSticker ? null : FileLoader.getClosestPhotoSizeWithSize(document.thumbs, 90); + TLRPC.PhotoSize thumb = (isVideoSticker && MessageObject.canAutoplayAnimatedSticker(document)) ? null : FileLoader.getClosestPhotoSizeWithSize(document.thumbs, 90); SvgHelper.SvgDrawable svgThumb = DocumentObject.getSvgThumb(document, fromEmojiPanel ? Theme.key_emptyListPlaceholder : Theme.key_windowBackgroundGray, fromEmojiPanel ? 0.2f : 1.0f); if (MessageObject.canAutoplayAnimatedSticker(document)) { if (svgThumb != null) { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/TextSelectionHelper.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/TextSelectionHelper.java index d91a04229..60e9bd088 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/TextSelectionHelper.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/TextSelectionHelper.java @@ -1388,7 +1388,6 @@ public abstract class TextSelectionHelper[] selectedMessagesIds = new SparseArray[]{new SparseArray<>(), new SparseArray<>()}; private SparseArray[] selectedMessagesCanCopyIds = new SparseArray[]{new SparseArray<>(), new SparseArray<>()}; @@ -726,6 +729,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not private String botUser; private long inlineReturn; private String voiceChatHash; + private boolean livestream; private MessageObject botButtons; private MessageObject botReplyButtons; private int botsCount; @@ -946,15 +950,6 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not int dialogFolderId; int dialogFilterId; boolean pulled = false; - public static class PulledDialog { - int stackIndex; - TLRPC.Chat chat; - TLRPC.User user; - long dialogId; - int folderId; - int filterId; - } - private static HashMap> pulledDialogs; private static boolean replacingChatActivity = false; private PinchToZoomHelper pinchToZoomHelper; @@ -1247,10 +1242,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not @Override public boolean validateGroupId(long groupId) { MessageObject.GroupedMessages groupedMessages = groupedMessagesMap.get(groupId); - if (groupedMessages != null && groupedMessages.messages.size() > 1) { - return true; - } - return false; + return groupedMessages != null && groupedMessages.messages.size() > 1; } }; @@ -1595,6 +1587,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not dialogFilterId = arguments.getInt("dialog_filter_id", 0); chatMode = arguments.getInt("chatMode", 0); voiceChatHash = arguments.getString("voicechat", null); + livestream = arguments.getString("livestream", null) != null; inlineReturn = arguments.getLong("inline_return", 0); String inlineQuery = arguments.getString("inline_query"); startLoadFromMessageId = arguments.getInt("message_id", 0); @@ -1709,6 +1702,8 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not return false; } + dialog_id_Long = dialog_id; + themeDelegate = new ThemeDelegate(); if (themeDelegate.isThemeChangeAvailable()) { NotificationCenter.getGlobalInstance().addObserver(this, NotificationCenter.needSetDayNightTheme); @@ -2165,8 +2160,9 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not pinchToZoomHelper.clear(); } chatThemeBottomSheet = null; - - clearPulledDialogs(currentAccount, getParentLayout().fragmentsStack.indexOf(this) - (replacingChatActivity ? 0 : 1)); + if (parentLayout != null && parentLayout.fragmentsStack != null) { + BackButtonMenu.clearPulledDialogs(currentAccount, parentLayout.fragmentsStack.indexOf(this) - (replacingChatActivity ? 0 : 1)); + } replacingChatActivity = false; } @@ -2558,87 +2554,9 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not }); View backButton = actionBar.getBackButton(); backButton.setOnLongClickListener(e -> { - ArrayList dialogs = getStackedHistoryDialogs(currentAccount, getParentLayout().fragmentsStack, dialog_id); - if (dialogs.size() <= 0) { - return false; - } - - ActionBarPopupWindow.ActionBarPopupWindowLayout layout = new ActionBarPopupWindow.ActionBarPopupWindowLayout(context); - Rect backgroundPaddings = new Rect(); - Drawable shadowDrawable = getParentActivity().getResources().getDrawable(R.drawable.popup_fixed_alert).mutate(); - shadowDrawable.getPadding(backgroundPaddings); - layout.setBackgroundColor(getThemedColor(Theme.key_actionBarDefaultSubmenuBackground)); - - for (int i = 0; i < dialogs.size(); ++i) { - final PulledDialog pDialog = dialogs.get(i); - final TLRPC.Chat chat = pDialog.chat; - final TLRPC.User user = pDialog.user; - FrameLayout cell = new FrameLayout(context); - cell.setMinimumWidth(AndroidUtilities.dp(200)); - - BackupImageView imageView = new BackupImageView(context); - imageView.setRoundRadius(AndroidUtilities.dp(32)); - cell.addView(imageView, LayoutHelper.createFrameRelatively(32, 32, Gravity.START | Gravity.CENTER_VERTICAL, 13, 0, 0, 0)); - - TextView titleView = new TextView(context); - titleView.setLines(1); - titleView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 16); - titleView.setTextColor(Theme.getColor(Theme.key_actionBarDefaultSubmenuItem)); - titleView.setEllipsize(TextUtils.TruncateAt.END); - cell.addView(titleView, LayoutHelper.createFrameRelatively(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.START | Gravity.CENTER_VERTICAL, 59, 0, 12, 0)); - - AvatarDrawable avatarDrawable = new AvatarDrawable(); - if (chat != null) { - avatarDrawable.setInfo(chat); - imageView.setImage(ImageLocation.getForChat(chat, ImageLocation.TYPE_SMALL), "50_50", avatarDrawable, chat); - titleView.setText(chat.title); - } else if (user != null) { - avatarDrawable.setInfo(user); - imageView.setImage(ImageLocation.getForUser(user, ImageLocation.TYPE_SMALL), "50_50", avatarDrawable, user); - titleView.setText(UserObject.getUserName(user)); - } - - boolean isFirst = i == 0, isLast = i == dialogs.size() - 1; - cell.setBackground(Theme.getSelectorDrawable(Theme.getColor(Theme.key_listSelector), false)); - cell.setOnClickListener(e2 -> { - if (scrimPopupWindow != null) { - scrimPopupWindow.dismiss(); - } - if (pDialog.stackIndex >= 0) { - final ActionBarLayout parentLayout = getParentLayout(); - BaseFragment fragment = pDialog.stackIndex >= parentLayout.fragmentsStack.size() ? null : parentLayout.fragmentsStack.get(pDialog.stackIndex); - if (fragment instanceof ChatActivity && ((ChatActivity) fragment).dialog_id != pDialog.dialogId) { - for (int j = parentLayout.fragmentsStack.size() - 2; j > pDialog.stackIndex; --j) { - parentLayout.removeFragmentFromStack(j); - } - goTo(this, chat != null ? chat : user, pDialog.dialogId, pDialog.folderId, pDialog.filterId); - } else { - for (int j = parentLayout.fragmentsStack.size() - 2; j > pDialog.stackIndex; --j) { - if (j >= 0 && j < parentLayout.fragmentsStack.size()) { - parentLayout.removeFragmentFromStack(j); - } - } - if (pDialog.stackIndex < parentLayout.fragmentsStack.size()) { - parentLayout.showFragment(pDialog.stackIndex); - parentLayout.closeLastFragment(true); - } else { - goTo(this, chat != null ? chat : user, pDialog.dialogId, pDialog.folderId, pDialog.filterId); - } - } - } else { - goTo(this, chat != null ? chat : user, pDialog.dialogId, pDialog.folderId, pDialog.filterId); - } - }); - layout.addView(cell, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, 44)); - } - - scrimPopupWindow = new ActionBarPopupWindow(layout, LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT) { - @Override - public void dismiss() { - super.dismiss(); - if (scrimPopupWindow != this) { - return; - } + scrimPopupWindow = BackButtonMenu.show(this, backButton, dialog_id); + if (scrimPopupWindow != null) { + scrimPopupWindow.setOnDismissListener(() -> { scrimPopupWindow = null; menuDeleteItem = null; scrimPopupWindowItems = null; @@ -2651,48 +2569,24 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not if (chatActivityEnterView != null) { chatActivityEnterView.getEditField().setAllowDrawCursor(true); } + }); + chatListView.stopScroll(); + chatLayoutManager.setCanScrollVertically(false); + dimBehindView(backButton, 0.3f); + hideHints(false); + if (topUndoView != null) { + topUndoView.hide(true, 1); } - }; - scrimPopupWindow.setPauseNotifications(true); - scrimPopupWindow.setDismissAnimationDuration(220); - scrimPopupWindow.setOutsideTouchable(true); - scrimPopupWindow.setClippingEnabled(true); - scrimPopupWindow.setAnimationStyle(R.style.PopupContextAnimation); - scrimPopupWindow.setFocusable(true); - layout.measure(View.MeasureSpec.makeMeasureSpec(AndroidUtilities.dp(1000), View.MeasureSpec.AT_MOST), View.MeasureSpec.makeMeasureSpec(AndroidUtilities.dp(1000), View.MeasureSpec.AT_MOST)); - scrimPopupWindow.setInputMethodMode(ActionBarPopupWindow.INPUT_METHOD_NOT_NEEDED); - scrimPopupWindow.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_UNSPECIFIED); - scrimPopupWindow.getContentView().setFocusableInTouchMode(true); - layout.setFitItems(true); - - int popupX = AndroidUtilities.dp(8) - backgroundPaddings.left; - if (AndroidUtilities.isTablet()) { - int[] location = new int[2]; - fragmentView.getLocationInWindow(location); - popupX += location[0]; + if (undoView != null) { + undoView.hide(true, 1); + } + if (chatActivityEnterView != null) { + chatActivityEnterView.getEditField().setAllowDrawCursor(false); + } + return true; + } else { + return false; } - int popupY = (int) (backButton.getBottom() - backgroundPaddings.top - AndroidUtilities.dp(8)); - final int finalPopupX = scrimPopupX = popupX; - final int finalPopupY = scrimPopupY = popupY; - scrimPopupWindow.showAtLocation(chatListView, Gravity.LEFT | Gravity.TOP, finalPopupX, finalPopupY); - try { - chatListView.performHapticFeedback(HapticFeedbackConstants.KEYBOARD_TAP, HapticFeedbackConstants.FLAG_IGNORE_GLOBAL_SETTING); - } catch (Exception ignore) {} - chatListView.stopScroll(); - chatLayoutManager.setCanScrollVertically(false); - dimBehindView(backButton, 0.3f); - hideHints(false); - if (topUndoView != null) { - topUndoView.hide(true, 1); - } - if (undoView != null) { - undoView.hide(true, 1); - } - if (chatActivityEnterView != null) { - chatActivityEnterView.getEditField().setAllowDrawCursor(false); - } - - return true; }); actionBar.setInterceptTouchEventListener((view, motionEvent) -> { if (chatThemeBottomSheet != null) { @@ -3309,7 +3203,9 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not pullingDownDrawable = null; } emojiAnimationsOverlay.onDetachedFromWindow(); - ReactionsEffectOverlay.removeCurrent(true); + AndroidUtilities.runOnUIThread(() -> { + ReactionsEffectOverlay.removeCurrent(true); + }); } @Override @@ -3371,7 +3267,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not @Override protected boolean drawChild(Canvas canvas, View child, long drawingTime) { - if (scrimView != null && (child == pagedownButton || child == mentiondownButton || child == floatingDateView || child == fireworksOverlay)) { + if ((scrimView != null || messageEnterTransitionContainer.isRunning()) && (child == pagedownButton || child == mentiondownButton || child == floatingDateView || child == fireworksOverlay || child == reactionsMentiondownButton || child == gifHintTextView)) { return false; } if (child == fragmentContextView && fragmentContextView.isCallStyle()) { @@ -3492,7 +3388,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not canvas.restore(); } - private RectF rect = new RectF(); + @Override protected void dispatchDraw(Canvas canvas) { chatActivityEnterView.checkAnimation(); @@ -3552,7 +3448,12 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not canvas.drawRect(0, 0, getMeasuredWidth(), getMeasuredHeight(), scrimPaint); } if (scrimView != null) { - if (scrimView instanceof ImageView) { + if (scrimView == reactionsMentiondownButton || scrimView == mentiondownButton) { + if (scrimViewAlpha < 1f) { + scrimPaint.setAlpha((int) (255 * scrimPaintAlpha * (1f - scrimViewAlpha))); + canvas.drawRect(0, 0, getMeasuredWidth(), getMeasuredHeight(), scrimPaint); + } + } else if (scrimView instanceof ImageView) { int c = canvas.save(); if (scrimViewAlpha < 1f) { canvas.saveLayerAlpha(scrimView.getLeft(), scrimView.getTop(), scrimView.getRight(), scrimView.getBottom(), (int) (255 * scrimViewAlpha), Canvas.ALL_SAVE_FLAG); @@ -3667,6 +3568,9 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not cell.drawBackgroundInternal(canvas, true); } child.draw(canvas); + if (cell != null && cell.hasOutboundsContent()) { + cell.drawOutboundsContent(canvas); + } canvas.restore(); if (cell != null) { @@ -3734,24 +3638,33 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } } + if (scrimViewReaction == null && scrimViewAlpha < 1f) { + scrimPaint.setAlpha((int) (255 * scrimPaintAlpha * (1f - scrimViewAlpha))); + canvas.drawRect(0, 0, getMeasuredWidth(), getMeasuredHeight(), scrimPaint); + } + } + + if (scrimView != null || messageEnterTransitionContainer.isRunning()) { if (pagedownButton != null && pagedownButton.getTag() != null) { super.drawChild(canvas, pagedownButton, SystemClock.uptimeMillis()); } if (mentiondownButton != null && mentiondownButton.getTag() != null) { super.drawChild(canvas, mentiondownButton, SystemClock.uptimeMillis()); } + if (reactionsMentiondownButton != null && reactionsMentiondownButton.getTag() != null) { + super.drawChild(canvas, reactionsMentiondownButton, SystemClock.uptimeMillis()); + } if (floatingDateView != null && floatingDateView.getTag() != null) { super.drawChild(canvas, floatingDateView, SystemClock.uptimeMillis()); } if (fireworksOverlay != null) { super.drawChild(canvas, fireworksOverlay, SystemClock.uptimeMillis()); } - - if (scrimViewReaction == null && scrimViewAlpha < 1f) { - scrimPaint.setAlpha((int) (255 * scrimPaintAlpha * (1f - scrimViewAlpha))); - canvas.drawRect(0, 0, getMeasuredWidth(), getMeasuredHeight(), scrimPaint); + if (gifHintTextView != null) { + super.drawChild(canvas, gifHintTextView, SystemClock.uptimeMillis()); } } + if (fixedKeyboardHeight > 0 && keyboardHeight < AndroidUtilities.dp(20)) { int color = getThemedColor(Theme.key_windowBackgroundWhite); if (backgroundPaint == null) { @@ -4777,9 +4690,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not drawLaterRoundProgressCell = null; canvas.save(); - // if (!NekoConfig.disableSwipeToNext.Bool() && fromPullingDownTransition && !toPullingDownTransition) { - canvas.clipRect(0, chatListViewPaddingTop - chatListViewPaddingVisibleOffset - AndroidUtilities.dp(4), getMeasuredWidth(), getMeasuredHeight() - blurredViewBottomOffset); - // } + canvas.clipRect(0, chatListViewPaddingTop - chatListViewPaddingVisibleOffset - AndroidUtilities.dp(4), getMeasuredWidth(), getMeasuredHeight() - blurredViewBottomOffset); selectorRect.setEmpty(); if (pullingDownOffset != 0) { @@ -5108,7 +5019,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not if (clipToGroupBounds) { canvas.restore(); } - if (cell != null && clipToGroupBounds) { + if (cell != null && cell.hasOutboundsContent()) { canvas.save(); canvas.translate(cell.getX(), cell.getY()); cell.drawOutboundsContent(canvas); @@ -6670,16 +6581,33 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not }); mentiondownButton.setOnLongClickListener(view -> { - for (int a = 0; a < messages.size(); a++) { - MessageObject messageObject = messages.get(a); - if (messageObject.messageOwner.mentioned && !messageObject.isContentUnread()) { - messageObject.setContentIsRead(); + scrimPopupWindow = ReadAllMentionsMenu.show(ReadAllMentionsMenu.TYPE_MENTIONS, getParentActivity(), contentView, view, getResourceProvider(), () -> { + for (int a = 0; a < messages.size(); a++) { + MessageObject messageObject = messages.get(a); + if (messageObject.messageOwner.mentioned && !messageObject.isContentUnread()) { + messageObject.setContentIsRead(); + } } - } - newMentionsCount = 0; - getMessagesController().markMentionsAsRead(dialog_id); - hasAllMentionsLocal = true; - showMentionDownButton(false, true); + newMentionsCount = 0; + getMessagesController().markMentionsAsRead(dialog_id); + hasAllMentionsLocal = true; + showMentionDownButton(false, true); + if (scrimPopupWindow != null) { + scrimPopupWindow.dismiss(); + } + }); + dimBehindView(mentiondownButton, true); + scrimPopupWindow.setOnDismissListener(() -> { + scrimPopupWindow = null; + menuDeleteItem = null; + scrimPopupWindowItems = null; + chatLayoutManager.setCanScrollVertically(true); + dimBehindView(false); + if (chatActivityEnterView != null) { + chatActivityEnterView.getEditField().setAllowDrawCursor(true); + } + }); + view.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS, HapticFeedbackConstants.FLAG_IGNORE_GLOBAL_SETTING); return true; }); @@ -7384,33 +7312,36 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not updateReactionsMentionButton(true); getMessagesController().markReactionsAsRead(dialog_id); } else { - reactionsMentionCount--; - if (reactionsMentionCount <= 0) { - reactionsMentionCount = 0; - getMessagesController().markReactionsAsRead(dialog_id); - } updateReactionsMentionButton(true); scrollToMessageId(messageId, 0, false, 0, true, 0); - AndroidUtilities.runOnUIThread(new Runnable() { - @Override - public void run() { - playReactionAnimation(messageId); - } - }, 200); } }); }); - reactionsMentiondownButton.setOnLongClickListener(new View.OnLongClickListener() { - @Override - public boolean onLongClick(View view) { + reactionsMentiondownButton.setOnLongClickListener(view -> { + scrimPopupWindow = ReadAllMentionsMenu.show(ReadAllMentionsMenu.TYPE_REACTIONS, getParentActivity(), contentView, view, getResourceProvider(), () -> { for (int i = 0; i < messages.size(); i++) { messages.get(i).markReactionsAsRead(); } reactionsMentionCount = 0; updateReactionsMentionButton(true); getMessagesController().markReactionsAsRead(dialog_id); - return false; - } + if (scrimPopupWindow != null) { + scrimPopupWindow.dismiss(); + } + }); + dimBehindView(reactionsMentiondownButton, true); + scrimPopupWindow.setOnDismissListener(() -> { + scrimPopupWindow = null; + menuDeleteItem = null; + scrimPopupWindowItems = null; + chatLayoutManager.setCanScrollVertically(true); + dimBehindView(false); + if (chatActivityEnterView != null) { + chatActivityEnterView.getEditField().setAllowDrawCursor(true); + } + }); + view.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS, HapticFeedbackConstants.FLAG_IGNORE_GLOBAL_SETTING); + return false; }); contentView.addView(reactionsMentiondownButton, LayoutHelper.createFrame(46, 61, Gravity.RIGHT | Gravity.BOTTOM, 0, 0, 7, 5)); @@ -8639,7 +8570,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not bottomMessagesActionContainer.addView(forwardButton, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.MATCH_PARENT, Gravity.RIGHT | Gravity.TOP)); contentView.addView(searchContainer, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 51, Gravity.BOTTOM)); - contentView.addView(messageEnterTransitionContainer = new MessageEnterTransitionContainer(context, currentAccount)); + contentView.addView(messageEnterTransitionContainer = new MessageEnterTransitionContainer(contentView, currentAccount)); undoView = new UndoView(context, this, false, themeDelegate); undoView.setAdditionalTranslationY(AndroidUtilities.dp(51)); contentView.addView(undoView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.BOTTOM | Gravity.LEFT, 8, 0, 8, 8)); @@ -8868,19 +8799,19 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not private void dimBehindView(View view, boolean enable) { scrimView = view; - dimBehindView(enable); + dimBehindView(enable ? 0.2f : 0, view != reactionsMentiondownButton && view != mentiondownButton); } private void dimBehindView(View view, float value) { scrimView = view; - dimBehindView(value); + dimBehindView(value, view != reactionsMentiondownButton && view != mentiondownButton); } private void dimBehindView(boolean enable) { - dimBehindView(enable ? 0.2f : 0); + dimBehindView(enable ? 0.2f : 0, true); } - private void dimBehindView(float value) { + private void dimBehindView(float value, boolean hidePagedownButtons) { boolean enable = value > 0; if (scrimView instanceof ChatMessageCell) { ChatMessageCell cell = (ChatMessageCell) scrimView; @@ -8892,6 +8823,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not contentView.invalidate(); chatListView.invalidate(); if (scrimAnimatorSet != null) { + scrimAnimatorSet.removeAllListeners(); scrimAnimatorSet.cancel(); } scrimAnimatorSet = new AnimatorSet(); @@ -8912,11 +8844,16 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not fragmentView.invalidate(); } }); - if (pagedownButton.getTag() != null) { - animators.add(ObjectAnimator.ofFloat(pagedownButton, View.ALPHA, enable ? 0 : 1)); - } - if (mentiondownButton.getTag() != null) { - animators.add(ObjectAnimator.ofFloat(mentiondownButton, View.ALPHA, enable ? 0 : 1)); + if (!enable || hidePagedownButtons) { + if (pagedownButton != null) { + animators.add(ObjectAnimator.ofFloat(pagedownButton, View.ALPHA, enable ? 0 : 1)); + } + if (mentiondownButton != null) { + animators.add(ObjectAnimator.ofFloat(mentiondownButton, View.ALPHA, enable ? 0 : 1)); + } + if (reactionsMentiondownButton != null) { + animators.add(ObjectAnimator.ofFloat(reactionsMentiondownButton, View.ALPHA, enable ? 0 : 1)); + } } scrimAnimatorSet.playTogether(animators); scrimAnimatorSet.setDuration(enable ? 150 : 220); @@ -9111,131 +9048,13 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not presentFragment(chatActivity, true); } - public static void goTo(BaseFragment fragment, TLObject obj, long dialogId, int folderId, int filterId) { - Bundle bundle = new Bundle(); - if (obj instanceof TLRPC.Chat) { - bundle.putLong("chat_id", ((TLRPC.Chat) obj).id); - } else if (obj instanceof TLRPC.User) { - bundle.putLong("user_id", ((TLRPC.User) obj).id); - } - bundle.putInt("dialog_folder_id", folderId); - bundle.putInt("dialog_filter_id", filterId); - fragment.presentFragment(new ChatActivity(bundle), true); - } - private void addToPulledDialogsMyself() { int stackIndex = getParentLayout().fragmentsStack.indexOf(this); - addToPulledDialogs(currentAccount, stackIndex, currentChat, currentUser, dialog_id, dialogFilterId, dialogFolderId); - } - private void addToPulledDialogs(TLRPC.User user, long dialogId, int folderId, int filterId) { - int stackIndex = getParentLayout().fragmentsStack.indexOf(this); - addToPulledDialogs(currentAccount, stackIndex, null, user, dialogId, folderId, filterId); + BackButtonMenu.addToPulledDialogs(currentAccount, stackIndex, currentChat, currentUser, dialog_id, dialogFilterId, dialogFolderId); } private void addToPulledDialogs(TLRPC.Chat chat, long dialogId, int folderId, int filterId) { int stackIndex = getParentLayout().fragmentsStack.indexOf(this); - addToPulledDialogs(currentAccount, stackIndex, chat, null, dialogId, folderId, filterId); - } - private static void addToPulledDialogs(int account, int stackIndex, TLRPC.Chat chat, TLRPC.User user, long dialogId, int folderId, int filterId) { - if (chat == null && user == null) { - return; - } - if (pulledDialogs == null) { - pulledDialogs = new HashMap<>(); - } - ArrayList dialogs = null; - if (pulledDialogs.containsKey(account)) { - dialogs = pulledDialogs.get(account); - } - if (dialogs == null) { - pulledDialogs.put(account, dialogs = new ArrayList<>()); - } - - boolean alreadyAdded = false; - for (PulledDialog d : dialogs) { - if (d.dialogId == dialogId) { - alreadyAdded = true; - break; - } - } - - if (!alreadyAdded) { - PulledDialog d = new PulledDialog(); - d.stackIndex = stackIndex; - d.dialogId = dialogId; - d.filterId = filterId; - d.folderId = folderId; - d.chat = chat; - d.user = user; - dialogs.add(d); - } - } - private void clearPulledDialogs(int account, int fromIndex) { - if (pulledDialogs != null && pulledDialogs.containsKey(account)) { - ArrayList dialogs = pulledDialogs.get(account); - if (dialogs != null) { - for (int i = 0; i < dialogs.size(); ++i) { - if (dialogs.get(i).stackIndex > fromIndex) { - dialogs.remove(i); - i--; - } - } - } - } - } - public static ArrayList getStackedHistoryDialogs(int account, ArrayList fragmentsStack, long ignoreDialogId) { - ArrayList dialogs = new ArrayList<>(); - if (fragmentsStack != null) { - final int count = fragmentsStack.size(); - for (int i = 0; i < count; ++i) { - BaseFragment fragment = fragmentsStack.get(i); - if (fragment instanceof ChatActivity) { - ChatActivity chatActivity = (ChatActivity) fragment; - if (chatActivity.dialog_id != ignoreDialogId && chatActivity.chatMode == 0 && chatActivity.reportType < 0) { - boolean alreadyAddedDialog = false; - for (int d = 0; d < dialogs.size(); ++d) { - if (dialogs.get(d).dialogId == chatActivity.dialog_id) { - alreadyAddedDialog = true; - break; - } - } - if (!alreadyAddedDialog) { - PulledDialog pDialog = new PulledDialog(); - pDialog.stackIndex = i; - pDialog.chat = chatActivity.currentChat; - pDialog.user = chatActivity.currentUser; - pDialog.dialogId = chatActivity.dialog_id; - pDialog.folderId = chatActivity.dialogFolderId; - pDialog.filterId = chatActivity.dialogFilterId; - if (pDialog.chat != null || pDialog.user != null) { - dialogs.add(pDialog); - } - } - } - } - } - } - if (pulledDialogs != null) { - ArrayList pulledDialogsAccount = pulledDialogs.get(account); - if (pulledDialogsAccount != null) { - for (PulledDialog pulledDialog : pulledDialogsAccount) { - if (pulledDialog.dialogId == ignoreDialogId) { - continue; - } - boolean alreadyAddedDialog = false; - for (int d = 0; d < dialogs.size(); ++d) { - if (dialogs.get(d).dialogId == pulledDialog.dialogId) { - alreadyAddedDialog = true; - break; - } - } - if (!alreadyAddedDialog) { - dialogs.add(pulledDialog); - } - } - } - } - Collections.sort(dialogs, (d1, d2) -> d2.stackIndex - d1.stackIndex); - return dialogs; + BackButtonMenu.addToPulledDialogs(currentAccount, stackIndex, chat, null, dialogId, folderId, filterId); } private void setPullingDownTransition(boolean fromPullingDownTransition) { @@ -9801,12 +9620,14 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } private void invalidateChatListViewTopPadding() { - invalidateChatListViewTopPadding = true; - if (contentView != null) { - contentView.invalidate(); - } - if (chatListView != null) { - chatListView.invalidate(); + if (!invalidateChatListViewTopPadding) { + invalidateChatListViewTopPadding = true; + if (contentView != null) { + contentView.invalidate(); + } + if (chatListView != null) { + chatListView.invalidate(); + } } float translation = contentPanTranslation + contentPaddingTop + Math.max(0, AndroidUtilities.dp(48) + topChatPanelViewOffset); @@ -9819,7 +9640,6 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not if (pendingRequestsView != null) { translation += pendingRequestsDelegate.getViewEnterOffset(); pendingRequestsView.setTranslationY(translation); - translation += pendingRequestsDelegate.getViewHeight(); } if (fragmentContextView != null) { float from = 0; @@ -10454,6 +10274,16 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not public long getDialogId() { return dialog_id; } + public int getDialogFolderId() { + return dialogFolderId; + } + public int getDialogFilterId() { + return dialogFilterId; + } + + public boolean openedWithLivestream() { + return livestream; + } public UndoView getUndoView() { return undoView; @@ -10467,6 +10297,10 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not return topChatPanelView != null && topChatPanelView.getTag() == null && reportSpamButton.getVisibility() != View.GONE; } + public boolean isReport() { + return reportType >= 0; + } + public void setChatInvite(TLRPC.ChatInvite invite) { chatInvite = invite; } @@ -11086,42 +10920,37 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not textSelectionHint.show(); } - private void showGifHint() { + private boolean showGifHint() { if (chatActivityEnterView == null || chatActivityEnterView.getVisibility() != View.VISIBLE) { - return; + return false; } SharedPreferences preferences = MessagesController.getGlobalMainSettings(); if (preferences.getBoolean("gifhint", false)) { - return; + return false; } preferences.edit().putBoolean("gifhint", true).apply(); if (getParentActivity() == null || fragmentView == null || gifHintTextView != null) { - return; + return false; } if (!allowContextBotPanelSecond) { if (chatActivityEnterView != null) { chatActivityEnterView.setOpenGifsTabFirst(); } - return; + return false; } SizeNotifierFrameLayout frameLayout = (SizeNotifierFrameLayout) fragmentView; int index = frameLayout.indexOfChild(chatActivityEnterView); if (index == -1) { - return; + return false; } chatActivityEnterView.setOpenGifsTabFirst(); emojiButtonRed = new View(getParentActivity()); emojiButtonRed.setBackgroundResource(R.drawable.redcircle); frameLayout.addView(emojiButtonRed, index + 1, LayoutHelper.createFrame(10, 10, Gravity.BOTTOM | Gravity.LEFT, 30, 0, 0, 27)); - gifHintTextView = new TextView(getParentActivity()); - gifHintTextView.setBackgroundDrawable(Theme.createRoundRectDrawable(AndroidUtilities.dp(3), getThemedColor(Theme.key_chat_gifSaveHintBackground))); - gifHintTextView.setTextColor(getThemedColor(Theme.key_chat_gifSaveHintText)); - gifHintTextView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14); - gifHintTextView.setPadding(AndroidUtilities.dp(8), AndroidUtilities.dp(7), AndroidUtilities.dp(8), AndroidUtilities.dp(7)); + gifHintTextView = new HintView(getParentActivity(), 9, themeDelegate); gifHintTextView.setText(LocaleController.getString("TapHereGifs", R.string.TapHereGifs)); - gifHintTextView.setGravity(Gravity.CENTER_VERTICAL); frameLayout.addView(gifHintTextView, index + 1, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.LEFT | Gravity.BOTTOM, 5, 0, 5, 3)); AnimatorSet AnimatorSet = new AnimatorSet(); @@ -11155,6 +10984,12 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not }); AnimatorSet.setDuration(300); AnimatorSet.start(); + + View emojiButton = chatActivityEnterView.getEmojiButton(); + if (emojiButton != null) { + gifHintTextView.showForView(emojiButton, true); + } + return true; } private void openAttachMenu() { @@ -12662,12 +12497,12 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not MessageObject maxVisibleMessageObject = null; threadMessageVisible = firstLoading; - Integer currentReadMaxId; + Integer currentReadMaxId = null; int threadId = threadMessageId; if (threadId != 0 && currentChat != null) { currentReadMaxId = replyMaxReadId; } else { - currentReadMaxId = getMessagesController().dialogs_read_inbox_max.get(dialog_id); + currentReadMaxId = getMessagesController().dialogs_read_inbox_max.get(dialog_id_Long); } if (currentReadMaxId == null) { currentReadMaxId = 0; @@ -12756,7 +12591,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not startFromVideoTimestamp = -1; } - if (messageCell.checkUnreadReactions(clipTop, chatListView.getMeasuredHeight() - blurredViewBottomOffset)) { + if (fragmentOpened && openAnimationEnded && (chatListItemAnimator == null || !chatListItemAnimator.isRunning()) && messageCell.checkUnreadReactions(clipTop, chatListView.getMeasuredHeight() - blurredViewBottomOffset)) { reactionsMentionCount--; getMessagesStorage().markMessageReactionsAsRead(getDialogId(), messageCell.getMessageObject().getId(), true); if (reactionsMentionCount <= 0) { @@ -14415,6 +14250,123 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } } + public boolean openPhotosEditor(ArrayList photoPathes, CharSequence caption) { + final ArrayList entries = new ArrayList<>(); + for (int a = 0; a < photoPathes.size(); ++a) { + SendMessagesHelper.SendingMediaInfo photoInfo = photoPathes.get(a); + String path; + if (photoInfo.path != null) { + path = photoInfo.path; + } else if (photoInfo.uri != null) { + path = AndroidUtilities.getPath(photoInfo.uri); + } else { + continue; + } + int orientation = 0; + try { + ExifInterface ei = new ExifInterface(path); + int exif = ei.getAttributeInt(ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_NORMAL); + switch (exif) { + case ExifInterface.ORIENTATION_ROTATE_90: + orientation = 90; + break; + case ExifInterface.ORIENTATION_ROTATE_180: + orientation = 180; + break; + case ExifInterface.ORIENTATION_ROTATE_270: + orientation = 270; + break; + } + } catch (Exception e) { + FileLog.e(e); + } + MediaController.PhotoEntry entry = new MediaController.PhotoEntry(0, 0, 0, path, orientation, false, 0, 0, 0); + if (a == photoPathes.size() - 1 && caption != null) { + entry.caption = caption; + } + entries.add(entry); + } + if (!entries.isEmpty()) { + if (getParentActivity() != null) { + final boolean[] checked = new boolean[entries.size()]; + Arrays.fill(checked, true); + PhotoViewer.getInstance().setParentActivity(getParentActivity(), themeDelegate); + PhotoViewer.getInstance().openPhotoForSelect(new ArrayList<>(entries), entries.size() - 1, 0, false, new PhotoViewer.EmptyPhotoViewerProvider() { + @Override + public ImageReceiver.BitmapHolder getThumbForPhoto(MessageObject messageObject, TLRPC.FileLocation fileLocation, int index) { + return null; + } + + @Override + public void sendButtonPressed(int index, VideoEditedInfo videoEditedInfo, boolean notify, int scheduleDate, boolean forceDocument) { + for (int i = entries.size() - 1; i >= 0; --i) { + if (!checked[i]) { + entries.remove(i); + } + } + sendPhotosGroup(entries, notify, scheduleDate, forceDocument); + } + + @Override + public int setPhotoChecked(int index, VideoEditedInfo videoEditedInfo) { + return index; + } + + @Override + public boolean isPhotoChecked(int index) { + return checked[index]; + } + + @Override + public boolean canScrollAway() { + return false; + } + }, this); + } else { + fillEditingMediaWithCaption(caption, null); + sendPhotosGroup(entries, false, 0, false); + afterMessageSend(); + } + return true; + } else { + return false; + } + } + private void sendPhotosGroup(ArrayList entries, boolean notify, int scheduleDate, boolean forceDocument) { + if (!entries.isEmpty()) { + ArrayList photos = new ArrayList<>(); + for (MediaController.PhotoEntry entry : entries) { + SendMessagesHelper.SendingMediaInfo info = new SendMessagesHelper.SendingMediaInfo(); + if (!entry.isVideo && entry.imagePath != null) { + info.path = entry.imagePath; + } else if (entry.path != null) { + info.path = entry.path; + } + info.thumbPath = entry.thumbPath; + info.isVideo = entry.isVideo; + info.caption = entry.caption != null ? entry.caption.toString() : null; + info.entities = entry.entities; + info.masks = entry.stickers; + info.ttl = entry.ttl; + info.videoEditedInfo = entry.editedInfo; + info.canDeleteAfter = entry.canDeleteAfter; + photos.add(info); + entry.reset(); + } + fillEditingMediaWithCaption(photos.get(0).caption, photos.get(0).entities); + SendMessagesHelper.prepareSendingMedia(getAccountInstance(), photos, dialog_id, null, getThreadMessage(), null, forceDocument, true, null, notify, scheduleDate); + afterMessageSend(); + chatActivityEnterView.setFieldText(""); + } + if (scheduleDate != 0) { + if (scheduledMessagesCount == -1) { + scheduledMessagesCount = 0; + } + scheduledMessagesCount += entries.size(); + updateScheduledInterface(true); + } + } + private void openEditingMessageInPhotoEditor() { if (editingMessageObject == null || !editingMessageObject.canEditMedia() || editingMessageObjectReqId != 0) { return; @@ -14761,7 +14713,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } else { chatListView.setEmptyView(emptyViewContainer); } - chatAdapter.notifyDataSetChanged(); + chatAdapter.notifyDataSetChanged(true); } resumeDelayedFragmentAnimation(); @@ -15666,7 +15618,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not checkScrollForLoad(false); if (postponedScroll) { - chatAdapter.notifyDataSetChanged(); + chatAdapter.notifyDataSetChanged(true); if (progressDialog != null) { progressDialog.dismiss(); } @@ -16170,7 +16122,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } } if (chatAdapter != null) { - chatAdapter.notifyDataSetChanged(false); + chatAdapter.notifyDataSetChanged(true); } } return; @@ -16306,7 +16258,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not chatActivityEnterView.updateFieldHint(false); } if (chatAdapter != null) { - chatAdapter.notifyDataSetChanged(); + chatAdapter.notifyDataSetChanged(true); } if (prevLinkedChatId != chatInfo.linked_chat_id) { if (prevLinkedChatId != 0) { @@ -16397,7 +16349,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not mergeDialogId = -chatInfo.migrated_from_chat_id; maxMessageId[1] = chatInfo.migrated_from_max_id; if (chatAdapter != null) { - chatAdapter.notifyDataSetChanged(false); + chatAdapter.notifyDataSetChanged(true); } if (mergeDialogId != 0 && endReached[0]) { checkScrollForLoad(false); @@ -18174,7 +18126,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not newGroups.put(groupedMessages.groupId, groupedMessages); } if (chatAdapter != null) { - chatAdapter.notifyDataSetChanged(false); + chatAdapter.notifyDataSetChanged(true); } } } @@ -19112,6 +19064,10 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not super.onTransitionAnimationStart(isOpen, backward); int[] alowedNotifications = null; if (isOpen) { + if (!fragmentOpened) { + fragmentOpened = true; + updateMessagesVisiblePart(false); + } if (transitionAnimationIndex == 0) { alowedNotifications = new int[]{ NotificationCenter.dialogsNeedReload, NotificationCenter.closeChats, @@ -19147,10 +19103,6 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not public void onTransitionAnimationEnd(boolean isOpen, boolean backward) { super.onTransitionAnimationEnd(isOpen, backward); if (isOpen) { - if (!fragmentOpened) { - fragmentOpened = true; - updateMessagesVisiblePart(false); - } if (backward) { if (showPinBulletin && pinBulletin != null) { pinBulletin.show(); @@ -19259,6 +19211,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not if (pendingRequestsDelegate != null && backward) { pendingRequestsDelegate.onBackToScreen(); } + updateMessagesVisiblePart(false); } else { getNotificationCenter().onAnimationFinish(transitionAnimationIndex); } @@ -21651,11 +21604,11 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } } else if (selectedObject.isMusic() && !noforwards) { items.add(LocaleController.getString("SaveToMusic", R.string.SaveToMusic)); - options.add(10); + options.add(OPTION_SAVE_TO_DOWNLOADS_OR_MUSIC); icons.add(R.drawable.msg_download); } else if (selectedObject.isDocument() && !noforwards) { items.add(LocaleController.getString("SaveToDownloads", R.string.SaveToDownloads)); - options.add(10); + options.add(OPTION_SAVE_TO_DOWNLOADS_OR_MUSIC); icons.add(R.drawable.msg_download); } } @@ -21678,20 +21631,20 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } } else if (selectedObject.isMusic()) { items.add(LocaleController.getString("SaveToMusic", R.string.SaveToMusic)); - options.add(10); + options.add(OPTION_SAVE_TO_DOWNLOADS_OR_MUSIC); icons.add(R.drawable.baseline_file_download_24); items.add(LocaleController.getString("ShareFile", R.string.ShareFile)); options.add(6); icons.add(R.drawable.baseline_share_24); } else if (selectedObject.getDocument() != null) { - items.add(LocaleController.getString("SaveToDownloads", R.string.SaveToDownloads)); - options.add(10); - icons.add(R.drawable.baseline_file_download_24); if (MessageObject.isNewGifDocument(selectedObject.getDocument())) { - items.add(LocaleController.getString("SaveToGIFs", R.string.SaveToGIFs)); - options.add(11); - icons.add(R.drawable.deproko_baseline_gif_24); - } + items.add(LocaleController.getString("SaveToGIFs", R.string.SaveToGIFs)); + options.add(11); + icons.add(R.drawable.deproko_baseline_gif_24); + } + items.add(LocaleController.getString("SaveToDownloads", R.string.SaveToDownloads)); + options.add(OPTION_SAVE_TO_DOWNLOADS_OR_MUSIC); + icons.add(R.drawable.baseline_file_download_24); items.add(LocaleController.getString("ShareFile", R.string.ShareFile)); options.add(6); icons.add(R.drawable.baseline_share_24); @@ -21709,7 +21662,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not icons.add(R.drawable.baseline_language_24); if (!noforwards) { items.add(LocaleController.getString("SaveToDownloads", R.string.SaveToDownloads)); - options.add(10); + options.add(OPTION_SAVE_TO_DOWNLOADS_OR_MUSIC); icons.add(R.drawable.baseline_file_download_24); items.add(LocaleController.getString("ShareFile", R.string.ShareFile)); options.add(6); @@ -21739,7 +21692,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } if (!noforwards) { items.add(LocaleController.getString("SaveToDownloads", R.string.SaveToDownloads)); - options.add(10); + options.add(OPTION_SAVE_TO_DOWNLOADS_OR_MUSIC); icons.add(R.drawable.baseline_file_download_24); items.add(LocaleController.getString("ShareFile", R.string.ShareFile)); options.add(6); @@ -21750,7 +21703,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not options.add(7); icons.add(R.drawable.baseline_image_24); items.add(LocaleController.getString("SaveToDownloads", R.string.SaveToDownloads)); - options.add(10); + options.add(OPTION_SAVE_TO_DOWNLOADS_OR_MUSIC); icons.add(R.drawable.baseline_file_download_24); items.add(LocaleController.getString("ShareFile", R.string.ShareFile)); options.add(6); @@ -22015,14 +21968,14 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not icons.add(R.drawable.baseline_share_24); } else if (selectedObject.isMusic()) { items.add(LocaleController.getString("SaveToMusic", R.string.SaveToMusic)); - options.add(10); + options.add(OPTION_SAVE_TO_DOWNLOADS_OR_MUSIC); icons.add(R.drawable.baseline_file_download_24); items.add(LocaleController.getString("ShareFile", R.string.ShareFile)); options.add(6); icons.add(R.drawable.baseline_share_24); } else if (!selectedObject.isVideo() && selectedObject.getDocument() != null) { items.add(LocaleController.getString("SaveToDownloads", R.string.SaveToDownloads)); - options.add(10); + options.add(OPTION_SAVE_TO_DOWNLOADS_OR_MUSIC); icons.add(R.drawable.baseline_file_download_24); items.add(LocaleController.getString("ShareFile", R.string.ShareFile)); options.add(6); @@ -22186,12 +22139,10 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not boolean nekoXShowReactionsView = (NekoConfig.reactions.Int() == 0 || onDoubleTapped); // Show reactions and hide them from tap boolean isReactionsViewAvailable = nekoXShowReactionsView && !isSecretChat() && !isInScheduleMode() && currentUser == null && message.hasReactions() && (!ChatObject.isChannel(currentChat) || currentChat.megagroup) && !availableReacts.isEmpty() && message.messageOwner.reactions.can_see_list; boolean isReactionsAvailable; - boolean needLoadReactionsChat = false; if (message.isForwardedChannelPost()) { TLRPC.ChatFull chatInfo = getMessagesController().getChatFull(-message.getFromChatId()); if (chatInfo == null) { isReactionsAvailable = true; - needLoadReactionsChat = true; } else { isReactionsAvailable = nekoXShowReactionsView && !isSecretChat() && !isInScheduleMode() && message.isReactionsAvailable() && (chatInfo != null && !chatInfo.available_reactions.isEmpty()) && !availableReacts.isEmpty(); } @@ -22234,7 +22185,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not }; linearLayout.setOrientation(LinearLayout.VERTICAL); linearLayout.setLayoutParams(new FrameLayout.LayoutParams(AndroidUtilities.dp(200), AndroidUtilities.dp(6 * 48 + (hasHeader ? 44 * 2 + 8 : 44)) + (!hasHeader ? 1 : 0))); - ActionBarMenuSubItem backCell = new ActionBarMenuSubItem(getParentActivity(), true, true, themeDelegate); + ActionBarMenuSubItem backCell = new ActionBarMenuSubItem(getParentActivity(), true, false, themeDelegate); backCell.setItemHeight(44); backCell.setTextAndIcon(LocaleController.getString("Back", R.string.Back), R.drawable.msg_arrow_back); backCell.getTextView().setPadding(LocaleController.isRTL ? 0 : AndroidUtilities.dp(40), 0, LocaleController.isRTL ? AndroidUtilities.dp(40) : 0, 0); @@ -22404,7 +22355,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not if (showMessageSeen) { messageSeenView = new MessageSeenView(contentView.getContext(), currentAccount, message, currentChat); FrameLayout messageSeenLayout = new FrameLayout(contentView.getContext()); - messageSeenLayout.addView(messageSeenView); + messageSeenLayout.addView(messageSeenView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT)); MessageSeenView finalMessageSeenView = messageSeenView; ActionBarMenuSubItem cell = new ActionBarMenuSubItem(getParentActivity(), true, true, themeDelegate); @@ -22701,9 +22652,6 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not scrimPopupWindow.getContentView().setFocusableInTouchMode(true); popupLayout.setFitItems(true); - if (messageSeenView != null) { - messageSeenView.getLayoutParams().width = scrimPopupContainerLayout.getMeasuredWidth() - (isReactionsAvailable ? AndroidUtilities.dp(56) : 0) - AndroidUtilities.dp(16); - } int popupX = v.getLeft() + (int) x - scrimPopupContainerLayout.getMeasuredWidth() + backgroundPaddings.left - AndroidUtilities.dp(28); if (popupX < AndroidUtilities.dp(6)) { popupX = AndroidUtilities.dp(6); @@ -22841,7 +22789,9 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not private void closeMenu() { closeMenu(true); } + private ValueAnimator scrimViewAlphaAnimator; + private void closeMenu(boolean hideDim) { scrimPopupWindowHideDimOnDismiss = hideDim; if (scrimPopupWindow != null) { @@ -22850,28 +22800,26 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not if (!hideDim) { if (scrimViewAlphaAnimator != null) { + scrimViewAlphaAnimator.removeAllListeners(); scrimViewAlphaAnimator.cancel(); } scrimViewAlphaAnimator = ValueAnimator.ofFloat(1f, 0f); scrimViewAlphaAnimator.addUpdateListener(a -> { scrimViewAlpha = (float) a.getAnimatedValue(); - contentView.invalidate(); - chatListView.invalidate(); + if (contentView != null) { + contentView.invalidate(); + chatListView.invalidate(); + } }); scrimViewAlphaAnimator.setDuration(150); scrimViewAlphaAnimator.start(); - } else { -// scrimView = null; -// scrimViewReaction = null; -// contentView.invalidate(); -// chatListView.invalidate(); } } Runnable updateReactionRunnable; private void selectReaction(MessageObject primaryMessage, ReactionsContainerLayout reactionsLayout, float x, float y, TLRPC.TL_availableReaction reaction, boolean fromDoubleTap, boolean bigEmoji) { ReactionsEffectOverlay.removeCurrent(false); - boolean added = primaryMessage.selectReaction(reaction.reaction, fromDoubleTap); + boolean added = primaryMessage.selectReaction(reaction.reaction, bigEmoji, fromDoubleTap); int messageIdForCell = primaryMessage.getId(); if (groupedMessagesMap.get(primaryMessage.getGroupId()) != null) { int flags = primaryMessage.shouldDrawReactionsInLayout() ? MessageObject.POSITION_FLAG_BOTTOM | MessageObject.POSITION_FLAG_LEFT : MessageObject.POSITION_FLAG_BOTTOM | MessageObject.POSITION_FLAG_RIGHT; @@ -23447,7 +23395,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not showDialog(alert); break; } - case 10: { + case OPTION_SAVE_TO_DOWNLOADS_OR_MUSIC: { //TODO scopped storage if (Build.VERSION.SDK_INT >= 23 && (Build.VERSION.SDK_INT <= 28 || BuildVars.NO_SCOPED_STORAGE) && getParentActivity().checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) { getParentActivity().requestPermissions(new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, 4); @@ -23502,7 +23450,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } else if (video) { fileType = BulletinFactory.FileType.VIDEO_TO_DOWNLOADS; } else if (gif) { - fileType = BulletinFactory.FileType.GIF; + fileType = BulletinFactory.FileType.GIF_TO_DOWNLOADS; } else { fileType = BulletinFactory.FileType.UNKNOWN; } @@ -23514,7 +23462,9 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not case 11: { TLRPC.Document document = selectedObject.getDocument(); getMessagesController().saveGif(selectedObject, document); - showGifHint(); + if (!showGifHint() && getParentActivity() != null) { + BulletinFactory.of(this).createDownloadBulletin(BulletinFactory.FileType.GIF, themeDelegate).show(); + } chatActivityEnterView.addRecentGif(document); break; } @@ -23838,7 +23788,9 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } else { SendMessagesHelper.getInstance(currentAccount).editMessage(message, null, false, ChatActivity.this, null, scheduleDate); } - }, () -> dimBehindView(false), themeDelegate); + }, null, themeDelegate) + .setOnPreDismissListener(di -> dimBehindView(false)) + .setDimBehind(false); preserveDim = true; break; } @@ -24383,16 +24335,14 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } else { SendMessagesHelper.prepareSendingVideo(getAccountInstance(), photoEntry.path, null, dialog_id, replyingMessageObject, getThreadMessage(), photoEntry.caption, photoEntry.entities, photoEntry.ttl, editingMessageObject, notify, scheduleDate, forceDocument); } - afterMessageSend(); } else { if (photoEntry.imagePath != null) { SendMessagesHelper.prepareSendingPhoto(getAccountInstance(), photoEntry.imagePath, photoEntry.thumbPath, null, dialog_id, replyingMessageObject, getThreadMessage(), photoEntry.caption, photoEntry.entities, photoEntry.stickers, null, photoEntry.ttl, editingMessageObject, videoEditedInfo, notify, scheduleDate, forceDocument); - afterMessageSend(); } else if (photoEntry.path != null) { SendMessagesHelper.prepareSendingPhoto(getAccountInstance(), photoEntry.path, photoEntry.thumbPath, null, dialog_id, replyingMessageObject, getThreadMessage(), photoEntry.caption, photoEntry.entities, photoEntry.stickers, null, photoEntry.ttl, editingMessageObject, videoEditedInfo, notify, scheduleDate, forceDocument); - afterMessageSend(); } } + afterMessageSend(); } public void showOpenGameAlert(final TLRPC.TL_game game, final MessageObject messageObject, final String urlStr, boolean ask, final long uid) { @@ -25120,8 +25070,9 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not return; } } - if (Browser.isTelegraphUrl(urlFinal, false)) + if (Browser.urlMustNotHaveConfirmation(urlFinal)) { forceAlert = false; + } processExternalUrl(2, urlFinal, forceAlert); } } @@ -25553,10 +25504,15 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not private void appendMention(TLRPC.User user) { if (chatActivityEnterView != null) { - final SpannableStringBuilder sb = new SpannableStringBuilder(); + SpannableStringBuilder sb; final CharSequence text = chatActivityEnterView.getFieldText(); if (text != null) { - sb.append(text); + sb = new SpannableStringBuilder(text); + if (text.charAt(text.length() - 1) != ' ') { + sb.append(" "); + } + } else { + sb = new SpannableStringBuilder(); } if (sb.length() > 0 && sb.charAt(sb.length() - 1) != ' ') { sb.append(' '); @@ -26208,6 +26164,11 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not public void invalidateBlur() { contentView.invalidateBlur(); } + + @Override + public boolean canDrawOutboundsContent() { + return false; + } }); if (currentEncryptedChat == null) { chatMessageCell.setAllowAssistant(true); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/AnimatedFileDrawable.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/AnimatedFileDrawable.java index 2b315874e..0fcc486b9 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/AnimatedFileDrawable.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/AnimatedFileDrawable.java @@ -121,6 +121,7 @@ public class AnimatedFileDrawable extends BitmapDrawable implements Animatable { private int renderingWidth; private float scaleFactor = 1f; public final boolean isWebmSticker; + private final TLRPC.Document document; private View parentView; private ArrayList secondParentViews = new ArrayList<>(); @@ -171,6 +172,9 @@ public class AnimatedFileDrawable extends BitmapDrawable implements Animatable { } loadFrameTask = null; scheduleNextGetFrame(); + for (int i = 0; i < parents.size(); i++) { + parents.get(i).invalidate(); + } } }; @@ -229,8 +233,8 @@ public class AnimatedFileDrawable extends BitmapDrawable implements Animatable { secondParentViews.get(a).invalidate(); } } - if ((secondParentViews.isEmpty() || invalidateParentViewWithSecond) && parentView != null) { - parentView.invalidate(); + for (int i = 0; i < parents.size(); i++) { + parents.get(i).invalidate(); } scheduleNextGetFrame(); } @@ -331,7 +335,8 @@ public class AnimatedFileDrawable extends BitmapDrawable implements Animatable { currentAccount = account; renderingHeight = h; renderingWidth = w; - isWebmSticker = MessageObject.isVideoSticker(document); + this.document = document; + isWebmSticker = MessageObject.isWebM(document) || MessageObject.isVideoSticker(document); if (isWebmSticker) { useSharedQueue = true; } @@ -388,7 +393,7 @@ public class AnimatedFileDrawable extends BitmapDrawable implements Animatable { } public void addParent(View view) { - if (!parents.contains(view)) { + if (view != null && !parents.contains(view)) { parents.add(view); if (isRunning) { scheduleNextGetFrame(); @@ -482,6 +487,7 @@ public class AnimatedFileDrawable extends BitmapDrawable implements Animatable { decodeQueue.recycle(); decodeQueue = null; } + getPaint().setShader(null); } else { destroyWhenDone = true; } @@ -534,7 +540,7 @@ public class AnimatedFileDrawable extends BitmapDrawable implements Animatable { @Override public void start() { - if (isRunning) { + if (isRunning || parents.size() == 0) { return; } isRunning = true; @@ -623,8 +629,6 @@ public class AnimatedFileDrawable extends BitmapDrawable implements Animatable { applyTransformation = true; } - Paint paint; - @Override public void draw(Canvas canvas) { if (nativePtr == 0 && decoderCreated || destroyWhenDone) { @@ -714,12 +718,6 @@ public class AnimatedFileDrawable extends BitmapDrawable implements Animatable { canvas.scale(scaleX, scaleY); canvas.drawBitmap(renderingBitmap, 0, 0, getPaint()); } - if (isRunning && !invalidateTaskIsRunning) { - invalidateTaskIsRunning = true; - long timeToNextFrame = Math.max(1, invalidateAfter - (now - lastFrameTime) - 17); - uiHandler.removeCallbacks(mInvalidateTask); - uiHandler.postDelayed(mInvalidateTask, Math.min(timeToNextFrame, invalidateAfter)); - } } } @@ -808,7 +806,7 @@ public class AnimatedFileDrawable extends BitmapDrawable implements Animatable { if (stream != null) { drawable = new AnimatedFileDrawable(path, false, streamFileSize, stream.getDocument(), stream.getLocation(), stream.getParentObject(), pendingSeekToUI, currentAccount, stream != null && stream.isPreview()); } else { - drawable = new AnimatedFileDrawable(path, false, streamFileSize, null, null, null, pendingSeekToUI, currentAccount, stream != null && stream.isPreview()); + drawable = new AnimatedFileDrawable(path, false, streamFileSize, document, null, null, pendingSeekToUI, currentAccount, stream != null && stream.isPreview()); } drawable.metaData[0] = metaData[0]; drawable.metaData[1] = metaData[1]; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/AvatarsDarawable.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/AvatarsDarawable.java index 522d295e1..273ae94c0 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/AvatarsDarawable.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/AvatarsDarawable.java @@ -10,6 +10,7 @@ import android.graphics.PorterDuffXfermode; import android.graphics.drawable.Drawable; import android.os.SystemClock; import android.view.View; +import android.view.animation.Interpolator; import androidx.core.graphics.ColorUtils; @@ -57,6 +58,8 @@ public class AvatarsDarawable { View parent; private int overrideSize; private float overrideAlpha = 1f; + public long transitionDuration = 220; + public Interpolator transitionInterpolator = CubicBezierInterpolator.DEFAULT; public void commitTransition(boolean animated) { if (!wasDraw || !animated) { @@ -133,7 +136,7 @@ public class AvatarsDarawable { transitionProgressAnimator = null; } }); - transitionProgressAnimator.setDuration(220); + transitionProgressAnimator.setDuration(transitionDuration); transitionProgressAnimator.setInterpolator(CubicBezierInterpolator.DEFAULT); transitionProgressAnimator.start(); invalidate(); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/BackButtonMenu.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/BackButtonMenu.java new file mode 100644 index 000000000..0ecaa899a --- /dev/null +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/BackButtonMenu.java @@ -0,0 +1,337 @@ +package org.telegram.ui.Components; + +import android.content.Context; +import android.graphics.Rect; +import android.graphics.drawable.Drawable; +import android.os.Bundle; +import android.text.TextUtils; +import android.util.TypedValue; +import android.view.Gravity; +import android.view.HapticFeedbackConstants; +import android.view.View; +import android.view.WindowManager; +import android.widget.FrameLayout; +import android.widget.TextView; + +import org.telegram.messenger.AndroidUtilities; +import org.telegram.messenger.ImageLocation; +import org.telegram.messenger.LocaleController; +import org.telegram.messenger.R; +import org.telegram.messenger.UserObject; +import org.telegram.tgnet.TLRPC; +import org.telegram.ui.ActionBar.ActionBarLayout; +import org.telegram.ui.ActionBar.ActionBarPopupWindow; +import org.telegram.ui.ActionBar.BaseFragment; +import org.telegram.ui.ActionBar.Theme; +import org.telegram.ui.ChatActivity; +import org.telegram.ui.ProfileActivity; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.concurrent.atomic.AtomicReference; + +public class BackButtonMenu { + public static class PulledDialog { + Class activity; + int stackIndex; + TLRPC.Chat chat; + TLRPC.User user; + long dialogId; + int folderId; + int filterId; + } + private static HashMap> pulledDialogs; + + public static ActionBarPopupWindow show(BaseFragment fragment, View backButton, long currentDialogId) { + if (fragment == null) { + return null; + } + final ActionBarLayout parentLayout = fragment.getParentLayout(); + ArrayList dialogs = getStackedHistoryDialogs(fragment.getCurrentAccount(), parentLayout == null ? null : parentLayout.fragmentsStack, currentDialogId); + if (dialogs.size() <= 0) { + return null; + } + + Context context = fragment.getParentActivity(); + ActionBarPopupWindow.ActionBarPopupWindowLayout layout = new ActionBarPopupWindow.ActionBarPopupWindowLayout(context); + android.graphics.Rect backgroundPaddings = new Rect(); + Drawable shadowDrawable = fragment.getParentActivity().getResources().getDrawable(R.drawable.popup_fixed_alert).mutate(); + shadowDrawable.getPadding(backgroundPaddings); + layout.setBackgroundColor(Theme.getColor(Theme.key_actionBarDefaultSubmenuBackground)); + + AtomicReference scrimPopupWindowRef = new AtomicReference<>(); + + for (int i = 0; i < dialogs.size(); ++i) { + final PulledDialog pDialog = dialogs.get(i); + final TLRPC.Chat chat = pDialog.chat; + final TLRPC.User user = pDialog.user; + FrameLayout cell = new FrameLayout(context); + cell.setMinimumWidth(AndroidUtilities.dp(200)); + + BackupImageView imageView = new BackupImageView(context); + imageView.setRoundRadius(AndroidUtilities.dp(32)); + cell.addView(imageView, LayoutHelper.createFrameRelatively(32, 32, Gravity.START | Gravity.CENTER_VERTICAL, 13, 0, 0, 0)); + + TextView titleView = new TextView(context); + titleView.setLines(1); + titleView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 16); + titleView.setTextColor(Theme.getColor(Theme.key_actionBarDefaultSubmenuItem)); + titleView.setEllipsize(TextUtils.TruncateAt.END); + cell.addView(titleView, LayoutHelper.createFrameRelatively(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.START | Gravity.CENTER_VERTICAL, 59, 0, 12, 0)); + + AvatarDrawable avatarDrawable = new AvatarDrawable(); + avatarDrawable.setSmallSize(true); + if (chat != null) { + avatarDrawable.setInfo(chat); + imageView.setImage(ImageLocation.getForChat(chat, ImageLocation.TYPE_SMALL), "50_50", avatarDrawable, chat); + titleView.setText(chat.title); + } else if (user != null) { + String name; + if (pDialog.activity == ChatActivity.class && UserObject.isUserSelf(user)) { + name = LocaleController.getString("SavedMessages", R.string.SavedMessages); + avatarDrawable.setAvatarType(AvatarDrawable.AVATAR_TYPE_SAVED); + imageView.setImageDrawable(avatarDrawable); + } else if (UserObject.isReplyUser(user)) { + name = LocaleController.getString("RepliesTitle", R.string.RepliesTitle); + avatarDrawable.setAvatarType(AvatarDrawable.AVATAR_TYPE_REPLIES); + imageView.setImageDrawable(avatarDrawable); + } else if (UserObject.isDeleted(user)) { + name = LocaleController.getString("HiddenName", R.string.HiddenName); + avatarDrawable.setInfo(user); + imageView.setImage(ImageLocation.getForUser(user, ImageLocation.TYPE_SMALL), "50_50", avatarDrawable, user); + } else { + name = UserObject.getUserName(user); + avatarDrawable.setInfo(user); + imageView.setImage(ImageLocation.getForUser(user, ImageLocation.TYPE_SMALL), "50_50", avatarDrawable, user); + } + titleView.setText(name); + } + + cell.setBackground(Theme.getSelectorDrawable(Theme.getColor(Theme.key_listSelector), false)); + cell.setOnClickListener(e2 -> { + if (scrimPopupWindowRef.get() != null) { + scrimPopupWindowRef.getAndSet(null).dismiss(); + } + if (pDialog.stackIndex >= 0) { + Long nextFragmentDialogId = null; + if (parentLayout == null || parentLayout.fragmentsStack == null || pDialog.stackIndex >= parentLayout.fragmentsStack.size()) { + nextFragmentDialogId = null; + } else { + BaseFragment nextFragment = parentLayout.fragmentsStack.get(pDialog.stackIndex); + if (nextFragment instanceof ChatActivity) { + nextFragmentDialogId = ((ChatActivity) nextFragment).getDialogId(); + } else if (nextFragment instanceof ProfileActivity) { + nextFragmentDialogId = ((ProfileActivity) nextFragment).getDialogId(); + } + } + if (nextFragmentDialogId != null && nextFragmentDialogId != pDialog.dialogId) { + for (int j = parentLayout.fragmentsStack.size() - 2; j > pDialog.stackIndex; --j) { + parentLayout.removeFragmentFromStack(j); + } + } else { + if (parentLayout != null && parentLayout.fragmentsStack != null) { + for (int j = parentLayout.fragmentsStack.size() - 2; j > pDialog.stackIndex; --j) { + if (j >= 0 && j < parentLayout.fragmentsStack.size()) { + parentLayout.removeFragmentFromStack(j); + } + } + if (pDialog.stackIndex < parentLayout.fragmentsStack.size()) { + parentLayout.showFragment(pDialog.stackIndex); + parentLayout.closeLastFragment(true); + return; + } + } + } + } + goToPulledDialog(fragment, pDialog); + }); + layout.addView(cell, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, 48)); + } + + ActionBarPopupWindow scrimPopupWindow = new ActionBarPopupWindow(layout, LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT); + scrimPopupWindowRef.set(scrimPopupWindow); + scrimPopupWindow.setPauseNotifications(true); + scrimPopupWindow.setDismissAnimationDuration(220); + scrimPopupWindow.setOutsideTouchable(true); + scrimPopupWindow.setClippingEnabled(true); + scrimPopupWindow.setAnimationStyle(R.style.PopupContextAnimation); + scrimPopupWindow.setFocusable(true); + layout.measure(View.MeasureSpec.makeMeasureSpec(AndroidUtilities.dp(1000), View.MeasureSpec.AT_MOST), View.MeasureSpec.makeMeasureSpec(AndroidUtilities.dp(1000), View.MeasureSpec.AT_MOST)); + scrimPopupWindow.setInputMethodMode(ActionBarPopupWindow.INPUT_METHOD_NOT_NEEDED); + scrimPopupWindow.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_UNSPECIFIED); + scrimPopupWindow.getContentView().setFocusableInTouchMode(true); + layout.setFitItems(true); + + View fragmentView = fragment.getFragmentView(); + if (fragmentView != null) { + int popupX = AndroidUtilities.dp(8) - backgroundPaddings.left; + if (AndroidUtilities.isTablet()) { + int[] location = new int[2]; + fragmentView.getLocationInWindow(location); + popupX += location[0]; + } + int popupY = (int) (backButton.getBottom() - backgroundPaddings.top - AndroidUtilities.dp(8)); + scrimPopupWindow.showAtLocation(fragmentView, Gravity.LEFT | Gravity.TOP, popupX, popupY); + + try { + fragmentView.performHapticFeedback(HapticFeedbackConstants.KEYBOARD_TAP, HapticFeedbackConstants.FLAG_IGNORE_GLOBAL_SETTING); + } catch (Exception ignore) {} + } + + return scrimPopupWindow; + } + + public static void goToPulledDialog(BaseFragment fragment, PulledDialog dialog) { + if (dialog == null) { + return; + } + if (dialog.activity == ChatActivity.class) { + Bundle bundle = new Bundle(); + if (dialog.chat != null) { + bundle.putLong("chat_id", dialog.chat.id); + } else if (dialog.user != null) { + bundle.putLong("user_id", dialog.user.id); + } + bundle.putInt("dialog_folder_id", dialog.folderId); + bundle.putInt("dialog_filter_id", dialog.filterId); + fragment.presentFragment(new ChatActivity(bundle), true); + } else if (dialog.activity == ProfileActivity.class) { + Bundle bundle = new Bundle(); + bundle.putLong("dialog_id", dialog.dialogId); + fragment.presentFragment(new ProfileActivity(bundle), true); + } + } + + public static ArrayList getStackedHistoryDialogs(int account, ArrayList fragmentsStack, long ignoreDialogId) { + ArrayList dialogs = new ArrayList<>(); + if (fragmentsStack != null) { + final int count = fragmentsStack.size(); + for (int i = 0; i < count; ++i) { + BaseFragment fragment = fragmentsStack.get(i); + Class activity; + TLRPC.Chat chat; + TLRPC.User user = null; + long dialogId; + int folderId, filterId; + if (fragment instanceof ChatActivity) { + activity = ChatActivity.class; + ChatActivity chatActivity = (ChatActivity) fragment; + if (chatActivity.getChatMode() != 0 || chatActivity.isReport()) { + continue; + } + chat = chatActivity.getCurrentChat(); + user = chatActivity.getCurrentUser(); + dialogId = chatActivity.getDialogId(); + folderId = chatActivity.getDialogFolderId(); + filterId = chatActivity.getDialogFilterId(); + } else if (fragment instanceof ProfileActivity) { + activity = ProfileActivity.class; + ProfileActivity profileActivity = (ProfileActivity) fragment; + chat = profileActivity.getCurrentChat(); + try { + user = profileActivity.getUserInfo().user; + } catch (Exception ignore) {} + dialogId = profileActivity.getDialogId(); + folderId = 0; + filterId = 0; + } else { + continue; + } + if (dialogId != ignoreDialogId && !(ignoreDialogId == 0 && UserObject.isUserSelf(user))) { + boolean alreadyAddedDialog = false; + for (int d = 0; d < dialogs.size(); ++d) { + if (dialogs.get(d).dialogId == dialogId) { + alreadyAddedDialog = true; + break; + } + } + if (!alreadyAddedDialog) { + PulledDialog pDialog = new PulledDialog(); + pDialog.activity = activity; + pDialog.stackIndex = i; + pDialog.chat = chat; + pDialog.user = user; + pDialog.dialogId = dialogId; + pDialog.folderId = folderId; + pDialog.filterId = filterId; + if (pDialog.chat != null || pDialog.user != null) { + dialogs.add(pDialog); + } + } + } + } + } + if (pulledDialogs != null) { + ArrayList pulledDialogsAccount = pulledDialogs.get(account); + if (pulledDialogsAccount != null) { + for (PulledDialog pulledDialog : pulledDialogsAccount) { + if (pulledDialog.dialogId == ignoreDialogId) { + continue; + } + boolean alreadyAddedDialog = false; + for (int d = 0; d < dialogs.size(); ++d) { + if (dialogs.get(d).dialogId == pulledDialog.dialogId) { + alreadyAddedDialog = true; + break; + } + } + if (!alreadyAddedDialog) { + dialogs.add(pulledDialog); + } + } + } + } + Collections.sort(dialogs, (d1, d2) -> d2.stackIndex - d1.stackIndex); + return dialogs; + } + + public static void addToPulledDialogs(int account, int stackIndex, TLRPC.Chat chat, TLRPC.User user, long dialogId, int folderId, int filterId) { + if (chat == null && user == null) { + return; + } + if (pulledDialogs == null) { + pulledDialogs = new HashMap<>(); + } + ArrayList dialogs = null; + if (pulledDialogs.containsKey(account)) { + dialogs = pulledDialogs.get(account); + } + if (dialogs == null) { + pulledDialogs.put(account, dialogs = new ArrayList<>()); + } + + boolean alreadyAdded = false; + for (PulledDialog d : dialogs) { + if (d.dialogId == dialogId) { + alreadyAdded = true; + break; + } + } + + if (!alreadyAdded) { + PulledDialog d = new PulledDialog(); + d.activity = ChatActivity.class; + d.stackIndex = stackIndex; + d.dialogId = dialogId; + d.filterId = filterId; + d.folderId = folderId; + d.chat = chat; + d.user = user; + dialogs.add(d); + } + } + public static void clearPulledDialogs(int account, int fromIndex) { + if (pulledDialogs != null && pulledDialogs.containsKey(account)) { + ArrayList dialogs = pulledDialogs.get(account); + if (dialogs != null) { + for (int i = 0; i < dialogs.size(); ++i) { + if (dialogs.get(i).stackIndex > fromIndex) { + dialogs.remove(i); + i--; + } + } + } + } + } +} diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/BulletinFactory.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/BulletinFactory.java index 32e1b6942..e9c9150f1 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/BulletinFactory.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/BulletinFactory.java @@ -45,7 +45,8 @@ public final class BulletinFactory { PHOTO_TO_DOWNLOADS("PhotoSavedToDownloadsHint", R.string.PhotoSavedToDownloadsHint, Icon.SAVED_TO_DOWNLOADS), VIDEO_TO_DOWNLOADS("VideoSavedToDownloadsHint", R.string.VideoSavedToDownloadsHint, Icon.SAVED_TO_DOWNLOADS), - GIF("GifSavedToDownloadsHint", Icon.SAVED_TO_DOWNLOADS), + GIF("GifSavedHint", R.string.GifSavedHint, Icon.SAVED_TO_GIFS), + GIF_TO_DOWNLOADS("GifSavedToDownloadsHint", R.string.GifSavedToDownloadsHint, Icon.SAVED_TO_DOWNLOADS), AUDIO("AudioSavedHint", R.string.AudioSavedHint, Icon.SAVED_TO_MUSIC), AUDIOS("AudiosSavedHint", Icon.SAVED_TO_MUSIC), @@ -88,7 +89,8 @@ public final class BulletinFactory { SAVED_TO_DOWNLOADS(R.raw.ic_download, 2, "Box", "Arrow"), SAVED_TO_GALLERY(R.raw.ic_save_to_gallery, 0, "Box", "Arrow", "Mask", "Arrow 2", "Splash"), - SAVED_TO_MUSIC(R.raw.ic_save_to_music, 2, "Box", "Arrow"); + SAVED_TO_MUSIC(R.raw.ic_save_to_music, 2, "Box", "Arrow"), + SAVED_TO_GIFS(R.raw.ic_save_to_gifs, 0, "gif"); private final int resId; private final String[] layers; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/ChatActivityEnterView.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/ChatActivityEnterView.java index 1a24f9546..9b93f157a 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/ChatActivityEnterView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/ChatActivityEnterView.java @@ -2003,7 +2003,7 @@ public class ChatActivityEnterView extends ChatBlurredFrameLayout implements Not } private void editPhoto(Uri uri, String mime) { - final File file = AndroidUtilities.generatePicturePath(fragment.isSecretChat(), MimeTypeMap.getSingleton().getExtensionFromMimeType(mime)); + final File file = AndroidUtilities.generatePicturePath(fragment != null && fragment.isSecretChat(), MimeTypeMap.getSingleton().getExtensionFromMimeType(mime)); Utilities.globalQueue.postRunnable(() -> { try { InputStream in = context.getContentResolver().openInputStream(uri); @@ -7332,6 +7332,10 @@ public class ChatActivityEnterView extends ChatBlurredFrameLayout implements Not return audioVideoButtonContainer; } + public View getEmojiButton() { + return emojiButton[0]; + } + public EmojiView getEmojiView() { return emojiView; } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/EmojiView.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/EmojiView.java index 34b615545..cb47059aa 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/EmojiView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/EmojiView.java @@ -2330,8 +2330,25 @@ public class EmojiView extends FrameLayout implements NotificationCenter.Notific @Override public void setTranslationY(float translationY) { super.setTranslationY(translationY); - updateBottomTabContainerPosition(); updateStickerTabsPosition(); + updateBottomTabContainerPosition(); + } + private void updateBottomTabContainerPosition() { + if (bottomTabContainer.getTag() == null && (delegate == null || !delegate.isSearchOpened()) && (pager == null || pager.getCurrentItem() != 0)) { + View parent = (View) getParent(); + if (parent != null) { + float y = getY() - parent.getHeight(); + if (getLayoutParams().height > 0) { + y += getLayoutParams().height; + } else { + y += getMeasuredHeight(); + } + if (bottomTabContainer.getTop() - y < 0) { + y = bottomTabContainer.getTop(); + } + bottomTabContainer.setTranslationY(-y); + } + } } Rect rect = new Rect(); @@ -2367,24 +2384,6 @@ public class EmojiView extends FrameLayout implements NotificationCenter.Notific } } - private void updateBottomTabContainerPosition() { - if (bottomTabContainer.getTag() == null && (delegate == null || !delegate.isSearchOpened())) { - View parent = (View) getParent(); - if (parent != null) { - float y = getY() - parent.getHeight(); - if (getLayoutParams().height > 0) { - y += getLayoutParams().height; - } else { - y += getMeasuredHeight(); - } - if (bottomTabContainer.getTop() - y < 0) { - y = bottomTabContainer.getTop(); - } - bottomTabContainer.setTranslationY(-y); - } - } - } - @Override protected void dispatchDraw(Canvas canvas) { updateBottomTabContainerPosition(); @@ -3646,11 +3645,11 @@ public class EmojiView extends FrameLayout implements NotificationCenter.Notific if (newHeight <= lastNotifyHeight) { bottomTabContainer.setTranslationY(0); } else { - float y = getY() + getMeasuredHeight() - parent.getHeight(); - if (bottomTabContainer.getTop() - y < 0) { - y = bottomTabContainer.getTop(); - } - bottomTabContainer.setTranslationY(-y); +// float y = getY() + getMeasuredHeight() - parent.getHeight() - bottomTabContainer.getTop(); +// if (bottomTabContainer.getTop() - y < 0) { +// y = bottomTabContainer.getTop(); +// } +// bottomTabContainer.setTranslationY(-y); } } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/FragmentContextView.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/FragmentContextView.java index d5409321e..e7d03c2cd 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/FragmentContextView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/FragmentContextView.java @@ -1050,6 +1050,7 @@ public class FragmentContextView extends FrameLayout implements NotificationCent } else if (fragment instanceof ChatActivity && ((ChatActivity) fragment).getGroupCall() != null && ((ChatActivity) fragment).getGroupCall().shouldShowPanel() && !GroupCallPip.isShowing() && !isPlayingVoice()) { checkCall(true); } else { + checkCall(true); checkPlayer(true); updatePlaybackButton(); } @@ -1786,6 +1787,10 @@ public class FragmentContextView extends FrameLayout implements NotificationCent visible = false; setVisibility(GONE); } + + if (create && fragment instanceof ChatActivity && ((ChatActivity) fragment).openedWithLivestream() && !GroupCallPip.isShowing()) { + BulletinFactory.of(fragment).createSimpleBulletin(R.raw.linkbroken, LocaleController.getString("InviteExpired", R.string.InviteExpired)).show(); + } } else { int newStyle; if (groupActive) { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/GroupedPhotosListView.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/GroupedPhotosListView.java index 0fa1172ee..dbcb4e8a8 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/GroupedPhotosListView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/GroupedPhotosListView.java @@ -129,7 +129,7 @@ public class GroupedPhotosListView extends View implements GestureDetector.OnGes } MessageObject messageObject = imagesArr.get(currentIndex); currentObject = messageObject; - long localGroupId = delegate.validGroupId(messageObject.getGroupIdForUse()) ? messageObject.getGroupIdForUse() : 0; + long localGroupId = messageObject.getGroupIdForUse(); if (localGroupId != currentGroupId) { changed = true; currentGroupId = localGroupId; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/JoinCallAlert.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/JoinCallAlert.java index 43cda3602..caa2932bc 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/JoinCallAlert.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/JoinCallAlert.java @@ -438,6 +438,7 @@ public class JoinCallAlert extends BottomSheet { listView.setVerticalScrollBarEnabled(false); listView.setClipToPadding(false); listView.setEnabled(true); + listView.setSelectorDrawableColor(0); listView.setGlowColor(Theme.getColor(Theme.key_dialogScrollGlow)); listView.setOnScrollListener(new RecyclerView.OnScrollListener() { @Override diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/LinkPath.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/LinkPath.java index e73dae90e..6110e7e95 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/LinkPath.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/LinkPath.java @@ -8,11 +8,11 @@ package org.telegram.ui.Components; +import android.graphics.CornerPathEffect; import android.graphics.Path; import android.graphics.RectF; import android.os.Build; import android.text.Layout; -import android.text.StaticLayout; import org.telegram.messenger.AndroidUtilities; @@ -28,10 +28,10 @@ public class LinkPath extends Path { private boolean allowReset = true; private int baselineShift; private int lineHeight; - private ArrayList rects = new ArrayList<>(); - private final int radius = AndroidUtilities.dp(4); - private final int halfRadius = radius >> 1; + private static final int radius = AndroidUtilities.dp(4); + private static final int halfRadius = radius >> 1; + public static final CornerPathEffect roundedEffect = new CornerPathEffect(radius); public LinkPath() { super(); @@ -108,9 +108,7 @@ public class LinkPath extends Path { y += baselineShift; } if (useRoundRect) { - RectF rect = new RectF(); - rect.set(left - halfRadius, y, right + halfRadius, y2); - rects.add(rect); + super.addRect(left - halfRadius, y, right + halfRadius, y2, dir); } else { super.addRect(left, y, right, y2, dir); } @@ -122,34 +120,5 @@ public class LinkPath extends Path { return; } super.reset(); - rects.clear(); - } - - private boolean containsPoint(float x, float y) { - for (RectF rect : rects) { - if (rect.contains(x, y)) { - return true; - } - } - return false; - } - - public void onPathEnd() { - if (useRoundRect) { - super.reset(); - final int count = rects.size(); - for (int i = 0; i < count; ++i) { - float[] radii = new float[8]; - - RectF rect = rects.get(i); - - radii[0] = radii[1] = containsPoint(rect.left, rect.top - radius) ? 0 : radius; // top left - radii[2] = radii[3] = containsPoint(rect.right, rect.top - radius) ? 0 : radius; // top right - radii[4] = radii[5] = containsPoint(rect.right, rect.bottom + radius) ? 0 : radius; // bottom right - radii[6] = radii[7] = containsPoint(rect.left, rect.bottom + radius) ? 0 : radius; // bottom left - - super.addRoundRect(rect, radii, Direction.CW); - } - } } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/RLottieDrawable.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/RLottieDrawable.java index ef9c0fc36..d97f07756 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/RLottieDrawable.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/RLottieDrawable.java @@ -211,12 +211,18 @@ public class RLottieDrawable extends BitmapDrawable implements Animatable { } protected void recycleResources() { - if (renderingBitmap != null) { - renderingBitmap.recycle(); + try { + if (renderingBitmap != null) { + renderingBitmap.recycle(); + renderingBitmap = null; + } + if (backgroundBitmap != null) { + backgroundBitmap.recycle(); + backgroundBitmap = null; + } + } catch (Exception e) { + FileLog.e(e); renderingBitmap = null; - } - if (backgroundBitmap != null) { - backgroundBitmap.recycle(); backgroundBitmap = null; } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/ReactedHeaderView.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/ReactedHeaderView.java index 0a1b2cfa9..a7b7c0ee0 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/ReactedHeaderView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/ReactedHeaderView.java @@ -100,7 +100,7 @@ public class ReactedHeaderView extends FrameLayout { MessagesController ctrl = MessagesController.getInstance(currentAccount); TLRPC.Chat chat = ctrl.getChat(message.getChatId()); TLRPC.ChatFull chatInfo = ctrl.getChatFull(message.getChatId()); - boolean showSeen = chat != null && message.isOutOwner() && message.isSent() && !message.isEditing() && !message.isSending() && !message.isSendError() && !message.isContentUnread() && !message.isUnread() && (ConnectionsManager.getInstance(currentAccount).getCurrentTime() - message.messageOwner.date < 7 * 86400) && (ChatObject.isMegagroup(chat) || !ChatObject.isChannel(chat)) && chatInfo != null && chatInfo.participants_count < MessagesController.getInstance(currentAccount).chatReadMarkSizeThreshold && !(message.messageOwner.action instanceof TLRPC.TL_messageActionChatJoinedByRequest); + boolean showSeen = chat != null && message.isOutOwner() && message.isSent() && !message.isEditing() && !message.isSending() && !message.isSendError() && !message.isContentUnread() && !message.isUnread() && (ConnectionsManager.getInstance(currentAccount).getCurrentTime() - message.messageOwner.date < 7 * 86400) && (ChatObject.isMegagroup(chat) || !ChatObject.isChannel(chat)) && chatInfo != null && chatInfo.participants_count <= MessagesController.getInstance(currentAccount).chatReadMarkSizeThreshold && !(message.messageOwner.action instanceof TLRPC.TL_messageActionChatJoinedByRequest); if (showSeen) { TLRPC.TL_messages_getMessageReadParticipants req = new TLRPC.TL_messages_getMessageReadParticipants(); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/Reactions/ReactionsEffectOverlay.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/Reactions/ReactionsEffectOverlay.java index 642546b75..0966fbf2b 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/Reactions/ReactionsEffectOverlay.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/Reactions/ReactionsEffectOverlay.java @@ -12,16 +12,23 @@ import android.widget.FrameLayout; import org.telegram.messenger.AndroidUtilities; import org.telegram.messenger.ImageLocation; +import org.telegram.messenger.ImageReceiver; import org.telegram.messenger.MediaDataController; +import org.telegram.messenger.MessageObject; import org.telegram.messenger.MessagesController; import org.telegram.tgnet.TLRPC; import org.telegram.ui.ActionBar.BaseFragment; import org.telegram.ui.Cells.ChatMessageCell; import org.telegram.ui.ChatActivity; +import org.telegram.ui.Components.AvatarDrawable; import org.telegram.ui.Components.BackupImageView; import org.telegram.ui.Components.CubicBezierInterpolator; +import org.telegram.ui.Components.RLottieDrawable; import org.telegram.ui.Components.ReactionsContainerLayout; +import java.util.ArrayList; +import java.util.Random; + public class ReactionsEffectOverlay { public final static int LONG_ANIMATION = 0; @@ -31,6 +38,7 @@ public class ReactionsEffectOverlay { private final int animationType; @SuppressLint("StaticFieldLeak") public static ReactionsEffectOverlay currentOverlay; + @SuppressLint("StaticFieldLeak") public static ReactionsEffectOverlay currentShortOverlay; private final AnimationView effectImageView; @@ -63,6 +71,9 @@ public class ReactionsEffectOverlay { private boolean finished; private boolean useWindow; private ViewGroup decorView; + private static long lastHapticTime; + ArrayList avatars = new ArrayList<>(); + private ReactionsEffectOverlay(Context context, BaseFragment fragment, ReactionsContainerLayout reactionsLayout, ChatMessageCell cell, float x, float y, String reaction, int currentAccount, int animationType) { this.fragment = fragment; @@ -83,6 +94,82 @@ public class ReactionsEffectOverlay { } } } + + if (animationType == SHORT_ANIMATION) { + Random random = new Random(); + ArrayList recentReactions = null; + if (cell.getMessageObject().messageOwner.reactions != null) { + recentReactions = cell.getMessageObject().messageOwner.reactions.recent_reactions; + } + if (recentReactions != null) { + for (int i = 0; i < recentReactions.size(); i++) { + if (reaction.equals(recentReactions.get(i).reaction) && recentReactions.get(i).unread) { + TLRPC.User user; + TLRPC.Chat chat; + + AvatarDrawable avatarDrawable = new AvatarDrawable(); + ImageReceiver imageReceiver = new ImageReceiver(); + long peerId = MessageObject.getPeerId(recentReactions.get(i).peer_id); + if (peerId < 0) { + chat = MessagesController.getInstance(currentAccount).getChat(-peerId); + if (chat == null) { + continue; + } + avatarDrawable.setInfo(chat); + imageReceiver.setForUserOrChat(chat, avatarDrawable); + } else { + user = MessagesController.getInstance(currentAccount).getUser(peerId); + if (user == null) { + continue; + } + avatarDrawable.setInfo(user); + imageReceiver.setForUserOrChat(user, avatarDrawable); + } + + AvatarParticle avatarParticle = new AvatarParticle(); + avatarParticle.imageReceiver = imageReceiver; + avatarParticle.fromX = 0.5f;// + Math.abs(random.nextInt() % 100) / 100f * 0.2f; + avatarParticle.fromY = 0.5f;// + Math.abs(random.nextInt() % 100) / 100f * 0.2f; + avatarParticle.jumpY = 0.3f + Math.abs(random.nextInt() % 100) / 100f * 0.1f; + avatarParticle.randomScale = 0.8f + Math.abs(random.nextInt() % 100) / 100f * 0.4f; + avatarParticle.randomRotation = 60 * Math.abs(random.nextInt() % 100) / 100f; + avatarParticle.leftTime = (int) (400 + Math.abs(random.nextInt() % 100) / 100f * 200); + + if (avatars.isEmpty()) { + avatarParticle.toX = 0.2f + 0.6f * Math.abs(random.nextInt() % 100) / 100f; + avatarParticle.toY = 0.4f * Math.abs(random.nextInt() % 100) / 100f; + } else { + float bestDistance = 0; + float bestX = 0; + float bestY = 0; + for (int k = 0; k < 10; k++) { + float randX = 0.2f + 0.6f * Math.abs(random.nextInt() % 100) / 100f; + float randY = 0.2f + 0.4f * Math.abs(random.nextInt() % 100) / 100f; + float minDistance = Integer.MAX_VALUE; + for (int j = 0; j < avatars.size(); j++) { + float rx = avatars.get(j).toX - randX; + float ry = avatars.get(j).toY - randY; + float distance = rx * rx + ry * ry; + if (distance < minDistance) { + minDistance = distance; + } + } + if (minDistance > bestDistance) { + bestDistance = minDistance; + bestX = randX; + bestY = randY; + } + } + avatarParticle.toX = bestX; + avatarParticle.toY = bestY; + } + + avatars.add(avatarParticle); + } + } + } + } + boolean fromHolder = holderView != null || (x != 0 && y != 0); if (holderView != null) { holderView.getLocationOnScreen(loc); @@ -306,8 +393,90 @@ public class ReactionsEffectOverlay { } } + + if (!avatars.isEmpty() && effectImageView.wasPlaying) { + RLottieDrawable animation = effectImageView.getImageReceiver().getLottieAnimation(); + + for (int i = 0; i < avatars.size(); i++) { + AvatarParticle particle = avatars.get(i); + float progress = particle.progress; + boolean isLeft; + if (animation != null && animation.isRunning()) { + long duration = effectImageView.getImageReceiver().getLottieAnimation().getDuration(); + int totalFramesCount = effectImageView.getImageReceiver().getLottieAnimation().getFramesCount(); + int currentFrame = effectImageView.getImageReceiver().getLottieAnimation().getCurrentFrame(); + int timeLeft = (int) (duration - duration * (currentFrame / (float) totalFramesCount)); + isLeft = timeLeft < particle.leftTime; + } else { + isLeft = true; + } + + if (isLeft && particle.outProgress != 1f) { + particle.outProgress += 16f / 150f; + if (particle.outProgress > 1f) { + particle.outProgress = 1f; + } + } + float jumpProgress = progress < 0.5f ? (progress / 0.5f) : (1f - ((progress - 0.5f) / 0.5f)); + float avatarX = particle.fromX * (1f - progress) + particle.toX * progress; + float avatarY = particle.fromY * (1f - progress) + particle.toY * progress - particle.jumpY * jumpProgress; + + float s = progress * particle.randomScale * (1f - particle.outProgress); + float cx = effectImageView.getX() + (effectImageView.getWidth() * effectImageView.getScaleX()) * avatarX; + float cy = effectImageView.getY() + (effectImageView.getHeight() * effectImageView.getScaleY()) * avatarY; + int size = AndroidUtilities.dp(16); + avatars.get(i).imageReceiver.setImageCoords(cx - size / 2f, cy - size / 2f, size, size); + avatars.get(i).imageReceiver.setRoundRadius(size >> 1); + canvas.save(); + canvas.translate(0, particle.globalTranslationY); + canvas.scale(s, s, cx, cy); + canvas.rotate(particle.currentRotation, cx, cy); + + avatars.get(i).imageReceiver.draw(canvas); + canvas.restore(); + + if (particle.progress < 1f) { + particle.progress += 16f / 350f; + if (particle.progress > 1f) { + particle.progress = 1f; + } + } + if (progress >= 1f) { + particle.globalTranslationY += AndroidUtilities.dp(20) * 16f / 500f; + } + + if (particle.incrementRotation) { + particle.currentRotation += particle.randomRotation / 250f; + if (particle.currentRotation > particle.randomRotation) { + particle.incrementRotation = false; + } + } else { + particle.currentRotation -= particle.randomRotation / 250f; + if (particle.currentRotation < -particle.randomRotation) { + particle.incrementRotation = true; + } + } + } + } + invalidate(); } + + @Override + protected void onAttachedToWindow() { + super.onAttachedToWindow(); + for (int i = 0; i < avatars.size(); i++) { + avatars.get(i).imageReceiver.onAttachedToWindow(); + } + } + + @Override + protected void onDetachedFromWindow() { + super.onDetachedFromWindow(); + for (int i = 0; i < avatars.size(); i++) { + avatars.get(i).imageReceiver.onDetachedFromWindow(); + } + } }; effectImageView = new AnimationView(context); emojiImageView = new AnimationView(context); @@ -461,6 +630,10 @@ public class ReactionsEffectOverlay { public static void startAnimation() { if (currentOverlay != null) { currentOverlay.started = true; + if (currentOverlay.animationType == LONG_ANIMATION && System.currentTimeMillis() - lastHapticTime > 200) { + lastHapticTime = System.currentTimeMillis(); + currentOverlay.cell.performHapticFeedback(HapticFeedbackConstants.KEYBOARD_TAP); + } } else { startShortAnimation(); if (currentShortOverlay != null) { @@ -472,7 +645,8 @@ public class ReactionsEffectOverlay { public static void startShortAnimation() { if (currentShortOverlay != null && !currentShortOverlay.started) { currentShortOverlay.started = true; - if (currentShortOverlay.animationType == SHORT_ANIMATION) { + if (currentShortOverlay.animationType == SHORT_ANIMATION && System.currentTimeMillis() - lastHapticTime > 200) { + lastHapticTime = System.currentTimeMillis(); currentShortOverlay.cell.performHapticFeedback(HapticFeedbackConstants.KEYBOARD_TAP); } } @@ -534,4 +708,23 @@ public class ReactionsEffectOverlay { } } } + + private class AvatarParticle { + ImageReceiver imageReceiver; + + public int leftTime; + float progress; + float outProgress; + float jumpY; + float fromX; + float fromY; + float toX; + float toY; + float randomScale; + float randomRotation; + float currentRotation; + boolean incrementRotation; + float globalTranslationY; + + } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/Reactions/ReactionsLayoutInBubble.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/Reactions/ReactionsLayoutInBubble.java index 38bb66dc4..0b3935947 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/Reactions/ReactionsLayoutInBubble.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/Reactions/ReactionsLayoutInBubble.java @@ -9,8 +9,7 @@ import android.view.MotionEvent; import android.view.ViewConfiguration; import androidx.core.graphics.ColorUtils; - -import com.google.android.exoplayer2.util.Log; +import androidx.recyclerview.widget.ChatListItemAnimator; import org.telegram.messenger.AndroidUtilities; import org.telegram.messenger.ApplicationLoader; @@ -560,6 +559,8 @@ public class ReactionsLayoutInBubble { if (users != null) { if (avatarsDarawable == null) { avatarsDarawable = new AvatarsDarawable(parentView, false); + avatarsDarawable.transitionDuration = ChatListItemAnimator.DEFAULT_DURATION; + avatarsDarawable.transitionInterpolator = ChatListItemAnimator.DEFAULT_INTERPOLATOR; avatarsDarawable.setSize(AndroidUtilities.dp(20)); avatarsDarawable.width = AndroidUtilities.dp(100); avatarsDarawable.height = height; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/ReactionsContainerLayout.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/ReactionsContainerLayout.java index ce7975147..45af7dca5 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/ReactionsContainerLayout.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/ReactionsContainerLayout.java @@ -51,7 +51,6 @@ import java.util.ArrayList; import java.util.Collections; import java.util.HashSet; import java.util.List; -import java.util.Random; public class ReactionsContainerLayout extends FrameLayout implements NotificationCenter.NotificationCenterDelegate { public final static Property TRANSITION_PROGRESS_VALUE = new Property(Float.class, "transitionProgress") { @@ -66,8 +65,6 @@ public class ReactionsContainerLayout extends FrameLayout implements Notificatio } }; - private final static Random RANDOM = new Random(); - private final static int ALPHA_DURATION = 150; private final static float SIDE_SCALE = 0.6f; private final static float SCALE_PROGRESS = 0.75f; @@ -127,7 +124,7 @@ public class ReactionsContainerLayout extends FrameLayout implements Notificatio recyclerListView = new RecyclerListView(context) { @Override public boolean drawChild(Canvas canvas, View child, long drawingTime) { - if (pressedReaction != null && ((ReactionHolderView) child).currentReaction.equals(pressedReaction)) { + if (pressedReaction != null && ((ReactionHolderView) child).currentReaction.reaction.equals(pressedReaction)) { return true; } return super.drawChild(canvas, child, drawingTime); @@ -377,7 +374,17 @@ public class ReactionsContainerLayout extends FrameLayout implements Notificatio } canvas.save(); - canvas.translate(recyclerListView.getX() + view.getX(), recyclerListView.getY() + view.getY()); + float x = recyclerListView.getX() + view.getX(); + float additionalWidth = (view.getMeasuredWidth() * view.getScaleX() - view.getMeasuredWidth()) / 2f; + if (x - additionalWidth < 0) { + view.setTranslationX(-(x - additionalWidth)); + } else if (x + view.getMeasuredWidth() + additionalWidth > getMeasuredWidth()) { + view.setTranslationX(getMeasuredWidth() - x - view.getMeasuredWidth() - additionalWidth); + } else { + view.setTranslationX(0); + } + x = recyclerListView.getX() + view.getX(); + canvas.translate(x, recyclerListView.getY() + view.getY()); canvas.scale(view.getScaleX(), view.getScaleY(), view.getPivotX(), view.getPivotY()); view.draw(canvas); canvas.restore(); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/ShareAlert.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/ShareAlert.java index b5d0e6756..7a0ac7072 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/ShareAlert.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/ShareAlert.java @@ -914,8 +914,7 @@ public class ShareAlert extends BottomSheet implements NotificationCenter.Notifi return y >= AndroidUtilities.dp(darkTheme && linkToCopy[1] != null ? 111 : 58) + (Build.VERSION.SDK_INT >= 21 ? AndroidUtilities.statusBarHeight : 0); } }; - gridView.setSelectorRadius(AndroidUtilities.dp(8)); - gridView.setSelectorDrawableColor(Theme.getColor(Theme.key_listSelector)); + gridView.setSelectorDrawableColor(0); gridView.setPadding(0, 0, 0, AndroidUtilities.dp(48)); gridView.setClipToPadding(false); gridView.setLayoutManager(layoutManager = new GridLayoutManager(getContext(), 4)); @@ -975,6 +974,7 @@ public class ShareAlert extends BottomSheet implements NotificationCenter.Notifi return y >= AndroidUtilities.dp(darkTheme && linkToCopy[1] != null ? 111 : 58) + (Build.VERSION.SDK_INT >= 21 ? AndroidUtilities.statusBarHeight : 0); } }; + searchGridView.setSelectorDrawableColor(0); searchGridView.setPadding(0, 0, 0, AndroidUtilities.dp(48)); searchGridView.setClipToPadding(false); searchGridView.setLayoutManager(searchLayoutManager = new FillLastGridLayoutManager(getContext(), 4, 0, searchGridView)); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/SharedMediaLayout.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/SharedMediaLayout.java index 9152647c8..d8b456f4e 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/SharedMediaLayout.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/SharedMediaLayout.java @@ -2234,6 +2234,9 @@ public class SharedMediaLayout extends FrameLayout implements NotificationCenter } private void updateForwardItem() { + if (forwardItem == null) { + return; + } boolean noforwards = profileActivity.getMessagesController().isChatNoForwards(-dialog_id); forwardItem.setAlpha(noforwards ? 0.5f : 1f); forwardNoQuoteItem.setAlpha(noforwards ? 0.5f : 1f); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/SizeNotifierFrameLayout.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/SizeNotifierFrameLayout.java index 8e4f56a14..7aade5614 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/SizeNotifierFrameLayout.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/SizeNotifierFrameLayout.java @@ -87,7 +87,6 @@ public class SizeNotifierFrameLayout extends FrameLayout { @Override protected void onDraw(Canvas canvas) { if (backgroundDrawable == null || skipBackgroundDrawing) { - super.onDraw(canvas); return; } Drawable newDrawable = getNewDrawable(); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/StaticLayoutEx.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/StaticLayoutEx.java index 544851294..ea87796c8 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/StaticLayoutEx.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/StaticLayoutEx.java @@ -172,6 +172,7 @@ public class StaticLayoutEx { .setAlignment(align) .setLineSpacing(spacingAdd, spacingMult) .setIncludePad(includePad) + .setEllipsize(ellipsize) .setEllipsizedWidth(ellipsisWidth) .setMaxLines(maxLines) .setBreakStrategy(canContainUrl ? StaticLayout.BREAK_STRATEGY_HIGH_QUALITY : StaticLayout.BREAK_STRATEGY_SIMPLE) diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/VideoPlayer.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/VideoPlayer.java index a25621ab3..a47569917 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/VideoPlayer.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/VideoPlayer.java @@ -163,7 +163,7 @@ public class VideoPlayer implements ExoPlayer.EventListener, SimpleExoPlayer.Vid } } - private void ensurePleyaerCreated() { + private void ensurePlayerCreated() { DefaultLoadControl loadControl = new DefaultLoadControl( new DefaultAllocator(true, C.DEFAULT_BUFFER_SEGMENT_SIZE), DefaultLoadControl.DEFAULT_MIN_BUFFER_MS, @@ -266,7 +266,7 @@ public class VideoPlayer implements ExoPlayer.EventListener, SimpleExoPlayer.Vid mixedAudio = true; audioPlayerReady = false; videoPlayerReady = false; - ensurePleyaerCreated(); + ensurePlayerCreated(); MediaSource mediaSource1 = null, mediaSource2 = null; for (int a = 0; a < 2; a++) { MediaSource mediaSource; @@ -316,7 +316,7 @@ public class VideoPlayer implements ExoPlayer.EventListener, SimpleExoPlayer.Vid currentUri = uri; String scheme = uri.getScheme(); isStreaming = scheme != null && !scheme.startsWith("file"); - ensurePleyaerCreated(); + ensurePlayerCreated(); MediaSource mediaSource; switch (type) { case "dash": diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/spoilers/SpoilerEffect.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/spoilers/SpoilerEffect.java index fb98247ec..1512b7175 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/spoilers/SpoilerEffect.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/spoilers/SpoilerEffect.java @@ -715,6 +715,7 @@ public class SpoilerEffect extends Drawable { public static void renderWithRipple(View v, boolean invalidateSpoilersParent, int spoilersColor, int verticalOffset, AtomicReference patchedLayoutRef, Layout textLayout, List spoilers, Canvas canvas) { if (spoilers.isEmpty()) { textLayout.draw(canvas); + return; } Layout pl = patchedLayoutRef.get(); @@ -751,8 +752,9 @@ public class SpoilerEffect extends Drawable { .setAlignment(Layout.Alignment.ALIGN_NORMAL) .setLineSpacing(textLayout.getSpacingAdd(), textLayout.getSpacingMultiplier()) .build(); - } else + } else { layout = new StaticLayout(sb, textLayout.getPaint(), textLayout.getWidth(), textLayout.getAlignment(), textLayout.getSpacingMultiplier(), textLayout.getSpacingAdd(), false); + } patchedLayoutRef.set(pl = layout); } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/voip/AcceptDeclineView.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/voip/AcceptDeclineView.java index e6678e7d0..5e8396268 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/voip/AcceptDeclineView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/voip/AcceptDeclineView.java @@ -213,7 +213,7 @@ public class AcceptDeclineView extends View { leftAnimator = animator; if (listener != null) { if ((!startDrag && Math.abs(dy) < touchSlop && !screenWasWakeup) || leftOffsetX > maxOffset * 0.8f) { - listener.onDicline(); + listener.onDecline(); } } } else { @@ -387,7 +387,7 @@ public class AcceptDeclineView extends View { public interface Listener { void onAccept(); - void onDicline(); + void onDecline(); } public void setRetryMod(boolean retryMod) { @@ -481,7 +481,7 @@ public class AcceptDeclineView extends View { if (virtualViewId == ACCEPT_VIEW_ID) { listener.onAccept(); } else if (virtualViewId == DECLINE_VIEW_ID) { - listener.onDicline(); + listener.onDecline(); } } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/voip/VoIPFloatingLayout.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/voip/VoIPFloatingLayout.java index a6bdd4436..8825892d1 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/voip/VoIPFloatingLayout.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/voip/VoIPFloatingLayout.java @@ -534,7 +534,7 @@ public class VoIPFloatingLayout extends FrameLayout { active = b; } - public void saveRelatedPosition() { + public void saveRelativePosition() { if (getMeasuredWidth() > 0 && relativePositionToSetX < 0) { ViewParent parent = getParent(); if (parent == null) { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/voip/VoIPTextureView.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/voip/VoIPTextureView.java index 2207c30d2..434588d69 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/voip/VoIPTextureView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/voip/VoIPTextureView.java @@ -363,9 +363,7 @@ public class VoIPTextureView extends FrameLayout { super.onMeasure(widthMeasureSpec, heightMeasureSpec); updateRendererSize(); super.onMeasure(widthMeasureSpec, heightMeasureSpec); - if (!applyRotation) { - renderer.updateRotation(); - } + renderer.updateRotation(); } protected void updateRendererSize() { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ContentPreviewViewer.java b/TMessagesProj/src/main/java/org/telegram/ui/ContentPreviewViewer.java index ac30691ea..83f36da70 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ContentPreviewViewer.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ContentPreviewViewer.java @@ -762,7 +762,11 @@ public class ContentPreviewViewer { } currentStickerSet = newSet; TLRPC.PhotoSize thumb = FileLoader.getClosestPhotoSizeWithSize(document.thumbs, 90); - centerImage.setImage(ImageLocation.getForDocument(document), null, ImageLocation.getForDocument(thumb, document), null, "webp", currentStickerSet, 1); + if (MessageObject.isVideoStickerDocument(document)) { + centerImage.setImage(ImageLocation.getForDocument(document), null, ImageLocation.getForDocument(thumb, document), null, null, 0, "webp", currentStickerSet, 1); + } else { + centerImage.setImage(ImageLocation.getForDocument(document), null, ImageLocation.getForDocument(thumb, document), null, "webp", currentStickerSet, 1); + } for (int a = 0; a < document.attributes.size(); a++) { TLRPC.DocumentAttribute attribute = document.attributes.get(a); if (attribute instanceof TLRPC.TL_documentAttributeSticker) { @@ -1002,5 +1006,4 @@ public class ContentPreviewViewer { Integer color = resourcesProvider != null ? resourcesProvider.getColor(key) : null; return color != null ? color : Theme.getColor(key); } - } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/LanguageSelectActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/LanguageSelectActivity.java index be2b07059..55190e84b 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/LanguageSelectActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/LanguageSelectActivity.java @@ -9,6 +9,9 @@ package org.telegram.ui; import android.content.Context; +import android.content.DialogInterface; +import android.content.SharedPreferences; +import android.content.res.Configuration; import android.view.View; import android.view.ViewGroup; import android.widget.EditText; @@ -40,6 +43,7 @@ import org.telegram.ui.Components.RecyclerListView; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; +import java.util.HashSet; import java.util.Timer; import kotlin.Unit; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/LaunchActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/LaunchActivity.java index d3d2158da..ba300e2d4 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/LaunchActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/LaunchActivity.java @@ -49,6 +49,7 @@ import android.view.MotionEvent; import android.view.View; import android.view.ViewAnimationUtils; import android.view.ViewGroup; +import android.view.ViewParent; import android.view.ViewTreeObserver; import android.view.Window; import android.view.WindowManager; @@ -99,6 +100,7 @@ import org.telegram.messenger.camera.CameraController; import org.telegram.messenger.voip.VideoCapturerDevice; import org.telegram.messenger.voip.VoIPPendingCall; import org.telegram.messenger.voip.VoIPService; +import org.telegram.tgnet.AbstractSerializedData; import org.telegram.tgnet.ConnectionsManager; import org.telegram.tgnet.TLObject; import org.telegram.tgnet.TLRPC; @@ -1642,6 +1644,7 @@ public class LaunchActivity extends Activity implements ActionBarLayout.ActionBa String phone = null; String game = null; String voicechat = null; + String livestream = null; String phoneHash = null; String lang = null; String theme = null; @@ -1831,6 +1834,7 @@ public class LaunchActivity extends Activity implements ActionBarLayout.ActionBa botChat = data.getQueryParameter("startgroup"); game = data.getQueryParameter("game"); voicechat = data.getQueryParameter("voicechat"); + livestream = data.getQueryParameter("livestream"); threadId = Utilities.parseInt(data.getQueryParameter("thread")); if (threadId == 0) { threadId = null; @@ -1868,6 +1872,7 @@ public class LaunchActivity extends Activity implements ActionBarLayout.ActionBa botChat = data.getQueryParameter("startgroup"); game = data.getQueryParameter("game"); voicechat = data.getQueryParameter("voicechat"); + livestream = data.getQueryParameter("livestream"); messageId = Utilities.parseInt(data.getQueryParameter("post")); if (messageId == 0) { messageId = null; @@ -2183,7 +2188,7 @@ public class LaunchActivity extends Activity implements ActionBarLayout.ActionBa if (message != null && message.startsWith("@")) { message = " " + message; } - runLinkRequest(intentAccount[0], username, group, sticker, botUser, botChat, message, hasUrl, messageId, channelId, threadId, commentId, game, auth, lang, unsupportedUrl, code, login, wallPaper, theme, voicechat, internal ? 3 : 0, videoTimestamp); + runLinkRequest(intentAccount[0], username, group, sticker, botUser, botChat, message, hasUrl, messageId, channelId, threadId, commentId, game, auth, lang, unsupportedUrl, code, login, wallPaper, theme, voicechat, livestream, internal ? 3 : 0, videoTimestamp); } else { try (Cursor cursor = getContentResolver().query(intent.getData(), null, null, null, null)) { if (cursor != null) { @@ -2858,6 +2863,7 @@ public class LaunchActivity extends Activity implements ActionBarLayout.ActionBa final TLRPC.TL_wallPaper wallPaper, final String theme, final String voicechat, + final String livestream, final int state, final int videoTimestamp) { if (state == 0 && UserConfig.getActivatedAccountsCount() >= 2) { @@ -2865,7 +2871,7 @@ public class LaunchActivity extends Activity implements ActionBarLayout.ActionBa if (account != intentAccount) { switchToAccount(account, true); } - runLinkRequest(account, username, group, sticker, botUser, botChat, message, hasUrl, messageId, channelId, threadId, commentId, game, auth, lang, unsupportedUrl, code, loginToken, wallPaper, theme, voicechat, 1, videoTimestamp); + runLinkRequest(account, username, group, sticker, botUser, botChat, message, hasUrl, messageId, channelId, threadId, commentId, game, auth, lang, unsupportedUrl, code, loginToken, wallPaper, theme, voicechat, livestream, 1, videoTimestamp); }).show(); return; } else if (code != null) { @@ -2934,7 +2940,7 @@ public class LaunchActivity extends Activity implements ActionBarLayout.ActionBa if (!LaunchActivity.this.isFinishing()) { boolean hideProgressDialog = true; final TLRPC.TL_contacts_resolvedPeer res = (TLRPC.TL_contacts_resolvedPeer) response; - if (error == null && actionBarLayout != null && (game == null && voicechat == null || game != null && !res.users.isEmpty() || voicechat != null && !res.chats.isEmpty())) { + if (error == null && actionBarLayout != null && (game == null && voicechat == null || game != null && !res.users.isEmpty() || voicechat != null && !res.chats.isEmpty() || livestream != null && !res.chats.isEmpty())) { MessagesController.getInstance(intentAccount).putUsers(res.users, false); MessagesController.getInstance(intentAccount).putChats(res.chats, false); MessagesStorage.getInstance(intentAccount).putUsersAndChats(res.users, res.chats, false, true); @@ -3047,6 +3053,9 @@ public class LaunchActivity extends Activity implements ActionBarLayout.ActionBa if (voicechat != null) { args.putString("voicechat", voicechat); } + if (livestream != null) { + args.putString("livestream", livestream); + } if (videoTimestamp >= 0) { args.putInt("video_timestamp", videoTimestamp); } @@ -3746,23 +3755,25 @@ public class LaunchActivity extends Activity implements ActionBarLayout.ActionBa return; } if (SharedConfig.isAppUpdateAvailable()) { + View prevUpdateLayout = updateLayout; createUpdateUI(); updateSizeTextView.setText(AndroidUtilities.formatFileSize(SharedConfig.pendingAppUpdate.document.size)); String fileName = FileLoader.getAttachFileName(SharedConfig.pendingAppUpdate.document); File path = FileLoader.getPathToAttach(SharedConfig.pendingAppUpdate.document, true); boolean showSize; if (path.exists()) { - updateLayoutIcon.setIcon(MediaActionDrawable.ICON_UPDATE, true, animated); + updateLayoutIcon.setIcon(MediaActionDrawable.ICON_UPDATE, true, false); updateTextView.setText(LocaleController.getString("AppUpdateNow", R.string.AppUpdateNow)); showSize = false; } else { if (FileLoader.getInstance(currentAccount).isLoadingFile(fileName)) { - updateLayoutIcon.setIcon(MediaActionDrawable.ICON_CANCEL, true, animated); + updateLayoutIcon.setIcon(MediaActionDrawable.ICON_CANCEL, true, false); + updateLayoutIcon.setProgress(0, false); Float p = ImageLoader.getInstance().getFileProgress(fileName); updateTextView.setText(LocaleController.formatString("AppUpdateDownloading", R.string.AppUpdateDownloading, (int) ((p != null ? p : 0.0f) * 100))); showSize = false; } else { - updateLayoutIcon.setIcon(MediaActionDrawable.ICON_DOWNLOAD, true, animated); + updateLayoutIcon.setIcon(MediaActionDrawable.ICON_DOWNLOAD, true, false); updateTextView.setText(LocaleController.getString("AppUpdate", R.string.AppUpdate)); showSize = true; } @@ -3796,9 +3807,18 @@ public class LaunchActivity extends Activity implements ActionBarLayout.ActionBa updateLayout.setVisibility(View.VISIBLE); updateLayout.setTag(1); if (animated) { - updateLayout.animate().translationY(0).setInterpolator(CubicBezierInterpolator.EASE_OUT).setListener(null).setDuration(180).start(); + updateLayout.animate().translationY(0).setInterpolator(CubicBezierInterpolator.EASE_OUT).setListener(null).setDuration(180).withEndAction(() -> { + if (prevUpdateLayout != null) { + ViewGroup parent = (ViewGroup) prevUpdateLayout.getParent(); + parent.removeView(prevUpdateLayout); + } + }).start(); } else { updateLayout.setTranslationY(0); + if (prevUpdateLayout != null) { + ViewGroup parent = (ViewGroup) prevUpdateLayout.getParent(); + parent.removeView(prevUpdateLayout); + } } sideMenu.setPadding(0, 0, 0, AndroidUtilities.dp(44)); } else { @@ -4027,11 +4047,17 @@ public class LaunchActivity extends Activity implements ActionBarLayout.ActionBa final long did = dids.get(i); AccountInstance accountInstance = AccountInstance.getInstance(UserConfig.selectedAccount); + boolean photosEditorOpened = false; if (fragment != null) { actionBarLayout.presentFragment(fragment, dialogsFragment != null, dialogsFragment == null, true, false); if (videoPath != null) { fragment.openVideoEditor(videoPath, sendingText); sendingText = null; + } else if (photoPathsArray != null && photoPathsArray.size() > 0) { + photosEditorOpened = fragment.openPhotosEditor(photoPathsArray, message == null || message.length() == 0 ? sendingText : message); + if (photosEditorOpened) { + sendingText = null; + } } } else { if (videoPath != null) { @@ -4044,7 +4070,7 @@ public class LaunchActivity extends Activity implements ActionBarLayout.ActionBa SendMessagesHelper.prepareSendingDocuments(accountInstance, arrayList, arrayList, null, captionToSend, null, did, null, null, null, null, true, 0); } } - if (photoPathsArray != null) { + if (photoPathsArray != null && !photosEditorOpened) { if (sendingText != null && sendingText.length() <= 1024 && photoPathsArray.size() == 1) { photoPathsArray.get(0).caption = sendingText; sendingText = null; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/MessageEnterTransitionContainer.java b/TMessagesProj/src/main/java/org/telegram/ui/MessageEnterTransitionContainer.java index 048c41780..2fc32253c 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/MessageEnterTransitionContainer.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/MessageEnterTransitionContainer.java @@ -1,9 +1,9 @@ package org.telegram.ui; import android.annotation.SuppressLint; -import android.content.Context; import android.graphics.Canvas; import android.view.View; +import android.view.ViewGroup; import org.telegram.messenger.NotificationCenter; @@ -14,11 +14,13 @@ public class MessageEnterTransitionContainer extends View { private ArrayList transitions = new ArrayList<>(); private final int currentAccount; + private final ViewGroup parent; Runnable hideRunnable = () -> setVisibility(View.GONE); - public MessageEnterTransitionContainer(Context context, int currentAccount) { - super(context); + public MessageEnterTransitionContainer(ViewGroup parent, int currentAccount) { + super(parent.getContext()); + this.parent = parent; this.currentAccount = currentAccount; } @@ -29,11 +31,13 @@ public class MessageEnterTransitionContainer extends View { void addTransition(Transition transition) { transitions.add(transition); checkVisibility(); + parent.invalidate(); } void removeTransition(Transition transition) { transitions.remove(transition); checkVisibility(); + parent.invalidate(); } @Override @@ -55,4 +59,8 @@ public class MessageEnterTransitionContainer extends View { setVisibility(View.VISIBLE); } } + + public boolean isRunning() { + return transitions.size() > 0; + } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/MessageSeenView.java b/TMessagesProj/src/main/java/org/telegram/ui/MessageSeenView.java index adaa63831..1d2e274ae 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/MessageSeenView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/MessageSeenView.java @@ -126,7 +126,7 @@ public class MessageSeenView extends FrameLayout { } else { if (ChatObject.isChannel(chat)) { TLRPC.TL_channels_getParticipants usersReq = new TLRPC.TL_channels_getParticipants(); - usersReq.limit = 50; + usersReq.limit = MessagesController.getInstance(currentAccount).chatReadMarkSizeThreshold; usersReq.offset = 0; usersReq.filter = new TLRPC.TL_channelParticipantsRecent(); usersReq.channel = MessagesController.getInstance(currentAccount).getInputChannel(chat.id); @@ -185,6 +185,10 @@ public class MessageSeenView extends FrameLayout { @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + View parent = (View) getParent(); + if (parent != null && parent.getWidth() > 0) { + widthMeasureSpec = MeasureSpec.makeMeasureSpec(parent.getWidth(), MeasureSpec.EXACTLY); + } if (flickerLoadingView.getVisibility() == View.VISIBLE) { ignoreLayout = true; flickerLoadingView.setVisibility(View.GONE); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/PhotoViewer.java b/TMessagesProj/src/main/java/org/telegram/ui/PhotoViewer.java index 665c40a10..58d7b103b 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/PhotoViewer.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/PhotoViewer.java @@ -104,6 +104,7 @@ import android.view.VelocityTracker; import android.view.View; import android.view.ViewConfiguration; import android.view.ViewGroup; +import android.view.ViewPropertyAnimator; import android.view.ViewTreeObserver; import android.view.WindowInsets; import android.view.WindowManager; @@ -428,6 +429,8 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat private View flashView; private AnimatorSet flashAnimator; private TextureView videoTextureView; + private boolean firstFrameSet = false; + private ImageView firstFrameView; private VideoPlayer videoPlayer; private boolean manuallyPaused; private Runnable videoPlayRunnable; @@ -806,6 +809,9 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat if (isCurrentVideo) { if (!videoTimelineView.isDragging()) { float progress = videoPlayer.getCurrentPosition() / (float) videoPlayer.getDuration(); + if (shownControlsByEnd && !actionBarWasShownBeforeByEnd) { + progress = 0; + } if (!inPreview && (currentEditMode != 0 || videoTimelineView.getVisibility() == View.VISIBLE)) { if (progress >= videoTimelineView.getRightProgress()) { videoTimelineView.setProgress(videoTimelineView.getLeftProgress()); @@ -828,6 +834,9 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat } } else { float progress = videoPlayer.getCurrentPosition() / (float) videoPlayer.getDuration(); + if (shownControlsByEnd && !actionBarWasShownBeforeByEnd) { + progress = 0; + } float bufferedProgress; if (currentVideoFinishedLoading) { bufferedProgress = 1.0f; @@ -883,6 +892,7 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat } updateVideoPlayerTime(); } + updateFirstFrameView(); } if (isPlaying) { AndroidUtilities.runOnUIThread(updateProgressRunnable, 17); @@ -4349,6 +4359,11 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat MediaDataController.getInstance(currentAccount).addRecentGif(document, (int) (System.currentTimeMillis() / 1000)); MessagesController.getInstance(currentAccount).saveGif(pageBlocksAdapter.getParentObject(), document); } + } else { + return; + } + if (containerView != null) { + BulletinFactory.of(containerView, resourcesProvider).createDownloadBulletin(BulletinFactory.FileType.GIF, resourcesProvider).show(); } } else if (id == gallery_menu_set_as_main) { TLRPC.Photo photo = avatarsArr.get(currentIndex); @@ -6455,6 +6470,9 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat textureImageView.setTranslationY(fromY2); videoTextureView.setTranslationY(fromY); + if (firstFrameView != null) { + firstFrameView.setTranslationY(fromY); + } translationY = 0; containerView.invalidate(); @@ -6477,6 +6495,13 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat videoTextureView.setTranslationX(fromX * (1f - xValue) + (toX2) * xValue); videoTextureView.setTranslationY(fromY * (1f - yValue) + (toY2) * yValue); + + if (firstFrameView != null) { + firstFrameView.setTranslationX(videoTextureView.getTranslationX()); + firstFrameView.setTranslationY(videoTextureView.getTranslationY()); + firstFrameView.setScaleX(videoTextureView.getScaleX()); + firstFrameView.setScaleY(videoTextureView.getScaleY()); + } }); AnimatorSet animatorSet = new AnimatorSet(); @@ -6569,6 +6594,12 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat videoTextureView.setScaleY(scale); videoTextureView.setTranslationX(rect.x - aspectRatioFrameLayout.getX()); videoTextureView.setTranslationY(rect.y - aspectRatioFrameLayout.getY()); + if (firstFrameView != null) { + firstFrameView.setScaleX(scale); + firstFrameView.setScaleY(scale); + firstFrameView.setTranslationX(videoTextureView.getTranslationX()); + firstFrameView.setTranslationY(videoTextureView.getTranslationY()); + } } else { pipVideoView.close(); pipVideoView = null; @@ -6986,6 +7017,9 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat Arrays.fill(videoPlayerTotalTime, 0); if (videoPlayer != null) { long current = Math.max(0, videoPlayer.getCurrentPosition()); + if (shownControlsByEnd && !actionBarWasShownBeforeByEnd) { + current = 0; + } long total = Math.max(0, videoPlayer.getDuration()); if (!inPreview && videoTimelineView.getVisibility() == View.VISIBLE) { total *= (videoTimelineView.getRightProgress() - videoTimelineView.getLeftProgress()); @@ -7364,6 +7398,7 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat if (videoTextureView != null) { videoPlayer.setTextureView(videoTextureView); } + firstFrameSet = false; videoPlayer.setDelegate(new VideoPlayer.VideoPlayerDelegate() { @Override public void onStateChanged(boolean playWhenReady, int playbackState) { @@ -7419,6 +7454,11 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat textureUploaded = true; containerView.invalidate(); } + + if (videoTextureView != null && !firstFrameSet && videoPlayer.getCurrentPosition() <= 60) { + firstFrameView.setImageBitmap(videoTextureView.getBitmap()); + firstFrameSet = true; + } } @Override @@ -7464,19 +7504,28 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat pipPosition[1] -= containerView.getTranslationY(); textureImageView.setTranslationX(textureImageView.getTranslationX() + getLeftInset()); videoTextureView.setTranslationX(videoTextureView.getTranslationX() + getLeftInset() - aspectRatioFrameLayout.getX()); + if (firstFrameView != null) { + firstFrameView.setTranslationX(videoTextureView.getTranslationX()); + } AnimatorSet animatorSet = new AnimatorSet(); - animatorSet.playTogether( - ObjectAnimator.ofFloat(textureImageView, View.SCALE_X, 1.0f), - ObjectAnimator.ofFloat(textureImageView, View.SCALE_Y, 1.0f), - ObjectAnimator.ofFloat(textureImageView, View.TRANSLATION_X, pipPosition[0]), - ObjectAnimator.ofFloat(textureImageView, View.TRANSLATION_Y, pipPosition[1]), - ObjectAnimator.ofFloat(videoTextureView, View.SCALE_X, 1.0f), - ObjectAnimator.ofFloat(videoTextureView, View.SCALE_Y, 1.0f), - ObjectAnimator.ofFloat(videoTextureView, View.TRANSLATION_X, pipPosition[0] - aspectRatioFrameLayout.getX()), - ObjectAnimator.ofFloat(videoTextureView, View.TRANSLATION_Y, pipPosition[1] - aspectRatioFrameLayout.getY()), - ObjectAnimator.ofInt(backgroundDrawable, AnimationProperties.COLOR_DRAWABLE_ALPHA, 255) - ); + ArrayList animators = new ArrayList<>(); + animators.add(ObjectAnimator.ofFloat(textureImageView, View.SCALE_X, 1.0f)); + animators.add(ObjectAnimator.ofFloat(textureImageView, View.SCALE_Y, 1.0f)); + animators.add(ObjectAnimator.ofFloat(textureImageView, View.TRANSLATION_X, pipPosition[0])); + animators.add(ObjectAnimator.ofFloat(textureImageView, View.TRANSLATION_Y, pipPosition[1])); + animators.add(ObjectAnimator.ofFloat(videoTextureView, View.SCALE_X, 1.0f)); + animators.add(ObjectAnimator.ofFloat(videoTextureView, View.SCALE_Y, 1.0f)); + animators.add(ObjectAnimator.ofFloat(videoTextureView, View.TRANSLATION_X, pipPosition[0] - aspectRatioFrameLayout.getX())); + animators.add(ObjectAnimator.ofFloat(videoTextureView, View.TRANSLATION_Y, pipPosition[1] - aspectRatioFrameLayout.getY())); + animators.add(ObjectAnimator.ofInt(backgroundDrawable, AnimationProperties.COLOR_DRAWABLE_ALPHA, 255)); + if (firstFrameView != null) { + animators.add(ObjectAnimator.ofFloat(firstFrameView, View.SCALE_X, 1.0f)); + animators.add(ObjectAnimator.ofFloat(firstFrameView, View.SCALE_Y, 1.0f)); + animators.add(ObjectAnimator.ofFloat(firstFrameView, View.TRANSLATION_X, pipPosition[0] - aspectRatioFrameLayout.getX())); + animators.add(ObjectAnimator.ofFloat(firstFrameView, View.TRANSLATION_Y, pipPosition[1] - aspectRatioFrameLayout.getY())); + } + animatorSet.playTogether(animators); final DecelerateInterpolator interpolator = new DecelerateInterpolator(); animatorSet.setInterpolator(interpolator); animatorSet.setDuration(250); @@ -7668,12 +7717,15 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat } if (videoTextureView instanceof VideoEditTextureView) { videoTextureView.setPivotX(videoTextureView.getMeasuredWidth() / 2); + firstFrameView.setPivotX(videoTextureView.getMeasuredWidth() / 2); } else { videoTextureView.setPivotX(0); + firstFrameView.setPivotX(0); } checkFullscreenButton(); } }; + aspectRatioFrameLayout.setWillNotDraw(false); aspectRatioFrameLayout.setVisibility(View.INVISIBLE); containerView.addView(aspectRatioFrameLayout, 0, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, Gravity.CENTER)); @@ -7697,6 +7749,12 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat videoTextureView.setOpaque(false); aspectRatioFrameLayout.addView(videoTextureView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, Gravity.CENTER)); + firstFrameView = new ImageView(parentActivity); + firstFrameView.setPivotX(0); + firstFrameView.setPivotY(0); + firstFrameView.setScaleType(ImageView.ScaleType.FIT_XY); + aspectRatioFrameLayout.addView(firstFrameView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, Gravity.CENTER)); + if (sendPhotoType == SELECT_TYPE_AVATAR) { flashView = new View(parentActivity); flashView.setBackgroundColor(0xffffffff); @@ -7705,6 +7763,51 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat } } + private final static float firstFrameFadeDuration = 200; + private boolean shownControlsByEnd = false; + private boolean actionBarWasShownBeforeByEnd = false; + private ViewPropertyAnimator firstFrameViewAnimator = null; + private void updateFirstFrameView() { + if (videoPlayer != null && firstFrameView != null) { + long toDuration = videoPlayer.getDuration() - videoPlayer.getCurrentPosition(); + float alpha = 1f - Math.max(Math.min(toDuration / firstFrameFadeDuration, 1), 0); + if (!videoPlayer.isPlaying()) { + if (firstFrameViewAnimator != null) { + firstFrameViewAnimator.cancel(); + firstFrameViewAnimator = null; + } + firstFrameView.clearAnimation(); + firstFrameView.setAlpha(alpha); + } else { + if (toDuration <= firstFrameFadeDuration) { + if (firstFrameViewAnimator == null) { + firstFrameView.setAlpha(alpha); + firstFrameViewAnimator = firstFrameView.animate().alpha(1).withEndAction(() -> { + if (firstFrameViewAnimator != null) { + firstFrameViewAnimator.cancel(); + firstFrameViewAnimator = null; + } + }).setDuration(Math.max(0, toDuration)); + firstFrameViewAnimator.start(); + } + } else { + firstFrameView.setAlpha(alpha); + } + } + if (!videoPlayer.isLooping()) { + if (!shownControlsByEnd && videoPlayer.getCurrentPosition() > videoPlayer.getDuration() - firstFrameFadeDuration) { + actionBarWasShownBeforeByEnd = isActionBarVisible; + shownControlsByEnd = true; + toggleActionBar(true, true); + checkProgress(0, false, false); + } else if (videoPlayer.getCurrentPosition() < videoPlayer.getDuration() - firstFrameFadeDuration) { + shownControlsByEnd = false; + actionBarWasShownBeforeByEnd = false; + } + } + } + } + private void releasePlayer(boolean onClose) { if (videoPlayer != null) { cancelVideoPlayRunnable(); @@ -9774,6 +9877,7 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat containerView.setTag(1); playerAutoStarted = false; isCurrentVideo = false; + shownControlsByEnd = false; imagesArr.clear(); imagesArrLocations.clear(); imagesArrLocationsSizes.clear(); @@ -10223,6 +10327,7 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat nameTextView.setText(""); dateTextView.setText(""); } else { + allowShare = !noforwards; if (newMessageObject.isNewGif() && allowShare) { menuItem.showSubItem(gallery_menu_savegif); } @@ -10713,11 +10818,12 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat if (switchingToIndex < 0 || switchingToIndex >= size) { return; } + allowShare = !MessagesController.getInstance(currentAccount).isChatNoForwards(-currentDialogId); TLRPC.PageBlock pageBlock = pageBlocksAdapter.get(switchingToIndex); caption = pageBlocksAdapter.getCaption(switchingToIndex); isVideo = pageBlocksAdapter.isVideo(switchingToIndex); if (isVideo) { - if (!MessagesController.getInstance(currentAccount).isChatNoForwards(-currentDialogId)) { + if (allowShare) { menuItem.showSubItem(gallery_menu_openin); } else { menuItem.hideSubItem(gallery_menu_openin); @@ -10739,7 +10845,6 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat } bottomLayout.setTag(null); - allowShare = !MessagesController.getInstance(currentAccount).isChatNoForwards(-currentDialogId); shareItem.setVisibility(allowShare ? View.VISIBLE : View.GONE); if (currentAnimation != null) { @@ -11483,6 +11588,10 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat } boolean existsFinal = exists; AndroidUtilities.runOnUIThread(() -> { + if (shownControlsByEnd && !actionBarWasShownBeforeByEnd && isPlaying) { + photoProgressViews[a].setBackgroundState(PROGRESS_PLAY, false, false); + return; + } if ((f1Final != null || f2Final != null) && (existsFinal || canStreamFinal)) { if (a != 0 || !isPlaying) { if (isVideoFinal && (!canAutoPlayFinal || a == 0 && playerWasPlaying)) { @@ -13209,6 +13318,7 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat selectedPhotosAdapter.notifyDataSetChanged(); pageBlocksAdapter = null; disableShowCheck = false; + shownControlsByEnd = false; videoCutStart = 0; videoCutEnd = 1f; if (object != null) { @@ -14177,6 +14287,9 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat if (currentEditMode == 1 || sendPhotoType == SELECT_TYPE_AVATAR) { if (videoTextureView != null) { videoTextureView.setScaleX(cropTransform.isMirrored() ? -1.0f : 1.0f); + if (firstFrameView != null) { + firstFrameView.setScaleX(videoTextureView.getScaleX()); + } } float trueScale = 1.0f + (cropTransform.getTrueCropScale() - 1.0f) * (1.0f - cropAnimationValue); cropScale = cropTransform.getScale() / trueScale; @@ -14195,6 +14308,9 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat } else { if (videoTextureView != null) { videoTextureView.setScaleX(editState.cropState != null && editState.cropState.mirrored ? -1.0f : 1.0f); + if (firstFrameView != null) { + firstFrameView.setScaleX(videoTextureView.getScaleX()); + } } cropScale = editState.cropState != null ? editState.cropState.cropScale : 1.0f; float trueScale = 1.0f + (cropScale - 1.0f) * (1.0f - cropAnimationValue); @@ -14217,6 +14333,10 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat if (videoTextureView != null) { videoTextureView.setScaleX(1.0f); videoTextureView.setScaleY(1.0f); + if (firstFrameView != null) { + firstFrameView.setScaleX(1); + firstFrameView.setScaleY(1); + } } } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ProfileActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/ProfileActivity.java index 6f128ee4c..cf06b3b1f 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ProfileActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ProfileActivity.java @@ -144,6 +144,7 @@ import org.telegram.ui.Components.AnimatedFileDrawable; import org.telegram.ui.Components.AnimationProperties; import org.telegram.ui.Components.AudioPlayerAlert; import org.telegram.ui.Components.AvatarDrawable; +import org.telegram.ui.Components.BackButtonMenu; import org.telegram.ui.Components.BackupImageView; import org.telegram.ui.Components.BulletinFactory; import org.telegram.ui.Components.ChatAvatarContainer; @@ -1557,126 +1558,17 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. actionBar.setOccupyStatusBar(Build.VERSION.SDK_INT >= 21 && !AndroidUtilities.isTablet() && !inBubbleMode); ImageView backButton = actionBar.getBackButton(); backButton.setOnLongClickListener(e -> { - ArrayList dialogs = ChatActivity.getStackedHistoryDialogs(currentAccount, getParentLayout().fragmentsStack, dialogId); - if (dialogs.size() <= 0) { + ActionBarPopupWindow menu = BackButtonMenu.show(this, backButton, getDialogId()); + if (menu != null) { + menu.setOnDismissListener(() -> dimBehindView(false)); + dimBehindView(backButton, 0.3f); + if (undoView != null) { + undoView.hide(true, 1); + } + return true; + } else { return false; } - - ActionBarPopupWindow.ActionBarPopupWindowLayout layout = new ActionBarPopupWindow.ActionBarPopupWindowLayout(context); - Rect backgroundPaddings = new Rect(); - Drawable shadowDrawable = getParentActivity().getResources().getDrawable(R.drawable.popup_fixed_alert).mutate(); - shadowDrawable.getPadding(backgroundPaddings); - layout.setBackgroundColor(getThemedColor(Theme.key_actionBarDefaultSubmenuBackground)); - - for (int i = 0; i < dialogs.size(); ++i) { - final ChatActivity.PulledDialog pDialog = dialogs.get(i); - final TLRPC.Chat chat = pDialog.chat; - final TLRPC.User user = pDialog.user; - FrameLayout cell = new FrameLayout(context); - cell.setMinimumWidth(AndroidUtilities.dp(200)); - - BackupImageView imageView = new BackupImageView(context); - imageView.setRoundRadius(AndroidUtilities.dp(32)); - cell.addView(imageView, LayoutHelper.createFrameRelatively(32, 32, Gravity.START | Gravity.CENTER_VERTICAL, 13, 0, 0, 0)); - - TextView titleView = new TextView(context); - titleView.setLines(1); - titleView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 16); - titleView.setTextColor(Theme.getColor(Theme.key_actionBarDefaultSubmenuItem)); - titleView.setEllipsize(TextUtils.TruncateAt.END); - cell.addView(titleView, LayoutHelper.createFrameRelatively(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.START | Gravity.CENTER_VERTICAL, 59, 0, 12, 0)); - - AvatarDrawable avatarDrawable = new AvatarDrawable(); - if (chat != null) { - avatarDrawable.setInfo(chat); - imageView.setImage(ImageLocation.getForChat(chat, ImageLocation.TYPE_SMALL), "50_50", avatarDrawable, chat); - titleView.setText(chat.title); - } else if (user != null) { - avatarDrawable.setInfo(user); - imageView.setImage(ImageLocation.getForUser(user, ImageLocation.TYPE_SMALL), "50_50", avatarDrawable, user); - titleView.setText(UserObject.getUserName(user)); - } - - boolean isFirst = i == 0, isLast = i == dialogs.size() - 1; - cell.setBackground(Theme.getSelectorDrawable(Theme.getColor(Theme.key_listSelector), false)); - cell.setOnClickListener(e2 -> { - if (scrimPopupWindow != null) { - scrimPopupWindow.dismiss(); - } - if (pDialog.stackIndex >= 0) { - final ActionBarLayout parentLayout = getParentLayout(); - BaseFragment fragment; - if (parentLayout == null || parentLayout.fragmentsStack == null || pDialog.stackIndex >= parentLayout.fragmentsStack.size()) { - fragment = null; - } else { - fragment = parentLayout.fragmentsStack.get(pDialog.stackIndex); - } - if (fragment instanceof ChatActivity && ((ChatActivity) fragment).getDialogId() != pDialog.dialogId) { - for (int j = parentLayout.fragmentsStack.size() - 2; j > pDialog.stackIndex; --j) { - parentLayout.removeFragmentFromStack(j); - } - } else { - if (parentLayout != null && parentLayout.fragmentsStack != null) { - for (int j = parentLayout.fragmentsStack.size() - 2; j > pDialog.stackIndex; --j) { - if (j >= 0 && j < parentLayout.fragmentsStack.size()) { - parentLayout.removeFragmentFromStack(j); - } - } - if (pDialog.stackIndex < parentLayout.fragmentsStack.size()) { - parentLayout.showFragment(pDialog.stackIndex); - parentLayout.closeLastFragment(true); - return; - } - } - } - } - ChatActivity.goTo(this, chat != null ? chat : user, pDialog.dialogId, pDialog.folderId, pDialog.filterId); - }); -// layout.addView(cell, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, 44 + (isFirst ? 4 : 0) + (isLast ? 4 : 0))); - layout.addView(cell, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, 44, 0, isFirst ? 4 : 0, 0, isLast ? 4 : 0)); - } - - scrimPopupWindow = new ActionBarPopupWindow(layout, LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT) { - @Override - public void dismiss() { - super.dismiss(); - if (scrimPopupWindow != this) { - return; - } - scrimPopupWindow = null; - dimBehindView(false); - } - }; - scrimPopupWindow.setPauseNotifications(true); - scrimPopupWindow.setDismissAnimationDuration(220); - scrimPopupWindow.setOutsideTouchable(true); - scrimPopupWindow.setClippingEnabled(true); - scrimPopupWindow.setAnimationStyle(R.style.PopupContextAnimation); - scrimPopupWindow.setFocusable(true); - layout.measure(View.MeasureSpec.makeMeasureSpec(AndroidUtilities.dp(1000), View.MeasureSpec.AT_MOST), View.MeasureSpec.makeMeasureSpec(AndroidUtilities.dp(1000), View.MeasureSpec.AT_MOST)); - scrimPopupWindow.setInputMethodMode(ActionBarPopupWindow.INPUT_METHOD_NOT_NEEDED); - scrimPopupWindow.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_UNSPECIFIED); - scrimPopupWindow.getContentView().setFocusableInTouchMode(true); - layout.setFitItems(true); - - int popupX = AndroidUtilities.dp(8) - backgroundPaddings.left; - if (AndroidUtilities.isTablet()) { - int[] location = new int[2]; - fragmentView.getLocationInWindow(location); - popupX += location[0]; - } - int popupY = (int) (backButton.getBottom() - backgroundPaddings.top - AndroidUtilities.dp(8)); - final int finalPopupX = popupX; - final int finalPopupY = popupY; - scrimPopupWindow.showAtLocation(fragmentView, Gravity.LEFT | Gravity.TOP, finalPopupX, finalPopupY); - try { - actionBar.performHapticFeedback(HapticFeedbackConstants.KEYBOARD_TAP, HapticFeedbackConstants.FLAG_IGNORE_GLOBAL_SETTING); - } catch (Exception ignore) {} - dimBehindView(backButton, 0.3f); - if (undoView != null) { - undoView.hide(true, 1); - } - return true; }); return actionBar; } @@ -3972,6 +3864,9 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. public TLRPC.Chat getCurrentChat() { return currentChat; } + public TLRPC.UserFull getUserInfo() { + return userInfo; + } @Override public boolean isFragmentOpened() { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ReadAllMentionsMenu.java b/TMessagesProj/src/main/java/org/telegram/ui/ReadAllMentionsMenu.java new file mode 100644 index 000000000..2bbb5f79d --- /dev/null +++ b/TMessagesProj/src/main/java/org/telegram/ui/ReadAllMentionsMenu.java @@ -0,0 +1,53 @@ +package org.telegram.ui; + +import android.app.Activity; +import android.view.Gravity; +import android.view.View; +import android.view.WindowManager; +import android.widget.FrameLayout; + +import org.telegram.messenger.AndroidUtilities; +import org.telegram.messenger.LocaleController; +import org.telegram.messenger.R; +import org.telegram.ui.ActionBar.ActionBarMenuSubItem; +import org.telegram.ui.ActionBar.ActionBarPopupWindow; +import org.telegram.ui.ActionBar.Theme; +import org.telegram.ui.Components.LayoutHelper; + +public class ReadAllMentionsMenu { + + public final static int TYPE_REACTIONS = 0; + public final static int TYPE_MENTIONS = 1; + + public static ActionBarPopupWindow show(int type, Activity activity, FrameLayout contentView, View mentionButton, Theme.ResourcesProvider resourcesProvider, Runnable onRead) { + ActionBarPopupWindow.ActionBarPopupWindowLayout popupWindowLayout = new ActionBarPopupWindow.ActionBarPopupWindowLayout(activity); + popupWindowLayout.setMinimumWidth(AndroidUtilities.dp(200)); + + ActionBarMenuSubItem cell = new ActionBarMenuSubItem(activity, true,true, resourcesProvider); + cell.setMinimumWidth(AndroidUtilities.dp(200)); + cell.setTextAndIcon(type == TYPE_REACTIONS ? LocaleController.getString("ReadAllReactions", R.string.ReadAllReactions) : LocaleController.getString("ReadAllMentions", R.string.ReadAllMentions) , R.drawable.msg_seen); + cell.setOnClickListener(view -> { + if (onRead != null) { + onRead.run(); + } + }); + popupWindowLayout.addView(cell); + + ActionBarPopupWindow scrimPopupWindow = new ActionBarPopupWindow(popupWindowLayout, LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT); + scrimPopupWindow.setPauseNotifications(true); + scrimPopupWindow.setDismissAnimationDuration(220); + scrimPopupWindow.setOutsideTouchable(true); + scrimPopupWindow.setClippingEnabled(true); + scrimPopupWindow.setAnimationStyle(R.style.PopupContextAnimation); + scrimPopupWindow.setFocusable(true); + popupWindowLayout.measure(View.MeasureSpec.makeMeasureSpec(AndroidUtilities.dp(1000), View.MeasureSpec.AT_MOST), View.MeasureSpec.makeMeasureSpec(AndroidUtilities.dp(1000), View.MeasureSpec.AT_MOST)); + scrimPopupWindow.setInputMethodMode(ActionBarPopupWindow.INPUT_METHOD_NOT_NEEDED); + scrimPopupWindow.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_UNSPECIFIED); + scrimPopupWindow.getContentView().setFocusableInTouchMode(true); + + float x = mentionButton.getX() + mentionButton.getWidth() - popupWindowLayout.getMeasuredWidth() + AndroidUtilities.dp(8); + float y = mentionButton.getY() - popupWindowLayout.getMeasuredHeight(); + scrimPopupWindow.showAtLocation(contentView, Gravity.LEFT | Gravity.TOP, (int) x, (int) y); + return scrimPopupWindow; + } +} diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ThemePreviewActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/ThemePreviewActivity.java index 52f33fd4b..db284c890 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ThemePreviewActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ThemePreviewActivity.java @@ -35,14 +35,6 @@ import android.graphics.drawable.ColorDrawable; import android.graphics.drawable.Drawable; import android.graphics.drawable.GradientDrawable; import android.os.Build; - -import androidx.collection.LongSparseArray; -import androidx.recyclerview.widget.DefaultItemAnimator; -import androidx.recyclerview.widget.LinearLayoutManager; -import androidx.recyclerview.widget.RecyclerView; -import androidx.viewpager.widget.PagerAdapter; -import androidx.viewpager.widget.ViewPager; - import android.os.SystemClock; import android.text.TextPaint; import android.text.TextUtils; @@ -59,7 +51,12 @@ import android.widget.FrameLayout; import android.widget.ImageView; import android.widget.TextView; -import com.google.android.exoplayer2.util.Log; +import androidx.collection.LongSparseArray; +import androidx.recyclerview.widget.DefaultItemAnimator; +import androidx.recyclerview.widget.LinearLayoutManager; +import androidx.recyclerview.widget.RecyclerView; +import androidx.viewpager.widget.PagerAdapter; +import androidx.viewpager.widget.ViewPager; import org.telegram.messenger.AndroidUtilities; import org.telegram.messenger.ApplicationLoader; @@ -326,21 +323,23 @@ public class ThemePreviewActivity extends BaseFragment implements DownloadContro if (screenType == SCREEN_TYPE_ACCENT_COLOR) { accent = applyingTheme.getAccent(!edit); - useDefaultThemeForButtons = false; - backupAccentColor = accent.accentColor; - backupAccentColor2 = accent.accentColor2; - backupMyMessagesAccentColor = accent.myMessagesAccentColor; - backupMyMessagesGradientAccentColor1 = accent.myMessagesGradientAccentColor1; - backupMyMessagesGradientAccentColor2 = accent.myMessagesGradientAccentColor2; - backupMyMessagesGradientAccentColor3 = accent.myMessagesGradientAccentColor3; - backupMyMessagesAnimated = accent.myMessagesAnimated; - backupBackgroundOverrideColor = accent.backgroundOverrideColor; - backupBackgroundGradientOverrideColor1 = accent.backgroundGradientOverrideColor1; - backupBackgroundGradientOverrideColor2 = accent.backgroundGradientOverrideColor2; - backupBackgroundGradientOverrideColor3 = accent.backgroundGradientOverrideColor3; - backupIntensity = accent.patternIntensity; - backupSlug = accent.patternSlug; - backupBackgroundRotation = accent.backgroundRotation; + if (accent != null) { + useDefaultThemeForButtons = false; + backupAccentColor = accent.accentColor; + backupAccentColor2 = accent.accentColor2; + backupMyMessagesAccentColor = accent.myMessagesAccentColor; + backupMyMessagesGradientAccentColor1 = accent.myMessagesGradientAccentColor1; + backupMyMessagesGradientAccentColor2 = accent.myMessagesGradientAccentColor2; + backupMyMessagesGradientAccentColor3 = accent.myMessagesGradientAccentColor3; + backupMyMessagesAnimated = accent.myMessagesAnimated; + backupBackgroundOverrideColor = accent.backgroundOverrideColor; + backupBackgroundGradientOverrideColor1 = accent.backgroundGradientOverrideColor1; + backupBackgroundGradientOverrideColor2 = accent.backgroundGradientOverrideColor2; + backupBackgroundGradientOverrideColor3 = accent.backgroundGradientOverrideColor3; + backupIntensity = accent.patternIntensity; + backupSlug = accent.patternSlug; + backupBackgroundRotation = accent.backgroundRotation; + } } else { if (screenType == SCREEN_TYPE_PREVIEW) { useDefaultThemeForButtons = false; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/VoIPFragment.java b/TMessagesProj/src/main/java/org/telegram/ui/VoIPFragment.java index 58bb12fa5..2959de26b 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/VoIPFragment.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/VoIPFragment.java @@ -1,5 +1,7 @@ package org.telegram.ui; +import static org.telegram.ui.GroupCallActivity.TRANSITION_DURATION; + import android.Manifest; import android.animation.Animator; import android.animation.AnimatorListenerAdapter; @@ -66,6 +68,7 @@ import org.telegram.messenger.voip.Instance; import org.telegram.messenger.voip.VideoCapturerDevice; import org.telegram.messenger.voip.VoIPService; import org.telegram.tgnet.TLRPC; +import org.telegram.ui.ActionBar.ActionBar; import org.telegram.ui.ActionBar.AlertDialog; import org.telegram.ui.ActionBar.DarkAlertDialog; import org.telegram.ui.ActionBar.Theme; @@ -129,6 +132,7 @@ public class VoIPFragment implements VoIPService.StateListener, NotificationCent LinearLayout statusLayout; private VoIPFloatingLayout currentUserCameraFloatingLayout; private VoIPFloatingLayout callingUserMiniFloatingLayout; + private boolean currentUserCameraIsFullscreen; private TextureViewRenderer callingUserMiniTextureRenderer; private VoIPTextureView callingUserTextureView; @@ -211,6 +215,25 @@ public class VoIPFragment implements VoIPService.StateListener, NotificationCent private boolean screenWasWakeup; private boolean isVideoCall; + /* === pinch to zoom === */ + private float pinchStartCenterX; + private float pinchStartCenterY; + private float pinchStartDistance; + private float pinchTranslationX; + private float pinchTranslationY; + private boolean isInPinchToZoomTouchMode; + + private float pinchCenterX; + private float pinchCenterY; + + private int pointerId1, pointerId2; + + float pinchScale = 1f; + private boolean zoomStarted; + private boolean canZoomGesture; + ValueAnimator zoomBackAnimator; + /* === pinch to zoom === */ + public static void show(Activity activity, int account) { show(activity, false, account); } @@ -317,6 +340,7 @@ public class VoIPFragment implements VoIPService.StateListener, NotificationCent if (callingUserIsVideo && currentUserIsVideo && cameraForceExpanded) { cameraForceExpanded = false; currentUserCameraFloatingLayout.setRelativePosition(callingUserMiniFloatingLayout); + currentUserCameraIsFullscreen = false; previousState = currentState; updateViewState(); return; @@ -508,11 +532,93 @@ public class VoIPFragment implements VoIPService.StateListener, NotificationCent long pressedTime; @Override - public boolean onTouchEvent(MotionEvent event) { - switch (event.getAction()) { + public boolean onTouchEvent(MotionEvent ev) { + /* === pinch to zoom === */ + if (!canZoomGesture && !isInPinchToZoomTouchMode && !zoomStarted && ev.getActionMasked() != MotionEvent.ACTION_DOWN) { + finishZoom(); + return false; + } + if (ev.getActionMasked() == MotionEvent.ACTION_DOWN) { + canZoomGesture = false; + isInPinchToZoomTouchMode = false; + zoomStarted = false; + } + VoIPTextureView currentTextureView = getFullscreenTextureView(); + + if (ev.getActionMasked() == MotionEvent.ACTION_DOWN || ev.getActionMasked() == MotionEvent.ACTION_POINTER_DOWN) { + if (ev.getActionMasked() == MotionEvent.ACTION_DOWN) { + AndroidUtilities.rectTmp.set(currentTextureView.getX(), currentTextureView.getY(), currentTextureView.getX() + currentTextureView.getMeasuredWidth(), currentTextureView.getY() + currentTextureView.getMeasuredHeight()); + AndroidUtilities.rectTmp.inset((currentTextureView.getMeasuredHeight() * currentTextureView.scaleTextureToFill - currentTextureView.getMeasuredHeight()) / 2, (currentTextureView.getMeasuredWidth() * currentTextureView.scaleTextureToFill - currentTextureView.getMeasuredWidth()) / 2); + if (!GroupCallActivity.isLandscapeMode) { + AndroidUtilities.rectTmp.top = Math.max(AndroidUtilities.rectTmp.top, ActionBar.getCurrentActionBarHeight()); + AndroidUtilities.rectTmp.bottom = Math.min(AndroidUtilities.rectTmp.bottom, currentTextureView.getMeasuredHeight() - AndroidUtilities.dp(90)); + } else { + AndroidUtilities.rectTmp.top = Math.max(AndroidUtilities.rectTmp.top, ActionBar.getCurrentActionBarHeight()); + AndroidUtilities.rectTmp.right = Math.min(AndroidUtilities.rectTmp.right, currentTextureView.getMeasuredWidth() - AndroidUtilities.dp(90)); + } + canZoomGesture = AndroidUtilities.rectTmp.contains(ev.getX(), ev.getY()); + if (!canZoomGesture) { + finishZoom(); +// return maybeSwipeToBackGesture; + } + } + if (!isInPinchToZoomTouchMode && ev.getPointerCount() == 2) { + pinchStartDistance = (float) Math.hypot(ev.getX(1) - ev.getX(0), ev.getY(1) - ev.getY(0)); + pinchStartCenterX = pinchCenterX = (ev.getX(0) + ev.getX(1)) / 2.0f; + pinchStartCenterY = pinchCenterY = (ev.getY(0) + ev.getY(1)) / 2.0f; + pinchScale = 1f; + + pointerId1 = ev.getPointerId(0); + pointerId2 = ev.getPointerId(1); + isInPinchToZoomTouchMode = true; + } + } else if (ev.getActionMasked() == MotionEvent.ACTION_MOVE && isInPinchToZoomTouchMode) { + int index1 = -1; + int index2 = -1; + for (int i = 0; i < ev.getPointerCount(); i++) { + if (pointerId1 == ev.getPointerId(i)) { + index1 = i; + } + if (pointerId2 == ev.getPointerId(i)) { + index2 = i; + } + } + if (index1 == -1 || index2 == -1) { + getParent().requestDisallowInterceptTouchEvent(false); + finishZoom(); +// return maybeSwipeToBackGesture; + } + pinchScale = (float) Math.hypot(ev.getX(index2) - ev.getX(index1), ev.getY(index2) - ev.getY(index1)) / pinchStartDistance; + if (pinchScale > 1.005f && !zoomStarted) { + pinchStartDistance = (float) Math.hypot(ev.getX(index2) - ev.getX(index1), ev.getY(index2) - ev.getY(index1)); + pinchStartCenterX = pinchCenterX = (ev.getX(index1) + ev.getX(index2)) / 2.0f; + pinchStartCenterY = pinchCenterY = (ev.getY(index1) + ev.getY(index2)) / 2.0f; + pinchScale = 1f; + pinchTranslationX = 0f; + pinchTranslationY = 0f; + getParent().requestDisallowInterceptTouchEvent(true); + zoomStarted = true;// + isInPinchToZoomTouchMode = true; + } + + float newPinchCenterX = (ev.getX(index1) + ev.getX(index2)) / 2.0f; + float newPinchCenterY = (ev.getY(index1) + ev.getY(index2)) / 2.0f; + + float moveDx = pinchStartCenterX - newPinchCenterX; + float moveDy = pinchStartCenterY - newPinchCenterY; + pinchTranslationX = -moveDx / pinchScale; + pinchTranslationY = -moveDy / pinchScale; + invalidate(); + } else if ((ev.getActionMasked() == MotionEvent.ACTION_UP || (ev.getActionMasked() == MotionEvent.ACTION_POINTER_UP && checkPointerIds(ev)) || ev.getActionMasked() == MotionEvent.ACTION_CANCEL)) { + getParent().requestDisallowInterceptTouchEvent(false); + finishZoom(); + } + fragmentView.invalidate(); + + switch (ev.getAction()) { case MotionEvent.ACTION_DOWN: - pressedX = event.getX(); - pressedY = event.getY(); + pressedX = ev.getX(); + pressedY = ev.getY(); check = true; pressedTime = System.currentTimeMillis(); break; @@ -521,8 +627,8 @@ public class VoIPFragment implements VoIPService.StateListener, NotificationCent break; case MotionEvent.ACTION_UP: if (check) { - float dx = event.getX() - pressedX; - float dy = event.getY() - pressedY; + float dx = ev.getX() - pressedX; + float dy = ev.getY() - pressedY; long currentTime = System.currentTimeMillis(); if (dx * dx + dy * dy < touchSlop * touchSlop && currentTime - pressedTime < 300 && currentTime - lastContentTapTime > 300) { lastContentTapTime = System.currentTimeMillis(); @@ -538,11 +644,34 @@ public class VoIPFragment implements VoIPService.StateListener, NotificationCent } break; } - return check; + return canZoomGesture || check; + } + + @Override + protected boolean drawChild(Canvas canvas, View child, long drawingTime) { + if (child == callingUserPhotoView && (currentUserIsVideo || callingUserIsVideo)) { + return false; + } + if ( + child == callingUserPhotoView || + child == callingUserTextureView || + (child == currentUserCameraFloatingLayout && currentUserCameraIsFullscreen) + ) { + if (zoomStarted || zoomBackAnimator != null) { + canvas.save(); + canvas.scale(pinchScale, pinchScale, pinchCenterX, pinchCenterY); + canvas.translate(pinchTranslationX, pinchTranslationY); + boolean b = super.drawChild(canvas, child, drawingTime); + canvas.restore(); + return b; + } + } + return super.drawChild(canvas, child, drawingTime); } }; frameLayout.setClipToPadding(false); frameLayout.setClipChildren(false); + frameLayout.setBackgroundColor(0xff000000); updateSystemBarColors(); fragmentView = frameLayout; frameLayout.setFitsSystemWindows(true); @@ -559,6 +688,7 @@ public class VoIPFragment implements VoIPService.StateListener, NotificationCent callingUserTextureView = new VoIPTextureView(context, false, true, false, false); callingUserTextureView.renderer.setScalingType(RendererCommon.ScalingType.SCALE_ASPECT_FIT); callingUserTextureView.renderer.setEnableHardwareScaler(true); + callingUserTextureView.renderer.setRotateTextureWithScreen(true); callingUserTextureView.scaleType = VoIPTextureView.SCALE_TYPE_FIT; // callingUserTextureView.attachBackgroundRenderer(); @@ -589,6 +719,7 @@ public class VoIPFragment implements VoIPService.StateListener, NotificationCent currentUserCameraFloatingLayout = new VoIPFloatingLayout(context); currentUserCameraFloatingLayout.setDelegate((progress, value) -> currentUserTextureView.setScreenshareMiniProgress(progress, value)); currentUserCameraFloatingLayout.setRelativePosition(1f, 1f); + currentUserCameraIsFullscreen = true; currentUserTextureView = new VoIPTextureView(context, true, false); currentUserTextureView.renderer.setIsCamera(true); currentUserTextureView.renderer.setUseCameraRotation(true); @@ -598,6 +729,7 @@ public class VoIPFragment implements VoIPService.StateListener, NotificationCent hideUiRunnableWaiting = false; lastContentTapTime = System.currentTimeMillis(); callingUserMiniFloatingLayout.setRelativePosition(currentUserCameraFloatingLayout); + currentUserCameraIsFullscreen = true; cameraForceExpanded = true; previousState = currentState; updateViewState(); @@ -625,6 +757,7 @@ public class VoIPFragment implements VoIPService.StateListener, NotificationCent hideUiRunnableWaiting = false; lastContentTapTime = System.currentTimeMillis(); currentUserCameraFloatingLayout.setRelativePosition(callingUserMiniFloatingLayout); + currentUserCameraIsFullscreen = false; cameraForceExpanded = false; previousState = currentState; updateViewState(); @@ -773,7 +906,7 @@ public class VoIPFragment implements VoIPService.StateListener, NotificationCent } @Override - public void onDicline() { + public void onDecline() { if (currentState == VoIPService.STATE_BUSY) { windowView.finish(); } else { @@ -856,6 +989,60 @@ public class VoIPFragment implements VoIPService.StateListener, NotificationCent return frameLayout; } + private boolean checkPointerIds(MotionEvent ev) { + if (ev.getPointerCount() < 2) { + return false; + } + if (pointerId1 == ev.getPointerId(0) && pointerId2 == ev.getPointerId(1)) { + return true; + } + if (pointerId1 == ev.getPointerId(1) && pointerId2 == ev.getPointerId(0)) { + return true; + } + return false; + } + + private VoIPTextureView getFullscreenTextureView() { + if (callingUserIsVideo) { + return callingUserTextureView; + } + return currentUserTextureView; + } + + private void finishZoom() { + if (zoomStarted) { + zoomStarted = false; + zoomBackAnimator = ValueAnimator.ofFloat(1f, 0); + + float fromScale = pinchScale; + float fromTranslateX = pinchTranslationX; + float fromTranslateY = pinchTranslationY; + zoomBackAnimator.addUpdateListener(valueAnimator -> { + float v = (float) valueAnimator.getAnimatedValue(); + pinchScale = fromScale * v + 1f * (1f - v); + pinchTranslationX = fromTranslateX * v; + pinchTranslationY = fromTranslateY * v; + fragmentView.invalidate(); + }); + + zoomBackAnimator.addListener(new AnimatorListenerAdapter() { + @Override + public void onAnimationEnd(Animator animation) { + zoomBackAnimator = null; + pinchScale = 1f; + pinchTranslationX = 0; + pinchTranslationY = 0; + fragmentView.invalidate(); + } + }); + zoomBackAnimator.setDuration(TRANSITION_DURATION); + zoomBackAnimator.setInterpolator(CubicBezierInterpolator.DEFAULT); + zoomBackAnimator.start(); + } + canZoomGesture = false; + isInPinchToZoomTouchMode = false; + } + private void initRenderers() { currentUserTextureView.renderer.init(VideoCapturerDevice.getEglBase().getEglBaseContext(), new RendererCommon.RendererEvents() { @Override @@ -1324,8 +1511,8 @@ public class VoIPFragment implements VoIPService.StateListener, NotificationCent } if (animated) { - currentUserCameraFloatingLayout.saveRelatedPosition(); - callingUserMiniFloatingLayout.saveRelatedPosition(); + currentUserCameraFloatingLayout.saveRelativePosition(); + callingUserMiniFloatingLayout.saveRelativePosition(); } if (callingUserIsVideo) { @@ -1621,9 +1808,9 @@ public class VoIPFragment implements VoIPService.StateListener, NotificationCent currentUserCameraFloatingLayout.setVisibility(View.GONE); } } else { - boolean swtichToFloatAnimated = animated; + boolean switchToFloatAnimated = animated; if (currentUserCameraFloatingLayout.getTag() == null || (int) currentUserCameraFloatingLayout.getTag() == STATE_GONE) { - swtichToFloatAnimated = false; + switchToFloatAnimated = false; } if (animated) { if (currentUserCameraFloatingLayout.getTag() != null && (int) currentUserCameraFloatingLayout.getTag() == STATE_GONE) { @@ -1651,8 +1838,10 @@ public class VoIPFragment implements VoIPService.StateListener, NotificationCent } if ((currentUserCameraFloatingLayout.getTag() == null || (int) currentUserCameraFloatingLayout.getTag() != STATE_FLOATING) && currentUserCameraFloatingLayout.relativePositionToSetX < 0) { currentUserCameraFloatingLayout.setRelativePosition(1f, 1f); + currentUserCameraIsFullscreen = true; } - currentUserCameraFloatingLayout.setFloatingMode(state == STATE_FLOATING, swtichToFloatAnimated); + currentUserCameraFloatingLayout.setFloatingMode(state == STATE_FLOATING, switchToFloatAnimated); + currentUserCameraIsFullscreen = state != STATE_FLOATING; } currentUserCameraFloatingLayout.setTag(state); } diff --git a/TMessagesProj/src/main/res/drawable-hdpi/ic_call.png b/TMessagesProj/src/main/res/drawable-hdpi/ic_call.png index 9c0766652..b3a24d546 100644 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/ic_call.png and b/TMessagesProj/src/main/res/drawable-hdpi/ic_call.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/ic_call_end_white_24dp.png b/TMessagesProj/src/main/res/drawable-hdpi/ic_call_end_white_24dp.png old mode 100755 new mode 100644 index 625b827c4..958cd742b Binary files a/TMessagesProj/src/main/res/drawable-hdpi/ic_call_end_white_24dp.png and b/TMessagesProj/src/main/res/drawable-hdpi/ic_call_end_white_24dp.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/ic_call_end_white_36dp.png b/TMessagesProj/src/main/res/drawable-hdpi/ic_call_end_white_36dp.png old mode 100755 new mode 100644 index 51456d3d5..01f6feae7 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/ic_call_end_white_36dp.png and b/TMessagesProj/src/main/res/drawable-hdpi/ic_call_end_white_36dp.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/ic_call_made_green_18dp.png b/TMessagesProj/src/main/res/drawable-hdpi/ic_call_made_green_18dp.png old mode 100755 new mode 100644 index 50b2464b9..354221821 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/ic_call_made_green_18dp.png and b/TMessagesProj/src/main/res/drawable-hdpi/ic_call_made_green_18dp.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/ic_gallery_background.png b/TMessagesProj/src/main/res/drawable-hdpi/ic_gallery_background.png index 9c1b36856..00e7fde40 100644 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/ic_gallery_background.png and b/TMessagesProj/src/main/res/drawable-hdpi/ic_gallery_background.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/profile_phone.png b/TMessagesProj/src/main/res/drawable-hdpi/profile_phone.png old mode 100755 new mode 100644 index 7b7e68a66..b3a24d546 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/profile_phone.png and b/TMessagesProj/src/main/res/drawable-hdpi/profile_phone.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/ic_call.png b/TMessagesProj/src/main/res/drawable-mdpi/ic_call.png index a84b9acdc..11abd1a02 100644 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/ic_call.png and b/TMessagesProj/src/main/res/drawable-mdpi/ic_call.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/ic_call_end_white_24dp.png b/TMessagesProj/src/main/res/drawable-mdpi/ic_call_end_white_24dp.png old mode 100755 new mode 100644 index 378272ffc..2865973ad Binary files a/TMessagesProj/src/main/res/drawable-mdpi/ic_call_end_white_24dp.png and b/TMessagesProj/src/main/res/drawable-mdpi/ic_call_end_white_24dp.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/ic_call_end_white_36dp.png b/TMessagesProj/src/main/res/drawable-mdpi/ic_call_end_white_36dp.png old mode 100755 new mode 100644 index 625b827c4..704cdba20 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/ic_call_end_white_36dp.png and b/TMessagesProj/src/main/res/drawable-mdpi/ic_call_end_white_36dp.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/ic_call_made_green_18dp.png b/TMessagesProj/src/main/res/drawable-mdpi/ic_call_made_green_18dp.png old mode 100755 new mode 100644 index 7d2ccaa22..dd42b7ddd Binary files a/TMessagesProj/src/main/res/drawable-mdpi/ic_call_made_green_18dp.png and b/TMessagesProj/src/main/res/drawable-mdpi/ic_call_made_green_18dp.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/ic_gallery_background.png b/TMessagesProj/src/main/res/drawable-mdpi/ic_gallery_background.png index 311345641..5795c70d5 100644 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/ic_gallery_background.png and b/TMessagesProj/src/main/res/drawable-mdpi/ic_gallery_background.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/profile_phone.png b/TMessagesProj/src/main/res/drawable-mdpi/profile_phone.png old mode 100755 new mode 100644 index 199982649..11abd1a02 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/profile_phone.png and b/TMessagesProj/src/main/res/drawable-mdpi/profile_phone.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/ic_call.png b/TMessagesProj/src/main/res/drawable-xhdpi/ic_call.png index 8e54cb03e..373a1e104 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/ic_call.png and b/TMessagesProj/src/main/res/drawable-xhdpi/ic_call.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/ic_call_end_white_24dp.png b/TMessagesProj/src/main/res/drawable-xhdpi/ic_call_end_white_24dp.png old mode 100755 new mode 100644 index a4fe6889d..698765d24 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/ic_call_end_white_24dp.png and b/TMessagesProj/src/main/res/drawable-xhdpi/ic_call_end_white_24dp.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/ic_call_end_white_36dp.png b/TMessagesProj/src/main/res/drawable-xhdpi/ic_call_end_white_36dp.png old mode 100755 new mode 100644 index e1831d7af..b81f3bbda Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/ic_call_end_white_36dp.png and b/TMessagesProj/src/main/res/drawable-xhdpi/ic_call_end_white_36dp.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/ic_call_made_green_18dp.png b/TMessagesProj/src/main/res/drawable-xhdpi/ic_call_made_green_18dp.png old mode 100755 new mode 100644 index 503b68701..f24558943 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/ic_call_made_green_18dp.png and b/TMessagesProj/src/main/res/drawable-xhdpi/ic_call_made_green_18dp.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/ic_gallery_background.png b/TMessagesProj/src/main/res/drawable-xhdpi/ic_gallery_background.png index 2dfd59ffc..5363abac8 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/ic_gallery_background.png and b/TMessagesProj/src/main/res/drawable-xhdpi/ic_gallery_background.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/profile_phone.png b/TMessagesProj/src/main/res/drawable-xhdpi/profile_phone.png old mode 100755 new mode 100644 index b30f8d525..373a1e104 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/profile_phone.png and b/TMessagesProj/src/main/res/drawable-xhdpi/profile_phone.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/ic_call.png b/TMessagesProj/src/main/res/drawable-xxhdpi/ic_call.png index 0423cbb9e..00a8829d3 100644 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/ic_call.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/ic_call.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/ic_call_end_white_24dp.png b/TMessagesProj/src/main/res/drawable-xxhdpi/ic_call_end_white_24dp.png old mode 100755 new mode 100644 index e1831d7af..0aaaec165 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/ic_call_end_white_24dp.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/ic_call_end_white_24dp.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/ic_call_end_white_36dp.png b/TMessagesProj/src/main/res/drawable-xxhdpi/ic_call_end_white_36dp.png old mode 100755 new mode 100644 index 13ffc2ad7..3912f6d5c Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/ic_call_end_white_36dp.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/ic_call_end_white_36dp.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/ic_call_made_green_18dp.png b/TMessagesProj/src/main/res/drawable-xxhdpi/ic_call_made_green_18dp.png old mode 100755 new mode 100644 index 5267f2c8b..d8d0b219d Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/ic_call_made_green_18dp.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/ic_call_made_green_18dp.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/ic_gallery_background.png b/TMessagesProj/src/main/res/drawable-xxhdpi/ic_gallery_background.png index 7621b782f..e444bb9f3 100644 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/ic_gallery_background.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/ic_gallery_background.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/profile_phone.png b/TMessagesProj/src/main/res/drawable-xxhdpi/profile_phone.png old mode 100755 new mode 100644 index 47104ca83..00a8829d3 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/profile_phone.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/profile_phone.png differ diff --git a/TMessagesProj/src/main/res/raw/ic_save_to_gifs.json b/TMessagesProj/src/main/res/raw/ic_save_to_gifs.json new file mode 100644 index 000000000..57f18429a --- /dev/null +++ b/TMessagesProj/src/main/res/raw/ic_save_to_gifs.json @@ -0,0 +1 @@ +{"v":"5.8.1","fr":60,"ip":0,"op":90,"w":512,"h":512,"nm":"gif","ddd":0,"assets":[],"layers":[{"ddd":0,"ind":1,"ty":4,"nm":"Gif","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[256,256,0],"ix":2,"l":2},"a":{"a":0,"k":[256,256,0],"ix":1,"l":2},"s":{"a":1,"k":[{"i":{"x":[0.4,0.4,0.4],"y":[1,1,1]},"o":{"x":[0.6,0.6,0.6],"y":[0,0,0]},"t":0,"s":[0,0,100]},{"i":{"x":[0.4,0.4,0.4],"y":[1,1,1]},"o":{"x":[0.6,0.6,0.6],"y":[0,0,0]},"t":15,"s":[120,120,100]},{"i":{"x":[0.4,0.4,0.4],"y":[1,1,1]},"o":{"x":[0.6,0.6,0.6],"y":[0,0,0]},"t":25,"s":[96,96,100]},{"t":35,"s":[100,100,100]}],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[357.564,262.852],[318.756,262.852]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ind":1,"ty":"sh","ix":2,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[0,-2.761],[0,0]],"o":[[0,0],[-2.761,0],[0,0],[0,0]],"v":[[376.934,206],[323.756,206],[318.756,211],[318.756,306]],"c":false},"ix":2},"nm":"Path 2","mn":"ADBE Vector Shape - Group","hd":false},{"ind":2,"ty":"sh","ix":3,"ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[265.097,206],[265.097,306]],"c":false},"ix":2},"nm":"Path 3","mn":"ADBE Vector Shape - Group","hd":false},{"ind":3,"ty":"sh","ix":4,"ks":{"a":0,"k":{"i":[[0,0],[10.112,0],[0,-27.614],[-27.614,0],[-7.761,4.955],[0,0],[3.368,0],[0,0]],"o":[[-7.867,-5.161],[-27.614,0],[0,27.614],[9.891,0],[0,0],[0,-3.368],[0,0],[0,0]],"v":[[212.39,214.163],[185,206],[135,256],[185,306],[211.871,298.173],[211.871,267.678],[205.774,261.581],[189.708,261.581]],"c":false},"ix":2},"nm":"Path 4","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"tm","s":{"a":1,"k":[{"i":{"x":[0],"y":[1]},"o":{"x":[0.167],"y":[0.167]},"t":10,"s":[100]},{"t":35,"s":[0]}],"ix":1},"e":{"a":0,"k":100,"ix":2},"o":{"a":0,"k":0,"ix":3},"m":1,"ix":5,"nm":"Trim Paths 1","mn":"ADBE Vector Filter - Trim","hd":false},{"ty":"st","c":{"a":0,"k":[0,0,0,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":24,"ix":5},"lc":2,"lj":2,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":6,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-28.529,0],[0,0],[-10.43,-5.578],[-5.578,-10.43],[0,-28.529],[0,0],[5.578,-10.43],[10.43,-5.578],[28.529,0],[0,0],[10.43,5.578],[5.578,10.43],[0,28.529],[0,0],[-5.578,10.43],[-10.43,5.578]],"o":[[0,0],[28.529,0],[10.43,5.578],[5.578,10.43],[0,0],[0,28.529],[-5.578,10.43],[-10.43,5.578],[0,0],[-28.529,0],[-10.43,-5.578],[-5.578,-10.43],[0,0],[0,-28.529],[5.578,-10.43],[10.43,-5.578]],"v":[[-98.956,-140],[99.956,-140],[149.259,-131.452],[173.452,-107.259],[182,-57.956],[182,57.956],[173.452,107.259],[149.259,131.452],[99.956,140],[-98.956,140],[-148.259,131.452],[-172.452,107.259],[-181,57.956],[-181,-57.956],[-172.452,-107.259],[-148.259,-131.452]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[1,1,1,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[256,256],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 5","np":2,"cix":2,"bm":0,"ix":2,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":90,"st":0,"bm":0}],"markers":[]} \ No newline at end of file diff --git a/TMessagesProj/src/main/res/values/strings.xml b/TMessagesProj/src/main/res/values/strings.xml index 8c8500ce0..43a1d38d1 100644 --- a/TMessagesProj/src/main/res/values/strings.xml +++ b/TMessagesProj/src/main/res/values/strings.xml @@ -2825,6 +2825,7 @@ Video saved to gallery Photo saved to downloads Video saved to downloads + Added to saved GIFs GIF saved to downloads File saved to music File saved to downloads @@ -4980,4 +4981,6 @@ %1$s: %3$s to your invoice in %2$s %1$s: %3$s to your GIF in %2$s Blur in chat + Read all reactions + Read all mentions