diff --git a/TMessagesProj/build.gradle b/TMessagesProj/build.gradle index 0f6c716d8f..a61cb7c168 100644 --- a/TMessagesProj/build.gradle +++ b/TMessagesProj/build.gradle @@ -3,12 +3,12 @@ import cn.hutool.core.util.RuntimeUtil apply plugin: "com.android.application" apply plugin: "kotlin-android" -def verName = "10.6.1" -def verCode = 1155 +def verName = "10.6.4" +def verCode = 1156 -def officialVer = "10.6.1" -def officialCode = 4275 +def officialVer = "10.6.4" +def officialCode = 4365 def serviceAccountCredentialsFile = rootProject.file("service_account_credentials.json") diff --git a/TMessagesProj/jni/tgnet/ConnectionsManager.cpp b/TMessagesProj/jni/tgnet/ConnectionsManager.cpp index 03d55d338c..448871f261 100644 --- a/TMessagesProj/jni/tgnet/ConnectionsManager.cpp +++ b/TMessagesProj/jni/tgnet/ConnectionsManager.cpp @@ -2388,7 +2388,7 @@ void ConnectionsManager::processRequestQueue(uint32_t connectionTypes, uint32_t } } if (request->retryCount >= retryMax) { - if (LOGS_ENABLED) DEBUG_E("timed out %s", typeInfo.name()); + if (LOGS_ENABLED) DEBUG_E("timed out %s, message_id = 0x%" PRIx64, typeInfo.name(), request->messageId); auto error = new TL_error(); error->code = -123; error->text = "RETRY_LIMIT"; diff --git a/TMessagesProj/src/main/assets/bluebubbles.attheme b/TMessagesProj/src/main/assets/bluebubbles.attheme index 6e29f76c94..bb94402b08 100644 --- a/TMessagesProj/src/main/assets/bluebubbles.attheme +++ b/TMessagesProj/src/main/assets/bluebubbles.attheme @@ -49,7 +49,7 @@ chat_inReplyNameText=-14643754 chats_onlineCircle=-13192972 chat_outAudioSelectedProgress=-7484939 chat_inInstant=-14707230 -avatar_backgroundSaved=-10438409 +avatar_backgroundSaved=-9847303 chats_sentReadCheck=-15754010 chats_nameMessageArchived=-7237231 chat_outSentCheckSelected=-14968350 diff --git a/TMessagesProj/src/main/assets/darkblue.attheme b/TMessagesProj/src/main/assets/darkblue.attheme index 8c3eda0baf..314ab31cd1 100644 --- a/TMessagesProj/src/main/assets/darkblue.attheme +++ b/TMessagesProj/src/main/assets/darkblue.attheme @@ -9,6 +9,9 @@ windowBackgroundWhiteBlueIcon=-528890628 chat_goDownButtonCounterBackground=-11425042 actionBarActionModeDefault=-14273984 actionBarActionModeDefaultTop=-14536643 +actionBarActionModeReaction=318767103 +actionBarActionModeReactionText=-1 +actionBarActionModeReactionDot=-13287865 statisticChartHintLine=452984831 chats_menuPhone=-1816080163 chat_outViews=-7357217 @@ -425,7 +428,7 @@ chats_attachMessage=-8548712 chat_topPanelBackground=-14602949 chat_outSentClock=-8213557 dialogBackgroundGray=-14932431 -chat_searchPanelText=-8796932 +chat_searchPanelText=-1 chat_inContactIcon=-1 code_comment=-2130706433 chat_outCodeBackground=857487708 diff --git a/TMessagesProj/src/main/assets/night.attheme b/TMessagesProj/src/main/assets/night.attheme index 46217ff1c2..5962858d63 100644 --- a/TMessagesProj/src/main/assets/night.attheme +++ b/TMessagesProj/src/main/assets/night.attheme @@ -8,6 +8,9 @@ chat_inSentClockSelected=-7490861 chat_goDownButtonCounterBackground=-11425042 actionBarActionModeDefault=-14211289 actionBarActionModeDefaultTop=-14277082 +actionBarActionModeReaction=318767103 +actionBarActionModeReactionText=-1 +actionBarActionModeReactionDot=-13287865 statisticChartHintLine=452984831 chats_menuPhone=-1815557944 chat_outViews=-7357217 @@ -450,7 +453,7 @@ chats_attachMessage=-8224126 chat_topPanelBackground=-15066597 chat_outSentClock=-6698513 dialogBackgroundGray=-14013910 -chat_searchPanelText=-10767620 +chat_searchPanelText=-1 chat_inContactIcon=-1 code_comment=-2130706433 chat_outCodeBackground=859062986 diff --git a/TMessagesProj/src/main/java/androidx/recyclerview/widget/ChatListItemAnimator.java b/TMessagesProj/src/main/java/androidx/recyclerview/widget/ChatListItemAnimator.java index 765c7c3cf4..2c542e65ec 100644 --- a/TMessagesProj/src/main/java/androidx/recyclerview/widget/ChatListItemAnimator.java +++ b/TMessagesProj/src/main/java/androidx/recyclerview/widget/ChatListItemAnimator.java @@ -990,7 +990,7 @@ public boolean animateChange(RecyclerView.ViewHolder oldHolder, RecyclerView.Vie return true; } - void animateChangeImpl(final ChangeInfo changeInfo) { + public void animateChangeImpl(final ChangeInfo changeInfo) { final RecyclerView.ViewHolder holder = changeInfo.oldHolder; final View view = holder == null ? null : holder.itemView; final RecyclerView.ViewHolder newHolder = changeInfo.newHolder; diff --git a/TMessagesProj/src/main/java/androidx/recyclerview/widget/DefaultItemAnimator.java b/TMessagesProj/src/main/java/androidx/recyclerview/widget/DefaultItemAnimator.java index 5d923a3a6f..b351c8746b 100644 --- a/TMessagesProj/src/main/java/androidx/recyclerview/widget/DefaultItemAnimator.java +++ b/TMessagesProj/src/main/java/androidx/recyclerview/widget/DefaultItemAnimator.java @@ -468,7 +468,7 @@ public boolean animateChange(RecyclerView.ViewHolder oldHolder, RecyclerView.Vie return true; } - void animateChangeImpl(final ChangeInfo changeInfo) { + public void animateChangeImpl(final ChangeInfo changeInfo) { final RecyclerView.ViewHolder holder = changeInfo.oldHolder; final View view = holder == null ? null : holder.itemView; final RecyclerView.ViewHolder newHolder = changeInfo.newHolder; diff --git a/TMessagesProj/src/main/java/org/telegram/SQLite/SQLitePreparedStatement.java b/TMessagesProj/src/main/java/org/telegram/SQLite/SQLitePreparedStatement.java index 40b1145a8c..cef386c19f 100755 --- a/TMessagesProj/src/main/java/org/telegram/SQLite/SQLitePreparedStatement.java +++ b/TMessagesProj/src/main/java/org/telegram/SQLite/SQLitePreparedStatement.java @@ -25,7 +25,6 @@ public class SQLitePreparedStatement { private long startTime; private String query; - //private static HashMap hashMap; public long getStatementHandle() { return sqliteStatementHandle; @@ -112,9 +111,6 @@ public void finalizeQuery() { } } try { - /*if (BuildVars.DEBUG_PRIVATE_VERSION) { - hashMap.remove(this); - }*/ isFinalized = true; finalize(sqliteStatementHandle); } catch (SQLiteException e) { diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/AndroidUtilities.java b/TMessagesProj/src/main/java/org/telegram/messenger/AndroidUtilities.java index cc922b85dc..f593671e4b 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/AndroidUtilities.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/AndroidUtilities.java @@ -73,6 +73,7 @@ import android.text.style.URLSpan; import android.text.util.Linkify; import android.util.DisplayMetrics; +import android.util.Log; import android.util.Pair; import android.util.StateSet; import android.util.TypedValue; @@ -154,6 +155,7 @@ import org.telegram.ui.Components.PickerBottomLayout; import org.telegram.ui.Components.PipRoundVideoView; import org.telegram.ui.Components.PipVideoOverlay; +import org.telegram.ui.Components.RLottieImageView; import org.telegram.ui.Components.RecyclerListView; import org.telegram.ui.Components.ShareAlert; import org.telegram.ui.Components.TypefaceSpan; @@ -333,6 +335,7 @@ public class AndroidUtilities { }; public static final String STICKERS_PLACEHOLDER_PACK_NAME = "tg_placeholders_android"; + public static final String STICKERS_PLACEHOLDER_PACK_NAME_2 = "tg_superplaceholders_android_2"; private static boolean containsUnsupportedCharacters(String text) { if (text.contains("\u202C")) { @@ -5026,6 +5029,7 @@ public static float distanceInfluenceForSnapDuration(float f) { } public static void makeAccessibilityAnnouncement(CharSequence what) { + if (TextUtils.isEmpty(what)) return; AccessibilityManager am = (AccessibilityManager) ApplicationLoader.applicationContext.getSystemService(Context.ACCESSIBILITY_SERVICE); if (am.isEnabled()) { AccessibilityEvent ev = AccessibilityEvent.obtain(); diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/ApplicationLoader.java b/TMessagesProj/src/main/java/org/telegram/messenger/ApplicationLoader.java index 4e6d107869..12f911574e 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/ApplicationLoader.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/ApplicationLoader.java @@ -507,11 +507,6 @@ public static boolean isConnectedToWiFi() { return false; } - public static boolean useLessData() { - ensureCurrentNetworkGet(); - return BuildVars.DEBUG_PRIVATE_VERSION && (SharedConfig.forceLessData || isConnectionSlow()); - } - public static boolean isConnectionSlow() { try { ensureCurrentNetworkGet(false); diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/ChatMessagesMetadataController.java b/TMessagesProj/src/main/java/org/telegram/messenger/ChatMessagesMetadataController.java index 9841be6e24..3a65cc5bc9 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/ChatMessagesMetadataController.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/ChatMessagesMetadataController.java @@ -23,7 +23,7 @@ public ChatMessagesMetadataController(ChatActivity chatActivity) { } public void checkMessages(ChatActivity.ChatActivityAdapter chatAdapter, int maxAdapterPosition, int minAdapterPosition, long currentTime) { - ArrayList messages = chatActivity.messages; + ArrayList messages = chatAdapter.getMessages(); if (!chatActivity.isInScheduleMode() && maxAdapterPosition >= 0 && minAdapterPosition >= 0) { int from = minAdapterPosition - chatAdapter.messagesStartRow - 10; int to = maxAdapterPosition - chatAdapter.messagesStartRow + 10; diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/DatabaseMigrationHelper.java b/TMessagesProj/src/main/java/org/telegram/messenger/DatabaseMigrationHelper.java index 497231fe73..72d9b98974 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/DatabaseMigrationHelper.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/DatabaseMigrationHelper.java @@ -1409,10 +1409,22 @@ public static int migrate(MessagesStorage messagesStorage, int version) throws E version = 138; } - if (version == 138) { - database.executeFast("CREATE TABLE IF NOT EXISTS saved_reaction_tags (data BLOB);").stepThis().dispose(); - database.executeFast("PRAGMA user_version = 139").stepThis().dispose(); - version = 139; + if (version == 138 || version == 139 || version == 140 || version == 141) { + database.executeFast("DROP TABLE IF EXISTS tag_message_id;").stepThis().dispose(); + database.executeFast("CREATE TABLE tag_message_id(mid INTEGER, topic_id INTEGER, tag INTEGER, text TEXT);").stepThis().dispose(); + database.executeFast("CREATE INDEX IF NOT EXISTS tag_idx_tag_message_id ON tag_message_id(tag);").stepThis().dispose(); + database.executeFast("CREATE INDEX IF NOT EXISTS tag_text_idx_tag_message_id ON tag_message_id(tag, text);").stepThis().dispose(); + database.executeFast("CREATE INDEX IF NOT EXISTS tag_topic_idx_tag_message_id ON tag_message_id(topic_id, tag);").stepThis().dispose(); + database.executeFast("CREATE INDEX IF NOT EXISTS tag_topic_text_idx_tag_message_id ON tag_message_id(topic_id, tag, text);").stepThis().dispose(); + database.executeFast("PRAGMA user_version = 142").stepThis().dispose(); + version = 142; + } + + if (version == 142) { + database.executeFast("DROP TABLE IF EXISTS saved_reaction_tags;").stepThis().dispose(); + database.executeFast("CREATE TABLE saved_reaction_tags (topic_id INTEGER PRIMARY KEY, data BLOB);").stepThis().dispose(); + database.executeFast("PRAGMA user_version = 143").stepThis().dispose(); + version = 143; } return version; diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/DocumentObject.java b/TMessagesProj/src/main/java/org/telegram/messenger/DocumentObject.java index 10ce541445..189740c2e7 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/DocumentObject.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/DocumentObject.java @@ -53,7 +53,7 @@ public static SvgHelper.SvgDrawable getSvgThumb(ArrayList sizes TLRPC.PhotoSize photoSize = sizes.get(a); if (photoSize instanceof TLRPC.TL_photoPathSize) { photoPathSize = (TLRPC.TL_photoPathSize) photoSize; - } else { + } else if (photoSize instanceof TLRPC.TL_photoSize) { w = photoSize.w; h = photoSize.h; } diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/FileLoadOperation.java b/TMessagesProj/src/main/java/org/telegram/messenger/FileLoadOperation.java index d9c485351a..ca9ca9e4f4 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/FileLoadOperation.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/FileLoadOperation.java @@ -2445,7 +2445,7 @@ protected void startDownloadRequest(int useConnectionType) { } }, null, null, flags, datacenterId, connectionType, isLast); if (BuildVars.LOGS_ENABLED) { - FileLog.d("debug_loading: " + cacheFileFinal.getName() + " dc=" + datacenterId + " send reqId " + requestInfo.requestToken + " offset=" + requestInfo.offset + " conType=" + connectionType + " priority="); + FileLog.d("debug_loading: " + cacheFileFinal.getName() + " dc=" + datacenterId + " send reqId " + requestInfo.requestToken + " offset=" + requestInfo.offset + " conType=" + connectionType + " priority=" + priority); } requestsCount++; } diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/FileLoader.java b/TMessagesProj/src/main/java/org/telegram/messenger/FileLoader.java index 69869dd4ef..2770c1c9f5 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/FileLoader.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/FileLoader.java @@ -999,7 +999,7 @@ public boolean isLocallyCreatedFile(String path) { loaderQueue.checkLoadingOperations(operation.isStory && priority >= PRIORITY_HIGH); if (BuildVars.LOGS_ENABLED) { - FileLog.d("create load operation fileName=" + finalFileName + " documentName=" + getDocumentFileName(document) + " size=" + AndroidUtilities.formatFileSize(operation.totalBytesCount) + " position in queue " + operation.getPositionInQueue() + " account=" + currentAccount); + FileLog.d("create load operation fileName=" + finalFileName + " documentName=" + getDocumentFileName(document) + " size=" + AndroidUtilities.formatFileSize(operation.totalBytesCount) + " position in queue " + operation.getPositionInQueue() + " account=" + currentAccount + " cacheType=" + cacheType); } return operation; } diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/FileLog.java b/TMessagesProj/src/main/java/org/telegram/messenger/FileLog.java index e7c380f942..dd556e332f 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/FileLog.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/FileLog.java @@ -78,7 +78,7 @@ public FileLog() { private static Gson gson; private static HashSet excludeRequests; - public static void dumpResponseAndRequest(TLObject request, TLObject response, TLRPC.TL_error error, long requestMsgId, long startRequestTimeInMillis, int requestToken) { + public static void dumpResponseAndRequest(int account, TLObject request, TLObject response, TLRPC.TL_error error, long requestMsgId, long startRequestTimeInMillis, int requestToken) { if (!BuildVars.DEBUG_PRIVATE_VERSION || !BuildVars.LOGS_ENABLED || request == null) { return; } @@ -100,7 +100,7 @@ public static void dumpResponseAndRequest(TLObject request, TLObject response, T long time = System.currentTimeMillis(); FileLog.getInstance().logQueue.postRunnable(() -> { try { - String metadata = "requestMsgId=" + requestMsgId + " requestingTime=" + (System.currentTimeMillis() - startRequestTimeInMillis) + " request_token=" + requestToken; + String metadata = "requestMsgId=" + requestMsgId + " requestingTime=" + (System.currentTimeMillis() - startRequestTimeInMillis) + " request_token=" + requestToken + " account=" + account; FileLog.getInstance().tlStreamWriter.write(getInstance().dateFormat.format(time) + " " + metadata); FileLog.getInstance().tlStreamWriter.write("\n"); FileLog.getInstance().tlStreamWriter.write(req); diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/LocaleController.java b/TMessagesProj/src/main/java/org/telegram/messenger/LocaleController.java index 9fef9f42b9..65bbfb7c5d 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/LocaleController.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/LocaleController.java @@ -1849,6 +1849,31 @@ public static String formatSeenDate(long date) { return "LOC_ERR"; } + public static String formatPmSeenDate(long date) { + try { + date *= 1000; + Calendar rightNow = Calendar.getInstance(); + int day = rightNow.get(Calendar.DAY_OF_YEAR); + int year = rightNow.get(Calendar.YEAR); + rightNow.setTimeInMillis(date); + int dateDay = rightNow.get(Calendar.DAY_OF_YEAR); + int dateYear = rightNow.get(Calendar.YEAR); + + if (dateDay == day && year == dateYear) { + return LocaleController.formatString(R.string.PmReadTodayAt, getInstance().formatterDay.format(new Date(date))); + } else if (dateDay + 1 == day && year == dateYear) { + return LocaleController.formatString(R.string.PmReadYesterdayAt, getInstance().formatterDay.format(new Date(date))); + } else if (Math.abs(System.currentTimeMillis() - date) < 31536000000L) { + return LocaleController.formatString(R.string.PmReadDateTimeAt, getInstance().formatterDayMonth.format(new Date(date)), getInstance().formatterDay.format(new Date(date))); + } else { + return LocaleController.formatString(R.string.PmReadDateTimeAt, getInstance().formatterYear.format(new Date(date)), getInstance().formatterDay.format(new Date(date))); + } + } catch (Exception e) { + FileLog.e(e); + } + return "LOC_ERR"; + } + public static String formatShortDate(long date) { try { date *= 1000; diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/MediaController.java b/TMessagesProj/src/main/java/org/telegram/messenger/MediaController.java index 1f6db5693b..b263fe3c4d 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/MediaController.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/MediaController.java @@ -54,7 +54,6 @@ import android.telephony.PhoneStateListener; import android.telephony.TelephonyManager; import android.text.TextUtils; -import android.util.Log; import android.util.Pair; import android.util.SparseArray; import android.view.HapticFeedbackConstants; @@ -86,6 +85,7 @@ import org.telegram.ui.Components.EmbedBottomSheet; import org.telegram.ui.Components.PhotoFilterView; import org.telegram.ui.Components.PipRoundVideoView; +import org.telegram.ui.Components.Reactions.ReactionsLayoutInBubble; import org.telegram.ui.Components.VideoPlayer; import org.telegram.ui.LaunchActivity; import org.telegram.ui.PhotoViewer; @@ -2428,10 +2428,10 @@ public void loadMoreMusic() { //TODO topics if (!playlistEndReached[0]) { loadingPlaylist = true; - AccountInstance.getInstance(playingMessageObject.currentAccount).getMediaDataController().loadMedia(playingMessageObject.getDialogId(), 50, playlistMaxId[0], 0, MediaDataController.MEDIA_MUSIC, 0, 1, playlistClassGuid, 0); + AccountInstance.getInstance(playingMessageObject.currentAccount).getMediaDataController().loadMedia(playingMessageObject.getDialogId(), 50, playlistMaxId[0], 0, MediaDataController.MEDIA_MUSIC, 0, 1, playlistClassGuid, 0, null, null); } else if (playlistMergeDialogId != 0 && !playlistEndReached[1]) { loadingPlaylist = true; - AccountInstance.getInstance(playingMessageObject.currentAccount).getMediaDataController().loadMedia(playlistMergeDialogId, 50, playlistMaxId[0], 0, MediaDataController.MEDIA_MUSIC, 0, 1, playlistClassGuid, 0); + AccountInstance.getInstance(playingMessageObject.currentAccount).getMediaDataController().loadMedia(playlistMergeDialogId, 50, playlistMaxId[0], 0, MediaDataController.MEDIA_MUSIC, 0, 1, playlistClassGuid, 0, null, null); } } @@ -5568,6 +5568,7 @@ public static class PlaylistGlobalSearchParams { final String query; final FiltersView.MediaFilterData filter; final long dialogId; + public long topicId; final long minDate; final long maxDate; public int totalCount; @@ -5575,6 +5576,8 @@ public static class PlaylistGlobalSearchParams { public int nextSearchRate; public int folderId; + public ReactionsLayoutInBubble.VisibleReaction reaction; + public PlaylistGlobalSearchParams(String query, long dialogId, long minDate, long maxDate, FiltersView.MediaFilterData filter) { this.filter = filter; this.query = query; diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/MediaDataController.java b/TMessagesProj/src/main/java/org/telegram/messenger/MediaDataController.java index ae7dd8c24b..421522b4e2 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/MediaDataController.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/MediaDataController.java @@ -63,10 +63,12 @@ import org.telegram.tgnet.TLRPC; import org.telegram.ui.ActionBar.BaseFragment; import org.telegram.ui.ActionBar.EmojiThemes; +import org.telegram.ui.ActionBar.Theme; import org.telegram.ui.ChatActivity; import org.telegram.ui.Components.AnimatedEmojiDrawable; import org.telegram.ui.Components.AnimatedEmojiSpan; import org.telegram.ui.Components.AvatarDrawable; +import org.telegram.ui.Components.BackupImageView; import org.telegram.ui.Components.Bulletin; import org.telegram.ui.Components.ChatThemeBottomSheet; import org.telegram.ui.Components.QuoteSpan; @@ -511,7 +513,7 @@ public void processLoadedMenuBots(TLRPC.TL_attachMenuBots bots, long hash, int d boolean forceReload = false; if (bots != null) { if (!cache) { - getMessagesStorage().putUsersAndChats(bots.users, null, true, false); + getMessagesStorage().putUsersAndChats(bots.users, null, true, true); } getMessagesController().putUsers(bots.users, cache); AndroidUtilities.runOnUIThread(() -> NotificationCenter.getInstance(currentAccount).postNotificationName(NotificationCenter.attachMenuBotsDidLoad)); @@ -1148,6 +1150,31 @@ public static TLRPC.InputStickerSet getInputStickerSet(TLRPC.StickerSet set) { return null; } + public void setPlaceholderImage(BackupImageView imageView, String setName, String emoji, String filter) { + TLRPC.InputStickerSet inputStickerSet = new TLRPC.TL_inputStickerSetShortName(); + inputStickerSet.short_name = setName; + MediaDataController.getInstance(currentAccount).getStickerSet(inputStickerSet, 0, false, set -> { + if (set == null) return; + TLRPC.Document document = null; + for (int i = 0; i < set.packs.size(); ++i) { + if (!set.packs.get(i).documents.isEmpty() && TextUtils.equals(set.packs.get(i).emoticon, emoji)) { + long documentId = set.packs.get(i).documents.get(0); + for (int j = 0; j < set.documents.size(); ++j) { + if (set.documents.get(j).id == documentId) { + document = set.documents.get(j); + break; + } + } + break; + } + } + if (document != null) { + Drawable thumbDrawable = DocumentObject.getSvgThumb(document, Theme.key_windowBackgroundWhiteGrayIcon, 0.2f, 1f, null); + imageView.setImage(ImageLocation.getForDocument(document), filter, thumbDrawable, 0, document); + } + }); + } + public TLRPC.TL_messages_stickerSet getStickerSet(TLRPC.InputStickerSet inputStickerSet, boolean cacheOnly) { return getStickerSet(inputStickerSet, null, cacheOnly, null); } @@ -3317,15 +3344,108 @@ public void processStickerSetInstallResultArchive(BaseFragment baseFragment, boo private int lastGuid; private TLRPC.User lastSearchUser; private TLRPC.Chat lastSearchChat; + private int messagesLocalSearchCount; private int[] messagesSearchCount = new int[]{0, 0}; private boolean[] messagesSearchEndReached = new boolean[]{false, false}; - private ArrayList searchResultMessages = new ArrayList<>(); - private SparseArray[] searchResultMessagesMap = new SparseArray[]{new SparseArray<>(), new SparseArray<>()}; + public ArrayList searchResultMessages = new ArrayList<>(); + public ArrayList searchServerResultMessages = new ArrayList<>(); + public ArrayList searchLocalResultMessages = new ArrayList<>(); + private SparseArray[] searchServerResultMessagesMap = new SparseArray[]{new SparseArray<>(), new SparseArray<>()}; + private ArrayList deletedFromResultMessages = new ArrayList<>(); private String lastSearchQuery; private int lastReturnedNum; private boolean loadingMoreSearchMessages; + private boolean loadingSearchLocal; + private boolean loadedPredirectedSearchLocal; - private int getMask() { + public void removeMessageFromResults(int id) { + for (int i = 0; i < searchResultMessages.size(); ++i) { + MessageObject m = searchResultMessages.get(i); + if (id == m.getId()) { + deletedFromResultMessages.add(searchResultMessages.remove(i)); + i--; + } + } + for (int i = 0; i < searchServerResultMessages.size(); ++i) { + MessageObject m = searchServerResultMessages.get(i); + if (id == m.getId()) { + searchServerResultMessages.remove(i); + i--; + } + } + for (int i = 0; i < searchLocalResultMessages.size(); ++i) { + MessageObject m = searchLocalResultMessages.get(i); + if (id == m.getId()) { + searchLocalResultMessages.remove(i); + i--; + } + } + } + + public boolean processDeletedMessage(int id, long[] topic_id) { + boolean updated = false; + MessageObject messageObject = null; + for (int i = 0; i < deletedFromResultMessages.size(); ++i) { + if (deletedFromResultMessages.get(i).getId() == id) { + messageObject = deletedFromResultMessages.get(i); + break; + } + } + if (messageObject != null && messageObject.getDialogId() == getUserConfig().getClientUserId()) { + updated = getMessagesController().processDeletedReactionTags(messageObject.messageOwner); + topic_id[0] = MessageObject.getSavedDialogId(getUserConfig().getClientUserId(), messageObject.messageOwner); + } + deletedFromResultMessages.remove(messageObject); + return updated; + } + + private void updateSearchResults() { + ArrayList previousSearchResultMessages = new ArrayList<>(searchResultMessages); + searchResultMessages.clear(); + HashSet messageIds = new HashSet<>(); + for (int i = 0; i < searchServerResultMessages.size(); ++i) { + MessageObject m = searchServerResultMessages.get(i); + if ((!m.hasValidGroupId() || m.isPrimaryGroupMessage) && !messageIds.contains(m.getId())) { + MessageObject prev = null; + for (int j = 0; j < previousSearchResultMessages.size(); ++j) { + if (previousSearchResultMessages.get(j).getId() == m.getId()) { + prev = previousSearchResultMessages.get(j); + break; + } + } + if (prev != null) { + m.copyStableParams(prev); + m.mediaExists = prev.mediaExists; + m.attachPathExists = prev.attachPathExists; + } + m.isSavedFiltered = true; + searchResultMessages.add(m); + messageIds.add(m.getId()); + } + } + for (int i = 0; i < searchLocalResultMessages.size(); ++i) { + MessageObject m = searchLocalResultMessages.get(i); + if (!messageIds.contains(m.getId())) { + MessageObject prev = null; + for (int j = 0; j < previousSearchResultMessages.size(); ++j) { + if (previousSearchResultMessages.get(j).getId() == m.getId()) { + prev = previousSearchResultMessages.get(j); + break; + } + } + if (prev != null) { + m.copyStableParams(prev); + m.mediaExists = prev.mediaExists; + m.attachPathExists = prev.attachPathExists; + } + m.isSavedFiltered = true; + searchResultMessages.add(m); + messageIds.add(m.getId()); + } + } + } + + public int getMask() { int mask = 0; if (lastReturnedNum < searchResultMessages.size() - 1 || !messagesSearchEndReached[0] || !messagesSearchEndReached[1]) { mask |= 1; @@ -3342,10 +3462,12 @@ public ArrayList getFoundMessageObjects() { public void clearFoundMessageObjects() { searchResultMessages.clear(); + searchServerResultMessages.clear(); + searchLocalResultMessages.clear(); } public boolean isMessageFound(int messageId, boolean mergeDialog) { - return searchResultMessagesMap[mergeDialog ? 1 : 0].indexOfKey(messageId) >= 0; + return searchServerResultMessagesMap[mergeDialog ? 1 : 0].indexOfKey(messageId) >= 0; } public void searchMessagesInChat(String query, long dialogId, long mergeDialogId, int guid, int direction, long replyMessageId, TLRPC.User user, TLRPC.Chat chat, ReactionsLayoutInBubble.VisibleReaction reaction) { @@ -3358,29 +3480,52 @@ public void jumpToSearchedMessage(int guid, int index) { } lastReturnedNum = index; MessageObject messageObject = searchResultMessages.get(lastReturnedNum); - getNotificationCenter().postNotificationName(NotificationCenter.chatSearchResultsAvailable, guid, messageObject.getId(), getMask(), messageObject.getDialogId(), lastReturnedNum, messagesSearchCount[0] + messagesSearchCount[1], true); + getNotificationCenter().postNotificationName(NotificationCenter.chatSearchResultsAvailable, guid, messageObject.getId(), getMask(), messageObject.getDialogId(), lastReturnedNum, getSearchCount(), true); + } + + public int getSearchPosition() { + return lastReturnedNum; + } + + public int getSearchCount() { + if (searchServerResultMessages.isEmpty()) { + return Math.max(Math.max(messagesSearchCount[0] + messagesSearchCount[1], messagesLocalSearchCount), searchServerResultMessages.size()); + } + return Math.max(messagesSearchCount[0] + messagesSearchCount[1], searchServerResultMessages.size()); + } + + public void setSearchedPosition(int index) { + if (index < 0 || index >= searchResultMessages.size()) { + return; + } + lastReturnedNum = index; } public boolean searchEndReached() { - return messagesSearchEndReached[0] && lastMergeDialogId == 0 && messagesSearchEndReached[1]; + return messagesSearchEndReached[0] && lastMergeDialogId == 0 && messagesSearchEndReached[1] || (loadingSearchLocal || loadedPredirectedSearchLocal); } - public void loadMoreSearchMessages() { - if (loadingMoreSearchMessages || messagesSearchEndReached[0] && lastMergeDialogId == 0 && messagesSearchEndReached[1]) { + public void loadMoreSearchMessages(boolean fromList) { + if (loadingMoreSearchMessages || reqId != 0 || messagesSearchEndReached[0] && lastMergeDialogId == 0 && messagesSearchEndReached[1]) { return; } - int temp = searchResultMessages.size(); + int temp = lastReturnedNum; lastReturnedNum = searchResultMessages.size(); + loadingMoreSearchMessages = true; searchMessagesInChat(null, lastDialogId, lastMergeDialogId, lastGuid, 1, lastReplyMessageId, false, lastSearchUser, lastSearchChat, false, lastReaction); lastReturnedNum = temp; - loadingMoreSearchMessages = true; } - private void searchMessagesInChat(String query, long dialogId, long mergeDialogId, int guid, int direction, long replyMessageId, boolean internal, TLRPC.User user, TLRPC.Chat chat, boolean jumpToMessage, ReactionsLayoutInBubble.VisibleReaction reaction) { + public boolean isSearchLoading() { + return reqId != 0; + } + + public void searchMessagesInChat(String query, long dialogId, long mergeDialogId, int guid, int direction, long replyMessageId, boolean internal, TLRPC.User user, TLRPC.Chat chat, boolean jumpToMessage, ReactionsLayoutInBubble.VisibleReaction reaction) { int max_id = 0; long queryWithDialog = dialogId; boolean firstQuery = !internal; if (reqId != 0) { + loadingMoreSearchMessages = false; getConnectionsManager().cancelRequest(reqId, true); reqId = 0; } @@ -3390,17 +3535,20 @@ private void searchMessagesInChat(String query, long dialogId, long mergeDialogI } if (query == null) { if (searchResultMessages.isEmpty()) { + loadingMoreSearchMessages = false; return; } if (direction == 1) { lastReturnedNum++; if (lastReturnedNum < searchResultMessages.size()) { MessageObject messageObject = searchResultMessages.get(lastReturnedNum); - getNotificationCenter().postNotificationName(NotificationCenter.chatSearchResultsAvailable, guid, messageObject.getId(), getMask(), messageObject.getDialogId(), lastReturnedNum, messagesSearchCount[0] + messagesSearchCount[1], jumpToMessage); + getNotificationCenter().postNotificationName(NotificationCenter.chatSearchResultsAvailable, guid, messageObject.getId(), getMask(), messageObject.getDialogId(), lastReturnedNum, getSearchCount(), jumpToMessage); + loadingMoreSearchMessages = false; return; } else { if (messagesSearchEndReached[0] && mergeDialogId == 0 && messagesSearchEndReached[1]) { lastReturnedNum--; + loadingMoreSearchMessages = false; return; } firstQuery = false; @@ -3427,17 +3575,20 @@ private void searchMessagesInChat(String query, long dialogId, long mergeDialogI lastReturnedNum = searchResultMessages.size() - 1; } MessageObject messageObject = searchResultMessages.get(lastReturnedNum); - getNotificationCenter().postNotificationName(NotificationCenter.chatSearchResultsAvailable, guid, messageObject.getId(), getMask(), messageObject.getDialogId(), lastReturnedNum, messagesSearchCount[0] + messagesSearchCount[1], jumpToMessage); + getNotificationCenter().postNotificationName(NotificationCenter.chatSearchResultsAvailable, guid, messageObject.getId(), getMask(), messageObject.getDialogId(), lastReturnedNum, getSearchCount(), jumpToMessage); + loadingMoreSearchMessages = false; return; } else { + loadingMoreSearchMessages = false; return; } } else if (firstQuery) { messagesSearchEndReached[0] = messagesSearchEndReached[1] = false; messagesSearchCount[0] = messagesSearchCount[1] = 0; searchResultMessages.clear(); - searchResultMessagesMap[0].clear(); - searchResultMessagesMap[1].clear(); + searchLocalResultMessages.clear(); + searchServerResultMessagesMap[0].clear(); + searchServerResultMessagesMap[1].clear(); getNotificationCenter().postNotificationName(NotificationCenter.chatSearchResultsLoading, guid); } if (messagesSearchEndReached[0] && !messagesSearchEndReached[1] && mergeDialogId != 0) { @@ -3500,6 +3651,7 @@ private void searchMessagesInChat(String query, long dialogId, long mergeDialogI TLRPC.TL_messages_search req = new TLRPC.TL_messages_search(); req.peer = getMessagesController().getInputPeer(queryWithDialog); if (req.peer == null) { + loadingMoreSearchMessages = false; return; } lastGuid = guid; @@ -3518,6 +3670,33 @@ private void searchMessagesInChat(String query, long dialogId, long mergeDialogI req.from_id = MessagesController.getInputPeer(chat); req.flags |= 1; } + loadingSearchLocal = false; + loadedPredirectedSearchLocal = false; + int currentReqId = ++lastReqId; + final boolean isSaved = dialogId == getUserConfig().getClientUserId(); + if (isSaved && reaction != null && firstQuery) { + lastReturnedNum = 0; + searchServerResultMessages.clear(); + searchServerResultMessagesMap[0].clear(); + searchServerResultMessagesMap[1].clear(); + + final int predictedCount = getMessagesController().getSavedTagCount(lastReplyMessageId, reaction); + messagesLocalSearchCount = TextUtils.isEmpty(req.q) ? predictedCount : 0; + loadingSearchLocal = true; + loadedPredirectedSearchLocal = false; + getMessagesStorage().searchSavedByTag(reaction.toTLReaction(), lastReplyMessageId, query, 300, searchLocalResultMessages == null ? 0 : searchLocalResultMessages.size(), (messages, users, chats, emojis) -> { + if (currentReqId == lastReqId) { + loadedPredirectedSearchLocal = messages.size() == predictedCount; + loadingSearchLocal = false; + getMessagesController().putUsers(users, true); + getMessagesController().putChats(chats, true); + AnimatedEmojiDrawable.getDocumentFetcher(currentAccount).processDocuments(emojis); + searchLocalResultMessages = messages; + updateSearchResults(); + getNotificationCenter().postNotificationName(NotificationCenter.chatSearchResultsAvailable, guid, 0, getMask(), dialogId, lastReturnedNum, getSearchCount(), true); + } + }, true); + } if (lastReplyMessageId != 0) { if (queryWithDialog == getUserConfig().getClientUserId()) { req.saved_peer_id = getMessagesController().getInputPeer(lastReplyMessageId); @@ -3532,7 +3711,6 @@ private void searchMessagesInChat(String query, long dialogId, long mergeDialogI req.flags |= 8; } req.filter = new TLRPC.TL_inputMessagesFilterEmpty(); - int currentReqId = ++lastReqId; lastSearchQuery = query; long queryWithDialogFinal = queryWithDialog; String finalQuery = query; @@ -3541,10 +3719,13 @@ private void searchMessagesInChat(String query, long dialogId, long mergeDialogI if (error == null) { TLRPC.messages_Messages res = (TLRPC.messages_Messages) response; - int N = Math.min(res.messages.size(), 20); + int N = Math.min(res.messages.size(), req.limit - 1); for (int a = 0; a < N; a++) { TLRPC.Message message = res.messages.get(a); - MessageObject messageObject = new MessageObject(currentAccount, message, false, false); + MessageObject messageObject = new MessageObject(currentAccount, message, null, null, null, null, null, true, true, 0, false, false, isSaved); + if (messageObject.hasValidGroupId()) { + messageObject.isPrimaryGroupMessage = true; + } messageObject.setQuery(finalQuery); messageObjects.add(messageObject); } @@ -3567,38 +3748,47 @@ private void searchMessagesInChat(String query, long dialogId, long mergeDialogI getMessagesStorage().putUsersAndChats(res.users, res.chats, true, true); getMessagesController().putUsers(res.users, false); getMessagesController().putChats(res.chats, false); - if (req.offset_id == 0 && queryWithDialogFinal == dialogId) { - lastReturnedNum = 0; - searchResultMessages.clear(); - searchResultMessagesMap[0].clear(); - searchResultMessagesMap[1].clear(); - messagesSearchCount[0] = 0; - getNotificationCenter().postNotificationName(NotificationCenter.chatSearchResultsLoading, guid); - } - boolean added = false; - int N = Math.min(res.messages.size(), 20); - for (int a = 0; a < N; a++) { - TLRPC.Message message = res.messages.get(a); - added = true; - MessageObject messageObject = messageObjects.get(a); - searchResultMessages.add(messageObject); - searchResultMessagesMap[queryWithDialogFinal == dialogId ? 0 : 1].put(messageObject.getId(), messageObject); - } - messagesSearchEndReached[queryWithDialogFinal == dialogId ? 0 : 1] = res.messages.size() < req.limit; - messagesSearchCount[queryWithDialogFinal == dialogId ? 0 : 1] = res instanceof TLRPC.TL_messages_messagesSlice || res instanceof TLRPC.TL_messages_channelMessages ? res.count : res.messages.size(); - if (searchResultMessages.isEmpty()) { - getNotificationCenter().postNotificationName(NotificationCenter.chatSearchResultsAvailable, guid, 0, getMask(), (long) 0, 0, 0, jumpToMessage); - } else { - if (added) { - if (lastReturnedNum >= searchResultMessages.size()) { - lastReturnedNum = searchResultMessages.size() - 1; + Runnable done = () -> { + if (req.offset_id == 0 && queryWithDialogFinal == dialogId) { + lastReturnedNum = 0; + searchServerResultMessages.clear(); + searchServerResultMessagesMap[0].clear(); + searchServerResultMessagesMap[1].clear(); + messagesSearchCount[0] = 0; + getNotificationCenter().postNotificationName(NotificationCenter.chatSearchResultsLoading, guid); + } + boolean added = false; + int N = Math.min(res.messages.size(), req.limit - 1); + for (int a = 0; a < N; a++) { + added = true; + MessageObject messageObject = messageObjects.get(a); + searchServerResultMessages.add(messageObject); + searchServerResultMessagesMap[queryWithDialogFinal == dialogId ? 0 : 1].put(messageObject.getId(), messageObject); + } + updateSearchResults(); + messagesSearchEndReached[queryWithDialogFinal == dialogId ? 0 : 1] = res.messages.size() < req.limit; + messagesSearchCount[queryWithDialogFinal == dialogId ? 0 : 1] = res instanceof TLRPC.TL_messages_messagesSlice || res instanceof TLRPC.TL_messages_channelMessages ? res.count : res.messages.size(); + if (searchServerResultMessages.isEmpty()) { + getNotificationCenter().postNotificationName(NotificationCenter.chatSearchResultsAvailable, guid, 0, getMask(), (long) 0, 0, 0, jumpToMessage); + } else { + if (added) { + if (lastReturnedNum >= searchResultMessages.size()) { + lastReturnedNum = searchResultMessages.size() - 1; + } + MessageObject messageObject = searchResultMessages.get(lastReturnedNum); + getNotificationCenter().postNotificationName(NotificationCenter.chatSearchResultsAvailable, guid, messageObject.getId(), getMask(), messageObject.getDialogId(), lastReturnedNum, getSearchCount(), jumpToMessage); + } else if (isSaved) { + getNotificationCenter().postNotificationName(NotificationCenter.chatSearchResultsAvailable, guid, 0, getMask(), dialogId, lastReturnedNum, getSearchCount(), false); } - MessageObject messageObject = searchResultMessages.get(lastReturnedNum); - getNotificationCenter().postNotificationName(NotificationCenter.chatSearchResultsAvailable, guid, messageObject.getId(), getMask(), messageObject.getDialogId(), lastReturnedNum, messagesSearchCount[0] + messagesSearchCount[1], jumpToMessage); } - } - if (queryWithDialogFinal == dialogId && messagesSearchEndReached[0] && mergeDialogId != 0 && !messagesSearchEndReached[1]) { - searchMessagesInChat(lastSearchQuery, dialogId, mergeDialogId, guid, 0, replyMessageId, true, user, chat, jumpToMessage, lastReaction); + if (queryWithDialogFinal == dialogId && messagesSearchEndReached[0] && mergeDialogId != 0 && !messagesSearchEndReached[1]) { + searchMessagesInChat(lastSearchQuery, dialogId, mergeDialogId, guid, 0, replyMessageId, true, user, chat, jumpToMessage, lastReaction); + } + }; + if (isSaved) { + loadReplyMessagesForMessages(messageObjects, dialogId, false, lastReplyMessageId, done, guid); + } else { + done.run(); } } } @@ -3606,6 +3796,22 @@ private void searchMessagesInChat(String query, long dialogId, long mergeDialogI }, ConnectionsManager.RequestFlagFailOnServerErrors); } + public void portSavedSearchResults(int guid, ReactionsLayoutInBubble.VisibleReaction reaction, String query, ArrayList local, ArrayList loaded, int num, int count, boolean reached) { + lastReaction = reaction; + lastSearchQuery = query; + messagesSearchEndReached[0] = reached; + messagesSearchEndReached[1] = true; + searchServerResultMessages.clear(); + searchServerResultMessages.addAll(loaded); + searchLocalResultMessages.clear(); + searchLocalResultMessages.addAll(local); + updateSearchResults(); + messagesSearchCount[0] = count; + messagesSearchCount[1] = 0; + lastReturnedNum = num; + getNotificationCenter().postNotificationName(NotificationCenter.chatSearchResultsAvailable, guid, 0, getMask(), getUserConfig().getClientUserId(), lastReturnedNum, getSearchCount(), true); + } + public String getLastSearchQuery() { return lastSearchQuery; } @@ -3624,18 +3830,18 @@ public String getLastSearchQuery() { public final static int MEDIA_STORIES = 8; - public void loadMedia(long dialogId, int count, int max_id, int min_id, int type, long topicId, int fromCache, int classGuid, int requestIndex) { - loadMedia(dialogId, count, max_id, min_id, type, topicId, fromCache, classGuid, requestIndex, false); + public void loadMedia(long dialogId, int count, int max_id, int min_id, int type, long topicId, int fromCache, int classGuid, int requestIndex, ReactionsLayoutInBubble.VisibleReaction tag, String query) { + loadMedia(dialogId, count, max_id, min_id, type, topicId, fromCache, classGuid, requestIndex, tag, query, false); } - public void loadMedia(long dialogId, int count, int max_id, int min_id, int type, long topicId, int fromCache, int classGuid, int requestIndex, boolean skipPhotos) { + public void loadMedia(long dialogId, int count, int max_id, int min_id, int type, long topicId, int fromCache, int classGuid, int requestIndex, ReactionsLayoutInBubble.VisibleReaction tag, String query, boolean skipPhotos) { boolean isChannel = DialogObject.isChatDialog(dialogId) && ChatObject.isChannel(-dialogId, currentAccount); if (BuildVars.LOGS_ENABLED) { FileLog.d("load media did " + dialogId + " count = " + count + " max_id " + max_id + " type = " + type + " cache = " + fromCache + " classGuid = " + classGuid); } - if (fromCache != 0 || DialogObject.isEncryptedDialog(dialogId)) { - loadMediaDatabase(dialogId, count, max_id, min_id, type, topicId, classGuid, isChannel, fromCache, requestIndex, skipPhotos); + if (fromCache != 0 && TextUtils.isEmpty(query) || DialogObject.isEncryptedDialog(dialogId)) { + loadMediaDatabase(dialogId, count, max_id, min_id, type, topicId, tag, classGuid, isChannel, fromCache, requestIndex, skipPhotos); } else { TLRPC.TL_messages_search req = new TLRPC.TL_messages_search(); req.limit = count; @@ -3645,6 +3851,10 @@ public void loadMedia(long dialogId, int count, int max_id, int min_id, int type } else { req.offset_id = max_id; } + if (tag != null) { + req.flags |= 8; + req.saved_reaction.add(tag.toTLReaction()); + } if (type == MEDIA_PHOTOVIDEO) { req.filter = skipPhotos @@ -3666,7 +3876,11 @@ public void loadMedia(long dialogId, int count, int max_id, int min_id, int type } else if (type == MEDIA_GIF) { req.filter = new TLRPC.TL_inputMessagesFilterGif(); } - req.q = ""; + if (!TextUtils.isEmpty(query)) { + req.q = query; + } else { + req.q = ""; + } req.peer = getMessagesController().getInputPeer(dialogId); if (topicId != 0) { if (dialogId == getUserConfig().getClientUserId()) { @@ -3814,7 +4028,7 @@ public void getMediaCounts(long dialogId, long topicId, int classGuid) { }); getConnectionsManager().bindRequestToGuid(reqId, classGuid); } - if (!missing) { + if (!missing || getConnectionsManager().getConnectionState() != ConnectionsManager.ConnectionStateConnected) { AndroidUtilities.runOnUIThread(() -> getNotificationCenter().postNotificationName(NotificationCenter.mediaCountsDidLoad, dialogId, topicId, countsFinal)); } } @@ -3844,7 +4058,7 @@ public void getMediaCount(long dialogId, long topicId, int type, int classGuid, } if (topicId != 0) { if (dialogId == getUserConfig().getClientUserId()) { - req.saved_peer_id = getMessagesController().getInputPeer(dialogId); + req.saved_peer_id = getMessagesController().getInputPeer(topicId); req.flags |= 4; } else { req.top_msg_id = (int) topicId; @@ -3947,7 +4161,7 @@ private void processLoadedMedia(TLRPC.messages_Messages res, long dialogId, int if (fromCache == 2) { return; } - loadMedia(dialogId, count, max_id, min_id, type, topicId, 0, classGuid, requestIndex, skipPhotos); + loadMedia(dialogId, count, max_id, min_id, type, topicId, 0, classGuid, requestIndex, null, null, skipPhotos); } else { if (fromCache == 0) { ImageLoader.saveMessagesThumbs(res.messages); @@ -4078,11 +4292,12 @@ private void getMediaCountDatabase(long dialogId, long topicId, int type, int cl }); } - private void loadMediaDatabase(long uid, int count, int max_id, int min_id, int type, long topicId, int classGuid, boolean isChannel, int fromCache, int requestIndex, boolean skipPhotos) { + private void loadMediaDatabase(long uid, int count, int max_id, int min_id, int type, long topicId, ReactionsLayoutInBubble.VisibleReaction tag, int classGuid, boolean isChannel, int fromCache, int requestIndex, boolean skipPhotos) { Runnable runnable = new Runnable() { @Override public void run() { boolean topReached = false; + final long selfId = getUserConfig().getClientUserId(); TLRPC.TL_messages_messages res = new TLRPC.TL_messages_messages(); try { ArrayList usersToLoad = new ArrayList<>(); @@ -4136,6 +4351,20 @@ public void run() { cursor.dispose(); } + String beforeWhere = ""; + String afterWhere = ""; + + if (tag != null) { + long taghash = 0; + if (!TextUtils.isEmpty(tag.emojicon)) { + taghash = tag.emojicon.hashCode(); + } else { + taghash = tag.documentId; + } + beforeWhere = "INNER JOIN tag_message_id t ON m.mid = t.mid"; + afterWhere = "t.tag = " + taghash + " AND"; + } + int holeMessageId = 0; if (max_id != 0) { int startHole = 0; @@ -4152,17 +4381,17 @@ public void run() { if (topicId != 0) { if (holeMessageId > 1) { - cursor = database.queryFinalized(String.format(Locale.US, "SELECT data, mid FROM media_topics WHERE uid = %d AND topic_id = %d AND mid > 0 AND mid < %d AND mid >= %d AND type = %d ORDER BY date DESC, mid DESC LIMIT %d", uid, topicId, max_id, holeMessageId, type, countToLoad)); + cursor = database.queryFinalized(String.format(Locale.US, "SELECT m.data, m.mid FROM media_topics m %s WHERE %s m.uid = %d AND m.topic_id = %d AND m.mid > 0 AND m.mid < %d AND m.mid >= %d AND m.type = %d ORDER BY m.date DESC, m.mid DESC LIMIT %d", beforeWhere, afterWhere, uid, topicId, max_id, holeMessageId, type, countToLoad)); isEnd = false; } else { - cursor = database.queryFinalized(String.format(Locale.US, "SELECT data, mid FROM media_topics WHERE uid = %d AND topic_id = %d AND mid > 0 AND mid < %d AND type = %d ORDER BY date DESC, mid DESC LIMIT %d", uid, topicId, max_id, type, countToLoad)); + cursor = database.queryFinalized(String.format(Locale.US, "SELECT m.data, m.mid FROM media_topics m %s WHERE %s m.uid = %d AND m.topic_id = %d AND m.mid > 0 AND m.mid < %d AND m.type = %d ORDER BY m.date DESC, m.mid DESC LIMIT %d", beforeWhere, afterWhere, uid, topicId, max_id, type, countToLoad)); } } else { if (holeMessageId > 1) { - cursor = database.queryFinalized(String.format(Locale.US, "SELECT data, mid FROM media_v4 WHERE uid = %d AND mid > 0 AND mid < %d AND mid >= %d AND type = %d ORDER BY date DESC, mid DESC LIMIT %d", uid, max_id, holeMessageId, type, countToLoad)); + cursor = database.queryFinalized(String.format(Locale.US, "SELECT m.data, m.mid FROM media_v4 m %s WHERE %s m.uid = %d AND m.mid > 0 AND m.mid < %d AND m.mid >= %d AND m.type = %d ORDER BY m.date DESC, m.mid DESC LIMIT %d", beforeWhere, afterWhere, uid, max_id, holeMessageId, type, countToLoad)); isEnd = false; } else { - cursor = database.queryFinalized(String.format(Locale.US, "SELECT data, mid FROM media_v4 WHERE uid = %d AND mid > 0 AND mid < %d AND type = %d ORDER BY date DESC, mid DESC LIMIT %d", uid, max_id, type, countToLoad)); + cursor = database.queryFinalized(String.format(Locale.US, "SELECT m.data, m.mid FROM media_v4 m %s WHERE %s m.uid = %d AND m.mid > 0 AND m.mid < %d AND m.type = %d ORDER BY m.date DESC, m.mid DESC LIMIT %d", beforeWhere, afterWhere, uid, max_id, type, countToLoad)); } } } else if (min_id != 0) { @@ -4180,17 +4409,17 @@ public void run() { reverseMessages = true; if (topicId != 0) { if (startHole > 1) { - cursor = database.queryFinalized(String.format(Locale.US, "SELECT data, mid FROM media_topics WHERE uid = %d AND topic_id = %d AND mid > 0 AND mid >= %d AND mid <= %d AND type = %d ORDER BY date ASC, mid ASC LIMIT %d", uid, topicId, min_id, startHole, type, countToLoad)); + cursor = database.queryFinalized(String.format(Locale.US, "SELECT m.data, m.mid FROM media_topics m %s WHERE %s m.uid = %d AND m.topic_id = %d AND m.mid > 0 AND m.mid >= %d AND m.mid <= %d AND m.type = %d ORDER BY m.date ASC, m.mid ASC LIMIT %d", beforeWhere, afterWhere, uid, topicId, min_id, startHole, type, countToLoad)); } else { isEnd = true; - cursor = database.queryFinalized(String.format(Locale.US, "SELECT data, mid FROM media_topics WHERE uid = %d AND topic_id = %d AND mid > 0 AND mid >= %d AND type = %d ORDER BY date ASC, mid ASC LIMIT %d", uid, topicId, min_id, type, countToLoad)); + cursor = database.queryFinalized(String.format(Locale.US, "SELECT m.data, m.mid FROM media_topics m %s WHERE %s m.uid = %d AND m.topic_id = %d AND m.mid > 0 AND m.mid >= %d AND m.type = %d ORDER BY m.date ASC, m.mid ASC LIMIT %d", beforeWhere, afterWhere, uid, topicId, min_id, type, countToLoad)); } } else { if (startHole > 1) { - cursor = database.queryFinalized(String.format(Locale.US, "SELECT data, mid FROM media_v4 WHERE uid = %d AND mid > 0 AND mid >= %d AND mid <= %d AND type = %d ORDER BY date ASC, mid ASC LIMIT %d", uid, min_id, startHole, type, countToLoad)); + cursor = database.queryFinalized(String.format(Locale.US, "SELECT m.data, m.mid FROM media_v4 m %s WHERE %s m.uid = %d AND m.mid > 0 AND m.mid >= %d AND m.mid <= %d AND m.type = %d ORDER BY m.date ASC, m.mid ASC LIMIT %d", beforeWhere, afterWhere, uid, min_id, startHole, type, countToLoad)); } else { isEnd = true; - cursor = database.queryFinalized(String.format(Locale.US, "SELECT data, mid FROM media_v4 WHERE uid = %d AND mid > 0 AND mid >= %d AND type = %d ORDER BY date ASC, mid ASC LIMIT %d", uid, min_id, type, countToLoad)); + cursor = database.queryFinalized(String.format(Locale.US, "SELECT m.data, m.mid FROM media_v4 m %s WHERE %s m.uid = %d AND m.mid > 0 AND m.mid >= %d AND m.type = %d ORDER BY m.date ASC, m.mid ASC LIMIT %d", beforeWhere, afterWhere, uid, min_id, type, countToLoad)); } } } else { @@ -4205,15 +4434,15 @@ public void run() { cursor.dispose(); if (topicId != 0) { if (holeMessageId > 1) { - cursor = database.queryFinalized(String.format(Locale.US, "SELECT data, mid FROM media_topics WHERE uid = %d AND topic_id = %d AND mid >= %d AND type = %d ORDER BY date DESC, mid DESC LIMIT %d", uid, topicId, holeMessageId, type, countToLoad)); + cursor = database.queryFinalized(String.format(Locale.US, "SELECT m.data, m.mid FROM media_topics m %s WHERE %s m.uid = %d AND m.topic_id = %d AND m.mid >= %d AND m.type = %d ORDER BY m.date DESC, m.mid DESC LIMIT %d", beforeWhere, afterWhere, uid, topicId, holeMessageId, type, countToLoad)); } else { - cursor = database.queryFinalized(String.format(Locale.US, "SELECT data, mid FROM media_topics WHERE uid = %d AND topic_id = %d AND mid > 0 AND type = %d ORDER BY date DESC, mid DESC LIMIT %d", uid, topicId, type, countToLoad)); + cursor = database.queryFinalized(String.format(Locale.US, "SELECT m.data, m.mid FROM media_topics m %s WHERE %s m.uid = %d AND m.topic_id = %d AND m.mid > 0 AND m.type = %d ORDER BY m.date DESC, m.mid DESC LIMIT %d", beforeWhere, afterWhere, uid, topicId, type, countToLoad)); } } else { if (holeMessageId > 1) { - cursor = database.queryFinalized(String.format(Locale.US, "SELECT data, mid FROM media_v4 WHERE uid = %d AND mid >= %d AND type = %d ORDER BY date DESC, mid DESC LIMIT %d", uid, holeMessageId, type, countToLoad)); + cursor = database.queryFinalized(String.format(Locale.US, "SELECT m.data, m.mid FROM media_v4 m %s WHERE %s m.uid = %d AND m.mid >= %d AND m.type = %d ORDER BY m.date DESC, m.mid DESC LIMIT %d", beforeWhere, afterWhere, uid, holeMessageId, type, countToLoad)); } else { - cursor = database.queryFinalized(String.format(Locale.US, "SELECT data, mid FROM media_v4 WHERE uid = %d AND mid > 0 AND type = %d ORDER BY date DESC, mid DESC LIMIT %d", uid, type, countToLoad)); + cursor = database.queryFinalized(String.format(Locale.US, "SELECT m.data, m.mid FROM media_v4 m %s WHERE %s m.uid = %d AND m.mid > 0 AND m.type = %d ORDER BY m.date DESC, m.mid DESC LIMIT %d", beforeWhere, afterWhere, uid, type, countToLoad)); } } } @@ -4239,11 +4468,12 @@ public void run() { } + HashSet groupsToLoad = tag != null ? new HashSet<>() : null; while (cursor.next()) { NativeByteBuffer data = cursor.byteBufferValue(0); if (data != null) { TLRPC.Message message = TLRPC.Message.TLdeserialize(data, data.readInt32(false), false); - message.readAttachPath(data, getUserConfig().clientUserId); + message.readAttachPath(data, selfId); data.reuse(); message.id = cursor.intValue(1); message.dialog_id = uid; @@ -4255,6 +4485,9 @@ public void run() { continue; } + if (message.grouped_id != 0 && groupsToLoad != null) { + groupsToLoad.add(message.grouped_id); + } if (reverseMessages) { res.messages.add(0, message); } else { @@ -4266,6 +4499,38 @@ public void run() { } cursor.dispose(); + if (tag != null && !groupsToLoad.isEmpty()) { + for (long grouped_id : groupsToLoad) { + int index = -1; + for (int i = 0; i < res.messages.size(); ++i) { + if (res.messages.get(i).grouped_id == grouped_id) { + index = i; + break; + } + } + if (index < 0) continue; + cursor = database.queryFinalized("SELECT data, mid FROM messages_v2 WHERE uid = ? AND group_id = ? ORDER BY mid DESC", uid, grouped_id); + ArrayList groupMessages = new ArrayList<>(); + while (cursor.next()) { + int id = cursor.intValue(1); + NativeByteBuffer data = cursor.byteBufferValue(0); + if (data == null) continue; + TLRPC.Message message = TLRPC.Message.TLdeserialize(data, data.readInt32(false), false); + message.readAttachPath(data, selfId); + data.reuse(); + message.id = id; + message.dialog_id = uid; + groupMessages.add(message); + MessagesStorage.addUsersAndChatsFromMessage(message, usersToLoad, chatsToLoad, null); + } + if (reverseMessages) + Collections.reverse(groupMessages); + res.messages.remove(index); + res.messages.addAll(index, groupMessages); + cursor.dispose(); + } + } + if (!usersToLoad.isEmpty()) { getMessagesStorage().getUsersInternal(TextUtils.join(",", usersToLoad), res.users); } @@ -7562,8 +7827,12 @@ public interface KeywordResultCallback { } private HashMap currentFetchingEmoji = new HashMap<>(); + private HashSet fetchedEmoji = new HashSet<>(); public void fetchNewEmojiKeywords(String[] langCodes) { + fetchNewEmojiKeywords(langCodes, false); + } + public void fetchNewEmojiKeywords(String[] langCodes, boolean doNotFetchTwice) { if (langCodes == null) { return; } @@ -7572,7 +7841,7 @@ public void fetchNewEmojiKeywords(String[] langCodes) { if (TextUtils.isEmpty(langCode)) { return; } - if (currentFetchingEmoji.get(langCode) != null) { + if (currentFetchingEmoji.get(langCode) != null || doNotFetchTwice && fetchedEmoji.contains(langCode)) { return; } currentFetchingEmoji.put(langCode, true); @@ -7592,7 +7861,11 @@ public void fetchNewEmojiKeywords(String[] langCodes) { FileLog.e(e); } if (!BuildVars.DEBUG_VERSION && Math.abs(System.currentTimeMillis() - date) < 60 * 60 * 1000) { - AndroidUtilities.runOnUIThread(() -> currentFetchingEmoji.remove(langCode)); + AndroidUtilities.runOnUIThread(() -> { + currentFetchingEmoji.remove(langCode); + fetchedEmoji.add(langCode); + getNotificationCenter().postNotificationName(NotificationCenter.emojiKeywordsLoaded); + }); return; } TLObject request; @@ -7621,7 +7894,9 @@ public void fetchNewEmojiKeywords(String[] langCodes) { AndroidUtilities.runOnUIThread(() -> { currentFetchingEmoji.remove(langCode); + fetchedEmoji.add(langCode); fetchNewEmojiKeywords(new String[]{langCode}); + getNotificationCenter().postNotificationName(NotificationCenter.emojiKeywordsLoaded); }); } catch (Exception e) { FileLog.e(e); @@ -7629,9 +7904,16 @@ public void fetchNewEmojiKeywords(String[] langCodes) { }); } else { putEmojiKeywords(langCode, res); + AndroidUtilities.runOnUIThread(() -> { + getNotificationCenter().postNotificationName(NotificationCenter.emojiKeywordsLoaded); + }); } } else { - AndroidUtilities.runOnUIThread(() -> currentFetchingEmoji.remove(langCode)); + AndroidUtilities.runOnUIThread(() -> { + currentFetchingEmoji.remove(langCode); + fetchedEmoji.add(langCode); + getNotificationCenter().postNotificationName(NotificationCenter.emojiKeywordsLoaded); + }); } }); }); @@ -7748,6 +8030,44 @@ public void getAnimatedEmojiByKeywords(String query, Utilities.Callback> whenDone) { + if (whenDone == null || emoji == null) return; + getMessagesStorage().getStorageQueue().postRunnable(() -> { + SQLiteCursor cursor = null; + try { + Object[] args = new Object[1 + langCodes.length]; + args[0] = emoji; + String langQuery = "1 = 1"; + for (int i = 0; i < langCodes.length; ++i) { + if (i == 0) langQuery = "lang = ?"; + else langQuery = langQuery + " OR lang = ?"; + cursor = getMessagesStorage().getDatabase().queryFinalized("SELECT alias FROM emoji_keywords_info_v2 WHERE lang = ?", langCodes[i]); + if (cursor.next()) { + langCodes[i] = cursor.stringValue(0); + } + cursor.dispose(); + args[1 + i] = langCodes[i]; + } + cursor = getMessagesStorage().getDatabase().executeFast("SELECT keyword FROM emoji_keywords_v2 WHERE emoji = ? AND (" + langQuery + ")").query(args); + ArrayList names = new ArrayList<>(); + while (cursor.next()) { + String name = cursor.stringValue(0); + names.add(name); + } + AndroidUtilities.runOnUIThread(() -> { + whenDone.run(names); + }); + } catch (Exception e) { + FileLog.e(e); + } finally { + if (cursor != null) { + cursor.dispose(); + cursor = null; + } + } + }); + } + public void getEmojiSuggestions(String[] langCodes, String keyword, boolean fullMatch, KeywordResultCallback callback, boolean allowAnimated) { getEmojiSuggestions(langCodes, keyword, fullMatch, callback, null, allowAnimated, false, false, null); } @@ -8498,7 +8818,7 @@ public void loadSavedReactions(boolean force) { saveReactionsToPref(savedReactionsPref, reactions.hash, reactions.reactions); - getNotificationCenter().postNotificationName(NotificationCenter.savedReactionTagsUpdate); + getNotificationCenter().postNotificationName(NotificationCenter.savedReactionTagsUpdate, 0L); } if (response instanceof TLRPC.TL_messages_reactionsNotModified) { diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/MessageObject.java b/TMessagesProj/src/main/java/org/telegram/messenger/MessageObject.java index 7d5b6ec674..108d799b0a 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/MessageObject.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/MessageObject.java @@ -34,6 +34,7 @@ import android.text.util.Linkify; import android.util.Base64; import android.util.Log; +import android.util.SparseIntArray; import androidx.annotation.NonNull; import androidx.collection.LongSparseArray; @@ -176,6 +177,7 @@ public class MessageObject { public long eventId; public int contentType; public String dateKey; + public int dateKeyInt; public String monthKey; public boolean deleted; public boolean deletedByThanos; @@ -327,6 +329,7 @@ public class MessageObject { public boolean forceAvatar; public Drawable customAvatarDrawable; public boolean isSaved; + public boolean isSavedFiltered; private byte[] randomWaveform; public boolean drawServiceWithDefaultTypeface; @@ -584,6 +587,10 @@ public boolean isReplyToStory() { return !(replyMessageObject != null && replyMessageObject.messageOwner instanceof TLRPC.TL_messageEmpty) && messageOwner.reply_to != null && messageOwner.reply_to.story_id != 0 && (messageOwner.flags & TLRPC.MESSAGE_FLAG_REPLY) != 0; } + public boolean isUnsupported() { + return getMedia(messageOwner) instanceof TLRPC.TL_messageMediaUnsupported; + } + public boolean isExpiredStory() { return (type == MessageObject.TYPE_STORY || type == MessageObject.TYPE_STORY_MENTION) && messageOwner.media.storyItem instanceof TL_stories.TL_storyItemDeleted; } @@ -943,9 +950,21 @@ public static class GroupedMessages { public ArrayList messages = new ArrayList<>(); public ArrayList posArray = new ArrayList<>(); public HashMap positions = new HashMap<>(); + public LongSparseArray positionsArray = new LongSparseArray<>(); public MessageObject captionMessage; public boolean isDocuments; + public GroupedMessagePosition getPosition(MessageObject msg) { + if (msg == null) { + return null; + } + GroupedMessagePosition pos = positions.get(msg); + if (pos == null) { + pos = positionsArray.get(msg.getId()); + } + return pos; + } + private int maxSizeWidth = 800; public final TransitionParams transitionParams = new TransitionParams(); @@ -984,6 +1003,7 @@ private float multiHeight(float[] array, int start, int end) { public void calculate() { posArray.clear(); positions.clear(); + positionsArray.clear(); captionMessage = null; maxSizeWidth = 800; @@ -1013,6 +1033,7 @@ public void calculate() { for (int a = (reversed ? count - 1 : 0); (reversed ? a >= 0 : a < count);) { MessageObject messageObject = messages.get(a); if (a == (reversed ? count - 1 : 0)) { + messageObject.isOutOwnerCached = null; isOut = messageObject.isOutOwner(); needShare = !isOut && ( messageObject.messageOwner.fwd_from != null && messageObject.messageOwner.fwd_from.saved_from_peer != null || @@ -1043,6 +1064,7 @@ public void calculate() { } positions.put(messageObject, position); + positionsArray.put(messageObject.getId(), position); posArray.add(position); if (messageObject.caption != null) { @@ -1065,19 +1087,21 @@ public void calculate() { for (int a = 0; a < count; a++) { GroupedMessagePosition pos = posArray.get(a); pos.flags = POSITION_FLAG_LEFT | POSITION_FLAG_RIGHT; - if (!reversed && a == 0 || reversed && a == count - 1) { + if (a == 0) { pos.flags |= POSITION_FLAG_TOP; pos.last = false; - } else if (reversed && a == 0 || !reversed && a == count - 1) { + } else if (a == count - 1) { pos.flags |= POSITION_FLAG_BOTTOM; pos.last = true; + } else { + pos.last = false; } pos.edge = true; pos.aspectRatio = 1.0f; pos.minX = 0; pos.maxX = 0; - pos.minY = (byte) (reversed ? count - 1 - a : a); - pos.maxY = (byte) (reversed ? count - 1 - a : a); + pos.minY = (byte) a; + pos.maxY = (byte) a; pos.spanSize = 1000; pos.pw = maxSizeWidth; pos.ph = 100; @@ -1383,7 +1407,7 @@ public void calculate() { } public MessageObject findPrimaryMessageObject() { - return findMessageWithFlags(MessageObject.POSITION_FLAG_TOP | MessageObject.POSITION_FLAG_LEFT); + return findMessageWithFlags(reversed ? MessageObject.POSITION_FLAG_BOTTOM | MessageObject.POSITION_FLAG_RIGHT : MessageObject.POSITION_FLAG_TOP | MessageObject.POSITION_FLAG_LEFT); } public MessageObject findCaptionMessageObject() { @@ -1552,7 +1576,7 @@ public MessageObject(int accountNum, TLRPC.Message message, MessageObject replyT this.isRepostPreview = isRepostPreview; this.isRepostVideoPreview = isRepostVideoPreview; - this.isSaved = isSavedMessages; + this.isSaved = isSavedMessages || getDialogId(message) == UserConfig.getInstance(accountNum).getClientUserId(); currentAccount = accountNum; messageOwner = message; @@ -1582,6 +1606,7 @@ public MessageObject(int accountNum, TLRPC.Message message, MessageObject replyT int dateYear = rightNow.get(Calendar.YEAR); int dateMonth = rightNow.get(Calendar.MONTH); dateKey = String.format("%d_%02d_%02d", dateYear, dateMonth, dateDay); + dateKeyInt = dateYear + 10000 * dateMonth + 10000 * 100 * dateDay; monthKey = String.format("%d_%02d", dateYear, dateMonth); createMessageSendInfo(); @@ -1826,6 +1851,7 @@ public MessageObject(int accountNum, TLRPC.TL_channelAdminLogEvent event, ArrayL int dateYear = rightNow.get(Calendar.YEAR); int dateMonth = rightNow.get(Calendar.MONTH); dateKey = String.format("%d_%02d_%02d", dateYear, dateMonth, dateDay); + dateKeyInt = dateYear + 1000 * dateMonth + 1000 * 100 * dateDay; monthKey = String.format("%d_%02d", dateYear, dateMonth); TLRPC.Peer peer_id = new TLRPC.TL_peerChannel(); @@ -2628,19 +2654,31 @@ public MessageObject(int accountNum, TLRPC.TL_channelAdminLogEvent event, ArrayL messageText = replaceWithLink(LocaleController.getString("EventLogSendMessages", R.string.EventLogSendMessages), "un1", fromUser); } else if (event.action instanceof TLRPC.TL_channelAdminLogEventActionChangeAvailableReactions) { TLRPC.TL_channelAdminLogEventActionChangeAvailableReactions eventActionChangeAvailableReactions = (TLRPC.TL_channelAdminLogEventActionChangeAvailableReactions) event.action; - - CharSequence oldReactions = getStringFrom(eventActionChangeAvailableReactions.prev_value); + boolean customReactionsChanged = eventActionChangeAvailableReactions.prev_value instanceof TLRPC.TL_chatReactionsSome + && eventActionChangeAvailableReactions.new_value instanceof TLRPC.TL_chatReactionsSome; CharSequence newReactions = getStringFrom(eventActionChangeAvailableReactions.new_value); - SpannableStringBuilder spannableStringBuilder = new SpannableStringBuilder(replaceWithLink(LocaleController.formatString("ActionReactionsChanged", R.string.ActionReactionsChanged, "**old**", "**new**"), "un1", fromUser)); - int i = spannableStringBuilder.toString().indexOf("**old**"); - if (i > 0) { - spannableStringBuilder.replace(i, i + "**old**".length(), oldReactions); - } - i = spannableStringBuilder.toString().indexOf("**new**"); - if (i > 0) { - spannableStringBuilder.replace(i, i + "**new**".length(), newReactions); + String newStr = "**new**"; + String oldStr = "**old**"; + if (customReactionsChanged) { + SpannableStringBuilder spannableStringBuilder = new SpannableStringBuilder(replaceWithLink(LocaleController.formatString("ActionReactionsChangedList", R.string.ActionReactionsChangedList, newStr), "un1", fromUser)); + int i = spannableStringBuilder.toString().indexOf(newStr); + if (i > 0) { + spannableStringBuilder.replace(i, i + newStr.length(), newReactions); + } + messageText = spannableStringBuilder; + } else { + CharSequence oldReactions = getStringFrom(eventActionChangeAvailableReactions.prev_value); + SpannableStringBuilder spannableStringBuilder = new SpannableStringBuilder(replaceWithLink(LocaleController.formatString("ActionReactionsChanged", R.string.ActionReactionsChanged, oldStr, newStr), "un1", fromUser)); + int i = spannableStringBuilder.toString().indexOf(oldStr); + if (i > 0) { + spannableStringBuilder.replace(i, i + oldStr.length(), oldReactions); + } + i = spannableStringBuilder.toString().indexOf(newStr); + if (i > 0) { + spannableStringBuilder.replace(i, i + newStr.length(), newReactions); + } + messageText = spannableStringBuilder; } - messageText = spannableStringBuilder; } else if (event.action instanceof TLRPC.TL_channelAdminLogEventActionChangeUsernames) { TLRPC.TL_channelAdminLogEventActionChangeUsernames log = (TLRPC.TL_channelAdminLogEventActionChangeUsernames) event.action; @@ -3047,10 +3085,12 @@ private CharSequence getStringFrom(TLRPC.ChatReactions reactions) { SpannableStringBuilder spannableStringBuilder = new SpannableStringBuilder(); for (int i = 0; i < reactionsSome.reactions.size(); i++) { if (i != 0) { - spannableStringBuilder.append(", "); + spannableStringBuilder.append(" "); } - spannableStringBuilder.append(ReactionsUtils.reactionToCharSequence(reactionsSome.reactions.get(i))); + CharSequence reaction = ReactionsUtils.reactionToCharSequence(reactionsSome.reactions.get(i)); + spannableStringBuilder.append(Emoji.replaceEmoji(reaction, null, false)); } + return spannableStringBuilder; } return LocaleController.getString("NoReactions", R.string.NoReactions); } @@ -3353,6 +3393,18 @@ public boolean hasReactions() { return messageOwner.reactions != null && !messageOwner.reactions.results.isEmpty(); } + public boolean hasReaction(ReactionsLayoutInBubble.VisibleReaction reaction) { + if (!hasReactions() || reaction == null) return false; + for (int i = 0; i < messageOwner.reactions.results.size(); ++i) { + TLRPC.ReactionCount rc = messageOwner.reactions.results.get(i); + if (reaction.isSame(rc.reaction)) { + return true; + } + } + return false; + } + + public static void updatePollResults(TLRPC.TL_messageMediaPoll media, TLRPC.PollResults results) { if (media == null || results == null) { return; @@ -4573,7 +4625,7 @@ private void updateMessageText(AbstractMap users, AbstractMap< } else if (getMedia(messageOwner) instanceof TLRPC.TL_messageMediaInvoice) { messageText = getMedia(messageOwner).description; } else if (getMedia(messageOwner) instanceof TLRPC.TL_messageMediaUnsupported) { - messageText = LocaleController.getString("UnsupportedMedia", R.string.UnsupportedMedia).replace("https://telegram.org/update", "https://t.me/nagram_channel"); + messageText = LocaleController.getString(R.string.UnsupportedMedia2); } else if (getMedia(messageOwner) instanceof TLRPC.TL_messageMediaDocument) { if (isSticker() || isAnimatedStickerDocument(getDocument(), true)) { String sch = getStickerChar(); @@ -4688,7 +4740,7 @@ public CharSequence getMediaTitle(TLRPC.MessageMedia media) { } else if (media instanceof TLRPC.TL_messageMediaInvoice) { return media.description; } else if (media instanceof TLRPC.TL_messageMediaUnsupported) { - return LocaleController.getString("UnsupportedMedia", R.string.UnsupportedMedia).replace("https://telegram.org/update", "https://t.me/nagram_channel"); + return LocaleController.getString(R.string.UnsupportedMedia2); } else if (media instanceof TLRPC.TL_messageMediaDocument) { if (isStickerDocument(media.document) || isAnimatedStickerDocument(media.document, true)) { String sch = getStickerChar(); @@ -5807,6 +5859,8 @@ public static int getInlineResultDuration(TLRPC.BotInlineResult inlineResult) { return result; } + // only set in searching with tags + public boolean isPrimaryGroupMessage; public boolean hasValidGroupId() { return getGroupId() != 0 && (photoThumbs != null && !photoThumbs.isEmpty() || isMusic() || isDocument()); } @@ -5860,7 +5914,7 @@ public boolean addEntitiesToText(CharSequence text, boolean photoViewer, boolean if (text == null) { return false; } - if (isRestrictedMessage) { + if (isRestrictedMessage || getMedia(messageOwner) instanceof TLRPC.TL_messageMediaUnsupported) { ArrayList entities = new ArrayList<>(); TLRPC.TL_messageEntityItalic entityItalic = new TLRPC.TL_messageEntityItalic(); entityItalic.offset = 0; @@ -6326,8 +6380,8 @@ public int getMaxMessageTextWidth() { if (needDrawAvatarInternal() && !isOutOwner() && !messageOwner.isThreadMessage) { maxWidth -= dp(52); } - if (needDrawShareButton() && !isOutOwner()) { - maxWidth -= dp(10); + if (needDrawShareButton() && (isSaved || !isOutOwner())) { + maxWidth -= dp(isSaved && isOutOwner() ? 40 : 10); } if (getMedia(messageOwner) instanceof TLRPC.TL_messageMediaGame) { maxWidth -= dp(10); @@ -6372,17 +6426,18 @@ private boolean applyEntities() { } boolean useManualParse = !hasEntities && ( - eventId != 0 || - messageOwner instanceof TLRPC.TL_message_old || - messageOwner instanceof TLRPC.TL_message_old2 || - messageOwner instanceof TLRPC.TL_message_old3 || - messageOwner instanceof TLRPC.TL_message_old4 || - messageOwner instanceof TLRPC.TL_messageForwarded_old || - messageOwner instanceof TLRPC.TL_messageForwarded_old2 || - messageOwner instanceof TLRPC.TL_message_secret || - getMedia(messageOwner) instanceof TLRPC.TL_messageMediaInvoice || - isOut() && messageOwner.send_state != MESSAGE_SEND_STATE_SENT || - messageOwner.id < 0 || getMedia(messageOwner) instanceof TLRPC.TL_messageMediaUnsupported); + eventId != 0 || + messageOwner instanceof TLRPC.TL_message_old || + messageOwner instanceof TLRPC.TL_message_old2 || + messageOwner instanceof TLRPC.TL_message_old3 || + messageOwner instanceof TLRPC.TL_message_old4 || + messageOwner instanceof TLRPC.TL_messageForwarded_old || + messageOwner instanceof TLRPC.TL_messageForwarded_old2 || + messageOwner instanceof TLRPC.TL_message_secret || + getMedia(messageOwner) instanceof TLRPC.TL_messageMediaInvoice || + isOut() && messageOwner.send_state != MESSAGE_SEND_STATE_SENT || + messageOwner.id < 0 + ); if (useManualParse) { addLinks(isOutOwner(), messageText, true, true); @@ -7288,7 +7343,7 @@ public boolean isOutOwner() { return isOutOwnerCached; } long selfUserId = UserConfig.getInstance(currentAccount).getClientUserId(); - if (isSaved && messageOwner.fwd_from != null) { + if ((isSaved || getDialogId() == selfUserId) && messageOwner.fwd_from != null) { return isOutOwnerCached = messageOwner.fwd_from.from_id != null && messageOwner.fwd_from.from_id.user_id == selfUserId || messageOwner.fwd_from.saved_out; } TLRPC.Chat chat = messageOwner.peer_id != null && messageOwner.peer_id.channel_id != 0 ? getChat(null, null, messageOwner.peer_id.channel_id) : null; @@ -7310,7 +7365,7 @@ public boolean needDrawAvatar() { return true; } if (isSaved) { - return getSavedDialogId() < 0 || getSavedDialogId() == UserObject.ANONYMOUS; + return true; } if (forceAvatar || customAvatarDrawable != null) { return true; @@ -7323,7 +7378,7 @@ private boolean needDrawAvatarInternal() { return true; } if (isSaved) { - return getSavedDialogId() < 0 || getSavedDialogId() == UserObject.ANONYMOUS; + return true; } if (forceAvatar || customAvatarDrawable != null) { return true; @@ -8846,6 +8901,9 @@ public boolean isForwarded() { } public boolean needDrawForwarded() { + if (type == MessageObject.TYPE_STORY && !isExpiredStory()) { + return true; + } if (isSaved) { if (messageOwner == null || messageOwner.fwd_from == null) return false; final long selfId = UserConfig.getInstance(currentAccount).getClientUserId(); @@ -8857,10 +8915,7 @@ public boolean needDrawForwarded() { if (fromId == 0) return savedId != UserObject.ANONYMOUS; return savedId != fromId && fromId != selfId; } - if (type == MessageObject.TYPE_STORY && !isExpiredStory()) { - return true; - } - return (messageOwner.flags & TLRPC.MESSAGE_FLAG_FWD) != 0 && messageOwner.fwd_from != null && !messageOwner.fwd_from.imported && (messageOwner.fwd_from.saved_from_peer == null || !(messageOwner.fwd_from.from_id instanceof TLRPC.TL_peerChannel) || messageOwner.fwd_from.saved_from_peer.channel_id != messageOwner.fwd_from.from_id.channel_id) && UserConfig.getInstance(currentAccount).getClientUserId() != getDialogId() && !UserObject.isReplyUser(messageOwner.dialog_id); + return (messageOwner.flags & TLRPC.MESSAGE_FLAG_FWD) != 0 && messageOwner.fwd_from != null && !messageOwner.fwd_from.imported && (messageOwner.fwd_from.saved_from_peer == null || !(messageOwner.fwd_from.from_id instanceof TLRPC.TL_peerChannel) || messageOwner.fwd_from.saved_from_peer.channel_id != messageOwner.fwd_from.from_id.channel_id) && UserConfig.getInstance(currentAccount).getClientUserId() != getDialogId(); } public static boolean isForwardedMessage(TLRPC.Message message) { @@ -9410,7 +9465,7 @@ private void handleFoundWords(ArrayList foundWords, String[] queryWord, } else { text = messageText; } - CharSequence charSequence = AndroidUtilities.replaceCharSequence("\n", text, " "); + CharSequence charSequence = AndroidUtilities.replaceMultipleCharSequence("\n", text, " "); if (inQuote && messageOwner != null && messageOwner.reply_to != null && messageOwner.reply_to.quote_text != null) { SpannableStringBuilder quoteText = new SpannableStringBuilder(messageOwner.reply_to.quote_text); addEntitiesToText(quoteText, messageOwner.reply_to.quote_entities, isOutOwner(), false, false, false); @@ -9423,13 +9478,13 @@ private void handleFoundWords(ArrayList foundWords, String[] queryWord, String str = charSequence.toString(); int lastIndex = str.length(); int startHighlightedIndex = str.toLowerCase().indexOf(foundWords.get(0)); - int maxSymbols = 200; + int maxSymbols = 120; if (startHighlightedIndex < 0) { startHighlightedIndex = 0; } if (lastIndex > maxSymbols) { - int newStart = Math.max(0, startHighlightedIndex - maxSymbols / 2); - charSequence = charSequence.subSequence(newStart, Math.min(lastIndex, startHighlightedIndex - newStart + startHighlightedIndex + maxSymbols / 2)); + int newStart = Math.max(0, startHighlightedIndex - (int) (maxSymbols * .1f)); + charSequence = charSequence.subSequence(newStart, Math.min(lastIndex, startHighlightedIndex - newStart + startHighlightedIndex + (int) (maxSymbols * .9f))); } messageTrimmedToHighlight = charSequence; } @@ -9531,9 +9586,6 @@ public boolean selectReaction(ReactionsLayoutInBubble.VisibleReaction visibleRea if (newReaction.count <= 0) { messageOwner.reactions.results.remove(newReaction); } - if (messageOwner.reactions.reactions_as_tags) { - MessagesController.getInstance(currentAccount).updateSavedReactionTags(visibleReaction, false); - } } if (messageOwner.reactions.can_see_list) { for (int i = 0; i < messageOwner.reactions.recent_reactions.size(); i++) { @@ -9560,9 +9612,6 @@ public boolean selectReaction(ReactionsLayoutInBubble.VisibleReaction visibleRea if (choosenReaction.count <= 0) { messageOwner.reactions.results.remove(choosenReaction); } - if (messageOwner.reactions.reactions_as_tags) { - MessagesController.getInstance(currentAccount).updateSavedReactionTags(ReactionsLayoutInBubble.VisibleReaction.fromTLReaction(choosenReaction.reaction), false); - } choosenReactions.remove(choosenReaction); if (messageOwner.reactions.can_see_list) { @@ -9583,9 +9632,6 @@ public boolean selectReaction(ReactionsLayoutInBubble.VisibleReaction visibleRea newReaction.chosen = true; newReaction.count++; newReaction.chosen_order = maxChoosenOrder + 1; - if (messageOwner.reactions.reactions_as_tags) { - MessagesController.getInstance(currentAccount).updateSavedReactionTags(visibleReaction, true); - } if (messageOwner.reactions.can_see_list || (messageOwner.dialog_id > 0 && maxReactionsCount > 1)) { TLRPC.TL_messagePeerReaction action = new TLRPC.TL_messagePeerReaction(); @@ -9860,13 +9906,14 @@ public boolean hasLinkMediaToMakeSmall() { webpage != null && (webpage.photo != null || isVideoDocument(webpage.document)) && !(webpage != null && TextUtils.isEmpty(webpage.description) && TextUtils.isEmpty(webpage.title)) && !(isSponsored() && sponsoredWebPage == null && sponsoredChannelPost == 0) && // drawInstantViewType = 1 - !"telegram_megagroup".equals(webpageType) && // drawInstantViewType = 2 - !"telegram_background".equals(webpageType) && // drawInstantViewType = 6 - !"telegram_voicechat".equals(webpageType) && // drawInstantViewType = 9 - !"telegram_livestream".equals(webpageType) && // drawInstantViewType = 11 - !"telegram_user".equals(webpageType) && // drawInstantViewType = 13 - !"telegram_story".equals(webpageType) && // drawInstantViewType = 17 - !"telegram_channel_boost".equals(webpageType) // drawInstantViewType = 18 + !"telegram_megagroup".equals(webpageType) && // drawInstantViewType = 2 + !"telegram_background".equals(webpageType) && // drawInstantViewType = 6 + !"telegram_voicechat".equals(webpageType) && // drawInstantViewType = 9 + !"telegram_livestream".equals(webpageType) && // drawInstantViewType = 11 + !"telegram_user".equals(webpageType) && // drawInstantViewType = 13 + !"telegram_story".equals(webpageType) && // drawInstantViewType = 17 + !"telegram_channel_boost".equals(webpageType) && // drawInstantViewType = 18 + !"telegram_chat".equals(webpageType) ; } @@ -9874,11 +9921,14 @@ public boolean isLinkMediaSmall() { final boolean hasLinkPreview = !isRestrictedMessage && MessageObject.getMedia(messageOwner) instanceof TLRPC.TL_messageMediaWebPage && MessageObject.getMedia(messageOwner).webpage instanceof TLRPC.TL_webPage; final TLRPC.WebPage webpage = hasLinkPreview ? MessageObject.getMedia(messageOwner).webpage : null; final String webpageType = webpage != null ? webpage.type : null; - return !(webpage != null && TextUtils.isEmpty(webpage.description) && TextUtils.isEmpty(webpage.title)) && ("app".equals(webpageType) || "profile".equals(webpageType) || + return !(webpage != null && TextUtils.isEmpty(webpage.description) && TextUtils.isEmpty(webpage.title)) && ( + "app".equals(webpageType) || "profile".equals(webpageType) || "article".equals(webpageType) || "telegram_bot".equals(webpageType) || "telegram_user".equals(webpageType) || "telegram_channel".equals(webpageType) || "telegram_megagroup".equals(webpageType) || "telegram_voicechat".equals(webpageType) || - "telegram_livestream".equals(webpageType) || "telegram_channel_boost".equals(webpageType)); + "telegram_livestream".equals(webpageType) || "telegram_channel_boost".equals(webpageType) || + "telegram_chat".equals(webpageType) + ); } diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/MessagesController.java b/TMessagesProj/src/main/java/org/telegram/messenger/MessagesController.java index 603c5f6709..06b4cfab0b 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/MessagesController.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/MessagesController.java @@ -603,6 +603,9 @@ protected boolean useCache(Integer arguments) { public int savedDialogsPinnedLimitDefault; public int savedDialogsPinnedLimitPremium; + public boolean savedViewAsChats; + public boolean storyQualityFull; + public int uploadMaxFileParts; public int uploadMaxFilePartsPremium; @@ -1571,6 +1574,8 @@ public MessagesController(int num) { boostsChannelLevelMax = mainPreferences.getInt("boostsChannelLevelMax", 100); savedDialogsPinnedLimitDefault = mainPreferences.getInt("savedDialogsPinnedLimitDefault", 4); savedDialogsPinnedLimitPremium = mainPreferences.getInt("savedDialogsPinnedLimitPremium", 6); + storyQualityFull = mainPreferences.getBoolean("storyQualityFull", true); + savedViewAsChats = mainPreferences.getBoolean("savedViewAsChats", false); scheduleTranscriptionUpdate(); // BuildVars.GOOGLE_AUTH_CLIENT_ID = mainPreferences.getString("googleAuthClientId", BuildVars.GOOGLE_AUTH_CLIENT_ID); if (mainPreferences.contains("dcDomainName2")) { @@ -5028,6 +5033,9 @@ public void didReceivedNotification(int id, int account, Object... args) { } else if (id == NotificationCenter.currentUserPremiumStatusChanged) { loadAppConfig(false); getContactsController().reloadContactsStatusesMaybe(true); + if (storyQualityFull && !getUserConfig().isPremium() || getUserConfig().isPremium()) { + getNotificationCenter().postNotificationName(NotificationCenter.storyQualityUpdate); + } } } @@ -8103,6 +8111,9 @@ public void setDialogsInTransaction(boolean transaction) { protected void deleteDialog(long did, int first, int onlyHistory, int max_id, boolean revoke, TLRPC.InputPeer peer, long taskId) { if (onlyHistory == 2) { + if (did == getUserConfig().getClientUserId()) { + getSavedMessagesController().deleteAllDialogs(); + } getMessagesStorage().deleteDialog(did, onlyHistory); return; } @@ -8127,6 +8138,9 @@ protected void deleteDialog(long did, int first, int onlyHistory, int max_id, bo if (first == 1 && max_id == 0) { TLRPC.InputPeer peerFinal = peer; getMessagesStorage().getDialogMaxMessageId(did, (param) -> { + if (did == getUserConfig().getClientUserId()) { + getSavedMessagesController().deleteAllDialogs(); + } deleteDialog(did, 2, onlyHistory, Math.max(0, param), revoke, peerFinal, taskId); checkIfFolderEmpty(1); }); @@ -8142,6 +8156,9 @@ protected void deleteDialog(long did, int first, int onlyHistory, int max_id, bo FileLog.d("delete dialog with id " + did); } boolean isPromoDialog = false; + if (did == getUserConfig().getClientUserId()) { + getSavedMessagesController().deleteAllDialogs(); + } getMessagesStorage().deleteDialog(did, onlyHistory); TLRPC.Dialog dialog = dialogs_dict.get(did); if (onlyHistory == 0 || onlyHistory == 3) { @@ -17556,6 +17573,8 @@ public boolean processUpdateArray(ArrayList updates, ArrayList loadingReactionTags; + private LongSparseArray reactionTags; + + public boolean processDeletedReactionTags(TLRPC.Message message) { + if (message == null || DialogObject.getPeerDialogId(message.peer_id) != getUserConfig().getClientUserId() || message.reactions == null || !message.reactions.reactions_as_tags || message.reactions.results == null) { + return false; + } + long topic_id = MessageObject.getSavedDialogId(getUserConfig().getClientUserId(), message); + boolean changed = false; + for (int i = 0; i < message.reactions.results.size(); ++i) { + if (updateSavedReactionTags(topic_id, ReactionsLayoutInBubble.VisibleReaction.fromTLReaction(message.reactions.results.get(i).reaction), false, false)) { + changed = true; + } + } + return changed; + } + + public boolean updateSavedReactionTags(long topic_id, ReactionsLayoutInBubble.VisibleReaction reaction, boolean add, boolean update) { + if (reactionTags == null) { + return false; + } + boolean gchanged = false; + for (int a = 0; a < 2; ++a) { + long topicId = a == 0 ? 0 : topic_id; + if (a == 1 && topicId == 0) continue; + TLRPC.TL_messages_savedReactionsTags tags = reactionTags.get(topicId); + if (tags == null) { + if (topicId != 0) { + reactionTags.put(topicId, tags = new TLRPC.TL_messages_savedReactionsTags()); + } else { + continue; + } + } boolean changed = false; boolean found = false; - for (int i = 0; i < reactionTags.tags.size(); ++i) { - TLRPC.TL_savedReactionTag tag = reactionTags.tags.get(i); + for (int i = 0; i < tags.tags.size(); ++i) { + TLRPC.TL_savedReactionTag tag = tags.tags.get(i); if (reaction.isSame(tag.reaction)) { found = true; int wasCount = tag.count; tag.count = Math.max(0, tag.count + (add ? +1 : -1)); if (tag.count <= 0) { - reactionTags.tags.remove(i); + tags.tags.remove(i); i--; + changed = true; + gchanged = true; } else if (tag.count != wasCount) { changed = true; + gchanged = true; } } } @@ -20294,43 +20345,205 @@ public void updateSavedReactionTags(ReactionsLayoutInBubble.VisibleReaction reac TLRPC.TL_savedReactionTag tag = new TLRPC.TL_savedReactionTag(); tag.reaction = reaction.toTLReaction(); tag.count = 1; - reactionTags.tags.add(tag); + tags.tags.add(tag); changed = true; + gchanged = true; } - if (changed) { - Collections.sort(reactionTags.tags, (a, b) -> b.count - a.count); - long hash = 0; - for (int i = 0; i < reactionTags.tags.size(); ++i) { - TLRPC.TL_savedReactionTag tag = reactionTags.tags.get(i); - if (tag.count <= 0) continue; - if (tag.reaction instanceof TLRPC.TL_reactionEmoji) { - String md5 = Utilities.MD5(((TLRPC.TL_reactionEmoji) tag.reaction).emoticon); - hash = MediaDataController.calcHash(hash, Long.parseLong(md5.substring(0, 16), 16)); - } else if (tag.reaction instanceof TLRPC.TL_reactionCustomEmoji) { - hash = MediaDataController.calcHash(hash, ((TLRPC.TL_reactionCustomEmoji) tag.reaction).document_id); - } - if ((tag.flags & 1) != 0 && tag.title != null) { - hash = MediaDataController.calcHash(hash, Long.parseLong(Utilities.MD5(tag.title).substring(0, 16), 16)); - } - hash = MediaDataController.calcHash(hash, tag.count); + if (update && changed) { + updateSavedReactionTags(topicId); + } + } + return gchanged; + } + + public void updateSavedReactionTags(HashSet topic_ids) { + updateSavedReactionTags(0); + for (long topic_id : topic_ids) { + updateSavedReactionTags(topic_id); + } + } + + public void updateSavedReactionTags(long topic_id) { + if (reactionTags == null) return; + TLRPC.TL_messages_savedReactionsTags tags = reactionTags.get(topic_id); + if (tags == null) { + if (topic_id != 0) { + reactionTags.put(topic_id, tags = new TLRPC.TL_messages_savedReactionsTags()); + } else { + return; + } + } + Collections.sort(tags.tags, (a, b) -> { + if (a.count == b.count) { + return Long.compareUnsigned(getTagLongId(b.reaction), getTagLongId(a.reaction)); + } + return b.count - a.count; + }); + long hash = 0; + for (int i = 0; i < tags.tags.size(); ++i) { + TLRPC.TL_savedReactionTag tag = tags.tags.get(i); + if (tag.count <= 0) continue; + if (tag.reaction instanceof TLRPC.TL_reactionEmoji) { + String md5 = Utilities.MD5(((TLRPC.TL_reactionEmoji) tag.reaction).emoticon); + hash = MediaDataController.calcHash(hash, Long.parseUnsignedLong(md5.substring(0, 16), 16)); + } else if (tag.reaction instanceof TLRPC.TL_reactionCustomEmoji) { + hash = MediaDataController.calcHash(hash, ((TLRPC.TL_reactionCustomEmoji) tag.reaction).document_id); + } + if (topic_id == 0 && (tag.flags & 1) != 0 && tag.title != null) { + hash = MediaDataController.calcHash(hash, Long.parseUnsignedLong(Utilities.MD5(tag.title).substring(0, 16), 16)); + } + hash = MediaDataController.calcHash(hash, tag.count); + } + tags.hash = hash; + saveSavedReactionsTags(topic_id, tags); + getNotificationCenter().postNotificationName(NotificationCenter.savedReactionTagsUpdate, topic_id); + } + + public String getSavedTagName(ReactionsLayoutInBubble.VisibleReaction reaction) { + if (reactionTags == null) { + return null; + } + TLRPC.TL_messages_savedReactionsTags tags = reactionTags.get(0); + if (tags == null) return null; + for (int i = 0; i < tags.tags.size(); ++i) { + if (reaction.isSame(tags.tags.get(i).reaction)) { + return tags.tags.get(i).title; + } + } + return null; + } + + public int getSavedTagCount(long topic_id, ReactionsLayoutInBubble.VisibleReaction reaction) { + if (reactionTags == null) { + return 0; + } + TLRPC.TL_messages_savedReactionsTags tags = reactionTags.get(topic_id); + if (tags == null) return 0; + for (int i = 0; i < tags.tags.size(); ++i) { + if (reaction.isSame(tags.tags.get(i).reaction)) { + return tags.tags.get(i).count; + } + } + return 0; + } + + public String getSavedTagName(TLRPC.Reaction reaction) { + if (reactionTags == null) { + return null; + } + TLRPC.TL_messages_savedReactionsTags tags = reactionTags.get(0); + if (tags == null) return null; + for (int i = 0; i < tags.tags.size(); ++i) { + if (ReactionsLayoutInBubble.reactionsEqual(reaction, tags.tags.get(i).reaction)) { + return tags.tags.get(i).title; + } + } + return null; + } + + public void renameSavedReactionTag(ReactionsLayoutInBubble.VisibleReaction reaction, String name) { + if (reactionTags == null) { + return; + } + TLRPC.TL_messages_savedReactionsTags tags = reactionTags.get(0); + if (tags == null) { + reactionTags.put(0, tags = new TLRPC.TL_messages_savedReactionsTags()); + } + boolean found = false; + boolean changed = false; + for (int i = 0; i < tags.tags.size(); ++i) { + TLRPC.TL_savedReactionTag tag = tags.tags.get(i); + if (reaction.isSame(tag.reaction)) { + found = true; + if (TextUtils.isEmpty(name)) { + changed = tag.title != null; + tag.flags &=~ 1; + tag.title = null; + } else { + changed = !TextUtils.equals(tag.title, name); + tag.flags |= 1; + tag.title = name; + } + break; + } + } + if (!found) { + TLRPC.TL_savedReactionTag tag = new TLRPC.TL_savedReactionTag(); + tag.reaction = reaction.toTLReaction(); + if (!TextUtils.isEmpty(name)) { + tag.title = name; + } + tag.count = 1; + tags.tags.add(tag); + changed = true; + } + if (changed) { + TLRPC.TL_messages_updateSavedReactionTag req = new TLRPC.TL_messages_updateSavedReactionTag(); + req.reaction = reaction.toTLReaction(); + if (!TextUtils.isEmpty(name)) { + req.flags |= 1; + req.title = name; + } + getConnectionsManager().sendRequest(req, null); + + Collections.sort(tags.tags, (a, b) -> { + if (a.count == b.count) { + return Long.compareUnsigned(getTagLongId(b.reaction), getTagLongId(a.reaction)); } - reactionTags.hash = hash; - saveSavedReactionsTags(reactionTags); - getNotificationCenter().postNotificationName(NotificationCenter.savedReactionTagsUpdate); + return b.count - a.count; + }); + long hash = 0; + for (int i = 0; i < tags.tags.size(); ++i) { + TLRPC.TL_savedReactionTag tag = tags.tags.get(i); + if (tag.count <= 0) continue; + if (tag.reaction instanceof TLRPC.TL_reactionEmoji) { + String md5 = Utilities.MD5(((TLRPC.TL_reactionEmoji) tag.reaction).emoticon); + hash = MediaDataController.calcHash(hash, Long.parseUnsignedLong(md5.substring(0, 16), 16)); + } else if (tag.reaction instanceof TLRPC.TL_reactionCustomEmoji) { + hash = MediaDataController.calcHash(hash, ((TLRPC.TL_reactionCustomEmoji) tag.reaction).document_id); + } + if ((tag.flags & 1) != 0 && tag.title != null) { + hash = MediaDataController.calcHash(hash, Long.parseUnsignedLong(Utilities.MD5(tag.title).substring(0, 16), 16)); + } + hash = MediaDataController.calcHash(hash, tag.count); } + tags.hash = hash; + saveSavedReactionsTags(0, tags); + getNotificationCenter().postNotificationName(NotificationCenter.savedReactionTagsUpdate, 0L); } } - public TLRPC.TL_messages_savedReactionsTags getSavedReactionTags() { - if (loadedReactionTags) { - return reactionTags; + + private long getTagLongId(TLRPC.Reaction reaction) { + if (reaction == null) return 0; + if (reaction.tag_long_id != 0) return reaction.tag_long_id; + if (reaction instanceof TLRPC.TL_reactionEmoji) { + String md5 = Utilities.MD5(((TLRPC.TL_reactionEmoji) reaction).emoticon); + return reaction.tag_long_id = Long.parseUnsignedLong(md5.substring(0, 16), 16); + } else if (reaction instanceof TLRPC.TL_reactionCustomEmoji) { + return reaction.tag_long_id = ((TLRPC.TL_reactionCustomEmoji) reaction).document_id; + } + return 0; + } + + public TLRPC.TL_messages_savedReactionsTags getSavedReactionTags(long topic_id) { + return getSavedReactionTags(topic_id, false); + } + + public TLRPC.TL_messages_savedReactionsTags getSavedReactionTags(long topic_id, boolean force) { + if (loadingReactionTags != null && loadingReactionTags.contains(topic_id) && !force) { + if (reactionTags == null) return null; + return reactionTags.get(topic_id); } - loadedReactionTags = true; + if (loadingReactionTags == null) { + loadingReactionTags = new HashSet<>(); + } + loadingReactionTags.add(topic_id); getMessagesStorage().getStorageQueue().postRunnable(() -> { TLRPC.messages_SavedReactionTags result = null; SQLiteDatabase database = getMessagesStorage().getDatabase(); SQLiteCursor cursor = null; try { - cursor = database.queryFinalized(String.format(Locale.US, "SELECT data FROM saved_reaction_tags")); + cursor = database.queryFinalized("SELECT data FROM saved_reaction_tags WHERE topic_id = ?", topic_id); if (cursor.next()) { NativeByteBuffer data = cursor.byteBufferValue(0); if (data != null) { @@ -20348,20 +20561,31 @@ public TLRPC.TL_messages_savedReactionsTags getSavedReactionTags() { final TLRPC.messages_SavedReactionTags finalResult = result; AndroidUtilities.runOnUIThread(() -> { + if (reactionTags == null) reactionTags = new LongSparseArray<>(); if (finalResult instanceof TLRPC.TL_messages_savedReactionsTags) { - reactionTags = (TLRPC.TL_messages_savedReactionsTags) finalResult; - getNotificationCenter().postNotificationName(NotificationCenter.savedReactionTagsUpdate); + reactionTags.put(topic_id, (TLRPC.TL_messages_savedReactionsTags) finalResult); + getNotificationCenter().postNotificationName(NotificationCenter.savedReactionTagsUpdate, topic_id); } TLRPC.TL_messages_getSavedReactionTags req = new TLRPC.TL_messages_getSavedReactionTags(); if (finalResult instanceof TLRPC.TL_messages_savedReactionsTags) { req.hash = finalResult.hash; } + if (topic_id != 0) { + req.flags |= 1; + req.peer = getInputPeer(topic_id); + } getConnectionsManager().sendRequest(req, (res, err) -> AndroidUtilities.runOnUIThread(() -> { if (res instanceof TLRPC.TL_messages_savedReactionsTags) { - reactionTags = (TLRPC.TL_messages_savedReactionsTags) res; - getNotificationCenter().postNotificationName(NotificationCenter.savedReactionTagsUpdate); - saveSavedReactionsTags(reactionTags); + TLRPC.TL_messages_savedReactionsTags tags = (TLRPC.TL_messages_savedReactionsTags) res; + reactionTags.put(topic_id, tags); + getNotificationCenter().postNotificationName(NotificationCenter.savedReactionTagsUpdate, topic_id); + saveSavedReactionsTags(topic_id, tags); + } else if (res instanceof TLRPC.TL_messages_savedReactionsTagsNotModified && finalResult == null && req.hash == 0) { + TLRPC.TL_messages_savedReactionsTags emptyTags = new TLRPC.TL_messages_savedReactionsTags(); + reactionTags.put(topic_id, emptyTags); + getNotificationCenter().postNotificationName(NotificationCenter.savedReactionTagsUpdate, topic_id); + saveSavedReactionsTags(topic_id, emptyTags); } })); }); @@ -20369,17 +20593,18 @@ public TLRPC.TL_messages_savedReactionsTags getSavedReactionTags() { return null; } - private void saveSavedReactionsTags(TLRPC.TL_messages_savedReactionsTags res) { + private void saveSavedReactionsTags(long topic_id, TLRPC.TL_messages_savedReactionsTags res) { getMessagesStorage().getStorageQueue().postRunnable(() -> { SQLiteDatabase database2 = getMessagesStorage().getDatabase(); SQLitePreparedStatement state = null; try { - database2.executeFast("DELETE FROM saved_reaction_tags WHERE 1").stepThis().dispose(); - state = database2.executeFast("REPLACE INTO saved_reaction_tags VALUES(?)"); + database2.executeFast("DELETE FROM saved_reaction_tags WHERE topic_id = " + topic_id).stepThis().dispose(); + state = database2.executeFast("REPLACE INTO saved_reaction_tags VALUES(?, ?)"); state.requery(); NativeByteBuffer buffer = new NativeByteBuffer(res.getObjectSize()); res.serializeToStream(buffer); - state.bindByteBuffer(1, buffer); + state.bindLong(1, topic_id); + state.bindByteBuffer(2, buffer); state.step(); } catch (Exception e) { FileLog.e(e); @@ -20425,6 +20650,27 @@ public void checkPeerColors(boolean force) { } } + public void setStoryQuality(boolean full) { + if (storyQualityFull != full) { + mainPreferences.edit().putBoolean("storyQualityFull", storyQualityFull = full).apply(); + getNotificationCenter().postNotificationName(NotificationCenter.storyQualityUpdate); + } + } + + public void setSavedViewAs(boolean chats) { + if (savedViewAsChats != chats) { + mainPreferences.edit().putBoolean("savedViewAsChats", savedViewAsChats = chats).apply(); + } + } + + public boolean isStoryQualityFullOnAccount() { + return getUserConfig().isPremium() && storyQualityFull; + } + + public static boolean isStoryQualityFull() { + return MessagesController.getInstance(UserConfig.selectedAccount).isStoryQualityFullOnAccount(); + } + private LongSparseArray cachedIsUserPremiumBlocked = new LongSparseArray<>(); private HashSet loadingIsUserPremiumBlocked = new HashSet<>(); public boolean isUserPremiumBlocked(long userId) { diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/MessagesStorage.java b/TMessagesProj/src/main/java/org/telegram/messenger/MessagesStorage.java index 3cf6a3df46..a74d3f66b9 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/MessagesStorage.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/MessagesStorage.java @@ -44,6 +44,7 @@ import org.telegram.ui.ActionBar.Theme; import org.telegram.ui.Adapters.DialogsSearchAdapter; import org.telegram.ui.ChatActivity; +import org.telegram.ui.Components.Reactions.ReactionsLayoutInBubble; import org.telegram.ui.DialogsActivity; import org.telegram.ui.EditWidgetActivity; @@ -105,7 +106,7 @@ public class MessagesStorage extends BaseController { private static SparseArray Instance = new SparseArray(); private static final Object lockObject = new Object(); - public final static int LAST_DB_VERSION = 139; + public final static int LAST_DB_VERSION = 143; private boolean databaseMigrationInProgress; public boolean showClearDatabaseAlert; private LongSparseIntArray dialogIsForum = new LongSparseIntArray(); @@ -705,7 +706,13 @@ public static void createTables(SQLiteDatabase database) throws SQLiteException database.executeFast("CREATE TABLE unconfirmed_auth (data BLOB);").stepThis().dispose(); - database.executeFast("CREATE TABLE saved_reaction_tags (data BLOB);").stepThis().dispose(); + database.executeFast("CREATE TABLE saved_reaction_tags (topic_id INTEGER PRIMARY KEY, data BLOB);").stepThis().dispose(); + + database.executeFast("CREATE TABLE tag_message_id(mid INTEGER, topic_id INTEGER, tag INTEGER, text TEXT);").stepThis().dispose(); + database.executeFast("CREATE INDEX IF NOT EXISTS tag_idx_tag_message_id ON tag_message_id(tag);").stepThis().dispose(); + database.executeFast("CREATE INDEX IF NOT EXISTS tag_text_idx_tag_message_id ON tag_message_id(tag, text COLLATE NOCASE);").stepThis().dispose(); + database.executeFast("CREATE INDEX IF NOT EXISTS tag_topic_idx_tag_message_id ON tag_message_id(topic_id, tag);").stepThis().dispose(); + database.executeFast("CREATE INDEX IF NOT EXISTS tag_topic_text_idx_tag_message_id ON tag_message_id(topic_id, tag, text COLLATE NOCASE);").stepThis().dispose(); database.executeFast("PRAGMA user_version = " + MessagesStorage.LAST_DB_VERSION).stepThis().dispose(); @@ -1937,13 +1944,26 @@ public void deleteSavedDialog(long did) { } cursor.dispose(); cursor = null; - if (!mids.isEmpty()) { - database.executeFast("DELETE FROM messages_v2 WHERE uid = " + selfId + " AND mid IN ("+TextUtils.join(",", mids)+")").stepThis().dispose(); - database.executeFast("DELETE FROM messages_topics WHERE uid = " + selfId + " AND topic_id = " + did).stepThis().dispose(); - database.executeFast("DELETE FROM media_v4 WHERE uid = " + selfId + " AND mid IN ("+TextUtils.join(",", mids)+")").stepThis().dispose(); + cursor = database.queryFinalized("SELECT mid, data FROM messages_v2 WHERE uid = ?", selfId); + while (cursor.next()) { + final int mid = cursor.intValue(0); + if (mids.contains(mid)) continue; + NativeByteBuffer buffer = cursor.byteBufferValue(1); + TLRPC.Message message = TLRPC.Message.TLdeserialize(buffer, buffer.readInt32(false), false); + if (MessageObject.getSavedDialogId(selfId, message) == did) { + mids.add(mid); + } + buffer.reuse(); } + cursor.dispose(); + cursor = null; if (!mids.isEmpty()) { - AndroidUtilities.runOnUIThread(() -> getNotificationCenter().postNotificationName(NotificationCenter.messagesDeleted, mids, 0L, false)); + markMessagesAsDeletedInternal(selfId, mids, true, false); + updateDialogsWithDeletedMessages(selfId, -selfId, mids, null, false); + AndroidUtilities.runOnUIThread(() -> { + getMessagesController().markDialogMessageAsDeleted(selfId, mids); + getNotificationCenter().postNotificationName(NotificationCenter.messagesDeleted, mids, 0L, false); + }); } } catch (Exception e) { checkSQLException(e); @@ -2534,6 +2554,7 @@ private void calcUnreadCounters(boolean apply) { forumUnreadCount.put(dialogId, 1); } } + cursor.dispose(); cursor = database.queryFinalized("SELECT did, folder_id, unread_count, unread_count_i FROM dialogs WHERE unread_count > 0 OR flags > 0 UNION ALL " + "SELECT did, folder_id, unread_count, unread_count_i FROM dialogs WHERE unread_count_i > 0"); while (cursor.next()) { @@ -4085,6 +4106,9 @@ public void deleteDialog(long did, int messagesOnly) { cursor2 = null; database.executeFast("DELETE FROM messages_v2 WHERE uid = " + did + " AND mid != " + last_mid_i + " AND mid != " + last_mid).stepThis().dispose(); + if (did == getUserConfig().getClientUserId()) { + database.executeFast("DELETE FROM messages_topics WHERE uid = " + did + " AND mid != " + last_mid_i + " AND mid != " + last_mid).stepThis().dispose(); + } database.executeFast("DELETE FROM messages_holes WHERE uid = " + did).stepThis().dispose(); database.executeFast("DELETE FROM bot_keyboard WHERE uid = " + did).stepThis().dispose(); database.executeFast("DELETE FROM bot_keyboard_topics WHERE uid = " + did).stepThis().dispose(); @@ -4111,6 +4135,9 @@ public void deleteDialog(long did, int messagesOnly) { database.executeFast("UPDATE dialogs SET unread_count = 0, unread_count_i = 0 WHERE did = " + did).stepThis().dispose(); database.executeFast("DELETE FROM messages_v2 WHERE uid = " + did).stepThis().dispose(); + if (did == getUserConfig().getClientUserId()) { + database.executeFast("DELETE FROM messages_topics WHERE uid = " + did).stepThis().dispose(); + } database.executeFast("DELETE FROM bot_keyboard WHERE uid = " + did).stepThis().dispose(); database.executeFast("DELETE FROM bot_keyboard_topics WHERE uid = " + did).stepThis().dispose(); database.executeFast("DELETE FROM media_counts_v2 WHERE uid = " + did).stepThis().dispose(); @@ -4581,10 +4608,138 @@ public void updateMessagePollResults(long pollId, TLRPC.Poll poll, TLRPC.PollRes }); } + public void searchSavedByTag(TLRPC.Reaction tag, long topic_id, String query, int limit, int offset, Utilities.Callback4, ArrayList, ArrayList, ArrayList> done, boolean includeGroups) { + if (done == null) { + return; + } + storageQueue.postRunnable(() -> { + SQLitePreparedStatement state = null; + SQLiteCursor cursor = null; + SQLiteCursor cursor_groups = null; + try { + final long selfId = getUserConfig().getClientUserId(); + state = database.executeFast("SELECT m.data, m.replydata, m.group_id FROM messages_v2 m INNER JOIN tag_message_id t ON m.mid = t.mid WHERE m.uid = ? AND t.tag = ?" + (!TextUtils.isEmpty(query) ? " AND t.text LIKE '%' || ? || '%'" : "") + (topic_id != 0 ? " AND topic_id = ? " : "") + " ORDER BY m.mid DESC LIMIT ? OFFSET ?"); + + ArrayList users = new ArrayList<>(); +// ArrayList encUsers = new ArrayList<>(); + ArrayList chats = new ArrayList<>(); + ArrayList animatedEmojiToLoad = new ArrayList<>(); + ArrayList usersToLoad = new ArrayList<>(); + ArrayList chatsToLoad = new ArrayList<>(); + ArrayList animatedEmoji = new ArrayList<>(); +// LongSparseArray>> replyMessageOwners = new LongSparseArray<>(); +// LongSparseArray> dialogReplyMessagesIds = new LongSparseArray<>(); + + int pointer = 1; + state.bindLong(pointer++, selfId); + long hash = 0; + if (tag instanceof TLRPC.TL_reactionEmoji) { + hash = ((TLRPC.TL_reactionEmoji) tag).emoticon.hashCode(); + } else if (tag instanceof TLRPC.TL_reactionCustomEmoji) { + hash = ((TLRPC.TL_reactionCustomEmoji) tag).document_id; + } + state.bindLong(pointer++, hash); + if (!TextUtils.isEmpty(query)) { + String q = LocaleController.getInstance().getTranslitString(query); + if (q == null) q = ""; + state.bindString(pointer++, q); + } + if (topic_id != 0) { + state.bindLong(pointer++, topic_id); + } + state.bindInteger(pointer++, limit); + state.bindInteger(pointer++, offset); + + cursor = state.query(new Object[] {}); + state = null; + + ArrayList messageObjects = new ArrayList<>(); + while (cursor.next()) { + long group_id = cursor.longValue(2); + if (group_id != 0 && includeGroups) { + cursor_groups = database.queryFinalized("SELECT data, replydata, group_id FROM messages_v2 WHERE uid = ? AND group_id = ? ORDER BY mid DESC", selfId, group_id); + ArrayList groupmessages = new ArrayList<>(); + while (cursor_groups.next()) { + NativeByteBuffer data = cursor_groups.byteBufferValue(0); + TLRPC.Message groupmessage = TLRPC.Message.TLdeserialize(data, data.readInt32(false), false); + groupmessage.readAttachPath(data, selfId); + data.reuse(); + addUsersAndChatsFromMessage(groupmessage, usersToLoad, chatsToLoad, animatedEmojiToLoad); + MessageObject messageObject = new MessageObject(currentAccount, groupmessage, null, null, null, null, null, true, true, 0, false, false, true); + if (groupmessage.reactions != null) { + messageObject.isPrimaryGroupMessage = true; + } + groupmessages.add(messageObject); + } + cursor_groups.dispose(); + messageObjects.addAll(groupmessages); + } else { + NativeByteBuffer data = cursor.byteBufferValue(0); + if (data == null) continue; + TLRPC.Message message = TLRPC.Message.TLdeserialize(data, data.readInt32(false), false); + if (message != null) { + message.readAttachPath(data, selfId); + data.reuse(); + addUsersAndChatsFromMessage(message, usersToLoad, chatsToLoad, animatedEmojiToLoad); + if (message.reply_to != null && (message.reply_to.reply_to_msg_id != 0 || message.reply_to.reply_to_random_id != 0)) { + if (!cursor.isNull(1)) { + data = cursor.byteBufferValue(1); + if (data != null) { + message.replyMessage = TLRPC.Message.TLdeserialize(data, data.readInt32(false), false); + message.replyMessage.readAttachPath(data, selfId); + data.reuse(); + if (message.replyMessage != null) { + addUsersAndChatsFromMessage(message.replyMessage, usersToLoad, chatsToLoad, animatedEmojiToLoad); + } + } + } + } + MessageObject messageObject = new MessageObject(currentAccount, message, null, null, null, null, null, true, true, 0, false, false, true); + messageObjects.add(messageObject); + } + } + } + cursor.dispose(); + +// loadReplyMessages(replyMessageOwners, dialogReplyMessagesIds, usersToLoad, chatsToLoad, false); + + if (!usersToLoad.isEmpty()) { + getUsersInternal(TextUtils.join(",", usersToLoad), users); + } + if (!chatsToLoad.isEmpty()) { + getChatsInternal(TextUtils.join(",", chatsToLoad), chats); + } + if (!animatedEmojiToLoad.isEmpty()) { + getAnimatedEmoji(TextUtils.join(",", animatedEmojiToLoad), animatedEmoji); + } + + AndroidUtilities.runOnUIThread(() -> { + done.run(messageObjects, users, chats, animatedEmoji); + }); + + } catch (Exception e) { + FileLog.e(e); + } finally { + if (state != null) { + state.dispose(); + } + if (cursor != null) { + cursor.dispose(); + } + if (cursor_groups != null) { + cursor_groups.dispose(); + } + } + }); + } + public void updateMessageReactions(long dialogId, int msgId, TLRPC.TL_messageReactions reactions) { storageQueue.postRunnable(() -> { SQLiteCursor cursor = null; try { + final long selfId = getUserConfig().getClientUserId(); + TLRPC.TL_messageReactions pastReactions = null; + long topicId = 0; database.beginTransaction(); for (int i = 0; i < 2; i++) { if (i == 0) { @@ -4599,6 +4754,10 @@ public void updateMessageReactions(long dialogId, int msgId, TLRPC.TL_messageRea if (message != null) { message.readAttachPath(data, getUserConfig().clientUserId); data.reuse(); + if (pastReactions == null) { + pastReactions = message.reactions; + topicId = MessageObject.getSavedDialogId(selfId, message); + } MessageObject.updateReactions(message, reactions); SQLitePreparedStatement state; if (i == 0) { @@ -4616,6 +4775,12 @@ public void updateMessageReactions(long dialogId, int msgId, TLRPC.TL_messageRea state.step(); data2.reuse(); state.dispose(); + if (selfId == dialogId) { + database.executeFast(String.format(Locale.US, "DELETE FROM tag_message_id WHERE mid = %d", message.id)).stepThis().dispose(); + SQLitePreparedStatement state_tag_message = database.executeFast("REPLACE INTO tag_message_id VALUES(?, ?, ?, ?)"); + bindMessageTags(state_tag_message, message); + state_tag_message.dispose(); + } } else { data.reuse(); } @@ -4625,6 +4790,9 @@ public void updateMessageReactions(long dialogId, int msgId, TLRPC.TL_messageRea cursor = null; } database.commitTransaction(); + if (dialogId == selfId && pastReactions != null) { + onReactionsUpdate(topicId, pastReactions, reactions); + } } catch (Exception e) { checkSQLException(e); } finally { @@ -4638,6 +4806,145 @@ public void updateMessageReactions(long dialogId, int msgId, TLRPC.TL_messageRea }); } + private class SavedReactionsUpdate { + long topic_id; + TLRPC.TL_messageReactions old; + TLRPC.TL_messageReactions last; + public SavedReactionsUpdate(long selfId, TLRPC.Message oldMessage, TLRPC.Message newMessage) { + topic_id = MessageObject.getSavedDialogId(selfId, newMessage); + old = oldMessage.reactions; + last = newMessage.reactions; + } + } + + private void onReactionsUpdate(ArrayList reactionUpdates) { + if (reactionUpdates == null || reactionUpdates.isEmpty()) return; + AndroidUtilities.runOnUIThread(() -> { + boolean updated = false; + HashSet topicIds = new HashSet<>(); + LongSparseArray oldTags = new LongSparseArray<>(); + LongSparseArray newTags = new LongSparseArray<>(); + for (int i = 0; i < reactionUpdates.size(); ++i) { + SavedReactionsUpdate pair = reactionUpdates.get(i); + TLRPC.TL_messageReactions a = pair.old; + TLRPC.TL_messageReactions b = pair.last; + + oldTags.clear(); + newTags.clear(); + + if (a != null && a.results != null && a.reactions_as_tags) { + for (int j = 0; j < a.results.size(); ++j) { + ReactionsLayoutInBubble.VisibleReaction reaction = ReactionsLayoutInBubble.VisibleReaction.fromTLReaction(a.results.get(j).reaction); + if (reaction != null) { + oldTags.put(reaction.hash, reaction); + } + } + } + if (b != null && b.results != null && b.reactions_as_tags) { + for (int j = 0; j < b.results.size(); ++j) { + ReactionsLayoutInBubble.VisibleReaction reaction = ReactionsLayoutInBubble.VisibleReaction.fromTLReaction(b.results.get(j).reaction); + if (reaction != null) { + newTags.put(reaction.hash, reaction); + } + } + } + // delete reactions + for (int j = 0; j < oldTags.size(); ++j) { + long hash = oldTags.keyAt(j); + ReactionsLayoutInBubble.VisibleReaction reaction = oldTags.valueAt(j); + if (!newTags.containsKey(hash)) { + if (getMessagesController().updateSavedReactionTags(pair.topic_id, reaction, false, false)) { + updated = true; + topicIds.add(pair.topic_id); + } + } + } + // add new reactions + for (int j = 0; j < newTags.size(); ++j) { + long hash = newTags.keyAt(j); + ReactionsLayoutInBubble.VisibleReaction reaction = newTags.valueAt(j); + if (!oldTags.containsKey(hash)) { + if (getMessagesController().updateSavedReactionTags(pair.topic_id, reaction, true, false)) { + updated = true; + topicIds.add(pair.topic_id); + } + } + } + } + if (updated && !topicIds.isEmpty()) { + getMessagesController().updateSavedReactionTags(topicIds); + } + }); + } + + private void onReactionsUpdate(long topic_id, TLRPC.TL_messageReactions a, TLRPC.TL_messageReactions b) { + if (a == null || a.results == null || a != null && a.results != null && a.results.isEmpty() && b != null && b.results.isEmpty()) { + return; + } + AndroidUtilities.runOnUIThread(() -> { + LongSparseArray oldTags = new LongSparseArray<>(); + LongSparseArray newTags = new LongSparseArray<>(); + if (a != null && a.results != null && a.reactions_as_tags) { + for (int i = 0; i < a.results.size(); ++i) { + ReactionsLayoutInBubble.VisibleReaction reaction = ReactionsLayoutInBubble.VisibleReaction.fromTLReaction(a.results.get(i).reaction); + oldTags.put(reaction.hash, reaction); + } + } + if (b != null && b.results != null && b.reactions_as_tags) { + for (int i = 0; i < b.results.size(); ++i) { + ReactionsLayoutInBubble.VisibleReaction reaction = ReactionsLayoutInBubble.VisibleReaction.fromTLReaction(b.results.get(i).reaction); + newTags.put(reaction.hash, reaction); + } + } + boolean updated = false; + // delete reactions + for (int i = 0; i < oldTags.size(); ++i) { + long hash = oldTags.keyAt(i); + ReactionsLayoutInBubble.VisibleReaction reaction = oldTags.valueAt(i); + if (!newTags.containsKey(hash)) { + updated = getMessagesController().updateSavedReactionTags(topic_id, reaction, false, false) || updated; + } + } + // add new reactions + for (int i = 0; i < newTags.size(); ++i) { + long hash = newTags.keyAt(i); + ReactionsLayoutInBubble.VisibleReaction reaction = newTags.valueAt(i); + if (!oldTags.containsKey(hash)) { + updated = getMessagesController().updateSavedReactionTags(topic_id, reaction, true, false) || updated; + } + } + if (updated) { + if (topic_id != 0) { + getMessagesController().updateSavedReactionTags(0); + } + getMessagesController().updateSavedReactionTags(topic_id); + } + }); + } + + private void bindMessageTags(SQLitePreparedStatement state, TLRPC.Message message) throws SQLiteException { + long selfId = getUserConfig().getClientUserId(); + if (message.reactions != null && message.reactions.reactions_as_tags && message.reactions.results != null && !message.reactions.results.isEmpty()) { + final String text = LocaleController.getInstance().getTranslitString(message.message == null ? "" : message.message); + for (TLRPC.ReactionCount result : message.reactions.results) { + if (result.reaction instanceof TLRPC.TL_reactionEmoji || result.reaction instanceof TLRPC.TL_reactionCustomEmoji) { + state.requery(); + state.bindLong(1, message.id); + state.bindLong(2, MessageObject.getSavedDialogId(selfId, message)); + long hash = 0; + if (result.reaction instanceof TLRPC.TL_reactionEmoji) { + hash = ((TLRPC.TL_reactionEmoji) result.reaction).emoticon.hashCode(); + } else if (result.reaction instanceof TLRPC.TL_reactionCustomEmoji) { + hash = ((TLRPC.TL_reactionCustomEmoji) result.reaction).document_id; + } + state.bindLong(3, hash); + state.bindString(4, text == null ? "" : text); + state.step(); + } + } + } + } + public void updateMessageVoiceTranscriptionOpen(long dialogId, int msgId, TLRPC.Message saveFromMessage) { storageQueue.postRunnable(() -> { SQLitePreparedStatement state = null; @@ -10542,6 +10849,7 @@ private void putMessagesInternal(ArrayList messages, boolean with boolean databaseInTransaction = false; SQLitePreparedStatement state_messages = null; SQLitePreparedStatement state_messages_topic = null; + SQLitePreparedStatement state_messages_tags = null; SQLitePreparedStatement state_randoms = null; SQLitePreparedStatement state_download = null; SQLitePreparedStatement state_webpage = null; @@ -10557,6 +10865,7 @@ private void putMessagesInternal(ArrayList messages, boolean with try { final boolean scheduled = mode == ChatActivity.MODE_SCHEDULED; final boolean saved = mode == ChatActivity.MODE_SAVED; + final long selfId = getUserConfig().getClientUserId(); if (scheduled) { if (withTransaction) { database.beginTransaction(); @@ -10939,6 +11248,8 @@ private void putMessagesInternal(ArrayList messages, boolean with mediaTypesChange.put(mid, type); } } + cursor.dispose(); + cursor = null; SparseIntArray mediaTypes = dialogMediaTypes.get(topicKey.dialogId); @@ -10996,6 +11307,7 @@ private void putMessagesInternal(ArrayList messages, boolean with if (!messageIdsMap.isEmpty()) { for (int b = 0, N2 = messageIdsMap.size(); b < N2; b++) { long dialogId = messageIdsMap.keyAt(b); + if (dialogId == selfId) continue; StringBuilder messageIds = messageIdsMap.valueAt(b); ArrayList messagesIdsMap = dialogMessagesIdsMap.get(dialogId); ArrayList mentionsIdsMap = dialogMentionsIdsMap.get(dialogId); @@ -11110,7 +11422,6 @@ private void putMessagesInternal(ArrayList messages, boolean with createNewTopics.add(message); } - final long selfId = getUserConfig().getClientUserId(); if (updateDialog) { TLRPC.Message lastMessage = messagesMap.get(message.dialog_id); if (lastMessage == null || message.date > lastMessage.date || lastMessage.id > 0 && message.id > lastMessage.id || lastMessage.id < 0 && message.id < lastMessage.id) { @@ -11138,6 +11449,9 @@ private void putMessagesInternal(ArrayList messages, boolean with } statement = state_messages_topic; if (selfId == dialogId && MessageObject.getSavedDialogId(selfId, message) != 0) { + if (message.id < 0 && MessageObject.getSavedDialogId(selfId, message) != selfId) { + continue; + } if (changedSavedMessages == null) { changedSavedMessages = new ArrayList<>(); } @@ -11225,6 +11539,16 @@ private void putMessagesInternal(ArrayList messages, boolean with if (storyData != null) { storyData.reuse(); } + + if (dialogId == selfId) { + database.executeFast(String.format(Locale.US, "DELETE FROM tag_message_id WHERE mid = %d", message.id)).stepThis().dispose(); + if (state_messages_tags == null) { + state_messages_tags = database.executeFast("REPLACE INTO tag_message_id VALUES(?, ?, ?, ?)"); + } + state_messages_tags.requery(); + bindMessageTags(state_messages_tags, message); + state_messages_tags.step(); + } } if (message.random_id != 0) { @@ -11366,6 +11690,14 @@ private void putMessagesInternal(ArrayList messages, boolean with state_media.dispose(); state_media = null; } + if (state_media_topics != null) { + state_media_topics.dispose(); + state_media_topics = null; + } + if (state_messages_tags != null) { + state_messages_tags.dispose(); + state_messages_tags = null; + } if (state_tasks != null) { state_tasks.dispose(); getMessagesController().didAddedNewTask(minDeleteTime, 0, null); @@ -11450,7 +11782,7 @@ private void putMessagesInternal(ArrayList messages, boolean with dids.add(key); if (exists) { - if (message == null || (DialogObject.isEncryptedDialog(key) ? message.date > dialog_date : message.id >= last_mid) || message.send_state != 0 && ((message.flags & TLRPC.MESSAGE_FLAG_EDITED) == 0 || message.id >= last_mid)) { + if (message == null || (DialogObject.isEncryptedDialog(key) ? message.date > dialog_date : message.id >= last_mid) || message.send_state != 0 && (message.flags & TLRPC.MESSAGE_FLAG_EDITED) == 0) { state_dialogs_update.requery(); state_dialogs_update.bindInteger(1, message != null && (!doNotUpdateDialogDate || dialog_date == 0) ? message.date : dialog_date); state_dialogs_update.bindInteger(2, old_unread_count + unread_count); @@ -11725,6 +12057,12 @@ private void putMessagesInternal(ArrayList messages, boolean with if (state_webpage != null) { state_webpage.dispose(); } + if (state_media_topics != null) { + state_media_topics.dispose(); + } + if (state_messages_tags != null) { + state_messages_tags.dispose(); + } if (state_media != null) { state_media.dispose(); } @@ -12408,6 +12746,9 @@ private ArrayList markMessagesAsDeletedInternal(long dialogId, ArrayList dialogsIds = new ArrayList<>(); if (scheduled) { String ids = TextUtils.join(",", messages); @@ -12433,6 +12774,8 @@ private ArrayList markMessagesAsDeletedInternal(long dialogId, ArrayList unknownMessages = new ArrayList<>(messages); ArrayList unknownMessagesInTopics = new ArrayList<>(messages); LongSparseArray dialogsToUpdate = new LongSparseArray<>(); @@ -12444,8 +12787,8 @@ private ArrayList markMessagesAsDeletedInternal(long dialogId, ArrayList namesToDelete = new ArrayList<>(); ArrayList> idsToDelete = new ArrayList<>(); ArrayList topicUpdatesInUi = null; + ArrayList deletedMessages = currentUser == dialogId || dialogId == 0 ? new ArrayList<>() : null; - long currentUser = getUserConfig().getClientUserId(); if (dialogId != 0) { cursor = database.queryFinalized(String.format(Locale.US, "SELECT uid, data, read_state, out, mention, mid FROM messages_v2 WHERE mid IN(%s) AND uid = %d", ids, dialogId)); } else { @@ -12486,6 +12829,9 @@ private ArrayList markMessagesAsDeletedInternal(long dialogId, ArrayList markMessagesAsDeletedInternal(long dialogId, ArrayList { + boolean changed = false; + HashSet topicIds = new HashSet<>(); + for (TLRPC.Message msg : deletedMessages) { + if (getMessagesController().processDeletedReactionTags(msg)) { + topicIds.add(MessageObject.getSavedDialogId(currentUser, msg)); + changed = true; + } + } + if (changed) { + getMessagesController().updateSavedReactionTags(topicIds); + } + }); + } else if (deletedMessages != null && deletedMessages.isEmpty()) { + AndroidUtilities.runOnUIThread(() -> { + HashSet topicIds = new HashSet<>(); + boolean changed = false; + long[] topic_id = new long[1]; + for (int i = 0; i < messages.size(); ++i) { + if (getMediaDataController().processDeletedMessage(messages.get(i), topic_id)) { + topicIds.add(topic_id[0]); + changed = true; + } + } + if (changed) { + getMessagesController().updateSavedReactionTags(topicIds); + } + }); + } if (!unknownMessagesInTopics.isEmpty()) { if (dialogId == 0) { database.executeFast("UPDATE media_counts_topics SET old = 1 WHERE 1").stepThis().dispose(); @@ -13857,6 +14233,7 @@ public void putMessages(TLRPC.messages_Messages messages, long dialogId, int loa SQLitePreparedStatement state_messages_topics = null; SQLitePreparedStatement state_media = null; SQLitePreparedStatement state_media_topics = null; + SQLitePreparedStatement state_messages_tags = null; SQLitePreparedStatement state_polls = null; SQLitePreparedStatement state_webpage = null; SQLitePreparedStatement state_tasks = null; @@ -13925,6 +14302,7 @@ public void putMessages(TLRPC.messages_Messages messages, long dialogId, int loa closeHolesInMedia(dialogId, minId, maxId, -1, threadMessageId); } int count = messages.messages.size(); + final long selfId = getUserConfig().getClientUserId(); //load_type == 0 ? backward loading //load_type == 1 ? forward loading @@ -13935,6 +14313,7 @@ public void putMessages(TLRPC.messages_Messages messages, long dialogId, int loa ArrayList namesToDelete = new ArrayList<>(); ArrayList> idsToDelete = new ArrayList<>(); ArrayList changedSavedMessages = null; + ArrayList reactionUpdates = dialogId == selfId ? new ArrayList<>() : null; Integer lastMessageId = null; Long lastMessageGroupId = null; @@ -13948,7 +14327,16 @@ public void putMessages(TLRPC.messages_Messages messages, long dialogId, int loa int minDeleteTime = Integer.MAX_VALUE; HashMap botKeyboards = null; long channelId = 0; - final long selfId = getUserConfig().getClientUserId(); + final boolean self = selfId == dialogId; + if (self) { + ArrayList ids = new ArrayList<>(); + for (int a = 0; a < count; a++) { + TLRPC.Message message = messages.messages.get(a); + ids.add(message.id); + } + database.executeFast("DELETE FROM tag_message_id WHERE mid IN (" + TextUtils.join(",", ids) + ")").stepThis().dispose(); + state_messages_tags = database.executeFast("REPLACE INTO tag_message_id VALUES(?, ?, ?, ?)"); + } for (int a = 0; a < count; a++) { TLRPC.Message message = messages.messages.get(a); if (lastMessageId == null && message != null || lastMessageId != null && lastMessageId < message.id) { @@ -13969,6 +14357,9 @@ public void putMessages(TLRPC.messages_Messages messages, long dialogId, int loa TLRPC.Message oldMessage = TLRPC.Message.TLdeserialize(data, data.readInt32(false), false); oldMessage.readAttachPath(data, getUserConfig().clientUserId); data.reuse(); + if (reactionUpdates != null) { + reactionUpdates.add(new SavedReactionsUpdate(selfId, oldMessage, message)); + } int send_state = cursor.intValue(5); if (send_state != 3) { if (MessageObject.getFileName(oldMessage).equals(MessageObject.getFileName(message))) { @@ -14175,6 +14566,10 @@ public void putMessages(TLRPC.messages_Messages messages, long dialogId, int loa } currentState.step(); + if (i == 0 && state_messages_tags != null) { + bindMessageTags(state_messages_tags, message); + } + if (repliesData != null) { repliesData.reuse(); } @@ -14273,6 +14668,10 @@ public void putMessages(TLRPC.messages_Messages messages, long dialogId, int loa state_messages = null; state_messages_topics.dispose(); state_messages_topics = null; + if (state_messages_tags != null) { + state_messages_tags.dispose(); + state_messages_tags = null; + } state_media.dispose(); state_media = null; if (state_webpage != null) { @@ -14327,6 +14726,7 @@ public void putMessages(TLRPC.messages_Messages messages, long dialogId, int loa } }); } + onReactionsUpdate(reactionUpdates); } } catch (Exception e) { checkSQLException(e); @@ -14337,6 +14737,9 @@ public void putMessages(TLRPC.messages_Messages messages, long dialogId, int loa if (state_messages_topics != null) { state_messages_topics.dispose(); } + if (state_messages_tags != null) { + state_messages_tags.dispose(); + } if (state_messages != null) { state_messages.dispose(); } diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/NotificationCenter.java b/TMessagesProj/src/main/java/org/telegram/messenger/NotificationCenter.java index 7ae0091765..338253ec1b 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/NotificationCenter.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/NotificationCenter.java @@ -9,6 +9,7 @@ package org.telegram.messenger; import android.os.SystemClock; +import android.util.Log; import android.util.SparseArray; import android.view.View; @@ -230,6 +231,9 @@ public class NotificationCenter { public static final int savedMessagesDialogsUpdate = totalEvents++; public static final int savedReactionTagsUpdate = totalEvents++; public static final int userIsPremiumBlockedUpadted = totalEvents++; + public static final int savedMessagesForwarded = totalEvents++; + public static final int emojiKeywordsLoaded = totalEvents++; + public static final int storyQualityUpdate = totalEvents++; //global public static final int pushMessagesUpdated = totalEvents++; @@ -517,7 +521,7 @@ public void postNotificationNameOnUIThread(final int id, final Object... args) { } public void postNotificationName(int id, Object... args) { - boolean allowDuringAnimation = id == startAllHeavyOperations || id == stopAllHeavyOperations || id == didReplacedPhotoInMemCache || id == closeChats || id == invalidateMotionBackground; + boolean allowDuringAnimation = id == startAllHeavyOperations || id == stopAllHeavyOperations || id == didReplacedPhotoInMemCache || id == closeChats || id == invalidateMotionBackground || id == needCheckSystemBarColors; ArrayList expiredIndices = null; if (!allowDuringAnimation && allowedNotifications.size() > 0) { int size = allowedNotifications.size(); diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/SavedMessagesController.java b/TMessagesProj/src/main/java/org/telegram/messenger/SavedMessagesController.java index 1f6b675aae..7d354ba0d4 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/SavedMessagesController.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/SavedMessagesController.java @@ -2,29 +2,23 @@ import android.os.Bundle; import android.text.TextUtils; +import android.util.Log; import androidx.collection.LongSparseArray; -import com.google.android.exoplayer2.util.Log; -import com.google.android.exoplayer2.util.Util; - import org.telegram.SQLite.SQLiteCursor; import org.telegram.SQLite.SQLiteDatabase; -import org.telegram.SQLite.SQLiteException; import org.telegram.SQLite.SQLitePreparedStatement; import org.telegram.tgnet.ConnectionsManager; import org.telegram.tgnet.NativeByteBuffer; import org.telegram.tgnet.TLRPC; import org.telegram.ui.ActionBar.BaseFragment; -import org.telegram.ui.Cells.TextCell; import org.telegram.ui.ChatActivity; import org.telegram.ui.Components.AnimatedEmojiDrawable; import org.telegram.ui.LaunchActivity; -import java.math.BigInteger; import java.util.ArrayList; import java.util.Collections; -import java.util.HashMap; import java.util.HashSet; import java.util.Objects; @@ -98,6 +92,9 @@ private void updateAllDialogs(boolean notify) { allDialogs.addAll(dialogs); if (notify) { NotificationCenter.getInstance(currentAccount).postNotificationName(NotificationCenter.savedMessagesDialogsUpdate); + if (!hasDialogs() && MessagesController.getInstance(currentAccount).savedViewAsChats) { + MessagesController.getInstance(currentAccount).setSavedViewAs(false); + } } } @@ -111,6 +108,15 @@ public int getAllCount() { return cachedDialogs.size(); } + public boolean hasDialogs() { + if (getAllCount() <= 0) return false; + final long selfId = UserConfig.getInstance(currentAccount).getClientUserId(); + if (allDialogs.size() == 1 && allDialogs.get(0).dialogId == selfId) { + return false; + } + return true; + } + public int getLoadedCount() { return loadedDialogs.size(); } @@ -191,20 +197,21 @@ public boolean containsDialog(long dialogId) { return false; } - public void preloadDialogs() { + public void preloadDialogs(boolean cache) { if (!dialogsLoaded) { - loadDialogs(); + loadDialogs(cache); } } - public void loadDialogs() { + public void loadDialogs(boolean onlyCache) { + loadingCacheOnly = onlyCache; if (dialogsLoading || dialogsEndReached || loadingCache) { return; } if (!loadedCache) { - loadCache(this::loadDialogs); + loadCache(() -> loadDialogs(false)); return; - } + } else if (onlyCache) return; dialogsLoading = true; TLRPC.TL_messages_getSavedDialogs req = new TLRPC.TL_messages_getSavedDialogs(); @@ -365,10 +372,18 @@ public boolean updateSavedDialogs(ArrayList inputMessages) { found = true; if (d.top_message_id < message.id || message.id < 0 && message.date > d.getDate()) { changed = true; + if (d.top_message_id < message.id) { + int count = 0; + for (int k = 0; k < inputMessages.size(); ++k) { + if (inputMessages.get(k).id > d.top_message_id) { + count++; + } + } + d.messagesCount += count; + } d.message = new MessageObject(currentAccount, message, false, false); d.top_message_id = d.message.getId(); } - dialogsCountToCheck.add(d.dialogId); break; } } @@ -387,10 +402,18 @@ public boolean updateSavedDialogs(ArrayList inputMessages) { found = true; if (d.top_message_id < message.id || message.id < 0 && message.date > d.getDate()) { changed = true; + if (d.top_message_id < message.id) { + int count = 0; + for (int k = 0; k < inputMessages.size(); ++k) { + if (inputMessages.get(k).id > d.top_message_id) { + count++; + } + } + d.messagesCount += count; + } d.message = new MessageObject(currentAccount, message, false, false); d.top_message_id = d.message.getId(); } - dialogsCountToCheck.add(d.dialogId); break; } } @@ -403,9 +426,6 @@ public boolean updateSavedDialogs(ArrayList inputMessages) { changed = true; } } - if (!dialogsCountToCheck.isEmpty()) { - updateDialogsCount(dialogsCountToCheck); - } return changed; } @@ -432,6 +452,7 @@ public boolean updatedDialogCount(long dialogId, int messagesCount) { if (d.dialogId == dialogId) { if (d.messagesCount != messagesCount) { d.messagesCount = messagesCount; + d.messagesCountLoaded = true; return true; } break; @@ -519,7 +540,7 @@ private void invalidate() { dialogsCount = 0; dialogsEndReached = false; update(); - loadDialogs(); + loadDialogs(false); } public void deleteDialog(long did) { @@ -534,6 +555,14 @@ public void deleteDialogs(ArrayList dids) { update(); } + public void deleteAllDialogs() { + dialogsCount = 0; + allDialogs.clear(); + loadedDialogs.clear(); + cachedDialogs.clear(); + update(); + } + private int removeDialog(long did) { int acount = 0; for (int i = 0; i < allDialogs.size(); ++i) { @@ -565,7 +594,7 @@ public void update() { saveCacheSchedule(); } - public boolean updatePinned(ArrayList dialogIds, boolean pin) { + public boolean updatePinned(ArrayList dialogIds, boolean pin, boolean toServer) { ArrayList currentOrder = getCurrentPinnedOrder(allDialogs); ArrayList newOrder = new ArrayList<>(currentOrder); for (int i = dialogIds.size() - 1; i >= 0; --i) { @@ -585,9 +614,16 @@ public boolean updatePinned(ArrayList dialogIds, boolean pin) { return false; } if (!sameOrder(currentOrder, newOrder)) { - updatePinnedOrderToServer(newOrder); + if (toServer) { + updatePinnedOrderToServer(newOrder); + return true; + } else { + final boolean updateLoaded = updatePinnedOrder(loadedDialogs, newOrder); + final boolean updateCached = updatePinnedOrder(cachedDialogs, newOrder); + return updateLoaded || updateCached; + } } - return true; + return false; } public boolean updatePinnedOrder(ArrayList newOrder) { @@ -636,18 +672,9 @@ private boolean processUpdateInternal(TLRPC.Update update) { TLRPC.TL_updateSavedDialogPinned upd = (TLRPC.TL_updateSavedDialogPinned) update; if (!(upd.peer instanceof TLRPC.TL_dialogPeer)) return false; long dialogId = DialogObject.getPeerDialogId(((TLRPC.TL_dialogPeer) upd.peer).peer); - boolean changed = false; - ArrayList[] arraysToCheck = new ArrayList[] { loadedDialogs, cachedDialogs }; - for (int a = 0; a < arraysToCheck.length; ++a) { - for (int i = 0; i < arraysToCheck[a].size(); ++i) { - SavedDialog d = arraysToCheck[a].get(i); - if (d.dialogId == dialogId && d.pinned != upd.pinned) { - d.pinned = upd.pinned; - changed = true; - } - } - } - return changed; + ArrayList ids = new ArrayList<>(); + ids.add(dialogId); + return updatePinned(ids, upd.pinned, false); } else if (update instanceof TLRPC.TL_updatePinnedSavedDialogs) { TLRPC.TL_updatePinnedSavedDialogs upd = (TLRPC.TL_updatePinnedSavedDialogs) update; ArrayList newOrder = new ArrayList<>(upd.order.size()); @@ -731,49 +758,8 @@ private boolean updatePinnedOrder(ArrayList dialogs, ArrayList dialogIds) { - final long selfId = UserConfig.getInstance(currentAccount).getClientUserId(); - MessagesStorage messagesStorage = MessagesStorage.getInstance(currentAccount); - messagesStorage.getStorageQueue().postRunnable(() -> { - SQLiteDatabase db = messagesStorage.getDatabase(); - LongSparseArray countResult = new LongSparseArray<>(); - SQLiteCursor cursor = null; - try { - for (long did : dialogIds) { - cursor = db.queryFinalized("SELECT COUNT(*) FROM messages_topics WHERE uid = ? AND topic_id = ?", selfId, did); - if (cursor.next()) { - countResult.put(did, cursor.intValue(0)); - } - cursor.dispose(); - } - } catch (Exception e) { - FileLog.e(e); - } finally { - if (cursor != null) { - cursor.dispose(); - cursor = null; - } - } - AndroidUtilities.runOnUIThread(() -> { - boolean changed = false; - for (int i = 0; i < countResult.size(); ++i) { - long did = countResult.keyAt(i); - int count = countResult.valueAt(i); - - SavedDialog d = findSavedDialog(did); - if (d != null && d.messagesCount != count) { - d.messagesCount = count; - changed = true; - } - } - if (changed) { - update(); - } - }); - }); - } - private boolean loadingCache, loadedCache; + private boolean loadingCacheOnly; private void loadCache(Runnable whenDone) { if (loadingCache) { return; @@ -802,6 +788,8 @@ private void loadCache(Runnable whenDone) { d.localDate = cursor.intValue(1); d.top_message_id = cursor.intValue(2); d.pinnedOrder = cursor.intValue(3); + final int flags = cursor.intValue(4); + d.messagesCountLoaded = (flags & 1) != 0; d.pinned = d.pinnedOrder != 999; d.messagesCount = cursor.intValue(7); if (d.dialogId < 0) { @@ -855,7 +843,7 @@ private void loadCache(Runnable whenDone) { cachedDialogs.addAll(dialogs); updateAllDialogs(true); - if (whenDone != null) { + if (whenDone != null && !loadingCacheOnly) { whenDone.run(); } }); @@ -974,7 +962,7 @@ private void saveCache() { state.bindInteger(2, d.getDate()); state.bindInteger(3, d.top_message_id); state.bindInteger(4, d.pinned ? i : 999); - state.bindInteger(5, 0); + state.bindInteger(5, d.messagesCountLoaded ? 1 : 0); state.bindInteger(6, 0); state.bindInteger(7, 0); state.bindInteger(8, d.messagesCount); @@ -1022,6 +1010,8 @@ public static class SavedDialog { public MessageObject message; public int messagesCount; + public boolean messagesCountLoaded; + // used only in cache private int localDate; @@ -1032,7 +1022,7 @@ public int getDate() { if (message == null || message.messageOwner == null) { return localDate; } - if ((message.messageOwner.flags & TLRPC.MESSAGE_FLAG_EDITED) != 0) { + if ((message.messageOwner.flags & TLRPC.MESSAGE_FLAG_EDITED) != 0 && !message.messageOwner.edit_hide) { return message.messageOwner.edit_date; } return message.messageOwner.date; @@ -1080,23 +1070,28 @@ public static void openSavedMessages() { lastFragment.presentFragment(new ChatActivity(args)); } + public void checkSavedDialogCount(long dialogId) { + SavedDialog d = findSavedDialog(dialogId); + if (d != null && !d.messagesCountLoaded) { + hasSavedMessages(dialogId, null); + } + } + private final LongSparseArray>> checkMessagesCallbacks = new LongSparseArray<>(); public void hasSavedMessages(long did, Utilities.Callback whenDone) { - if (whenDone == null) return; - final SavedDialog savedDialog = findSavedDialog(did); - if (savedDialog != null && savedDialog.messagesCount > 0) { - whenDone.run(true); + if (savedDialog != null && savedDialog.messagesCount > 0 && savedDialog.messagesCountLoaded) { + if (whenDone != null) whenDone.run(true); return; } ArrayList> existingCallbacks = checkMessagesCallbacks.get(did); if (existingCallbacks != null) { - existingCallbacks.add(whenDone); + if (whenDone != null) existingCallbacks.add(whenDone); return; } existingCallbacks = new ArrayList<>(); - existingCallbacks.add(whenDone); + if (whenDone != null) existingCallbacks.add(whenDone); checkMessagesCallbacks.put(did, existingCallbacks); TLRPC.TL_messages_getSavedHistory req = new TLRPC.TL_messages_getSavedHistory(); @@ -1124,9 +1119,12 @@ public void hasSavedMessages(long did, Utilities.Callback whenDone) { if (!r.messages.isEmpty()) { SavedDialog dialog = SavedDialog.fromMessage(currentAccount, r.messages.get(0)); dialog.messagesCount = count; + dialog.messagesCountLoaded = true; cachedDialogs.add(dialog); update(); } + } else { + update(); } } diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/SendMessagesHelper.java b/TMessagesProj/src/main/java/org/telegram/messenger/SendMessagesHelper.java index 60599857e3..bf8b6e049a 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/SendMessagesHelper.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/SendMessagesHelper.java @@ -2191,6 +2191,7 @@ public int sendMessage(ArrayList messages, final long peer, boole a1--; } } + getNotificationCenter().postNotificationNameOnUIThread(NotificationCenter.savedMessagesForwarded, newMessagesByIds); Integer value = getMessagesController().dialogs_read_outbox_max.get(peer); if (value == null) { value = getMessagesStorage().getDialogReadMax(true, peer); @@ -2960,7 +2961,7 @@ protected long getVoteSendTime(long pollId) { return voteSendTime.get(pollId, 0L); } - public void sendReaction(MessageObject messageObject, ArrayList visibleReactions, ReactionsLayoutInBubble.VisibleReaction addedReaction, boolean big, boolean addToRecent, ChatActivity parentFragment, Runnable callback) { + public void sendReaction(MessageObject messageObject, ArrayList visibleReactions, ReactionsLayoutInBubble.VisibleReaction addedReaction, boolean big, boolean addToRecent, BaseFragment parentFragment, Runnable callback) { if (messageObject == null || parentFragment == null) { return; } @@ -4094,6 +4095,7 @@ public void sendMessage(SendMessageParams sendMessageParams) { inputWebPage.url = mediaWebPage.webpage.url; inputWebPage.force_large_media = mediaWebPage.force_large_media; inputWebPage.force_small_media = mediaWebPage.force_small_media; + inputWebPage.optional = true; reqSend.media = inputWebPage; if (replyToStoryItem != null) { reqSend.reply_to = createReplyInput(replyToStoryItem); @@ -5104,10 +5106,12 @@ private void performSendDelayedMessage(final DelayedMessage message, int index) } } putToDelayedMessages(location, message); - if (message.obj.videoEditedInfo != null && message.obj.videoEditedInfo.needConvert()) { - getFileLoader().uploadFile(location, true, false, document.size, ConnectionsManager.FileTypeVideo, false); - } else { - getFileLoader().uploadFile(location, true, false, ConnectionsManager.FileTypeVideo); + if (message.obj.videoEditedInfo == null || !message.obj.videoEditedInfo.notReadyYet) { + if (message.obj.videoEditedInfo != null && message.obj.videoEditedInfo.needConvert()) { + getFileLoader().uploadFile(location, true, false, document.size, ConnectionsManager.FileTypeVideo, false); + } else { + getFileLoader().uploadFile(location, true, false, ConnectionsManager.FileTypeVideo); + } } putToUploadingMessages(message.obj); } diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/SharedConfig.java b/TMessagesProj/src/main/java/org/telegram/messenger/SharedConfig.java index ca0572ede7..900abde146 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/SharedConfig.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/SharedConfig.java @@ -278,7 +278,6 @@ private static boolean isWhitelisted(MediaCodecInfo codecInfo) { public static int keepMedia = CacheByChatsController.KEEP_MEDIA_ONE_MONTH; //deprecated public static int lastKeepMediaCheckTime; public static int lastLogsCheckTime; - public static int searchMessagesAsListHintShows; public static int textSelectionHintShows; public static int scheduledOrNoSoundHintShows; public static long scheduledOrNoSoundHintSeenAt; @@ -349,7 +348,6 @@ private static boolean isWhitelisted(MediaCodecInfo codecInfo) { public static int messageSeenHintCount; public static int emojiInteractionsHintCount; public static int dayNightThemeSwitchHintCount; - public static boolean forceLessData; public static int callEncryptionHintDisplayedCount; public static TLRPC.TL_help_appUpdate pendingAppUpdate; @@ -1487,7 +1485,6 @@ public static void loadConfig() { debugWebView = preferences.getBoolean("debugWebView", false); lastKeepMediaCheckTime = preferences.getInt("lastKeepMediaCheckTime", 0); lastLogsCheckTime = preferences.getInt("lastLogsCheckTime", 0); - searchMessagesAsListHintShows = preferences.getInt("searchMessagesAsListHintShows", 0); searchMessagesAsListUsed = preferences.getBoolean("searchMessagesAsListUsed", false); stickersReorderingHintUsed = preferences.getBoolean("stickersReorderingHintUsed", false); storyReactionsLongPressHint = preferences.getBoolean("storyReactionsLongPressHint", false); @@ -1552,7 +1549,6 @@ public static void loadConfig() { payByInvoice = preferences.getBoolean("payByInvoice", false); photoViewerBlur = preferences.getBoolean("photoViewerBlur", true); multipleReactionsPromoShowed = preferences.getBoolean("multipleReactionsPromoShowed", false); - forceLessData = preferences.getBoolean("forceLessData", false); callEncryptionHintDisplayedCount = preferences.getInt("callEncryptionHintDisplayedCount", 0); loadDebugConfig(preferences); @@ -1910,13 +1906,6 @@ public static void removeLockRecordAudioVideoHint() { editor.apply(); } - public static void increaseSearchAsListHintShows() { - SharedPreferences preferences = MessagesController.getGlobalMainSettings(); - SharedPreferences.Editor editor = preferences.edit(); - editor.putInt("searchMessagesAsListHintShows", ++searchMessagesAsListHintShows); - editor.apply(); - } - public static void setKeepMedia(int value) { keepMedia = value; SharedPreferences preferences = MessagesController.getGlobalMainSettings(); @@ -2637,11 +2626,6 @@ public static void updateEmojiInteractionsHintCount(int count) { preferences.edit().putInt("emojiInteractionsHintCount", emojiInteractionsHintCount).apply(); } - public static void setForceLessData(boolean value) { - SharedPreferences preferences = MessagesController.getGlobalMainSettings(); - preferences.edit().putBoolean("forceLessData", forceLessData = value).apply(); - } - public static void updateDayNightThemeSwitchHintCount(int count) { dayNightThemeSwitchHintCount = count; SharedPreferences preferences = ApplicationLoader.applicationContext.getSharedPreferences("mainconfig", Activity.MODE_PRIVATE); diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/TopicsController.java b/TMessagesProj/src/main/java/org/telegram/messenger/TopicsController.java index e07eae3b57..4155f19d09 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/TopicsController.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/TopicsController.java @@ -1001,7 +1001,7 @@ public void processEditedMessage(TLRPC.Message newMsg) { } } - public void loadTopic(long chatId, int topicId, Runnable runnable) { + public void loadTopic(long chatId, long topicId, Runnable runnable) { getMessagesStorage().loadTopics(-chatId, topics -> { AndroidUtilities.runOnUIThread(() -> { if (BuildVars.LOGS_ENABLED) { @@ -1015,7 +1015,7 @@ public void loadTopic(long chatId, int topicId, Runnable runnable) { } else { ArrayList topicToReload = new ArrayList<>(); TLRPC.TL_forumTopic topic = new TLRPC.TL_forumTopic(); - topic.id = topicId; + topic.id = (int) topicId; reloadTopics(chatId, topicToReload, runnable); } }); diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/Utilities.java b/TMessagesProj/src/main/java/org/telegram/messenger/Utilities.java index bce77a26b0..0f68903dd7 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/Utilities.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/Utilities.java @@ -500,6 +500,16 @@ public static float clamp(float value, float maxValue, float minValue) { return Math.max(Math.min(value, maxValue), minValue); } + public static double clamp(double value, double maxValue, double minValue) { + if (Double.isNaN(value)) { + return minValue; + } + if (Double.isInfinite(value)) { + return maxValue; + } + return Math.max(Math.min(value, maxValue), minValue); + } + public static String generateRandomString() { return generateRandomString(16); } diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/VideoEncodingService.java b/TMessagesProj/src/main/java/org/telegram/messenger/VideoEncodingService.java index 0c9f6bf851..b64d51bd2f 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/VideoEncodingService.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/VideoEncodingService.java @@ -11,11 +11,10 @@ import android.app.Service; import android.content.Intent; import android.os.IBinder; + import androidx.core.app.NotificationCompat; import androidx.core.app.NotificationManagerCompat; -import com.google.android.exoplayer2.util.Log; - public class VideoEncodingService extends Service implements NotificationCenter.NotificationCenterDelegate { private NotificationCompat.Builder builder; @@ -89,11 +88,7 @@ public void didReceivedNotification(int id, int account, Object... args) { Boolean enc = (Boolean) args[3]; int currentProgress = (int) (progress * 100); builder.setProgress(100, currentProgress, currentProgress == 0); - try { - NotificationManagerCompat.from(ApplicationLoader.applicationContext).notify(4, builder.build()); - } catch (Throwable e) { - FileLog.e(e); - } + updateNotification(); } } else if (id == NotificationCenter.fileUploaded || id == NotificationCenter.fileUploadFailed) { String fileName = (String) args[0]; @@ -110,12 +105,27 @@ public void didReceivedNotification(int id, int account, Object... args) { } } + private void updateNotification() { + try { + MediaController.VideoConvertMessage message = MediaController.getInstance().getCurrentForegroundConverMessage(); + if (message == null) { + return; + } + NotificationManagerCompat.from(ApplicationLoader.applicationContext).notify(4, builder.build()); + } catch (Throwable e) { + FileLog.e(e); + } + } + public int onStartCommand(Intent intent, int flags, int startId) { if (isRunning()) { return Service.START_NOT_STICKY; } - instance = this; MediaController.VideoConvertMessage videoConvertMessage = MediaController.getInstance().getCurrentForegroundConverMessage(); + if (videoConvertMessage == null) { + return Service.START_NOT_STICKY; + } + instance = this; if (builder == null) { NotificationsController.checkOtherNotificationsChannel(); builder = new NotificationCompat.Builder(ApplicationLoader.applicationContext, NotificationsController.OTHER_NOTIFICATIONS_CHANNEL); @@ -124,7 +134,6 @@ public int onStartCommand(Intent intent, int flags, int startId) { builder.setChannelId(NotificationsController.OTHER_NOTIFICATIONS_CHANNEL); builder.setContentTitle(LocaleController.getString("AppName", R.string.AppName)); } - setCurrentMessage(videoConvertMessage); try { startForeground(4, builder.build()); @@ -132,7 +141,7 @@ public int onStartCommand(Intent intent, int flags, int startId) { //ignore ForegroundServiceStartNotAllowedException FileLog.e(e); } - AndroidUtilities.runOnUIThread(() -> NotificationManagerCompat.from(ApplicationLoader.applicationContext).notify(4, builder.build())); + AndroidUtilities.runOnUIThread(this::updateNotification); return Service.START_NOT_STICKY; } @@ -169,7 +178,7 @@ private void setCurrentMessage(MediaController.VideoConvertMessage message) { NotificationCenter.getInstance(currentAccount).addObserver(this, NotificationCenter.fileUploadFailed); NotificationCenter.getInstance(currentAccount).addObserver(this, NotificationCenter.fileUploaded); if (isRunning()) { - NotificationManagerCompat.from(ApplicationLoader.applicationContext).notify(4, builder.build()); + updateNotification(); } } diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/video/VideoPlayerHolderBase.java b/TMessagesProj/src/main/java/org/telegram/messenger/video/VideoPlayerHolderBase.java index 53a6283c58..3f8b016f6c 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/video/VideoPlayerHolderBase.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/video/VideoPlayerHolderBase.java @@ -86,7 +86,7 @@ public void run() { long startTime; - public void preparePlayer(Uri uri, boolean audioDisabled) { + public void preparePlayer(Uri uri, boolean audioDisabled, float speed) { this.audioDisabled = audioDisabled; this.currentAccount = currentAccount; this.contentUri = uri; @@ -99,13 +99,14 @@ public void preparePlayer(Uri uri, boolean audioDisabled) { return; } ensurePlayerCreated(audioDisabled); + videoPlayer.setPlaybackSpeed(speed); videoPlayer.preparePlayer(uri, "other", FileLoader.PRIORITY_LOW); videoPlayer.setPlayWhenReady(false); videoPlayer.setWorkerQueue(dispatchQueue); }); } - public void start(boolean paused, Uri uri, long position, boolean audioDisabled) { + public void start(boolean paused, Uri uri, long position, boolean audioDisabled, float speed) { startTime = System.currentTimeMillis(); this.audioDisabled = audioDisabled; this.paused = paused; @@ -118,6 +119,7 @@ public void start(boolean paused, Uri uri, long position, boolean audioDisabled) } if (videoPlayer == null) { ensurePlayerCreated(audioDisabled); + videoPlayer.setPlaybackSpeed(speed); videoPlayer.preparePlayer(uri, "other"); videoPlayer.setWorkerQueue(dispatchQueue); if (!paused) { @@ -280,6 +282,17 @@ public void prepareStub() { } } + public void setSpeed(float speed) { + if (released) { + return; + } + dispatchQueue.postRunnable(() -> { + if (videoPlayer != null) { + videoPlayer.setPlaybackSpeed(speed); + } + }); + } + public void play() { if (released) { return; @@ -304,6 +317,31 @@ public void play() { }); } + public void play(float speed) { + if (released) { + return; + } + if (!paused) { + return; + } + paused = false; + dispatchQueue.postRunnable(() -> { + if (videoPlayer != null) { + if (surfaceView != null) { + videoPlayer.setSurfaceView(surfaceView); + } else { + videoPlayer.setTextureView(textureView); + } + if (pendingSeekTo > 0) { + videoPlayer.seekTo(pendingSeekTo); + pendingSeekTo = 0; + } + videoPlayer.setPlaybackSpeed(speed); + videoPlayer.setPlayWhenReady(true); + } + }); + } + public void setAudioEnabled(boolean enabled, boolean prepared) { boolean disabled = !enabled; if (audioDisabled == disabled) { @@ -430,16 +468,6 @@ public Uri getCurrentUri() { return contentUri; } - public void setPlaybackSpeed(float currentVideoSpeed) { - dispatchQueue.postRunnable(() -> { - if (videoPlayer == null) { - return; - } - videoPlayer.setPlaybackSpeed(currentVideoSpeed); - }); - - } - private Runnable onSeekUpdate; public void setOnSeekUpdate(Runnable onSeekUpdate) { this.onSeekUpdate = onSeekUpdate; diff --git a/TMessagesProj/src/main/java/org/telegram/tgnet/ConnectionsManager.java b/TMessagesProj/src/main/java/org/telegram/tgnet/ConnectionsManager.java index 7236287872..5f00677df6 100644 --- a/TMessagesProj/src/main/java/org/telegram/tgnet/ConnectionsManager.java +++ b/TMessagesProj/src/main/java/org/telegram/tgnet/ConnectionsManager.java @@ -399,7 +399,7 @@ private void sendRequestInternal(TLObject object, RequestDelegate onComplete, Re if (BuildVars.LOGS_ENABLED) { FileLog.d("java received " + resp + " error = " + error + " messageId = " + requestMsgId); } - FileLog.dumpResponseAndRequest(object, resp, error, requestMsgId, finalStartRequestTime, requestToken); + FileLog.dumpResponseAndRequest(currentAccount, object, resp, error, requestMsgId, finalStartRequestTime, requestToken); final TLObject finalResponse = resp; final TLRPC.TL_error finalError = error; Utilities.stageQueue.postRunnable(() -> { diff --git a/TMessagesProj/src/main/java/org/telegram/tgnet/TLRPC.java b/TMessagesProj/src/main/java/org/telegram/tgnet/TLRPC.java index f0afb74bef..ce89ddd479 100644 --- a/TMessagesProj/src/main/java/org/telegram/tgnet/TLRPC.java +++ b/TMessagesProj/src/main/java/org/telegram/tgnet/TLRPC.java @@ -24,6 +24,7 @@ import org.telegram.messenger.FileLog; import org.telegram.messenger.ImageLoader; import org.telegram.messenger.MessageObject; +import org.telegram.messenger.MessagesController; import org.telegram.messenger.SvgHelper; import org.telegram.messenger.Utilities; import org.telegram.tgnet.tl.TL_stories; @@ -82,7 +83,7 @@ public class TLRPC { public static final int MESSAGE_FLAG_HAS_BOT_ID = 0x00000800; public static final int MESSAGE_FLAG_EDITED = 0x00008000; - public static final int LAYER = 172; + public static final int LAYER = 173; public static class TL_stats_megagroupStats extends TLObject { public static final int constructor = 0xef7ff916; @@ -28886,6 +28887,8 @@ public static class TL_savedReactionTag extends TLObject { public String title; public int count; + public long hash; // custom + public static TL_savedReactionTag TLdeserialize(AbstractSerializedData stream, int constructor, boolean exception) { if (TL_savedReactionTag.constructor != constructor) { if (exception) { @@ -55749,6 +55752,8 @@ public void serializeToStream(AbstractSerializedData stream) { public static abstract class Reaction extends TLObject { + public long tag_long_id; // custom + public static Reaction TLdeserialize(AbstractSerializedData stream, int constructor, boolean exception) { Reaction result = null; switch (constructor) { @@ -60870,7 +60875,7 @@ public void serializeToStream(AbstractSerializedData stream) { stream.writeInt32(constructor); stream.writeInt32(flags); peer.serializeToStream(stream); - if ((flags & 2) != 0) { + if ((flags & 4) != 0) { saved_peer_id.serializeToStream(stream); } if ((flags & 1) != 0) { @@ -65009,9 +65014,8 @@ public static MessageMedia TLdeserialize(AbstractSerializedData stream, int cons return result; } - public Boolean documentExists; public Document getDocument() { - if (alt_document != null && ApplicationLoader.useLessData()) { + if (alt_document != null && !MessagesController.isStoryQualityFull()) { return alt_document; } return document; @@ -75116,8 +75120,10 @@ public void serializeToStream(AbstractSerializedData stream) { } public static class TL_messages_getSavedReactionTags extends TLObject { - public static final int constructor = 0x761ddacf; + public static final int constructor = 0x3637e05b; + public int flags; + public InputPeer peer; public long hash; @Override @@ -75128,6 +75134,10 @@ public TLObject deserializeResponse(AbstractSerializedData stream, int construct @Override public void serializeToStream(AbstractSerializedData stream) { stream.writeInt32(constructor); + stream.writeInt32(flags); + if ((flags & 1) != 0) { + peer.serializeToStream(stream); + } stream.writeInt64(hash); } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/ActionBar.java b/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/ActionBar.java index d56da32a48..2de590e386 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/ActionBar.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/ActionBar.java @@ -25,6 +25,7 @@ import android.graphics.PorterDuffColorFilter; import android.graphics.Rect; import android.graphics.RectF; +import android.graphics.drawable.BitmapDrawable; import android.graphics.drawable.Drawable; import android.os.Build; import android.text.Layout; @@ -153,8 +154,6 @@ public boolean canOpenMenu() { private View.OnTouchListener interceptTouchEventListener; private final Theme.ResourcesProvider resourcesProvider; - private PorterDuff.Mode colorFilterMode = PorterDuff.Mode.SRC_IN; - SizeNotifierFrameLayout contentView; boolean blurredBackground; public Paint blurScrimPaint = new Paint(); @@ -179,10 +178,6 @@ public ActionBar(Context context, Theme.ResourcesProvider resourcesProvider) { }); } - public void setColorFilterMode(PorterDuff.Mode colorFilterMode) { - this.colorFilterMode = colorFilterMode; - } - public INavigationLayout.BackButtonState getBackButtonState() { if (backButtonDrawable instanceof INavigationLayout.IBackButtonDrawable) { return ((INavigationLayout.IBackButtonDrawable) backButtonDrawable).getBackButtonState(); @@ -197,9 +192,6 @@ private void createBackButtonImage() { backButtonImageView = new UnreadImageView(getContext()); backButtonImageView.setScaleType(ImageView.ScaleType.CENTER); backButtonImageView.setBackgroundDrawable(Theme.createSelectorDrawable(itemsBackgroundColor)); - if (itemsColor != 0) { - backButtonImageView.setColorFilter(new PorterDuffColorFilter(itemsColor, colorFilterMode)); - } backButtonImageView.setPadding(dp(1), 0, 0, 0); addView(backButtonImageView, LayoutHelper.createFrame(54, 54, Gravity.LEFT | Gravity.TOP)); @@ -234,6 +226,8 @@ public void setBackButtonDrawable(Drawable drawable) { MenuDrawable menuDrawable = (MenuDrawable) drawable; menuDrawable.setBackColor(actionBarColor); menuDrawable.setIconColor(itemsColor); + } else if (drawable instanceof BitmapDrawable) { + backButtonImageView.setColorFilter(new PorterDuffColorFilter(itemsColor, PorterDuff.Mode.SRC_IN)); } } @@ -383,6 +377,7 @@ public void setBackButtonImage(int resource) { } backButtonImageView.setVisibility(resource == 0 ? GONE : VISIBLE); backButtonImageView.setImageResource(resource); + backButtonImageView.setColorFilter(new PorterDuffColorFilter(itemsColor, PorterDuff.Mode.SRC_IN)); } private void createSubtitleTextView() { @@ -1624,18 +1619,21 @@ public void setItemsColor(int color, boolean isActionMode) { Drawable drawable = backButtonImageView.getDrawable(); if (drawable instanceof BackDrawable) { ((BackDrawable) drawable).setRotatedColor(color); + } else if (drawable instanceof BitmapDrawable) { + backButtonImageView.setColorFilter(new PorterDuffColorFilter(color, PorterDuff.Mode.SRC_IN)); } } } else { itemsColor = color; if (backButtonImageView != null) { if (itemsColor != 0) { - backButtonImageView.setColorFilter(new PorterDuffColorFilter(itemsColor, colorFilterMode)); Drawable drawable = backButtonImageView.getDrawable(); if (drawable instanceof BackDrawable) { ((BackDrawable) drawable).setColor(color); } else if (drawable instanceof MenuDrawable) { ((MenuDrawable) drawable).setIconColor(color); + } else if (drawable instanceof BitmapDrawable) { + backButtonImageView.setColorFilter(new PorterDuffColorFilter(color, PorterDuff.Mode.SRC_IN)); } } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/ActionBarLayout.java b/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/ActionBarLayout.java index 11ce0d2050..8004b340ee 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/ActionBarLayout.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/ActionBarLayout.java @@ -65,6 +65,7 @@ import org.telegram.ui.Components.GroupCallPip; import org.telegram.ui.Components.LayoutHelper; import org.telegram.ui.LaunchActivity; +import org.telegram.ui.LogoutActivity; import org.telegram.ui.Stories.StoryViewer; import java.util.ArrayList; @@ -1639,6 +1640,12 @@ public boolean addFragmentToStack(BaseFragment fragment, int position) { fragmentsStack.add(position, fragment); onFragmentStackChanged("addFragmentToStack"); } + if (!useAlphaAnimations) { + setVisibility(VISIBLE); + if (backgroundView != null) { + backgroundView.setVisibility(VISIBLE); + } + } return true; } @@ -2055,6 +2062,11 @@ public void removeAllFragments() { removeFragmentFromStackInternal(fragmentsStack.get(a), false); a--; } + if (backgroundView != null) { + backgroundView.animate().alpha(0.0f).setDuration(180).withEndAction(() -> { + backgroundView.setVisibility(View.GONE); + }).start(); + } } @Keep diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/ActionBarMenu.java b/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/ActionBarMenu.java index ddeb8f9343..d161290284 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/ActionBarMenu.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/ActionBarMenu.java @@ -508,6 +508,13 @@ public ActionBarMenuItem getItem(int id) { return null; } + public void setItemVisibility(int id, int visibility) { + View item = getItem(id); + if (item != null) { + item.setVisibility(visibility); + } + } + @Override public void setEnabled(boolean enabled) { super.setEnabled(enabled); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/ActionBarMenuItem.java b/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/ActionBarMenuItem.java index 849ab85d24..d8b0d9f014 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/ActionBarMenuItem.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/ActionBarMenuItem.java @@ -32,6 +32,7 @@ import android.transition.TransitionSet; import android.transition.TransitionValues; import android.transition.Visibility; +import android.util.Log; import android.util.TypedValue; import android.view.ActionMode; import android.view.Gravity; @@ -962,7 +963,7 @@ private void onFiltersChanged() { boolean visible = !currentSearchFilters.isEmpty(); ArrayList localFilters = new ArrayList<>(currentSearchFilters); - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT && searchContainer.getTag() != null) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT && searchContainer != null && searchContainer.getTag() != null) { TransitionSet transition = new TransitionSet(); ChangeBounds changeBounds = new ChangeBounds(); changeBounds.setDuration(150); @@ -1028,11 +1029,13 @@ public void onTransitionResume(Transition transition) { TransitionManager.beginDelayedTransition(searchFilterLayout, transition); } - for (int i = 0; i < searchFilterLayout.getChildCount(); i++) { - boolean removed = localFilters.remove(((SearchFilterView) searchFilterLayout.getChildAt(i)).getFilter()); - if (!removed) { - searchFilterLayout.removeViewAt(i); - i--; + if (searchFilterLayout != null) { + for (int i = 0; i < searchFilterLayout.getChildCount(); i++) { + boolean removed = localFilters.remove(((SearchFilterView) searchFilterLayout.getChildAt(i)).getFilter()); + if (!removed) { + searchFilterLayout.removeViewAt(i); + i--; + } } } @@ -2071,10 +2074,11 @@ public void setData(FiltersView.MediaFilterData data) { reactionCount.count = 1; reactionCount.reaction = data.reaction.toTLReaction(); - reactionButton = new ReactionsLayoutInBubble.ReactionButton(null, UserConfig.selectedAccount, this, reactionCount, false, resourcesProvider) { + reactionButton = new ReactionsLayoutInBubble.ReactionButton(null, UserConfig.selectedAccount, this, reactionCount, false, true, resourcesProvider) { @Override protected void updateColors(float progress) { lastDrawnBackgroundColor = ColorUtils.blendARGB(fromBackgroundColor, Theme.getColor(Theme.key_chat_inReactionButtonBackground, resourcesProvider), progress); + lastDrawnTagDotColor = ColorUtils.blendARGB(fromTagDotColor, 0x5affffff, progress); } @Override @@ -2082,6 +2086,7 @@ protected int getCacheType() { return AnimatedEmojiDrawable.CACHE_TYPE_ALERT_EMOJI_STATUS; } }; + reactionButton.isTag = true; reactionButton.width = dp(44.33f); reactionButton.height = dp(28); reactionButton.choosen = true; 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 4a4c006c68..65c4757494 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/ActionBarMenuSubItem.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/ActionBarMenuSubItem.java @@ -37,7 +37,7 @@ public class ActionBarMenuSubItem extends FrameLayout { private int itemHeight = 48; private final Theme.ResourcesProvider resourcesProvider; - Runnable openSwipeBackLayout; + public Runnable openSwipeBackLayout; public ActionBarMenuSubItem(Context context, boolean top, boolean bottom) { this(context, false, top, bottom); 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 74f84127ad..8519c87ae2 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/AlertDialog.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/AlertDialog.java @@ -65,6 +65,7 @@ import org.telegram.messenger.NotificationCenter; import org.telegram.messenger.R; import org.telegram.messenger.SharedConfig; +import org.telegram.ui.Components.AnimatedEmojiDrawable; import org.telegram.ui.Components.AnimatedFloat; import org.telegram.ui.Components.EffectsTextView; import org.telegram.ui.Components.LayoutHelper; @@ -85,11 +86,12 @@ public class AlertDialog extends Dialog implements Drawable.Callback, Notificati public static final int ALERT_TYPE_LOADING = 2; public static final int ALERT_TYPE_SPINNER = 3; + private int customWidth = -1; private View customView; private View bottomView; private View aboveMessageView; private int customViewHeight = LayoutHelper.WRAP_CONTENT; - private TextView titleTextView; + private SpoilersTextView titleTextView; private TextView secondTitleTextView; private TextView subtitleTextView; private TextView messageTextView; @@ -343,6 +345,11 @@ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { inLayout = true; int width = MeasureSpec.getSize(widthMeasureSpec); int height = MeasureSpec.getSize(heightMeasureSpec); + + if (customWidth > 0) { + width = customWidth + backgroundPaddings.left + backgroundPaddings.right; + } + int maxContentHeight; int availableHeight = maxContentHeight = height - getPaddingTop() - getPaddingBottom(); int availableWidth = width - getPaddingLeft() - getPaddingRight(); @@ -598,7 +605,13 @@ protected void dispatchDraw(Canvas canvas) { } containerView.setFitsSystemWindows(Build.VERSION.SDK_INT >= 21); if (setContent) { - setContentView(containerView); + if (customWidth > 0) { + FrameLayout.LayoutParams lp = new FrameLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT); + lp.gravity = Gravity.CENTER; + setContentView(containerView, lp); + } else { + setContentView(containerView); + } } final boolean hasButtons = positiveButtonText != null || negativeButtonText != null || neutralButtonText != null; @@ -670,6 +683,8 @@ public int getOpacity() { containerView.addView(titleContainer, LayoutHelper.createLinear(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, topAnimationIsNew ? Gravity.CENTER_HORIZONTAL : 0, 24, 0, 24, 0)); titleTextView = new SpoilersTextView(getContext(), false); + NotificationCenter.listenEmojiLoading(titleTextView); + titleTextView.cacheType = AnimatedEmojiDrawable.CACHE_TYPE_ALERT_PREVIEW; titleTextView.setText(title); titleTextView.setTextColor(getThemedColor(Theme.key_dialogTextBlack)); titleTextView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 20); @@ -1555,6 +1570,11 @@ public Builder setView(View view, int height) { return this; } + public Builder setWidth(int width) { + alertDialog.customWidth = width; + return this; + } + public Builder aboveMessageView(View view) { alertDialog.aboveMessageView = view; return this; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/AlertDialogDecor.java b/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/AlertDialogDecor.java index cbabb65380..a49530b7de 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/AlertDialogDecor.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/AlertDialogDecor.java @@ -9,6 +9,7 @@ import android.graphics.Color; import android.graphics.Rect; import android.os.Build; +import android.util.Log; import android.util.TypedValue; import android.view.ContextThemeWrapper; import android.view.Gravity; @@ -25,6 +26,7 @@ import androidx.core.view.WindowInsetsCompat; import org.telegram.messenger.AndroidUtilities; +import org.telegram.ui.Stories.recorder.KeyboardNotifier; public class AlertDialogDecor extends AlertDialog { @@ -102,11 +104,8 @@ public void show() { container.addView(dimView, new FrameLayout.LayoutParams(FrameLayout.LayoutParams.MATCH_PARENT, FrameLayout.LayoutParams.MATCH_PARENT)); final FrameLayout contentWrapper = new FrameLayout(getContext()); - contentWrapper.addView(contentView, new FrameLayout.LayoutParams(FrameLayout.LayoutParams.MATCH_PARENT, FrameLayout.LayoutParams.WRAP_CONTENT)); - - FrameLayout.LayoutParams containerParams = new FrameLayout.LayoutParams(params.width, FrameLayout.LayoutParams.WRAP_CONTENT); - containerParams.gravity = Gravity.CENTER; - container.addView(contentWrapper, containerParams); + contentWrapper.addView(contentView, new FrameLayout.LayoutParams(FrameLayout.LayoutParams.MATCH_PARENT, FrameLayout.LayoutParams.WRAP_CONTENT, Gravity.CENTER)); + container.addView(contentWrapper, new FrameLayout.LayoutParams(params.width, FrameLayout.LayoutParams.WRAP_CONTENT, Gravity.CENTER)); rootView = container; getDecorView().addView(rootView); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/BackDrawable.java b/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/BackDrawable.java index a520b28f97..b5aa9ff667 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/BackDrawable.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/BackDrawable.java @@ -16,7 +16,10 @@ import android.graphics.drawable.Drawable; import android.view.animation.DecelerateInterpolator; +import androidx.core.graphics.ColorUtils; + import org.telegram.messenger.AndroidUtilities; +import org.telegram.messenger.Utilities; public class BackDrawable extends Drawable { @@ -111,11 +114,7 @@ public void draw(Canvas canvas) { invalidateSelf(); } - int rD = rotated ? (int) ((Color.red(rotatedColor) - Color.red(color)) * currentRotation) : 0; - int rG = rotated ? (int) ((Color.green(rotatedColor) - Color.green(color)) * currentRotation) : 0; - int rB = rotated ? (int) ((Color.blue(rotatedColor) - Color.blue(color)) * currentRotation) : 0; - int c = Color.rgb(Color.red(color) + rD, Color.green(color) + rG, Color.blue(color) + rB); - paint.setColor(c); + paint.setColor(ColorUtils.blendARGB(color, rotatedColor, currentRotation)); canvas.save(); canvas.translate(getIntrinsicWidth() / 2, getIntrinsicHeight() / 2); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/OKLCH.java b/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/OKLCH.java new file mode 100644 index 0000000000..4766642bc1 --- /dev/null +++ b/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/OKLCH.java @@ -0,0 +1,154 @@ +package org.telegram.ui.ActionBar; + +import android.graphics.Color; + +import androidx.core.graphics.ColorUtils; + +import org.telegram.messenger.Utilities; + +// https://gist.github.com/dkaraush/65d19d61396f5f3cd8ba7d1b4b3c9432 +public class OKLCH { + + public static final double[] XYZtoLMS_M = new double[] { + 0.8190224379967030, 0.3619062600528904, -0.1288737815209879, + 0.0329836539323885, 0.9292868615863434, 0.0361446663506424, + 0.0481771893596242, 0.2642395317527308, 0.6335478284694309 + }; + public static final double[] LMStoXYZ_M = new double[] { + 1.2268798758459243, -0.5578149944602171, 0.2813910456659647, + -0.0405757452148008, 1.1122868032803170, -0.0717110580655164, + -0.0763729366746601, -0.4214933324022432, 1.5869240198367816 + }; + public static final double[] LMStoLab_M = new double[] { + 0.2104542683093140, 0.7936177747023054, -0.0040720430116193, + 1.9779985324311684, -2.4285922420485799, 0.4505937096174110, + 0.0259040424655478, 0.7827717124575296, -0.8086757549230774 + }; + public static final double[] LabtoLMS_M = new double[] { + 1., 0.3963377773761749, 0.2158037573099136, + 1., -0.1055613458156586, -0.0638541728258133, + 1., -0.0894841775298119, -1.2914855480194092, + }; + public static final double[] toXYZ_M = new double[] { + 0.41239079926595934, 0.357584339383878, 0.1804807884018343, + 0.21263900587151027, 0.715168678767756, 0.07219231536073371, + 0.01933081871559182, 0.11919477979462598, 0.9505321522496607 + }; + public static final double[] fromXYZ_M = new double[] { + 3.2409699419045226, -1.537383177570094, -0.4986107602930034, + -0.9692436362808796, 1.8759675015077202, 0.04155505740717559, + 0.05563007969699366, -0.20397695888897652, 1.0569715142428786 + }; + + public static double[] oklch2oklab(double[] lch) { + final double L = lch[0]; + final double C = lch[1]; + final double H = lch[2]; + return new double[] { + L, + Double.isNaN(H) ? 0 : C * Math.cos(H * Math.PI / 180), + Double.isNaN(H) ? 0 : C * Math.sin(H * Math.PI / 180) + }; + } + public static double[] oklab2oklch(double[] lab) { + final double L = lab[0]; + final double A = lab[1]; + final double B = lab[2]; + return new double[] { + L, + Math.sqrt(Math.pow(A, 2) + Math.pow(B, 2)), + Math.abs(A) < 0.0002 && Math.abs(B) < 0.0002 ? Double.NaN : (((Math.atan2(B, A) * 180) / Math.PI % 360) + 360) % 360 + }; + } + + public static double[] rgb2srgbLinear(double[] rgb) { + double[] rgbLinear = new double[3]; + for (int i = 0; i < rgb.length; ++i) { + rgbLinear[i] = Math.abs(rgb[i]) <= 0.04045 ? + rgb[i] / 12.92 : + (rgb[i] < 0 ? -1 : 1) * (Math.pow((Math.abs(rgb[i]) + 0.055) / 1.055, 2.4)); + } + return rgbLinear; + } + public static double[] srgbLinear2rgb(double[] rgbLinear) { + double[] rgb = new double[3]; + for (int i = 0; i < rgbLinear.length; ++i) { + rgb[i] = Math.abs(rgbLinear[i]) > 0.0031308 ? + (rgbLinear[i] < 0 ? -1 : 1) * (1.055 * Math.pow(Math.abs(rgbLinear[i]), (1 / 2.4)) - 0.055) : + 12.92 * rgbLinear[i]; + } + return rgb; + } + + public static double[] oklab2xyz(double[] lab) { + final double[] LMS = multiply(LabtoLMS_M, lab); + for (int i = 0; i < LMS.length; ++i) { + LMS[i] = Math.pow(LMS[i], 3.0); + } + return multiply(LMStoXYZ_M, LMS); + } + public static double[] xyz2oklab(double[] xyz) { + final double[] LMSg = multiply(XYZtoLMS_M, xyz); + for (int i = 0; i < LMSg.length; ++i) { + LMSg[i] = Math.cbrt(LMSg[i]); + } + return multiply(LMStoLab_M, LMSg); + } + + public static double[] xyz2rgbLinear(double[] xyz) { + return multiply(fromXYZ_M, xyz); + } + public static double[] rgbLinear2xyz(double[] rgb) { + return multiply(toXYZ_M, rgb); + } + + public static double[] oklch2rgb(double[] lch) { + return srgbLinear2rgb(xyz2rgbLinear(oklab2xyz(oklch2oklab(lch)))); + } + + public static double[] rgb2oklch(double[] rgb) { + return oklab2oklch(xyz2oklab(rgbLinear2xyz(rgb2srgbLinear(rgb)))); + } + + public static double[] rgb(int color) { + return new double[] { + Color.red(color) / 255.0, + Color.green(color) / 255.0, + Color.blue(color) / 255.0 + }; + } + public static int rgb(double[] color) { + return Color.rgb( + (int) Math.round(Utilities.clamp(color[0], 1.0, 0.0) * 255.0), + (int) Math.round(Utilities.clamp(color[1], 1.0, 0.0) * 255.0), + (int) Math.round(Utilities.clamp(color[2], 1.0, 0.0) * 255.0) + ); + } + + // takes hue from `hueColor` color and applies to `baseColor` + public static int adapt(int baseColor, int hueColor) { + double[] hueoklch = rgb2oklch(rgb(hueColor)); + double[] oklch = rgb2oklch(rgb(baseColor)); + oklch[2] = hueoklch[2]; + if (Double.isNaN(hueoklch[2])) { + oklch[1] = hueoklch[1]; + } + return ColorUtils.setAlphaComponent(rgb(oklch2rgb(oklch)), Color.alpha(baseColor)); + } + + public static int adapt(int color, double c, double l) { + double[] oklch = rgb2oklch(rgb(color)); + oklch[0] = Utilities.clamp(oklch[0] + l, 1.0, 0.0); + oklch[1] = Utilities.clamp(oklch[1] + c, 1.0, 0.0); + return ColorUtils.setAlphaComponent(rgb(oklch2rgb(oklch)), Color.alpha(color)); + } + + private static double[] multiply(double[] mat3, double[] vec3) { + return new double[] { + mat3[0] * vec3[0] + mat3[1] * vec3[1] + mat3[2] * vec3[2], + mat3[3] * vec3[0] + mat3[4] * vec3[1] + mat3[5] * vec3[2], + mat3[6] * vec3[0] + mat3[7] * vec3[1] + mat3[8] * vec3[2] + }; + } + +} 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 920ecdcbbd..ca51aba3c6 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/Theme.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/Theme.java @@ -3659,6 +3659,7 @@ public void run() { public static final int key_chat_inBubbleShadow = colorsCount++; public static final int key_actionBarActionModeReaction = colorsCount++; + public static final int key_actionBarActionModeReactionText = colorsCount++; public static final int key_actionBarActionModeReactionDot = colorsCount++; //my messages bubbles @@ -3735,6 +3736,7 @@ public void run() { public static final int key_chat_outLocationIcon = colorsCount++; public static final int key_chat_outContactBackground = colorsCount++; public static final int key_chat_outContactIcon = colorsCount++; + public static final int key_chat_outReactionButtonBackground = colorsCount++; public static final int myMessagesEndIndex = colorsCount; public static final int key_chat_outTextSelectionHighlight = colorsCount++; @@ -4117,7 +4119,6 @@ public void run() { public static final int key_color_cyan = colorsCount++; public static final int[] keys_colors = {key_color_lightblue, key_color_blue, key_color_green, key_color_lightgreen, key_color_red, key_color_orange, key_color_yellow, key_color_purple, key_color_cyan}; - public static final int key_chat_outReactionButtonBackground = colorsCount++; public static final int key_chat_inReactionButtonBackground = colorsCount++; public static final int key_chat_outReactionButtonText = colorsCount++; public static final int key_chat_inReactionButtonText = colorsCount++; @@ -4411,6 +4412,7 @@ public void run() { fallbackKeys.put(key_statisticChartLine_cyan, key_color_cyan); fallbackKeys.put(key_actionBarActionModeReaction, key_windowBackgroundGray); + fallbackKeys.put(key_actionBarActionModeReactionText, key_chat_inReactionButtonText); for (int i = 0; i < keys_avatar_background.length; i++) { themeAccentExclusionKeys.add(keys_avatar_background[i]); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/ThemeColors.java b/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/ThemeColors.java index b65adca334..236e3e6988 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/ThemeColors.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/ThemeColors.java @@ -142,8 +142,8 @@ public static int[] createDefaultColors() { defaultColors[key_avatar_text] = 0xffffffff; - defaultColors[key_avatar_backgroundSaved] = 0xff69BFFA; - defaultColors[key_avatar_background2Saved] = 0xff3D9DE0; + defaultColors[key_avatar_backgroundSaved] = 0xff69BDF9; + defaultColors[key_avatar_background2Saved] = 0xff409FE1; defaultColors[key_avatar_backgroundArchived] = 0xffB8C2CC; defaultColors[key_avatar_backgroundArchivedHidden] = 0xff66bffa; defaultColors[key_avatar_backgroundRed] = 0xffFF845E; @@ -193,6 +193,7 @@ public static int[] createDefaultColors() { defaultColors[key_actionBarDefaultSubmenuSeparator] = 0xfff5f5f5; defaultColors[key_actionBarActionModeDefaultSelector] = 0xffe2e2e2; defaultColors[key_actionBarActionModeReaction] = 0xfff0f0f0; + defaultColors[key_actionBarActionModeReactionText] = 0xff82868a; defaultColors[key_actionBarActionModeReactionDot] = 0xffc0c0c0; defaultColors[key_actionBarTabActiveText] = 0xffffffff; defaultColors[key_actionBarTabUnactiveText] = 0xffd5e8f7; @@ -965,6 +966,7 @@ public static SparseArray createColorKeysMap() { colorKeysMap.put(key_actionBarActionModeDefaultIcon, "actionBarActionModeDefaultIcon"); colorKeysMap.put(key_actionBarActionModeDefaultSelector, "actionBarActionModeDefaultSelector"); colorKeysMap.put(key_actionBarActionModeReaction, "actionBarActionModeReaction"); + colorKeysMap.put(key_actionBarActionModeReactionText, "actionBarActionModeReactionText"); colorKeysMap.put(key_actionBarActionModeReactionDot, "actionBarActionModeReactionDot"); colorKeysMap.put(key_actionBarDefaultTitle, "actionBarDefaultTitle"); colorKeysMap.put(key_actionBarDefaultSubtitle, "actionBarDefaultSubtitle"); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Adapters/DialogsSearchAdapter.java b/TMessagesProj/src/main/java/org/telegram/ui/Adapters/DialogsSearchAdapter.java index e60b7b2ab5..3592beff3b 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Adapters/DialogsSearchAdapter.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Adapters/DialogsSearchAdapter.java @@ -473,7 +473,7 @@ private void searchMessagesInternal(final String query, int searchId) { ConnectionsManager.getInstance(currentAccount).cancelRequest(reqId, true); reqId = 0; } - if (TextUtils.isEmpty(query)) { + if (TextUtils.isEmpty(query) || delegate.getSearchForumDialogId() != 0) { filteredRecentQuery = null; searchResultMessages.clear(); searchForumResultMessages.clear(); @@ -1109,7 +1109,7 @@ public void searchDialogs(String text, int folderId) { if (searchId != lastSearchId) { return; } - if (needMessagesSearch != 2 && dialogsType != DialogsActivity.DIALOGS_TYPE_GROUPS_ONLY && dialogsType != DialogsActivity.DIALOGS_TYPE_CHANNELS_ONLY) { + if (needMessagesSearch != 2 && dialogsType != DialogsActivity.DIALOGS_TYPE_GROUPS_ONLY && dialogsType != DialogsActivity.DIALOGS_TYPE_CHANNELS_ONLY && delegate.getSearchForumDialogId() == 0) { searchAdapterHelper.queryServerSearch( query, true, diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Adapters/MessagesSearchAdapter.java b/TMessagesProj/src/main/java/org/telegram/ui/Adapters/MessagesSearchAdapter.java index a54538aaa8..51f08c5cea 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Adapters/MessagesSearchAdapter.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Adapters/MessagesSearchAdapter.java @@ -23,11 +23,14 @@ import org.telegram.ui.Components.RecyclerListView; import java.util.ArrayList; +import java.util.HashSet; public class MessagesSearchAdapter extends RecyclerListView.SelectionAdapter { private Context mContext; + private HashSet messageIds = new HashSet<>(); private ArrayList searchResultMessages = new ArrayList<>(); + public int loadedCount; private int currentAccount = UserConfig.selectedAccount; private final Theme.ResourcesProvider resourcesProvider; @@ -39,7 +42,17 @@ public MessagesSearchAdapter(Context context, Theme.ResourcesProvider resourcesP @Override public void notifyDataSetChanged() { - searchResultMessages = MediaDataController.getInstance(currentAccount).getFoundMessageObjects(); + searchResultMessages.clear(); + messageIds.clear(); + ArrayList searchResults = MediaDataController.getInstance(currentAccount).getFoundMessageObjects(); + for (int i = 0; i < searchResults.size(); ++i) { + MessageObject m = searchResults.get(i); + if ((!m.hasValidGroupId() || m.isPrimaryGroupMessage) && !messageIds.contains(m.getId())) { + searchResultMessages.add(m); + messageIds.add(m.getId()); + } + } + loadedCount = searchResultMessages.size(); super.notifyDataSetChanged(); } @@ -85,8 +98,26 @@ public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) { if (holder.getItemViewType() == 0) { DialogCell cell = (DialogCell) holder.itemView; cell.useSeparator = true; + cell.isSavedDialog = true; MessageObject messageObject = (MessageObject) getItem(position); - cell.setDialog(messageObject.getDialogId(), messageObject, messageObject.messageOwner.date, true, false); + int date; + boolean useMe = false; + long did; + if (messageObject.getDialogId() == UserConfig.getInstance(currentAccount).getClientUserId()) { + did = messageObject.getSavedDialogId(); + if (messageObject.messageOwner.fwd_from != null && (messageObject.messageOwner.fwd_from.date != 0 || messageObject.messageOwner.fwd_from.saved_date != 0)) { + date = messageObject.messageOwner.fwd_from.date; + if (date == 0) { + date = messageObject.messageOwner.fwd_from.saved_date; + } + } else { + date = messageObject.messageOwner.date; + } + } else { + did = messageObject.getDialogId(); + date = messageObject.messageOwner.date; + } + cell.setDialog(did, messageObject, date, useMe, false); } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ArticleViewer.java b/TMessagesProj/src/main/java/org/telegram/ui/ArticleViewer.java index 9a70bc5c93..b00b458dd0 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ArticleViewer.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ArticleViewer.java @@ -6542,7 +6542,7 @@ public void onRenderedFirstFrame() { } videoPlayer.seekTo(playFrom); - videoPlayer.preparePlayer(uri, true); + videoPlayer.preparePlayer(uri, true, 1f); videoPlayer.play(); } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/CalendarActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/CalendarActivity.java index 11a70bf273..d5d584a379 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/CalendarActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/CalendarActivity.java @@ -478,7 +478,13 @@ private void loadNext() { req.filter = new TLRPC.TL_inputMessagesFilterPhotoVideo(); } - req.peer = MessagesController.getInstance(currentAccount).getInputPeer(dialogId); + req.peer = getMessagesController().getInputPeer(dialogId); + if (topicId != 0) { + if (dialogId == getUserConfig().getClientUserId()) { + req.flags |= 4; + req.saved_peer_id = getMessagesController().getInputPeer(topicId); + } + } req.offset_id = lastId; Calendar calendar = Calendar.getInstance(); 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 61b0a6583a..a4e63300c3 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/AboutLinkCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/AboutLinkCell.java @@ -196,6 +196,14 @@ protected void onDraw(Canvas canvas) { } } + protected int processColor(int color) { + return color; + } + + public void updateColors() { + Theme.profile_aboutTextPaint.linkColor = processColor(Theme.getColor(Theme.key_chat_messageLinkIn, resourcesProvider)); + } + @Override public boolean onTouchEvent(MotionEvent event) { int x = (int) event.getX(); @@ -292,7 +300,7 @@ private void drawText(Canvas canvas) { canvas.translate(0, textY = AndroidUtilities.dp(8)); try { - Theme.profile_aboutTextPaint.linkColor = Theme.getColor(Theme.key_chat_messageLinkIn, resourcesProvider); + Theme.profile_aboutTextPaint.linkColor = processColor(Theme.getColor(Theme.key_chat_messageLinkIn, resourcesProvider)); if (firstThreeLinesLayout == null || !shouldExpand) { if (textLayout != null) { textLayout.draw(canvas); @@ -478,7 +486,8 @@ private LinkSpanDrawable checkTouchTextLayout(StaticLayout textLayout, int textX Spannable buffer = (Spannable) textLayout.getText(); ClickableSpan[] link = buffer.getSpans(off, off, ClickableSpan.class); if (link.length != 0 && !AndroidUtilities.isAccessibilityScreenReaderEnabled()) { - LinkSpanDrawable linkDrawable = new LinkSpanDrawable(link[0], parentFragment.getResourceProvider(), ex, ey); + LinkSpanDrawable linkDrawable = new LinkSpanDrawable(link[0], resourcesProvider, ex, ey); + linkDrawable.setColor(processColor(Theme.getColor(Theme.key_chat_linkSelectBackground, resourcesProvider))); int start = buffer.getSpanStart(link[0]); int end = buffer.getSpanEnd(link[0]); LinkPath path = linkDrawable.obtainNewPath(); @@ -507,11 +516,12 @@ public void init() { links.removeLoading(currentLoading, true); } currentLoading = thisLoading = LinkSpanDrawable.LinkCollector.makeLoading(layout, pressedLink, yOffset); + final int color = processColor(Theme.getColor(Theme.key_chat_linkSelectBackground, resourcesProvider)); thisLoading.setColors( - Theme.multAlpha(Theme.getColor(Theme.key_chat_linkSelectBackground, resourcesProvider), .8f), - Theme.multAlpha(Theme.getColor(Theme.key_chat_linkSelectBackground, resourcesProvider), 1.3f), - Theme.multAlpha(Theme.getColor(Theme.key_chat_linkSelectBackground, resourcesProvider), 1f), - Theme.multAlpha(Theme.getColor(Theme.key_chat_linkSelectBackground, resourcesProvider), 4f) + Theme.multAlpha(color, .8f), + Theme.multAlpha(color, 1.3f), + Theme.multAlpha(color, 1f), + Theme.multAlpha(color, 4f) ); thisLoading.strokePaint.setStrokeWidth(AndroidUtilities.dpf2(1.25f)); links.addLoading(thisLoading); 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 cff35a7db0..dd7952463a 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/ChatMessageCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/ChatMessageCell.java @@ -62,6 +62,7 @@ import android.text.style.ClickableSpan; import android.text.style.LeadingMarginSpan; import android.text.style.URLSpan; +import android.util.Log; import android.util.Property; import android.util.SparseArray; import android.util.StateSet; @@ -392,11 +393,11 @@ private void updateSpoilersVisiblePart(int top, int bottom) { } } - public void setScrimReaction(String scrimViewReaction) { + public void setScrimReaction(Integer scrimViewReaction) { reactionsLayoutInBubble.setScrimReaction(scrimViewReaction); } - public void drawScrimReaction(Canvas canvas, String scrimViewReaction) { + public void drawScrimReaction(Canvas canvas, Integer scrimViewReaction) { if ((currentPosition == null || ((currentPosition.flags & MessageObject.POSITION_FLAG_BOTTOM) != 0 && (currentPosition.flags & MessageObject.POSITION_FLAG_LEFT) != 0)) && !reactionsLayoutInBubble.isSmall) { reactionsLayoutInBubble.draw(canvas, transitionParams.animateChangeProgress, scrimViewReaction); } @@ -666,6 +667,10 @@ default boolean shouldShowTopicButton() { default void didPressEmojiStatus() { } + + default boolean doNotShowLoadingReply(MessageObject msg) { + return msg != null && msg.getDialogId() == UserObject.REPLY_BOT; + } } private final static int DOCUMENT_ATTACH_TYPE_NONE = 0; @@ -767,7 +772,7 @@ public static class PollButton { private static class InstantViewButton { private int type; - private int buttonWidth; + private float buttonWidth; private float textX; private StaticLayout layout; private final RectF rect = new RectF(); @@ -2579,7 +2584,7 @@ private boolean checkPollButtonMotionEvent(MotionEvent event) { } private boolean checkInstantButtonMotionEvent(MotionEvent event) { - if (!currentMessageObject.isSponsored() && (!drawInstantView || currentMessageObject.type == MessageObject.TYPE_TEXT)) { + if (!currentMessageObject.isSponsored() && !currentMessageObject.isUnsupported() && (!drawInstantView || currentMessageObject.type == MessageObject.TYPE_TEXT)) { return false; } int x = (int) event.getX(); @@ -4916,7 +4921,11 @@ private void setMessageContent(MessageObject messageObject, MessageObject.Groupe boolean pollChanged = false; if (!messageIdChanged && currentMessageObject != null) { + int oldStableId = messageObject.stableId; messageObject.copyStableParams(currentMessageObject); + if (currentMessageObject.isSavedFiltered && messageObject.isSavedFiltered) { + messageObject.stableId = oldStableId; + } } accessibilityText = null; if (drawCommentButton || useTranscribeButton || drawSideButton == 3 && !((hasDiscussion && messageObject.isLinkedToChat(linkedChatId) || isRepliesChat) && (currentPosition == null || currentPosition.siblingHeights == null && (currentPosition.flags & MessageObject.POSITION_FLAG_BOTTOM) != 0 || currentPosition.siblingHeights != null && (currentPosition.flags & MessageObject.POSITION_FLAG_TOP) == 0))) { @@ -4978,7 +4987,7 @@ private void setMessageContent(MessageObject messageObject, MessageObject.Groupe if (!groupChanged && groupedMessages != null) { MessageObject.GroupedMessagePosition newPosition; if (groupedMessages.messages.size() > 1) { - newPosition = currentMessagesGroup.positions.get(currentMessageObject); + newPosition = currentMessagesGroup.getPosition(currentMessageObject); } else { newPosition = null; } @@ -5007,7 +5016,7 @@ private void setMessageContent(MessageObject messageObject, MessageObject.Groupe } widthBeforeNewTimeLine = -1; if (currentMessagesGroup != null && (currentMessagesGroup.posArray.size() > 1)) { - currentPosition = currentMessagesGroup.positions.get(currentMessageObject); + currentPosition = currentMessagesGroup.getPosition(currentMessageObject); if (currentPosition == null) { currentMessagesGroup = null; } @@ -5222,15 +5231,20 @@ private void setMessageContent(MessageObject messageObject, MessageObject.Groupe if (messageIdChanged || messageObject.reactionsChanged || wasPlayingRound != isPlayingRound) { messageObject.reactionsChanged = false; + boolean isTag = messageObject.messageOwner != null && messageObject.messageOwner.reactions != null && messageObject.messageOwner.reactions.reactions_as_tags; if (messageObject.shouldDrawReactions() && !messageObject.isExpiredStory() && (currentPosition == null || ((currentPosition.flags & MessageObject.POSITION_FLAG_BOTTOM) != 0))) { boolean isSmall = !messageObject.shouldDrawReactionsInLayout(); if (currentPosition != null) { - reactionsLayoutInBubble.setMessage(groupedMessages.findPrimaryMessageObject(), !messageObject.shouldDrawReactionsInLayout(), resourcesProvider); + MessageObject primaryMessage = groupedMessages.findPrimaryMessageObject(); + if (!isTag) { + isTag = primaryMessage.messageOwner.reactions != null && primaryMessage.messageOwner.reactions.reactions_as_tags; + } + reactionsLayoutInBubble.setMessage(groupedMessages.findPrimaryMessageObject(), !messageObject.shouldDrawReactionsInLayout(), isTag, resourcesProvider); } else { - reactionsLayoutInBubble.setMessage(messageObject, isSmall, resourcesProvider); + reactionsLayoutInBubble.setMessage(messageObject, isSmall, isTag, resourcesProvider); } } else { - reactionsLayoutInBubble.setMessage(null, false, resourcesProvider); + reactionsLayoutInBubble.setMessage(null, false, false, resourcesProvider); } } @@ -5440,7 +5454,10 @@ private void setMessageContent(MessageObject messageObject, MessageObject.Groupe } if (!drawInstantView) { - if (messageObject.isSponsored()) { + if (messageObject.isUnsupported()) { + drawInstantView = true; + drawInstantViewType = 21; + } else if (messageObject.isSponsored()) { drawInstantView = true; hasLinkPreview = true; instantViewButtonText = messageObject.sponsoredButtonText; @@ -5717,7 +5734,7 @@ private void setMessageContent(MessageObject messageObject, MessageObject.Groupe linkPreviewMaxWidth = getParentWidth() - AndroidUtilities.dp(80 + (drawAvatar ? 52 : 0)); } if (drawSideButton != 0) { - linkPreviewMaxWidth -= AndroidUtilities.dp(20); + linkPreviewMaxWidth -= AndroidUtilities.dp(currentMessageObject.isSaved && currentMessageObject.isOutOwner() ? 25 : 20); } int site_name_additionalWidth = 0; CharSequence site_name; @@ -6683,6 +6700,10 @@ private void setMessageContent(MessageObject messageObject, MessageObject.Groupe blurredPhotoImage.getBitmap().recycle(); blurredPhotoImage.setImageBitmap((Bitmap) null); } + + if (messageObject.isUnsupported()) { + createInstantViewButton(); + } } } else if (messageObject.type == MessageObject.TYPE_PHONE_CALL) { createSelectorDrawable(0); @@ -7352,30 +7373,20 @@ private void setMessageContent(MessageObject messageObject, MessageObject.Groupe } if (!reactionsLayoutInBubble.isSmall && !reactionsLayoutInBubble.isEmpty) { if (!drawPhotoImage) { - reactionsLayoutInBubble.positionOffsetY += AndroidUtilities.dp(2); + reactionsLayoutInBubble.positionOffsetY += dp(2); } - if (captionLayout != null && currentPosition != null && currentMessagesGroup != null && currentMessagesGroup.isDocuments) { - reactionsLayoutInBubble.positionOffsetY += AndroidUtilities.dp(10); - } else if (!drawPhotoImage && !TextUtils.isEmpty(messageObject.caption) && ((docTitleLayout != null && docTitleLayout.getLineCount() > 1) || currentMessageObject.hasValidReplyMessageObject()) && !currentMessageObject.isForwarded()) { - reactionsLayoutInBubble.positionOffsetY += AndroidUtilities.dp(10); - } else if (!drawPhotoImage && !TextUtils.isEmpty(messageObject.caption) && !currentMessageObject.isOutOwner()) { - reactionsLayoutInBubble.positionOffsetY += AndroidUtilities.dp(10); - } - reactionsLayoutInBubble.totalHeight = reactionsLayoutInBubble.height + AndroidUtilities.dp(8); + reactionsLayoutInBubble.totalHeight = reactionsLayoutInBubble.height + dp(!drawPhotoImage || captionLayout == null ? 8 : 0); measureTime(messageObject); if (drawPhotoImage && captionLayout == null) { - reactionsLayoutInBubble.totalHeight += AndroidUtilities.dp(8); - } - if (!drawPhotoImage && captionLayout != null && currentMessageObject != null && currentMessageObject.isOutOwner() && currentMessageObject.isDocument() && currentMessagesGroup == null && !currentMessageObject.isForwarded() && !currentMessageObject.isReply()) { - reactionsLayoutInBubble.positionOffsetY += AndroidUtilities.dp(10); + reactionsLayoutInBubble.totalHeight += dp(8); } - int timeLeft = backgroundWidth - reactionsLayoutInBubble.lastLineX - AndroidUtilities.dp(31); + int timeLeft = backgroundWidth - reactionsLayoutInBubble.lastLineX - dp(42); if (timeLeft < timeWidth) { - reactionsLayoutInBubble.totalHeight += AndroidUtilities.dp(12); - reactionsLayoutInBubble.positionOffsetY -= AndroidUtilities.dp(12); + reactionsLayoutInBubble.totalHeight += dp(captionLayout == null ? 15 : 12); + reactionsLayoutInBubble.positionOffsetY -= dp(15); } additionHeight += reactionsLayoutInBubble.totalHeight; } @@ -8479,7 +8490,7 @@ private void setMessageContent(MessageObject messageObject, MessageObject.Groupe invalidate(); } - if ((currentPosition == null || currentMessageObject.isMusic() || currentMessageObject.isDocument()) && !messageObject.isAnyKindOfSticker() && addedCaptionHeight == 0 && !messageObject.isExpiredStory()) { + if ((currentPosition == null || currentMessageObject.isMusic() || currentMessageObject.isDocument()) && !messageObject.isAnyKindOfSticker() && addedCaptionHeight == 0 && !messageObject.isExpiredStory() && !messageObject.isUnsupported()) { int addCaptionLayoutWidth = 0; if (!messageObject.isRestrictedMessage && captionLayout == null && (messageObject.caption != null || messageObject.isVoiceTranscriptionOpen())) { currentCaption = messageObject.isVoiceTranscriptionOpen() ? messageObject.getVoiceTranscription() : messageObject.caption; @@ -9444,6 +9455,7 @@ private void updateWaveform() { } useTranscribeButton = ( currentMessageObject != null && + !currentMessageObject.isRepostPreview && (!currentMessageObject.isOutOwner() || currentMessageObject.isSent()) && ( UserConfig.getInstance(currentAccount).isPremium() @@ -9693,6 +9705,9 @@ private void calcBackgroundWidth(int maxWidth, int timeMore, int maxChildWidth) } int newLineForTimeDp = 14; + if (currentMessageObject.isUnsupported()) { + newLineForTime = true; + } if ( currentMessageObject.hasCodeAtBottom && (reactionsLayoutInBubble.isEmpty || reactionsLayoutInBubble.isSmall) || currentMessageObject.hasQuoteAtBottom && (reactionsLayoutInBubble.isEmpty || reactionsLayoutInBubble.isSmall) @@ -9985,7 +10000,7 @@ public boolean setHighlightedSpan(CharacterStyle span) { @Override protected boolean verifyDrawable(Drawable who) { - return super.verifyDrawable(who) || who == selectorDrawable[0] || who == selectorDrawable[1] || who == linkPreviewSelector || who == nameLayoutSelector || who == replySelector; + return super.verifyDrawable(who) || who == selectorDrawable[0] || who == selectorDrawable[1] || who == linkPreviewSelector || who == nameLayoutSelector || who == replySelector || reactionsLayoutInBubble != null && reactionsLayoutInBubble.verifyDrawable(who); } @Override @@ -10068,7 +10083,9 @@ public void createSelectorDrawable(int num) { return; } int color; - if (psaHintPressed) { + if (currentMessageObject.isUnsupported()) { + color = getThemedColor(currentMessageObject.isOutOwner() ? Theme.key_chat_outPreviewInstantText : Theme.key_chat_inPreviewInstantText); + } else if (psaHintPressed) { color = getThemedColor(currentMessageObject.isOutOwner() ? Theme.key_chat_outViews : Theme.key_chat_inViews); } else if (linkLine != null) { color = linkLine.getColor(); @@ -10215,6 +10232,8 @@ private void createInstantViewButton() { str = LocaleController.getString("BoostingHowItWork", R.string.BoostingHowItWork); } else if (drawInstantViewType == 20) { str = LocaleController.getString(R.string.OpenGift); + } else if (drawInstantViewType == 21) { + str = LocaleController.getString(R.string.AppUpdate); } else { str = LocaleController.getString(R.string.InstantView); } @@ -10274,7 +10293,7 @@ private void createContactButtons() { if (needRecreate) { drawnContactButtonsFlag = 0; int mWidth = (backgroundWidth - AndroidUtilities.dp(10 + 24 + 10 + 31)) / buttonsCount; - int parentWidth = (backgroundWidth - AndroidUtilities.dp(37)) / buttonsCount; + float parentWidth = (backgroundWidth - AndroidUtilities.dpf2(37)) / buttonsCount; if (contactButtons == null) { contactButtons = new ArrayList<>(buttonsCount); @@ -10304,7 +10323,7 @@ private void createContactButtons() { } } - private InstantViewButton createInstantViewButton(int type, String str, int availableWidth, int parentWidth) { + private InstantViewButton createInstantViewButton(int type, String str, int availableWidth, float parentWidth) { InstantViewButton instantViewButton = new InstantViewButton(); instantViewButton.type = type; instantViewButton.layout = new StaticLayout(TextUtils.ellipsize(str, Theme.chat_instantViewPaint, availableWidth, TextUtils.TruncateAt.END), Theme.chat_instantViewPaint, availableWidth + AndroidUtilities.dp(2), Layout.Alignment.ALIGN_NORMAL, 1.0f, 0.0f, false); @@ -11744,7 +11763,7 @@ private void updateReactionLayoutPosition() { if (hasNewLineForTime && !(drawForwardedName && hasLinkPreview && documentAttachType == DOCUMENT_ATTACH_TYPE_AUDIO)) { reactionsLayoutInBubble.y -= AndroidUtilities.dp(16); } - if (captionLayout != null && ((currentMessageObject.type != MessageObject.TYPE_VOICE && !(currentMessageObject.isOut() && drawForwardedName && !drawPhotoImage) && !(currentMessageObject.type == MessageObject.TYPE_FILE && drawPhotoImage)) || (currentPosition != null && currentMessagesGroup != null))) { + if (currentMessageObject.type != MessageObject.TYPE_FILE && (captionLayout != null && ((currentMessageObject.type != MessageObject.TYPE_VOICE && !(currentMessageObject.isOut() && drawForwardedName && !drawPhotoImage)) || (currentPosition != null && currentMessagesGroup != null)))) { reactionsLayoutInBubble.y -= AndroidUtilities.dp(14); } reactionsLayoutInBubble.y += reactionsLayoutInBubble.positionOffsetY; @@ -11871,7 +11890,7 @@ public void drawVoiceOnce(Canvas canvas, float progress, Runnable drawRadialProg } public void drawLinkPreview(Canvas canvas, float alpha) { - if (!currentMessageObject.isSponsored() && !hasLinkPreview && !hasGamePreview && !hasInvoicePreview) { + if (!currentMessageObject.isSponsored() && !currentMessageObject.isUnsupported() && !hasLinkPreview && !hasGamePreview && !hasInvoicePreview) { return; } int restoreCount = canvas.getSaveCount(); @@ -11935,7 +11954,7 @@ public void drawLinkPreview(Canvas canvas, float alpha) { boolean restore = false; boolean drawInstantButtonInside = false; boolean loading = delegate != null && delegate.isProgressLoading(this, ChatActivity.PROGRESS_INSTANT); - if (!hasInvoicePreview && !currentMessageObject.isGiveawayOrGiveawayResults()) { + if (!hasInvoicePreview && !currentMessageObject.isGiveawayOrGiveawayResults() && !currentMessageObject.isUnsupported()) { drawInstantButtonInside = true; if (linkPreviewBounce == null) { @@ -12351,7 +12370,7 @@ public void drawLinkPreview(Canvas canvas, float alpha) { } } else { int color = getThemedColor(Theme.key_chat_inPreviewInstantText); - if (linkLine != null) { + if (linkLine != null && !currentMessageObject.isUnsupported()) { color = linkLine.getColor(); } if (this.instantDrawable == null) { @@ -12402,7 +12421,7 @@ public void drawLinkPreview(Canvas canvas, float alpha) { canvas.restore(); } } else { - int instantY = startY + linkPreviewHeight + AndroidUtilities.dp(10); + int instantY = startY + linkPreviewHeight + AndroidUtilities.dp(currentMessageObject.isUnsupported() ? -5 : 10); if (instantButtonLoading != null && !loading && !instantButtonLoading.isDisappeared() && !instantButtonLoading.isDisappearing()) { instantButtonLoading.disappear(); } @@ -12548,17 +12567,18 @@ private void drawContact(Canvas canvas) { canvas.drawRect(contactRect.left + AndroidUtilities.dp(3 + 7), instantY + AndroidUtilities.dp(2), contactRect.right - AndroidUtilities.dp(7), instantY + AndroidUtilities.dp(2) + Math.max(1, AndroidUtilities.dp(0.66f)), Theme.chat_instantViewPaint); Theme.chat_instantViewPaint.setAlpha(wasAlpha); instantY += AndroidUtilities.dp(2); - textX += AndroidUtilities.dp(3); + float instantButtonLeft = textX + AndroidUtilities.dp(3); boolean needCreateSelectorDrawable = contactButtons != null && contactButtons.size() > 1; int rippleColor = contactLine.getBackgroundColor(); for (int i = 0; i < contactButtons.size(); i++) { InstantViewButton instantViewButton = contactButtons.get(i); - instantViewButton.rect.set(textX, instantY, textX + instantViewButton.buttonWidth, instantY + AndroidUtilities.dp(36)); + float right = Math.min(instantButtonLeft + instantViewButton.buttonWidth, contactRect.right); + instantViewButton.rect.set(instantButtonLeft, instantY, right, instantY + AndroidUtilities.dp(36)); if (needCreateSelectorDrawable && instantViewButton.selectorDrawable == null) { instantViewButton.selectorDrawable = Theme.createRadSelectorDrawable(linkPreviewSelectorColor = rippleColor, 0, 0, i == (contactButtons.size() - 1) ? rad : 0, 0); } if (instantViewButton.selectorDrawable != null) { - instantViewButton.selectorDrawable.setBounds(textX, instantY, textX + instantViewButton.buttonWidth, instantY + AndroidUtilities.dp(36)); + instantViewButton.selectorDrawable.setBounds((int) instantButtonLeft, instantY, (int) right, instantY + AndroidUtilities.dp(36)); instantViewButton.selectorDrawable.draw(canvas); } float buttonScale = 1f; @@ -12575,14 +12595,14 @@ private void drawContact(Canvas canvas) { } if (instantViewButton.layout != null) { canvas.save(); - canvas.translate(textX + instantViewButton.textX, instantY + AndroidUtilities.dp(10.5f)); + canvas.translate(instantButtonLeft + instantViewButton.textX, instantY + AndroidUtilities.dp(10.5f)); instantViewButton.layout.draw(canvas); canvas.restore(); } if (needButtonScale) { canvas.restore(); } - textX += instantViewButton.buttonWidth; + instantButtonLeft += instantViewButton.buttonWidth; } } if (needContactViewScale) { @@ -12986,7 +13006,7 @@ public void drawMessageText(float textX, float textY, Canvas canvas, ArrayList 0 ? viaNameWidth - dp(4 + 28) : nameLayoutWidth) + dp(4)), (int) (nameY + nameLayout.getHeight() + dp(1.33f)) ); + nameLayoutSelector.setAlpha((int) (0xFF * nameAlpha)); nameLayoutSelector.draw(canvas); if (currentNameStatus != null) { @@ -17002,12 +17031,16 @@ public void drawNamesLayout(Canvas canvas, float alpha) { (int) (nx + (viaNameWidth > 0 ? viaNameWidth - dp(4 + 28) : nameLayoutWidth) + dp(4 + 12 + 4 + 4)), (int) (nameY + nameLayout.getHeight() + dp(1.33f + 2)) ); + nameStatusSelector.setAlpha((int) (0xFF * nameAlpha)); nameStatusSelector.draw(canvas); } } canvas.translate(nx, nameY); + oldAlpha = Theme.chat_namePaint.getAlpha(); + Theme.chat_namePaint.setAlpha((int) (oldAlpha * nameAlpha)); nameLayout.draw(canvas); + Theme.chat_namePaint.setAlpha(oldAlpha); canvas.restore(); float end; if (currentMessagesGroup != null && !currentMessagesGroup.isDocuments) { @@ -17553,7 +17586,7 @@ public void drawNamesLayout(Canvas canvas, float alpha) { canvas.restore(); } int spoilersColor; - if (currentMessageObject != null && currentMessageObject.isOut() && !ChatObject.isChannelAndNotMegaGroup(currentMessageObject.getChatId(), currentAccount)) { + if (currentMessageObject != null && currentMessageObject.isOutOwner() && !ChatObject.isChannelAndNotMegaGroup(currentMessageObject.getChatId(), currentAccount)) { spoilersColor = getThemedColor(Theme.key_chat_outTimeText); } else { spoilersColor = Theme.chat_replyTextPaint.getColor(); @@ -20499,7 +20532,7 @@ public int computeHeight(MessageObject object, MessageObject.GroupedMessages gro int h = 0; for (int i = 0; i < groupedMessages.messages.size(); i++) { MessageObject o = groupedMessages.messages.get(i); - MessageObject.GroupedMessagePosition position = groupedMessages.positions.get(o); + MessageObject.GroupedMessagePosition position = groupedMessages.getPosition(o); if (position != null && (position.flags & MessageObject.POSITION_FLAG_LEFT) != 0) { setMessageContent(o, groupedMessages, false, false); if (withCaption && !TextUtils.isEmpty(currentCaption)) { @@ -20971,7 +21004,7 @@ public void onClick(View view) { if (drawInstantView && !instantButtonRect.isEmpty()) { info.addChild(ChatMessageCell.this, INSTANT_VIEW); } - if (drawContact && !contactRect.isEmpty()) { + if (drawContact && contactRect != null && !contactRect.isEmpty()) { info.addChild(ChatMessageCell.this, CONTACT); if (contactButtons != null && contactButtons.size() > 1) { for (InstantViewButton instantViewButton : contactButtons) { @@ -21782,6 +21815,9 @@ public class TransitionParams { public boolean animateRecommendationsExpanded; public boolean animateFromRecommendationsExpanded; + public boolean lastDrawNameLayout; + public boolean animateDrawNameLayout; + public void recordDrawingState() { wasDraw = true; lastDrawingImageX = photoImage.getImageX(); @@ -21875,6 +21911,8 @@ public void recordDrawingState() { } else { lastDrawReplyY = 0; } + + lastDrawNameLayout = drawNameLayout; } public void recordDrawingStatePreview() { @@ -21922,6 +21960,11 @@ public boolean animateChange() { animatedEmojiStack = AnimatedEmojiSpan.update(AnimatedEmojiDrawable.CACHE_TYPE_MESSAGES, ChatMessageCell.this, animatedEmojiStack, currentMessageObject.textLayoutBlocks); } } + animateDrawNameLayout = false; + if (drawNameLayout != lastDrawNameLayout) { + animateDrawNameLayout = true; + changed = true; + } if (replyTextLayout != lastDrawnReplyTextLayout) { CharSequence newText = replyTextLayout != null ? replyTextLayout.getText() : null; CharSequence oldText = lastDrawnReplyTextLayout != null ? lastDrawnReplyTextLayout.getText() : null; @@ -22231,6 +22274,7 @@ public void resetAnimation() { animateRadius = false; animateChangeProgress = 1f; animateMessageText = false; + animateDrawNameLayout = false; animateOutTextBlocks = null; animateEditedLayout = null; animateTimeLayout = null; @@ -22389,4 +22433,12 @@ public boolean needDrawAvatar() { protected boolean drawPhotoImage(Canvas canvas) { return photoImage.draw(canvas); } + + public boolean areTags() { + MessageObject msg = getPrimaryMessageObject(); + if (msg == null) return false; + if (msg.messageOwner == null) return false; + if (msg.messageOwner.reactions == null) return false; + return msg.messageOwner.reactions.reactions_as_tags; + } } 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 6342047877..61522333ff 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/DialogCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/DialogCell.java @@ -176,6 +176,7 @@ public class DialogCell extends BaseCell implements StoriesListPlaceProvider.Ava private Paint timerPaint2; SharedResources sharedResources; public boolean isSavedDialog; + public boolean isSavedDialogCell; public final StoriesUtilities.AvatarStoryParams storyParams = new StoriesUtilities.AvatarStoryParams(false) { @Override @@ -336,7 +337,7 @@ public static class CustomDialog { private int currentDialogFolderId; private int currentDialogFolderDialogsCount; private int currentEditDate; - private boolean isDialogCell; + public boolean isDialogCell; private int lastMessageDate; private int unreadCount; private boolean markUnread; @@ -959,6 +960,11 @@ public void buildLayout() { } if (useForceThreeLines || SharedConfig.useThreeLinesLayout) { + Theme.dialogs_namePaint[0].setTextSize(AndroidUtilities.dp(17)); + Theme.dialogs_nameEncryptedPaint[0].setTextSize(AndroidUtilities.dp(17)); + Theme.dialogs_messagePaint[0].setTextSize(AndroidUtilities.dp(16)); + Theme.dialogs_messagePrintingPaint[0].setTextSize(AndroidUtilities.dp(16)); + Theme.dialogs_namePaint[1].setTextSize(AndroidUtilities.dp(16)); Theme.dialogs_nameEncryptedPaint[1].setTextSize(AndroidUtilities.dp(16)); Theme.dialogs_messagePaint[1].setTextSize(AndroidUtilities.dp(15)); @@ -1235,7 +1241,7 @@ public void buildLayout() { if (draftMessage != null && TextUtils.isEmpty(draftMessage.message)) { draftMessage = null; } - } else if (isDialogCell) { + } else if (isDialogCell || isSavedDialogCell) { draftMessage = MediaDataController.getInstance(currentAccount).getDraft(currentDialogId, 0); } else { draftMessage = null; @@ -1434,9 +1440,13 @@ public void buildLayout() { } else { needEmoji = true; updateMessageThumbs(); - if (chat != null && chat.id > 0 && (!ChatObject.isChannel(chat) || ChatObject.isMegagroup(chat)) && !ForumUtilities.isTopicCreateMessage(message)) { - messageNameString = getMessageNameString(); - if (chat.forum && !isTopic && !useFromUserAsAvatar) { + String triedMessageName = null; + if (!isSavedDialog && user != null && user.self && !message.isOutOwner()) { + triedMessageName = getMessageNameString(); + } + if (isSavedDialog && user != null && !user.self && message != null && message.isOutOwner() || triedMessageName != null || chat != null && chat.id > 0 && (!ChatObject.isChannel(chat) || ChatObject.isMegagroup(chat)) && !ForumUtilities.isTopicCreateMessage(message)) { + messageNameString = triedMessageName != null ? triedMessageName : getMessageNameString(); + if (chat != null && chat.forum && !isTopic && !useFromUserAsAvatar) { CharSequence topicName = MessagesController.getInstance(currentAccount).getTopicsController().getTopicIconName(chat, message, currentMessagePaint); if (!TextUtils.isEmpty(topicName)) { SpannableStringBuilder arrowSpan = new SpannableStringBuilder("-"); @@ -2221,7 +2231,7 @@ public void buildLayout() { if (messageString instanceof Spannable) { Spannable messageStringSpannable = (Spannable) messageString; for (Object span : messageStringSpannable.getSpans(0, messageStringSpannable.length(), Object.class)) { - if (span instanceof ClickableSpan || span instanceof CodeHighlighting.Span || span instanceof TypefaceSpan || span instanceof CodeHighlighting.ColorSpan || span instanceof QuoteSpan || span instanceof QuoteSpan.QuoteStyleSpan || (span instanceof StyleSpan && ((StyleSpan) span).getStyle() == android.graphics.Typeface.BOLD)) { + if (span instanceof ClickableSpan || span instanceof CodeHighlighting.Span || !isFolderCell() && span instanceof TypefaceSpan || span instanceof CodeHighlighting.ColorSpan || span instanceof QuoteSpan || span instanceof QuoteSpan.QuoteStyleSpan || (span instanceof StyleSpan && ((StyleSpan) span).getStyle() == android.graphics.Typeface.BOLD)) { messageStringSpannable.removeSpan(span); } } @@ -3069,7 +3079,7 @@ public void onAnimationEnd(Animator animation) { reactionsMentionsAnimator.start(); } - avatarImage.setRoundRadius(chat != null && chat.forum && currentDialogFolderId == 0 && !useFromUserAsAvatar ? AndroidUtilities.dp(16) : AndroidUtilities.dp(28)); + avatarImage.setRoundRadius(chat != null && chat.forum && currentDialogFolderId == 0 && !useFromUserAsAvatar || !isSavedDialog && user != null && user.self && MessagesController.getInstance(currentAccount).savedViewAsChats ? dp(16) : dp(28)); } if (!isTopic && (getMeasuredWidth() != 0 || getMeasuredHeight() != 0)) { rebuildLayout = true; @@ -4844,6 +4854,24 @@ public String getMessageNameString() { TLRPC.User fromUser = null; TLRPC.Chat fromChat = null; long fromId = message.getFromChatId(); + final long selfId = UserConfig.getInstance(currentAccount).getClientUserId(); + if (!isSavedDialog && currentDialogId == selfId) { + long savedDialogId = message.getSavedDialogId(); + if (savedDialogId == selfId) { + return null; + } else if (savedDialogId != UserObject.ANONYMOUS) { + if (message.messageOwner != null && message.messageOwner.fwd_from != null) { + long fwdId = DialogObject.getPeerDialogId(message.messageOwner.fwd_from.saved_from_id); + if (fwdId == 0) { + fwdId = DialogObject.getPeerDialogId(message.messageOwner.fwd_from.from_id); + } + if (fwdId > 0 && fwdId != savedDialogId) { + return null; + } + } + fromId = savedDialogId; + } + } if (isSavedDialog && message.messageOwner != null && message.messageOwner.fwd_from != null) { fromId = DialogObject.getPeerDialogId(message.messageOwner.fwd_from.saved_from_id); if (fromId == 0) { @@ -4856,7 +4884,14 @@ public String getMessageNameString() { fromChat = MessagesController.getInstance(currentAccount).getChat(-fromId); } - if (message.isOutOwner()) { + if (currentDialogId == selfId) { + if (fromUser != null) { + return UserObject.getFirstName(fromUser).replace("\n", ""); + } else if (fromChat != null) { + return fromChat.title.replace("\n", ""); + } + return null; + } else if (message.isOutOwner()) { return LocaleController.getString("FromYou", R.string.FromYou); } else if (!isSavedDialog && message != null && message.messageOwner != null && message.messageOwner.from_id instanceof TLRPC.TL_peerUser && (user = MessagesController.getInstance(currentAccount).getUser(message.messageOwner.from_id.user_id)) != null) { return UserObject.getFirstName(user).replace("\n", ""); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/ExpiredStoryView.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/ExpiredStoryView.java index c32605d25c..3e895fc021 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/ExpiredStoryView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/ExpiredStoryView.java @@ -14,6 +14,7 @@ import org.telegram.messenger.AndroidUtilities; import org.telegram.messenger.LocaleController; +import org.telegram.messenger.MessageObject; import org.telegram.messenger.MessagesController; import org.telegram.messenger.R; import org.telegram.tgnet.TLRPC; @@ -36,7 +37,17 @@ public class ExpiredStoryView { public void measure(ChatMessageCell parent) { CharSequence title = StoriesUtilities.createExpiredStoryString(); - TLRPC.TL_messageMediaStory mediaStory = (TLRPC.TL_messageMediaStory) parent.getMessageObject().messageOwner.media; + MessageObject messageObject = parent.getMessageObject(); + TLRPC.TL_messageMediaStory mediaStory; + if (messageObject != null && messageObject.messageOwner != null && messageObject.messageOwner.media instanceof TLRPC.TL_messageMediaStory) { + mediaStory = (TLRPC.TL_messageMediaStory) messageObject.messageOwner.media; + } else { + verticalPadding = AndroidUtilities.dp(4); + horizontalPadding = AndroidUtilities.dp(12); + height = 0; + width = 0; + return; + } TLRPC.User user = MessagesController.getInstance(parent.currentAccount).getUser(mediaStory.user_id); String fromName = user == null ? "DELETED" : user.first_name; int forwardedNameWidth; @@ -119,9 +130,13 @@ public void draw(Canvas canvas, ChatMessageCell parent) { canvas.save(); canvas.translate(textX, textY); - titleLayout.draw(canvas); - canvas.translate(0, titleLayout.getHeight() + AndroidUtilities.dp(2)); - subtitleLayout.draw(canvas); + if (titleLayout != null) { + titleLayout.draw(canvas); + canvas.translate(0, titleLayout.getHeight() + AndroidUtilities.dp(2)); + } + if (subtitleLayout != null) { + subtitleLayout.draw(canvas); + } canvas.restore(); } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/StickerSetCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/StickerSetCell.java index e3e6f26966..bfe767f826 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/StickerSetCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/StickerSetCell.java @@ -433,8 +433,13 @@ public void onAnimationStart(Animator animation) { } else { sideButtons.setVisibility(checked ? VISIBLE : INVISIBLE); if (!checked) { + sideButtons.setAlpha(0f); sideButtons.setScaleX(0.1f); sideButtons.setScaleY(0.1f); + } else { + sideButtons.setAlpha(1f); + sideButtons.setScaleX(1f); + sideButtons.setScaleY(1f); } } } else if (option == 3) { @@ -458,8 +463,13 @@ public void onAnimationStart(Animator animation) { } else { optionsButton.setVisibility(checked ? VISIBLE : INVISIBLE); if (!checked) { + optionsButton.setAlpha(0f); optionsButton.setScaleX(0.1f); optionsButton.setScaleY(0.1f); + } else { + optionsButton.setAlpha(1f); + optionsButton.setScaleX(1f); + optionsButton.setScaleY(1f); } } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/TextCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/TextCell.java index abc4dfb3aa..3968f76674 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/TextCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/TextCell.java @@ -268,7 +268,7 @@ public void updateColors() { int textKey = textView.getTag() instanceof Integer ? (int) textView.getTag() : Theme.key_windowBackgroundWhiteBlackText; textView.setTextColor(processColor(Theme.getColor(textKey, resourcesProvider))); if (imageView.getTag() instanceof Integer) { - imageView.setColorFilter(new PorterDuffColorFilter(processColor(Theme.getColor((int) imageView.getTag(), resourcesProvider)), PorterDuff.Mode.MULTIPLY)); + imageView.setColorFilter(new PorterDuffColorFilter(Theme.getColor((int) imageView.getTag(), resourcesProvider), PorterDuff.Mode.MULTIPLY)); } subtitleView.setTextColor(processColor(Theme.getColor(Theme.key_windowBackgroundWhiteGrayText, resourcesProvider))); valueTextView.setTextColor(processColor(Theme.getColor(Theme.key_windowBackgroundWhiteValueText, resourcesProvider))); @@ -279,7 +279,7 @@ public void setColors(int icon, int text) { textView.setTextColor(processColor(Theme.getColor(text, resourcesProvider))); textView.setTag(text); if (icon >= 0) { - imageView.setColorFilter(new PorterDuffColorFilter(processColor(Theme.getColor(icon, resourcesProvider)), PorterDuff.Mode.MULTIPLY)); + imageView.setColorFilter(new PorterDuffColorFilter(Theme.getColor(icon, resourcesProvider), PorterDuff.Mode.MULTIPLY)); imageView.setTag(icon); } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ChatActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/ChatActivity.java index 367011c15c..fc3ca6a63d 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ChatActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ChatActivity.java @@ -252,6 +252,7 @@ import java.util.Collections; import java.util.Comparator; import java.util.HashMap; +import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Locale; @@ -370,9 +371,10 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not private boolean chatActivityEnterViewAnimateBeforeSending; private ActionBarMenuItem.Item timeItem2; private ActionBarMenu.LazyItem attachItem; + private ActionBarMenuItem.Item savedChatsItem, savedChatsGap;; private ActionBarMenuItem headerItem; private ActionBarMenu.LazyItem editTextItem; - private ActionBarMenuItem searchItem; + protected ActionBarMenuItem searchItem; private ActionBarMenuItem.Item translateItem; private ActionBarMenuItem searchIconItem; private ActionBarMenuItem viewInChatItem; @@ -424,6 +426,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not private ActionBarMenuItem.Item muteItemGap; private ChatNotificationsPopupWrapper chatNotificationsPopupWrapper; private float pagedownButtonEnterProgress; + private float searchUpDownEnterProgress; private float mentionsButtonEnterProgress; private float reactionsMentionButtonEnterProgress; private FrameLayout pagedownButton; @@ -439,8 +442,16 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not private Bulletin messageSeenPrivacyBulletin; TextView webBotTitle; public SearchTagsList actionBarSearchTags; + private FrameLayout searchUpButton; + private ImageView searchUpButtonArrow; + private FrameLayout searchDownButton; + private ImageView searchDownButtonArrow; + private FrameLayout searchGoToBeginningButton; + private ImageView searchGoToBeginningButtonArrow; private HintView2 savedMessagesHint; + private HintView2 savedMessagesSearchHint; + private HintView2 savedMessagesTagHint; private int reactionsMentionCount; private FrameLayout reactionsMentiondownButton; @@ -484,7 +495,6 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not private HintView gifHintTextView; private HintView emojiHintTextView; private HintView mediaBanTooltip; - private HintView searchAsListHint; private HintView scheduledOrNoSoundHint; private boolean scheduledOrNoSoundHintShown; private HintView scheduledHint; @@ -528,13 +538,10 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not private AnimatorSet alertViewAnimator; private final int searchContainerHeight = 51; private BlurredFrameLayout searchContainer; - private View searchAsListTogglerView; private ImageView searchCalendarButton; private ImageView searchUserButton; - private ImageView searchUpButton; - private ImageView searchDownButton; - private ImageView searchGoToBeginningButton; - private SearchCounterView searchCountText; + private AnimatedTextView searchCountText; + private AnimatedTextView searchExpandList; private AnimatedTextView searchOtherButton; private ChatActionCell floatingDateView; private ChatActionCell infoTopView; @@ -550,7 +557,22 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not private boolean searchingForUser; private TLRPC.User searchingUserMessages; private TLRPC.Chat searchingChatMessages; - private ReactionsLayoutInBubble.VisibleReaction searchingReaction; + public ReactionsLayoutInBubble.VisibleReaction searchingReaction; + public ReactionsLayoutInBubble.VisibleReaction getFilterTag() { + return chatAdapter != null && chatAdapter.isFiltered ? searchingReaction : null; + } + public String getFilterQuery() { + return chatAdapter != null && chatAdapter.isFiltered ? searchingQuery : null; + } + public boolean isFiltered() { + return chatAdapter != null && chatAdapter.isFiltered; + } + public ArrayList getFilteredMessages() { + return chatAdapter != null ? chatAdapter.filteredMessages : null; + } + private boolean searchingFiltered; + private boolean searching; + private String searchingQuery; private UndoView undoView; private UndoView topUndoView; private Bulletin pinBulletin; @@ -562,6 +584,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not private MessageObject hintMessageObject; private int hintMessageType; + private MessageObject hint2MessageObject; private RecyclerListView messagesSearchListView; private MessagesSearchAdapter messagesSearchAdapter; @@ -633,6 +656,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not private boolean pinnedEndReached; private ValueAnimator pagedownButtonAnimation; + private ValueAnimator searchUpButtonAnimation; private ValueAnimator mentiondownButtonAnimation; private ValueAnimator reactionsMentionButtonAnimation; private AnimatorSet replyButtonAnimation; @@ -640,7 +664,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not private AnimatorSet forwardButtonAnimation; SparseIntArray dateObjectsStableIds = new SparseIntArray(); - private static int lastStableId = 10; + public static int lastStableId = 10; private boolean openSearchKeyboard; @@ -733,6 +757,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not private SparseArray repliesMessagesDict = new SparseArray<>(); private SparseArray> replyMessageOwners = new SparseArray<>(); private HashMap> messagesByDays = new HashMap<>(); + private SparseArray> messagesByDaysSorted = new SparseArray<>(); public ArrayList messages = new ArrayList<>(); private SparseArray waitingForReplies = new SparseArray<>(); private LongSparseArray> polls = new LongSparseArray<>(); @@ -871,7 +896,8 @@ public int getColor(int key) { private float scrimPaintAlpha = 0f; private View scrimView; private float scrimViewAlpha = 1f; - private String scrimViewReaction; + private Integer scrimViewReaction; + private boolean scrimViewReactionAnimated; private int popupAnimationIndex = -1; private AnimatorSet scrimAnimatorSet; public ActionBarPopupWindow scrimPopupWindow; @@ -903,6 +929,7 @@ public void run() { private int postponedScrollMinMessageId; private int postponedScrollToLastMessageQueryIndex; private int postponedScrollMessageId; + private boolean fakePostponedScroll; private boolean postponedScrollIsCanceled; private static ArrayList textSelectionHelpersCache; private ChatActivityTextSelectionHelper textSelectionHelper; @@ -1048,6 +1075,7 @@ public void run() { NotificationCenter.userInfoDidLoad, NotificationCenter.pinnedInfoDidLoad, NotificationCenter.didSetNewWallpapper, + NotificationCenter.savedMessagesDialogsUpdate, NotificationCenter.didApplyNewTheme }; @@ -1167,7 +1195,7 @@ public void showHeaderItem(boolean show) { } public long getTopicId() { - return isTopic ? threadMessageId : 0L; + return isTopic || chatMode == MODE_SAVED ? threadMessageId : 0L; } public long getSavedDialogId() { @@ -1363,8 +1391,7 @@ public void sendButtonPressed(int index, VideoEditedInfo videoEditedInfo, boolea private final static int save_to = 25; private final static int auto_delete_timer = 26; private final static int change_colors = 27; - private final static int to_the_beginning = 28; - private final static int to_the_message = 29; + private final static int tag_message = 28; private final static int bot_help = 30; private final static int bot_settings = 31; @@ -1402,11 +1429,13 @@ public void sendButtonPressed(int index, VideoEditedInfo videoEditedInfo, boolea private ActionBarMenuItem actionModeOtherItem; // NekoX private final static int id_chat_compose_panel = 1000; + private final static int to_the_beginning = 200; + private final static int to_the_message = 201; RecyclerListView.OnItemLongClickListenerExtended onItemLongClickListener = new RecyclerListView.OnItemLongClickListenerExtended() { @Override public boolean onItemClick(View view, int position, float x, float y) { - if (textSelectionHelper.isTryingSelect() || textSelectionHelper.isInSelectionMode() || inPreviewMode) { + if (textSelectionHelper.isTryingSelect() || textSelectionHelper.isInSelectionMode() || inPreviewMode || isInsideContainer) { return false; } if((scrimPopupWindow != null && NaConfig.INSTANCE.getDoubleTapAction().Int()==DoubleTap.DOUBLE_TAP_ACTION_SHOW_REACTIONS)) @@ -1440,7 +1469,7 @@ public RecyclerListView getChatListView() { } private void startMultiselect(int position) { - if (chatMode == MODE_SAVED) { + if (isInsideContainer) { return; } int indexOfMessage = position - chatAdapter.messagesStartRow; @@ -1692,7 +1721,7 @@ public void onDoubleTap(View view, int position, float x, float y) { if (!available) { return; } - selectReaction(primaryMessage, null, null, x, y, ReactionsLayoutInBubble.VisibleReaction.fromEmojicon(reactionString), true, false, false); + selectReaction(primaryMessage, null, null, x, y, ReactionsLayoutInBubble.VisibleReaction.fromEmojicon(reactionString), true, false, false, false); } else { TLRPC.TL_availableReaction reaction = getMediaDataController().getReactionsMap().get(reactionString); if (reaction == null || cell.getMessageObject().isSponsored()) { @@ -1705,7 +1734,7 @@ public void onDoubleTap(View view, int position, float x, float y) { if (!available) { return; } - selectReaction(primaryMessage, null, null, x, y, ReactionsLayoutInBubble.VisibleReaction.fromEmojicon(reaction), true, false, false); + selectReaction(primaryMessage, null, null, x, y, ReactionsLayoutInBubble.VisibleReaction.fromEmojicon(reaction), true, false, false, false); } } else if (NaConfig.INSTANCE.getDoubleTapAction().Int() == DoubleTap.DOUBLE_TAP_ACTION_SHOW_REACTIONS) { createMenu(view, true, false, x, y, true, true); @@ -1904,8 +1933,12 @@ public void onTextSelectionChanged(int start, int end) { if (chatMode == MODE_SAVED && getSavedDialogId() == getUserConfig().getClientUserId() || chatMode == 0 && (threadMessageId == 0 || isTopic) && !UserObject.isReplyUser(currentUser) && reportType < 0) { editTextItem.setVisibility(View.VISIBLE); checkEditTextItemMenu(); - headerItem.setVisibility(View.GONE); - attachItem.setVisibility(View.GONE); + if (headerItem != null) { + headerItem.setVisibility(View.GONE); + } + if (attachItem != null) { + attachItem.setVisibility(View.GONE); + } } else { ValueAnimator valueAnimator = ValueAnimator.ofFloat(AndroidUtilities.dp(48), 0); valueAnimator.setDuration(220); @@ -1939,11 +1972,19 @@ public void onAnimationEnd(Animator animation) { editTextItem.setVisibility(View.GONE); if (chatActivityEnterView.hasText() && TextUtils.isEmpty(chatActivityEnterView.getSlowModeTimer())) { - headerItem.setVisibility(View.GONE); - attachItem.setVisibility(View.VISIBLE); + if (headerItem != null) { + headerItem.setVisibility(View.GONE); + } + if (attachItem != null) { + attachItem.setVisibility(View.VISIBLE); + } } else { - headerItem.setVisibility(View.VISIBLE); - attachItem.setVisibility(View.GONE); + if (headerItem != null) { + headerItem.setVisibility(View.VISIBLE); + } + if (attachItem != null) { + attachItem.setVisibility(View.GONE); + } } } else { ValueAnimator valueAnimator = ValueAnimator.ofFloat(0, AndroidUtilities.dp(48)); @@ -2210,7 +2251,7 @@ public boolean hasScheduledMessages() { if (getMessagesController().isForum(getDialogId()) && !isTopic) { return false; } - return scheduledMessagesCount > 0 && chatMode == 0; + return scheduledMessagesCount > 0 && (chatMode == 0 || chatMode == MODE_SAVED && getSavedDialogId() == getUserConfig().getClientUserId()); } @Override @@ -2335,6 +2376,7 @@ public ReplyQuote getReplyQuote() { scheduledHintShown = true; }; + public Utilities.Callback0Return insideContainerResizableView; public boolean isInsideContainer; public boolean reversed; @@ -2577,6 +2619,7 @@ public boolean onFragmentCreate() { getNotificationCenter().addObserver(this, NotificationCenter.channelRightsUpdated); getNotificationCenter().addObserver(this, NotificationCenter.audioRecordTooShort); getNotificationCenter().addObserver(this, NotificationCenter.didUpdateReactions); + getNotificationCenter().addObserver(this, NotificationCenter.savedReactionTagsUpdate); getNotificationCenter().addObserver(this, NotificationCenter.didUpdateExtendedMedia); getNotificationCenter().addObserver(this, NotificationCenter.videoLoadingStateChanged); getNotificationCenter().addObserver(this, NotificationCenter.scheduledMessagesUpdated); @@ -2675,6 +2718,7 @@ public boolean onFragmentCreate() { endReached[0] = endReached[1] = true; forwardEndReached[0] = forwardEndReached[1] = true; firstLoading = false; + loading = false; checkDispatchHideSkeletons(false); } if (chatMode != MODE_PINNED && !forceHistoryEmpty) { @@ -2755,7 +2799,11 @@ public boolean onFragmentCreate() { if (isTopic) { getMessagesController().getTopicsController().getTopicRepliesCount(dialog_id, getTopicId()); } - getMessagesController().getSavedMessagesController().preloadDialogs(); + getMessagesController().getSavedMessagesController().preloadDialogs(false); + if (chatMode == MODE_SAVED) { + getMessagesController().getSavedMessagesController().checkSavedDialogCount(getTopicId()); + } + return true; } @@ -2782,9 +2830,9 @@ private void firstLoadMessages() { getMessagesController().loadMessages(dialog_id, mergeDialogId, loadInfo, initialMessagesSize, startLoadFromMessageId, 0, true, 0, classGuid, 2, 0, chatMode, threadMessageId, replyMaxReadId, lastLoadIndex++, isTopic); } } - if (chatMode == 0 && (!isThreadChat() || isTopic)) { + if ((chatMode == 0 || chatMode == MODE_SAVED && getSavedDialogId() == getUserConfig().getClientUserId()) && (!isThreadChat() || isTopic)) { waitingForLoad.add(lastLoadIndex); - getMessagesController().loadMessages(dialog_id, mergeDialogId, false, 1, 0, 0, true, 0, classGuid, 2, 0, MODE_SCHEDULED, threadMessageId, replyMaxReadId, lastLoadIndex++, isTopic); + getMessagesController().loadMessages(dialog_id, mergeDialogId, false, 1, 0, 0, true, 0, classGuid, 2, 0, MODE_SCHEDULED, chatMode == MODE_SAVED ? 0 : threadMessageId, replyMaxReadId, lastLoadIndex++, isTopic); } } @@ -2947,6 +2995,7 @@ public void onFragmentDestroy() { getNotificationCenter().removeObserver(this, NotificationCenter.audioRecordTooShort); getNotificationCenter().removeObserver(this, NotificationCenter.didUpdatePollResults); getNotificationCenter().removeObserver(this, NotificationCenter.didUpdateReactions); + getNotificationCenter().removeObserver(this, NotificationCenter.savedReactionTagsUpdate); getNotificationCenter().removeObserver(this, NotificationCenter.didUpdateExtendedMedia); getNotificationCenter().removeObserver(this, NotificationCenter.chatOnlineCountDidLoad); getNotificationCenter().removeObserver(this, NotificationCenter.videoLoadingStateChanged); @@ -3192,7 +3241,6 @@ public View createView(Context context) { infoTopView = null; aspectRatioFrameLayout = null; videoTextureView = null; - searchAsListHint = null; mediaBanTooltip = null; noSoundHintView = null; forwardHintView = null; @@ -3248,8 +3296,13 @@ public void onItemClick(final int id) { } } } else if (id == view_as_topics) { - getMessagesController().getTopicsController().toggleViewForumAsMessages(-dialog_id, false); - TopicsFragment.prepareToSwitchAnimation(ChatActivity.this); + if (getUserConfig().getClientUserId() == dialog_id) { + getMessagesController().setSavedViewAs(true); + avatarContainer.openProfile(false, true, true); + } else { + getMessagesController().getTopicsController().toggleViewForumAsMessages(-dialog_id, false); + TopicsFragment.prepareToSwitchAnimation(ChatActivity.this); + } } else if (id == copy) { SpannableStringBuilder str = new SpannableStringBuilder(); long previousUid = 0; @@ -3330,6 +3383,12 @@ public void onItemClick(final int id) { createDeleteMessagesAlert(null, null); } else if (id == forward) { openForward(true); + } else if (id == tag_message) { + if (tagSelector == null) { + showTagSelector(); + } else { + hideTagSelector(); + } } else if (id == save_to) { ArrayList messageObjects = new ArrayList<>(); for (int a = 1; a >= 0; a--) { @@ -3361,39 +3420,6 @@ public void onItemClick(final int id) { if (getParentActivity() == null) { return; } - if (chatMode == MODE_SAVED) { - String dialogName = ""; - long dialogId = getSavedDialogId(); - TLRPC.User user = null; - TLRPC.Chat chat = null; - if (dialogId >= 0) { - user = getMessagesController().getUser(dialogId); - } else { - chat = getMessagesController().getChat(-dialogId); - } - if (UserObject.isAnonymous(user)) { - dialogName = LocaleController.getString(R.string.AnonymousForward); - } else if (chat != null) { - dialogName = chat.title; - } else if (user != null) { - dialogName = UserObject.getUserName(user); - } - AlertDialog dialog = new AlertDialog.Builder(getContext(), getResourceProvider()) - .setTitle(LocaleController.formatString(R.string.ClearHistoryTitleSingle, dialogName)) - .setMessage(LocaleController.formatString(R.string.ClearHistoryMessageSingle, dialogName)) - .setPositiveButton(LocaleController.getString(R.string.Delete), (di, w) -> { - getMessagesController().deleteSavedDialog(getSavedDialogId()); - finishFragment(); - }) - .setNegativeButton(LocaleController.getString(R.string.Cancel), null) - .create(); - showDialog(dialog); - TextView button = (TextView) dialog.getButton(DialogInterface.BUTTON_POSITIVE); - if (button != null) { - button.setTextColor(Theme.getColor(Theme.key_text_RedBold)); - } - return; - } boolean canDeleteHistory = chatInfo != null && chatInfo.can_delete_channel; if (id == auto_delete_timer || id == clear_history && currentEncryptedChat == null && ((currentUser != null && !UserObject.isUserSelf(currentUser) && !UserObject.isDeleted(currentUser)) || (chatInfo != null && chatInfo.can_delete_channel))) { AlertsCreator.createClearDaysDialogAlert(ChatActivity.this, -1, currentUser, currentChat, canDeleteHistory, new MessagesStorage.BooleanCallback() { @@ -3496,7 +3522,7 @@ public void run(boolean revoke) { } else if (id == bot_settings) { getSendMessagesHelper().sendMessage(SendMessagesHelper.SendMessageParams.of("/settings", dialog_id, null, null, null, false, null, null, null, true, 0, null, false)); } else if (id == search) { - openSearchWithText(null); + openSearchWithText(isSupportedTags() ? "" : null); } else if (id == translate) { getMessagesController().getTranslateController().setHideTranslateDialog(getDialogId(), false, true); if (!getMessagesController().getTranslateController().toggleTranslatingDialog(getDialogId(), true)) { @@ -3632,6 +3658,16 @@ public void onLongPress() { protected boolean useAnimatedSubtitle() { return chatMode == MODE_SAVED; } + + @Override + protected boolean canSearch() { + return searchItem != null && !searching; + } + + @Override + protected void openSearch() { + openSearchWithText(isSupportedTags() ? "" : null); + } }; avatarContainer.allowShorterStatus = true; avatarContainer.premiumIconHiddable = true; @@ -3717,12 +3753,12 @@ protected boolean useAnimatedSubtitle() { } if (currentEncryptedChat == null && (chatMode == 0 || chatMode == MODE_SAVED) && reportType < 0) { - searchIconItem = menu.addItem(search, R.drawable.ic_ab_search); + searchIconItem = menu.addItem(search, isSupportedTags() ? R.drawable.navbar_search_tag : R.drawable.ic_ab_search); searchIconItem.setContentDescription(LocaleController.getString("Search", R.string.Search)); searchItem = menu.addItem(chat_menu_search, R.drawable.ic_ab_search); searchItem.setIsSearchField(true); searchItem.setActionBarMenuItemSearchListener(getSearchItemListener()); - searchItem.setSearchFieldHint(LocaleController.getString("Search", R.string.Search)); + searchItem.setSearchFieldHint(isSupportedTags() ? LocaleController.getString(R.string.SavedTagSearchHint) : LocaleController.getString("Search", R.string.Search)); if (chatMode == MODE_SAVED || threadMessageId == 0 && !UserObject.isReplyUser(currentUser) || threadMessageObject != null && threadMessageObject.getRepliesCount() < 10) { searchItem.setVisibility(View.GONE); } else { @@ -3756,7 +3792,7 @@ protected boolean useAnimatedSubtitle() { editTextItem.setTag(null); editTextItem.setVisibility(View.GONE); - if (chatMode == MODE_SAVED || (chatMode == 0 && (threadMessageId == 0 || isTopic)) && !UserObject.isReplyUser(currentUser) && reportType < 0) { + if ((chatMode == 0 && (threadMessageId == 0 || isTopic)) && !UserObject.isReplyUser(currentUser) && reportType < 0) { TLRPC.UserFull userFull = null; if (currentUser != null) { userFull = getMessagesController().getUserFull(currentUser.id); @@ -3764,7 +3800,12 @@ protected boolean useAnimatedSubtitle() { headerItem = menu.addItem(chat_menu_options, R.drawable.ic_ab_other, themeDelegate); headerItem.setContentDescription(LocaleController.getString("AccDescrMoreOptions", R.string.AccDescrMoreOptions)); - if (chatMode != MODE_SAVED && (currentUser == null || !currentUser.self)) { + if (currentUser != null && currentUser.self && chatMode != MODE_SAVED) { + savedChatsItem = headerItem.lazilyAddSubItem(view_as_topics, R.drawable.msg_topics, LocaleController.getString(R.string.SavedViewAsChats)); + savedChatsGap = headerItem.lazilyAddColoredGap(); + savedChatsItem.setVisibility(getMessagesController().getSavedMessagesController().hasDialogs() ? View.VISIBLE : View.GONE); + savedChatsGap.setVisibility(getMessagesController().getSavedMessagesController().hasDialogs() ? View.VISIBLE : View.GONE); + } else if (chatMode != MODE_SAVED && (currentUser == null || !currentUser.self)) { chatNotificationsPopupWrapper = new ChatNotificationsPopupWrapper(context, currentAccount, headerItem.getPopupLayout().getSwipeBack(), false, false, new ChatNotificationsPopupWrapper.Callback() { @Override public void dismiss() { @@ -3859,64 +3900,58 @@ public void toggleMute() { if (searchItem != null) { headerItem.lazilyAddSubItem(search, R.drawable.msg_search, LocaleController.getString(R.string.Search)); } - if (chatMode != MODE_SAVED) { - boolean allowShowPinned; - if (currentChat != null) { - allowShowPinned = ChatObject.canUserDoAction(currentChat, ChatObject.ACTION_PIN) || ChatObject.isChannel(currentChat); - } else if (currentUser != null && currentUser.self) { - allowShowPinned = true; - } else if (userInfo != null) { - allowShowPinned = userInfo.can_pin_message; - } else { - allowShowPinned = false; - } - if (allowShowPinned) { - headerItem.lazilyAddSubItem(nkheaderbtn_show_pinned, R.drawable.msg_pin, LocaleController.getString("PinnedMessage", R.string.PinnedMessage)); - } - translateItem = headerItem.lazilyAddSubItem(translate, R.drawable.msg_translate, LocaleController.getString("TranslateMessage", R.string.TranslateMessage)); - updateTranslateItemVisibility(); - if (currentChat != null && !currentChat.creator && !ChatObject.hasAdminRights(currentChat)) { - headerItem.lazilyAddSubItem(report, R.drawable.msg_report, LocaleController.getString("ReportChat", R.string.ReportChat)); - } + boolean allowShowPinned; + if (currentChat != null) { + allowShowPinned = ChatObject.canUserDoAction(currentChat, ChatObject.ACTION_PIN) || ChatObject.isChannel(currentChat); + } else if (currentUser != null && currentUser.self) { + allowShowPinned = true; + } else if (userInfo != null) { + allowShowPinned = userInfo.can_pin_message; + } else { + allowShowPinned = false; + } + if (allowShowPinned) { + headerItem.lazilyAddSubItem(nkheaderbtn_show_pinned, R.drawable.msg_pin, LocaleController.getString("PinnedMessage", R.string.PinnedMessage)); + } + translateItem = headerItem.lazilyAddSubItem(translate, R.drawable.msg_translate, LocaleController.getString("TranslateMessage", R.string.TranslateMessage)); + updateTranslateItemVisibility(); + if (currentChat != null && !currentChat.creator && !ChatObject.hasAdminRights(currentChat)) { + headerItem.lazilyAddSubItem(report, R.drawable.msg_report, LocaleController.getString("ReportChat", R.string.ReportChat)); + } - if (currentChat != null && (currentChat.has_link || (chatInfo != null && chatInfo.linked_chat_id != 0))) { - String text; - int draw; - if (!currentChat.megagroup) { - text = LocaleController.getString("LinkedGroupChat", R.string.LinkedGroupChat); - draw = R.drawable.msg_discussion; - } else { - text = LocaleController.getString("LinkedChannelChat", R.string.LinkedChannelChat); - draw = R.drawable.msg_channel; - } - headerItem.lazilyAddSubItem(nkheaderbtn_linked_chat, draw, text); + if (currentChat != null && (currentChat.has_link || (chatInfo != null && chatInfo.linked_chat_id != 0))) { + String text; + int draw; + if (!currentChat.megagroup) { + text = LocaleController.getString("LinkedGroupChat", R.string.LinkedGroupChat); + draw = R.drawable.msg_discussion; + } else { + text = LocaleController.getString("LinkedChannelChat", R.string.LinkedChannelChat); + draw = R.drawable.msg_channel; } + headerItem.lazilyAddSubItem(nkheaderbtn_linked_chat, draw, text); + } - if (currentUser != null) { - addContactItem = headerItem.lazilyAddSubItem(share_contact, R.drawable.msg_addcontact, ""); - } + if (currentUser != null) { + addContactItem = headerItem.lazilyAddSubItem(share_contact, R.drawable.msg_addcontact, ""); + } - shareKeyItem = headerItem.lazilyAddSubItem(nkheaderbtn_share_key, R.drawable.baseline_vpn_key_24, LocaleController.getString("ShareMyKey", R.string.ShareMyKey)); + shareKeyItem = headerItem.lazilyAddSubItem(nkheaderbtn_share_key, R.drawable.baseline_vpn_key_24, LocaleController.getString("ShareMyKey", R.string.ShareMyKey)); - if (currentEncryptedChat != null) { - timeItem2 = headerItem.lazilyAddSubItem(chat_enc_timer, R.drawable.msg_autodelete, LocaleController.getString("SetTimer", R.string.SetTimer)); - } - if (currentChat != null && !isTopic) { - viewAsTopics = headerItem.lazilyAddSubItem(view_as_topics, R.drawable.msg_topics, LocaleController.getString("TopicViewAsTopics", R.string.TopicViewAsTopics)); - } - if (themeDelegate.isThemeChangeAvailable(true)) { - headerItem.lazilyAddSubItem(change_colors, R.drawable.msg_colors, LocaleController.getString("SetWallpapers", R.string.SetWallpapers)); - } - if (!isTopic) { - clearHistoryItem = headerItem.lazilyAddSubItem(clear_history, R.drawable.msg_clear, LocaleController.getString("ClearHistory", R.string.ClearHistory)); - } + if (currentEncryptedChat != null) { + timeItem2 = headerItem.lazilyAddSubItem(chat_enc_timer, R.drawable.msg_autodelete, LocaleController.getString("SetTimer", R.string.SetTimer)); + } + if (currentChat != null && !isTopic) { + viewAsTopics = headerItem.lazilyAddSubItem(view_as_topics, R.drawable.msg_topics, LocaleController.getString("TopicViewAsTopics", R.string.TopicViewAsTopics)); + } + if (themeDelegate.isThemeChangeAvailable(true)) { + headerItem.lazilyAddSubItem(change_colors, R.drawable.msg_colors, LocaleController.getString("SetWallpapers", R.string.SetWallpapers)); + } + if (!isTopic) { + clearHistoryItem = headerItem.lazilyAddSubItem(clear_history, R.drawable.msg_clear, LocaleController.getString("ClearHistory", R.string.ClearHistory)); } boolean addedSettings = false; - if (chatMode == MODE_SAVED) { - if (threadMessageId != getUserConfig().getClientUserId()) { - headerItem.lazilyAddSubItem(delete_chat, R.drawable.msg_delete, LocaleController.getString("DeleteChatUser", R.string.DeleteChatUser)); - } - } else if (!isTopic) { + if (!isTopic) { toTheBeginning = headerItem.lazilyAddSubItem(to_the_beginning, R.drawable.ic_upward, LocaleController.getString("ToTheBeginning", R.string.ToTheBeginning)); toTheMessage = headerItem.lazilyAddSubItem(to_the_message, R.drawable.msg_go_up, LocaleController.getString("ToTheMessage", R.string.ToTheMessage)); hideTitleItem = headerItem.lazilyAddSubItem(nkheaderbtn_hide_title, R.drawable.hide_title, LocaleController.getString("HideTitle", R.string.HideTitle)); @@ -3947,17 +3982,12 @@ public void toggleMute() { } } } - if (chatMode != MODE_SAVED) { - if (currentUser != null && currentUser.self) { - headerItem.lazilyAddSubItem(add_shortcut, R.drawable.msg_home, LocaleController.getString("AddShortcut", R.string.AddShortcut)); - } - if (currentUser != null && currentEncryptedChat == null && currentUser.bot) { - if (!addedSettings) { - headerItem.lazilyAddSubItem(bot_settings, R.drawable.msg_settings_old, LocaleController.getString("BotSettings", R.string.BotSettings)); - } - headerItem.lazilyAddSubItem(bot_help, R.drawable.msg_help, LocaleController.getString("BotHelp", R.string.BotHelp)); - updateBotButtons(); + if (currentUser != null && currentEncryptedChat == null && currentUser.bot) { + if (!addedSettings) { + headerItem.lazilyAddSubItem(bot_settings, R.drawable.msg_settings_old, LocaleController.getString("BotSettings", R.string.BotSettings)); } + headerItem.lazilyAddSubItem(bot_help, R.drawable.msg_help, LocaleController.getString("BotHelp", R.string.BotHelp)); + updateBotButtons(); } } if (ChatObject.isForum(currentChat) && isTopic && getParentLayout() != null && getParentLayout().getFragmentStack() != null && chatMode == MODE_DEFAULT) { @@ -4129,7 +4159,7 @@ protected boolean allowSelectChildAtPosition(View child) { @Override protected void onMeasure(int widthSpec, int heightSpec) { - saveScrollPosition(); +// saveScrollPosition(); super.onMeasure(widthSpec, heightSpec); } @@ -4405,7 +4435,7 @@ private void processTouchEvent(MotionEvent e) { slidingView = (ChatMessageCell) view; MessageObject message = slidingView.getMessageObject(); boolean allowReplyOnOpenTopic = canSendMessageToTopic(message); - if (chatMode != 0 || threadMessageObjects != null && threadMessageObjects.contains(message) || + if (chatMode != 0 && (chatMode != MODE_SAVED || threadMessageId != getUserConfig().getClientUserId()) || threadMessageObjects != null && threadMessageObjects.contains(message) || getMessageType(message) == 1 && (message.getDialogId() == mergeDialogId || message.needDrawBluredPreview()) || currentEncryptedChat == null && message.getId() < 0 || bottomOverlayChat != null && bottomOverlayChat.getVisibility() == View.VISIBLE && !(bottomOverlayChatWaitsReply && allowReplyOnOpenTopic || message.wasJustSent) || @@ -5396,13 +5426,7 @@ public boolean drawChild(Canvas canvas, View child, long drawingTime) { ImageReceiver imageReceiver = cell.getAvatarImage(); if (imageReceiver != null) { MessageObject.GroupedMessages groupedMessages = getValidGroupedMessage(message); - if (cell.getMessageObject().deleted && !cell.getMessageObject().deletedByThanos) { - if (child.getTranslationY() != 0) { - canvas.restore(); - } - imageReceiver.setVisible(false, false); - return result; - } + boolean updateVisibility = !cell.getMessageObject().deleted && chatListView.getChildAdapterPosition(cell) != RecyclerView.NO_POSITION; boolean replaceAnimation = chatListView.isFastScrollAnimationRunning() || (groupedMessages != null && groupedMessages.transitionParams.backgroundChangeBounds); int top = replaceAnimation ? child.getTop() : (int) child.getY(); @@ -5587,7 +5611,9 @@ public boolean drawChild(Canvas canvas, View child, long drawingTime) { y -= cell.getTranslationY(); } } - imageReceiver.setImageY(y - AndroidUtilities.dp(44)); + if (updateVisibility) { + imageReceiver.setImageY(y - AndroidUtilities.dp(44)); + } if (cell.shouldDrawAlphaLayer()) { imageReceiver.setAlpha(cell.getAlpha()); canvas.scale( @@ -5597,7 +5623,9 @@ public boolean drawChild(Canvas canvas, View child, long drawingTime) { } else { imageReceiver.setAlpha(1f); } - imageReceiver.setVisible(true, false); + if (updateVisibility) { + imageReceiver.setVisible(true, false); + } cell.drawStatusWithImage(canvas, imageReceiver, AndroidUtilities.dp(7)); canvas.restore(); @@ -5650,6 +5678,7 @@ protected void onDetachedFromWindow() { if (currentEncryptedChat != null && Build.VERSION.SDK_INT >= 19) { chatListView.setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS); } + chatListView.setHideIfEmpty(false); chatListView.setAccessibilityEnabled(false); chatListView.setNestedScrollingEnabled(false); chatListView.setInstantClick(true); @@ -5821,11 +5850,11 @@ public boolean shouldLayoutChildFromOpositeSide(View child) { protected boolean hasSiblingChild(int position) { if (position >= chatAdapter.messagesStartRow && position < chatAdapter.messagesEndRow) { int index = position - chatAdapter.messagesStartRow; - if (index >= 0 && index < messages.size()) { - MessageObject message = messages.get(index); + if (index >= 0 && index < chatAdapter.getMessages().size()) { + MessageObject message = chatAdapter.getMessages().get(index); MessageObject.GroupedMessages group = getValidGroupedMessage(message); if (group != null) { - MessageObject.GroupedMessagePosition pos = group.positions.get(message); + MessageObject.GroupedMessagePosition pos = group.getPosition(message); if (pos.minX == pos.maxX || pos.minY != pos.maxY || pos.minY == 0) { return false; } @@ -5931,11 +5960,11 @@ public int scrollVerticallyBy(int dy, RecyclerView.Recycler recycler, RecyclerVi public int getSpanSize(int position) { if (position >= chatAdapter.messagesStartRow && position < chatAdapter.messagesEndRow) { int idx = position - chatAdapter.messagesStartRow; - if (idx >= 0 && idx < messages.size()) { - MessageObject message = messages.get(idx); + if (idx >= 0 && idx < chatAdapter.getMessages().size()) { + MessageObject message = chatAdapter.getMessages().get(idx); MessageObject.GroupedMessages groupedMessages = getValidGroupedMessage(message); if (groupedMessages != null) { - return groupedMessages.positions.get(message).spanSize; + return groupedMessages.getPosition(message).spanSize; } } } @@ -6004,6 +6033,9 @@ public void onScrollStateChanged(RecyclerView recyclerView, int newState) { updateVisibleRows(); scrollByTouch = false; } else { + if (searchOtherButton != null && searchOtherButton.getVisibility() == View.VISIBLE && isKeyboardVisible()) { + AndroidUtilities.hideKeyboard(getParentActivity().getCurrentFocus()); + } if (newState == RecyclerView.SCROLL_STATE_SETTLING) { wasManualScroll = true; scrollingChatListView = true; @@ -6118,12 +6150,22 @@ public void onScrolled(RecyclerView recyclerView, int dx, int dy) { ReactionsEffectOverlay.onScrolled(dy); checkTranslation(false); + + if (savedMessagesTagHint != null) { + if (savedMessagesTagHint.shown()) { + savedMessagesTagHint.hide(); + } else if (!savedMessagesTagHintShown) { + lastScrollTime = System.currentTimeMillis(); + AndroidUtilities.cancelRunOnUIThread(ChatActivity.this::checkSavedMessagesTagHint); + AndroidUtilities.runOnUIThread(ChatActivity.this::checkSavedMessagesTagHint, 2000); + } + } } }); contentView.addView(chatListView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT)); - if (!NekoConfig.disableReactionsWhenSelecting.Bool()) { + if (getDialogId() != getUserConfig().getClientUserId() && !NekoConfig.disableReactionsWhenSelecting.Bool()) { selectionReactionsOverlay = new ChatSelectionReactionMenuOverlay(this, context); contentView.addView(selectionReactionsOverlay, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT)); } @@ -6285,6 +6327,120 @@ protected void onDraw(Canvas canvas) { return true; }); } + ScaleStateListAnimator.apply(pagedownButton, .13f, 2f); + + searchUpButton = new FrameLayout(context); + searchUpButton.setVisibility(View.INVISIBLE); + contentView.addView(searchUpButton, LayoutHelper.createFrame(66, 61, Gravity.RIGHT | Gravity.BOTTOM, 0, 0, -3, 5)); + ImageView searchUpButtonImage = new ImageView(context); + searchUpButtonImage.setPadding(0, AndroidUtilities.dp(2), 0, 0); + Drawable drawable; + if (Build.VERSION.SDK_INT >= 21) { + searchUpButtonImage.setOutlineProvider(new ViewOutlineProvider() { + @Override + public void getOutline(View view, Outline outline) { + outline.setOval(0, 0, AndroidUtilities.dp(42), AndroidUtilities.dp(42)); + } + }); + drawable = Theme.createSimpleSelectorCircleDrawable(AndroidUtilities.dp(42), getThemedColor(Theme.key_chat_goDownButton), getThemedColor(Theme.key_listSelector)); + } else { + drawable = Theme.createCircleDrawable(AndroidUtilities.dp(42), getThemedColor(Theme.key_chat_goDownButton)); + } + Drawable shadowDrawable = context.getResources().getDrawable(R.drawable.pagedown_shadow).mutate(); + shadowDrawable.setColorFilter(new PorterDuffColorFilter(0xff000000, PorterDuff.Mode.MULTIPLY)); + CombinedDrawable combinedDrawable = new CombinedDrawable(shadowDrawable, drawable, 0, 0); + combinedDrawable.setIconSize(AndroidUtilities.dp(42), AndroidUtilities.dp(42)); + drawable = combinedDrawable; + searchUpButtonImage.setBackground(drawable); + searchUpButton.addView(searchUpButtonImage, LayoutHelper.createFrame(46, 46, Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM)); + searchUpButton.setContentDescription(LocaleController.getString(R.string.AccDescrSearchNext)); + searchUpButtonArrow = new ImageView(context); + searchUpButtonArrow.setScaleY(-1f); + searchUpButtonArrow.setImageResource(R.drawable.pagedown); + searchUpButtonArrow.setScaleType(ImageView.ScaleType.CENTER); + searchUpButtonArrow.setColorFilter(new PorterDuffColorFilter(getThemedColor(Theme.key_chat_goDownButtonIcon), PorterDuff.Mode.MULTIPLY)); + searchUpButtonArrow.setPadding(0, AndroidUtilities.dp(2), 0, 0); + searchUpButton.addView(searchUpButtonArrow, LayoutHelper.createFrame(46, 46, Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM)); + ScaleStateListAnimator.apply(searchUpButton, .12f, 2f); + + searchDownButton = new FrameLayout(context); + searchDownButton.setVisibility(View.INVISIBLE); + contentView.addView(searchDownButton, LayoutHelper.createFrame(66, 61, Gravity.RIGHT | Gravity.BOTTOM, 0, 0, -3, 5)); + ImageView searchDownButtonImage = new ImageView(context); + searchDownButtonImage.setPadding(0, AndroidUtilities.dp(2), 0, 0); + if (Build.VERSION.SDK_INT >= 21) { + searchDownButtonImage.setOutlineProvider(new ViewOutlineProvider() { + @Override + public void getOutline(View view, Outline outline) { + outline.setOval(0, 0, AndroidUtilities.dp(42), AndroidUtilities.dp(42)); + } + }); + drawable = Theme.createSimpleSelectorCircleDrawable(AndroidUtilities.dp(42), getThemedColor(Theme.key_chat_goDownButton), getThemedColor(Theme.key_listSelector)); + } else { + drawable = Theme.createCircleDrawable(AndroidUtilities.dp(42), getThemedColor(Theme.key_chat_goDownButton)); + } + shadowDrawable = context.getResources().getDrawable(R.drawable.pagedown_shadow).mutate(); + shadowDrawable.setColorFilter(new PorterDuffColorFilter(0xff000000, PorterDuff.Mode.MULTIPLY)); + combinedDrawable = new CombinedDrawable(shadowDrawable, drawable, 0, 0); + combinedDrawable.setIconSize(AndroidUtilities.dp(42), AndroidUtilities.dp(42)); + drawable = combinedDrawable; + searchDownButtonImage.setBackground(drawable); + searchDownButton.addView(searchDownButtonImage, LayoutHelper.createFrame(46, 46, Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM)); + searchDownButton.setContentDescription(LocaleController.getString(R.string.AccDescrSearchPrev)); + searchDownButtonArrow = new ImageView(context); + searchDownButtonArrow.setImageResource(R.drawable.pagedown); + searchDownButtonArrow.setScaleType(ImageView.ScaleType.CENTER); + searchDownButtonArrow.setColorFilter(new PorterDuffColorFilter(getThemedColor(Theme.key_chat_goDownButtonIcon), PorterDuff.Mode.MULTIPLY)); + searchDownButtonArrow.setPadding(0, AndroidUtilities.dp(2), 0, 0); + searchDownButton.addView(searchDownButtonArrow, LayoutHelper.createFrame(46, 46, Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM)); + ScaleStateListAnimator.apply(searchDownButton, .12f, 2f); + + searchUpButton.setOnClickListener(view -> { + getMediaDataController().searchMessagesInChat(null, dialog_id, mergeDialogId, classGuid, reversed ? 2 : 1, threadMessageId, searchingUserMessages, searchingChatMessages, searchingReaction); + showMessagesSearchListView(false); + }); + searchDownButton.setOnClickListener(view -> { + getMediaDataController().searchMessagesInChat(null, dialog_id, mergeDialogId, classGuid, reversed ? 1 : 2, threadMessageId, searchingUserMessages, searchingChatMessages, searchingReaction); + showMessagesSearchListView(false); + }); + + // nekox: go to the first message + searchGoToBeginningButton = new FrameLayout(context); + searchGoToBeginningButton.setVisibility(View.INVISIBLE); + contentView.addView(searchGoToBeginningButton, LayoutHelper.createFrame(66, 61, Gravity.RIGHT | Gravity.BOTTOM, 0, 0, -3, 5)); + ImageView searchGoToBeginningButtonImage = new ImageView(context); + searchGoToBeginningButtonImage.setPadding(0, AndroidUtilities.dp(2), 0, 0); + if (Build.VERSION.SDK_INT >= 21) { + searchGoToBeginningButtonImage.setOutlineProvider(new ViewOutlineProvider() { + @Override + public void getOutline(View view, Outline outline) { + outline.setOval(0, 0, AndroidUtilities.dp(42), AndroidUtilities.dp(42)); + } + }); + drawable = Theme.createSimpleSelectorCircleDrawable(AndroidUtilities.dp(42), getThemedColor(Theme.key_chat_goDownButton), getThemedColor(Theme.key_listSelector)); + } else { + drawable = Theme.createCircleDrawable(AndroidUtilities.dp(42), getThemedColor(Theme.key_chat_goDownButton)); + } + shadowDrawable = context.getResources().getDrawable(R.drawable.pagedown_shadow).mutate(); + shadowDrawable.setColorFilter(new PorterDuffColorFilter(0xff000000, PorterDuff.Mode.MULTIPLY)); + combinedDrawable = new CombinedDrawable(shadowDrawable, drawable, 0, 0); + combinedDrawable.setIconSize(AndroidUtilities.dp(42), AndroidUtilities.dp(42)); + drawable = combinedDrawable; + searchGoToBeginningButtonImage.setBackground(drawable); + searchGoToBeginningButton.addView(searchGoToBeginningButtonImage, LayoutHelper.createFrame(46, 46, Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM)); + searchGoToBeginningButton.setContentDescription(LocaleController.getString(R.string.AccDescrSearchNext)); + searchGoToBeginningButtonArrow = new ImageView(context); + searchGoToBeginningButtonArrow.setScaleY(-1f); + searchGoToBeginningButtonArrow.setImageResource(R.drawable.ic_upward); + searchGoToBeginningButtonArrow.setScaleType(ImageView.ScaleType.CENTER); + searchGoToBeginningButtonArrow.setColorFilter(new PorterDuffColorFilter(getThemedColor(Theme.key_chat_searchPanelIcons), PorterDuff.Mode.MULTIPLY)); + searchGoToBeginningButtonArrow.setPadding(0, AndroidUtilities.dp(2), 0, 0); + searchGoToBeginningButton.addView(searchGoToBeginningButtonArrow, LayoutHelper.createFrame(46, 46, Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM)); + ScaleStateListAnimator.apply(searchGoToBeginningButton, .12f, 2f); + + searchGoToBeginningButton.setOnClickListener(view -> { + scrollToMessageId(1, 0, false, 0, true, 0); + }); mentiondownButton = new FrameLayout(context); mentiondownButton.setVisibility(View.INVISIBLE); @@ -6681,7 +6837,6 @@ public long getDialogId() { pagedownButtonImage = new ImageView(context); pagedownButtonImage.setPadding(0, AndroidUtilities.dp(2), 0, 0); - Drawable drawable; if (Build.VERSION.SDK_INT >= 21) { pagedownButtonImage.setOutlineProvider(new ViewOutlineProvider() { @Override @@ -6693,9 +6848,9 @@ public void getOutline(View view, Outline outline) { } else { drawable = Theme.createCircleDrawable(AndroidUtilities.dp(42), getThemedColor(Theme.key_chat_goDownButton)); } - Drawable shadowDrawable = context.getResources().getDrawable(R.drawable.pagedown_shadow).mutate(); - shadowDrawable.setColorFilter(new PorterDuffColorFilter(0xff000000, PorterDuff.Mode.SRC_IN)); - CombinedDrawable combinedDrawable = new CombinedDrawable(shadowDrawable, drawable, 0, 0); + shadowDrawable = context.getResources().getDrawable(R.drawable.pagedown_shadow).mutate(); + shadowDrawable.setColorFilter(new PorterDuffColorFilter(0xff000000, PorterDuff.Mode.MULTIPLY)); + combinedDrawable = new CombinedDrawable(shadowDrawable, drawable, 0, 0); combinedDrawable.setIconSize(AndroidUtilities.dp(42), AndroidUtilities.dp(42)); drawable = combinedDrawable; pagedownButtonImage.setBackground(drawable); @@ -6863,16 +7018,37 @@ public void getOutline(View view, Outline outline) { messagesSearchListView.setAdapter(messagesSearchAdapter = new MessagesSearchAdapter(context, themeDelegate)); contentView.addView(messagesSearchListView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, Gravity.LEFT | Gravity.TOP, 0, 0, 0, 48)); messagesSearchListView.setOnItemClickListener((view, position) -> { - getMediaDataController().jumpToSearchedMessage(classGuid, position); - showMessagesSearchListView(false); + if (searchingReaction != null) { + + if (position < 0 || position >= getMediaDataController().searchResultMessages.size()) + return; + MessageObject msg = getMediaDataController().searchResultMessages.get(position); + setFilterMessages(searchingFiltered = false, true, false); + getMediaDataController().setSearchedPosition(position); + updateSearchButtons(getMediaDataController().getMask(), getMediaDataController().getSearchPosition(), getMediaDataController().getSearchCount()); + AndroidUtilities.runOnUIThread(() -> { + scrollToMessageId(msg.getId(), 0, true, 0, true, 0, () -> { + progressDialog = new AlertDialog(getParentActivity(), AlertDialog.ALERT_TYPE_SPINNER, themeDelegate); + progressDialog.setOnShowListener(dialogInterface -> showPinnedProgress(false)); + progressDialog.setOnCancelListener(postponedScrollCancelListener); + progressDialog.showDelayed(500); + }); + if (waitingForLoad.isEmpty()) { + showMessagesSearchListView(false); + } + }); + } else { + getMediaDataController().jumpToSearchedMessage(classGuid, position); + showMessagesSearchListView(false); + } }); messagesSearchListView.setOnScrollListener(new RecyclerView.OnScrollListener() { @Override public void onScrolled(RecyclerView recyclerView, int dx, int dy) { int lastVisibleItem = messagesSearchLayoutManager.findLastVisibleItemPosition(); int visibleItemCount = lastVisibleItem == RecyclerView.NO_POSITION ? 0 : lastVisibleItem; - if (visibleItemCount > 0 && lastVisibleItem > messagesSearchLayoutManager.getItemCount() - 5) { - getMediaDataController().loadMoreSearchMessages(); + if (visibleItemCount > 0 && lastVisibleItem > messagesSearchAdapter.loadedCount - 5) { + getMediaDataController().loadMoreSearchMessages(true); } } }); @@ -7629,7 +7805,7 @@ protected void onSend(int type, String message) { chatListView.setEmptyView(null); } else { showProgressView(false); - createEmptyView(); + createEmptyView(false); chatListView.setEmptyView(emptyViewContainer); } @@ -7640,7 +7816,19 @@ protected void onSend(int type, String message) { updatePinnedMessageView(false); updateInfoTopView(false); - chatScrollHelper = new RecyclerAnimationScrollHelper(chatListView, chatLayoutManager); + chatScrollHelper = new RecyclerAnimationScrollHelper(chatListView, chatLayoutManager) { + @Override + public void setScrollDirection(int scrollDirection) { + if (reversed) { + if (scrollDirection == RecyclerAnimationScrollHelper.SCROLL_DIRECTION_DOWN) { + scrollDirection = RecyclerAnimationScrollHelper.SCROLL_DIRECTION_UP; + } else if (scrollDirection == RecyclerAnimationScrollHelper.SCROLL_DIRECTION_UP) { + scrollDirection = RecyclerAnimationScrollHelper.SCROLL_DIRECTION_DOWN; + } + } + super.setScrollDirection(scrollDirection); + } + }; chatScrollHelper.setScrollListener(this::invalidateMessagesVisiblePart); chatScrollHelper.setAnimationCallback(chatScrollHelperCallback); @@ -7823,29 +8011,87 @@ public void onAllEffectsEnd() { savedMessagesHint.setTextAlign(Layout.Alignment.ALIGN_CENTER); savedMessagesHint.setText(AndroidUtilities.replaceTags(LocaleController.getString(R.string.SavedMessagesHint))); savedMessagesHint.setMaxWidthPx(HintView2.cutInFancyHalf(savedMessagesHint.getText(), savedMessagesHint.getTextPaint())); - savedMessagesHint.setJoint(0.5f, 0); + if (AndroidUtilities.isTablet()) { + savedMessagesHint.setJoint(0, 77); + } else { + savedMessagesHint.setJoint(0.5f, 0); + } savedMessagesHint.setCloseButton(true); - savedMessagesHint.setDuration(-1); + savedMessagesHint.setOnHiddenListener(() -> { + if (searchContainer == null || searchContainer.getVisibility() != View.VISIBLE) { + if (savedMessagesSearchHint != null) { + savedMessagesSearchHint.show(); + } + } + }); + savedMessagesHint.setDuration(-1); + savedMessagesHint.setPadding(dp(8), 0, dp(8), 0); contentView.addView(savedMessagesHint, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 120, Gravity.TOP | Gravity.FILL_HORIZONTAL, 0, -8, 0, 0)); + + savedMessagesSearchHint = new HintView2(context, HintView2.DIRECTION_TOP) + .setMultilineText(true) + .setTextAlign(Layout.Alignment.ALIGN_CENTER) + .setDuration(-1) + .setHideByTouch(true) + .useScale(true) + .setCloseButton(true) + .setJointPx(1, -dp(56)) + .setRounding(8); + savedMessagesSearchHint.setText(LocaleController.getString(R.string.SavedTagSearchTooltipHint)); + contentView.addView(savedMessagesSearchHint, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 120, Gravity.TOP | Gravity.FILL_HORIZONTAL, 16, -8, 16, 0)); + + if (getUserConfig().isPremium()) { + savedMessagesTagHint = new HintView2(context, HintView2.DIRECTION_BOTTOM) + .setMultilineText(true) + .setTextAlign(Layout.Alignment.ALIGN_CENTER) + .setDuration(-1) + .setHideByTouch(true) + .useScale(true) + .setCloseButton(true) + .setRounding(8); + savedMessagesTagHint.setText(LocaleController.getString(R.string.SavedTagLongpressHint)); + contentView.addView(savedMessagesTagHint, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 120, Gravity.TOP | Gravity.FILL_HORIZONTAL, 16, 0, 16, 0)); + } } if (getDialogId() == getUserConfig().getClientUserId()) { - actionBarSearchTags = new SearchTagsList(context, contentView, currentAccount, themeDelegate) { + actionBarSearchTags = new SearchTagsList(context, ChatActivity.this, contentView, currentAccount, getSavedDialogId(), themeDelegate, true) { @Override - protected void setFilter(ReactionsLayoutInBubble.VisibleReaction reaction) { - actionBar.clearSearchFilters(); -// if (reaction != null) { -// actionBar.setSearchFilter(new FiltersView.MediaFilterData(reaction)); + protected boolean setFilter(ReactionsLayoutInBubble.VisibleReaction reaction) { +// if (!isInsideContainer) { +// actionBar.clearSearchFilters(); // } searchingReaction = reaction; -// showSearchShowOther(searchingReaction != null); - getMediaDataController().searchMessagesInChat(searchItem.getSearchField().getText().toString(), dialog_id, mergeDialogId, classGuid, 0, threadMessageId, searchingUserMessages, searchingChatMessages, searchingReaction); + searchingFiltered = reaction != null; + if (reaction == null) { + getMediaDataController().clearFoundMessageObjects(); + setFilterMessages(false); + updateSearchButtons(0, 0, -1); + } + updateSearchUpDownButtonVisibility(true); + updatePagedownButtonVisibility(true); + searchingQuery = searchItem.getSearchField().getText().toString(); + getMediaDataController().searchMessagesInChat(searchingQuery, dialog_id, mergeDialogId, classGuid, 0, threadMessageId, false, searchingUserMessages, searchingChatMessages, !TextUtils.isEmpty(searchingQuery) || searchingReaction != null, searchingReaction); + AndroidUtilities.hideKeyboard(searchItem.getSearchField()); + return true; } @Override - public void updateTags() { - super.updateTags(); -// showActionBarSearchTags(searchItem != null && searchItem.isSearchFieldVisible() && hasFilters()); + public void updateTags(boolean notify) { + super.updateTags(notify); + show(searchItem != null && searchItem.isSearchFieldVisible() && hasFilters()); + } + + @Override + protected void onShownUpdate(boolean finish) { + setBackgroundColor(actionBar.getBackgroundColor()); + if (tagSelector != null) { + tagSelector.setTranslationY(contentPanTranslation + getCurrentHeight()); + } + if (finish) { + invalidateChatListViewTopPadding = true; + updateChatListViewTopPadding(); + } } }; actionBarSearchTags.setVisibility(View.GONE); @@ -7856,47 +8102,422 @@ public void updateTags() { return fragmentView; } + public void setTagFilter(ReactionsLayoutInBubble.VisibleReaction reaction) { + if (actionBarSearchTags != null) { + actionBarSearchTags.setChosen(reaction, true); + } + searchItemVisible = searching = !TextUtils.isEmpty(searchingQuery) || searchingReaction != null; + updateBottomOverlay(); + updateSearchUpDownButtonVisibility(true); + } + + public void setSearchQuery(String text) { + if (searchItem != null) { + searchItem.setSearchFieldText(searchingQuery = text, false); + } + } + + public void hitSearch() { + searchWas = true; + updateSearchButtons(0, 0, -1); + getMediaDataController().searchMessagesInChat(searchingQuery, dialog_id, mergeDialogId, classGuid, 0, threadMessageId, searchingUserMessages, searchingChatMessages, searchingReaction); + searchItemVisible = searching = !TextUtils.isEmpty(searchingQuery) || searchingReaction != null; + updateBottomOverlay(); + updateSearchUpDownButtonVisibility(true); + } + + public void clearSearch() { + if (searchItemListener != null) { + searchItemListener.onSearchCollapse(); + } + searching = false; + searchItemVisible = false; + updateBottomOverlay(); + updateSearchUpDownButtonVisibility(true); + } + + protected void onSearchLoadingUpdate(boolean loading) { + + } + private void setFilterMessages(boolean filter) { + setFilterMessages(filter, false, true); + } + private void setFilterMessages(boolean filter, boolean ignoreMessageNotFound, boolean animated) { if (chatAdapter.isFiltered == filter) return; chatAdapter.isFiltered = filter; + createEmptyView(true); if (filter) { - updateFilteredMessages(); - } else { - chatAdapter.updateRowsSafe(); - chatAdapter.notifyDataSetChanged(true); + updateFilteredMessages(false); + } + if (!saveScrollOnFilterToggle(animated, ignoreMessageNotFound)) { + chatAdapter.isFiltered = !filter; + } + if (searchOtherButton != null) { + searchOtherButton.setText(LocaleController.getString(chatAdapter.isFiltered ? R.string.SavedTagShowOtherMessages : R.string.SavedTagHideOtherMessages)); + } + updateSearchUpDownButtonVisibility(true); + showProgressView(!chatAdapter.isFiltered ? loading && messages.isEmpty() && chatAdapter.botInfoRow < 0 : getMediaDataController().isSearchLoading() && chatAdapter.filteredMessages.isEmpty()); + if (chatListView != null) { + createEmptyView(false); + if (!(!chatAdapter.isFiltered ? !loading && messages.isEmpty() && chatAdapter.botInfoRow < 0 : !getMediaDataController().isSearchLoading() && chatAdapter.filteredMessages.isEmpty())) { + emptyViewContainer.setVisibility(View.GONE); + chatListView.setEmptyView(null); + } else { + chatListView.setEmptyView(emptyViewContainer); + chatListView.checkIfEmpty(); + } + } + } + + private boolean saveScrollOnFilterToggle(boolean animated, boolean ignoreMessageNotFound) { + final ArrayList newMessagesArray = chatAdapter.getMessages(); + + int index = -1; + int centerId = 0; + int centerStableId = 0; + int offset = 0; + int cy = chatListView.getMeasuredHeight() / 2; + ArrayList views = new ArrayList<>(); + HashMap distances = new HashMap<>(); + for (int i = 0; i < chatListView.getChildCount(); ++i) { + View child = chatListView.getChildAt(i); +// int ccy = (child.getTop() + child.getBottom()) / 2; +// views.put(Math.abs(ccy - cy), child); // base on center + int dist = (int) (chatListView.getMeasuredHeight() * .97f) - dp(42) - child.getBottom(); + if (dist < 0) continue; + distances.put(child, dist); + views.add(child); + } + Collections.sort(views, Comparator.comparingInt(distances::get)); + HashSet ids = new HashSet(); + HashSet stableIds = new HashSet(); + for (int i = 0; i < newMessagesArray.size(); ++i) { + MessageObject m = newMessagesArray.get(i); + if (!m.isDateObject) { + ids.add(m.getId()); + } + stableIds.add(m.stableId); + } + for (int i = 0; i < views.size(); ++i) { + View child = views.get(i); + MessageObject msg; + if (child instanceof ChatMessageCell) { + msg = ((ChatMessageCell) child).getMessageObject(); + } else if (child instanceof ChatActionCell) { + msg = ((ChatActionCell) child).getMessageObject(); + } else { + continue; + } + if (msg == null) continue; + int id = msg.getId(); + if (ids.contains(id)) { + centerId = id; + offset = getScrollingOffsetForView(child); + break; + } else if (stableIds.contains(msg.stableId)) { + centerStableId = msg.stableId; + offset = getScrollingOffsetForView(child); + break; + } + } + if (centerId == 0 && centerStableId == 0) { + if (!chatAdapter.isFiltered && !ignoreMessageNotFound) { + for (int j = 0; j < views.size(); ++j) { + View centerView = views.get(j); + MessageObject msg; + if (centerView instanceof ChatMessageCell) { + msg = ((ChatMessageCell) centerView).getMessageObject(); + } else { + continue; + } + if (msg == null) { + continue; + } + int id = msg.getId(); + + waitingForLoad.clear(); + removeSelectedMessageHighlight(); + scrollToMessagePosition = -10000; + startLoadFromMessageId = id; + showScrollToMessageError = false; + createUnreadMessageAfterIdLoading = false; + postponedScrollIsCanceled = false; + waitingForLoad.add(lastLoadIndex); + postponedScrollToLastMessageQueryIndex = lastLoadIndex; + fakePostponedScroll = true; + postponedScrollMinMessageId = minMessageId[0]; + postponedScrollMessageId = id; + getMessagesController().loadMessages(dialog_id, 0, false, 50, startLoadFromMessageId, 0, true, 0, classGuid, 3, 0, chatMode, threadMessageId, replyMaxReadId, lastLoadIndex++, isTopic); + return false; + } + } + for (int j = 0; j < views.size(); ++j) { + View centerView = views.get(j); + MessageObject msg; + if (centerView instanceof ChatMessageCell) { + msg = ((ChatMessageCell) centerView).getMessageObject(); + } else { + continue; + } + if (msg == null) { + continue; + } + int id = msg.getId(); + int mid = -1; + int leastDist = Integer.MAX_VALUE; + for (int i = 0; i < newMessagesArray.size(); ++i) { + MessageObject msg2 = newMessagesArray.get(i); + if (msg2.getId() == 0) continue; + final int dist = Math.abs(msg2.getId() - id); + if (dist < leastDist) { + leastDist = dist; + mid = msg2.getId(); + + index = i; + offset = 0; + } + } + if (mid != -1) { + break; + } + } + } + if (centerStableId != 0) { + for (int i = 0; i < newMessagesArray.size(); ++i) { + if (newMessagesArray.get(i).stableId == centerStableId) { + index = i; + break; + } + } + } else if (centerId != 0) { + for (int i = 0; i < newMessagesArray.size(); ++i) { + if (newMessagesArray.get(i).getId() == centerId) { + index = i; + break; + } + } + } + chatAdapter.updateRowsSafe(); + if (index >= 0) { + int newPosition = chatAdapter.messagesStartRow + index; + chatLayoutManager.scrollToPositionWithOffset(newPosition, offset); } + chatAdapter.notifyDataSetChanged(animated); + return true; } - private void updateFilteredMessages() { + private LongSparseArray> filteredMessagesByDays; + private LongSparseArray filteredMessagesDict; + + private void putFilteredDate(int index, MessageObject baseMsg) { + TLRPC.Message dateMsg = new TLRPC.TL_message(); + dateMsg.message = LocaleController.formatDateChat(baseMsg.messageOwner.date); + dateMsg.id = 0; + Calendar calendar = Calendar.getInstance(); + calendar.setTimeInMillis(((long) baseMsg.messageOwner.date) * 1000); + calendar.set(Calendar.HOUR_OF_DAY, 0); + calendar.set(Calendar.MINUTE, 0); + calendar.set(Calendar.SECOND, 0); + calendar.set(Calendar.MILLISECOND, 0); + dateMsg.date = (int) (calendar.getTimeInMillis() / 1000); + MessageObject dateObj = new MessageObject(currentAccount, dateMsg, false, false); + dateObj.type = 10; + dateObj.contentType = 1; + dateObj.isDateObject = true; + dateObj.stableId = getStableIdForDateObject(baseMsg.dateKeyInt); + chatAdapter.filteredMessages.add(index, dateObj); + } + + private void createHint2MessageObject() { + if (hint2MessageObject != null) return; + TLRPC.Message dateMsg = new TLRPC.TL_message(); + dateMsg.message = LocaleController.getString(R.string.SavedMessagesProfileHint); + dateMsg.id = 0; + hint2MessageObject = new MessageObject(currentAccount, dateMsg, false, false); + hint2MessageObject.type = 10; + hint2MessageObject.contentType = 1; + } + + private void updateFilteredMessages(boolean notify) { ArrayList results = new ArrayList<>(MediaDataController.getInstance(currentAccount).getFoundMessageObjects()); + if (filteredMessagesDict == null) { + filteredMessagesDict = new LongSparseArray<>(); + } + if (filteredMessagesByDays == null) { + filteredMessagesByDays = new LongSparseArray<>(); + } else { + filteredMessagesByDays.clear(); + } + LongSparseArray newGroups = null; + LongSparseArray changedGroups = null; chatAdapter.filteredMessages.clear(); + filteredMessagesDict.clear(); for (int i = 0; i < results.size(); ++i) { MessageObject msg = results.get(i); MessageObject from = null; - for (int j = 0; j < messages.size(); ++j) { - MessageObject m = messages.get(j); - if (m.getDialogId() == msg.getDialogId() && m.getId() == msg.getId()) { - from = m; - break; + if (from == null) { + for (int j = 0; j < messages.size(); ++j) { + MessageObject m = messages.get(j); + if (m.getDialogId() == msg.getDialogId() && m.getId() == msg.getId()) { + from = m; + break; + } } } if (msg.stableId == 0) { - msg.checkMediaExistance(); - if (from != null) { - msg.copyStableParams(from); + if (from == null) { + msg.checkMediaExistance(); } else { - msg.stableId = lastStableId++; + msg.mediaExists = from.mediaExists; + msg.attachPathExists = from.attachPathExists; + } + } + if (from != null) { + msg.isSaved = from.isSaved; + if (chatAdapter.isFiltered && msg.stableId != 0) { + from.copyStableParams(msg); + } else { + msg.copyStableParams(from); } + } else if (msg.stableId == 0) { + msg.stableId = lastStableId++; } msg.isOutOwnerCached = null; if (msg.messageOwner != null) { msg.messageOwner.out = true; } + msg.isOutOwner(); + + if (msg.hasValidGroupId()) { + MessageObject.GroupedMessages groupedMessages = groupedMessagesMap.get(msg.getGroupIdForUse()); + if (groupedMessages == null) { + groupedMessages = new MessageObject.GroupedMessages(); + groupedMessages.reversed = reversed; + groupedMessages.groupId = msg.getGroupId(); + groupedMessagesMap.put(groupedMessages.groupId, groupedMessages); + } else if (newGroups == null || newGroups.indexOfKey(msg.getGroupId()) < 0) { + if (changedGroups == null) { + changedGroups = new LongSparseArray<>(); + } + changedGroups.put(msg.getGroupId(), groupedMessages); + } + if (newGroups == null) { + newGroups = new LongSparseArray<>(); + } + newGroups.put(groupedMessages.groupId, groupedMessages); + if (groupedMessages.getPosition(msg) == null) { + boolean found = false; + for (int j = 0; j < groupedMessages.messages.size(); ++j) { + if (groupedMessages.messages.get(j).getId() == msg.getId()) { + found = true; + break; + } + } + if (!found) { + groupedMessages.messages.add(msg); + } + } + } else if (msg.getGroupIdForUse() != 0) { + msg.messageOwner.grouped_id = 0; + msg.localSentGroupId = 0; + } + chatAdapter.filteredMessages.add(msg); + filteredMessagesDict.put(msg.getId(), msg); + } + if (newGroups != null) { + for (int i = 0; i < newGroups.size(); ++i) { + MessageObject.GroupedMessages group = newGroups.valueAt(i); + Collections.sort(group.messages, (a, b) -> a.getId() - b.getId()); + group.calculate(); + } + } + ArrayList messagesResults = new ArrayList<>(); + if (searchingReaction != null && TextUtils.isEmpty(searchingQuery)) { + for (int i = 0; i < messages.size(); ++i) { + MessageObject msg = messages.get(i); + if (msg != null && msg.messageOwner != null && msg.messageOwner.reactions != null && msg.messageOwner.reactions.reactions_as_tags) { + for (int j = 0; j < msg.messageOwner.reactions.results.size(); ++j) { + if (searchingReaction.isSame(msg.messageOwner.reactions.results.get(j).reaction)) { + messagesResults.add(msg); + break; + } + } + } + } + } + for (int i = 0; i < messagesResults.size(); ++i) { + MessageObject msg = messagesResults.get(i); + if (filteredMessagesDict.containsKey(msg.getId())) { + continue; + } + msg.isOutOwnerCached = null; + if (msg.messageOwner != null) { + msg.messageOwner.out = true; + } + chatAdapter.filteredMessages.add(msg); + filteredMessagesDict.put(msg.getId(), msg); + } + for (int i = 0; i < chatAdapter.filteredMessages.size(); ++i) { + MessageObject obj = chatAdapter.filteredMessages.get(i); + if (!obj.hasValidGroupId()) { + continue; + } + MessageObject.GroupedMessages group = groupedMessagesMap.get(obj.getGroupId()); + if (group != null) { + for (int j = group.messages.size() - 1; j >= 0; --j) { + MessageObject groupmsg = group.messages.get(j); + if (groupmsg == obj || filteredMessagesDict.containsKey(groupmsg.getId())) + continue; + chatAdapter.filteredMessages.add(i, groupmsg); + filteredMessagesDict.put(groupmsg.getId(), groupmsg); + i++; + } + } else { + + } + } + Collections.sort(chatAdapter.filteredMessages, (a, b) -> b.getId() - a.getId()); + MessageObject lastFilteredMessage = null; + for (int i = 0; i < chatAdapter.filteredMessages.size(); ++i) { + MessageObject msg = chatAdapter.filteredMessages.get(i); + if (reversed && msg != null && i == 0) { + putFilteredDate(i++, msg); + } + if (!reversed && lastFilteredMessage != null && msg.dateKeyInt != lastFilteredMessage.dateKeyInt) { + putFilteredDate(i++, lastFilteredMessage); + } + ArrayList dayArray = filteredMessagesByDays.get(msg.dateKeyInt); + if (dayArray == null) { + filteredMessagesByDays.put(msg.dateKeyInt, dayArray = new ArrayList<>()); + } + dayArray.add(msg); + if (reversed && lastFilteredMessage != null && msg.dateKeyInt != lastFilteredMessage.dateKeyInt) { + putFilteredDate(i++, msg); + } + lastFilteredMessage = msg; + if (!reversed && lastFilteredMessage != null && i >= chatAdapter.filteredMessages.size() - 1) { + putFilteredDate(chatAdapter.filteredMessages.size(), lastFilteredMessage); + i++; + } } chatAdapter.filteredEndReached = MediaDataController.getInstance(currentAccount).searchEndReached(); - chatAdapter.updateRowsSafe(); - chatAdapter.notifyDataSetChanged(true); + if (notify) { + chatAdapter.updateRowsSafe(); + chatAdapter.notifyDataSetChanged(true); + showProgressView(!chatAdapter.isFiltered ? loading && messages.isEmpty() && chatAdapter.botInfoRow < 0 : getMediaDataController().isSearchLoading() && chatAdapter.filteredMessages.isEmpty()); + if (chatListView != null) { + createEmptyView(false); + if (!(!chatAdapter.isFiltered ? !loading && messages.isEmpty() && chatAdapter.botInfoRow < 0 : !getMediaDataController().isSearchLoading() && chatAdapter.filteredMessages.isEmpty())) { + emptyViewContainer.setVisibility(View.GONE); + chatListView.setEmptyView(null); + } else { + chatListView.setEmptyView(emptyViewContainer); + chatListView.checkIfEmpty(); + } + } + } } private void createBottomMessagesActionButtons() { @@ -8300,6 +8921,9 @@ private void createActionMode() { if (NaConfig.INSTANCE.getShowNoQuoteForward().Bool()) { actionModeOtherItem.addSubItem(nkbtn_forward_noquote, R.drawable.msg_forward_noquote, LocaleController.getString("NoQuoteForward", R.string.NoQuoteForward)); } + if (getDialogId() == getUserConfig().getClientUserId() && (chatMode == 0 || chatMode == MODE_SAVED)) { + actionModeViews.add(actionMode.addItemWithWidth(tag_message, R.drawable.menu_tag_edit, AndroidUtilities.dp(54), LocaleController.getString(R.string.AccDescrTagMessage))); + } actionModeOtherItem.addSubItem(star, R.drawable.msg_fave, LocaleController.getString("AddToFavorites", R.string.AddToFavorites)); actionModeOtherItem.addSubItem(save_to, R.drawable.msg_download, LocaleController.getString("SaveToMusic", R.string.SaveToMusic)); } @@ -8327,6 +8951,7 @@ private void createActionMode() { actionMode.getItem(copy).setVisibility(!getMessagesController().isChatNoForwardsWithOverride(currentChat) && selectedMessagesCanCopyIds[0].size() + selectedMessagesCanCopyIds[1].size() != 0 ? View.VISIBLE : View.GONE); actionMode.getItem(delete).setVisibility(cantDeleteMessagesCount == 0 ? View.VISIBLE : View.GONE); actionMode.getItem(combine_message).setVisibility(selectedMessagesCanCopyIds[0].size() + selectedMessagesCanCopyIds[1].size() != 0 ? View.VISIBLE : View.GONE); + actionMode.setItemVisibility(tag_message, getUserConfig().isPremium() ? View.VISIBLE : View.GONE); actionModeOtherItem.setSubItemVisibility(star, selectedMessagesCanStarIds[0].size() + selectedMessagesCanStarIds[1].size() != 0); boolean doShrinkActionBarItems = isActionBarTooNarrow && actionMode.getItem(edit).getVisibility() == View.VISIBLE && actionMode.getItem(copy).getVisibility() == View.VISIBLE && actionMode.getItem(delete).getVisibility() == View.VISIBLE; @@ -8335,6 +8960,170 @@ private void createActionMode() { } } + private void hideTagSelector() { + if (tagSelector == null) return; + final ReactionsContainerLayout thisTagSelector = tagSelector; + tagSelector = null; + thisTagSelector.dismissWindow(); + if (thisTagSelector.getReactionsWindow() != null && thisTagSelector.getReactionsWindow().containerView != null) { + thisTagSelector.getReactionsWindow().containerView.animate().alpha(0).setDuration(180).start(); + } + thisTagSelector.animate().alpha(0.01f).translationY(-dp(12)).scaleX(.7f).scaleY(.7f).withEndAction(() -> { + contentView.removeView(thisTagSelector); + }).setDuration(180).start(); + } + + private ReactionsContainerLayout tagSelector; + private void showTagSelector() { + if (getDialogId() != getUserConfig().getClientUserId() || !getUserConfig().isPremium()) return; + if (tagSelector != null) return; + tagSelector = new ReactionsContainerLayout(ReactionsContainerLayout.TYPE_TAGS, this, getContext(), currentAccount, themeDelegate) { + + private int[] loc = new int[2]; + + private ValueAnimator va; + private boolean firstLayout = true; + private void updateBubbleOffset(float x, boolean animated) { + if (va != null) { + va.cancel(); + va = null; + } + if (!animated) { + setBubbleOffset(x); + } else { + va = ValueAnimator.ofFloat(bubblesOffset, x); + va.addUpdateListener(anm -> { + setBubbleOffset((float) anm.getAnimatedValue()); + invalidate(); + }); + va.setInterpolator(CubicBezierInterpolator.EASE_OUT_QUINT); + va.setDuration(420); + va.start(); + } + } + + @Override + protected void onLayout(boolean changed, int left, int top, int right, int bottom) { + super.onLayout(changed, left, top, right, bottom); + final ActionBarMenu actionMode = actionBar.createActionMode(); + View item = actionMode.getItem(tag_message); + if (item != null) { + getLocationInWindow(loc); + float x = getX(); + float x2 = x + getWidth(); + item.getLocationInWindow(loc); + float cx = loc[0] + item.getWidth() / 2f + dp(20) * (LocaleController.isRTL ? -1 : 1); + + if (LocaleController.isRTL) { + updateBubbleOffset(cx - x, !firstLayout); + } else { + updateBubbleOffset(cx - x2, !firstLayout); + } + firstLayout = false; + } + } + }; + tagSelector.setPadding(AndroidUtilities.dp(4), AndroidUtilities.dp(24), AndroidUtilities.dp(4), AndroidUtilities.dp(0)); + tagSelector.setDelegate(new ReactionsContainerLayout.ReactionsContainerDelegate() { + @Override + public void onReactionClicked(View view, ReactionsLayoutInBubble.VisibleReaction visibleReaction, boolean longpress, boolean addToRecent) { + if (tagSelector == null) return; + if (getDialogId() == getUserConfig().getClientUserId() && !getUserConfig().isPremium()) { + new PremiumFeatureBottomSheet(ChatActivity.this, PremiumPreviewFragment.PREMIUM_FEATURE_SAVED_TAGS, true).show(); + clearSelectionMode(false); + return; + } + boolean updateFilteredMessages = false; + boolean notifyFilteredMessages = false; + boolean remove = tagSelector.getSelectedReactions().contains(visibleReaction); + HashSet groupsChecked = new HashSet<>(); + int messagesCount = 0; + for (int a = 0; a < selectedMessagesIds.length; ++a) { + for (int k = 0; k < selectedMessagesIds[a].size(); ++k) { + MessageObject messageObject = selectedMessagesIds[a].valueAt(k); + if (messageObject.hasValidGroupId()) { + MessageObject.GroupedMessages group = getValidGroupedMessage(messageObject); + if (group == null || groupsChecked.contains(group.groupId)) + continue; + groupsChecked.add(group.groupId); + messageObject = group.findPrimaryMessageObject(); + if (messageObject == null) continue; + } + if (messageObject.hasReaction(visibleReaction) == remove) { + selectReaction(messageObject, null, null, 0, 0, visibleReaction, false, false, false, true); + if (!remove) { + messagesCount++; + } + } + if (messageObject != null && messageObject.messageOwner != null) { + if (chatAdapter.isFiltered) { + MessageObject realMessage = messagesDict[0].get(messageObject.getId()); + if (realMessage != null && realMessage.messageOwner != null) { + realMessage.messageOwner.reactions = messageObject.messageOwner.reactions; + } + } else if (!chatAdapter.isFiltered && searchingReaction != null) { + updateFilteredMessages = true; + } + } + if (chatAdapter.isFiltered && !messageObject.hasReaction(searchingReaction)) { + final MessageObject msg = messageObject; + final MessageObject.GroupedMessages groupedMessages = getValidGroupedMessage(msg); + if (groupedMessages != null) { + for (int i = 0; i < groupedMessages.messages.size(); ++i) { + MessageObject gmsg = groupedMessages.messages.get(i); + getMediaDataController().removeMessageFromResults(gmsg.getId()); + } + } else { + getMediaDataController().removeMessageFromResults(msg.getId()); + } + if (messagesSearchAdapter != null) { + messagesSearchAdapter.notifyDataSetChanged(); + } + updateFilteredMessages = true; + notifyFilteredMessages = true; + } + } + } + if (updateFilteredMessages) { + updateFilteredMessages(notifyFilteredMessages); + } + clearSelectionMode(true); + + if (messagesCount > 0) { + TLRPC.Document document; + if (visibleReaction.documentId == 0) { + TLRPC.TL_availableReaction availableReaction = MediaDataController.getInstance(UserConfig.selectedAccount).getReactionsMap().get(visibleReaction.emojicon); + if (availableReaction == null) { + return; + } + document = availableReaction.activate_animation; + } else { + document = AnimatedEmojiDrawable.findDocument(UserConfig.selectedAccount, visibleReaction.documentId); + } + + if (document == null) { + return; + } + + BulletinFactory.of(ChatActivity.this).createMessagesTaggedBulletin(messagesCount, document, null).show(true); + } + } + }); + tagSelector.setTop(true); + tagSelector.setClipChildren(false); + tagSelector.setClipToPadding(false); + tagSelector.setVisibility(View.VISIBLE); + tagSelector.setHint(LocaleController.getString(tagSelector.getSelectedReactions().isEmpty() ? R.string.SavedTagReactionsSelectedAddHint : R.string.SavedTagReactionsSelectedEditHint)); + contentView.addView(tagSelector, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, 92.5f, Gravity.CENTER_HORIZONTAL | Gravity.TOP, 0, 0, 0, 0)); + tagSelector.setMessage(null, null); + tagSelector.setTranslationY(-dp(12)); + tagSelector.setScaleY(.4f); + tagSelector.setScaleX(.4f); + tagSelector.animate().scaleY(1f).scaleX(1f).translationY(0).setDuration(420).setInterpolator(CubicBezierInterpolator.EASE_OUT_QUINT).start(); + updateSelectedMessageReactions(); + tagSelector.setTranslationY(contentPanTranslation + (actionBarSearchTags != null ? actionBarSearchTags.getCurrentHeight() : 0)); + } + private void createSearchContainer() { if (searchContainer != null || getContext() == null) { return; @@ -8366,7 +9155,16 @@ protected void measureChildWithMargins(View child, int parentWidthMeasureSpec, i } super.measureChildWithMargins(child, parentWidthMeasureSpec, widthUsed, parentHeightMeasureSpec, heightUsed); } + + @Override + public void setVisibility(int visibility) { + super.setVisibility(visibility); + if (chatListView != null && isInsideContainer) { + chatListView.setPadding(chatListView.getPaddingLeft(), chatListView.getPaddingTop(), chatListView.getPaddingRight(), AndroidUtilities.dp(3) + blurredViewBottomOffset + (isInsideContainer && visibility == VISIBLE ? dp(50) : 0)); + } + } }; + searchContainer.setClickable(false); searchContainer.drawBlur = false; searchContainer.isTopView = false; searchContainer.setWillNotDraw(false); @@ -8374,53 +9172,46 @@ protected void measureChildWithMargins(View child, int parentWidthMeasureSpec, i searchContainer.setPadding(0, AndroidUtilities.dp(3), 0, 0); searchContainer.setClipToPadding(false); - searchAsListTogglerView = new View(getContext()); - searchAsListTogglerView.setOnTouchListener((v, event) -> getMediaDataController().getFoundMessageObjects().size() <= 1); - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { - searchAsListTogglerView.setBackground(Theme.getSelectorDrawable(getThemedColor(Theme.key_actionBarActionModeDefaultSelector), false)); - } - searchAsListTogglerView.setOnClickListener(v -> { - if (getMediaDataController().getFoundMessageObjects().size() > 1) { - if (searchAsListHint != null) { - searchAsListHint.hide(); - } - toggleMesagesSearchListView(); - if (!SharedConfig.searchMessagesAsListUsed) { - SharedConfig.setSearchMessagesAsListUsed(true); - } - } - }); - final float paddingTop = Theme.chat_composeShadowDrawable.getIntrinsicHeight() / AndroidUtilities.density - 3f; - searchContainer.addView(searchAsListTogglerView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, Gravity.NO_GRAVITY, 0, paddingTop, 0, 0)); - - searchUpButton = new ImageView(getContext()); - searchUpButton.setScaleType(ImageView.ScaleType.CENTER); - searchUpButton.setImageResource(R.drawable.msg_go_up); - searchUpButton.setColorFilter(new PorterDuffColorFilter(getThemedColor(Theme.key_chat_searchPanelIcons), PorterDuff.Mode.MULTIPLY)); - searchUpButton.setBackgroundDrawable(Theme.createSelectorDrawable(getThemedColor(Theme.key_actionBarActionModeDefaultSelector), 1)); - searchContainer.addView(searchUpButton, LayoutHelper.createFrame(48, 48, Gravity.RIGHT | Gravity.TOP, 0, 0, 48, 0)); - searchUpButton.setOnClickListener(view -> { - getMediaDataController().searchMessagesInChat(null, dialog_id, mergeDialogId, classGuid, 1, threadMessageId, searchingUserMessages, searchingChatMessages, searchingReaction); - showMessagesSearchListView(false); - if (!SharedConfig.searchMessagesAsListUsed && SharedConfig.searchMessagesAsListHintShows < 3 && !searchAsListHintShown && Math.random() <= 0.25) { - showSearchAsListHint(); - searchAsListHintShown = true; - SharedConfig.increaseSearchAsListHintShows(); - } + searchCountText = new AnimatedTextView(getContext(), true, true, true); + searchCountText.setAnimationProperties(.25f, 0, 280, CubicBezierInterpolator.EASE_OUT_QUINT); +// searchCountText.setScaleProperty(.5f); + searchCountText.setTextSize(dp(15)); + searchCountText.setTypeface(AndroidUtilities.getTypeface(AndroidUtilities.TYPEFACE_ROBOTO_MEDIUM)); + searchCountText.setTextColor(getThemedColor(Theme.key_chat_searchPanelText)); + searchCountText.setGravity(Gravity.LEFT); + searchContainer.addView(searchCountText, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, 30, Gravity.CENTER_VERTICAL, 0, -1, 97.33f, 0)); + contentView.addView(searchContainer, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, searchContainerHeight, Gravity.BOTTOM)); + + searchExpandList = new AnimatedTextView(getContext(), true, false, true); + searchExpandList.setAnimationProperties(0, 0, 420, CubicBezierInterpolator.EASE_OUT_QUINT); + searchExpandList.setScaleProperty(.7f); + searchExpandList.setTextSize(dp(15)); + searchExpandList.setGravity(Gravity.RIGHT); + searchExpandList.setTypeface(AndroidUtilities.getTypeface(AndroidUtilities.TYPEFACE_ROBOTO_MEDIUM)); + searchExpandList.setTextColor(getThemedColor(Theme.key_windowBackgroundWhiteBlueText2)); + searchExpandList.setText(LocaleController.getString(messagesSearchListView != null && messagesSearchListView.getTag() != null ? R.string.SearchAsChat : R.string.SearchAsList)); + searchExpandList.adaptWidth = false; + searchExpandList.setPadding(dp(15.33f), 0, dp(15.33f), 0); + searchExpandList.setOnClickListener(v -> { + toggleMesagesSearchListView(); }); - searchUpButton.setContentDescription(LocaleController.getString("AccDescrSearchNext", R.string.AccDescrSearchNext)); - - searchDownButton = new ImageView(getContext()); - searchDownButton.setScaleType(ImageView.ScaleType.CENTER); - searchDownButton.setImageResource(R.drawable.msg_go_down); - searchDownButton.setColorFilter(new PorterDuffColorFilter(getThemedColor(Theme.key_chat_searchPanelIcons), PorterDuff.Mode.MULTIPLY)); - searchDownButton.setBackgroundDrawable(Theme.createSelectorDrawable(getThemedColor(Theme.key_actionBarActionModeDefaultSelector), 1)); - searchContainer.addView(searchDownButton, LayoutHelper.createFrame(48, 48, Gravity.RIGHT | Gravity.TOP, 0, 0, 0, 0)); - searchDownButton.setOnClickListener(view -> { - getMediaDataController().searchMessagesInChat(null, dialog_id, mergeDialogId, classGuid, 2, threadMessageId, searchingUserMessages, searchingChatMessages, searchingReaction); - showMessagesSearchListView(false); + searchExpandList.setAlpha(0.5f); + searchExpandList.setClickable(false); + searchContainer.addView(searchExpandList, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.MATCH_PARENT, Gravity.RIGHT | Gravity.FILL_VERTICAL)); + + searchOtherButton = new AnimatedTextView(getContext(), true, true, true); + searchOtherButton.setGravity(Gravity.CENTER); + searchOtherButton.setTypeface(AndroidUtilities.getTypeface(AndroidUtilities.TYPEFACE_ROBOTO_MEDIUM)); + searchOtherButton.setTextColor(getThemedColor(Theme.key_chat_fieldOverlayText)); + searchOtherButton.setTextSize(AndroidUtilities.dp(15)); + searchOtherButton.setBackground(Theme.createSelectorWithBackgroundDrawable(getThemedColor(Theme.key_windowBackgroundWhite), Theme.blendOver(getThemedColor(Theme.key_windowBackgroundWhite), getThemedColor(Theme.key_listSelector)))); + searchOtherButton.setText(LocaleController.getString(chatAdapter.isFiltered ? R.string.SavedTagHideOtherMessages : R.string.SavedTagShowOtherMessages)); + searchOtherButton.setOnClickListener(v -> { + setFilterMessages(!chatAdapter.isFiltered); }); - searchDownButton.setContentDescription(LocaleController.getString("AccDescrSearchPrev", R.string.AccDescrSearchPrev)); + searchOtherButton.setVisibility(View.GONE); + searchOtherButton.setAlpha(0f); + searchContainer.addView(searchOtherButton, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, Gravity.FILL)); if (currentChat != null && (!ChatObject.isChannel(currentChat) || currentChat.megagroup)) { searchUserButton = new ImageView(getContext()); @@ -8452,7 +9243,7 @@ protected void measureChildWithMargins(View child, int parentWidthMeasureSpec, i searchCalendarButton.setImageResource(R.drawable.msg_calendar); searchCalendarButton.setColorFilter(new PorterDuffColorFilter(getThemedColor(Theme.key_chat_searchPanelIcons), PorterDuff.Mode.SRC_IN)); searchCalendarButton.setBackgroundDrawable(Theme.createSelectorDrawable(getThemedColor(Theme.key_actionBarActionModeDefaultSelector), 1)); - searchContainer.addView(searchCalendarButton, LayoutHelper.createFrame(48, 48, Gravity.LEFT | Gravity.TOP)); + searchContainer.addView(searchCalendarButton, LayoutHelper.createFrame(48, 48, Gravity.LEFT | Gravity.TOP, 2.66f, 0, 0, 0)); searchCalendarButton.setOnClickListener(view -> { if (getParentActivity() == null) { return; @@ -8467,39 +9258,13 @@ public void run(int param) { }); searchCalendarButton.setContentDescription(LocaleController.getString("JumpToDate", R.string.JumpToDate)); - // NekoX: go to the first message - searchGoToBeginningButton = new ImageView(getContext()); - searchGoToBeginningButton.setScaleType(ImageView.ScaleType.CENTER); - searchGoToBeginningButton.setImageResource(R.drawable.ic_upward); - searchGoToBeginningButton.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_chat_searchPanelIcons), PorterDuff.Mode.SRC_IN)); - searchGoToBeginningButton.setBackgroundDrawable(Theme.createSelectorDrawable(Theme.getColor(Theme.key_actionBarActionModeDefaultSelector), 1)); - searchContainer.addView(searchGoToBeginningButton, LayoutHelper.createFrame(48, 48, Gravity.RIGHT | Gravity.TOP, 0, 0, 48 * 2, 0)); - searchGoToBeginningButton.setOnClickListener(view -> { - scrollToMessageId(1, 0, false, 0, true, 0); - }); - searchGoToBeginningButton.setContentDescription(LocaleController.getString("GoToBeginning", R.string.GoToBeginning)); - - searchCountText = new SearchCounterView(getContext(), themeDelegate); - searchCountText.setGravity(Gravity.LEFT); - searchContainer.addView(searchCountText, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.CENTER_VERTICAL, 0, 0, 108, 0)); - contentView.addView(searchContainer, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, searchContainerHeight, Gravity.BOTTOM)); - - searchOtherButton = new AnimatedTextView(getContext(), true, true, true); - searchOtherButton.setGravity(Gravity.CENTER); - searchOtherButton.setTypeface(AndroidUtilities.getTypeface(AndroidUtilities.TYPEFACE_ROBOTO_MEDIUM)); - searchOtherButton.setTextColor(getThemedColor(Theme.key_chat_fieldOverlayText)); - searchOtherButton.setTextSize(AndroidUtilities.dp(15)); - searchOtherButton.setBackground(Theme.createSelectorWithBackgroundDrawable(getThemedColor(Theme.key_windowBackgroundWhite), Theme.blendOver(getThemedColor(Theme.key_windowBackgroundWhite), getThemedColor(Theme.key_listSelector)))); - searchOtherButton.setVisibility(View.GONE); - searchOtherButton.setAlpha(0f); - searchContainer.addView(searchOtherButton, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, Gravity.FILL)); } private void showSearchShowOther(boolean show) { searchOtherButton.setVisibility(View.VISIBLE); searchOtherButton.animate().alpha(show ? 1f : 0f).withEndAction(() -> { searchOtherButton.setVisibility(show ? View.VISIBLE : View.GONE); - }).start(); + }).setDuration(170).start(); } public void onPageDownClicked() { @@ -8673,7 +9438,7 @@ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { private boolean filledEditTextItemMenu = false; private void checkEditTextItemMenu() { - if (filledEditTextItemMenu) { + if (filledEditTextItemMenu || editTextItem == null) { return; } @@ -8713,13 +9478,19 @@ private void checkEditTextItemMenu() { private void updatePagedownButtonsPosition() { float baseTranslationY = chatActivityEnterView.getAnimatedTop() + chatActivityEnterView.getTranslationY() + (chatActivityEnterTopView.getVisibility() == View.VISIBLE ? chatActivityEnterTopView.getTranslationY() : 0); if (pagedownButton != null) { - pagedownButton.setTranslationY(baseTranslationY + AndroidUtilities.dp(100) * (1f - pagedownButtonEnterProgress)); + pagedownButton.setTranslationY(baseTranslationY + dp(100) * (1f - pagedownButtonEnterProgress)); + } + if (searchUpButton != null) { + searchUpButton.setTranslationY(baseTranslationY - dp(51.33f) * searchUpDownEnterProgress + dp(100) * (1f - searchUpDownEnterProgress)); + } + if (searchDownButton != null) { + searchDownButton.setTranslationY(baseTranslationY + dp(100) * (1f - searchUpDownEnterProgress)); } if (mentiondownButton != null) { - mentiondownButton.setTranslationY(baseTranslationY + AndroidUtilities.dp(100) * (1f - mentionsButtonEnterProgress) - (AndroidUtilities.dp(72) * pagedownButtonEnterProgress) * mentionsButtonEnterProgress); + mentiondownButton.setTranslationY(baseTranslationY + dp(100) * (1f - mentionsButtonEnterProgress) - (dp(72) * pagedownButtonEnterProgress) * mentionsButtonEnterProgress); } if (reactionsMentiondownButton != null) { - reactionsMentiondownButton.setTranslationY(baseTranslationY + AndroidUtilities.dp(100) * (1f - reactionsMentionButtonEnterProgress) - ((AndroidUtilities.dp(50) + AndroidUtilities.dp(22) * pagedownButtonCounter.getEnterProgress()) * pagedownButtonEnterProgress + AndroidUtilities.dp(72) * mentionsButtonEnterProgress) * reactionsMentionButtonEnterProgress); + reactionsMentiondownButton.setTranslationY(baseTranslationY + dp(100) * (1f - reactionsMentionButtonEnterProgress) - ((dp(50) + dp(22) * pagedownButtonCounter.getEnterProgress()) * pagedownButtonEnterProgress + dp(72) * mentionsButtonEnterProgress) * reactionsMentionButtonEnterProgress); } if (suggestEmojiPanel != null) { suggestEmojiPanel.setTranslationY(baseTranslationY); @@ -9073,7 +9844,7 @@ private void searchUserMessages(TLRPC.User user, TLRPC.Chat chat) { mentionContainer.getAdapter().searchUsernameOrHashtag(null, 0, null, false, true); searchItem.setSearchFieldHint(null); searchItem.clearSearchText(); - getMediaDataController().searchMessagesInChat("", dialog_id, mergeDialogId, classGuid, 0, threadMessageId, searchingUserMessages, searchingChatMessages, searchingReaction); + getMediaDataController().searchMessagesInChat(searchingQuery = "", dialog_id, mergeDialogId, classGuid, 0, threadMessageId, searchingUserMessages, searchingChatMessages, searchingReaction); } private void updateTranslateItemVisibility() { @@ -9728,6 +10499,7 @@ private boolean getLiteModeChat() { return liteModeChat; } + private void showProgressView(boolean show) { if (progressView == null) { return; @@ -9819,6 +10591,9 @@ private void updateChatListViewTopPadding() { if (isThreadChat() && (!isTopic || pinnedOnlyStarterMessage())) { pinnedViewH = 0; } + if (actionBarSearchTags != null) { + pinnedViewH = Math.max(pinnedViewH, actionBarSearchTags.getCurrentHeight()); + } float pendingViewH = 0; View pendingRequestsView = pendingRequestsDelegate != null ? pendingRequestsDelegate.getView() : null; if (pendingRequestsView != null && pendingRequestsView.getVisibility() == View.VISIBLE) { @@ -9830,9 +10605,6 @@ private void updateChatListViewTopPadding() { chatListViewPaddingVisibleOffset = 0; chatListViewPaddingTop += contentPanTranslation + bottomPanelTranslationY; float searchExpandOffset = 0; - if (actionBarSearchTags != null && actionBarSearchTags.shown()) { - chatListViewPaddingTop += actionBarSearchTags.getMeasuredHeight(); - } if (searchExpandProgress != 0 && chatActivityEnterView.getVisibility() == View.VISIBLE) { chatListViewPaddingTop -= (searchExpandOffset = searchExpandProgress * (chatActivityEnterView.getMeasuredHeight() - AndroidUtilities.dp(searchContainerHeight))); } @@ -9860,7 +10632,7 @@ private void updateChatListViewTopPadding() { floatingDateView.setTranslationY(chatListView.getTranslationY() - searchExpandOffset + chatListViewPaddingTop + floatingDateViewOffset - AndroidUtilities.dp(4)); } - int p = isInsideContainer ? 0 : chatListView.getMeasuredHeight() * 2 / 3; + int p = isInsideContainer ? dp(4) : chatListView.getMeasuredHeight() * 2 / 3; if (chatListView != null && chatLayoutManager != null && chatAdapter != null) { if (chatListView.getPaddingTop() != p) { @@ -9879,7 +10651,7 @@ private void updateChatListViewTopPadding() { } } - chatListView.setPadding(0, p, 0, AndroidUtilities.dp(3) + blurredViewBottomOffset); + chatListView.setPadding(0, p, 0, AndroidUtilities.dp(3) + blurredViewBottomOffset + (isInsideContainer && searchContainer != null && searchContainer.getVisibility() == View.VISIBLE ? dp(50) : 0)); if (scrollToMessageObject != null) { chatAdapter.updateRowsSafe(); @@ -9941,25 +10713,26 @@ private void invalidateChatListViewTopPadding() { translation += pendingRequestsDelegate.getViewEnterOffset(); pendingRequestsView.setTranslationY(translation); } + float p = actionBarSearchTags != null ? actionBarSearchTags.getCurrentHeight() : 0; if (fragmentContextView != null) { float from = 0; if (fragmentLocationContextView != null && fragmentLocationContextView.getVisibility() == View.VISIBLE) { from += AndroidUtilities.dp(36); } - fragmentContextView.setTranslationY(contentPanTranslation + from + fragmentContextView.getTopPadding()); + fragmentContextView.setTranslationY(contentPanTranslation + p + from + fragmentContextView.getTopPadding()); } if (fragmentLocationContextView != null) { float from = 0; if (fragmentContextView != null && fragmentContextView.getVisibility() == View.VISIBLE) { from += AndroidUtilities.dp(fragmentContextView.getStyleHeight()) + fragmentContextView.getTopPadding(); } - fragmentLocationContextView.setTranslationY(contentPanTranslation + from + fragmentLocationContextView.getTopPadding()); + fragmentLocationContextView.setTranslationY(contentPanTranslation + p + from + fragmentLocationContextView.getTopPadding()); } if (topChatPanelView != null) { - topChatPanelView.setTranslationY(contentPanTranslation + contentPaddingTop + topChatPanelViewOffset); + topChatPanelView.setTranslationY(contentPanTranslation + p + contentPaddingTop + topChatPanelViewOffset); } if (alertView != null && alertView.getVisibility() == View.VISIBLE) { - alertView.setTranslationY(contentPanTranslation + contentPaddingTop - AndroidUtilities.dp(50) * (1f - alertViewEnterProgress)); + alertView.setTranslationY(contentPanTranslation + p + contentPaddingTop - AndroidUtilities.dp(50) * (1f - alertViewEnterProgress)); } if (bottomOverlayChat != null) { bottomOverlayChat.setTranslationY(bottomPanelTranslationYReverse); @@ -10349,7 +11122,7 @@ private MessageObject.GroupedMessages getValidGroupedMessage(MessageObject messa MessageObject.GroupedMessages groupedMessages = null; if (message.getGroupId() != 0) { groupedMessages = groupedMessagesMap.get(message.getGroupId()); - if (groupedMessages != null && (groupedMessages.messages.size() <= 1 || groupedMessages.positions.get(message) == null)) { + if (groupedMessages != null && (groupedMessages.messages.size() <= 1 || groupedMessages.getPosition(message) == null)) { groupedMessages = null; } } @@ -10397,6 +11170,7 @@ public void jumpToDate(int date) { progressDialog.showDelayed(1000); postponedScrollToLastMessageQueryIndex = lastLoadIndex; + fakePostponedScroll = false; waitingForLoad.add(lastLoadIndex); postponedScrollMessageId = 0; postponedScrollIsCanceled = false; @@ -10597,7 +11371,7 @@ public void onEditTextDialogClose(boolean resetAdjust, boolean reset) { openKeyboardOnAttachMenuClose = false; } } - if (resetAdjust) { + if (resetAdjust && !isInsideContainer) { AndroidUtilities.requestAdjustResize(getParentActivity(), classGuid); } } @@ -10713,6 +11487,7 @@ private void showMessagesSearchListView(boolean show) { messagesSearchListView.setVisibility(View.VISIBLE); } messagesSearchListView.setTag(show ? 1 : null); + messagesSearchListView.setPadding(0, actionBarSearchTags != null ? actionBarSearchTags.getHeight() : 0, 0, 0); messagesSearchListViewAnimation = new AnimatorSet(); messagesSearchListViewAnimation.playTogether(ObjectAnimator.ofFloat(messagesSearchListView, View.ALPHA, show ? 1.0f : 0.0f)); messagesSearchListViewAnimation.setInterpolator(CubicBezierInterpolator.EASE_IN); @@ -10736,7 +11511,12 @@ public void onAnimationCancel(Animator animation) { } }); messagesSearchListViewAnimation.start(); - + if (searchExpandList != null) { + searchExpandList.setText(LocaleController.getString(messagesSearchListView != null && messagesSearchListView.getTag() != null ? R.string.SearchAsChat : R.string.SearchAsList), !LocaleController.isRTL); + } + if (savedMessagesTagHint != null && savedMessagesTagHint.shown()) { + savedMessagesTagHint.hide(); + } } public boolean playFirstUnreadVoiceMessage() { @@ -10964,9 +11744,6 @@ private void hideHints(boolean scroll) { if (slowModeHint != null) { slowModeHint.hide(); } - if (searchAsListHint != null) { - searchAsListHint.hide(); - } if (scheduledOrNoSoundHint != null) { scheduledOrNoSoundHint.hide(); } @@ -11041,20 +11818,6 @@ public void showTimerHint() { timerHintView.showForView(avatarContainer.getTimeItem(), true); } - private void showSearchAsListHint() { - if (getParentActivity() == null || fragmentView == null || searchCountText == null) { - return; - } - if (searchAsListHint == null) { - searchAsListHint = new HintView(getParentActivity(), HintView.TYPE_SEARCH_AS_LIST, themeDelegate); - searchAsListHint.setAlpha(0.0f); - searchAsListHint.setVisibility(View.INVISIBLE); - searchAsListHint.setText(LocaleController.getString("TapToViewAsList", R.string.TapToViewAsList)); - contentView.addView(searchAsListHint, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.LEFT | Gravity.TOP, 19, 0, 19, 0)); - } - searchAsListHint.showForView(searchCountText, true); - } - private void showScheduledHint() { boolean disableNoSound = (UserObject.isUserSelf(currentUser) || (chatInfo != null && chatInfo.slowmode_next_send_date > 0) && chatMode == 0); if (scheduledHintShown || scheduledOrNoSoundHintShown || disableNoSound || SharedConfig.scheduledHintShows >= 3 || chatActivityEnterView.isEditingMessage()) { @@ -11552,11 +12315,8 @@ private void checkScrollForLoad(boolean scroll) { if (chatLayoutManager == null || paused || chatAdapter.isFrozen || waitingForGetDifference) { return; } - if (chatAdapter.isFiltered) { - getMediaDataController().loadMoreSearchMessages(); - return; - } int firstVisibleItem = RecyclerListView.NO_POSITION; + int lastVisibleItem = RecyclerListView.NO_POSITION; int visibleItemCount = 0; for (int i = 0; i < chatListView.getChildCount(); i++) { int position = chatListView.getChildAdapterPosition(chatListView.getChildAt(i)); @@ -11564,9 +12324,18 @@ private void checkScrollForLoad(boolean scroll) { if (firstVisibleItem == RecyclerListView.NO_POSITION || position < firstVisibleItem) { firstVisibleItem = position; } + if (lastVisibleItem == RecyclerListView.NO_POSITION || position > lastVisibleItem) { + lastVisibleItem = position; + } visibleItemCount++; } } + if (chatAdapter.isFiltered) { + if (chatAdapter.loadingUpRow >= 0 && firstVisibleItem >= 0 && chatAdapter.loadingUpRow >= firstVisibleItem && chatAdapter.loadingUpRow <= lastVisibleItem) { + getMediaDataController().loadMoreSearchMessages(false); + } + return; + } final int firstVisibleItemFinal = firstVisibleItem; final int visibleItemCountFinal = visibleItemCount; int totalItemCount = chatAdapter.getItemCount(); @@ -13056,9 +13825,10 @@ private Runnable sendSecretMediaDelete(MessageObject messageObject) { return () -> getMessagesController().doDeleteShowOnceTask(taskId, dialog_id, messageObject.getId()); } - private void clearChatData() { + private void clearChatData(boolean full) { messages.clear(); messagesByDays.clear(); + messagesByDaysSorted.clear(); waitingForLoad.clear(); groupedMessagesMap.clear(); threadMessageAdded = false; @@ -13084,10 +13854,12 @@ private void clearChatData() { cacheEndReached[a] = false; forwardEndReached[a] = true; } - first = true; - firstLoading = true; - loading = true; - loadingForward = false; + if (full) { + first = true; + firstLoading = true; + loading = true; + loadingForward = false; + } waitingForReplyMessageLoad = false; startLoadFromMessageId = 0; showScrollToMessageError = false; @@ -13096,7 +13868,7 @@ private void clearChatData() { createUnreadMessageAfterId = 0; createUnreadMessageAfterIdLoading = false; needSelectFromMessageId = false; - if (chatAdapter != null) { + if (chatAdapter != null && !chatAdapter.isFiltered) { chatAdapter.notifyDataSetChanged(false); } } @@ -13174,6 +13946,7 @@ public void scrollToLastMessage(boolean skipSponsored, boolean top, Runnable inC } postponedScrollToLastMessageQueryIndex = lastLoadIndex; + fakePostponedScroll = false; postponedScrollMessageId = 0; postponedScrollIsCanceled = false; waitingForLoad.clear(); @@ -13605,7 +14378,9 @@ public void updateMessagesVisiblePart(boolean inLayout) { } else { messageObject = ((ChatActionCell) minMessageChild).getMessageObject(); } - floatingDateView.setCustomDate(messageObject.messageOwner.date, chatMode == MODE_SCHEDULED, true); + if (messageObject != null && messageObject.messageOwner != null) { + floatingDateView.setCustomDate(messageObject.messageOwner.date, chatMode == MODE_SCHEDULED, true); + } } currentFloatingDateOnScreen = false; currentFloatingTopIsNotMessage = !(minChild instanceof ChatMessageCell || minChild instanceof ChatActionCell); @@ -14008,7 +14783,7 @@ public void scrollToMessageId(int id, int fromMessageId, boolean select, int loa forceNextPinnedMessageId = Math.abs(forcePinnedMessageId); forceScrollToFirst = forcePinnedMessageId > 0; wasManualScroll = true; - MessageObject object = messagesDict[loadIndex].get(id); + MessageObject object = chatAdapter.isFiltered ? (filteredMessagesDict != null ? filteredMessagesDict.get(id) : null) : messagesDict[loadIndex].get(id); boolean query = false; int scrollDirection = RecyclerAnimationScrollHelper.SCROLL_DIRECTION_UNSET; int scrollFromIndex = 0; @@ -14018,14 +14793,14 @@ public void scrollToMessageId(int id, int fromMessageId, boolean select, int loa scrollDown = !scrollDown; } scrollDirection = scrollDown ? RecyclerAnimationScrollHelper.SCROLL_DIRECTION_DOWN : RecyclerAnimationScrollHelper.SCROLL_DIRECTION_UP; - } else if (messages.size() > 0) { + } else if (chatAdapter.getMessages().size() > 0) { if (isThreadChat() && id == threadMessageId) { scrollDirection = RecyclerAnimationScrollHelper.SCROLL_DIRECTION_UP; } else { int end = chatLayoutManager.findLastVisibleItemPosition(); for (int i = chatLayoutManager.findFirstVisibleItemPosition(); i <= end; i++) { if (i >= chatAdapter.messagesStartRow && i < chatAdapter.messagesEndRow) { - MessageObject messageObject = messages.get(i - chatAdapter.messagesStartRow); + MessageObject messageObject = chatAdapter.getMessages().get(i - chatAdapter.messagesStartRow); if (messageObject.getId() == 0 || messageObject.isSponsored()) { continue; } @@ -14051,7 +14826,7 @@ public void scrollToMessageId(int id, int fromMessageId, boolean select, int loa } } - int index = messages.indexOf(object); + int index = chatAdapter.getMessages().indexOf(object); if (index != -1) { if (scrollFromIndex > 0) { scrollDirection = scrollFromIndex > index ? RecyclerAnimationScrollHelper.SCROLL_DIRECTION_DOWN : RecyclerAnimationScrollHelper.SCROLL_DIRECTION_UP; @@ -14063,7 +14838,7 @@ public void scrollToMessageId(int id, int fromMessageId, boolean select, int loa } chatAdapter.updateRowsSafe(); - int position = chatAdapter.messagesStartRow + messages.indexOf(object); + int position = chatAdapter.messagesStartRow + chatAdapter.getMessages().indexOf(object); updateVisibleRows(); boolean found = false; @@ -14155,11 +14930,10 @@ public void scrollToMessageId(int id, int fromMessageId, boolean select, int loa postponedScrollIsCanceled = false; waitingForLoad.add(lastLoadIndex); postponedScrollToLastMessageQueryIndex = lastLoadIndex; + fakePostponedScroll = false; postponedScrollMinMessageId = minMessageId[0]; postponedScrollMessageId = id; - AndroidUtilities.runOnUIThread(() -> { - getMessagesController().loadMessages(loadIndex == 0 ? dialog_id : mergeDialogId, 0, false, ((isThreadChat() && !isTopic) || AndroidUtilities.isTablet()) ? 30 : 20, startLoadFromMessageId, 0, true, 0, classGuid, 3, 0, chatMode, threadMessageId, replyMaxReadId, lastLoadIndex++, isTopic); - }, SCROLL_DEBUG_DELAY ? 7500 : 0); + getMessagesController().loadMessages(loadIndex == 0 ? dialog_id : mergeDialogId, 0, false, ((isThreadChat() && !isTopic) || AndroidUtilities.isTablet()) ? 30 : 20, startLoadFromMessageId, 0, true, 0, classGuid, 3, 0, chatMode, threadMessageId, replyMaxReadId, lastLoadIndex++, isTopic); } else { View child = chatListView.getChildAt(0); if (child != null && child.getTop() <= 0) { @@ -14196,7 +14970,7 @@ private void updatePagedownButtonVisibility(boolean animated) { if (pagedownButton == null) { return; } - boolean show = canShowPagedownButton && !textSelectionHelper.isInSelectionMode() && !chatActivityEnterView.isRecordingAudioVideo() && !isInsideContainer; + boolean show = canShowPagedownButton && !textSelectionHelper.isInSelectionMode() && !chatActivityEnterView.isRecordingAudioVideo() && !isInsideContainer && (!searching || getMediaDataController().searchResultMessages.isEmpty()); if (show) { if (animated && (openAnimationStartTime == 0 || SystemClock.elapsedRealtime() < openAnimationStartTime + 150)) { animated = false; @@ -14267,6 +15041,76 @@ public void onAnimationEnd(Animator animation) { } } + private void updateSearchUpDownButtonVisibility(boolean animated) { + if (searchUpButton == null || searchDownButton == null) { + return; + } + boolean show = !getMediaDataController().searchResultMessages.isEmpty() && searching && !searchingFiltered; + if (show) { + if (searchUpButton.getTag() == null) { + if (searchUpButtonAnimation != null) { + searchUpButtonAnimation.removeAllListeners(); + searchUpButtonAnimation.cancel(); + searchUpButtonAnimation = null; + } + if (animated) { + searchUpButton.setVisibility(View.VISIBLE); + searchDownButton.setVisibility(View.VISIBLE); + searchUpButton.setTag(1); + searchUpButtonAnimation = ValueAnimator.ofFloat(searchUpDownEnterProgress, 1f); + searchUpButtonAnimation.addUpdateListener(valueAnimator -> { + searchUpDownEnterProgress = (float) valueAnimator.getAnimatedValue(); + contentView.invalidate(); + }); + searchUpButtonAnimation.addListener(new AnimatorListenerAdapter() { + @Override + public void onAnimationEnd(Animator animation) { + searchUpDownEnterProgress = 1f; + contentView.invalidate(); + } + }); + searchUpButtonAnimation.setDuration(200); + searchUpButtonAnimation.start(); + } else { + searchUpDownEnterProgress = 1f; + contentView.invalidate(); + } + } + } else { + returnToMessageId = 0; + if (searchUpButton.getTag() != null) { + searchUpButton.setTag(null); + if (searchUpButtonAnimation != null) { + searchUpButtonAnimation.removeAllListeners(); + searchUpButtonAnimation.cancel(); + searchUpButtonAnimation = null; + } + if (animated) { + searchUpButtonAnimation = ValueAnimator.ofFloat(searchUpDownEnterProgress, 0f); + searchUpButtonAnimation.addUpdateListener(valueAnimator -> { + searchUpDownEnterProgress = (float) valueAnimator.getAnimatedValue(); + contentView.invalidate(); + }); + searchUpButtonAnimation.addListener(new AnimatorListenerAdapter() { + @Override + public void onAnimationEnd(Animator animation) { + searchUpDownEnterProgress = 0f; + searchUpButton.setVisibility(View.INVISIBLE); + searchDownButton.setVisibility(View.INVISIBLE); + contentView.invalidate(); + } + }); + searchUpButtonAnimation.setDuration(200); + searchUpButtonAnimation.start(); + } else { + searchUpDownEnterProgress = 0f; + searchUpButton.setVisibility(View.INVISIBLE); + searchDownButton.setVisibility(View.INVISIBLE); + } + } + } + } + private void showMentionDownButton(boolean show, boolean animated) { if (mentiondownButton == null) { return; @@ -14382,6 +15226,15 @@ protected void onPanTranslationUpdate(float y, float progress, boolean keyboardV setNonNoveTranslation(y); } else { actionBar.setTranslationY(y); + if (tagSelector != null) { + tagSelector.setTranslationY(contentPanTranslation + (actionBarSearchTags != null ? actionBarSearchTags.getCurrentHeight() : 0)); + } + if (savedMessagesSearchHint != null) { + savedMessagesSearchHint.setTranslationY(y); + } + if (savedMessagesHint != null) { + savedMessagesHint.setTranslationY(y); + } if (actionBarSearchTags != null) { actionBarSearchTags.setTranslationY(y); } @@ -14425,7 +15278,7 @@ protected void onPanTranslationUpdate(float y, float progress, boolean keyboardV @Override protected boolean heightAnimationEnabled() { INavigationLayout actionBarLayout = getParentLayout(); - if (inPreviewMode || inBubbleMode || AndroidUtilities.isInMultiwindow || actionBarLayout == null || fixedKeyboardHeight > 0) { + if (isInsideContainer || inPreviewMode || inBubbleMode || AndroidUtilities.isInMultiwindow || actionBarLayout == null || fixedKeyboardHeight > 0) { return false; } if (System.currentTimeMillis() - activityResumeTime < 250) { @@ -14521,7 +15374,9 @@ protected float getListTranslationY() { @Override protected void onAttachedToWindow() { super.onAttachedToWindow(); - if (parentLayout != null && parentLayout.isSheet()) { + if (isInsideContainer) { + adjustPanLayoutHelper.setResizableView(contentView); + } else if (parentLayout != null && parentLayout.isSheet()) { adjustPanLayoutHelper.setResizableView((FrameLayout) parentLayout.getView().getParent().getParent().getParent().getParent()); } adjustPanLayoutHelper.onAttach(); @@ -14661,7 +15516,7 @@ protected void onDraw(Canvas canvas) { @Override protected boolean drawChild(Canvas canvas, View child, long drawingTime) { - if ((scrimView != null || messageEnterTransitionContainer.isRunning()) && (child == pagedownButton || child == mentiondownButton || child == floatingDateView || child == fireworksOverlay || child == reactionsMentiondownButton || child == gifHintTextView || child == emojiHintTextView || child == undoView || child == topUndoView)) { + if ((scrimView != null || messageEnterTransitionContainer.isRunning()) && (child == pagedownButton || child == searchUpButton || child == searchDownButton || child == mentiondownButton || child == floatingDateView || child == fireworksOverlay || child == reactionsMentiondownButton || child == gifHintTextView || child == emojiHintTextView || child == undoView || child == topUndoView)) { return false; } if (child == fragmentContextView && fragmentContextView.isCallStyle()) { @@ -14855,6 +15710,11 @@ protected void dispatchDraw(Canvas canvas) { scrimPaint.setAlpha((int) (255 * scrimPaintAlpha * (scrimView != null ? scrimViewAlpha : 1f))); canvas.drawRect(0, 0, getMeasuredWidth(), getMeasuredHeight(), scrimPaint); } + + if (scrimViewReaction != null && scrimViewReactionAnimated) { + invalidate(); + } + if (scrimView != null) { if (scrimView == reactionsMentiondownButton || scrimView == mentiondownButton) { if (scrimViewAlpha < 1f) { @@ -15012,7 +15872,7 @@ protected void dispatchDraw(Canvas canvas) { drawCaptionAfter.add(cell); } } - if (scrimViewReaction != null && cell != null) { + if (scrimViewReaction != null && cell != null && scrimGroup == null) { scrimPaint.setAlpha((int) (255 * scrimPaintAlpha * scrimViewAlpha)); canvas.drawRect(0, 0, getMeasuredWidth(), getMeasuredHeight(), scrimPaint); @@ -15045,6 +15905,10 @@ protected void dispatchDraw(Canvas canvas) { } drawNamesAfter.clear(); } + if (scrimViewReaction != null && scrimGroup != null) { + scrimPaint.setAlpha((int) (255 * scrimPaintAlpha * scrimViewAlpha)); + canvas.drawRect(0, 0, getMeasuredWidth(), getMeasuredHeight(), scrimPaint); + } size = drawCaptionAfter.size(); if (size > 0) { for (int a = 0; a < size; a++) { @@ -15094,6 +15958,9 @@ protected void dispatchDraw(Canvas canvas) { if (topUndoView != null && topUndoView.getVisibility() == View.VISIBLE) { super.drawChild(canvas, topUndoView, SystemClock.uptimeMillis()); } + if (savedMessagesTagHint != null && savedMessagesTagHint.getVisibility() == View.VISIBLE) { + super.drawChild(canvas, savedMessagesTagHint, SystemClock.uptimeMillis()); + } } if (fixedKeyboardHeight > 0 && keyboardHeight < AndroidUtilities.dp(20)) { @@ -15148,9 +16015,7 @@ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { if (lastWidth != widthSize) { globalIgnoreLayout = false; lastWidth = widthMeasureSpec; - if (chatMode == MODE_SAVED) { - showSearchAsIcon = false; - } else if (!inPreviewMode && currentUser != null && currentUser.self) { + if (!inPreviewMode && currentUser != null && currentUser.self) { SimpleTextView textView = avatarContainer.getTitleTextView(); int textWidth = (int) textView.getPaint().measureText(textView.getText(), 0, textView.getText().length()); if (widthSize - AndroidUtilities.dp(96 + 56) > textWidth + AndroidUtilities.dp(10)) { @@ -15163,7 +16028,7 @@ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { } if (showSearchAsIcon || showAudioCallAsIcon) { if (avatarContainer != null && avatarContainer.getLayoutParams() != null) { - ((ViewGroup.MarginLayoutParams) avatarContainer.getLayoutParams()).rightMargin = AndroidUtilities.dp(96); + ((ViewGroup.MarginLayoutParams) avatarContainer.getLayoutParams()).rightMargin = AndroidUtilities.dp(chatMode == MODE_SAVED ? 40 : 96); } } else { if (avatarContainer != null && avatarContainer.getLayoutParams() != null) { @@ -15284,7 +16149,7 @@ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { child.measure(contentWidthSpec, contentHeightSpec); } else if (child == blurredView) { int h = allHeight; - if (keyboardSize > AndroidUtilities.dp(20) && getLayoutParams().height < 0) { + if (keyboardSize > AndroidUtilities.dp(20) && getLayoutParams().height < 0 && !isInsideContainer) { h += keyboardSize; } int contentWidthSpec = View.MeasureSpec.makeMeasureSpec(widthSize, View.MeasureSpec.EXACTLY); @@ -15293,7 +16158,7 @@ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { } else if (child == chatListView || child == chatListThanosEffect) { int contentWidthSpec = View.MeasureSpec.makeMeasureSpec(widthSize, View.MeasureSpec.EXACTLY); int h = heightSize - listViewTopHeight - (inPreviewMode && Build.VERSION.SDK_INT >= 21 ? AndroidUtilities.statusBarHeight : 0) + blurredViewTopOffset + blurredViewBottomOffset; - if (keyboardSize > AndroidUtilities.dp(20) && getLayoutParams().height < 0) { + if (keyboardSize > AndroidUtilities.dp(20) && getLayoutParams().height < 0 && !isInsideContainer) { h += keyboardSize; } if (bottomOverlay != null && bottomOverlay.getVisibility() == View.VISIBLE && bottomOverlayStartButton != null && bottomOverlayStartButton.getVisibility() != View.GONE) { @@ -15315,7 +16180,7 @@ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { child.measure(contentWidthSpec, contentHeightSpec); } else if (child == messagesSearchListView) { int contentWidthSpec = View.MeasureSpec.makeMeasureSpec(widthSize, View.MeasureSpec.EXACTLY); - int contentHeightSpec = View.MeasureSpec.makeMeasureSpec(allHeight - actionBarHeight - AndroidUtilities.dp(48), View.MeasureSpec.EXACTLY); + int contentHeightSpec = View.MeasureSpec.makeMeasureSpec(allHeight - (isInsideContainer ? 0 : actionBarHeight) - AndroidUtilities.dp(48), View.MeasureSpec.EXACTLY); child.measure(contentWidthSpec, contentHeightSpec); } else if (chatActivityEnterView.isPopupView(child)) { int height = chatActivityEnterView.getPopupViewHeight(child); @@ -15377,7 +16242,7 @@ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { } else if (child == textSelectionHelper.getOverlayView(getContext())) { int contentWidthSpec = View.MeasureSpec.makeMeasureSpec(widthSize, View.MeasureSpec.EXACTLY); int h = heightSize + blurredViewTopOffset; - if (keyboardSize > AndroidUtilities.dp(20) && getLayoutParams().height < 0) { + if (keyboardSize > AndroidUtilities.dp(20) && getLayoutParams().height < 0 && !isInsideContainer) { h += keyboardSize; textSelectionHelper.setKeyboardSize(keyboardSize); } else { @@ -15387,7 +16252,7 @@ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { } else if (child instanceof MessagePreviewView) { int contentWidthSpec = View.MeasureSpec.makeMeasureSpec(widthSize, View.MeasureSpec.EXACTLY); int h = allHeight - AndroidUtilities.statusBarHeight; - if (keyboardSize > AndroidUtilities.dp(20) && getLayoutParams().height < 0) { + if (keyboardSize > AndroidUtilities.dp(20) && getLayoutParams().height < 0 && !isInsideContainer) { h += keyboardSize; } int contentHeightSpec = View.MeasureSpec.makeMeasureSpec(h, View.MeasureSpec.EXACTLY); @@ -15423,6 +16288,12 @@ public void requestLayout() { super.requestLayout(); } + @Override + public int getKeyboardHeight() { + if (isInsideContainer) return 0; + return super.getKeyboardHeight(); + } + @Override protected void onLayout(boolean changed, int l, int t, int r, int b) { final int count = getChildCount(); @@ -15495,7 +16366,7 @@ protected void onLayout(boolean changed, int l, int t, int r, int b) { } else if (child == mentionContainer) { childTop -= chatActivityEnterView.getMeasuredHeight() - AndroidUtilities.dp(2); mentionContainer.setTranslationY(chatActivityEnterView.getAnimatedTop()); - } else if (child == pagedownButton || child == mentiondownButton || child == reactionsMentiondownButton) { + } else if (child == pagedownButton || child == searchUpButton || child == searchDownButton || child == mentiondownButton || child == reactionsMentiondownButton) { if (!inPreviewMode) { childTop -= chatActivityEnterView.getMeasuredHeight(); } @@ -15559,6 +16430,15 @@ protected void onLayout(boolean changed, int l, int t, int r, int b) { private void setNonNoveTranslation(float y) { contentView.setTranslationY(y); actionBar.setTranslationY(0); + if (tagSelector != null) { + tagSelector.setTranslationY((actionBarSearchTags != null ? actionBarSearchTags.getCurrentHeight() : 0)); + } + if (savedMessagesSearchHint != null) { + savedMessagesSearchHint.setTranslationY(0); + } + if (savedMessagesHint != null) { + savedMessagesHint.setTranslationY(0); + } if (actionBarSearchTags != null) { actionBarSearchTags.setTranslationY(0); } @@ -15646,7 +16526,7 @@ private void updateSecretStatus() { suggestEmojiPanel.forceClose(); } } else { - createEmptyView(); + createEmptyView(false); if (currentEncryptedChat == null || bigEmptyView == null) { bottomOverlay.setVisibility(View.INVISIBLE); if (suggestEmojiPanel != null && chatActivityEnterView != null && chatActivityEnterView.hasText()) { @@ -16394,17 +17274,51 @@ public void onAnimationCancel(Animator animation) { } private void updateSelectedMessageReactions() { - List selected = new ArrayList<>(); - SparseArray objs = selectedMessagesIds[0]; - for (int i = 0; i < objs.size(); i++) { - selected.add(objs.valueAt(i)); - } - objs = selectedMessagesIds[1]; - for (int i = 0; i < objs.size(); i++) { - selected.add(objs.valueAt(i)); + if (getDialogId() == getUserConfig().getClientUserId()) { + ArrayList messageObjects = new ArrayList<>(); + for (int a = 0; a < selectedMessagesIds.length; ++a) { + for (int k = 0; k < selectedMessagesIds[a].size(); ++k) { + MessageObject messageObject = selectedMessagesIds[a].valueAt(k); + if (messageObject.hasValidGroupId()) { + MessageObject.GroupedMessages group = getValidGroupedMessage(messageObject); + MessageObject.GroupedMessagePosition position = group != null ? group.getPosition(messageObject) : null; + if (position == null || !position.last) { + continue; + } + } + messageObjects.add(messageObject); + } + } + boolean hasReactions = false; + if (tagSelector != null) { + tagSelector.setSelectedReactionsInclusive(messageObjects); + hasReactions = !tagSelector.getSelectedReactions().isEmpty(); + tagSelector.setHint(LocaleController.getString(!hasReactions ? R.string.SavedTagReactionsSelectedAddHint : R.string.SavedTagReactionsSelectedEditHint)); + AndroidUtilities.runOnUIThread(() -> { + if (tagSelector != null) { + tagSelector.requestLayout(); + } + }, 120); + } else { + hasReactions = !ReactionsContainerLayout.getInclusiveReactions(messageObjects).isEmpty(); + } + ActionBarMenuItem tagItem = actionBar.createActionMode().getItem(tag_message); + if (tagItem != null) { + tagItem.setIcon(hasReactions ? R.drawable.menu_tag_edit : R.drawable.menu_tag_plus, true); + } } - if (selectionReactionsOverlay != null) + if (selectionReactionsOverlay != null) { + List selected = new ArrayList<>(); + SparseArray objs = selectedMessagesIds[0]; + for (int i = 0; i < objs.size(); i++) { + selected.add(objs.valueAt(i)); + } + objs = selectedMessagesIds[1]; + for (int i = 0; i < objs.size(); i++) { + selected.add(objs.valueAt(i)); + } selectionReactionsOverlay.setSelectedMessages(selected); + } } private void processRowSelect(View view, boolean outside, float touchX, float touchY) { @@ -17211,6 +18125,8 @@ public void didReceivedNotification(int id, int account, final Object... args) { int mode = (Integer) args[14]; boolean isCache = (Boolean) args[3]; boolean postponedScroll = postponedScrollToLastMessageQueryIndex > 0 && queryLoadIndex == postponedScrollToLastMessageQueryIndex; + boolean fakePostponedScroll = this.fakePostponedScroll; + this.fakePostponedScroll = false; if (postponedScroll) { postponedScrollToLastMessageQueryIndex = 0; } @@ -17234,7 +18150,7 @@ public void didReceivedNotification(int id, int account, final Object... args) { showProgressView(false); checkDispatchHideSkeletons(true); if (chatListView != null) { - createEmptyView(); + createEmptyView(false); if (!fragmentOpened) { chatListView.setAnimateEmptyView(false, 1); chatListView.setEmptyView(emptyViewContainer); @@ -17252,7 +18168,7 @@ public void didReceivedNotification(int id, int account, final Object... args) { fragmentTransitionRunnable.run(); return; } - if (chatMode != mode && chatMode != MODE_SAVED) { + if (chatMode != mode && (chatMode != MODE_SAVED || getSavedDialogId() == getUserConfig().getClientUserId())) { if (chatMode != MODE_SCHEDULED) { if (isTopic) { ForumUtilities.filterMessagesByTopic(threadMessageId, messArr); @@ -17295,8 +18211,8 @@ public void didReceivedNotification(int id, int account, final Object... args) { int unreadAfterId = createUnreadMessageAfterId; createUnreadLoading = createUnreadMessageAfterIdLoading; oldMessagesDict = messagesDict[0].clone(); - clearChatData(); - if (chatMode == 0) { + clearChatData(!fakePostponedScroll); + if (chatMode == 0 || chatMode == MODE_SAVED) { createUnreadMessageAfterId = unreadAfterId; startLoadFromMessageId = startLoadFrom; needSelectFromMessageId = needSelect; @@ -17353,7 +18269,7 @@ public void didReceivedNotification(int id, int account, final Object... args) { return; } if (postponedScrollMessageId == 0) { - clearChatData(); + clearChatData(true); } else { if (showScrollToMessageError) { boolean found = false; @@ -17386,8 +18302,8 @@ public void didReceivedNotification(int id, int account, final Object... args) { boolean needSelect = needSelectFromMessageId; int unreadAfterId = createUnreadMessageAfterId; createUnreadLoading = createUnreadMessageAfterIdLoading; - clearChatData(); - if (chatMode == 0) { + clearChatData(!fakePostponedScroll); + if (chatMode == 0 || chatMode == MODE_SAVED) { createUnreadMessageAfterId = unreadAfterId; startLoadFromMessageId = startLoadFrom; needSelectFromMessageId = needSelect; @@ -17475,6 +18391,7 @@ public void didReceivedNotification(int id, int account, final Object... args) { if (!forwardEndReached[loadIndex]) { messages.clear(); messagesByDays.clear(); + messagesByDaysSorted.clear(); groupedMessagesMap.clear(); threadMessageAdded = false; for (int a = 0; a < 2; a++) { @@ -17737,6 +18654,7 @@ public void didReceivedNotification(int id, int account, final Object... args) { if (dayArray == null) { dayArray = new ArrayList<>(); messagesByDays.put(obj.dateKey, dayArray); + messagesByDaysSorted.put(obj.dateKeyInt, dayArray); TLRPC.Message dateMsg = new TLRPC.TL_message(); if (chatMode == MODE_SCHEDULED) { if (obj.messageOwner.date == 0x7ffffffe) { @@ -17752,6 +18670,8 @@ public void didReceivedNotification(int id, int account, final Object... args) { calendar.setTimeInMillis(((long) obj.messageOwner.date) * 1000); calendar.set(Calendar.HOUR_OF_DAY, 0); calendar.set(Calendar.MINUTE, 0); + calendar.set(Calendar.SECOND, 0); + calendar.set(Calendar.MILLISECOND, 0); if (chatMode == MODE_SCHEDULED && obj.messageOwner.date == 0x7ffffffe) { dateMsg.date = 0x7ffffffe; @@ -17763,7 +18683,7 @@ public void didReceivedNotification(int id, int account, final Object... args) { dateObj.type = MessageObject.TYPE_DATE; dateObj.contentType = 1; dateObj.isDateObject = true; - dateObj.stableId = getStableIdForDateObject(dateMsg.date); + dateObj.stableId = getStableIdForDateObject(obj.dateKeyInt); if (load_type == 1) { messages.add(0, dateObj); } else { @@ -17838,6 +18758,9 @@ public void didReceivedNotification(int id, int account, final Object... args) { newRowsCount++; dayArray.add(obj); + if (oldMessage == null && filteredMessagesDict != null) { + oldMessage = filteredMessagesDict.get(obj.getId()); + } if (oldMessage != null) { obj.copyStableParams(oldMessage); } else { @@ -17894,7 +18817,7 @@ public void didReceivedNotification(int id, int account, final Object... args) { scrolledToUnread = true; newRowsCount++; } - } else if ((load_type == 3 || load_type == 4) && (startLoadFromMessageId < 0 && messageId == startLoadFromMessageId || startLoadFromMessageId > 0 && messageId > 0 && messageId <= startLoadFromMessageId)) { + } else if ((load_type == 3 || load_type == 4) && (startLoadFromMessageId < 0 && messageId == startLoadFromMessageId || startLoadFromMessageId > 0 && messageId > 0 && messageId <= startLoadFromMessageId) && !fakePostponedScroll) { removeSelectedMessageHighlight(); if (needSelectFromMessageId && messageId == startLoadFromMessageId) { highlightMessageId = messageId; @@ -17956,11 +18879,13 @@ public void didReceivedNotification(int id, int account, final Object... args) { first_unread_id = 0; last_message_id = 0; createUnreadMessageAfterId = 0; - chatAdapter.notifyItemRemoved(chatAdapter.loadingDownRow); + if (!chatAdapter.isFiltered) { + chatAdapter.notifyItemRemoved(chatAdapter.loadingDownRow); + } } startLoadFromMessageId = 0; } - if (newRowsCount > 0) { + if (newRowsCount > 0 && !chatAdapter.isFiltered) { int top = 0; MessageObject scrollToMessageObject = null; for (int i = 0; i < chatListView.getChildCount(); i++) { @@ -18008,7 +18933,10 @@ public void didReceivedNotification(int id, int account, final Object... args) { loadSendAsPeers(fragmentBeginToShow); if (chatListView != null && chatScrollHelper != null) { - if (first || scrollToTopOnResume || forceScrollToTop) { + if (chatAdapter.isFiltered) { + scrollToMessagePosition = -10000; + scrollToMessage = null; + } else if (first || scrollToTopOnResume || forceScrollToTop) { forceScrollToTop = false; if (!postponedScroll) { chatAdapter.notifyDataSetChanged(true); @@ -18065,7 +18993,7 @@ public void didReceivedNotification(int id, int account, final Object... args) { } scrollToMessagePosition = -10000; scrollToMessage = null; - } else { + } else if (!fakePostponedScroll) { addSponsoredMessages(!isFirstLoading); moveScrollToLastMessage(true); } @@ -18130,7 +19058,7 @@ public void didReceivedNotification(int id, int account, final Object... args) { if (first) { if (chatListView != null) { AndroidUtilities.runOnUIThread(() -> { - createEmptyView(); + createEmptyView(false); if (!fragmentBeginToShow) { chatListView.setAnimateEmptyView(false, 0); chatListView.setEmptyView(emptyViewContainer); @@ -18152,7 +19080,7 @@ public void didReceivedNotification(int id, int account, final Object... args) { for (int a = 0; a < newGroups.size(); a++) { MessageObject.GroupedMessages groupedMessages = newGroups.valueAt(a); groupedMessages.calculate(); - if (chatAdapter != null && changedGroups != null && changedGroups.indexOfKey(newGroups.keyAt(a)) >= 0) { + if (chatAdapter != null && !chatAdapter.isFiltered && changedGroups != null && changedGroups.indexOfKey(newGroups.keyAt(a)) >= 0) { MessageObject messageObject = groupedMessages.messages.get(groupedMessages.messages.size() - 1); int idx = messages.indexOf(messageObject); if (idx >= 0) { @@ -18221,10 +19149,11 @@ public void didReceivedNotification(int id, int account, final Object... args) { addSponsoredMessages(!isFirstLoading); checkScrollForLoad(false); - if (postponedScroll) { + if (postponedScroll && !fakePostponedScroll) { chatAdapter.notifyDataSetChanged(true); if (progressDialog != null) { progressDialog.dismiss(); + showMessagesSearchListView(false); } resetProgressDialogLoading(); updatePinnedListButton(false); @@ -18304,6 +19233,10 @@ public void didReceivedNotification(int id, int account, final Object... args) { checkNewMessagesOnQuoteEdit(true); invalidatePremiumBlocked(); + + if (fakePostponedScroll) { + setFilterMessages(false, true, true); + } } else if (id == NotificationCenter.invalidateMotionBackground) { if (chatListView != null) { chatListView.invalidateViews(); @@ -18655,6 +19588,7 @@ public void didReceivedNotification(int id, int account, final Object... args) { dayArr.remove(obj); if (dayArr.isEmpty()) { messagesByDays.remove(obj.dateKey); + messagesByDaysSorted.remove(obj.dateKeyInt); if (b >= 0 && b < messages.size()) { messages.remove(b); b--; @@ -18742,6 +19676,7 @@ public void didReceivedNotification(int id, int account, final Object... args) { dayArr.remove(obj); if (dayArr.isEmpty()) { messagesByDays.remove(obj.dateKey); + messagesByDaysSorted.remove(obj.dateKeyInt); if (index >= 0 && index < messages.size()) { messages.remove(index); } @@ -19075,11 +20010,12 @@ public void didReceivedNotification(int id, int account, final Object... args) { } else if (id == NotificationCenter.removeAllMessagesFromDialog) { long did = (Long) args[0]; if (dialog_id == did) { + setFilterMessages(false); if (threadMessageId != 0) { if (forwardEndReached[0]) { forwardEndReached[0] = false; hideForwardEndReached = false; - if (chatAdapter != null) { + if (chatAdapter != null && !chatAdapter.isFiltered) { chatAdapter.notifyItemInserted(0); } } @@ -19411,6 +20347,14 @@ public void didReceivedNotification(int id, int account, final Object... args) { long did = (Long) args[0]; doOnIdle(() -> { int msgId = (Integer) args[1]; + if (filteredMessagesDict != null) { + MessageObject messageObject = filteredMessagesDict.get(msgId); + if (messageObject != null) { + MessageObject.updateReactions(messageObject.messageOwner, (TLRPC.TL_messageReactions) args[2]); + messageObject.forceUpdate = true; + messageObject.reactionsChanged = true; + } + } MessageObject messageObject = messagesDict[did == dialog_id ? 0 : 1].get(msgId); if (messageObject != null) { MessageObject.updateReactions(messageObject.messageOwner, (TLRPC.TL_messageReactions) args[2]); @@ -19419,6 +20363,26 @@ public void didReceivedNotification(int id, int account, final Object... args) { updateMessageAnimated(messageObject, true); } }); + } else if (id == NotificationCenter.savedReactionTagsUpdate) { + if (dialog_id != getUserConfig().getClientUserId()) { + return; + } + long topicId = (long) args[0]; + if (topicId != 0 && topicId != getSavedDialogId()) { + return; + } + doOnIdle(() -> { + AndroidUtilities.forEachViews(chatListView, view -> { + if (view instanceof ChatMessageCell) { + MessageObject message = ((ChatMessageCell) view).getMessageObject(); + if (message != null) { + message.forceUpdate = true; + message.reactionsChanged = true; + } + } + }); + chatAdapter.notifyDataSetChanged(true); + }); } else if (id == NotificationCenter.didVerifyMessagesStickers) { ArrayList messages = (ArrayList) args[0]; for (int a = 0, N = messages.size(); a < N; a++) { @@ -19468,10 +20432,8 @@ public void didReceivedNotification(int id, int account, final Object... args) { } groupedMessages.calculate(); int index = messages.indexOf(messageObject); - if (index >= 0) { - if (chatAdapter != null) { - chatAdapter.notifyItemRangeChanged(index + chatAdapter.messagesStartRow, updateCount); - } + if (chatAdapter != null && !chatAdapter.isFiltered && index >= 0) { + chatAdapter.notifyItemRangeChanged(index + chatAdapter.messagesStartRow, updateCount); } } } @@ -19896,45 +20858,54 @@ public void didReceivedNotification(int id, int account, final Object... args) { } } else if (id == NotificationCenter.chatSearchResultsAvailable) { if (classGuid == (Integer) args[0]) { + updateSearchUpDownButtonVisibility(true); boolean jumpToMessage = (Boolean) args[6]; + updateSearchButtons((Integer) args[2], (Integer) args[4], (Integer) args[5]); if (jumpToMessage) { int messageId = (Integer) args[1]; long did = (Long) args[3]; -// if (searchingReaction != null) { -// if (chatAdapter.isFiltered) { -// updateFilteredMessages(); -// } else { -// setFilterMessages(true); -// } -// } else - if (messageId != 0) { + if (searchingReaction != null && searchingFiltered) { + if (chatAdapter.isFiltered) { + updateFilteredMessages(true); + } else { + setFilterMessages(true); + } + } else if (messageId != 0) { + final boolean wasFiltered = chatAdapter.isFiltered; setFilterMessages(false); - scrollToMessageId(messageId, 0, true, did == dialog_id ? 0 : 1, true, 0); + if (!wasFiltered) { + scrollToMessageId(messageId, 0, true, did == dialog_id ? 0 : 1, true, 0); + } else { + updateVisibleRows(); + } } else { setFilterMessages(false); updateVisibleRows(); } - updateSearchButtons((Integer) args[2], (Integer) args[4], (Integer) args[5]); if (searchItem != null) { searchItem.setShowSearchProgress(false); } + onSearchLoadingUpdate(false); + } else if (searchingReaction != null) { + if (chatAdapter.isFiltered) { + updateFilteredMessages(true); + } else { + setFilterMessages(true); + } } -// else if (searchingReaction != null) { -// if (chatAdapter.isFiltered) { -// updateFilteredMessages(); -// } else { -// setFilterMessages(true); -// } -// } if (messagesSearchAdapter != null) { messagesSearchAdapter.notifyDataSetChanged(); } + if (chatAdapter.isFiltered) { + AndroidUtilities.runOnUIThread(() -> checkScrollForLoad(false)); + } } } else if (id == NotificationCenter.chatSearchResultsLoading) { if (classGuid == (Integer) args[0]) { if (searchItem != null) { searchItem.setShowSearchProgress(true); } + onSearchLoadingUpdate(true); if (messagesSearchAdapter != null) { messagesSearchAdapter.notifyDataSetChanged(); } @@ -20067,13 +21038,13 @@ public void didReceivedNotification(int id, int account, final Object... args) { if (!groupedMessages.messages.isEmpty()) { MessageObject messageObject = groupedMessages.messages.get(groupedMessages.messages.size() - 1); int index = messages.indexOf(messageObject); - if (index >= 0) { + if (index >= 0 && !chatAdapter.isFiltered) { chatAdapter.notifyItemRangeChanged(index + chatAdapter.messagesStartRow, groupedMessages.messages.size()); } } } } - if (updatedRows != null) { + if (updatedRows != null && !chatAdapter.isFiltered) { for (int b = 0, N = updatedRows.size(); b < N; b++) { chatAdapter.notifyItemChanged(updatedRows.get(b)); } @@ -20554,16 +21525,14 @@ public void didReceivedNotification(int id, int account, final Object... args) { } } } else if (id == NotificationCenter.savedMessagesDialogsUpdate) { - if (checkedSavedMessagesHint && !savedMessagesHintShown && chatMode == 0 && savedMessagesHint != null && MessagesController.getGlobalMainSettings().getInt("savedhint", 0) < 1 && !getMessagesController().getSavedMessagesController().unsupported && getMessagesController().getSavedMessagesController().getAllCount() > 2) { - savedMessagesHint.show(); - savedMessagesHintShown = true; - MessagesController.getGlobalMainSettings().edit().putInt("savedhint", MessagesController.getGlobalMainSettings().getInt("savedhint", 0) + 1).apply(); - } - + checkSavedMessagesHint(); if (avatarContainer != null) { avatarContainer.updateSubtitle(true); } - + if (savedChatsItem != null && savedChatsGap != null) { + savedChatsItem.setVisibility(getMessagesController().getSavedMessagesController().hasDialogs() ? View.VISIBLE : View.GONE); + savedChatsGap.setVisibility(getMessagesController().getSavedMessagesController().hasDialogs() ? View.VISIBLE : View.GONE); + } if (chatMode == MODE_SAVED && !isInsideContainer && getUserConfig().getClientUserId() != getSavedDialogId() && !getMessagesController().getSavedMessagesController().containsDialog(getSavedDialogId())) { finishFragment(); } @@ -20913,12 +21882,12 @@ private void checkWaitingForReplies() { MessageObject.GroupedMessages groupedMessages = newGroups.valueAt(b); MessageObject messageObject = groupedMessages.messages.get(groupedMessages.messages.size() - 1); int index = messages.indexOf(messageObject); - if (index >= 0) { + if (index >= 0 && !chatAdapter.isFiltered) { chatAdapter.notifyItemRangeChanged(index + chatAdapter.messagesStartRow, groupedMessages.messages.size()); } } } - if (updatedRows != null) { + if (updatedRows != null && !chatAdapter.isFiltered) { for (int b = 0, N = updatedRows.size(); b < N; b++) { chatAdapter.notifyItemChanged(updatedRows.get(b)); } @@ -20969,6 +21938,7 @@ private void clearHistory(boolean overwrite, TLRPC.TL_updates_channelDifferenceT messages.clear(); waitingForLoad.clear(); messagesByDays.clear(); + messagesByDaysSorted.clear(); groupedMessagesMap.clear(); threadMessageAdded = false; for (int a = 1; a >= 0; a--) { @@ -20998,7 +21968,7 @@ private void clearHistory(boolean overwrite, TLRPC.TL_updates_channelDifferenceT if (progressView != null) { showProgressView(false); - createEmptyView(); + createEmptyView(false); chatListView.setEmptyView(emptyViewContainer); } @@ -21448,6 +22418,7 @@ private void processNewMessages(ArrayList arr) { dayArr.remove(removed); if (dayArr.isEmpty()) { messagesByDays.remove(removed.dateKey); + messagesByDaysSorted.remove(removed.dateKeyInt); if (index >= 0 && index < messages.size()) { messages.remove(index); } @@ -21647,6 +22618,7 @@ private void processNewMessages(ArrayList arr) { if (dayArray == null) { dayArray = new ArrayList<>(); messagesByDays.put(obj.dateKey, dayArray); + messagesByDaysSorted.put(obj.dateKeyInt, dayArray); TLRPC.Message dateMsg = new TLRPC.TL_message(); if (chatMode == MODE_SCHEDULED) { if (obj.messageOwner.date == 0x7ffffffe) { @@ -21662,12 +22634,14 @@ private void processNewMessages(ArrayList arr) { calendar.setTimeInMillis(((long) obj.messageOwner.date) * 1000); calendar.set(Calendar.HOUR_OF_DAY, 0); calendar.set(Calendar.MINUTE, 0); + calendar.set(Calendar.SECOND, 0); + calendar.set(Calendar.MILLISECOND, 0); dateMsg.date = (int) (calendar.getTimeInMillis() / 1000); MessageObject dateObj = new MessageObject(currentAccount, dateMsg, false, false); dateObj.type = 10; dateObj.contentType = 1; dateObj.isDateObject = true; - dateObj.stableId = getStableIdForDateObject(dateMsg.date); + dateObj.stableId = getStableIdForDateObject(obj.dateKeyInt); messages.add(placeToPaste, dateObj); if (chatAdapter != null) { chatAdapter.notifyItemInserted(placeToPaste); @@ -21859,6 +22833,10 @@ private void processNewMessages(ArrayList arr) { processNewMessages(notPushedSponsoredMessages); } invalidatePremiumBlocked(); + + if (savedMessagesTagHint != null && savedMessagesTagHint.shown()) { + savedMessagesTagHint.hide(); + } } private int getStableIdForDateObject(int date) { @@ -21875,24 +22853,23 @@ private void saveScrollPosition() { return; } int top = 0; - MessageObject scrollToMessageObject = null; + int position = RecyclerListView.NO_POSITION; for (int i = 0; i < chatListView.getChildCount(); i++) { View v = chatListView.getChildAt(i); + final int vposition = chatListView.getChildAdapterPosition(v); + if (vposition < 0) continue; if (v instanceof ChatMessageCell) { - scrollToMessageObject = ((ChatMessageCell) v).getMessageObject(); + position = vposition; top = getScrollingOffsetForView(v); break; } else if (v instanceof ChatActionCell) { - scrollToMessageObject = ((ChatActionCell) v).getMessageObject(); + position = vposition; top = getScrollingOffsetForView(v); break; } } - if (scrollToMessageObject != null) { - int scrollToIndex = messages.indexOf(scrollToMessageObject); - if (scrollToIndex > 0) { -// chatLayoutManager.scrollToPositionWithOffset(chatAdapter.messagesStartRow + scrollToIndex, top); - } + if (position >= 0) { + chatLayoutManager.scrollToPositionWithOffset(position, top); } } @@ -21955,7 +22932,7 @@ private void processDeletedMessages(ArrayList markAsDeletedMessages, lo int commentsDeleted = 0; for (int a = 0; a < size; a++) { Integer mid = markAsDeletedMessages.get(a); - MessageObject obj = messagesDict[loadIndex].get(mid); + MessageObject obj = chatAdapter.isFiltered ? filteredMessagesDict.get(mid) : messagesDict[loadIndex].get(mid); if (selectedObject != null && obj == selectedObject || obj != null && selectedObjectGroup != null && selectedObjectGroup == groupedMessagesMap.get(obj.getGroupId())) { closeMenu(); } @@ -22001,7 +22978,7 @@ private void processDeletedMessages(ArrayList markAsDeletedMessages, lo if (editingMessageObject == obj) { hideFieldPanel(true); } - int index = messages.indexOf(obj); + int index = chatAdapter.isFiltered && filteredMessagesDict != null ? chatAdapter.filteredMessages.indexOf(filteredMessagesDict.get(mid)) : messages.indexOf(obj); if (index != -1) { if (obj.scheduled) { scheduledMessagesCount--; @@ -22011,8 +22988,25 @@ private void processDeletedMessages(ArrayList markAsDeletedMessages, lo updatedSelected = true; addToSelectedMessages(obj, false, updatedSelectedLast = (a == size - 1)); } - MessageObject removed = messages.remove(index); + MessageObject removed = chatAdapter.getMessages().remove(index); if (chatAdapter != null) { + if (chatAdapter.isFiltered) { + int mindex = messages.indexOf(obj); + if (mindex >= 0) { + messages.remove(mindex); + } + getMediaDataController().removeMessageFromResults(removed.getId()); + } else if (filteredMessagesDict != null) { + MessageObject msg = filteredMessagesDict.get(mid); + if (msg != null) { + filteredMessagesDict.remove(mid); + chatAdapter.filteredMessages.remove(msg); + getMediaDataController().removeMessageFromResults(msg.getId()); + } + } + if (messagesSearchAdapter != null) { + messagesSearchAdapter.notifyDataSetChanged(); + } removedIndexes.add(chatAdapter.messagesStartRow + index); if (!sent && !obj.scheduledSent && removed != null && removed.messageOwner != null && removed.messageOwner.send_state == MessageObject.MESSAGE_SEND_STATE_SENT && currentTime - removed.messageOwner.date >= (currentChat != null || currentUser != null && currentUser.bot ? 2 : 0)) { thanosMessagesIndexes.add(chatAdapter.messagesStartRow + index); @@ -22039,10 +23033,35 @@ private void processDeletedMessages(ArrayList markAsDeletedMessages, lo dayArr.remove(obj); if (dayArr.isEmpty()) { messagesByDays.remove(obj.dateKey); - if (index < messages.size()) { - messages.remove(index); - if (chatAdapter != null) { - removedIndexes.add(chatAdapter.messagesStartRow + index); + messagesByDaysSorted.remove(obj.dateKeyInt); + int dindex = index; + if (chatAdapter != null && chatAdapter.isFiltered) { + dindex = messages.indexOf(obj); + } + if (dindex >= 0 && dindex < messages.size()) { + messages.remove(dindex); + if (chatAdapter != null && !chatAdapter.isFiltered) { + removedIndexes.add(chatAdapter.messagesStartRow + dindex); + } + } + } + } + if (filteredMessagesByDays != null) { + dayArr = filteredMessagesByDays.get(obj.dateKeyInt); + if (dayArr != null) { + MessageObject mobj = chatAdapter.isFiltered ? filteredMessagesDict.get(obj.getId()) : obj; + dayArr.remove(mobj); + if (dayArr.isEmpty()) { + filteredMessagesByDays.remove(obj.dateKeyInt); + int dindex = index; + if (chatAdapter != null && !chatAdapter.isFiltered) { + dindex = chatAdapter.filteredMessages.indexOf(mobj); + } + if (chatAdapter != null && dindex >= 0 && dindex < chatAdapter.filteredMessages.size()) { + chatAdapter.filteredMessages.remove(dindex); + if (chatAdapter.isFiltered) { + removedIndexes.add(chatAdapter.messagesStartRow + dindex); + } } } } @@ -22080,7 +23099,7 @@ private void processDeletedMessages(ArrayList markAsDeletedMessages, lo } else { groupedMessages.calculate(); MessageObject messageObject = groupedMessages.messages.get(groupedMessages.messages.size() - 1); - int index = messages.indexOf(messageObject); + int index = chatAdapter.getMessages().indexOf(messageObject); if (index >= 0) { if (chatAdapter != null) { chatAdapter.notifyItemRangeChanged(index + chatAdapter.messagesStartRow, newGroupsSizes.get(groupedMessages.groupId)); @@ -22091,7 +23110,9 @@ private void processDeletedMessages(ArrayList markAsDeletedMessages, lo } if (messages.isEmpty()) { if (!endReached[0] && !loading) { - showProgressView(false); + if (!chatAdapter.isFiltered) { + showProgressView(false); + } if (chatListView != null) { chatListView.setEmptyView(null); } @@ -22139,7 +23160,7 @@ private void processDeletedMessages(ArrayList markAsDeletedMessages, lo if (!isThreadChat() || messages.size() <= 3) { removeUnreadPlane(false); } - if (messages.isEmpty()) { + if (chatAdapter.getMessages().isEmpty()) { if (prevLoadingUpRow >= 0) { chatAdapter.notifyItemRemoved(0); } @@ -22147,7 +23168,7 @@ private void processDeletedMessages(ArrayList markAsDeletedMessages, lo chatAdapter.notifyItemRemoved(0); } } else { - chatAdapter.notifyItemRangeChanged(chatAdapter.messagesStartRow, messages.size()); + chatAdapter.notifyItemRangeChanged(chatAdapter.messagesStartRow, chatAdapter.getMessages().size()); } } updateVisibleRows(); @@ -22162,6 +23183,10 @@ private void processDeletedMessages(ArrayList markAsDeletedMessages, lo updateScheduledInterface(true); } invalidatePremiumBlocked(); + + if (savedMessagesTagHint != null && savedMessagesTagHint.shown()) { + savedMessagesTagHint.hide(); + } } private void replaceMessageObjects(ArrayList messageObjects, int loadIndex, boolean remove) { @@ -22275,8 +23300,10 @@ private void replaceMessageObjects(ArrayList messageObjects, int } else { groupedMessages.messages.set(idx, messageObject); MessageObject.GroupedMessagePosition oldPosition = groupedMessages.positions.remove(old); + groupedMessages.positionsArray.remove(old.getId()); if (oldPosition != null) { groupedMessages.positions.put(messageObject, oldPosition); + groupedMessages.positionsArray.put(messageObject.getId(), oldPosition); } if (newGroups == null) { newGroups = new LongSparseArray<>(); @@ -22292,7 +23319,7 @@ private void replaceMessageObjects(ArrayList messageObjects, int if (messageObject.type >= 0) { messageObject.copyStableParams(old); messages.set(index, messageObject); - if (chatAdapter != null) { + if (chatAdapter != null && !chatAdapter.isFiltered) { chatAdapter.updateRowAtPosition(chatAdapter.messagesStartRow + index); } if (index2 >= 0) { @@ -22300,23 +23327,26 @@ private void replaceMessageObjects(ArrayList messageObjects, int } } else { messages.remove(index); - if (chatAdapter != null) { + if (chatAdapter != null && !chatAdapter.isFiltered) { chatAdapter.notifyItemRemoved(chatAdapter.messagesStartRow + index); } if (index2 >= 0) { dayArr.remove(index2); if (dayArr.isEmpty()) { messagesByDays.remove(old.dateKey); + messagesByDaysSorted.remove(old.dateKeyInt); messages.remove(index); int prevLoadingUpRow = chatAdapter.loadingUpRow; int prevLoadingDownRow = chatAdapter.loadingDownRow; - chatAdapter.notifyItemRemoved(chatAdapter.messagesStartRow + index); - if (messages.isEmpty()) { - if (prevLoadingUpRow >= 0) { - chatAdapter.notifyItemRemoved(0); - } - if (prevLoadingDownRow >= 0) { - chatAdapter.notifyItemRemoved(0); + if (!chatAdapter.isFiltered) { + chatAdapter.notifyItemRemoved(chatAdapter.messagesStartRow + index); + if (messages.isEmpty()) { + if (prevLoadingUpRow >= 0) { + chatAdapter.notifyItemRemoved(0); + } + if (prevLoadingDownRow >= 0) { + chatAdapter.notifyItemRemoved(0); + } } } } @@ -22455,22 +23485,29 @@ private void showPollSolution(MessageObject messageObject, TLRPC.PollResults res private void updateSearchButtons(int mask, int num, int count) { if (searchUpButton != null) { - searchUpButton.setEnabled((mask & 1) != 0); - searchUpButton.setAlpha(searchUpButton.isEnabled() ? 1.0f : 0.5f); + searchUpButton.setEnabled((mask & (reversed ? 2 : 1)) != 0); + searchUpButtonArrow.setAlpha(searchUpButton.isEnabled() ? 1.0f : 0.5f); } if (searchDownButton != null) { - searchDownButton.setEnabled((mask & 2) != 0); - searchDownButton.setAlpha(searchDownButton.isEnabled() ? 1.0f : 0.5f); + searchDownButton.setEnabled((mask & (reversed ? 1 : 2)) != 0); + searchDownButtonArrow.setAlpha(searchDownButton.isEnabled() ? 1.0f : 0.5f); } if (searchCountText != null) { + boolean animated = !LocaleController.isRTL; if (count < 0) { - searchCountText.setCount("", 0, false); + searchCountText.setText("", animated); } else if (count == 0) { - searchCountText.setCount(LocaleController.getString("NoResult", R.string.NoResult), 0, false); + searchCountText.setText(LocaleController.getString(R.string.NoResult), animated); + } else if (searchingFiltered) { + searchCountText.setText(LocaleController.formatPluralString("TaggedMessages", count), animated); } else { - searchCountText.setCount(LocaleController.formatString("OfCounted", R.string.OfCounted, num + 1, count), num + 1, true); + searchCountText.setText(LocaleController.formatString(R.string.Of, num + 1, count), animated); } } + if (searchExpandList != null) { + searchExpandList.setClickable(count > 0); + searchExpandList.animate().alpha(count > 0 ? 1f : 0.5f).start(); + } } @Override @@ -22512,15 +23549,68 @@ private void checkSavedMessagesHint() { if (checkedSavedMessagesHint) return; checkedSavedMessagesHint = true; - if (!savedMessagesHintShown && savedMessagesHint != null && chatMode == 0 && MessagesController.getGlobalMainSettings().getInt("savedhint", 0) < 1 && !getMessagesController().getSavedMessagesController().unsupported && getMessagesController().getSavedMessagesController().getAllCount() > 2) { - savedMessagesHint.show(); - savedMessagesHintShown = true; - MessagesController.getGlobalMainSettings().edit().putInt("savedhint", MessagesController.getGlobalMainSettings().getInt("savedhint", 0) + 1).apply(); + if (!savedMessagesHintShown && chatMode == 0 && !getMessagesController().getSavedMessagesController().unsupported && getMessagesController().getSavedMessagesController().getAllCount() > 2) { + if (savedMessagesHint != null && MessagesController.getGlobalMainSettings().getInt("savedhint", 0) < 1) { + savedMessagesHint.show(); + savedMessagesHintShown = true; + MessagesController.getGlobalMainSettings().edit() + .putInt("savedhint", MessagesController.getGlobalMainSettings().getInt("savedhint", 0) + 1) + .putInt("savedsearchhint", MessagesController.getGlobalMainSettings().getInt("savedsearchhint", 0) + 1) + .apply(); + } else if (savedMessagesSearchHint != null && MessagesController.getGlobalMainSettings().getInt("savedsearchhint", 0) < 1) { + savedMessagesSearchHint.show(); + savedMessagesHintShown = true; + MessagesController.getGlobalMainSettings().edit().putInt("savedsearchhint", MessagesController.getGlobalMainSettings().getInt("savedsearchhint", 0) + 1).apply(); + } else { + checkSavedMessagesTagHint(); + } + } + } + + private long lastScrollTime; + private boolean savedMessagesTagHintShown; + private void checkSavedMessagesTagHint() { + if (savedMessagesTagHint == null || savedMessagesTagHint.shown() || savedMessagesTagHintShown || !checkedSavedMessagesHint) { + return; + } + if (savedMessagesTagHint != null && (messagesSearchListView == null || messagesSearchListView.getTag() == null) && System.currentTimeMillis() - lastScrollTime > 1800 && MessagesController.getGlobalMainSettings().getInt("savedsearchtaghint", 0) < 1) { + final int[] loc = new int[2]; + ChatMessageCell foundCell = null; + for (int i = chatListView.getChildCount() - 1; i >= 0; --i) { + View child = chatListView.getChildAt(i); + if (child instanceof ChatMessageCell) { + ChatMessageCell cell = (ChatMessageCell) child; + if (cell.areTags() && !cell.reactionsLayoutInBubble.reactionButtons.isEmpty()) { + cell.getLocationInWindow(loc); + + final float y = loc[1] + cell.reactionsLayoutInBubble.y; + if (y >= dp(240) && y <= AndroidUtilities.displaySize.y - dp(25) - AndroidUtilities.navigationBarHeight) { + foundCell = cell; + break; + } + } + } + } + + if (foundCell != null) { + savedMessagesTagHintShown = true; + ReactionsLayoutInBubble.ReactionButton btn = foundCell.reactionsLayoutInBubble.reactionButtons.get(0); + foundCell.getLocationInWindow(loc); + savedMessagesTagHint.setTranslationY(loc[1] - savedMessagesTagHint.getTop() - dp(120) + foundCell.reactionsLayoutInBubble.y); + savedMessagesTagHint.setJointPx(0, -dp(16) + loc[0] + foundCell.reactionsLayoutInBubble.x + btn.width / 2f); + savedMessagesTagHint.show(); + + MessagesController.getGlobalMainSettings().edit().putInt("savedsearchtaghint", 1).apply(); + } else { + AndroidUtilities.cancelRunOnUIThread(ChatActivity.this::checkSavedMessagesTagHint); + AndroidUtilities.runOnUIThread(ChatActivity.this::checkSavedMessagesTagHint, 2000); + } } } @Override public void onBecomeFullyHidden() { + hideTagSelector(); if (!getMessagesController().premiumFeaturesBlocked() && getMessagesController().transcribeAudioTrialWeeklyNumber <= 0 && !getMessagesController().didPressTranscribeButtonEnough() && !getUserConfig().isPremium() && messages != null) { for (int i = 0; i < messages.size(); ++i) { MessageObject msg = messages.get(i); @@ -22955,6 +24045,7 @@ private void updateBottomOverlay() { } bottomOverlayChatWaitsReply = false; bottomOverlayLinks = false; + boolean forceNoBottom = false; if (chatMode == MODE_DEFAULT && userInfo != null && userInfo.contact_require_premium && !getUserConfig().isPremium()) { bottomOverlayLinks = true; bottomOverlayChatText.setVisibility(View.GONE); @@ -22965,9 +24056,7 @@ private void updateBottomOverlay() { showBottomOverlayProgress(false, false); } else if (chatMode == MODE_SAVED && getSavedDialogId() != getUserConfig().getClientUserId()) { if (getSavedDialogId() == UserObject.ANONYMOUS) { - bottomOverlayChat.setVisibility(View.GONE); - chatActivityEnterView.setVisibility(View.INVISIBLE); - return; + forceNoBottom = true; } else { bottomOverlayChatText.setTag(null); bottomOverlayChatText.setText(LocaleController.getString(currentUser != null ? R.string.SavedOpenChat : (ChatObject.isChannelAndNotMegaGroup(currentChat) ? R.string.SavedOpenChannel : R.string.SavedOpenGroup))); @@ -23104,7 +24193,7 @@ private void updateBottomOverlay() { } else { bottomOverlayImage.setVisibility(View.INVISIBLE); } - if (inPreviewMode || isInsideContainer) { + if (inPreviewMode) { if (searchContainer != null) { searchContainer.setVisibility(View.INVISIBLE); } @@ -23179,7 +24268,7 @@ public void onAnimationEnd(Animator animation) { public void onAnimationEnd(Animator animation) { super.onAnimationEnd(animation); searchContainer.setVisibility(View.INVISIBLE); - } + } }).start(); } } @@ -23221,7 +24310,10 @@ public void onAnimationEnd(Animator animation) { muteItemGap.setVisibility(View.VISIBLE); } } - if (reportType >= 0) { + if (isInsideContainer || forceNoBottom) { + bottomOverlayChat.setVisibility(View.GONE); + chatActivityEnterView.setVisibility(View.GONE); + } else if (reportType >= 0) { bottomOverlayChat.setVisibility(View.VISIBLE); chatActivityEnterView.setVisibility(View.INVISIBLE); } else if (chatMode == MODE_PINNED || @@ -24511,7 +25603,7 @@ public void onClick(View view) { addToContactsButton.setTag(1); addToContactsButton.setVisibility(View.VISIBLE); } else { - if (!user.contact && !user.self && !show) { + if (!user.contact && !UserObject.isService(user.id) && !user.self && !show) { createTopPanel(); if (topChatPanelView == null) { return; @@ -25049,6 +26141,7 @@ public float getPullingDownOffset() { } public void checkAdjustResize() { + if (isInsideContainer) return; if (reportType >= 0) { AndroidUtilities.requestAdjustNothing(getParentActivity(), classGuid); } else { @@ -25102,11 +26195,13 @@ public void onPause() { if (contentView != null) { contentView.onPause(); } - if (chatMode == 0) { + if (chatMode == 0 || chatMode == MODE_SAVED && getUserConfig().getClientUserId() == getSavedDialogId()) { CharSequence[] message = new CharSequence[]{ignoreDraft ? null : draftMessage}; ArrayList entities = getMediaDataController().getEntities(message, currentEncryptedChat == null || AndroidUtilities.getPeerLayerVersion(currentEncryptedChat.layer) >= 101); long draftThreadId; - if (ChatObject.isForum(currentChat) && !isTopic && replyMessage != null) { + if (chatMode == MODE_SAVED) { + draftThreadId = 0; + } else if (ChatObject.isForum(currentChat) && !isTopic && replyMessage != null) { if (replyMessage.replyToForumTopic != null) { draftThreadId = replyMessage.replyToForumTopic.id; } else { @@ -25212,8 +26307,9 @@ public void onPause() { } } + private int appliedDraftDate; public void applyDraftMaybe(boolean canClear) { - if (chatActivityEnterView == null || chatMode != 0) { + if (chatActivityEnterView == null || chatMode != 0 && (chatMode != MODE_SAVED || getUserConfig().getClientUserId() != getSavedDialogId())) { return; } TLRPC.DraftMessage draftMessage = null; @@ -25225,11 +26321,12 @@ public void applyDraftMaybe(boolean canClear) { draftMessage = pair.second; } } else { - draftMessage = getMediaDataController().getDraft(dialog_id, threadMessageId); + draftMessage = getMediaDataController().getDraft(dialog_id, chatMode == MODE_SAVED ? 0 : threadMessageId); } TLRPC.Message draftReplyMessage = draftMessage != null && draftMessage.reply_to != null && draftMessage.reply_to.reply_to_msg_id != 0 ? getMediaDataController().getDraftMessage(dialog_id, topicId != null ? topicId : threadMessageId) : null; - if (chatActivityEnterView.getFieldText() == null) { + if (chatActivityEnterView.getFieldText() == null || chatMode == 0 && getUserConfig().getClientUserId() == getDialogId() && draftMessage != null && appliedDraftDate < draftMessage.date) { if (draftMessage != null) { + appliedDraftDate = draftMessage.date; chatActivityEnterView.setWebPage(null, !draftMessage.no_webpage); CharSequence message; if (!draftMessage.entities.isEmpty()) { @@ -25606,6 +26703,10 @@ private void hideActionMode() { chatActivityEnterView.preventInput = false; } textSelectionHintWasShowed = false; + + if (tagSelector != null) { + hideTagSelector(); + } } private boolean createMenu(View v, boolean single, boolean listView, float x, float y) { @@ -25936,7 +27037,7 @@ public void setAutoDeleteHistory(int time, int action) { items.add(LocaleController.getString("Retry", R.string.Retry)); options.add(OPTION_RETRY); icons.add(R.drawable.msg_retry); - items.add(LocaleController.getString("Delete", R.string.Delete)); + items.add(LocaleController.getString(chatMode == MODE_SAVED && threadMessageId != getUserConfig().getClientUserId() ? R.string.Remove : R.string.Delete)); options.add(OPTION_DELETE); icons.add(selectedObject.messageOwner.ttl_period != 0 ? R.drawable.msg_delete_auto : R.drawable.msg_delete); } else if (type == 1) { @@ -25995,7 +27096,7 @@ public void setAutoDeleteHistory(int time, int action) { } } if (message.canDeleteMessage(chatMode == MODE_SCHEDULED, currentChat) && (threadMessageObjects == null || !threadMessageObjects.contains(message)) && !(message != null && message.messageOwner != null && message.messageOwner.action instanceof TLRPC.TL_messageActionTopicCreate)) { - items.add(LocaleController.getString("Delete", R.string.Delete)); + items.add(LocaleController.getString(chatMode == MODE_SAVED && threadMessageId != getUserConfig().getClientUserId() ? R.string.Remove : R.string.Delete)); options.add(OPTION_DELETE); icons.add(selectedObject.messageOwner.ttl_period != 0 ? R.drawable.msg_delete_auto : R.drawable.msg_delete); } @@ -26008,7 +27109,7 @@ public void setAutoDeleteHistory(int time, int action) { options.add(OPTION_COPY); icons.add(R.drawable.msg_copy); } - items.add(LocaleController.getString("Delete", R.string.Delete)); + items.add(LocaleController.getString(chatMode == MODE_SAVED && threadMessageId != getUserConfig().getClientUserId() ? R.string.Remove : R.string.Delete)); options.add(OPTION_DELETE); icons.add(selectedObject.messageOwner.ttl_period != 0 ? R.drawable.msg_delete_auto : R.drawable.msg_delete); } else { @@ -26450,7 +27551,7 @@ public void setAutoDeleteHistory(int time, int action) { } } if (message.canDeleteMessage(chatMode == MODE_SCHEDULED, currentChat) && (threadMessageObjects == null || !threadMessageObjects.contains(message))) { - items.add(LocaleController.getString("Delete", R.string.Delete)); + items.add(LocaleController.getString(chatMode == MODE_SAVED && threadMessageId != getUserConfig().getClientUserId() ? R.string.Remove : R.string.Delete)); options.add(OPTION_DELETE); icons.add(selectedObject.messageOwner.ttl_period != 0 ? R.drawable.msg_delete_auto : R.drawable.msg_delete); } @@ -26603,7 +27704,7 @@ public void setAutoDeleteHistory(int time, int action) { options.add(204); icons.add(R.drawable.msg_disable); } - items.add(LocaleController.getString("Delete", R.string.Delete)); + items.add(LocaleController.getString(chatMode == MODE_SAVED && threadMessageId != getUserConfig().getClientUserId() ? R.string.Remove : R.string.Delete)); options.add(OPTION_DELETE); icons.add(selectedObject.messageOwner.ttl_period != 0 ? R.drawable.msg_delete_auto : R.drawable.msg_delete); } @@ -27034,10 +28135,7 @@ public void onClick(View view) { addGap = true; } else if (showPrivateMessageSeen) { MessagePrivateSeenView messagePrivateSeenView = new MessagePrivateSeenView(getContext(), message, () -> { - if (scrimPopupWindow != null) { - scrimPopupWindow.dismiss(false); - scrimPopupWindow = null; - } + closeMenu(true); }, themeDelegate); popupLayout.addView(messagePrivateSeenView, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, 36)); addGap = true; @@ -27408,8 +28506,20 @@ public boolean onTouch(View v, MotionEvent event) { if (optionsView != null) { scrimPopupContainerLayout.addView(optionsView); } else { - reactionsLayout = new ReactionsContainerLayout(ReactionsContainerLayout.TYPE_DEFAULT, ChatActivity.this, contentView.getContext(), currentAccount, getResourceProvider()); - if (isReactionsAvailable) { + final boolean tags = getUserConfig().getClientUserId() == getDialogId(); + reactionsLayout = new ReactionsContainerLayout(tags ? ReactionsContainerLayout.TYPE_TAGS : ReactionsContainerLayout.TYPE_DEFAULT, ChatActivity.this, contentView.getContext(), currentAccount, getResourceProvider()); + if (tags) { + reactionsLayout.setHint(getUserConfig().isPremium() ? LocaleController.getString(R.string.SavedTagReactionsHint2) : AndroidUtilities.replaceSingleTag(LocaleController.getString(R.string.SavedTagReactionsPremiumHint), Theme.key_windowBackgroundWhiteBlueText2, 0, () -> { + closeMenu(false); + PremiumFeatureBottomSheet sheet = new PremiumFeatureBottomSheet(ChatActivity.this, PremiumPreviewFragment.PREMIUM_FEATURE_SAVED_TAGS, true); + sheet.setDimBehind(false); + sheet.setOnHideListener(d -> { + dimBehindView(false); + }); + sheet.show(); + })); + } + if (isReactionsAvailable && (!tags || !getMessagesController().premiumFeaturesBlocked())) { int pad = 22; int sPad = 24; reactionsLayout.setPadding(AndroidUtilities.dp(4) + (LocaleController.isRTL ? 0 : sPad), AndroidUtilities.dp(4), AndroidUtilities.dp(4) + (LocaleController.isRTL ? sPad : 0), AndroidUtilities.dp(pad)); @@ -27418,7 +28528,7 @@ public boolean onTouch(View v, MotionEvent event) { reactionsLayout.setDelegate(new ReactionsContainerLayout.ReactionsContainerDelegate() { @Override public void onReactionClicked(View v, ReactionsLayoutInBubble.VisibleReaction visibleReaction, boolean longpress, boolean addToRecent) { - selectReaction(primaryMessage, finalReactionsLayout, v,0, 0, visibleReaction,false, longpress, addToRecent); + selectReaction(primaryMessage, finalReactionsLayout, v,0, 0, visibleReaction,false, longpress, addToRecent, false); } @Override @@ -27429,11 +28539,16 @@ public void hideMenu() { } }); - LinearLayout.LayoutParams params = LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, 52 + pad, Gravity.RIGHT, 0, 50, 0, -20); + LinearLayout.LayoutParams params = LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, (int) (52 + reactionsLayout.getTopOffset() / AndroidUtilities.density + pad), Gravity.RIGHT, 0, 50, 0, -20); scrimPopupContainerLayout.addView(reactionsLayout, params); scrimPopupContainerLayout.setReactionsLayout(reactionsLayout); scrimPopupContainerLayout.setClipChildren(false); - reactionsLayout.setMessage(message, chatInfo); + MessageObject messageWithReactions = message; + MessageObject.GroupedMessages group = getValidGroupedMessage(message); + if (group != null) { + messageWithReactions = group.findPrimaryMessageObject(); + } + reactionsLayout.setMessage(messageWithReactions, chatInfo); reactionsLayout.setTransitionProgress(0); if (popupLayout.getSwipeBack() != null) { @@ -27608,22 +28723,28 @@ public void dismiss(boolean animated) { totalHeight += keyboardHeight; } int popupY; + int minY = (int) (chatListView.getY() + dp(24)); + int maxY = totalHeight - height - dp(8); if (height < totalHeight) { popupY = (int) (chatListView.getY() + v.getTop() + y); - if (height - backgroundPaddings.top - backgroundPaddings.bottom > AndroidUtilities.dp(240)) { + if (isInsideContainer) { + int[] location = new int[2]; + v.getLocationInWindow(location); + popupY = (int) (location[1] + y); + + chatListView.getLocationInWindow(location); + minY = dp(24); + maxY = Math.min(location[1] + chatListView.getMeasuredHeight(), AndroidUtilities.displaySize.y) - dp(8) - height; + } else if (height - backgroundPaddings.top - backgroundPaddings.bottom > AndroidUtilities.dp(240)) { popupY += AndroidUtilities.dp(240) - height; } - if (popupY < chatListView.getY() + AndroidUtilities.dp(24)) { - popupY = (int) (chatListView.getY() + AndroidUtilities.dp(24)); - } else if (popupY > totalHeight - height - AndroidUtilities.dp(8)) { - popupY = totalHeight - height - AndroidUtilities.dp(8); - } + popupY = Utilities.clamp(popupY, maxY, minY); } else { popupY = inBubbleMode ? 0 : AndroidUtilities.statusBarHeight; } final int finalPopupX = scrimPopupX = popupX; final int finalPopupY = scrimPopupY = popupY; - scrimPopupContainerLayout.setMaxHeight(totalHeight - popupY); + scrimPopupContainerLayout.setMaxHeight(maxY + height - popupY); ReactionsContainerLayout finalReactionsLayout = reactionsLayout; Runnable showMenu = () -> { if (scrimPopupWindow == null || fragmentView == null || scrimPopupWindow.isShowing() || !AndroidUtilities.isActivityRunning(getParentActivity())) { @@ -27677,10 +28798,7 @@ public void dismiss(boolean animated) { } if (chatMode != MODE_SCHEDULED && actionModeOtherItem != null && NaConfig.INSTANCE.getShowNoQuoteForward().Bool()) actionModeOtherItem.showSubItem(nkbtn_forward_noquote); - item = actionMode.getItem(delete); - if (item != null) { - item.setVisibility(View.VISIBLE); - } + actionMode.setItemVisibility(delete, View.VISIBLE); createBottomMessagesActionButtons(); bottomMessagesActionContainer.setVisibility(View.VISIBLE); @@ -27749,18 +28867,32 @@ public void dismiss(boolean animated) { return false; } - private void createEmptyView() { - if (emptyViewContainer != null || getContext() == null) { + private void createEmptyView(boolean recreate) { + if (emptyViewContainer != null && !recreate || getContext() == null) { return; } - emptyViewContainer = new FrameLayout(getContext()); - emptyViewContainer.setOnTouchListener((v, event) -> true); - emptyViewContainer.setVisibility(View.INVISIBLE); - contentView.addView(emptyViewContainer, 1, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.CENTER)); + if (emptyViewContainer == null) { + emptyViewContainer = new FrameLayout(getContext()); + emptyViewContainer.setOnTouchListener((v, event) -> true); + emptyViewContainer.setVisibility(View.INVISIBLE); + contentView.addView(emptyViewContainer, 1, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.CENTER)); + } else { + emptyViewContainer.removeAllViews(); + } int distance = getArguments().getInt("nearby_distance", -1); - if ((distance >= 0 || preloadedGreetingsSticker != null) && currentUser != null && !userBlocked || userInfo != null && userInfo.contact_require_premium && !getUserConfig().isPremium()) { + if (chatAdapter.isFiltered) { + emptyView = new TextView(getContext()); + emptyView.setText(LocaleController.getString(R.string.NoFilteredMessages)); + emptyView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14); + emptyView.setGravity(Gravity.CENTER); + emptyView.setTextColor(getThemedColor(Theme.key_chat_serviceText)); + emptyView.setBackground(Theme.createServiceDrawable(AndroidUtilities.dp(6), emptyView, contentView, getThemedPaint(Theme.key_paint_chatActionBackground))); + emptyView.setTypeface(AndroidUtilities.getTypeface(AndroidUtilities.TYPEFACE_ROBOTO_MEDIUM)); + emptyView.setPadding(AndroidUtilities.dp(10), AndroidUtilities.dp(2), AndroidUtilities.dp(10), AndroidUtilities.dp(3)); + emptyViewContainer.addView(emptyView, new FrameLayout.LayoutParams(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.CENTER)); + } else if ((distance >= 0 || preloadedGreetingsSticker != null) && currentUser != null && !userBlocked || userInfo != null && userInfo.contact_require_premium && !getUserConfig().isPremium()) { greetingsViewContainer = new ChatGreetingsView(getContext(), currentUser, distance, currentAccount, preloadedGreetingsSticker, themeDelegate); greetingsViewContainer.setPremiumLock(userInfo != null && userInfo.contact_require_premium && !getUserConfig().isPremium(), dialog_id); greetingsViewContainer.setListener((sticker) -> { @@ -27783,16 +28915,16 @@ private void createEmptyView() { String emptyMessage = null; if (isThreadChat() && chatMode == 0) { if (isComments) { - emptyMessage = LocaleController.getString("NoComments", R.string.NoComments); + emptyMessage = LocaleController.getString(R.string.NoComments); } else { - emptyMessage = LocaleController.getString("NoReplies", R.string.NoReplies); + emptyMessage = LocaleController.getString(R.string.NoReplies); } } else if (chatMode == MODE_SCHEDULED) { - emptyMessage = LocaleController.getString("NoScheduledMessages", R.string.NoScheduledMessages); + emptyMessage = LocaleController.getString(R.string.NoScheduledMessages); } else if (currentUser != null && currentUser.id != 777000 && currentUser.id != 429000 && currentUser.id != 4244000 && MessagesController.isSupportUser(currentUser)) { - emptyMessage = LocaleController.getString("GotAQuestion", R.string.GotAQuestion); + emptyMessage = LocaleController.getString(R.string.GotAQuestion); } else if (currentUser == null || currentUser.self || currentUser.deleted || userBlocked) { - emptyMessage = LocaleController.getString("NoMessages", R.string.NoMessages); + emptyMessage = LocaleController.getString(R.string.NoMessages); } if (emptyMessage == null) { greetingsViewContainer = new ChatGreetingsView(getContext(), currentUser, distance, currentAccount, preloadedGreetingsSticker, themeDelegate); @@ -27810,7 +28942,7 @@ private void createEmptyView() { emptyView.setGravity(Gravity.CENTER); emptyView.setTextColor(getThemedColor(Theme.key_chat_serviceText)); emptyView.setBackground(Theme.createServiceDrawable(AndroidUtilities.dp(6), emptyView, contentView, getThemedPaint(Theme.key_paint_chatActionBackground))); - emptyView.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf")); + emptyView.setTypeface(AndroidUtilities.getTypeface(AndroidUtilities.TYPEFACE_ROBOTO_MEDIUM)); emptyView.setPadding(AndroidUtilities.dp(10), AndroidUtilities.dp(2), AndroidUtilities.dp(10), AndroidUtilities.dp(3)); emptyViewContainer.addView(emptyView, new FrameLayout.LayoutParams(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.CENTER)); } @@ -27884,10 +29016,15 @@ private void showMultipleReactionsPromo(ChatMessageCell cell, ReactionsLayoutInB } } - public void selectReaction(MessageObject primaryMessage, ReactionsContainerLayout reactionsLayout, View fromView, float x, float y, ReactionsLayoutInBubble.VisibleReaction visibleReaction, boolean fromDoubleTap, boolean bigEmoji, boolean addToRecent) { + public void selectReaction(MessageObject primaryMessage, ReactionsContainerLayout reactionsLayout, View fromView, float x, float y, ReactionsLayoutInBubble.VisibleReaction visibleReaction, boolean fromDoubleTap, boolean bigEmoji, boolean addToRecent, boolean withoutAnimation) { if (isInScheduleMode() || primaryMessage == null) { return; } + + if (getDialogId() == getUserConfig().getClientUserId() && !getUserConfig().isPremium() && primaryMessage.messageOwner != null && (primaryMessage.messageOwner.reactions == null || (primaryMessage.messageOwner.reactions.reactions_as_tags || primaryMessage.messageOwner.reactions.results.isEmpty()))) { + new PremiumFeatureBottomSheet(ChatActivity.this, PremiumPreviewFragment.PREMIUM_FEATURE_SAVED_TAGS, true).show(); + return; + } ReactionsEffectOverlay.removeCurrent(false); int currentChosenReactions = primaryMessage.getChoosenReactions().size(); @@ -27920,6 +29057,9 @@ public void selectReaction(MessageObject primaryMessage, ReactionsContainerLayou getSendMessagesHelper().sendReaction(primaryMessage, visibleReactions, added ? visibleReaction : null, bigEmoji, addToRecent, ChatActivity.this, updateReactionRunnable = new Runnable() { @Override public void run() { + if (withoutAnimation) { + return; + } if (updateReactionRunnable != null) { updateReactionRunnable = null; if (fromDoubleTap) { @@ -27950,11 +29090,13 @@ public void run() { } }); - if (fromDoubleTap) { + if (fromDoubleTap || withoutAnimation) { updateMessageAnimated(primaryMessage, true); updateReactionRunnable.run(); } - AndroidUtilities.runOnUIThread(updateReactionRunnable, 50); + if (!withoutAnimation) { + AndroidUtilities.runOnUIThread(updateReactionRunnable, 50); + } } @SuppressLint("NotifyDataSetChanged") @@ -27980,13 +29122,25 @@ private void updateMessageAnimated(MessageObject message, boolean updateReaction chatAdapter.notifyDataSetChanged(true); } else { MessageObject messageInList = messagesDict[0].get(message.getId()); - int index = messages.indexOf(messageInList); if (updateReactions) { message.forceUpdate = true; message.reactionsChanged = true; } - if (index >= 0) { - chatAdapter.notifyItemChanged(chatAdapter.messagesStartRow + index); + if (chatAdapter.isFiltered) { + MessageObject filteredMessage = filteredMessagesDict != null ? filteredMessagesDict.get(message.getId()) : null; + int index = chatAdapter.filteredMessages.indexOf(filteredMessage); + if (filteredMessage != null && updateReactions) { + filteredMessage.forceUpdate = true; + filteredMessage.reactionsChanged = true; + } + if (index >= 0) { + chatAdapter.notifyItemChanged(chatAdapter.messagesStartRow + index); + } + } else { + int index = messages.indexOf(messageInList); + if (index >= 0) { + chatAdapter.notifyItemChanged(chatAdapter.messagesStartRow + index); + } } } }); @@ -29131,9 +30285,11 @@ public boolean didSelectDialogs(DialogsActivity fragment, ArrayList openSearchWithText(text), 200); + return; + } if (!actionBar.isSearchFieldVisible()) { AndroidUtilities.updateViewVisibilityAnimated(avatarContainer, false, 0.95f, true); if (headerItem != null) { @@ -29564,12 +30739,10 @@ private void openSearchWithText(String text) { searchItem.openSearch(openSearchKeyboard); } } - if (text != null) { - if (searchItem != null) { - searchItem.setSearchFieldText(text, false); - } - getMediaDataController().searchMessagesInChat(text, dialog_id, mergeDialogId, classGuid, 0, threadMessageId, searchingUserMessages, searchingChatMessages, searchingReaction); + if (searchItem != null) { + searchItem.setSearchFieldText(text, false); } + getMediaDataController().searchMessagesInChat(searchingQuery = (text == null ? "" : text), dialog_id, mergeDialogId, classGuid, 0, threadMessageId, false, searchingUserMessages, searchingChatMessages, !TextUtils.isEmpty(text), searchingReaction); updatePinnedMessageView(true); } @@ -30142,7 +31315,7 @@ private void removeMessageObject(MessageObject messageObject) { return; } messages.remove(index); - if (chatAdapter != null) { + if (chatAdapter != null && !chatAdapter.isFiltered) { chatAdapter.notifyItemRemoved(chatAdapter.messagesStartRow + index); } } @@ -30744,7 +31917,7 @@ void openPhotoViewerForMessage(ChatMessageCell cell, MessageObject message) { } PhotoViewer.getInstance().openPhoto(arrayList, arrayList.indexOf(message), dialog_id, 0, getTopicId(),photoViewerProvider); } else { - PhotoViewer.getInstance().openPhoto(message, ChatActivity.this, message.type != 0 ? dialog_id : 0, message.type != 0 ? mergeDialogId : 0, message.type != 0 ? getTopicId() : 0, photoViewerProvider); + PhotoViewer.getInstance().openPhoto(message, ChatActivity.this, message.type != 0 ? dialog_id : 0, message.type != 0 ? mergeDialogId : 0, message.type != 0 ? getTopicId() : 0, photoViewerProvider); } hideHints(false); MediaController.getInstance().resetGoingToShowMessageObject(); @@ -30787,6 +31960,7 @@ public class ChatActivityAdapter extends RecyclerAnimationScrollHelper.Animatabl private Context mContext; private boolean isBot; private int rowCount; + private int hintRow = -5; private int botInfoRow = -5; private int botInfoEmptyRow = -5; private int loadingUpRow = -5; @@ -30794,6 +31968,16 @@ public class ChatActivityAdapter extends RecyclerAnimationScrollHelper.Animatabl public int messagesStartRow; private int messagesEndRow; + public ArrayList getMessages() { + if (isFrozen) { + return frozenMessages; + } else if (isFiltered) { + return filteredMessages; + } else { + return ChatActivity.this.messages; + } + } + public boolean isFrozen; public ArrayList frozenMessages = new ArrayList<>(); @@ -30810,14 +31994,17 @@ public ChatActivityAdapter(Context context) { public void updateRowsSafe() { int prevRowCount = rowCount; int prevBotInfoRow = botInfoRow; + int prevHintRow = hintRow; int prevLoadingUpRow = loadingUpRow; int prevLoadingDownRow = loadingDownRow; int prevMessagesStartRow = messagesStartRow; int prevMessagesEndRow = messagesEndRow; updateRowsInternal(); if (prevRowCount != rowCount || prevBotInfoRow != botInfoRow || - prevLoadingUpRow != loadingUpRow || prevLoadingDownRow != loadingDownRow || - prevMessagesStartRow != messagesStartRow || prevMessagesEndRow != messagesEndRow) { + prevLoadingUpRow != loadingUpRow || prevLoadingDownRow != loadingDownRow || + prevMessagesStartRow != messagesStartRow || prevMessagesEndRow != messagesEndRow || + prevHintRow != hintRow + ) { notifyDataSetChanged(false); } } @@ -30832,6 +32019,11 @@ private void updateRowsInternal() { } else { messages = ChatActivity.this.messages; } + if (chatMode == MODE_SAVED && isInsideContainer) { + hintRow = rowCount++; + } else { + hintRow = -5; + } if (!messages.isEmpty()) { if (!isFiltered && (!forwardEndReached[0] || mergeDialogId != 0 && !forwardEndReached[1]) && !hideForwardEndReached) { loadingDownRow = rowCount++; @@ -30904,8 +32096,10 @@ public long getItemId(int position) { return 2; } else if (position == loadingDownRow) { return 3; + } else if (position == hintRow) { + return 4; } - return 4; + return 5; } @Override @@ -31160,8 +32354,16 @@ public void needOpenUserProfile(long uid) { @Override public void didPressReplyMessage(ChatActionCell cell, int id) { - MessageObject messageObject = cell.getMessageObject(); - scrollToMessageId(id, messageObject.getId(), true, messageObject.getDialogId() == mergeDialogId ? 1 : 0, true, 0); + Runnable scroll = () -> { + MessageObject messageObject = cell.getMessageObject(); + scrollToMessageId(id, messageObject.getId(), true, messageObject.getDialogId() == mergeDialogId ? 1 : 0, true, 0); + }; + if (chatAdapter.isFiltered) { + setFilterMessages(false, true, true); + AndroidUtilities.runOnUIThread(scroll, 80); + } else { + scroll.run(); + } } @Override @@ -31222,6 +32424,13 @@ public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) { } else if (position == loadingDownRow || position == loadingUpRow) { ChatLoadingCell loadingCell = (ChatLoadingCell) holder.itemView; loadingCell.setProgressVisible(loadsCount > 1); + } else if (position == hintRow) { + ChatActionCell actionCell = (ChatActionCell) holder.itemView; + createHint2MessageObject(); + actionCell.setMessageObject(hint2MessageObject); + actionCell.setCustomText(LocaleController.getString(R.string.SavedMessagesProfileHint)); + actionCell.setAlpha(1.0f); + actionCell.setSpoilersSuppressed(chatListView.getScrollState() != RecyclerView.SCROLL_STATE_IDLE); } else if (position >= messagesStartRow && position < messagesEndRow) { final ArrayList messages; if (isFrozen) { @@ -31259,7 +32468,7 @@ public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) { int prevPosition; int nextPosition; if (groupedMessages != null) { - MessageObject.GroupedMessagePosition pos = groupedMessages.positions.get(message); + MessageObject.GroupedMessagePosition pos = groupedMessages.getPosition(message); if (pos != null) { if (groupedMessages.isDocuments) { prevPosition = position + groupedMessages.posArray.indexOf(pos) + 1; @@ -31664,6 +32873,9 @@ public int getItemViewType(int position) { return 3; } } + if (position == hintRow) { + return 1; + } if (position >= messagesStartRow && position < messagesEndRow) { final ArrayList messages; if (isFrozen) { @@ -32086,47 +33298,9 @@ public boolean isEnabled(RecyclerView.ViewHolder holder) { } } - private float actionBarTagsT; - private ValueAnimator actionBarTagsAnimator; - private void showActionBarSearchTags(boolean show) { - if (actionBarSearchTags == null) return; - if (actionBarTagsAnimator != null) { - actionBarTagsAnimator.cancel(); - } - actionBarSearchTags.setVisibility(View.VISIBLE); - actionBarTagsAnimator = ValueAnimator.ofFloat(actionBarTagsT, show ? 1f : 0f); - actionBarTagsAnimator.addUpdateListener(valueAnimator1 -> { - actionBarTagsT = (float) valueAnimator1.getAnimatedValue(); - if (actionBarSearchTags != null) { - actionBarSearchTags.setBackgroundColor(actionBar.getBackgroundColor()); - actionBarSearchTags.setShown(actionBarTagsT); - } - }); - actionBarTagsAnimator.setInterpolator(CubicBezierInterpolator.EASE_OUT_QUINT); - actionBarTagsAnimator.setDuration(320); - actionBarTagsAnimator.addListener(new AnimatorListenerAdapter() { - @Override - public void onAnimationEnd(Animator animation) { - actionBarTagsT = show ? 1f : 0f; - if (actionBarSearchTags != null) { - actionBarSearchTags.setBackgroundColor(actionBar.getBackgroundColor()); - actionBarSearchTags.setShown(actionBarTagsT); - if (!show) { - actionBarSearchTags.setVisibility(View.GONE); - } - } - - invalidateChatListViewTopPadding = true; - updateChatListViewTopPadding(); - } - }); - actionBarTagsAnimator.start(); - } - + boolean searchWas; private class SearchItemListener extends ActionBarMenuItem.ActionBarMenuItemSearchListener { - boolean searchWas; - @Override public boolean canCollapseSearch() { if (messagesSearchListView.getTag() != null) { @@ -32143,12 +33317,16 @@ public void onSearchFilterCleared(FiltersView.MediaFilterData filterData) { actionBarSearchTags.clear(); } searchingReaction = null; - showSearchShowOther(false); + updateSearchUpDownButtonVisibility(true); + updatePagedownButtonVisibility(true); setFilterMessages(false); } @Override public void onSearchCollapse() { + searching = false; + updatePagedownButtonVisibility(true); + updateSearchUpDownButtonVisibility(true); if (searchCalendarButton != null) { searchCalendarButton.setVisibility(View.VISIBLE); } @@ -32163,7 +33341,7 @@ public void onSearchCollapse() { mentionContainer.getAdapter().setSearchingMentions(false); searchingUserMessages = null; searchingChatMessages = null; - searchItem.setSearchFieldHint(LocaleController.getString("Search", R.string.Search)); + searchItem.setSearchFieldHint(isSupportedTags() ? LocaleController.getString("SavedTagSearchHint", R.string.SavedTagSearchHint) : LocaleController.getString("Search", R.string.Search)); searchItem.setSearchFieldCaption(null); AndroidUtilities.updateViewVisibilityAnimated(avatarContainer, true, 0.95f, true); if (editTextItem != null && editTextItem.getTag() != null) { @@ -32240,31 +33418,36 @@ public void onSearchCollapse() { valueAnimator.start(); searchingReaction = null; - showSearchShowOther(false); + updateSearchUpDownButtonVisibility(true); + updatePagedownButtonVisibility(true); if (actionBarSearchTags != null) { actionBarSearchTags.clear(); + actionBarSearchTags.show(false); } - showActionBarSearchTags(false); setFilterMessages(false); } @Override public void onSearchExpand() { - if (threadMessageId != 0 || UserObject.isReplyUser(currentUser)) { + searching = true; + updatePagedownButtonVisibility(true); + updateSearchUpDownButtonVisibility(true); + if (threadMessageId != 0 && chatMode != MODE_SAVED || UserObject.isReplyUser(currentUser)) { openSearchWithText(null); } - if (!openSearchKeyboard) { - return; + if (openSearchKeyboard) { + saveKeyboardPositionBeforeTransition(); + if (!isInsideContainer) { + AndroidUtilities.requestAdjustResize(getParentActivity(), classGuid); + } + AndroidUtilities.runOnUIThread(() -> { + searchWas = false; + searchItem.getSearchField().requestFocus(); + AndroidUtilities.showKeyboard(searchItem.getSearchField()); + removeKeyboardPositionBeforeTransition(); + }, 500); + hideSendButtonHints(); } - saveKeyboardPositionBeforeTransition(); - AndroidUtilities.requestAdjustResize(getParentActivity(), classGuid); - AndroidUtilities.runOnUIThread(() -> { - searchWas = false; - searchItem.getSearchField().requestFocus(); - AndroidUtilities.showKeyboard(searchItem.getSearchField()); - removeKeyboardPositionBeforeTransition(); - }, 500); - hideSendButtonHints(); whiteActionBar = getDialogId() == getUserConfig().getClientUserId(); ValueAnimator valueAnimator = ValueAnimator.ofFloat(searchAnimationProgress, 1f); @@ -32272,7 +33455,9 @@ public void onSearchExpand() { valueAnimator.setInterpolator(CubicBezierInterpolator.EASE_OUT_QUINT); valueAnimator.setDuration(320); valueAnimator.start(); -// showActionBarSearchTags(actionBarSearchTags != null && actionBarSearchTags.hasFilters()); + if (actionBarSearchTags != null) { + actionBarSearchTags.show(!isInsideContainer && actionBarSearchTags != null && actionBarSearchTags.hasFilters()); + } } private float searchAnimationProgress; @@ -32283,7 +33468,7 @@ public void setSearchAnimationProgress(float progress) { if (whiteActionBar) { int color1 = getThemedColor(Theme.key_actionBarDefaultIcon); actionBar.setItemsColor(ColorUtils.blendARGB(color1, getThemedColor(Theme.key_actionBarActionModeDefaultIcon), searchAnimationProgress), false); - actionBar.setItemsColor(ColorUtils.blendARGB(getThemedColor(Theme.key_actionBarActionModeDefaultIcon), getThemedColor(Theme.key_actionBarActionModeDefaultIcon), searchAnimationProgress), true); + actionBar.setItemsColor(getThemedColor(Theme.key_actionBarActionModeDefaultIcon), true); color1 = getThemedColor(Theme.key_actionBarDefaultSelector); int color2 = getThemedColor(Theme.key_actionBarActionModeDefaultSelector); @@ -32293,7 +33478,10 @@ public void setSearchAnimationProgress(float progress) { actionBar.setSearchTextColor(ColorUtils.blendARGB(Theme.getColor(Theme.key_actionBarDefaultSearch), getThemedColor(Theme.key_windowBackgroundWhiteBlackText), searchAnimationProgress), false); actionBar.setSearchTextColor(ColorUtils.blendARGB(Theme.getColor(Theme.key_actionBarDefaultSearchPlaceholder), getThemedColor(Theme.key_windowBackgroundWhiteGrayText), searchAnimationProgress), true); actionBar.setSearchCursorColor(ColorUtils.blendARGB(Theme.getColor(Theme.key_actionBarDefaultSearch), getThemedColor(Theme.key_windowBackgroundWhiteBlueText), searchAnimationProgress)); - AndroidUtilities.setLightStatusBar(fragmentView, isLightStatusBar()); + + if (!isInsideContainer && getParentActivity() != null) { + AndroidUtilities.setLightStatusBar(getParentActivity().getWindow(), isLightStatusBar()); + } } if (fragmentView != null) { fragmentView.invalidate(); @@ -32304,7 +33492,7 @@ public void setSearchAnimationProgress(float progress) { public void onSearchPressed(EditText editText) { searchWas = true; updateSearchButtons(0, 0, -1); - getMediaDataController().searchMessagesInChat(editText.getText().toString(), dialog_id, mergeDialogId, classGuid, 0, threadMessageId, searchingUserMessages, searchingChatMessages, searchingReaction); + getMediaDataController().searchMessagesInChat(searchingQuery = editText.getText().toString(), dialog_id, mergeDialogId, classGuid, 0, threadMessageId, searchingUserMessages, searchingChatMessages, searchingReaction); } @Override @@ -32329,7 +33517,7 @@ public void onCaptionCleared() { searchingForUser = false; searchItem.setSearchFieldText("", true); } - searchItem.setSearchFieldHint(LocaleController.getString("Search", R.string.Search)); + searchItem.setSearchFieldHint(isSupportedTags() ? LocaleController.getString("SavedTagSearchHint", R.string.SavedTagSearchHint) : LocaleController.getString("Search", R.string.Search)); searchCalendarButton.setVisibility(View.VISIBLE); searchUserButton.setVisibility(View.VISIBLE); searchingUserMessages = null; @@ -32350,6 +33538,10 @@ private SearchItemListener getSearchItemListener() { return searchItemListener; } + private boolean isSupportedTags() { + return getUserConfig().getClientUserId() == getDialogId() && !getMessagesController().getSavedMessagesController().unsupported && getUserConfig().isPremium(); + } + private ChatMessageCellDelegate chatMessageCellDelegate; private ChatMessageCellDelegate getChatMessageCellDelegate() { if (chatMessageCellDelegate == null) { @@ -32458,8 +33650,8 @@ public void didPressSideButton(ChatMessageCell cell) { { includeStoryFromMessage = includeStory; } @Override public void dismissInternal() { - super.dismissInternal(); AndroidUtilities.requestAdjustResize(getParentActivity(), classGuid); + super.dismissInternal(); if (chatActivityEnterView.getVisibility() == View.VISIBLE) { fragmentView.requestLayout(); } @@ -32516,7 +33708,9 @@ protected void onSend(LongSparseArray dids, int count, TLRPC.TL_fo return; } if (dids.size() == 1) { - undoView.showWithAction(dids.valueAt(0).id, UndoView.ACTION_FWD_MESSAGES, count, topic, null, null); + if (dids.valueAt(0).id != getUserConfig().getClientUserId() || !BulletinFactory.of(ChatActivity.this).showForwardedBulletinWithTag(dids.valueAt(0).id, count)) { + undoView.showWithAction(dids.valueAt(0).id, UndoView.ACTION_FWD_MESSAGES, count, topic, null, null); + } } else { undoView.showWithAction(0, UndoView.ACTION_FWD_MESSAGES, count, dids.size(), null, null); } @@ -32556,7 +33750,7 @@ public boolean needPlayMessage(ChatMessageCell cell, MessageObject messageObject MediaController.getInstance().setVoiceMessagesPlaylist(result ? createVoiceMessagesPlaylist(messageObject, false) : null, false); return result; } else if (messageObject.isMusic()) { - return MediaController.getInstance().setPlaylist(messages, messageObject, mergeDialogId); + return MediaController.getInstance().setPlaylist(chatAdapter.getMessages(), messageObject, mergeDialogId, !chatAdapter.isFiltered, null); } return false; } @@ -32964,7 +34158,15 @@ public void didPressReaction(ChatMessageCell cell, TLRPC.ReactionCount reaction, if (getParentActivity() == null) { return; } - if (longpress) { + if (savedMessagesTagHint != null && savedMessagesTagHint.shown()) { + savedMessagesTagHint.hide(); + } + if (getUserConfig().getClientUserId() == getDialogId() && cell.areTags() && !getUserConfig().isPremium()) { + if (longpress) return; + new PremiumFeatureBottomSheet(ChatActivity.this, PremiumPreviewFragment.PREMIUM_FEATURE_SAVED_TAGS, true).show(); + return; + } + if (longpress || cell.areTags() && (isInsideContainer || searchingReaction != null && searchingReaction.isSame(reaction.reaction))) { if (!ChatObject.isChannelAndNotMegaGroup(currentChat) || dialog_id >= 0) { if (!NekoConfig.disableVibration.Bool()) cell.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS); @@ -33003,47 +34205,87 @@ protected void dispatchDraw(Canvas canvas) { }; scrimPopupContainerLayout.setLayoutParams(LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT)); - Rect backgroundPaddings = new Rect(); - Drawable shadowDrawable2 = ContextCompat.getDrawable(getParentActivity(), R.drawable.popup_fixed_alert).mutate(); - shadowDrawable2.setColorFilter(new PorterDuffColorFilter(getThemedColor(Theme.key_actionBarDefaultSubmenuBackground), PorterDuff.Mode.MULTIPLY)); - shadowDrawable2.getPadding(backgroundPaddings); - scrimPopupContainerLayout.setBackground(shadowDrawable2); - - ReactionsLayoutInBubble.ReactionButton button = cell.getReactionButton(ReactionsLayoutInBubble.VisibleReaction.fromTLReaction(reaction.reaction)); + final ReactionsLayoutInBubble.ReactionButton button = cell.getReactionButton(ReactionsLayoutInBubble.VisibleReaction.fromTLReaction(reaction.reaction)); if (button == null) { return; } + + Rect backgroundPaddings = new Rect(); + Drawable shadowDrawable2 = ContextCompat.getDrawable(getParentActivity(), R.drawable.popup_fixed_alert).mutate(); + shadowDrawable2.setColorFilter(new PorterDuffColorFilter(getThemedColor(Theme.key_actionBarDefaultSubmenuBackground), PorterDuff.Mode.MULTIPLY)); + shadowDrawable2.getPadding(backgroundPaddings); + scrimPopupContainerLayout.setBackground(shadowDrawable2); + float bottom = cell.reactionsLayoutInBubble.y + button.y + AndroidUtilities.dp(28); float left = cell.reactionsLayoutInBubble.x + button.x; int[] loc = new int[2]; cell.getLocationInWindow(loc); - scrimPopupContainerLayout.addView(new ReactedUsersListView(getParentActivity(), themeDelegate, currentAccount, cell.getPrimaryMessageObject(), reaction, false) - .setOnCustomEmojiSelectedListener((reactedUsersListView1, customEmojiStickerSets) -> { - EmojiPacksAlert alert = new EmojiPacksAlert(ChatActivity.this, getParentActivity(), themeDelegate, customEmojiStickerSets) { - @Override - public void dismiss() { - super.dismiss(); - dimBehindView(false); - } - }; - alert.setCalcMandatoryInsets(isKeyboardVisible()); - alert.setDimBehind(false); - closeMenu(false); - showDialog(alert); - }) - .setOnProfileSelectedListener((view1, userId, messagePeerReaction) -> { - Bundle args = new Bundle(); - if (userId > 0) { - args.putLong("user_id", userId); - } else { - args.putLong("chat_id", -userId); - } - args.putInt("report_reaction_message_id", cell.getMessageObject().getId()); - args.putLong("report_reaction_from_dialog_id", dialog_id); - ProfileActivity fragment = new ProfileActivity(args); - presentFragment(fragment); + final boolean tags = getUserConfig().getClientUserId() == getDialogId() && !getMessagesController().getSavedMessagesController().unsupported; + if (tags) { + MessagesController.getGlobalMainSettings().edit().putInt("savedsearchtaghint", 1).apply(); + + ActionBarPopupWindow.ActionBarPopupWindowLayout popupLayout = new ActionBarPopupWindow.ActionBarPopupWindowLayout(getParentActivity(), 0, getResourceProvider(), 0); + if (getUserConfig().isPremium()) { + ActionBarMenuSubItem editTag = new ActionBarMenuSubItem(getParentActivity(), false, false); + editTag.setTextAndIcon(LocaleController.getString(TextUtils.isEmpty(getMessagesController().getSavedTagName(reaction.reaction)) ? R.string.SavedTagLabelTag : R.string.SavedTagRenameTag), R.drawable.menu_tag_rename); + editTag.setMinimumWidth(160); + editTag.setOnClickListener(view -> { + closeMenu(); + SearchTagsList.openRenameTagAlert(getContext(), currentAccount, reaction.reaction, themeDelegate, false); + }); + popupLayout.addView(editTag); + } + if (!isInsideContainer && (searchingReaction == null || !searchingReaction.isSame(reaction.reaction)) && (chatMode == 0 || chatMode == MODE_SAVED)) { + ActionBarMenuSubItem filterByTag = new ActionBarMenuSubItem(getParentActivity(), false, false); + filterByTag.setTextAndIcon(LocaleController.getString(R.string.SavedTagFilterByTag), R.drawable.menu_tag_filter); + filterByTag.setMinimumWidth(160); + filterByTag.setOnClickListener(view -> { closeMenu(); - }), LayoutHelper.createFrame(240, LayoutHelper.WRAP_CONTENT)); + openSearchWithText(""); + if (actionBarSearchTags != null) { + actionBarSearchTags.setChosen(ReactionsLayoutInBubble.VisibleReaction.fromTLReaction(reaction.reaction), true); + } + }); + popupLayout.addView(filterByTag); + } + ActionBarMenuSubItem removeTag = new ActionBarMenuSubItem(getParentActivity(), false, false); + removeTag.setTextAndIcon(LocaleController.getString(R.string.SavedTagRemoveTag), R.drawable.menu_tag_delete); + removeTag.setMinimumWidth(160); + removeTag.setOnClickListener(view -> { + pressedReaction(cell, reaction); + }); + removeTag.setColors(Theme.getColor(Theme.key_color_red), Theme.getColor(Theme.key_color_red)); + popupLayout.addView(removeTag); + scrimPopupContainerLayout.addView(popupLayout); + } else { + scrimPopupContainerLayout.addView(new ReactedUsersListView(getParentActivity(), themeDelegate, currentAccount, cell.getPrimaryMessageObject(), reaction, false) + .setOnCustomEmojiSelectedListener((reactedUsersListView1, customEmojiStickerSets) -> { + EmojiPacksAlert alert = new EmojiPacksAlert(ChatActivity.this, getParentActivity(), themeDelegate, customEmojiStickerSets) { + @Override + public void dismiss() { + super.dismiss(); + dimBehindView(false); + } + }; + alert.setCalcMandatoryInsets(isKeyboardVisible()); + alert.setDimBehind(false); + closeMenu(false); + showDialog(alert); + }) + .setOnProfileSelectedListener((view1, userId, messagePeerReaction) -> { + Bundle args = new Bundle(); + if (userId > 0) { + args.putLong("user_id", userId); + } else { + args.putLong("chat_id", -userId); + } + args.putInt("report_reaction_message_id", cell.getMessageObject().getId()); + args.putLong("report_reaction_from_dialog_id", dialog_id); + ProfileActivity fragment = new ProfileActivity(args); + presentFragment(fragment); + closeMenu(); + }), LayoutHelper.createFrame(240, LayoutHelper.WRAP_CONTENT)); + } scrimPopupWindow = new ActionBarPopupWindow(scrimPopupContainerLayout, LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT) { @Override @@ -33093,10 +34335,16 @@ public void dismiss() { } int popupY; if (height < totalHeight) { - if (height < totalHeight / 2f && chatListView.getY() + cell.getY() + cell.reactionsLayoutInBubble.y + button.y > totalHeight / 2f) { - popupY = (int) (chatListView.getY() + cell.getY() + cell.reactionsLayoutInBubble.y + button.y - height); + float cellY = chatListView.getY() + cell.getY(); + if (isInsideContainer) { + int[] location = new int[2]; + cell.getLocationInWindow(location); + cellY = location[1]; + } + if (height < totalHeight / 2f && cellY + cell.reactionsLayoutInBubble.y + button.y > totalHeight / 2f) { + popupY = (int) (cellY + cell.reactionsLayoutInBubble.y + button.y - height); } else { - popupY = (int) (chatListView.getY() + cell.getY() + cell.reactionsLayoutInBubble.y + button.y + button.height); + popupY = (int) (cellY + cell.reactionsLayoutInBubble.y + button.y + button.height); } } else { popupY = inBubbleMode ? 0 : AndroidUtilities.statusBarHeight; @@ -33105,7 +34353,8 @@ public void dismiss() { chatListView.stopScroll(); chatLayoutManager.setCanScrollVertically(false); - scrimViewReaction = reaction.reaction instanceof TLRPC.TL_reactionEmoji ? ((TLRPC.TL_reactionEmoji) reaction.reaction).emoticon : null; + scrimViewReaction = reaction.reaction.hashCode(); + scrimViewReactionAnimated = reaction.reaction instanceof TLRPC.TL_reactionCustomEmoji && LiteMode.isEnabled(LiteMode.FLAG_ANIMATED_EMOJI_KEYBOARD); dimBehindView(cell, true); hideHints(false); if (topUndoView != null) { @@ -33118,12 +34367,50 @@ public void dismiss() { chatActivityEnterView.getEditField().setAllowDrawCursor(false); } } + } else if (cell.areTags() && (chatMode == 0 || chatMode == MODE_SAVED)) { + closeMenu(); + openSearchWithText(""); + if (actionBarSearchTags != null) { + actionBarSearchTags.setChosen(ReactionsLayoutInBubble.VisibleReaction.fromTLReaction(reaction.reaction), true); + } } else if (reaction != null) { - ReactionsLayoutInBubble.VisibleReaction visibleReaction = ReactionsLayoutInBubble.VisibleReaction.fromTLReaction(reaction.reaction); - selectReaction(cell.getPrimaryMessageObject(), null, null,0, 0, visibleReaction,false, false, false); + pressedReaction(cell, reaction); } } + private void pressedReaction(ChatMessageCell cell, TLRPC.ReactionCount reaction) { + ReactionsLayoutInBubble.VisibleReaction visibleReaction = ReactionsLayoutInBubble.VisibleReaction.fromTLReaction(reaction.reaction); + MessageObject messageObject = cell.getPrimaryMessageObject(); + selectReaction(cell.getPrimaryMessageObject(), null, null, 0, 0, visibleReaction,false, false, false, false); + if (messageObject != null & messageObject.messageOwner != null) { + if (chatAdapter.isFiltered) { + MessageObject realMessage = messagesDict[0].get(messageObject.getId()); + if (realMessage != null && realMessage.messageOwner != null) { + realMessage.messageOwner.reactions = messageObject.messageOwner.reactions; + } + } else if (!chatAdapter.isFiltered && searchingReaction != null) { + updateFilteredMessages(false); + } + } + if (chatAdapter.isFiltered && !cell.getPrimaryMessageObject().hasReaction(searchingReaction)) { + final MessageObject msg = cell.getPrimaryMessageObject(); + final MessageObject.GroupedMessages groupedMessages = getValidGroupedMessage(msg); + if (groupedMessages != null) { + for (int i = 0; i < groupedMessages.messages.size(); ++i) { + MessageObject gmsg = groupedMessages.messages.get(i); + getMediaDataController().removeMessageFromResults(gmsg.getId()); + } + } else { + getMediaDataController().removeMessageFromResults(msg.getId()); + } + if (messagesSearchAdapter != null) { + messagesSearchAdapter.notifyDataSetChanged(); + } + updateFilteredMessages(true); + } + } + + @Override public void didPressVoteButtons(ChatMessageCell cell, ArrayList buttons, int showCount, int x, int y) { if (showCount >= 0 || buttons.isEmpty()) { @@ -33229,7 +34516,7 @@ public void didPressChannelRecommendation(ChatMessageCell cell, TLRPC.Chat chat, Bundle args = new Bundle(); args.putLong("chat_id", chat.id); if (longPress) { - ActionBarPopupWindow.ActionBarPopupWindowLayout previewMenu = new ActionBarPopupWindow.ActionBarPopupWindowLayout(getParentActivity(), R.drawable.popup_fixed_alert, getResourceProvider(), ActionBarPopupWindow.ActionBarPopupWindowLayout.FLAG_SHOWN_FROM_BOTTOM); + ActionBarPopupWindow.ActionBarPopupWindowLayout previewMenu = new ActionBarPopupWindow.ActionBarPopupWindowLayout(getContext(), R.drawable.popup_fixed_alert, getResourceProvider(), ActionBarPopupWindow.ActionBarPopupWindowLayout.FLAG_SHOWN_FROM_BOTTOM); previewMenu.setBackgroundColor(getThemedColor(Theme.key_actionBarDefaultSubmenuBackground)); ActionBarMenuSubItem openChannel = new ActionBarMenuSubItem(getParentActivity(), false, false); @@ -33455,7 +34742,7 @@ public void didPressReplyMessage(ChatMessageCell cell, int id) { } return; } - if ((did != dialog_id || ChatObject.isForum(currentChat) && couldBeDifferentTopic) && did != Long.MAX_VALUE) { + if ((did != dialog_id || ChatObject.isForum(currentChat) && couldBeDifferentTopic) && did != Long.MAX_VALUE || chatMode == MODE_SAVED && (messageObject.replyMessageObject == null || messageObject.replyMessageObject.getSavedDialogId() != getTopicId())) { if (LaunchActivity.instance != null) { if (progressDialogCurrent != null) { progressDialogCurrent.cancel(); @@ -33484,10 +34771,19 @@ public void end(boolean replaced) { highlightMessageQuoteOffset = quoteOffset; showNoQuoteAlert = true; } - scrollToMessageId(id, messageObject.getId(), true, messageObject.getDialogId() == mergeDialogId ? 1 : 0, true, 0, () -> { - progressDialogAtMessageId = messageObject.getId(); - progressDialogAtMessageType = PROGRESS_REPLY; - }); + Runnable scroll = () -> { + scrollToMessageId(id, messageObject.getId(), true, messageObject.getDialogId() == mergeDialogId ? 1 : 0, true, 0, () -> { + progressDialogAtMessageId = messageObject.getId(); + progressDialogAtMessageType = PROGRESS_REPLY; + }); + }; + if (chatAdapter.isFiltered) { + setFilterMessages(searchingFiltered = false, true, false); + updateSearchButtons(getMediaDataController().getMask(), getMediaDataController().getSearchPosition(), getMediaDataController().getSearchCount()); + AndroidUtilities.runOnUIThread(scroll, 80); + } else { + scroll.run(); + } } } } @@ -33772,6 +35068,36 @@ public void end(boolean replaced) { } }; BoostDialogs.openGiveAwayStatusDialog(messageObject, progressDialogCurrent, getContext(), getResourceProvider()); + } else if (type == 21) { + if (ApplicationLoader.isStandaloneBuild()) { + if (LaunchActivity.instance != null) { + if (progressDialogCurrent != null) { + progressDialogCurrent.cancel(true); + } + progressDialogCurrent = cell == null || cell.getMessageObject() == null ? null : new Browser.Progress() { + @Override + public void init() { + progressDialogAtMessageId = cell.getMessageObject().getId(); + progressDialogAtMessageType = PROGRESS_INSTANT; + progressDialogLinkSpan = null; + cell.invalidate(); + } + + @Override + public void end(boolean replaced) { + if (!replaced) { + AndroidUtilities.runOnUIThread(ChatActivity.this::resetProgressDialogLoading, 250); + } + } + }; + LaunchActivity.instance.checkAppUpdate(true, progressDialogCurrent); + } + } +// else if (BuildVars.isHuaweiStoreApp()){ +// Browser.openUrl(getContext(), BuildVars.HUAWEI_STORE_URL); +// } else { +// Browser.openUrl(getContext(), BuildVars.PLAYSTORE_APP_URL); +// } } else if (type == 8) { PollVotesAlert.showForPoll(ChatActivity.this, messageObject); } else if (type == 0) { @@ -34062,6 +35388,11 @@ public boolean onAccessibilityAction(int action, Bundle arguments) { } return false; } + + @Override + public boolean doNotShowLoadingReply(MessageObject msg) { + return msg != null && msg.getDialogId() == UserObject.REPLY_BOT || (chatAdapter != null && chatAdapter.isFiltered); + } }; private void openUserProfile(long uid) { @@ -34211,6 +35542,12 @@ private boolean openLinkInternally(String urlFinal, ChatMessageCell cell, Charac if (threadId != 0 || topicId != 0 || commentId != 0) { return false; } else { + if (ChatObject.isForum(currentChat)) { + TLRPC.TL_forumTopic requestedForumTopic = getMessagesController().getTopicsController().findTopic(channelId, messageId); + if (requestedForumTopic != null) { + return forumTopic != null && forumTopic.id == requestedForumTopic.id; + } + } showScrollToMessageError = true; if (chatMode == MODE_PINNED) { chatActivityDelegate.openReplyMessage(messageId); @@ -34806,16 +36143,10 @@ public ArrayList getThemeDescriptions() { themeDescriptions.add(new ThemeDescription(replyCloseImageView, ThemeDescription.FLAG_IMAGECOLOR, null, null, null, null, Theme.key_chat_replyPanelClose)); themeDescriptions.add(new ThemeDescription(null, 0, null, null, null, selectedBackgroundDelegate, Theme.key_chat_replyPanelName)); - themeDescriptions.add(new ThemeDescription(searchUpButton, ThemeDescription.FLAG_IMAGECOLOR, null, null, null, null, Theme.key_chat_searchPanelIcons)); - themeDescriptions.add(new ThemeDescription(searchUpButton, ThemeDescription.FLAG_BACKGROUNDFILTER | ThemeDescription.FLAG_DRAWABLESELECTEDSTATE, null, null, null, null, Theme.key_actionBarActionModeDefaultSelector)); - themeDescriptions.add(new ThemeDescription(searchDownButton, ThemeDescription.FLAG_IMAGECOLOR, null, null, null, null, Theme.key_chat_searchPanelIcons)); - themeDescriptions.add(new ThemeDescription(searchDownButton, ThemeDescription.FLAG_BACKGROUNDFILTER | ThemeDescription.FLAG_DRAWABLESELECTEDSTATE, null, null, null, null, Theme.key_actionBarActionModeDefaultSelector)); themeDescriptions.add(new ThemeDescription(searchCalendarButton, ThemeDescription.FLAG_IMAGECOLOR, null, null, null, null, Theme.key_chat_searchPanelIcons)); themeDescriptions.add(new ThemeDescription(searchCalendarButton, ThemeDescription.FLAG_BACKGROUNDFILTER | ThemeDescription.FLAG_DRAWABLESELECTEDSTATE, null, null, null, null, Theme.key_actionBarActionModeDefaultSelector)); themeDescriptions.add(new ThemeDescription(searchUserButton, ThemeDescription.FLAG_IMAGECOLOR, null, null, null, null, Theme.key_chat_searchPanelIcons)); themeDescriptions.add(new ThemeDescription(searchUserButton, ThemeDescription.FLAG_BACKGROUNDFILTER | ThemeDescription.FLAG_DRAWABLESELECTEDSTATE, null, null, null, null, Theme.key_actionBarActionModeDefaultSelector)); - themeDescriptions.add(new ThemeDescription(searchCountText, ThemeDescription.FLAG_TEXTCOLOR, null, null, null, null, Theme.key_chat_searchPanelText)); - themeDescriptions.add(new ThemeDescription(searchAsListTogglerView, ThemeDescription.FLAG_BACKGROUNDFILTER | ThemeDescription.FLAG_DRAWABLESELECTEDSTATE, null, null, null, null, Theme.key_actionBarActionModeDefaultSelector)); themeDescriptions.add(new ThemeDescription(replyButton, ThemeDescription.FLAG_TEXTCOLOR | ThemeDescription.FLAG_IMAGECOLOR, null, null, null, null, Theme.key_actionBarActionModeDefaultIcon)); themeDescriptions.add(new ThemeDescription(replyButton, ThemeDescription.FLAG_BACKGROUNDFILTER | ThemeDescription.FLAG_DRAWABLESELECTEDSTATE, null, null, null, null, Theme.key_actionBarActionModeDefaultSelector)); @@ -35084,6 +36415,20 @@ public ChatAvatarContainer getAvatarContainer() { return avatarContainer; } + public void openedInstantly() { + fragmentOpened = true; + fragmentBeginToShow = true; + fragmentTransition = null; + contentView.invalidate(); + contentView.setSkipBackgroundDrawing(false); + toPullingDownTransition = false; + fragmentView.setAlpha(1f); + avatarContainer.setTranslationY(0); + avatarContainer.getAvatarImageView().setScaleX(1f); + avatarContainer.getAvatarImageView().setScaleY(1f); + avatarContainer.getAvatarImageView().setAlpha(1f); + } + @Override public AnimatorSet onCustomTransitionAnimation(boolean isOpen, Runnable callback) { if (isOpen && fromPullingDownTransition && getParentLayout() != null && getParentLayout().getFragmentStack().size() > 1) { @@ -36975,9 +38320,6 @@ private void checkLeaveChannelButton() { } public boolean supportsThanosEffect() { - if (chatListThanosEffect != null && chatListThanosEffect.destroyed) { - return false; - } return ThanosEffect.supports() && LiteMode.isEnabled(LiteMode.FLAG_CHAT_THANOS); } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ChatActivityContainer.java b/TMessagesProj/src/main/java/org/telegram/ui/ChatActivityContainer.java index 531cecad6d..0e004d6d3c 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ChatActivityContainer.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ChatActivityContainer.java @@ -14,6 +14,7 @@ import com.google.android.exoplayer2.util.Log; +import org.telegram.messenger.Utilities; import org.telegram.ui.ActionBar.BaseFragment; import org.telegram.ui.ActionBar.DrawerLayoutContainer; import org.telegram.ui.ActionBar.INavigationLayout; @@ -30,14 +31,27 @@ public class ChatActivityContainer extends FrameLayout { private final INavigationLayout parentLayout; private View fragmentView; - public ChatActivityContainer(Context context, INavigationLayout parentLayout, Bundle args) { + public ChatActivityContainer(Context context, Utilities.Callback0Return resizableView, INavigationLayout parentLayout, Bundle args) { super(context); this.parentLayout = parentLayout; - chatActivity = new ChatActivity(args); + chatActivity = new ChatActivity(args) { + @Override + public void setNavigationBarColor(int color) {} + + @Override + protected void onSearchLoadingUpdate(boolean loading) { + ChatActivityContainer.this.onSearchLoadingUpdate(loading); + } + }; + chatActivity.insideContainerResizableView = resizableView; chatActivity.isInsideContainer = true; } + protected void onSearchLoadingUpdate(boolean loading) { + + } + @Override protected void onAttachedToWindow() { super.onAttachedToWindow(); @@ -57,6 +71,7 @@ protected void onAttachedToWindow() { parent.removeView(fragmentView); } } + chatActivity.openedInstantly(); addView(fragmentView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT)); if (isActive) { chatActivity.onResume(); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ChatReactionsEditActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/ChatReactionsEditActivity.java index 4808e6422d..efa124fb1f 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ChatReactionsEditActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ChatReactionsEditActivity.java @@ -199,6 +199,7 @@ public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int positi infoCell.setText(ChatObject.isChannelAndNotMegaGroup(currentChat) ? LocaleController.getString("EnableReactionsChannelInfo", R.string.EnableReactionsChannelInfo) : LocaleController.getString("EnableReactionsGroupInfo", R.string.EnableReactionsGroupInfo)); } else { + infoCell.setForeground(Theme.getThemedDrawableByKey(getContext(), R.drawable.greydivider_bottom, Theme.key_windowBackgroundGrayShadow)); if (selectedType == SELECT_TYPE_SOME) { infoCell.setText(LocaleController.getString("EnableSomeReactionsInfo", R.string.EnableSomeReactionsInfo)); } else if (selectedType == SELECT_TYPE_ALL) { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ChooseSpeedLayout.java b/TMessagesProj/src/main/java/org/telegram/ui/ChooseSpeedLayout.java index de2350010e..d6230701e3 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ChooseSpeedLayout.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ChooseSpeedLayout.java @@ -24,7 +24,7 @@ public class ChooseSpeedLayout { - ActionBarPopupWindow.ActionBarPopupWindowLayout speedSwipeBackLayout; + public ActionBarPopupWindow.ActionBarPopupWindowLayout speedSwipeBackLayout; ActionBarMenuSlider.SpeedSlider slider; private static final float MIN_SPEED = 0.2f; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/AnimatedEmojiDrawable.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/AnimatedEmojiDrawable.java index ac5d2f0997..4cb085afb9 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/AnimatedEmojiDrawable.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/AnimatedEmojiDrawable.java @@ -604,7 +604,7 @@ protected boolean setImageBitmapByKey(Drawable drawable, String key, int type, b imageReceiver.setLayerNum(6656); } imageReceiver.setAspectFit(true); - if (cacheType == CACHE_TYPE_RENDERING_VIDEO || cacheType == STANDARD_LOTTIE_FRAME || cacheType == CACHE_TYPE_TAB_STRIP || cacheType == CACHE_TYPE_ALERT_PREVIEW_TAB_STRIP) { + if (cacheType == CACHE_TYPE_RENDERING_VIDEO || cacheType == CACHE_TYPE_SAVED_REACTION || cacheType == STANDARD_LOTTIE_FRAME || cacheType == CACHE_TYPE_TAB_STRIP || cacheType == CACHE_TYPE_ALERT_PREVIEW_TAB_STRIP) { imageReceiver.setAllowStartAnimation(false); imageReceiver.setAllowStartLottieAnimation(false); imageReceiver.setAutoRepeat(0); @@ -628,7 +628,7 @@ private void updateAutoRepeat(ImageReceiver imageReceiver) { imageReceiver.setAutoRepeatCount(2); } else if (cacheType == CACHE_TYPE_FORUM_TOPIC_LARGE || cacheType == CACHE_TYPE_SAVED_REACTION || cacheType == CACHE_TYPE_AVATAR_CONSTRUCTOR_PREVIEW || cacheType == CACHE_TYPE_TAB_STRIP || cacheType == CACHE_TYPE_ALERT_PREVIEW_TAB_STRIP) { imageReceiver.setAutoRepeatCount(1); - } else if (cacheType == CACHE_TYPE_EMOJI_CALL){ + } else if (cacheType == CACHE_TYPE_EMOJI_CALL) { imageReceiver.setAutoRepeatCount(0); } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/AnimatedTextView.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/AnimatedTextView.java index b32fbb7433..720f2936c8 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/AnimatedTextView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/AnimatedTextView.java @@ -1,5 +1,7 @@ package org.telegram.ui.Components; +import static org.telegram.messenger.AndroidUtilities.lerp; + import android.animation.Animator; import android.animation.AnimatorListenerAdapter; import android.animation.TimeInterpolator; @@ -93,6 +95,8 @@ public void layout(float offset) { private TimeInterpolator animateInterpolator = CubicBezierInterpolator.EASE_OUT_QUINT; private float moveAmplitude = 1f; + private float scaleAmplitude = 0; + private int alpha = 255; private final Rect bounds = new Rect(); @@ -163,8 +167,8 @@ public void draw(@NonNull Canvas canvas) { int fullWidth = bounds.width(); int fullHeight = bounds.height(); if (currentParts != null && oldParts != null && t != 1) { - float width = AndroidUtilities.lerp(oldWidth, currentWidth, t); - float height = AndroidUtilities.lerp(oldHeight, currentHeight, t); + float width = lerp(oldWidth, currentWidth, t); + float height = lerp(oldHeight, currentHeight, t); canvas.translate(0, (fullHeight - height) / 2f); for (int i = 0; i < currentParts.length; ++i) { Part current = currentParts[i]; @@ -179,7 +183,7 @@ public void draw(@NonNull Canvas canvas) { if (isRTL && !ignoreRTL) { oldX = oldWidth - (oldX + old.width); } - x = AndroidUtilities.lerp(oldX - old.left, x - current.left, t); + x = lerp(oldX - old.left, x - current.left, t); applyAlphaInternal(1f); } else { x -= current.left; @@ -198,6 +202,10 @@ public void draw(@NonNull Canvas canvas) { } } canvas.translate(x, y); + if (j < 0 && scaleAmplitude > 0) { + final float s = lerp(1f - scaleAmplitude, 1f, t); + canvas.scale(s, s, current.width / 2f, current.layout.getHeight() / 2f); + } current.layout.draw(canvas); canvas.restore(); } @@ -225,6 +233,10 @@ public void draw(@NonNull Canvas canvas) { } } canvas.translate(x, y); + if (scaleAmplitude > 0) { + final float s = lerp(1f, 1f - scaleAmplitude, t); + canvas.scale(s, s, old.width / 2f, old.layout.getHeight() / 2f); + } old.layout.draw(canvas); canvas.restore(); } @@ -249,7 +261,6 @@ public void draw(@NonNull Canvas canvas) { x += fullWidth - currentWidth; } } -// boolean isAppeared = currentLayoutToOldIndex != null && i < currentLayoutToOldIndex.length && currentLayoutToOldIndex[i] < 0; canvas.translate(x, 0); current.layout.draw(canvas); canvas.restore(); @@ -445,7 +456,7 @@ public float getWidth() { public float getCurrentWidth() { if (currentParts != null && oldParts != null) { - return AndroidUtilities.lerp(oldWidth, currentWidth, t); + return lerp(oldWidth, currentWidth, t); } return currentWidth; } @@ -458,7 +469,7 @@ public float getMaxWidth(AnimatedTextDrawable otherTextDrawable) { if (oldParts == null || otherTextDrawable.oldParts == null) { return Math.max(getCurrentWidth(), otherTextDrawable.getCurrentWidth()); } - return AndroidUtilities.lerp( + return lerp( Math.max(oldWidth, otherTextDrawable.oldWidth), Math.max(currentWidth, otherTextDrawable.currentWidth), Math.max(t, otherTextDrawable.t) @@ -865,6 +876,10 @@ public void setAnimationProperties(float moveAmplitude, long startDelay, long du animateInterpolator = interpolator; } + public void setScaleProperty(float scale) { + this.scaleAmplitude = scale; + } + public void copyStylesFrom(TextPaint paint) { setTextColor(paint.getColor()); setTextSize(paint.getTextSize()); @@ -913,7 +928,7 @@ public Rect getDirtyBounds() { } public float isNotEmpty() { - return AndroidUtilities.lerp( + return lerp( oldText == null || oldText.length() <= 0 ? 0f : 1f, currentText == null || currentText.length() <= 0 ? 0f : 1f, oldText == null ? 1f : t @@ -1056,6 +1071,10 @@ public void setAnimationProperties(float moveAmplitude, long startDelay, long du drawable.setAnimationProperties(moveAmplitude, startDelay, duration, interpolator); } + public void setScaleProperty(float scale) { + drawable.setScaleProperty(scale); + } + public AnimatedTextDrawable getDrawable() { return drawable; } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/AudioPlayerAlert.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/AudioPlayerAlert.java index fee86bb1fe..af2cae6ae4 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/AudioPlayerAlert.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/AudioPlayerAlert.java @@ -80,6 +80,7 @@ import org.telegram.messenger.SendMessagesHelper; import org.telegram.messenger.SharedConfig; import org.telegram.messenger.UserConfig; +import org.telegram.messenger.UserObject; import org.telegram.messenger.Utilities; import org.telegram.messenger.audioinfo.AudioInfo; import org.telegram.tgnet.TLRPC; @@ -462,6 +463,12 @@ public void setAlpha(float alpha) { actionBar.setTitle(ContactsController.formatName(user.first_name, user.last_name)); } } + } else if (did == UserConfig.getInstance(currentAccount).getClientUserId()) { + if (messageObject.getSavedDialogId() == UserObject.ANONYMOUS) { + actionBar.setTitle(LocaleController.getString(R.string.AnonymousForward)); + } else { + actionBar.setTitle(LocaleController.getString(R.string.SavedMessages)); + } } else if (DialogObject.isUserDialog(did)) { TLRPC.User user = MessagesController.getInstance(currentAccount).getUser(did); if (user != null) { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/BackupImageView.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/BackupImageView.java index 3bdd4a8e81..0732f4fc29 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/BackupImageView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/BackupImageView.java @@ -354,6 +354,10 @@ public void setAnimatedEmojiDrawable(AnimatedEmojiDrawable animatedEmojiDrawable invalidate(); } + public AnimatedEmojiDrawable getAnimatedEmojiDrawable() { + return animatedEmojiDrawable; + } + ValueAnimator roundRadiusAnimator; public void animateToRoundRadius(int animateToRad) { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/BlurredFrameLayout.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/BlurredFrameLayout.java index dd77a898dc..eea05353fe 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/BlurredFrameLayout.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/BlurredFrameLayout.java @@ -15,7 +15,7 @@ public class BlurredFrameLayout extends FrameLayout { - private final SizeNotifierFrameLayout sizeNotifierFrameLayout; + protected final SizeNotifierFrameLayout sizeNotifierFrameLayout; protected Paint backgroundPaint; public int backgroundColor = Color.TRANSPARENT; public int backgroundPaddingBottom; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/BottomSheetWithRecyclerListView.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/BottomSheetWithRecyclerListView.java index 9dec200294..1084597105 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/BottomSheetWithRecyclerListView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/BottomSheetWithRecyclerListView.java @@ -160,10 +160,10 @@ public void setTag(Object tag) { actionBar.setBackgroundColor(getThemedColor(Theme.key_dialogBackground)); actionBar.setTitleColor(getThemedColor(Theme.key_windowBackgroundWhiteBlackText)); actionBar.setItemsBackgroundColor(getThemedColor(Theme.key_actionBarActionModeDefaultSelector), false); + actionBar.setBackButtonImage(R.drawable.ic_ab_back); actionBar.setItemsColor(getThemedColor(Theme.key_actionBarActionModeDefaultIcon), false); actionBar.setCastShadows(true); - actionBar.setBackButtonImage(R.drawable.ic_ab_back); actionBar.setTitle(getTitle()); actionBar.setActionBarMenuOnItemClick(new ActionBar.ActionBarMenuOnItemClick() { @Override diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/Bulletin.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/Bulletin.java index 47c5213e46..3a7ce0f0e9 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/Bulletin.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/Bulletin.java @@ -22,10 +22,15 @@ import android.graphics.Typeface; import android.graphics.drawable.Drawable; import android.os.Build; +import android.os.Bundle; +import android.text.SpannableString; +import android.text.SpannableStringBuilder; +import android.text.Spanned; import android.text.StaticLayout; import android.text.TextPaint; import android.text.TextUtils; import android.text.method.LinkMovementMethod; +import android.util.Log; import android.util.Property; import android.util.TypedValue; import android.view.GestureDetector; @@ -57,14 +62,20 @@ import org.telegram.messenger.AndroidUtilities; import org.telegram.messenger.Emoji; import org.telegram.messenger.LocaleController; +import org.telegram.messenger.MediaDataController; +import org.telegram.messenger.MessageObject; import org.telegram.messenger.MessagesController; import org.telegram.messenger.NotificationCenter; import org.telegram.messenger.R; +import org.telegram.messenger.UserConfig; +import org.telegram.messenger.support.SparseLongArray; import org.telegram.tgnet.TLRPC; import org.telegram.ui.ActionBar.BaseFragment; import org.telegram.ui.ActionBar.Theme; import org.telegram.ui.ChatActivity; +import org.telegram.ui.Components.Reactions.ReactionsLayoutInBubble; import org.telegram.ui.DialogsActivity; +import org.telegram.ui.LaunchActivity; import java.lang.annotation.Retention; import java.util.ArrayList; @@ -1023,12 +1034,16 @@ private void setInOutOffset(float offset) { private Matrix clipMatrix; private Paint clipPaint; + protected int getMeasuredBackgroundHeight() { + return getMeasuredHeight(); + } + @Override protected void dispatchDraw(Canvas canvas) { if (bulletin == null) { return; } - background.setBounds(getPaddingLeft(), getPaddingTop(), getMeasuredWidth() - getPaddingRight(), getMeasuredHeight() - getPaddingBottom()); + background.setBounds(getPaddingLeft(), getPaddingTop(), getMeasuredWidth() - getPaddingRight(), getMeasuredBackgroundHeight() - getPaddingBottom()); if (isTransitionRunning() && delegate != null) { final float top = delegate.getTopOffset(bulletin.tag) - getY(); final float bottom = ((View) getParent()).getMeasuredHeight() - getBottomOffset() - getY(); @@ -1044,7 +1059,7 @@ protected void dispatchDraw(Canvas canvas) { if (clipPaint == null) { clipPaint = new Paint(Paint.ANTI_ALIAS_FLAG); clipPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OUT)); - clipGradient = new LinearGradient(0, 0, 0, AndroidUtilities.dp(8), this.top ? new int[] {0xff000000, 0} : new int[] {0, 0xff000000}, new float[] { 0, 1 }, Shader.TileMode.CLAMP); + clipGradient = new LinearGradient(0, 0, 0, AndroidUtilities.dp(8), this.top ? new int[]{0xff000000, 0} : new int[]{0, 0xff000000}, new float[]{0, 1}, Shader.TileMode.CLAMP); clipMatrix = new Matrix(); clipGradient.setLocalMatrix(clipMatrix); clipPaint.setShader(clipGradient); @@ -1090,6 +1105,7 @@ public ButtonLayout(@NonNull Context context, Theme.ResourcesProvider resourcesP } private boolean wrapWidth; + public void setWrapWidth() { wrapWidth = true; } @@ -1324,10 +1340,156 @@ public void hideImage() { } } + public static class LottieLayoutWithReactions extends LottieLayout implements NotificationCenter.NotificationCenterDelegate { + + private ReactionsContainerLayout reactionsContainerLayout; + private SparseLongArray newMessagesByIds; + private final BaseFragment fragment; + private final int messagesCount; + + public LottieLayoutWithReactions(BaseFragment fragment, int messagesCount) { + super(fragment.getContext(), fragment.getResourceProvider()); + this.fragment = fragment; + this.messagesCount = messagesCount; + init(); + } + + private Bulletin bulletin; + public void setBulletin(Bulletin b) { + this.bulletin = b; + } + + public void init() { + textView.setLayoutParams(LayoutHelper.createFrameRelatively(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.START | Gravity.TOP, 56, 6, 8, 0)); + imageView.setLayoutParams(LayoutHelper.createFrameRelatively(56, 48, Gravity.START | Gravity.TOP)); + reactionsContainerLayout = new ReactionsContainerLayout(ReactionsContainerLayout.TYPE_TAGS, fragment, getContext(), fragment.getCurrentAccount(), fragment.getResourceProvider()) { + @Override + protected void onShownCustomEmojiReactionDialog() { + Bulletin bulletin = Bulletin.getVisibleBulletin(); + if (bulletin != null) { + bulletin.setCanHide(false); + } + reactionsContainerLayout.getReactionsWindow().windowView.setOnClickListener(v -> { + hideReactionsDialog(); + Bulletin.hideVisible(); + }); + } + + @Override + public boolean dispatchTouchEvent(MotionEvent ev) { + if (ev.getAction() == MotionEvent.ACTION_DOWN) { + if (bulletin != null) { + bulletin.setCanHide(false); + } + } else if (ev.getAction() == MotionEvent.ACTION_UP) { + if (bulletin != null) { + bulletin.setCanHide(true); + } + } + return super.dispatchTouchEvent(ev); + } + }; + reactionsContainerLayout.setPadding(AndroidUtilities.dp(4), AndroidUtilities.dp(24), AndroidUtilities.dp(4), AndroidUtilities.dp(0)); + reactionsContainerLayout.setDelegate(new ReactionsContainerLayout.ReactionsContainerDelegate() { + @Override + public void onReactionClicked(View view, ReactionsLayoutInBubble.VisibleReaction visibleReaction, boolean longpress, boolean addToRecent) { + if (newMessagesByIds == null) { + return; + } + final long selfId = UserConfig.getInstance(fragment.getCurrentAccount()).getClientUserId(); + boolean isFragmentSavedMessages = fragment instanceof ChatActivity && ((ChatActivity) fragment).getDialogId() == selfId; + int lastMessageId = 0; + for (int i = 0; i < newMessagesByIds.size(); i++) { + int key = newMessagesByIds.keyAt(i); + TLRPC.Message message = new TLRPC.Message(); + message.dialog_id = fragment.getUserConfig().getClientUserId(); + message.id = key; + MessageObject messageObject = new MessageObject(fragment.getCurrentAccount(), message, false, false); + ArrayList visibleReactions = new ArrayList<>(); + visibleReactions.add(visibleReaction); + fragment.getSendMessagesHelper().sendReaction(messageObject, visibleReactions, visibleReaction, false, false, fragment, null); + lastMessageId = message.id; + } + hideReactionsDialog(); + Bulletin.hideVisible(); + showTaggedReactionToast(visibleReaction, fragment.getCurrentAccount(), lastMessageId, !isFragmentSavedMessages); + } + + private void showTaggedReactionToast(ReactionsLayoutInBubble.VisibleReaction visibleReaction, int currentAccount, int messageId, boolean addViewButton) { + AndroidUtilities.runOnUIThread(() -> { + BaseFragment baseFragment = LaunchActivity.getLastFragment(); + TLRPC.Document document; + if (visibleReaction.documentId == 0) { + TLRPC.TL_availableReaction availableReaction = MediaDataController.getInstance(UserConfig.selectedAccount).getReactionsMap().get(visibleReaction.emojicon); + if (availableReaction == null) { + return; + } + document = availableReaction.activate_animation; + } else { + document = AnimatedEmojiDrawable.findDocument(UserConfig.selectedAccount, visibleReaction.documentId); + } + + if (document == null || baseFragment == null) { + return; + } + + BulletinFactory.of(baseFragment).createMessagesTaggedBulletin(messagesCount, document, addViewButton ? () -> { + Bundle args = new Bundle(); + args.putLong("user_id", UserConfig.getInstance(currentAccount).getClientUserId()); + args.putInt("message_id", messageId); + baseFragment.presentFragment(new ChatActivity(args)); + } : null).show(true); + }, 300); + } + }); + reactionsContainerLayout.setTop(true); + reactionsContainerLayout.setClipChildren(false); + reactionsContainerLayout.setClipToPadding(false); + reactionsContainerLayout.setVisibility(View.VISIBLE); + reactionsContainerLayout.setBubbleOffset(-AndroidUtilities.dp(80)); + reactionsContainerLayout.setHint(LocaleController.getString(R.string.SavedTagReactionsHint)); + addView(reactionsContainerLayout, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, 92.5f, Gravity.CENTER_HORIZONTAL, 0, 36, 0, 0)); + reactionsContainerLayout.setMessage(null, null); + } + + @Override + protected void onAttachedToWindow() { + super.onAttachedToWindow(); + NotificationCenter.getInstance(UserConfig.selectedAccount).addObserver(this, NotificationCenter.savedMessagesForwarded); + } + + @Override + protected void onDetachedFromWindow() { + super.onDetachedFromWindow(); + NotificationCenter.getInstance(UserConfig.selectedAccount).removeObserver(this, NotificationCenter.savedMessagesForwarded); + } + + public void hideReactionsDialog() { + if (reactionsContainerLayout.getReactionsWindow() != null) { + reactionsContainerLayout.dismissWindow(); + if (reactionsContainerLayout.getReactionsWindow().containerView != null) { + reactionsContainerLayout.getReactionsWindow().containerView.animate().alpha(0).setDuration(180).start(); + } + } + } + + @Override + protected int getMeasuredBackgroundHeight() { + return textView.getMeasuredHeight() + AndroidUtilities.dp(30); + } + + @Override + public void didReceivedNotification(int id, int account, Object... args) { + if (id == NotificationCenter.savedMessagesForwarded) { + newMessagesByIds = (SparseLongArray) args[0]; + } + } + } + public static class LottieLayout extends ButtonLayout { public RLottieImageView imageView; - public LinkSpanDrawable.LinksTextView textView; + public TextView textView; private int textColor; @@ -1339,6 +1501,10 @@ public LottieLayout(@NonNull Context context, Theme.ResourcesProvider resourcesP addView(imageView, LayoutHelper.createFrameRelatively(56, 48, Gravity.START | Gravity.CENTER_VERTICAL)); textView = new LinkSpanDrawable.LinksTextView(context) { + { + setDisablePaddingsOffset(true); + } + @Override public void setText(CharSequence text, BufferType type) { text = Emoji.replaceEmoji(text, getPaint().getFontMetricsInt(), AndroidUtilities.dp(13), false); @@ -1346,7 +1512,6 @@ public void setText(CharSequence text, BufferType type) { } }; NotificationCenter.listenEmojiLoading(textView); - textView.setDisablePaddingsOffset(true); textView.setSingleLine(); textView.setTypeface(Typeface.SANS_SERIF); textView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 15); @@ -1804,11 +1969,12 @@ public static BulletinWindowLayout make(Context context) { } private final BulletinWindowLayout container; + private BulletinWindow(Context context, Delegate delegate) { super(context); setContentView( - container = new BulletinWindowLayout(context), - new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT) + container = new BulletinWindowLayout(context), + new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT) ); if (Build.VERSION.SDK_INT >= 21) { container.setFitsSystemWindows(true); @@ -1822,7 +1988,7 @@ private BulletinWindow(Context context, Delegate delegate) { } }); if (Build.VERSION.SDK_INT >= 30) { - container.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_STABLE | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION); + container.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_STABLE | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION); } else { container.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_STABLE | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN); } 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 a9f3e0b4a1..337b4be51c 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/BulletinFactory.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/BulletinFactory.java @@ -3,21 +3,24 @@ import android.content.Context; import android.graphics.PorterDuff; import android.graphics.PorterDuffColorFilter; +import android.graphics.Typeface; import android.graphics.drawable.Drawable; +import android.os.Bundle; import android.text.Spannable; +import android.text.SpannableString; import android.text.SpannableStringBuilder; import android.text.Spanned; import android.text.TextPaint; +import android.text.TextUtils; import android.text.style.ClickableSpan; -import android.util.Log; import android.util.TypedValue; +import android.view.Gravity; import android.view.HapticFeedbackConstants; import android.view.ViewGroup; import android.os.Build; import android.view.View; import android.view.ViewGroup; import android.widget.FrameLayout; -import android.widget.ImageView; import androidx.annotation.CheckResult; import androidx.annotation.NonNull; @@ -42,6 +45,7 @@ import org.telegram.tgnet.TLRPC; import org.telegram.ui.ActionBar.BaseFragment; import org.telegram.ui.ActionBar.Theme; +import org.telegram.ui.ChatActivity; import org.telegram.ui.LaunchActivity; import org.telegram.ui.PremiumPreviewFragment; import org.telegram.ui.Stories.recorder.HintView2; @@ -1034,6 +1038,32 @@ public static Bulletin createInviteSentBulletin(Context context, FrameLayout con return Bulletin.make(containerLayout, layout, Bulletin.DURATION_SHORT); } + public boolean showForwardedBulletinWithTag(long did, int messagesCount) { + if (!UserConfig.getInstance(UserConfig.selectedAccount).isPremium()) { + return false; + } + final Bulletin.LottieLayoutWithReactions layout = new Bulletin.LottieLayoutWithReactions(fragment, messagesCount); + CharSequence text; + if (did == UserConfig.getInstance(UserConfig.selectedAccount).clientUserId) { + if (messagesCount <= 1) { + text = AndroidUtilities.replaceSingleTag(LocaleController.getString(R.string.FwdMessageToSavedMessages), -1, AndroidUtilities.REPLACING_TAG_TYPE_LINKBOLD, SavedMessagesController::openSavedMessages); + } else { + text = AndroidUtilities.replaceSingleTag(LocaleController.getString(R.string.FwdMessagesToSavedMessages), -1, AndroidUtilities.REPLACING_TAG_TYPE_LINKBOLD, SavedMessagesController::openSavedMessages); + } + } else { + return false; + } + layout.setAnimation(R.raw.saved_messages, 36, 36); + layout.textView.setText(text); + layout.textView.setSingleLine(false); + layout.textView.setMaxLines(2); + Bulletin bulletin = create(layout, 3500); + layout.setBulletin(bulletin); + bulletin.hideAfterBottomSheet(false); + bulletin.show(true); + return true; + } + @CheckResult public static Bulletin createForwardedBulletin(Context context, FrameLayout containerLayout, int dialogsCount, long did, int messagesCount, int backgroundColor, int textColor) { final Bulletin.LottieLayout layout = new Bulletin.LottieLayout(context, null, backgroundColor, textColor); @@ -1190,6 +1220,39 @@ public static Bulletin createSoundEnabledBulletin(BaseFragment fragment, int set layout.textView.setText(text); return Bulletin.make(fragment, layout, Bulletin.DURATION_SHORT); } + + public Bulletin createMessagesTaggedBulletin(int messagesCount, TLRPC.Document document, Runnable onViewButton) { + final Bulletin.LottieLayout layout = new Bulletin.LottieLayout(getContext(), resourcesProvider); + layout.setAnimation(R.raw.tag_icon_3, 36, 36); + layout.removeView(layout.textView); + layout.textView = new AnimatedEmojiSpan.TextViewEmojis(layout.getContext()); + layout.textView.setTypeface(Typeface.SANS_SERIF); + layout.textView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 15); + layout.textView.setEllipsize(TextUtils.TruncateAt.END); + layout.textView.setPadding(0, 0, 0, AndroidUtilities.dp(8)); + + TextPaint textPaint = new TextPaint(); + textPaint.setTextSize(AndroidUtilities.dp(20)); + SpannableString spannable = new SpannableString("d"); + spannable.setSpan(new AnimatedEmojiSpan(document, textPaint.getFontMetricsInt()), 0, spannable.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); + layout.textView.setText( + new SpannableStringBuilder(messagesCount > 1 ? + LocaleController.formatPluralString("SavedTagMessagesTagged", messagesCount) : + LocaleController.getString(R.string.SavedTagMessageTagged)) + .append(" ") + .append(spannable) + ); + + if (onViewButton != null) { + layout.setButton(new Bulletin.UndoButton(getContext(), true, resourcesProvider).setText(LocaleController.getString(R.string.ViewAction)).setUndoAction(onViewButton)); + } + + layout.setTextColor(Theme.getColor(Theme.key_undo_infoColor, resourcesProvider)); + layout.addView(layout.textView, LayoutHelper.createFrameRelatively(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.START | Gravity.CENTER_VERTICAL, 56, 2, 8, 0)); + + return create(layout, Bulletin.DURATION_LONG); + } + //endregion public static class UndoObject { 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 88b736f8da..8e43bb7441 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/ChatActivityEnterView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/ChatActivityEnterView.java @@ -1126,9 +1126,14 @@ protected boolean onSetAlpha(int alpha) { return super.onSetAlpha(alpha); } + private VirtualViewHelper virtualViewHelper; + public ControlsView(Context context) { super(context); + virtualViewHelper = new VirtualViewHelper(this); + ViewCompat.setAccessibilityDelegate(this, virtualViewHelper); + periodDrawable = new CaptionContainerView.PeriodDrawable(); periodDrawable.setCallback(this); periodDrawable.setValue(1, voiceOnce, false); @@ -1552,6 +1557,11 @@ protected void onDraw(Canvas canvas) { } } + @Override + protected boolean dispatchHoverEvent(MotionEvent event) { + return super.dispatchHoverEvent(event) || virtualViewHelper.dispatchHoverEvent(event); + } + public void updateColors() { periodDrawable.updateColors( getThemedColor(Theme.key_chat_messagePanelVoiceLock), @@ -1634,6 +1644,53 @@ public boolean onTouchEvent(MotionEvent event) { protected boolean verifyDrawable(@NonNull Drawable who) { return who == periodDrawable || super.verifyDrawable(who); } + + + private class VirtualViewHelper extends ExploreByTouchHelper { + + public VirtualViewHelper(@NonNull View host) { + super(host); + } + + @Override + protected int getVirtualViewAt(float x, float y) { + if (sendButtonVisible && recordCircle != null && pauseRect.contains(x, y)) { + return 2; + } + if (onceVisible && (recordCircle != null && snapAnimationProgress > .1f) && onceRect.contains(x, y)) { + return 4; + } + return HOST_ID; + } + + @Override + protected void getVisibleVirtualViews(List list) { + if (sendButtonVisible) { + list.add(2); + } + if (onceVisible && (recordCircle != null && snapAnimationProgress > .1f)) { + list.add(4); + } + } + + @Override + protected void onPopulateNodeForVirtualView(int id, @NonNull AccessibilityNodeInfoCompat info) { + if (id == 2) { + rect.set((int) pauseRect.left, (int) pauseRect.top, (int) pauseRect.right, (int) pauseRect.bottom); + info.setBoundsInParent(rect); + info.setText(LocaleController.getString(transformToSeekbar > .5f ? R.string.AccActionResume : R.string.AccActionPause)); + } else if (id == 4) { + rect.set((int) onceRect.left, (int) onceRect.top, (int) onceRect.right, (int) onceRect.bottom); + info.setBoundsInParent(rect); + info.setText(LocaleController.getString(voiceOnce ? R.string.AccActionOnceDeactivate : R.string.AccActionOnceActivate)); + } + } + + @Override + protected boolean onPerformActionForVirtualView(int id, int action, @Nullable Bundle args) { + return true; + } + } } private float scale; @@ -2858,6 +2915,7 @@ public boolean onTouchEvent(MotionEvent motionEvent) { sendButtonContainer.addView(audioVideoButtonContainer, LayoutHelper.createFrame(48, 48)); audioVideoButtonContainer.setFocusable(true); audioVideoButtonContainer.setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_YES); + // audioVideoButtonContainer.setOnTouchListener((view, motionEvent) -> { // createRecordCircle(); // if (motionEvent.getAction() == MotionEvent.ACTION_DOWN) { @@ -3027,9 +3085,9 @@ public boolean onTouchEvent(MotionEvent motionEvent) { // } audioVideoSendButton = new ChatActivityEnterViewAnimatedIconView(context, this); - audioVideoSendButton.setFocusable(true); - audioVideoSendButton.setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_YES); - audioVideoSendButton.setAccessibilityDelegate(mediaMessageButtonsDelegate); + audioVideoSendButton.setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_NO); +// audioVideoSendButton.setFocusable(true); +// audioVideoSendButton.setAccessibilityDelegate(mediaMessageButtonsDelegate); padding = dp(9.5f); audioVideoSendButton.setPadding(padding, padding, padding, padding); audioVideoSendButton.setColorFilter(new PorterDuffColorFilter(getThemedColor(Theme.key_chat_messagePanelIcons), PorterDuff.Mode.SRC_IN)); @@ -4601,7 +4659,7 @@ public void dismiss() { if (sendWhenOnlineButton != null) { TLRPC.User user = parentFragment.getCurrentUser(); - if (user != null && !user.bot && !(user.status instanceof TLRPC.TL_userStatusEmpty) && !(user.status instanceof TLRPC.TL_userStatusOnline) && !(user.status instanceof TLRPC.TL_userStatusRecently)) { + if (user != null && !user.bot && !(user.status instanceof TLRPC.TL_userStatusEmpty) && !(user.status instanceof TLRPC.TL_userStatusOnline) && !(user.status instanceof TLRPC.TL_userStatusRecently) && !(user.status instanceof TLRPC.TL_userStatusLastMonth) && !(user.status instanceof TLRPC.TL_userStatusLastWeek)) { sendWhenOnlineButton.setVisibility(VISIBLE); } else { sendWhenOnlineButton.setVisibility(GONE); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/ChatAvatarContainer.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/ChatAvatarContainer.java index df24521152..f48380e356 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/ChatAvatarContainer.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/ChatAvatarContainer.java @@ -25,6 +25,7 @@ import android.view.Gravity; import android.view.MotionEvent; import android.view.View; +import android.view.ViewConfiguration; import android.view.accessibility.AccessibilityNodeInfo; import android.widget.FrameLayout; import android.widget.ImageView; @@ -300,7 +301,7 @@ public boolean onTouchEvent(MotionEvent event) { } if (parentFragment != null && (parentFragment.getChatMode() == 0 || parentFragment.getChatMode() == ChatActivity.MODE_SAVED)) { - if ((!parentFragment.isThreadChat() || parentFragment.isTopic) && !UserObject.isReplyUser(parentFragment.getCurrentUser()) && parentFragment.getChatMode() != ChatActivity.MODE_SAVED) { + if ((!parentFragment.isThreadChat() || parentFragment.isTopic) && !UserObject.isReplyUser(parentFragment.getCurrentUser())) { setOnClickListener(v -> openProfile(false)); } @@ -317,6 +318,62 @@ public boolean onTouchEvent(MotionEvent event) { } emojiStatusDrawable = new AnimatedEmojiDrawable.SwapAnimatedEmojiDrawable(titleTextView, AndroidUtilities.dp(24)); + + setOnLongClickListener(v -> { + if (canSearch()) { + openSearch(); + return true; + } + return false; + }); + } + + private ButtonBounce bounce = new ButtonBounce(this); + private Runnable onLongClick = () -> { + pressed = false; + bounce.setPressed(false); + if (canSearch()) { + openSearch(); + } + }; + + private boolean pressed; + @Override + public boolean onTouchEvent(MotionEvent ev) { + if (ev.getAction() == MotionEvent.ACTION_DOWN && canSearch()) { + pressed = true; + bounce.setPressed(true); + AndroidUtilities.cancelRunOnUIThread(this.onLongClick); + AndroidUtilities.runOnUIThread(this.onLongClick, ViewConfiguration.getLongPressTimeout()); + return true; + } else if (ev.getAction() == MotionEvent.ACTION_UP || ev.getAction() == MotionEvent.ACTION_CANCEL) { + if (pressed) { + bounce.setPressed(false); + pressed = false; + if (isClickable()) { + openProfile(false); + } + AndroidUtilities.cancelRunOnUIThread(this.onLongClick); + } + } + return super.onTouchEvent(ev); + } + + @Override + protected void dispatchDraw(Canvas canvas) { + canvas.save(); + final float s = bounce.getScale(.02f); + canvas.scale(s, s, getWidth() / 2f, getHeight() / 2f); + super.dispatchDraw(canvas); + canvas.restore(); + } + + protected boolean canSearch() { + return false; + } + + protected void openSearch() { + } protected boolean onAvatarClick() { @@ -408,10 +465,10 @@ public void dismiss() { } public void openProfile(boolean byAvatar) { - openProfile(byAvatar, true); + openProfile(byAvatar, true, false); } - public void openProfile(boolean byAvatar, boolean fromChatAnimation) { + public void openProfile(boolean byAvatar, boolean fromChatAnimation, boolean removeLast) { if (byAvatar && (AndroidUtilities.isTablet() || AndroidUtilities.displaySize.x > AndroidUtilities.displaySize.y || !avatarImageView.getImageReceiver().hasNotThumb())) { byAvatar = false; } @@ -429,13 +486,17 @@ public void openProfile(boolean byAvatar, boolean fromChatAnimation) { if (user != null) { Bundle args = new Bundle(); - if (UserObject.isUserSelf(user) && parentFragment.getChatMode() != ChatActivity.MODE_SAVED) { + if (UserObject.isUserSelf(user)) { + if (!sharedMediaPreloader.hasSharedMedia()) { + return; + } args.putLong("dialog_id", parentFragment.getDialogId()); - int[] media = new int[MediaDataController.MEDIA_TYPES_COUNT]; - System.arraycopy(sharedMediaPreloader.getLastMediaCount(), 0, media, 0, media.length); + if (parentFragment.getChatMode() == ChatActivity.MODE_SAVED) { + args.putLong("topic_id", parentFragment.getSavedDialogId()); + } MediaActivity fragment = new MediaActivity(args, sharedMediaPreloader); fragment.setChatInfo(parentFragment.getCurrentChatInfo()); - parentFragment.presentFragment(fragment); + parentFragment.presentFragment(fragment, removeLast); } else { if (parentFragment.getChatMode() == ChatActivity.MODE_SAVED) { long dialogId = parentFragment.getSavedDialogId(); @@ -458,7 +519,7 @@ public void openProfile(boolean byAvatar, boolean fromChatAnimation) { if (fromChatAnimation) { fragment.setPlayProfileAnimation(byAvatar ? 2 : 1); } - parentFragment.presentFragment(fragment); + parentFragment.presentFragment(fragment, removeLast); } } else if (chat != null) { Bundle args = new Bundle(); @@ -473,7 +534,7 @@ public void openProfile(boolean byAvatar, boolean fromChatAnimation) { if (fromChatAnimation) { fragment.setPlayProfileAnimation(byAvatar ? 2 : 1); } - parentFragment.presentFragment(fragment); + parentFragment.presentFragment(fragment, removeLast); } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/ChatGreetingsView.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/ChatGreetingsView.java index 8815c62634..d2bdba8916 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/ChatGreetingsView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/ChatGreetingsView.java @@ -97,7 +97,7 @@ public ChatGreetingsView(Context context, TLRPC.User user, int distance, int cur } } - private ImageView premiumIconView; + private RLottieImageView premiumIconView; private TextView premiumTextView; private TextView premiumButtonView; @@ -107,12 +107,17 @@ public void setPremiumLock(boolean lock, long dialogId) { premiumLock = lock; if (premiumLock) { if (premiumIconView == null) { - premiumIconView = new ImageView(getContext()); + premiumIconView = new RLottieImageView(getContext()); premiumIconView.setScaleType(ImageView.ScaleType.CENTER); premiumIconView.setColorFilter(new PorterDuffColorFilter(Color.WHITE, PorterDuff.Mode.SRC_IN)); premiumIconView.setBackground(Theme.createCircleDrawable(dp(78), 0x1c000000)); - premiumIconView.setImageResource(R.drawable.large_message_lock); + premiumIconView.setAnimation(R.raw.large_message_lock, 80, 80); + premiumIconView.setOnClickListener(v -> { + premiumIconView.setProgress(0); + premiumIconView.playAnimation(); + }); } + premiumIconView.playAnimation(); if (premiumTextView == null) { premiumTextView = new TextView(getContext()); premiumTextView.setTextAlignment(TEXT_ALIGNMENT_CENTER); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/ChatScrimPopupContainerLayout.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/ChatScrimPopupContainerLayout.java index b74e5a08b1..cee8fe9726 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/ChatScrimPopupContainerLayout.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/ChatScrimPopupContainerLayout.java @@ -1,6 +1,9 @@ package org.telegram.ui.Components; +import static org.telegram.messenger.AndroidUtilities.dp; + import android.content.Context; +import android.util.Log; import android.view.View; import android.widget.FrameLayout; import android.widget.LinearLayout; @@ -25,6 +28,11 @@ public ChatScrimPopupContainerLayout(Context context) { setOrientation(LinearLayout.VERTICAL); } + @Override + protected void onLayout(boolean changed, int l, int t, int r, int b) { + super.onLayout(changed, l, t, r, b); + } + @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { if (maxHeight != 0) { @@ -46,20 +54,27 @@ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { if (reactionsLayout.showCustomEmojiReaction()) { widthMeasureSpec = MeasureSpec.makeMeasureSpec(maxWidth, MeasureSpec.EXACTLY); } + reactionsLayout.measureHint(); int reactionsLayoutTotalWidth = reactionsLayout.getTotalWidth(); View menuContainer = popupWindowLayout.getSwipeBack() != null ? popupWindowLayout.getSwipeBack().getChildAt(0) : popupWindowLayout.getChildAt(0); - int maxReactionsLayoutWidth = menuContainer.getMeasuredWidth() + AndroidUtilities.dp(16) + AndroidUtilities.dp(16) + AndroidUtilities.dp(36); - if (maxReactionsLayoutWidth > maxWidth) { + int maxReactionsLayoutWidth = menuContainer.getMeasuredWidth() + dp(16) + dp(16) + dp(36); + int hintTextWidth = reactionsLayout.getHintTextWidth(); + if (hintTextWidth > maxReactionsLayoutWidth) { + maxReactionsLayoutWidth = hintTextWidth; + } else if (maxReactionsLayoutWidth > maxWidth) { maxReactionsLayoutWidth = maxWidth; } - reactionsLayout.bigCircleOffset = AndroidUtilities.dp(36); + reactionsLayout.bigCircleOffset = dp(36); if (reactionsLayout.showCustomEmojiReaction()) { reactionsLayout.getLayoutParams().width = reactionsLayoutTotalWidth; - reactionsLayout.bigCircleOffset = Math.max(reactionsLayoutTotalWidth - menuContainer.getMeasuredWidth() - AndroidUtilities.dp(36), AndroidUtilities.dp(36)); + reactionsLayout.bigCircleOffset = Math.max(reactionsLayoutTotalWidth - menuContainer.getMeasuredWidth() - dp(36), dp(36)); } else if (reactionsLayoutTotalWidth > maxReactionsLayoutWidth) { - int maxFullCount = ((maxReactionsLayoutWidth - AndroidUtilities.dp(16)) / AndroidUtilities.dp(36)) + 1; - int newWidth = maxFullCount * AndroidUtilities.dp(36) + AndroidUtilities.dp(16) - AndroidUtilities.dp(8); + int maxFullCount = ((maxReactionsLayoutWidth - dp(16)) / dp(36)) + 1; + int newWidth = maxFullCount * dp(36) + dp(8); + if (hintTextWidth + dp(24) > newWidth) { + newWidth = hintTextWidth + dp(24); + } if (newWidth > reactionsLayoutTotalWidth || maxFullCount == reactionsLayout.getItemsCount()) { newWidth = reactionsLayoutTotalWidth; } @@ -73,7 +88,7 @@ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { widthDiff = popupWindowLayout.getSwipeBack().getMeasuredWidth() - popupWindowLayout.getSwipeBack().getChildAt(0).getMeasuredWidth(); } if (reactionsLayout.getLayoutParams().width != LayoutHelper.WRAP_CONTENT && reactionsLayout.getLayoutParams().width + widthDiff > maxWidth) { - widthDiff = maxWidth - reactionsLayout.getLayoutParams().width + AndroidUtilities.dp(8); + widthDiff = maxWidth - reactionsLayout.getLayoutParams().width + dp(8); } if (widthDiff < 0) { widthDiff = 0; @@ -84,23 +99,23 @@ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { } else { popupLayoutLeftOffset = (maxWidth - menuContainer.getMeasuredWidth()) * 0.25f; reactionsLayout.bigCircleOffset -= popupLayoutLeftOffset; - if (reactionsLayout.bigCircleOffset < AndroidUtilities.dp(36)) { + if (reactionsLayout.bigCircleOffset < dp(36)) { popupLayoutLeftOffset = 0; - reactionsLayout.bigCircleOffset = AndroidUtilities.dp(36); + reactionsLayout.bigCircleOffset = dp(36); } updatePopupTranslation(); } if (bottomView != null) { if (reactionsLayout.showCustomEmojiReaction()) { - bottomView.getLayoutParams().width = menuContainer.getMeasuredWidth() + AndroidUtilities.dp(16); + bottomView.getLayoutParams().width = menuContainer.getMeasuredWidth() + dp(16); updatePopupTranslation(); } else { bottomView.getLayoutParams().width = LayoutHelper.MATCH_PARENT; } if (popupWindowLayout.getSwipeBack() != null) { - ((LayoutParams) bottomView.getLayoutParams()).rightMargin = widthDiff + AndroidUtilities.dp(36); + ((LayoutParams) bottomView.getLayoutParams()).rightMargin = widthDiff + dp(36); } else { - ((LayoutParams) bottomView.getLayoutParams()).rightMargin = AndroidUtilities.dp(36); + ((LayoutParams) bottomView.getLayoutParams()).rightMargin = dp(36); } } super.onMeasure(widthMeasureSpec, heightMeasureSpec); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/CounterView.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/CounterView.java index 78b6c01762..98ef9a30fb 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/CounterView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/CounterView.java @@ -12,6 +12,7 @@ import android.text.SpannableStringBuilder; import android.text.StaticLayout; import android.text.TextPaint; +import android.text.TextUtils; import android.view.Gravity; import android.view.View; import android.view.animation.OvershootInterpolator; @@ -82,9 +83,11 @@ public static class CounterDrawable { public boolean addServiceGradient; int currentCount; + CharSequence currentText; private boolean countAnimationIncrement; private ValueAnimator countAnimator; public float countChangeProgress = 1f; + private float countLayoutWidth; private StaticLayout countLayout; private StaticLayout countOldLayout; private StaticLayout countAnimationStableLayout; @@ -172,7 +175,15 @@ private void drawInternal(Canvas canvas) { } public void setCount(int count, boolean animated) { - if (count == currentCount) { + setText(getStringOfCCount(count), animated, count, false); + } + + public void setText(CharSequence text, boolean animated) { + setText(text, animated, 1, true); + } + + public void setText(CharSequence text, boolean animated, int count, boolean isText) { + if (TextUtils.equals(text, currentText)) { return; } if (countAnimator != null) { @@ -186,21 +197,23 @@ public void setCount(int count, boolean animated) { } if (!animated) { currentCount = count; + currentText = text; if (count == 0) { if (updateVisibility && parent != null) { parent.setVisibility(View.GONE); } return; } - String newStr = getStringOfCCount(count); - countWidth = Math.max(AndroidUtilities.dp(12), (int) Math.ceil(textPaint.measureText(newStr))); + CharSequence newStr = text; // getStringOfCCount(count); + countWidth = Math.max(AndroidUtilities.dp(12), (int) Math.ceil(textPaint.measureText(newStr.toString()))); countLayout = new StaticLayout(newStr, textPaint, countWidth, Layout.Alignment.ALIGN_CENTER, 1.0f, 0.0f, false); + countLayoutWidth = countLayout.getLineCount() >= 1 ? countLayout.getLineWidth(0) : 0; if (parent != null) { parent.invalidate(); } return; } - String newStr = getStringOfCCount(count); + CharSequence newStr = text; // getStringOfCCount(count); if (animated) { if (countAnimator != null) { @@ -244,9 +257,9 @@ public void onAnimationEnd(Animator animation) { countAnimator.setInterpolator(CubicBezierInterpolator.DEFAULT); } if (countLayout != null) { - String oldStr = getStringOfCCount(currentCount); + CharSequence oldStr = currentText; // getStringOfCCount(currentCount); - if (oldStr.length() == newStr.length()) { + if (oldStr.length() == newStr.length() && !isText) { SpannableStringBuilder oldSpannableStr = new SpannableStringBuilder(oldStr); SpannableStringBuilder newSpannableStr = new SpannableStringBuilder(newStr); SpannableStringBuilder stableStr = new SpannableStringBuilder(newStr); @@ -259,7 +272,7 @@ public void onAnimationEnd(Animator animation) { } } - int countOldWidth = Math.max(AndroidUtilities.dp(12), (int) Math.ceil(textPaint.measureText(oldStr))); + int countOldWidth = Math.max(AndroidUtilities.dp(12), (int) Math.ceil(textPaint.measureText(oldStr.toString()))); countOldLayout = new StaticLayout(oldSpannableStr, textPaint, countOldWidth, Layout.Alignment.ALIGN_CENTER, 1.0f, 0.0f, false); countAnimationStableLayout = new StaticLayout(stableStr, textPaint, countOldWidth, Layout.Alignment.ALIGN_CENTER, 1.0f, 0.0f, false); countAnimationInLayout = new StaticLayout(newSpannableStr, textPaint, countOldWidth, Layout.Alignment.ALIGN_CENTER, 1.0f, 0.0f, false); @@ -272,16 +285,22 @@ public void onAnimationEnd(Animator animation) { countAnimator.start(); } if (count > 0) { - countWidth = Math.max(AndroidUtilities.dp(12), (int) Math.ceil(textPaint.measureText(newStr))); + countWidth = Math.max(AndroidUtilities.dp(12), (int) Math.ceil(textPaint.measureText(newStr.toString()))); countLayout = new StaticLayout(newStr, textPaint, countWidth, Layout.Alignment.ALIGN_CENTER, 1.0f, 0.0f, false); + countLayoutWidth = countLayout.getLineCount() >= 1 ? countLayout.getLineWidth(0) : 0; } currentCount = count; + currentText = newStr; if (parent != null) { parent.invalidate(); } } + public int getCurrentWidth() { + return (int) Math.ceil(countLayoutWidth); + } + private String getStringOfCCount(int count) { if (shortFormat) { return AndroidUtilities.formatWholeNumber(count, 0); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/EditTextBoldCursor.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/EditTextBoldCursor.java index 212b747237..1fc5f7b324 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/EditTextBoldCursor.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/EditTextBoldCursor.java @@ -707,6 +707,7 @@ public void setHintText(CharSequence text, boolean animated, TextPaint paint) { } } hintLayout = new StaticLayout(text, paint, AndroidUtilities.dp(1000), Layout.Alignment.ALIGN_NORMAL, 1.0f, 0.0f, false); + invalidate(); } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/EditTextCaption.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/EditTextCaption.java index b3573c42f5..9f94550d69 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/EditTextCaption.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/EditTextCaption.java @@ -520,35 +520,23 @@ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { AndroidUtilities.showKeyboard(editText); }); creationLinkDialog.showDelayed(250); - if (editText != null) { - ViewGroup.MarginLayoutParams layoutParams = (ViewGroup.MarginLayoutParams) editText.getLayoutParams(); - if (layoutParams != null) { - if (layoutParams instanceof FrameLayout.LayoutParams) { - ((FrameLayout.LayoutParams) layoutParams).gravity = Gravity.CENTER_HORIZONTAL; - } - layoutParams.rightMargin = layoutParams.leftMargin = AndroidUtilities.dp(24); - layoutParams.height = AndroidUtilities.dp(36); - editText.setLayoutParams(layoutParams); - } - editText.setSelection(0, editText.getText().length()); - } } else { builder.show().setOnShowListener(dialog -> { editText.requestFocus(); AndroidUtilities.showKeyboard(editText); }); - if (editText != null) { - ViewGroup.MarginLayoutParams layoutParams = (ViewGroup.MarginLayoutParams) editText.getLayoutParams(); - if (layoutParams != null) { - if (layoutParams instanceof FrameLayout.LayoutParams) { - ((FrameLayout.LayoutParams) layoutParams).gravity = Gravity.CENTER_HORIZONTAL; - } - layoutParams.rightMargin = layoutParams.leftMargin = AndroidUtilities.dp(24); - layoutParams.height = AndroidUtilities.dp(36); - editText.setLayoutParams(layoutParams); + } + if (editText != null) { + ViewGroup.MarginLayoutParams layoutParams = (ViewGroup.MarginLayoutParams) editText.getLayoutParams(); + if (layoutParams != null) { + if (layoutParams instanceof FrameLayout.LayoutParams) { + ((FrameLayout.LayoutParams) layoutParams).gravity = Gravity.CENTER_HORIZONTAL; } - editText.setSelection(0, editText.getText().length()); + layoutParams.rightMargin = layoutParams.leftMargin = AndroidUtilities.dp(24); + layoutParams.height = AndroidUtilities.dp(36); + editText.setLayoutParams(layoutParams); } + editText.setSelection(0, editText.getText().length()); } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/EditTextEmoji.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/EditTextEmoji.java index 16a355fcc5..8c4ed66679 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/EditTextEmoji.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/EditTextEmoji.java @@ -487,6 +487,10 @@ public void setSelection(int selection) { editText.setSelection(selection); } + public void setSelection(int from, int to) { + editText.setSelection(from, to); + } + public void hidePopup(boolean byBackButton) { if (isPopupShowing()) { showPopup(0); @@ -532,6 +536,7 @@ protected void bottomPanelTranslationY(float translation) { } public void openKeyboard() { + editText.requestFocus(); AndroidUtilities.showKeyboard(editText); } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/InstantCameraView.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/InstantCameraView.java index 28fcbca54e..2ba1a06839 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/InstantCameraView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/InstantCameraView.java @@ -1650,7 +1650,7 @@ public void handleMessage(Message inputMessage) { break; case DO_SHUTDOWN_MESSAGE: finish(); - if (recording && inputMessage.arg2 != -2) { + if (recording && inputMessage.arg2 != -2 && videoEncoder != null) { videoEncoder.stopRecording(inputMessage.arg1, inputMessage.arg2); } Looper looper = Looper.myLooper(); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/MediaActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/MediaActivity.java index ab629e55f0..c57caf616d 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/MediaActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/MediaActivity.java @@ -80,6 +80,7 @@ public class MediaActivity extends BaseFragment implements SharedMediaLayout.Sha private TLRPC.ChatFull currentChatInfo; private TLRPC.UserFull currentUserInfo; private long dialogId; + private long topicId; private FrameLayout titlesContainer; private FrameLayout[] titles = new FrameLayout[2]; private SimpleTextView[] nameTextView = new SimpleTextView[2]; @@ -116,6 +117,7 @@ public MediaActivity(Bundle args, SharedMediaLayout.SharedMediaPreloader sharedM public boolean onFragmentCreate() { type = getArguments().getInt("type", TYPE_MEDIA); dialogId = getArguments().getLong("dialog_id"); + topicId = getArguments().getLong("topic_id", 0); int defaultTab = SharedMediaLayout.TAB_PHOTOVIDEO; if (type == TYPE_ARCHIVED_CHANNEL_STORIES) { defaultTab = SharedMediaLayout.TAB_ARCHIVED_STORIES; @@ -126,7 +128,7 @@ public boolean onFragmentCreate() { getNotificationCenter().addObserver(this, NotificationCenter.userInfoDidLoad); getNotificationCenter().addObserver(this, NotificationCenter.currentUserPremiumStatusChanged); getNotificationCenter().addObserver(this, NotificationCenter.storiesEnabledUpdate); - if (DialogObject.isUserDialog(dialogId)) { + if (DialogObject.isUserDialog(dialogId) && topicId == 0) { TLRPC.User user = getMessagesController().getUser(dialogId); if (UserObject.isUserSelf(user)) { getMessagesController().loadUserInfo(user, false, this.classGuid); @@ -211,10 +213,12 @@ public void onClick(DialogInterface dialog, int which) { } } else if (id == 10) { sharedMediaLayout.showMediaCalendar(sharedMediaLayout.getClosestTab(), false); + } else if (id == 11) { + sharedMediaLayout.closeActionMode(true); + sharedMediaLayout.getSearchItem().openSearch(false); } } }); - actionBar.setColorFilterMode(PorterDuff.Mode.SRC_IN); FrameLayout avatarContainer = new FrameLayout(context); SizeNotifierFrameLayout fragmentView = new SizeNotifierFrameLayout(context) { @@ -387,7 +391,7 @@ public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) { } }; avatarImageView.getImageReceiver().setAllowDecodeSingleFrame(true); - avatarImageView.setRoundRadius(dp(21)); + avatarImageView.setRoundRadius(dp(getDialogId() == getUserConfig().getClientUserId() && topicId == 0 && getMessagesController().savedViewAsChats ? 13 : 21)); avatarImageView.setPivotX(0); avatarImageView.setPivotY(0); AvatarDrawable avatarDrawable = new AvatarDrawable(); @@ -538,7 +542,7 @@ public int getBottomOffset(int tag) { hideFloatingButton(true, false); } - if (type == TYPE_MEDIA && dialogId == getUserConfig().getClientUserId() && !getMessagesController().getSavedMessagesController().unsupported && getMessagesController().getSavedMessagesController().getAllCount() > 0) { + if (type == TYPE_MEDIA && dialogId == getUserConfig().getClientUserId() && topicId == 0 && !getMessagesController().getSavedMessagesController().unsupported && getMessagesController().getSavedMessagesController().hasDialogs()) { initialTab = SharedMediaLayout.TAB_SAVED_DIALOGS; } sharedMediaLayout = new SharedMediaLayout(context, dialogId, sharedMediaPreloader, 0, null, currentChatInfo, currentUserInfo, initialTab, this, new SharedMediaLayout.Delegate() { @@ -617,7 +621,7 @@ protected boolean includeStories() { @Override protected boolean includeSavedDialogs() { - return type == TYPE_MEDIA && dialogId == getUserConfig().getClientUserId(); + return type == TYPE_MEDIA && dialogId == getUserConfig().getClientUserId() && topicId == 0; } @Override @@ -753,9 +757,15 @@ protected void onTabScroll(boolean scrolling) { } } }; + if (sharedMediaLayout.getSearchOptionsItem() != null) { + sharedMediaLayout.getSearchOptionsItem().setColorFilter(new PorterDuffColorFilter(getThemedColor(Theme.key_windowBackgroundWhiteBlackText), PorterDuff.Mode.MULTIPLY)); + } sharedMediaLayout.setPinnedToTop(true); sharedMediaLayout.getSearchItem().setTranslationY(0); sharedMediaLayout.photoVideoOptionsItem.setTranslationY(0); + if (sharedMediaLayout.getSearchOptionsItem() != null) { + sharedMediaLayout.getSearchOptionsItem().setTranslationY(0); + } if (type == TYPE_STORIES || type == TYPE_ARCHIVED_CHANNEL_STORIES) { fragmentView.addView(sharedMediaLayout, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, Gravity.FILL, 0, 0, 0, 64)); @@ -780,14 +790,26 @@ protected void onTabScroll(boolean scrolling) { fragmentView.addView(buttonContainer, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 64, Gravity.BOTTOM | Gravity.FILL_HORIZONTAL)); } + long avatarDialogId = dialogId; + if (topicId != 0 && dialogId == getUserConfig().getClientUserId()) { + avatarDialogId = topicId; + } TLObject avatarObject = null; if (type == TYPE_ARCHIVED_CHANNEL_STORIES) { nameTextView[0].setText(LocaleController.getString("ProfileStoriesArchive")); } else if (type == TYPE_STORIES) { nameTextView[0].setText(LocaleController.getString("ProfileMyStories")); nameTextView[1].setText(LocaleController.getString("ProfileStoriesArchive")); - } else if (DialogObject.isEncryptedDialog(dialogId)) { - TLRPC.EncryptedChat encryptedChat = getMessagesController().getEncryptedChat(DialogObject.getEncryptedChatId(dialogId)); + } else if (avatarDialogId == UserObject.ANONYMOUS) { + nameTextView[0].setText(LocaleController.getString(R.string.AnonymousForward)); + avatarDrawable.setAvatarType(AvatarDrawable.AVATAR_TYPE_ANONYMOUS); + avatarDrawable.setScaleSize(.75f); + } else if (topicId != 0 && avatarDialogId == getUserConfig().getClientUserId()) { + nameTextView[0].setText(LocaleController.getString(R.string.MyNotes)); + avatarDrawable.setAvatarType(AvatarDrawable.AVATAR_TYPE_MY_NOTES); + avatarDrawable.setScaleSize(.75f); + } else if (DialogObject.isEncryptedDialog(avatarDialogId)) { + TLRPC.EncryptedChat encryptedChat = getMessagesController().getEncryptedChat(DialogObject.getEncryptedChatId(avatarDialogId)); if (encryptedChat != null) { TLRPC.User user = getMessagesController().getUser(encryptedChat.user_id); if (user != null) { @@ -796,8 +818,8 @@ protected void onTabScroll(boolean scrolling) { avatarObject = user; } } - } else if (DialogObject.isUserDialog(dialogId)) { - TLRPC.User user = MessagesController.getInstance(currentAccount).getUser(dialogId); + } else if (DialogObject.isUserDialog(avatarDialogId)) { + TLRPC.User user = MessagesController.getInstance(currentAccount).getUser(avatarDialogId); if (user != null) { if (user.self) { nameTextView[0].setText(LocaleController.getString("SavedMessages", R.string.SavedMessages)); @@ -810,7 +832,7 @@ protected void onTabScroll(boolean scrolling) { } } } else { - TLRPC.Chat chat = MessagesController.getInstance(currentAccount).getChat(-dialogId); + TLRPC.Chat chat = MessagesController.getInstance(currentAccount).getChat(-avatarDialogId); if (chat != null) { nameTextView[0].setText(chat.title); avatarDrawable.setInfo(currentAccount, chat); @@ -828,6 +850,13 @@ protected void onTabScroll(boolean scrolling) { if (sharedMediaLayout.isSearchItemVisible() && type != TYPE_STORIES) { sharedMediaLayout.getSearchItem().setVisibility(View.VISIBLE); } + if (sharedMediaLayout.searchItemIcon != null && initialTab != SharedMediaLayout.TAB_SAVED_DIALOGS) { + sharedMediaLayout.searchItemIcon.setVisibility(View.GONE); + } + if (sharedMediaLayout.getSearchOptionsItem() != null && type != TYPE_STORIES) { + sharedMediaLayout.animateSearchToOptions(!sharedMediaLayout.isSearchItemVisible(), false); + sharedMediaLayout.getSearchOptionsItem().setVisibility(View.VISIBLE); + } if (sharedMediaLayout.isCalendarItemVisible() && type != TYPE_STORIES) { sharedMediaLayout.photoVideoOptionsItem.setVisibility(View.VISIBLE); } else { @@ -1115,8 +1144,12 @@ public void mediaCountUpdated() { private void updateColors() { + if (sharedMediaLayout.getSearchOptionsItem() != null) { + sharedMediaLayout.getSearchOptionsItem().setColorFilter(new PorterDuffColorFilter(getThemedColor(Theme.key_windowBackgroundWhiteBlackText), PorterDuff.Mode.MULTIPLY)); + } actionBar.setBackgroundColor(Theme.getColor(Theme.key_windowBackgroundWhite)); actionBar.setItemsColor(Theme.getColor(Theme.key_windowBackgroundWhiteBlackText), false); + actionBar.setItemsColor(Theme.getColor(Theme.key_windowBackgroundWhiteBlackText), true); actionBar.setItemsBackgroundColor(Theme.getColor(Theme.key_actionBarActionModeDefaultSelector), false); actionBar.setTitleColor(Theme.getColor(Theme.key_windowBackgroundWhiteBlackText)); nameTextView[0].setTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteBlackText)); @@ -1161,11 +1194,9 @@ public List onGetDebugItems() { } private class StoriesTabsView extends BottomPagerTabs { - public StoriesTabsView(Context context, Theme.ResourcesProvider resourcesProvider) { super(context, resourcesProvider); } - @Override public Tab[] createTabs() { Tab[] tabs = new Tab[] { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/MessagePreviewView.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/MessagePreviewView.java index a4c57f5405..e334d49cfc 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/MessagePreviewView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/MessagePreviewView.java @@ -693,7 +693,7 @@ protected boolean hasSiblingChild(int position) { MessageObject message = messages.previewMessages.get(position); MessageObject.GroupedMessages group = getValidGroupedMessage(message); if (group != null) { - MessageObject.GroupedMessagePosition pos = group.positions.get(message); + MessageObject.GroupedMessagePosition pos = group.getPosition(message); if (pos.minX == pos.maxX || pos.minY != pos.maxY || pos.minY == 0) { return false; } @@ -733,7 +733,7 @@ public int getSpanSize(int position) { MessageObject message = messages.previewMessages.get(idx); MessageObject.GroupedMessages groupedMessages = getValidGroupedMessage(message); if (groupedMessages != null) { - return groupedMessages.positions.get(message).spanSize; + return groupedMessages.getPosition(message).spanSize; } } return 1000; @@ -1691,7 +1691,7 @@ private MessageObject.GroupedMessages getValidGroupedMessage(MessageObject messa MessageObject.GroupedMessages groupedMessages = null; if (message.getGroupId() != 0) { groupedMessages = messages.groupedMessagesMap.get(message.getGroupId()); - if (groupedMessages != null && (groupedMessages.messages.size() <= 1 || groupedMessages.positions.get(message) == null)) { + if (groupedMessages != null && (groupedMessages.messages.size() <= 1 || groupedMessages.getPosition(message) == null)) { groupedMessages = null; } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/MessagePrivateSeenView.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/MessagePrivateSeenView.java index 6930c51036..f4cbdf7f52 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/MessagePrivateSeenView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/MessagePrivateSeenView.java @@ -43,6 +43,8 @@ import org.telegram.ui.Stories.recorder.ButtonWithCounterView; import org.telegram.ui.Stories.recorder.HintView2; +import java.util.Date; + public class MessagePrivateSeenView extends FrameLayout { private final int currentAccount; @@ -57,12 +59,15 @@ public class MessagePrivateSeenView extends FrameLayout { private final int messageId; private final Runnable dismiss; + private final int messageDiff; + public MessagePrivateSeenView(Context context, @NonNull MessageObject messageObject, Runnable dismiss, Theme.ResourcesProvider resourcesProvider) { super(context); currentAccount = messageObject.currentAccount; this.resourcesProvider = resourcesProvider; this.dismiss = dismiss; + messageDiff = ConnectionsManager.getInstance(currentAccount).getCurrentTime() - messageObject.messageOwner.date; dialogId = messageObject.getDialogId(); messageId = messageObject.getId(); @@ -126,7 +131,7 @@ private void request() { } } else if (res instanceof TLRPC.TL_outboxReadDate) { TLRPC.TL_outboxReadDate r = (TLRPC.TL_outboxReadDate) res; - valueTextView.setText(LocaleController.formatString(R.string.PmReadAt, LocaleController.formatSeenDate(r.date))); + valueTextView.setText(LocaleController.formatPmSeenDate(r.date)); premiumTextView.setVisibility(View.GONE); } valueLayout.animate().alpha(1f).setInterpolator(CubicBezierInterpolator.EASE_OUT_QUINT).setDuration(320).start(); @@ -302,22 +307,29 @@ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { if (minWidth < 0) { minWidth = 0; + final long date = System.currentTimeMillis(); minWidth = Math.max(minWidth, dp(40 + 96 + 8)); minWidth = Math.max(minWidth, dp(40 + 8) + valueTextView.getPaint().measureText(LocaleController.getString(R.string.PmReadUnknown))); minWidth = Math.max(minWidth, dp(40 + 16 + 8) + valueTextView.getPaint().measureText(LocaleController.getString(R.string.PmRead) + premiumTextView.getPaint().measureText(LocaleController.getString(R.string.PmReadShowWhen)))); - minWidth = Math.max(minWidth, dp(40 + 8) + valueTextView.getPaint().measureText(LocaleController.formatString(R.string.PmReadAt, LocaleController.formatString(R.string.TodayAtFormattedWithToday, "99:99")))); - minWidth = Math.max(minWidth, dp(40 + 8) + valueTextView.getPaint().measureText(LocaleController.formatString(R.string.PmReadAt, LocaleController.formatString(R.string.YesterdayAtFormatted, "99:99")))); - minWidth = Math.max(minWidth, dp(40 + 8) + valueTextView.getPaint().measureText(LocaleController.formatString(R.string.PmReadAt, LocaleController.formatString(R.string.formatDateAtTime, "99.99.99", "99:99")))); + minWidth = Math.max(minWidth, dp(40 + 8) + valueTextView.getPaint().measureText(LocaleController.formatString(R.string.PmReadTodayAt, LocaleController.getInstance().formatterDay.format(new Date(date))))); + if (messageDiff > 60 * 60 * 24) { + minWidth = Math.max(minWidth, dp(40 + 8) + valueTextView.getPaint().measureText(LocaleController.formatString(R.string.PmReadYesterdayAt, LocaleController.getInstance().formatterDay.format(new Date(date))))); + } + if (messageDiff > 60 * 60 * 24 * 2) { + minWidth = Math.max(minWidth, dp(40 + 8) + valueTextView.getPaint().measureText(LocaleController.formatString(R.string.PmReadDateTimeAt, LocaleController.getInstance().formatterDayMonth.format(new Date(date)), LocaleController.getInstance().formatterDay.format(new Date(date))))); + minWidth = Math.max(minWidth, dp(40 + 8) + valueTextView.getPaint().measureText(LocaleController.formatString(R.string.PmReadDateTimeAt, LocaleController.getInstance().formatterYear.format(new Date(date)), LocaleController.getInstance().formatterDay.format(new Date(date))))); + } } - if (width < minWidth) { - width = (int) minWidth; - } if (parent != null && parent.getWidth() > 0) { width = parent.getWidth(); widthMode = MeasureSpec.EXACTLY; } + if (width < minWidth || widthMode == MeasureSpec.AT_MOST) { + width = (int) minWidth; + widthMode = MeasureSpec.EXACTLY; + } - super.onMeasure(widthMeasureSpec, heightMeasureSpec); + super.onMeasure(MeasureSpec.makeMeasureSpec(width, widthMode), heightMeasureSpec); } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/Paint/Views/MessageEntityView.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/Paint/Views/MessageEntityView.java index d17b18c29d..269f9ff78b 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/Paint/Views/MessageEntityView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/Paint/Views/MessageEntityView.java @@ -792,7 +792,7 @@ public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int positi MessageObject message = messageObjects.get(position); boolean pinnedTop = false; if (groupedMessages != null) { - MessageObject.GroupedMessagePosition p = groupedMessages.positions.get(message); + MessageObject.GroupedMessagePosition p = groupedMessages.getPosition(message); if (p != null) { pinnedTop = p.minY != 0; } @@ -825,7 +825,7 @@ protected boolean hasSiblingChild(int position) { position = messageObjects.size() - 1 - position; if (groupedMessages != null && position >= 0 && position < messageObjects.size()) { MessageObject message = messageObjects.get(position); - MessageObject.GroupedMessagePosition pos = groupedMessages.positions.get(message); + MessageObject.GroupedMessagePosition pos = groupedMessages.getPosition(message); if (pos == null || pos.minX == pos.maxX || pos.minY != pos.maxY || pos.minY == 0) { return false; } @@ -849,7 +849,7 @@ public int getSpanSize(int position) { position = messageObjects.size() - 1 - position; if (groupedMessages != null && position >= 0 && position < groupedMessages.messages.size()) { MessageObject message = groupedMessages.messages.get(position); - MessageObject.GroupedMessagePosition groupedPosition = groupedMessages.positions.get(message); + MessageObject.GroupedMessagePosition groupedPosition = groupedMessages.getPosition(message); if (groupedPosition != null) { return groupedPosition.spanSize; } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/LimitReachedBottomSheet.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/LimitReachedBottomSheet.java index 05072ce5be..b2c7ed1837 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/LimitReachedBottomSheet.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/LimitReachedBottomSheet.java @@ -648,6 +648,7 @@ public Animator onDisappear(ViewGroup sceneRoot, View view, TransitionValues sta fireworksOverlay.start(); fireworksOverlay.performHapticFeedback(HapticFeedbackConstants.KEYBOARD_TAP); headerView.boostCounterView.setCount(canApplyBoost.boostCount, true); + recyclerListView.smoothScrollToPosition(0); } private void sendInviteMessages() { @@ -1092,7 +1093,7 @@ public void onClick(View v) { view.setPadding(0, 0, 0, AndroidUtilities.dp(8)); break; case VIEW_TYPE_USER: - view = new GroupCreateUserCell(context, 1, 8, false); + view = new GroupCreateUserCell(context, 1, 0, false); break; case VIEW_TYPE_PROGRESS: FlickerLoadingView flickerLoadingView = new FlickerLoadingView(context, null); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/PremiumFeatureBottomSheet.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/PremiumFeatureBottomSheet.java index cb738343ba..a432ee79ff 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/PremiumFeatureBottomSheet.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/PremiumFeatureBottomSheet.java @@ -489,8 +489,6 @@ private void setButtonText() { if (startType == PremiumPreviewFragment.PREMIUM_FEATURE_REACTIONS) { premiumButtonView.buttonTextView.setText(LocaleController.getString(R.string.UnlockPremiumReactions)); premiumButtonView.setIcon(R.raw.unlock_icon); - } else if (startType == PremiumPreviewFragment.PREMIUM_FEATURE_ADS || startType == PremiumPreviewFragment.PREMIUM_FEATURE_DOWNLOAD_SPEED || startType == PremiumPreviewFragment.PREMIUM_FEATURE_ADVANCED_CHAT_MANAGEMENT || startType == PremiumPreviewFragment.PREMIUM_FEATURE_VOICE_TO_TEXT) { - premiumButtonView.buttonTextView.setText(LocaleController.getString(R.string.AboutTelegramPremium)); } else if (startType == PremiumPreviewFragment.PREMIUM_FEATURE_APPLICATION_ICONS) { premiumButtonView.buttonTextView.setText(LocaleController.getString(R.string.UnlockPremiumIcons)); premiumButtonView.setIcon(R.raw.unlock_icon); @@ -535,6 +533,7 @@ public void setTag(Object tag) { actionBar.setTitleColor(getThemedColor(Theme.key_windowBackgroundWhiteBlackText)); actionBar.setItemsBackgroundColor(getThemedColor(Theme.key_actionBarActionModeDefaultSelector), false); actionBar.setItemsColor(getThemedColor(Theme.key_actionBarActionModeDefaultIcon), false); + actionBar.setItemsColor(getThemedColor(Theme.key_actionBarActionModeDefaultIcon), true); actionBar.setCastShadows(true); actionBar.setExtraHeight(AndroidUtilities.dp(2)); @@ -678,8 +677,11 @@ void setFeatureDate(PremiumPreviewFragment.PremiumFeatureData featureData) { title.setText(LocaleController.getString("AdditionalReactions", R.string.AdditionalReactions)); description.setText(AndroidUtilities.replaceTags(LocaleController.getString("AdditionalReactionsDescription", R.string.AdditionalReactionsDescription))); } else if (startType == PremiumPreviewFragment.PREMIUM_FEATURE_ADS) { - title.setText(LocaleController.getString("PremiumPreviewNoAds", R.string.PremiumPreviewNoAds)); - description.setText(AndroidUtilities.replaceTags(LocaleController.getString("PremiumPreviewNoAdsDescription2", R.string.PremiumPreviewNoAdsDescription2))); + title.setText(LocaleController.getString(R.string.PremiumPreviewNoAds)); + description.setText(AndroidUtilities.replaceTags(LocaleController.getString(R.string.PremiumPreviewNoAdsDescription2))); + } else if (startType == PremiumPreviewFragment.PREMIUM_FEATURE_SAVED_TAGS) { + title.setText(LocaleController.getString(R.string.PremiumPreviewTags)); + description.setText(AndroidUtilities.replaceTags(LocaleController.getString(R.string.PremiumPreviewTagsDescription))); } else if (startType == PremiumPreviewFragment.PREMIUM_FEATURE_APPLICATION_ICONS) { title.setText(LocaleController.getString("PremiumPreviewAppIcon", R.string.PremiumPreviewAppIcon)); description.setText(AndroidUtilities.replaceTags(LocaleController.getString("PremiumPreviewAppIconDescription2", R.string.PremiumPreviewAppIconDescription2))); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/PremiumLockIconView.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/PremiumLockIconView.java index 90f593b081..290bddd2d8 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/PremiumLockIconView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/PremiumLockIconView.java @@ -17,6 +17,7 @@ import org.telegram.messenger.ImageReceiver; import org.telegram.messenger.R; import org.telegram.ui.ActionBar.Theme; +import org.telegram.ui.Components.AnimatedEmojiDrawable; import org.telegram.ui.Components.voip.CellFlickerDrawable; public class PremiumLockIconView extends ImageView { @@ -61,6 +62,7 @@ public PremiumLockIconView(Context context, int type, Theme.ResourcesProvider re Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG); Paint oldShaderPaint; ImageReceiver imageReceiver; + AnimatedEmojiDrawable emojiDrawable; float shaderCrossfadeProgress = 1f; boolean waitingImage; boolean wasDrawn; @@ -106,6 +108,14 @@ protected void onDraw(Canvas canvas) { if (imageReceiver != null && imageReceiver.getBitmap() != null) { waitingImage = false; setColor(AndroidUtilities.getDominantColor(imageReceiver.getBitmap())); + } else if (emojiDrawable != null) { + int color = AnimatedEmojiDrawable.getDominantColor(emojiDrawable); + if (color != 0) { + waitingImage = false; + setColor(color); + } else { + invalidate(); + } } else { invalidate(); } @@ -163,6 +173,14 @@ public void setImageReceiver(ImageReceiver imageReceiver) { } } + public void setAnimatedEmojiDrawable(AnimatedEmojiDrawable emojiDrawable) { + this.emojiDrawable = emojiDrawable; + if (emojiDrawable != null) { + waitingImage = true; + invalidate(); + } + } + public ImageReceiver getImageReceiver() { return imageReceiver; } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/StarParticlesView.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/StarParticlesView.java index 05c536b519..9e02c30373 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/StarParticlesView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/StarParticlesView.java @@ -267,6 +267,18 @@ private void generateBitmaps() { stars[i] = SvgHelper.getBitmap(R.raw.premium_object_star2, size, size, ColorUtils.setAlphaComponent(Theme.getColor(colorKey, resourcesProvider), 30)); svg = true; continue; + } else if (type == PremiumPreviewFragment.PREMIUM_FEATURE_SAVED_TAGS) { + int res; + if (i == 0) { + res = R.raw.premium_object_tag; + } else if (i == 1) { + res = R.raw.premium_object_check; + } else { + res = R.raw.premium_object_star; + } + stars[i] = SvgHelper.getBitmap(res, size, size, ColorUtils.setAlphaComponent(Theme.getColor(colorKey, resourcesProvider), 30)); + svg = true; + continue; } bitmap = Bitmap.createBitmap(size, size, Bitmap.Config.ARGB_8888); @@ -540,6 +552,7 @@ public void genPosition(long time) { type == PremiumPreviewFragment.PREMIUM_FEATURE_ADVANCED_CHAT_MANAGEMENT || type == PremiumPreviewFragment.PREMIUM_FEATURE_ADS || type == PremiumPreviewFragment.PREMIUM_FEATURE_ANIMATED_AVATARS || + type == PremiumPreviewFragment.PREMIUM_FEATURE_SAVED_TAGS || type == PremiumPreviewFragment.PREMIUM_FEATURE_ANIMATED_EMOJI || type == PremiumPreviewFragment.PREMIUM_FEATURE_WALLPAPER || type == PremiumPreviewFragment.PREMIUM_FEATURE_REACTIONS diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/StoriesPageView.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/StoriesPageView.java index c055a6b23b..58e57d3c34 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/StoriesPageView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/StoriesPageView.java @@ -61,6 +61,11 @@ public StoriesPageView(Context context, Theme.ResourcesProvider resourcesProvide LocaleController.getString("PremiumStoriesStealthDescription", R.string.PremiumStoriesStealthDescription), PremiumPreviewFragment.PREMIUM_FEATURE_STORIES_STEALTH_MODE )); + itemsTmp.add(new Item(VIEW_TYPE_ITEM, R.drawable.menu_quality_hd, + LocaleController.getString(R.string.PremiumStoriesQuality), + LocaleController.getString(R.string.PremiumStoriesQualityDescription), + PremiumPreviewFragment.PREMIUM_FEATURE_STORIES_QUALITY + )); itemsTmp.add(new Item(VIEW_TYPE_ITEM, R.drawable.msg_stories_views, LocaleController.getString("PremiumStoriesViews", R.string.PremiumStoriesViews), LocaleController.getString("PremiumStoriesViewsDescription", R.string.PremiumStoriesViewsDescription), diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/VideoScreenPreview.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/VideoScreenPreview.java index a514de4558..c138f73eec 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/VideoScreenPreview.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/VideoScreenPreview.java @@ -131,12 +131,14 @@ public VideoScreenPreview(Context context, SvgHelper.SvgDrawable svgDrawable, in type == PremiumPreviewFragment.PREMIUM_FEATURE_ADS || type == PremiumPreviewFragment.PREMIUM_FEATURE_ANIMATED_AVATARS || type == PremiumPreviewFragment.PREMIUM_FEATURE_ANIMATED_EMOJI || - type == PremiumPreviewFragment.PREMIUM_FEATURE_REACTIONS) { + type == PremiumPreviewFragment.PREMIUM_FEATURE_REACTIONS || + type == PremiumPreviewFragment.PREMIUM_FEATURE_SAVED_TAGS + ) { starDrawable = new StarParticlesView.Drawable(40); starDrawable.speedScale = 3; starDrawable.type = type; - if (type == PremiumPreviewFragment.PREMIUM_FEATURE_ADS) { + if (type == PremiumPreviewFragment.PREMIUM_FEATURE_ADS || type == PremiumPreviewFragment.PREMIUM_FEATURE_SAVED_TAGS) { starDrawable.size1 = 14; starDrawable.size2 = 18; starDrawable.size3 = 18; @@ -325,6 +327,7 @@ protected void onLayout(boolean changed, int left, int top, int right, int botto type == PremiumPreviewFragment.PREMIUM_FEATURE_ADVANCED_CHAT_MANAGEMENT || type == PremiumPreviewFragment.PREMIUM_FEATURE_ADS || type == PremiumPreviewFragment.PREMIUM_FEATURE_ANIMATED_AVATARS || + type == PremiumPreviewFragment.PREMIUM_FEATURE_SAVED_TAGS || type == PremiumPreviewFragment.PREMIUM_FEATURE_ANIMATED_EMOJI || type == PremiumPreviewFragment.PREMIUM_FEATURE_REACTIONS) { starDrawable.rect.set(0, 0, getMeasuredWidth(), getMeasuredHeight()); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/boosts/UserSelectorBottomSheet.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/boosts/UserSelectorBottomSheet.java index 6ecddba604..39b2edd823 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/boosts/UserSelectorBottomSheet.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/boosts/UserSelectorBottomSheet.java @@ -444,8 +444,13 @@ private void updateActionButton(boolean animated) { actionButton.setShowZero(false); SpannableStringBuilder stringBuilder = new SpannableStringBuilder(); if (selectedIds.size() == 0) { - stringBuilder.append("d").setSpan(recipientsBtnSpaceSpan, 0, 1, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); - stringBuilder.append(LocaleController.getString("GiftPremiumChooseRecipientsBtn", R.string.GiftPremiumChooseRecipientsBtn)); + if (LocaleController.isRTL) { + stringBuilder.append(LocaleController.getString("GiftPremiumChooseRecipientsBtn", R.string.GiftPremiumChooseRecipientsBtn)); + stringBuilder.append("d").setSpan(recipientsBtnSpaceSpan, stringBuilder.length() - 1, stringBuilder.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); + } else { + stringBuilder.append("d").setSpan(recipientsBtnSpaceSpan, 0, 1, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); + stringBuilder.append(LocaleController.getString("GiftPremiumChooseRecipientsBtn", R.string.GiftPremiumChooseRecipientsBtn)); + } } else { stringBuilder.append(LocaleController.getString("GiftPremiumProceedBtn", R.string.GiftPremiumProceedBtn)); } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/Reactions/ChatCustomReactionsEditActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/Reactions/ChatCustomReactionsEditActivity.java index 739b4193ea..3fc8967c15 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/Reactions/ChatCustomReactionsEditActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/Reactions/ChatCustomReactionsEditActivity.java @@ -11,6 +11,7 @@ import android.animation.LayoutTransition; import android.annotation.SuppressLint; import android.content.Context; +import android.os.Build; import android.text.Editable; import android.text.Layout; import android.text.SpannableString; @@ -706,7 +707,12 @@ public void onAnimationEnd(Animator animation) { private boolean closeKeyboard() { if (emojiKeyboardVisible) { emojiKeyboardVisible = false; - editText.clearFocus(); + if (isClearFocusNotWorking()) { + switchLayout.setFocusableInTouchMode(true); + switchLayout.requestFocus(); + } else { + editText.clearFocus(); + } updateScrollViewMarginBottom(0); NotificationCenter.getGlobalInstance().postNotificationName(NotificationCenter.stopAllHeavyOperations, 512); bottomDialogLayout.animate().setListener(null).cancel(); @@ -717,6 +723,9 @@ private boolean closeKeyboard() { public void onAnimationEnd(Animator animation) { NotificationCenter.getGlobalInstance().postNotificationName(NotificationCenter.startAllHeavyOperations, 512); bottomDialogLayout.setVisibility(View.INVISIBLE); + if (isClearFocusNotWorking()) { + switchLayout.setFocusableInTouchMode(false); + } } }).start(); return true; @@ -724,6 +733,10 @@ public void onAnimationEnd(Animator animation) { return false; } + private boolean isClearFocusNotWorking() { + return Build.MODEL.toLowerCase().startsWith("zte") && Build.VERSION.SDK_INT <= Build.VERSION_CODES.P; + } + private void updateScrollViewMarginBottom(int margin) { ViewGroup.MarginLayoutParams marginLayoutParams = ((ViewGroup.MarginLayoutParams) scrollView.getLayoutParams()); marginLayoutParams.bottomMargin = margin; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/Reactions/ChatSelectionReactionMenuOverlay.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/Reactions/ChatSelectionReactionMenuOverlay.java index e30d22e70b..7cca87513e 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/Reactions/ChatSelectionReactionMenuOverlay.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/Reactions/ChatSelectionReactionMenuOverlay.java @@ -66,7 +66,9 @@ public void onScrolled(@NonNull RecyclerView recyclerView, int dx, int dy) { private void checkCreateReactionsLayout() { if (reactionsContainerLayout == null) { - reactionsContainerLayout = new ReactionsContainerLayout(ReactionsContainerLayout.TYPE_DEFAULT, parentFragment, getContext(), parentFragment.getCurrentAccount(), parentFragment.getResourceProvider()) { + final boolean tags = parentFragment.getUserConfig().getClientUserId() == parentFragment.getDialogId(); + + reactionsContainerLayout = new ReactionsContainerLayout(tags ? ReactionsContainerLayout.TYPE_TAGS : ReactionsContainerLayout.TYPE_DEFAULT, parentFragment, getContext(), parentFragment.getCurrentAccount(), parentFragment.getResourceProvider()) { float enabledAlpha = 1f; long lastUpdate; @@ -110,7 +112,7 @@ public void setVisibility(int visibility) { reactionsContainerLayout.setDelegate(new ReactionsContainerLayout.ReactionsContainerDelegate() { @Override public void onReactionClicked(View view, ReactionsLayoutInBubble.VisibleReaction visibleReaction, boolean longpress, boolean addToRecent) { - parentFragment.selectReaction(currentPrimaryObject, reactionsContainerLayout, view, 0, 0, visibleReaction, false, longpress, addToRecent); + parentFragment.selectReaction(currentPrimaryObject, reactionsContainerLayout, view, 0, 0, visibleReaction, false, longpress, addToRecent, false); AndroidUtilities.runOnUIThread(() -> { if (reactionsContainerLayout != null) { reactionsContainerLayout.dismissParent(true); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/Reactions/CustomEmojiReactionsWindow.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/Reactions/CustomEmojiReactionsWindow.java index 78cbb7cb31..d2ed41a285 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/Reactions/CustomEmojiReactionsWindow.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/Reactions/CustomEmojiReactionsWindow.java @@ -2,6 +2,7 @@ import static org.telegram.ui.Components.ReactionsContainerLayout.TYPE_STORY; import static org.telegram.ui.Components.ReactionsContainerLayout.TYPE_STORY_LIKES; +import static org.telegram.ui.Components.ReactionsContainerLayout.TYPE_TAGS; import android.animation.Animator; import android.animation.AnimatorListenerAdapter; @@ -66,7 +67,7 @@ public class CustomEmojiReactionsWindow { - ContainerView containerView; + public ContainerView containerView; WindowManager windowManager; public FrameLayout windowView; boolean attachToParent; @@ -164,7 +165,7 @@ public void setAlpha(float alpha) { // sizeNotifierFrameLayout.setFitsSystemWindows(true); containerView = new ContainerView(context); - int dialogType = reactionsContainerLayout.showExpandableReactions() ? SelectAnimatedEmojiDialog.TYPE_EXPANDABLE_REACTIONS : SelectAnimatedEmojiDialog.TYPE_REACTIONS; + final int dialogType = reactionsContainerLayout.getWindowType(); selectAnimatedEmojiDialog = new SelectAnimatedEmojiDialog(baseFragment, context, false, null, dialogType, type != TYPE_STORY, resourcesProvider, 16) { @Override @@ -309,7 +310,7 @@ private void updateWindowPosition() { private WindowManager.LayoutParams createLayoutParams(boolean focusable) { WindowManager.LayoutParams lp = new WindowManager.LayoutParams(); lp.width = lp.height = WindowManager.LayoutParams.MATCH_PARENT; - lp.type = type == ReactionsContainerLayout.TYPE_DEFAULT ? WindowManager.LayoutParams.TYPE_APPLICATION_PANEL : WindowManager.LayoutParams.LAST_APPLICATION_WINDOW; + lp.type = (type == ReactionsContainerLayout.TYPE_DEFAULT || type == ReactionsContainerLayout.TYPE_TAGS) ? WindowManager.LayoutParams.TYPE_APPLICATION_PANEL : WindowManager.LayoutParams.LAST_APPLICATION_WINDOW; lp.softInputMode = WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE; if (focusable) { lp.flags = WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN | WindowManager.LayoutParams.FLAG_LAYOUT_INSET_DECOR; @@ -699,7 +700,7 @@ public void onAnimationEnd(Animator animation) { } } - private class ContainerView extends FrameLayout { + public class ContainerView extends FrameLayout { Drawable shadow; Rect shadowPad = new Rect(); @@ -781,7 +782,7 @@ protected void dispatchDraw(Canvas canvas) { } if (reactionsContainerLayout.hintView != null) { canvas.save(); - canvas.translate(drawingRect.left, drawingRect.top + reactionsContainerLayout.hintView.getY()); + canvas.translate(drawingRect.left, drawingRect.top + reactionsContainerLayout.hintView.getY() - (type == TYPE_TAGS ? reactionsContainerLayout.rect.top : 0)); canvas.saveLayerAlpha( 0, 0, reactionsContainerLayout.hintView.getMeasuredWidth(), reactionsContainerLayout.hintView.getMeasuredHeight(), (int) (255 * reactionsContainerLayout.hintView.getAlpha() * (1f - enterTransitionProgress)), Canvas.ALL_SAVE_FLAG); reactionsContainerLayout.hintView.draw(canvas); canvas.restore(); 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 3c6bfd6eef..caa5e0c366 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 @@ -12,6 +12,9 @@ import android.graphics.PorterDuffXfermode; import android.graphics.Rect; import android.graphics.RectF; +import android.graphics.drawable.Drawable; +import android.text.SpannableString; +import android.text.Spanned; import android.text.TextPaint; import android.text.TextUtils; import android.view.Gravity; @@ -19,14 +22,18 @@ import android.view.View; import android.view.ViewConfiguration; +import androidx.annotation.NonNull; import androidx.core.graphics.ColorUtils; import androidx.recyclerview.widget.ChatListItemAnimator; +import org.checkerframework.checker.units.qual.A; import org.telegram.messenger.AndroidUtilities; import org.telegram.messenger.ApplicationLoader; import org.telegram.messenger.DocumentObject; +import org.telegram.messenger.Emoji; import org.telegram.messenger.ImageLocation; import org.telegram.messenger.ImageReceiver; +import org.telegram.messenger.LocaleController; import org.telegram.messenger.MediaDataController; import org.telegram.messenger.MessageObject; import org.telegram.messenger.MessagesController; @@ -38,8 +45,13 @@ import org.telegram.ui.ActionBar.Theme; import org.telegram.ui.Cells.ChatMessageCell; import org.telegram.ui.Components.AnimatedEmojiDrawable; +import org.telegram.ui.Components.AnimatedEmojiSpan; +import org.telegram.ui.Components.AnimatedFileDrawable; +import org.telegram.ui.Components.AnimatedTextView; import org.telegram.ui.Components.AvatarsDrawable; import org.telegram.ui.Components.CounterView; +import org.telegram.ui.Components.CubicBezierInterpolator; +import org.telegram.ui.Components.RLottieDrawable; import java.util.ArrayList; import java.util.Collections; @@ -58,6 +70,14 @@ public class ReactionsLayoutInBubble { private static Paint tagPaint = new Paint(Paint.ANTI_ALIAS_FLAG); private static Paint cutTagPaint = new Paint(Paint.ANTI_ALIAS_FLAG); private static TextPaint textPaint = new TextPaint(Paint.ANTI_ALIAS_FLAG); + + public static void initPaints(Theme.ResourcesProvider resourcesProvider) { + paint.setColor(Theme.getColor(Theme.key_chat_inLoader, resourcesProvider)); + textPaint.setColor(Theme.getColor(Theme.key_featuredStickers_buttonText, resourcesProvider)); + textPaint.setTextSize(dp(12)); + textPaint.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf")); + cutTagPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR)); + } public boolean isSmall; public int x; @@ -79,14 +99,14 @@ public class ReactionsLayoutInBubble { public boolean isEmpty; private float touchSlop; public int lastLineX; - ArrayList reactionButtons = new ArrayList<>(); + public ArrayList reactionButtons = new ArrayList<>(); ArrayList outButtons = new ArrayList<>(); HashMap lastDrawingReactionButtons = new HashMap<>(); HashMap lastDrawingReactionButtonsTmp = new HashMap<>(); ChatMessageCell parentView; MessageObject messageObject; Theme.ResourcesProvider resourcesProvider; - private String scrimViewReaction; + private Integer scrimViewReaction; int availableWidth; private int lastDrawnWidth; @@ -117,12 +137,8 @@ private static long getPeerId(TLObject object) { public ReactionsLayoutInBubble(ChatMessageCell parentView) { this.parentView = parentView; currentAccount = UserConfig.selectedAccount; - paint.setColor(Theme.getColor(Theme.key_chat_inLoader, resourcesProvider)); - textPaint.setColor(Theme.getColor(Theme.key_featuredStickers_buttonText, resourcesProvider)); - textPaint.setTextSize(dp(12)); - textPaint.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf")); + initPaints(resourcesProvider); touchSlop = ViewConfiguration.get(ApplicationLoader.applicationContext).getScaledTouchSlop(); - cutTagPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR)); } public static boolean equalsTLReaction(TLRPC.Reaction reaction, TLRPC.Reaction reaction1) { @@ -135,9 +151,10 @@ public static boolean equalsTLReaction(TLRPC.Reaction reaction, TLRPC.Reaction r return false; } - public void setMessage(MessageObject messageObject, boolean isSmall, Theme.ResourcesProvider resourcesProvider) { + public void setMessage(MessageObject messageObject, boolean isSmall, boolean isTag, Theme.ResourcesProvider resourcesProvider) { this.resourcesProvider = resourcesProvider; this.isSmall = isSmall; + this.tags = isTag; this.messageObject = messageObject; ArrayList oldButtons = new ArrayList<>(reactionButtons); hasUnreadReactions = false; @@ -159,9 +176,9 @@ public void setMessage(MessageObject messageObject, boolean isSmall, Theme.Resou // break; // } // } - ReactionButton button = new ReactionLayoutButton(old, reactionCount, isSmall); + ReactionButton button = new ReactionLayoutButton(old, reactionCount, isSmall, isTag); reactionButtons.add(button); - if (!isSmall && messageObject.messageOwner.reactions.recent_reactions != null) { + if (!isSmall && !isTag && messageObject.messageOwner.reactions.recent_reactions != null) { ArrayList users = null; if (messageObject.getDialogId() > 0 && !UserObject.isReplyUser(messageObject.getDialogId())) { @@ -212,7 +229,7 @@ public void setMessage(MessageObject messageObject, boolean isSmall, Theme.Resou } } if (isSmall && reactionCount.count > 1 && reactionCount.chosen) { - ReactionButton button2 = new ReactionLayoutButton(null, reactionCount, isSmall); + ReactionButton button2 = new ReactionLayoutButton(null, reactionCount, isSmall, isTag); reactionButtons.add(button2); reactionButtons.get(0).isSelected = false; reactionButtons.get(1).isSelected = true; @@ -261,6 +278,14 @@ public void measure(int availableWidth, int gravity) { if (button.isSmall) { button.width = dp(14); button.height = dp(14); + } else if (button.isTag) { + button.width = dp(42); + button.height = dp(26); + if (button.hasName) { + button.width += button.textDrawable.getAnimateToWidth() + dp(8); + } else if (button.counterDrawable != null && button.count > 1) { + button.width += button.counterDrawable.getCurrentWidth() + dp(8); + } } else { button.width = (int) (dp(8) + dp(20) + dp(4)); if (button.avatarsDrawable != null && button.users.size() > 0) { @@ -269,8 +294,10 @@ public void measure(int availableWidth, int gravity) { int c2 = button.users.size() > 1 ? button.users.size() - 1 : 0; button.width += dp(2) + c1 * dp(20) + c2 * dp(20) * 0.8f + dp(1); button.avatarsDrawable.height = dp(26); + } else if (button.hasName) { + button.width += button.textDrawable.getAnimateToWidth() + dp(8); } else { - button.width += button.counterDrawable.textPaint.measureText(button.countText) + dp(8); + button.width += button.counterDrawable.getCurrentWidth() + dp(8); } button.height = dp(26); } @@ -314,7 +341,7 @@ public void measure(int availableWidth, int gravity) { drawServiceShaderBackground = 0f; } - public void draw(Canvas canvas, float animationProgress, String drawOnlyReaction) { + public void draw(Canvas canvas, float animationProgress, Integer drawOnlyReaction) { if (isEmpty && outButtons.isEmpty()) { return; } @@ -329,7 +356,7 @@ public void draw(Canvas canvas, float animationProgress, String drawOnlyReaction } for (int i = 0; i < reactionButtons.size(); i++) { ReactionButton reactionButton = reactionButtons.get(i); - if (reactionButton.reaction.equals(scrimViewReaction) || (drawOnlyReaction != null && !reactionButton.reaction.equals(drawOnlyReaction))) { + if ((Objects.equals(reactionButton.reaction.hashCode(), scrimViewReaction)) || (drawOnlyReaction != null && reactionButton.reaction.hashCode() != drawOnlyReaction)) { continue; } canvas.save(); @@ -397,6 +424,7 @@ public boolean animateChange() { button.fromTextColor = lastButton.lastDrawnTextColor; button.fromBackgroundColor = lastButton.lastDrawnBackgroundColor; + button.fromTagDotColor = lastButton.lastDrawnTagDotColor; button.animationType = ANIMATION_TYPE_MOVE; if (button.count != lastButton.count && button.counterDrawable != null) { @@ -492,13 +520,13 @@ public ReactionButton getReactionButton(VisibleReaction visibleReaction) { return lastDrawingReactionButtons.get(hash); } - public void setScrimReaction(String scrimViewReaction) { + public void setScrimReaction(Integer scrimViewReaction) { this.scrimViewReaction = scrimViewReaction; } public class ReactionLayoutButton extends ReactionButton { - public ReactionLayoutButton(ReactionButton reuseFrom, TLRPC.ReactionCount reactionCount, boolean isSmall) { - super(reuseFrom, currentAccount, parentView, reactionCount, isSmall, resourcesProvider); + public ReactionLayoutButton(ReactionButton reuseFrom, TLRPC.ReactionCount reactionCount, boolean isSmall, boolean isTag) { + super(reuseFrom, currentAccount, parentView, reactionCount, isSmall, isTag, resourcesProvider); } @Override @@ -532,6 +560,13 @@ protected void removeImageReceiver() { } } + public boolean verifyDrawable(Drawable drawable) { + if (drawable instanceof AnimatedTextView.AnimatedTextDrawable) { + return true; + } + return false; + } + public static class ReactionButton { private final TLRPC.ReactionCount reactionCount; @@ -541,6 +576,7 @@ public static class ReactionButton { public int animateFromY; public int animateFromWidth; public int fromBackgroundColor; + public int fromTagDotColor; public int fromTextColor; public int realCount; public int choosenOrder; @@ -555,15 +591,19 @@ public static class ReactionButton { VisibleReaction visibleReaction; android.graphics.Rect drawingImageRect = new Rect(); + public boolean hasName; + public String name; + public int count; public int x; public int y; public int width; public int height; - ImageReceiver imageReceiver; - AnimatedEmojiDrawable animatedEmojiDrawable; + public ImageReceiver imageReceiver; + public AnimatedEmojiDrawable animatedEmojiDrawable; int animatedEmojiDrawableColor; public CounterView.CounterDrawable counterDrawable; + public AnimatedTextView.AnimatedTextDrawable textDrawable; int backgroundColor; int textColor; int serviceBackgroundColor; @@ -571,8 +611,10 @@ public static class ReactionButton { public int lastDrawnTextColor; public int lastDrawnBackgroundColor; + public int lastDrawnTagDotColor; boolean isSelected; + public boolean isTag; AvatarsDrawable avatarsDrawable; ArrayList users; @@ -581,13 +623,17 @@ public static class ReactionButton { private final Theme.ResourcesProvider resourcesProvider; protected int getCacheType() { + if (isTag) { + return AnimatedEmojiDrawable.CACHE_TYPE_SAVED_REACTION; + } return AnimatedEmojiDrawable.CACHE_TYPE_ALERT_PREVIEW; } - public ReactionButton(ReactionButton reuseFrom, int currentAccount, View parentView, TLRPC.ReactionCount reactionCount, boolean isSmall, Theme.ResourcesProvider resourcesProvider) { + public ReactionButton(ReactionButton reuseFrom, int currentAccount, View parentView, TLRPC.ReactionCount reactionCount, boolean isSmall, boolean isTag, Theme.ResourcesProvider resourcesProvider) { this.currentAccount = currentAccount; this.parentView = parentView; this.resourcesProvider = resourcesProvider; + this.isTag = isTag; if (reuseFrom != null) { counterDrawable = reuseFrom.counterDrawable; } @@ -597,6 +643,14 @@ public ReactionButton(ReactionButton reuseFrom, int currentAccount, View parentV if (counterDrawable == null) { counterDrawable = new CounterView.CounterDrawable(parentView, false, null); } + if (textDrawable == null) { + textDrawable = new AnimatedTextView.AnimatedTextDrawable(true, true, true); + textDrawable.setAnimationProperties(.4f, 0, 320, CubicBezierInterpolator.EASE_OUT_QUINT); + textDrawable.setTextSize(dp(13)); + textDrawable.setCallback(parentView); + textDrawable.setTypeface(AndroidUtilities.getTypeface(AndroidUtilities.TYPEFACE_ROBOTO_MEDIUM)); + textDrawable.setOverrideFullWidth(AndroidUtilities.displaySize.x); + } this.reactionCount = reactionCount; this.reaction = reactionCount.reaction; this.visibleReaction = VisibleReaction.fromTLReaction(reactionCount.reaction); @@ -612,7 +666,6 @@ public ReactionButton(ReactionButton reuseFrom, int currentAccount, View parentV } else { throw new RuntimeException("unsupported"); } - countText = Integer.toString(reactionCount.count); imageReceiver.setParentView(parentView); isSelected = reactionCount.chosen; counterDrawable.updateVisibility = false; @@ -633,17 +686,54 @@ public ReactionButton(ReactionButton reuseFrom, int currentAccount, View parentV counterDrawable.setSize(dp(26), dp(100)); counterDrawable.textPaint = textPaint; - counterDrawable.setCount(count, false); + if (isTag) { + name = MessagesController.getInstance(currentAccount).getSavedTagName(reaction); + hasName = !TextUtils.isEmpty(name); + } + if (hasName) { + textDrawable.setText(Emoji.replaceEmoji(name, textDrawable.getPaint().getFontMetricsInt(), false), !LocaleController.isRTL); + if (drawTextWithCounter()) { + countText = Integer.toString(reactionCount.count); + counterDrawable.setCount(count, false); + } else { + countText = ""; + counterDrawable.setCount(0, false); + } + } else { + if (textDrawable != null) { + textDrawable.setText("", false); + } + countText = Integer.toString(reactionCount.count); + counterDrawable.setCount(count, false); + } counterDrawable.setType(CounterView.CounterDrawable.TYPE_CHAT_REACTIONS); counterDrawable.gravity = Gravity.LEFT; } + private RectF bounds = new RectF(), rect2 = new RectF(); + private final Path tagPath = new Path(); + private void drawRoundRect(Canvas canvas, RectF rectF, float r, Paint paint) { + if (isTag) { + if (bounds.left != rectF.left || bounds.top != rectF.top || bounds.right != rectF.right || bounds.bottom != rectF.bottom) { + bounds.set(rectF); + fillTagPath(bounds, rect2, tagPath); + } + canvas.drawPath(tagPath, paint); + } else { + canvas.drawRoundRect(rectF, r, r, paint); + } + } + protected boolean isOutOwner() { return false; } protected boolean drawCounter() { - return count != 0 || counterDrawable.countChangeProgress != 1f; + return count != 0 && (!isTag || hasName || count != 1) || counterDrawable.countChangeProgress != 1f; + } + + protected boolean drawTextWithCounter() { + return false; } public void draw(Canvas canvas, float x, float y, float progress, float alpha, boolean drawOverlayScrim) { @@ -672,7 +762,11 @@ public void draw(Canvas canvas, float x, float y, float progress, float alpha, b } updateColors(progress); textPaint.setColor(lastDrawnTextColor); + if (textDrawable != null) { + textDrawable.setTextColor(lastDrawnTextColor); + } paint.setColor(lastDrawnBackgroundColor); + final boolean cutTagCircle = isTag && drawTagDot() && Color.alpha(lastDrawnTagDotColor) == 0; if (alpha != 1f) { textPaint.setAlpha((int) (textPaint.getAlpha() * alpha)); @@ -695,20 +789,39 @@ public void draw(Canvas canvas, float x, float y, float progress, float alpha, b int oldAlpha2 = paint2.getAlpha(); paint1.setAlpha((int) (oldAlpha * alpha * getDrawServiceShaderBackground())); paint2.setAlpha((int) (oldAlpha2 * alpha * getDrawServiceShaderBackground())); - canvas.drawRoundRect(AndroidUtilities.rectTmp, rad, rad, paint1); + drawRoundRect(canvas, AndroidUtilities.rectTmp, rad, paint1); if (resourcesProvider != null ? resourcesProvider.hasGradientService() : Theme.hasGradientService()) { - canvas.drawRoundRect(AndroidUtilities.rectTmp, rad, rad, paint2); + drawRoundRect(canvas, AndroidUtilities.rectTmp, rad, paint2); } paint1.setAlpha(oldAlpha); paint2.setAlpha(oldAlpha2); } if (drawOverlayScrim && getDrawServiceShaderBackground() < 1 && parentView instanceof ChatMessageCell) { Theme.MessageDrawable messageBackground = ((ChatMessageCell) parentView).getCurrentBackgroundDrawable(false); - if (messageBackground != null) { + if (messageBackground != null && !isTag) { canvas.drawRoundRect(AndroidUtilities.rectTmp, rad, rad, messageBackground.getPaint()); } } - canvas.drawRoundRect(AndroidUtilities.rectTmp, rad, rad, paint); + if (cutTagCircle) { + AndroidUtilities.rectTmp.right += dp(4); + canvas.saveLayerAlpha(AndroidUtilities.rectTmp, 0xFF, Canvas.ALL_SAVE_FLAG); + AndroidUtilities.rectTmp.right -= dp(4); + } + drawRoundRect(canvas, AndroidUtilities.rectTmp, rad, paint); + if (isTag && drawTagDot()) { + Paint paint; + if (cutTagCircle) { + paint = cutTagPaint; + } else { + tagPaint.setColor(lastDrawnTagDotColor); + tagPaint.setAlpha((int) (tagPaint.getAlpha() * alpha)); + paint = tagPaint; + } + canvas.drawCircle(AndroidUtilities.rectTmp.right - dp(8.4f), AndroidUtilities.rectTmp.centerY(), dp(2.66f), paint); + } + if (cutTagCircle) { + canvas.restore(); + } if (imageReceiver != null) { int size, X; @@ -722,31 +835,47 @@ public void draw(Canvas canvas, float x, float y, float progress, float alpha, b imageReceiver.setRoundRadius(0); } int Y = (int) ((height - size) / 2f); + if (isTag) { + X -= dp(2); + } drawingImageRect.set((int) x + X, (int) y + Y, (int) x + X + size, (int) y + Y + size); imageReceiver.setImageCoords(drawingImageRect); drawImage(canvas, alpha); } + float tx = 0; + if (textDrawable != null && textDrawable.isNotEmpty() > 0) { + canvas.save(); + canvas.translate(x + dp(hasName && !drawTagDot() ? 10 : (hasName ? 9 : 8)) + dp(20) + dp(2), y); + textDrawable.setBounds(0, 0, width, height); + textDrawable.draw(canvas); + textDrawable.setAlpha((int) (0xFF * alpha)); + canvas.restore(); + tx = textDrawable.getCurrentWidth() + dp(4) * textDrawable.isNotEmpty(); + } if (counterDrawable != null && drawCounter()) { canvas.save(); - canvas.translate(x + dp(8) + dp(20) + dp(2), y); + canvas.translate(x + dp(hasName && !drawTagDot() ? 10 : (hasName ? 9 : 8)) + dp(20) + dp(2) + tx, y); counterDrawable.draw(canvas); canvas.restore(); } - if (avatarsDrawable != null) { - canvas.save(); - canvas.translate(x + dp(10) + dp(20) + dp(2), y); - avatarsDrawable.setAlpha(alpha); - avatarsDrawable.setTransitionProgress(progress); - avatarsDrawable.onDraw(canvas); - canvas.restore(); + if (!isTag) { + if (avatarsDrawable != null) { + canvas.save(); + canvas.translate(x + dp(10) + dp(20) + dp(2), y); + avatarsDrawable.setAlpha(alpha); + avatarsDrawable.setTransitionProgress(progress); + avatarsDrawable.onDraw(canvas); + canvas.restore(); + } } } protected void updateColors(float progress) { lastDrawnTextColor = ColorUtils.blendARGB(fromTextColor, ColorUtils.blendARGB(textColor, serviceTextColor, getDrawServiceShaderBackground()), progress); lastDrawnBackgroundColor = ColorUtils.blendARGB(fromBackgroundColor, ColorUtils.blendARGB(backgroundColor, serviceBackgroundColor, getDrawServiceShaderBackground()), progress); + lastDrawnTagDotColor = ColorUtils.blendARGB(fromTagDotColor, AndroidUtilities.computePerceivedBrightness(lastDrawnBackgroundColor) > .8f ? 0 : 0x5affffff, progress); } protected boolean isPlaying() { @@ -870,6 +999,26 @@ public void detach() { animatedEmojiDrawable.removeView(parentView); } } + + public void startAnimation() { + ImageReceiver imageReceiver; + if (animatedEmojiDrawable != null && animatedEmojiDrawable.getImageReceiver() != null) { + imageReceiver = animatedEmojiDrawable.getImageReceiver(); + } else { + imageReceiver = this.imageReceiver; + } + if (imageReceiver != null) { + RLottieDrawable rLottieDrawable = imageReceiver.getLottieAnimation(); + if (rLottieDrawable != null) { + rLottieDrawable.restart(true); + } else { + AnimatedFileDrawable animatedFileDrawable = imageReceiver.getAnimation(); + if (animatedFileDrawable != null) { + animatedFileDrawable.start(); + } + } + } + } } float lastX; @@ -1017,6 +1166,13 @@ public void animateReaction(VisibleReaction reaction) { imageReceiver.setAutoRepeat(0); imageReceiver.onAttachedToWindow(); animatedReactions.put(reaction, imageReceiver); + } else if (tags && reaction.documentId != 0) { + for (int i = 0; i < reactionButtons.size(); ++i) { + if (reaction.isSame(reactionButtons.get(i).reaction)) { + reactionButtons.get(i).startAnimation(); + return; + } + } } } @@ -1107,5 +1263,102 @@ public boolean isSame(TLRPC.Reaction reaction) { } return false; } + + @NonNull + @Override + public String toString() { + if (!TextUtils.isEmpty(emojicon)) + return emojicon; + if (documentId != 0) { + TLRPC.Document document = AnimatedEmojiDrawable.findDocument(UserConfig.selectedAccount, documentId); + if (document != null) { + return MessageObject.findAnimatedEmojiEmoticon(document, null); + } + } + return "VisibleReaction{" + documentId + ", " + emojicon + "}"; + } + + public CharSequence toCharSequence(Paint.FontMetricsInt fontMetrics, int cacheType) { + if (!TextUtils.isEmpty(emojicon)) { + return emojicon; + } + SpannableString string = new SpannableString("😀"); + AnimatedEmojiSpan emojiSpan = new AnimatedEmojiSpan(documentId, fontMetrics); + emojiSpan.cacheType = cacheType; + string.setSpan(emojiSpan, 0, string.length(), Spanned.SPAN_INCLUSIVE_EXCLUSIVE); + return string; + } + + public CharSequence toCharSequence(Paint.FontMetricsInt fontMetrics) { + if (!TextUtils.isEmpty(emojicon)) { + return emojicon; + } + SpannableString string = new SpannableString("😀"); + AnimatedEmojiSpan emojiSpan = new AnimatedEmojiSpan(documentId, fontMetrics); + string.setSpan(emojiSpan, 0, string.length(), Spanned.SPAN_INCLUSIVE_EXCLUSIVE); + return string; + } + + public CharSequence toCharSequence(int textSizeDp) { + TextPaint textPaint = new TextPaint(); + textPaint.setTextSize(AndroidUtilities.dp(textSizeDp)); + if (!TextUtils.isEmpty(emojicon)) { + CharSequence string = emojicon; + string = Emoji.replaceEmoji(string, textPaint.getFontMetricsInt(), false); + return string; + } + SpannableString string = new SpannableString("😀"); + AnimatedEmojiSpan emojiSpan = new AnimatedEmojiSpan(documentId, textPaint.getFontMetricsInt()); + string.setSpan(emojiSpan, 0, string.length(), Spanned.SPAN_INCLUSIVE_EXCLUSIVE); + return string; + } + } + + public static boolean reactionsEqual(TLRPC.Reaction a, TLRPC.Reaction b) { + if (a instanceof TLRPC.TL_reactionEmoji) { + if (!(b instanceof TLRPC.TL_reactionEmoji)) + return false; + return TextUtils.equals(((TLRPC.TL_reactionEmoji) a).emoticon, ((TLRPC.TL_reactionEmoji) b).emoticon); + } else if (a instanceof TLRPC.TL_reactionCustomEmoji) { + if (!(b instanceof TLRPC.TL_reactionCustomEmoji)) + return false; + return ((TLRPC.TL_reactionCustomEmoji) a).document_id == ((TLRPC.TL_reactionCustomEmoji) b).document_id; + } + return false; + } + + public static void fillTagPath(RectF bounds, Path path) { + fillTagPath(bounds, AndroidUtilities.rectTmp, path); + } + public static void fillTagPath(RectF bounds, RectF tempRect, Path path) { + path.rewind(); + tempRect.set(bounds.left, bounds.top, bounds.left + dp(12), bounds.top + dp(12)); + path.arcTo(tempRect, -90, -90, false); + tempRect.set(bounds.left, bounds.bottom - dp(12), bounds.left + dp(12), bounds.bottom); + path.arcTo(tempRect, -180, -90, false); + + float arrowRound = bounds.height() > dp(26) ? 1.4f : 0f; + float x = bounds.right - dpf2(9.09f); + float x1 = x - dpf2(0.056f); + float x1a = x + dpf2(1.22f); + float x2 = x + dpf2(3.07f); + float x2a = x + dpf2(2.406f); + float x3 = x + dpf2(8.27f + arrowRound); + float x3a = x + dpf2(8.923f + arrowRound); + float ty2 = bounds.top + dpf2(1.753f); + float by2 = bounds.bottom - dpf2(1.753f); + float ty2a = bounds.top + dpf2(0.663f); + float by2a = bounds.bottom - dpf2(0.663f); + float ty3 = bounds.top + dpf2(10.263f + arrowRound); + float by3 = bounds.bottom - dpf2(10.263f + arrowRound); + float ty3a = bounds.top + dpf2(11.333f + arrowRound); + float by3a = bounds.bottom - dpf2(11.333f + arrowRound); + path.lineTo(x1, bounds.bottom); + path.cubicTo(x1a, bounds.bottom, x2a, by2a, x2, by2); + path.lineTo(x3, by3); + path.cubicTo(x3a, by3a, x3a, ty3a, x3, ty3); + path.lineTo(x2, ty2); + path.cubicTo(x2a, ty2a, x1a, bounds.top, x1, bounds.top); + path.close(); } } 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 13928b182f..dd1f779437 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/ReactionsContainerLayout.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/ReactionsContainerLayout.java @@ -1,5 +1,7 @@ package org.telegram.ui.Components; +import static org.telegram.messenger.AndroidUtilities.dp; + import android.animation.Animator; import android.animation.AnimatorListenerAdapter; import android.animation.ObjectAnimator; @@ -19,7 +21,11 @@ import android.graphics.Shader; import android.graphics.drawable.Drawable; import android.provider.Settings; +import android.text.Layout; +import android.text.StaticLayout; +import android.util.LongSparseArray; import android.util.Property; +import android.util.SparseArray; import android.util.TypedValue; import android.view.Gravity; import android.view.HapticFeedbackConstants; @@ -27,6 +33,7 @@ import android.view.View; import android.view.ViewConfiguration; import android.view.ViewGroup; +import android.view.ViewTreeObserver; import android.view.accessibility.AccessibilityNodeInfo; import android.view.animation.OvershootInterpolator; import android.widget.FrameLayout; @@ -58,6 +65,7 @@ import org.telegram.messenger.SvgHelper; import org.telegram.messenger.UserConfig; import org.telegram.messenger.Utilities; +import org.telegram.messenger.support.LongSparseLongArray; import org.telegram.tgnet.TLRPC; import org.telegram.tgnet.tl.TL_stories; import org.telegram.ui.ActionBar.AlertDialog; @@ -72,6 +80,8 @@ import org.telegram.ui.Components.Reactions.ReactionsLayoutInBubble; import org.telegram.ui.Components.Reactions.ReactionsUtils; import org.telegram.ui.PremiumPreviewFragment; +import org.telegram.ui.SelectAnimatedEmojiDialog; +import org.telegram.ui.Stories.recorder.HintView2; import java.util.ArrayList; import java.util.HashSet; @@ -104,6 +114,34 @@ public void set(ReactionsContainerLayout object, Float value) { public final RecyclerListView recyclerListView; public final float durationScale; + private static final int VIEW_TYPE_REACTION = 0; + private static final int VIEW_TYPE_PREMIUM_BUTTON = 1; + private static final int VIEW_TYPE_CUSTOM_EMOJI_BUTTON = 2; + private static final int VIEW_TYPE_CUSTOM_REACTION = 3; + + public ArrayList items = new ArrayList<>(); + public ArrayList oldItems = new ArrayList<>(); + + class InnerItem extends AdapterWithDiffUtils.Item { + ReactionsLayoutInBubble.VisibleReaction reaction; + + public InnerItem(int viewType, ReactionsLayoutInBubble.VisibleReaction reaction) { + super(viewType, false); + this.reaction = reaction; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + InnerItem innerItem = (InnerItem) o; + if (viewType == innerItem.viewType && (viewType == VIEW_TYPE_REACTION || viewType == VIEW_TYPE_CUSTOM_REACTION)) { + return reaction != null && reaction.equals(innerItem.reaction); + } + return viewType == innerItem.viewType; + } + } + private Paint bgPaint = new Paint(Paint.ANTI_ALIAS_FLAG); private Paint leftShadowPaint = new Paint(Paint.ANTI_ALIAS_FLAG), rightShadowPaint = new Paint(Paint.ANTI_ALIAS_FLAG); @@ -111,10 +149,10 @@ public void set(ReactionsContainerLayout object, Float value) { private float transitionProgress = 1f; public RectF rect = new RectF(); private Path mPath = new Path(); - public float radius = AndroidUtilities.dp(72); - private float bigCircleRadius = AndroidUtilities.dp(8); + public float radius = dp(72); + private float bigCircleRadius = dp(8); private float smallCircleRadius = bigCircleRadius / 2; - public int bigCircleOffset = AndroidUtilities.dp(36); + public int bigCircleOffset = dp(36); private MessageObject messageObject; private int currentAccount; private long waitingLoadingChatId; @@ -181,9 +219,10 @@ public void set(ReactionsContainerLayout object, Float value) { public boolean skipEnterAnimation; public boolean isHiddenNextReaction = true; private Runnable onSwitchedToLoopView; - private boolean hasHint; + public boolean hasHint; public TextView hintView; - private float bubblesOffset; + public int hintViewWidth, hintViewHeight; + public float bubblesOffset; public ReactionsContainerLayout(int type, BaseFragment fragment, @NonNull Context context, int currentAccount, Theme.ResourcesProvider resourcesProvider) { super(context); @@ -205,7 +244,7 @@ public ReactionsContainerLayout(int type, BaseFragment fragment, @NonNull Contex animationEnabled = SharedConfig.animationsEnabled() && SharedConfig.getDevicePerformanceClass() != SharedConfig.PERFORMANCE_CLASS_LOW; shadow = ContextCompat.getDrawable(context, R.drawable.reactions_bubble_shadow).mutate(); - shadowPad.left = shadowPad.top = shadowPad.right = shadowPad.bottom = AndroidUtilities.dp(7); + shadowPad.left = shadowPad.top = shadowPad.right = shadowPad.bottom = dp(7); shadow.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_chat_messagePanelShadow), PorterDuff.Mode.MULTIPLY)); recyclerListView = new RecyclerListView(context) { @@ -295,14 +334,14 @@ public void getItemOffsets(@NonNull Rect outRect, @NonNull View view, @NonNull R if (!showCustomEmojiReaction()) { int position = parent.getChildAdapterPosition(view); if (position == 0) { - outRect.left = AndroidUtilities.dp(6); + outRect.left = dp(6); } - outRect.right = AndroidUtilities.dp(4); + outRect.right = dp(4); if (position == listAdapter.getItemCount() - 1) { if (showUnlockPremiumButton() || showCustomEmojiReaction()) { - outRect.right = AndroidUtilities.dp(2); + outRect.right = dp(2); } else { - outRect.right = AndroidUtilities.dp(6); + outRect.right = dp(6); } } } else { @@ -337,7 +376,7 @@ public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int premiumLockIconView.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_dialogBackground), PorterDuff.Mode.MULTIPLY)); premiumLockIconView.setScaleX(0f); premiumLockIconView.setScaleY(0f); - premiumLockIconView.setPadding(AndroidUtilities.dp(1), AndroidUtilities.dp(1), AndroidUtilities.dp(1), AndroidUtilities.dp(1)); + premiumLockIconView.setPadding(dp(1), dp(1), dp(1), dp(1)); premiumLockContainer.addView(premiumLockIconView, LayoutHelper.createFrame(26, 26, Gravity.CENTER)); premiumLockIconView.setOnClickListener(v -> { int[] position = new int[2]; @@ -356,8 +395,8 @@ public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int } else { customEmojiReactionsIconView.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_dialogBackground), PorterDuff.Mode.MULTIPLY)); } - customEmojiReactionsIconView.setBackground(Theme.createSimpleSelectorCircleDrawable(AndroidUtilities.dp(28), Color.TRANSPARENT, ColorUtils.setAlphaComponent(Theme.getColor(Theme.key_listSelector), 40))); - customEmojiReactionsIconView.setPadding(AndroidUtilities.dp(2), AndroidUtilities.dp(2), AndroidUtilities.dp(2), AndroidUtilities.dp(2)); + customEmojiReactionsIconView.setBackground(Theme.createSimpleSelectorCircleDrawable(dp(28), Color.TRANSPARENT, ColorUtils.setAlphaComponent(Theme.getColor(Theme.key_listSelector), 40))); + customEmojiReactionsIconView.setPadding(dp(2), dp(2), dp(2), dp(2)); customEmojiReactionsIconView.setContentDescription(LocaleController.getString(R.string.AccDescrExpandPanel)); customReactionsContainer.addView(customEmojiReactionsIconView, LayoutHelper.createFrame(30, 30, Gravity.CENTER)); customEmojiReactionsIconView.setOnClickListener(v -> { @@ -367,8 +406,8 @@ public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int break; } - int size = getLayoutParams().height - (hasHint ? AndroidUtilities.dp(20) : 0) - getPaddingTop() - getPaddingBottom(); - view.setLayoutParams(new RecyclerView.LayoutParams(size - AndroidUtilities.dp(12), size)); + int size = getLayoutParams().height - (int) getTopOffset() - getPaddingTop() - getPaddingBottom(); + view.setLayoutParams(new RecyclerView.LayoutParams(size - dp(12), size)); return new RecyclerListView.Holder(view); } @@ -382,6 +421,17 @@ public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int positi } } + @Override + public void onViewAttachedToWindow(@NonNull RecyclerView.ViewHolder holder) { + if (holder.getItemViewType() == VIEW_TYPE_REACTION || holder.getItemViewType() == VIEW_TYPE_CUSTOM_REACTION) { + int position = holder.getAdapterPosition(); + if (position >= 0 && position < items.size()) { + ((ReactionHolderView) holder.itemView).updateSelected(items.get(position).reaction); + } + } + super.onViewAttachedToWindow(holder); + } + @Override public int getItemCount() { return items.size(); @@ -392,14 +442,6 @@ public int getItemViewType(int position) { return items.get(position).viewType; } - ArrayList items = new ArrayList<>(); - ArrayList oldItems = new ArrayList<>(); - - private static final int VIEW_TYPE_REACTION = 0; - private static final int VIEW_TYPE_PREMIUM_BUTTON = 1; - private static final int VIEW_TYPE_CUSTOM_EMOJI_BUTTON = 2; - private static final int VIEW_TYPE_CUSTOM_REACTION = 3; - @Override public void notifyDataSetChanged() { oldItems.clear(); @@ -417,28 +459,6 @@ public void notifyDataSetChanged() { } setItems(oldItems, items); } - - class InnerItem extends AdapterWithDiffUtils.Item { - - ReactionsLayoutInBubble.VisibleReaction reaction; - - public InnerItem(int viewType, ReactionsLayoutInBubble.VisibleReaction reaction) { - super(viewType, false); - this.reaction = reaction; - } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - InnerItem innerItem = (InnerItem) o; - if (viewType == innerItem.viewType && (viewType == VIEW_TYPE_REACTION || viewType == VIEW_TYPE_CUSTOM_REACTION)) { - return reaction != null && reaction.equals(innerItem.reaction); - } - return viewType == innerItem.viewType; - } - - } }); recyclerListView.addOnScrollListener(new LeftRightShadowsListener()); recyclerListView.addOnScrollListener(new RecyclerView.OnScrollListener() { @@ -480,9 +500,9 @@ public void onScrolled(@NonNull RecyclerView recyclerView, int dx, int dy) { public void getItemOffsets(@NonNull Rect outRect, @NonNull View view, @NonNull RecyclerView parent, @NonNull RecyclerView.State state) { int i = parent.getChildAdapterPosition(view); if (i == 0) - outRect.left = AndroidUtilities.dp(8); + outRect.left = dp(8); if (i == listAdapter.getItemCount() - 1) { - outRect.right = AndroidUtilities.dp(8); + outRect.right = dp(8); } } }); @@ -506,7 +526,7 @@ public void getItemOffsets(@NonNull Rect outRect, @NonNull View view, @NonNull R invalidateShaders(); int size = recyclerListView.getLayoutParams().height - recyclerListView.getPaddingTop() - recyclerListView.getPaddingBottom(); - nextRecentReaction.getLayoutParams().width = size - AndroidUtilities.dp(12); + nextRecentReaction.getLayoutParams().width = size - dp(12); nextRecentReaction.getLayoutParams().height = size; if (type == TYPE_STORY_LIKES) { @@ -521,6 +541,16 @@ public boolean showExpandableReactions() { return showExpandableReactions; } + public int getWindowType() { + if (type == TYPE_TAGS) { + return SelectAnimatedEmojiDialog.TYPE_TAGS; + } + if (showExpandableReactions) { + return SelectAnimatedEmojiDialog.TYPE_EXPANDABLE_REACTIONS; + } + return SelectAnimatedEmojiDialog.TYPE_REACTIONS; + } + private void animatePullingBack() { if (pullingLeftOffset != 0) { pullingDownBackAnimator = ValueAnimator.ofFloat(pullingLeftOffset, 0); @@ -541,7 +571,9 @@ public void setOnSwitchedToLoopView(Runnable onSwitchedToLoopView) { } public void dismissWindow() { - reactionsWindow.dismiss(); + if (reactionsWindow != null) { + reactionsWindow.dismiss(); + } } public CustomEmojiReactionsWindow getReactionsWindow() { @@ -561,9 +593,14 @@ private void showCustomEmojiReactionDialog() { delegate.onEmojiWindowDismissed(); } }); + onShownCustomEmojiReactionDialog(); //animatePullingBack(); } + protected void onShownCustomEmojiReactionDialog(){ + + } + private void invalidateLoopViews() { for (int i = 0; i < recyclerListView.getChildCount(); i++) { View child = recyclerListView.getChildAt(i); @@ -618,7 +655,7 @@ private void setVisibleReactionsList(List 7) { n = 7; } @@ -643,8 +680,8 @@ private void setVisibleReactionsList(List 0) { float progress = getPullingLeftProgress(); - int reactionSize = nextRecentReaction.getMeasuredWidth() - AndroidUtilities.dp(2); + int reactionSize = nextRecentReaction.getMeasuredWidth() - dp(2); int left = lastReactionX + reactionSize; float leftProgress = Utilities.clamp(left / (float) (getMeasuredWidth() - nextRecentReaction.getMeasuredWidth()), 1f, 0f); float pullingOffsetX = leftProgress * progress * reactionSize; @@ -826,9 +863,9 @@ protected void dispatchDraw(Canvas canvas) { nextRecentReaction.setScaleY(scale); float additionalOffset = 0; if (type != TYPE_STORY && type != TYPE_STORY_LIKES) { - additionalOffset = - AndroidUtilities.dp(20); + additionalOffset = - dp(20); } else { - additionalOffset = - AndroidUtilities.dp(8); + additionalOffset = - dp(8); } nextRecentReaction.setTranslationX(recyclerListView.getX() + left - pullingOffsetX + additionalOffset); if (nextRecentReaction.getVisibility() != View.VISIBLE) { @@ -893,12 +930,12 @@ private void drawBubbles(Canvas canvas, float br, float cPr, float sr, int alpha if (isTop) { canvas.clipRect(0, 0, getMeasuredWidth(), AndroidUtilities.lerp(rect.top, getMeasuredHeight(), CubicBezierInterpolator.DEFAULT.getInterpolation(flipVerticalProgress)) - (int) Math.ceil(rect.height() / 2f * (1f - transitionProgress)) + 1); } else { - canvas.clipRect(0, AndroidUtilities.lerp(rect.bottom, 0, CubicBezierInterpolator.DEFAULT.getInterpolation(flipVerticalProgress)) - (int) Math.ceil(rect.height() / 2f * (1f - transitionProgress)) - 1, getMeasuredWidth(), AndroidUtilities.lerp(getMeasuredHeight() + AndroidUtilities.dp(8), getPaddingTop() - expandSize(), CubicBezierInterpolator.DEFAULT.getInterpolation(flipVerticalProgress))); + canvas.clipRect(0, AndroidUtilities.lerp(rect.bottom, 0, CubicBezierInterpolator.DEFAULT.getInterpolation(flipVerticalProgress)) - (int) Math.ceil(rect.height() / 2f * (1f - transitionProgress)) - 1, getMeasuredWidth(), AndroidUtilities.lerp(getMeasuredHeight() + dp(8), getPaddingTop() - expandSize(), CubicBezierInterpolator.DEFAULT.getInterpolation(flipVerticalProgress))); } float cx = LocaleController.isRTL || mirrorX ? bigCircleOffset : getWidth() - bigCircleOffset; cx += bubblesOffset; float cy = isTop ? getPaddingTop() - expandSize() : getHeight() - getPaddingBottom() + expandSize(); - int sPad = AndroidUtilities.dp(3); + int sPad = dp(3); shadow.setAlpha(alpha); bgPaint.setAlpha(alpha); shadow.setBounds((int) (cx - br - sPad * cPr), (int) (cy - br - sPad * cPr), (int) (cx + br + sPad * cPr), (int) (cy + br + sPad * cPr)); @@ -912,9 +949,9 @@ private void drawBubbles(Canvas canvas, float br, float cPr, float sr, int alpha cx = LocaleController.isRTL || mirrorX ? bigCircleOffset - bigCircleRadius : getWidth() - bigCircleOffset + bigCircleRadius; cx += bubblesOffset; - cy = isTop ? getPaddingTop() - expandSize() - AndroidUtilities.dp(16) : getHeight() - smallCircleRadius - sPad + expandSize(); + cy = isTop ? getPaddingTop() - expandSize() - dp(16) : getHeight() - smallCircleRadius - sPad + expandSize(); cy = AndroidUtilities.lerp(cy, smallCircleRadius + sPad - expandSize(), CubicBezierInterpolator.DEFAULT.getInterpolation(flipVerticalProgress)); - sPad = -AndroidUtilities.dp(1); + sPad = -dp(1); shadow.setBounds((int) (cx - br - sPad * cPr), (int) (cy - br - sPad * cPr), (int) (cx + br + sPad * cPr), (int) (cy + br + sPad * cPr)); shadow.draw(canvas); if (delegate.drawBackground()) { @@ -949,8 +986,8 @@ private void checkPressedProgress(Canvas canvas, ReactionHolderView view) { float pullingOffsetX = 0; if (pullingLeftOffset != 0) { float progress = getPullingLeftProgress(); - float leftProgress = Utilities.clamp(view.getLeft() / (float) (getMeasuredWidth() - AndroidUtilities.dp(34)), 1f, 0f); - pullingOffsetX = leftProgress * progress * AndroidUtilities.dp(46); + float leftProgress = Utilities.clamp(view.getLeft() / (float) (getMeasuredWidth() - dp(34)), 1f, 0f); + pullingOffsetX = leftProgress * progress * dp(46); } if (view.currentReaction.equals(pressedReaction)) { View imageView = view.loopImageView.getVisibility() == View.VISIBLE ? view.loopImageView : view.enterImageView; @@ -1018,7 +1055,7 @@ private void checkPressedProgress(Canvas canvas, ReactionHolderView view) { } public float getPullingLeftProgress() { - return Utilities.clamp(pullingLeftOffset / AndroidUtilities.dp(42), 2f, 0f); + return Utilities.clamp(pullingLeftOffset / dp(42), 2f, 0f); } @Override @@ -1031,7 +1068,7 @@ protected void onSizeChanged(int w, int h, int oldw, int oldh) { * Invalidates shaders */ private void invalidateShaders() { - int dp = AndroidUtilities.dp(24); + int dp = dp(24); float cy = getHeight() / 2f; int clr = Theme.getColor(Theme.key_actionBarDefaultSubmenuBackground); leftShadowPaint.setShader(new LinearGradient(0, cy, dp, cy, clr, Color.TRANSPARENT, Shader.TileMode.CLAMP)); @@ -1096,6 +1133,9 @@ public void setMessage(MessageObject message, TLRPC.ChatFull chatFull) { } filterReactions(visibleReactions); showExpandableReactions = !allReactionsAvailable && visibleReactions.size() > 16 || allReactionsAvailable && !UserConfig.getInstance(currentAccount).isPremium() && MessagesController.getInstance(currentAccount).premiumFeaturesBlocked(); + if (type == TYPE_TAGS && !UserConfig.getInstance(currentAccount).isPremium()) { + showExpandableReactions = false; + } setVisibleReactionsList(visibleReactions); if (message != null && message.messageOwner.reactions != null && message.messageOwner.reactions.results != null) { @@ -1124,6 +1164,74 @@ public void setSelectedReaction(ReactionsLayoutInBubble.VisibleReaction visibleR listAdapter.notifyDataSetChanged(); } + public void setSelectedReactions(ArrayList messages) { + selectedReactions.clear(); + for (int a = 0; a < messages.size(); ++a) { + MessageObject message = messages.get(a); + if (message != null && message.messageOwner.reactions != null && message.messageOwner.reactions.results != null) { + for (int i = 0; i < message.messageOwner.reactions.results.size(); i++) { + if (message.messageOwner.reactions.results.get(i).chosen) { + selectedReactions.add(ReactionsLayoutInBubble.VisibleReaction.fromTLReaction(message.messageOwner.reactions.results.get(i).reaction)); + } + } + } + } + listAdapter.notifyDataSetChanged(); + } + + public HashSet getSelectedReactions() { + return selectedReactions; + } + + public static HashSet getInclusiveReactions(ArrayList messages) { + LongSparseArray arr = new LongSparseArray<>(); + HashSet messageReactions = new HashSet<>(); + boolean firstMessage = true; + for (int k = 0; k < messages.size(); ++k) { + MessageObject message = messages.get(k); + messageReactions.clear(); + if (message != null && message.messageOwner.reactions != null && message.messageOwner.reactions.results != null) { + for (int i = 0; i < message.messageOwner.reactions.results.size(); i++) { + if (message.messageOwner.reactions.results.get(i).chosen) { + ReactionsLayoutInBubble.VisibleReaction reaction = ReactionsLayoutInBubble.VisibleReaction.fromTLReaction(message.messageOwner.reactions.results.get(i).reaction); + if (firstMessage || arr.indexOfKey(reaction.hash) >= 0) { + messageReactions.add(reaction.hash); + arr.put(reaction.hash, reaction); + } + } + } + } + firstMessage = false; + for (int j = 0; j < arr.size(); ++j) { + if (!messageReactions.contains(arr.keyAt(j))) { + arr.removeAt(j); + j--; + } + } + } + HashSet selectedReactions = new HashSet<>(); + for (int j = 0; j < arr.size(); ++j) { + selectedReactions.add(arr.valueAt(j)); + } + return selectedReactions; + } + + public void setSelectedReactionsInclusive(ArrayList messages) { + selectedReactions.clear(); + selectedReactions.addAll(getInclusiveReactions(messages)); + updateSelected(); + } + + private void updateSelected() { + AndroidUtilities.forEachViews(recyclerListView, child -> { + int position = recyclerListView.getChildAdapterPosition(child); + if (position < 0 || position >= items.size()) return; + if (child instanceof ReactionHolderView) { + ((ReactionHolderView) child).updateSelected(items.get(position).reaction); + } + }); + } + private void filterReactions(List visibleReactions) { HashSet set = new HashSet<>(); for (int i = 0; i < visibleReactions.size(); i++) { @@ -1172,7 +1280,7 @@ private void fillRecentReactionsList(List hashSet = new HashSet<>(); int added = 0; if (type == TYPE_TAGS) { - TLRPC.TL_messages_savedReactionsTags savedTags = MessagesController.getInstance(currentAccount).getSavedReactionTags(); + TLRPC.TL_messages_savedReactionsTags savedTags = MessagesController.getInstance(currentAccount).getSavedReactionTags(0); if (savedTags != null) { for (int i = 0; i < savedTags.tags.size(); i++) { ReactionsLayoutInBubble.VisibleReaction visibleReaction = ReactionsLayoutInBubble.VisibleReaction.fromTLReaction(savedTags.tags.get(i).reaction); @@ -1181,21 +1289,22 @@ private void fillRecentReactionsList(List 1 && !hintView.getText().toString().contains("\n")) { + maxWidth = HintView2.cutInFancyHalf(hintView.getText(), hintView.getPaint()); + layout = new StaticLayout(hintView.getText(), hintView.getPaint(), maxWidth, Layout.Alignment.ALIGN_NORMAL, 1.0f, 0.0f, false); + hintViewHeight = layout.getHeight(); + hintViewWidth = 0; + for (int i = 0; i < layout.getLineCount(); ++i) { + hintViewWidth = Math.max(hintViewWidth, (int) Math.ceil(layout.getLineWidth(i))); + } + hintView.setPadding(dp(24), 0, dp(24), 0); + hintView.setWidth(dp(48) + maxWidth); + } else { + hintView.setWidth(dp(16) + maxWidth); + } + + int margin = Math.max(dp(20), dp(7) + hintViewHeight); + if (type == TYPE_STORY || type == TYPE_STORY_LIKES) { + margin = dp(20); + } else { + getLayoutParams().height = dp(52) + margin + dp(22); + } + ((LayoutParams) nextRecentReaction.getLayoutParams()).topMargin = margin; + ((LayoutParams) recyclerListView.getLayoutParams()).topMargin = margin; + hintMeasured = true; } public void setTop(boolean isTop) { @@ -1429,7 +1590,7 @@ public void setTop(boolean isTop) { } public float getTopOffset() { - return hasHint ? AndroidUtilities.dp(20) : 0; + return hasHint ? ((LayoutParams) recyclerListView.getLayoutParams()).topMargin : 0; } public void setBubbleOffset(float v) { @@ -1488,6 +1649,7 @@ public final class ReactionHolderView extends FrameLayout { public BackupImageView pressedBackupImageView; private ImageReceiver preloadImageReceiver = new ImageReceiver(); public ReactionsLayoutInBubble.VisibleReaction currentReaction; + public PremiumLockIconView lockIconView; public float sideScale = 1f; private boolean isEnter; public boolean hasEnterAnimation; @@ -1661,6 +1823,25 @@ public void invalidate() { pressedBackupImageView.setLayerNum(Integer.MAX_VALUE); } + + public boolean isLocked; + + public void updateSelected(ReactionsLayoutInBubble.VisibleReaction react) { + boolean wasSelected = selected; + selected = selectedReactions.contains(react); + if (selected != wasSelected) { + if (selected) { + loopImageView.getLayoutParams().width = loopImageView.getLayoutParams().height = dp(26); + enterImageView.getLayoutParams().width = enterImageView.getLayoutParams().height = dp(26); + } else { + loopImageView.getLayoutParams().width = loopImageView.getLayoutParams().height = dp(34); + enterImageView.getLayoutParams().width = enterImageView.getLayoutParams().height = dp(34); + } + requestLayout(); + invalidate(); + } + } + private void setReaction(ReactionsLayoutInBubble.VisibleReaction react, int position) { if (currentReaction != null && currentReaction.equals(react)) { this.position = position; @@ -1668,6 +1849,18 @@ private void setReaction(ReactionsLayoutInBubble.VisibleReaction react, int posi updateImage(react); return; } + + isLocked = type == TYPE_TAGS && !UserConfig.getInstance(currentAccount).isPremium(); + if (isLocked && lockIconView == null) { + lockIconView = new PremiumLockIconView(getContext(), PremiumLockIconView.TYPE_STICKERS_PREMIUM_LOCKED); + lockIconView.setScaleType(ImageView.ScaleType.CENTER_INSIDE); + lockIconView.setImageReceiver(loopImageView.getImageReceiver()); + addView(lockIconView, LayoutHelper.createFrame(18, 18, Gravity.CENTER, 8, 8, 0, 0)); + } + if (lockIconView != null) { + lockIconView.setVisibility(isLocked ? View.VISIBLE : View.GONE); + } + resetAnimation(); currentReaction = react; selected = selectedReactions.contains(react); @@ -1679,15 +1872,26 @@ private void setReaction(ReactionsLayoutInBubble.VisibleReaction react, int posi if (enterImageView.getImageReceiver().getLottieAnimation() != null) { enterImageView.getImageReceiver().getLottieAnimation().setCurrentFrame(0, false); } + if (lockIconView != null) { + lockIconView.setAnimatedEmojiDrawable(null); + } } else { pressedBackupImageView.getImageReceiver().clearImage(); loopImageView.getImageReceiver().clearImage(); AnimatedEmojiDrawable pressedDrawable = new AnimatedEmojiDrawable(AnimatedEmojiDrawable.CACHE_TYPE_ALERT_PREVIEW_LARGE, currentAccount, currentReaction.documentId); - pressedDrawable.setColorFilter(Theme.getAnimatedEmojiColorFilter(resourcesProvider)); pressedBackupImageView.setAnimatedEmojiDrawable(pressedDrawable); AnimatedEmojiDrawable loopDrawable = new AnimatedEmojiDrawable(AnimatedEmojiDrawable.CACHE_TYPE_ALERT_PREVIEW, currentAccount, currentReaction.documentId); - loopDrawable.setColorFilter(Theme.getAnimatedEmojiColorFilter(resourcesProvider)); + if (type == TYPE_STORY || type == TYPE_STORY_LIKES) { + pressedDrawable.setColorFilter(new PorterDuffColorFilter(Color.WHITE, PorterDuff.Mode.MULTIPLY)); + loopDrawable.setColorFilter(new PorterDuffColorFilter(Color.WHITE, PorterDuff.Mode.MULTIPLY)); + } else { + pressedDrawable.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_dialogBackground), PorterDuff.Mode.MULTIPLY)); + loopDrawable.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_dialogBackground), PorterDuff.Mode.MULTIPLY)); + } loopImageView.setAnimatedEmojiDrawable(loopDrawable); + if (lockIconView != null) { + lockIconView.setAnimatedEmojiDrawable(loopDrawable); + } } setFocusable(true); shouldSwitchToLoopView = hasEnterAnimation;// && !allReactionsIsDefault; @@ -1701,11 +1905,11 @@ private void setReaction(ReactionsLayoutInBubble.VisibleReaction react, int posi loopImageView.setVisibility(View.GONE); } if (selected) { - loopImageView.getLayoutParams().width = loopImageView.getLayoutParams().height = AndroidUtilities.dp(26); - enterImageView.getLayoutParams().width = enterImageView.getLayoutParams().height = AndroidUtilities.dp(26); + loopImageView.getLayoutParams().width = loopImageView.getLayoutParams().height = dp(26); + enterImageView.getLayoutParams().width = enterImageView.getLayoutParams().height = dp(26); } else { - loopImageView.getLayoutParams().width = loopImageView.getLayoutParams().height = AndroidUtilities.dp(34); - enterImageView.getLayoutParams().width = enterImageView.getLayoutParams().height = AndroidUtilities.dp(34); + loopImageView.getLayoutParams().width = loopImageView.getLayoutParams().height = dp(34); + enterImageView.getLayoutParams().width = enterImageView.getLayoutParams().height = dp(34); } } @@ -1733,6 +1937,9 @@ private void updateImage(ReactionsLayoutInBubble.VisibleReaction react) { preloadImageReceiver.setAllowStartLottieAnimation(false); MediaDataController.getInstance(currentAccount).preloadImage(preloadImageReceiver, ImageLocation.getForDocument(defaultReaction.around_animation), ReactionsEffectOverlay.getFilterForAroundAnimation()); } + if (lockIconView != null) { + lockIconView.setImageReceiver(loopImageView.getImageReceiver()); + } } } @@ -1841,17 +2048,14 @@ public void run() { @Override public boolean onTouchEvent(MotionEvent event) { - if (!touchable) { - return false; - } - if (cancelPressedAnimation != null) { + if (!touchable || cancelPressedAnimation != null) { return false; } if (event.getAction() == MotionEvent.ACTION_DOWN) { pressed = true; pressedX = event.getX(); pressedY = event.getY(); - if (sideScale == 1f) { + if (sideScale == 1f && !isLocked && type != TYPE_TAGS) { AndroidUtilities.runOnUIThread(longPressRunnable, ViewConfiguration.getLongPressTimeout()); } } @@ -1879,13 +2083,13 @@ public boolean onTouchEvent(MotionEvent event) { @Override protected void dispatchDraw(Canvas canvas) { if (selected && drawSelected) { - canvas.drawCircle(getMeasuredWidth() >> 1, getMeasuredHeight() >> 1, (getMeasuredWidth() >> 1) - AndroidUtilities.dp(1), selectedPaint); + canvas.drawCircle(getMeasuredWidth() >> 1, getMeasuredHeight() >> 1, (getMeasuredWidth() >> 1) - dp(1), selectedPaint); } if (loopImageView.animatedEmojiDrawable != null && loopImageView.animatedEmojiDrawable.getImageReceiver() != null) { if (position == 0) { - loopImageView.animatedEmojiDrawable.getImageReceiver().setRoundRadius(AndroidUtilities.dp(6), 0, 0, AndroidUtilities.dp(6)); + loopImageView.animatedEmojiDrawable.getImageReceiver().setRoundRadius(dp(6), 0, 0, dp(6)); } else { - loopImageView.animatedEmojiDrawable.getImageReceiver().setRoundRadius(selected ? AndroidUtilities.dp(6) : 0); + loopImageView.animatedEmojiDrawable.getImageReceiver().setRoundRadius(selected ? dp(6) : 0); } } super.dispatchDraw(canvas); @@ -2096,7 +2300,7 @@ protected void dispatchDraw(Canvas canvas) { } public float expandSize() { - return (int) (getPullingLeftProgress() * AndroidUtilities.dp(6)); + return (int) (getPullingLeftProgress() * dp(6)); } public void setParentLayout(ChatScrimPopupContainerLayout layout) { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/SearchTagsList.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/SearchTagsList.java index bb13929e7d..ac65f14971 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/SearchTagsList.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/SearchTagsList.java @@ -1,60 +1,105 @@ package org.telegram.ui.Components; +import static org.telegram.messenger.AndroidUtilities.cancelRunOnUIThread; import static org.telegram.messenger.AndroidUtilities.dp; import static org.telegram.messenger.AndroidUtilities.lerp; +import static org.telegram.messenger.AndroidUtilities.runOnUIThread; +import android.animation.Animator; +import android.animation.AnimatorListenerAdapter; +import android.animation.ValueAnimator; +import android.app.Activity; import android.content.Context; import android.graphics.Canvas; -import android.graphics.Color; import android.graphics.Paint; +import android.graphics.Path; +import android.graphics.PorterDuff; +import android.graphics.PorterDuffColorFilter; +import android.graphics.RectF; +import android.graphics.drawable.Drawable; +import android.text.Editable; +import android.text.InputType; +import android.text.SpannableString; +import android.text.SpannableStringBuilder; +import android.text.Spanned; +import android.text.TextPaint; +import android.text.TextUtils; +import android.text.TextWatcher; +import android.text.style.CharacterStyle; +import android.util.TypedValue; +import android.view.Gravity; +import android.view.HapticFeedbackConstants; +import android.util.Log; +import android.view.KeyEvent; import android.view.MotionEvent; import android.view.View; import android.view.ViewGroup; +import android.view.inputmethod.EditorInfo; +import android.widget.EditText; import android.widget.FrameLayout; import android.widget.LinearLayout; +import android.widget.TextView; import androidx.annotation.NonNull; import androidx.annotation.Nullable; -import androidx.collection.LongSparseArray; import androidx.core.graphics.ColorUtils; import androidx.recyclerview.widget.DefaultItemAnimator; import androidx.recyclerview.widget.DiffUtil; import androidx.recyclerview.widget.LinearLayoutManager; import androidx.recyclerview.widget.RecyclerView; +import org.checkerframework.checker.units.qual.A; import org.telegram.messenger.AndroidUtilities; +import org.telegram.messenger.Emoji; +import org.telegram.messenger.ImageReceiver; +import org.telegram.messenger.LocaleController; import org.telegram.messenger.MediaDataController; +import org.telegram.messenger.MessageObject; import org.telegram.messenger.MessagesController; -import org.telegram.messenger.MessagesStorage; import org.telegram.messenger.NotificationCenter; +import org.telegram.messenger.R; +import org.telegram.messenger.SharedConfig; +import org.telegram.messenger.UserConfig; +import org.telegram.tgnet.ConnectionsManager; import org.telegram.tgnet.TLRPC; +import org.telegram.ui.ActionBar.AlertDialog; +import org.telegram.ui.ActionBar.AlertDialogDecor; +import org.telegram.ui.ActionBar.BaseFragment; import org.telegram.ui.ActionBar.Theme; +import org.telegram.ui.Components.Premium.PremiumFeatureBottomSheet; import org.telegram.ui.Components.Reactions.ReactionsLayoutInBubble; -import org.telegram.ui.LaunchActivity; +import org.telegram.ui.PremiumPreviewFragment; import java.util.ArrayList; import java.util.HashSet; -import java.util.Objects; public class SearchTagsList extends BlurredFrameLayout implements NotificationCenter.NotificationCenterDelegate { private final int currentAccount; + private final BaseFragment fragment; private final Theme.ResourcesProvider resourcesProvider; public final RecyclerListView listView; private final Adapter adapter; + private LinearLayout premiumLayout; + private long chosen; private final ArrayList oldItems = new ArrayList<>(); private final ArrayList items = new ArrayList<>(); + private boolean shownPremiumLayout; private static class Item { ReactionsLayoutInBubble.VisibleReaction reaction; int count; + String name; + int nameHash; - public static Item get(ReactionsLayoutInBubble.VisibleReaction reaction, int count) { + public static Item get(ReactionsLayoutInBubble.VisibleReaction reaction, int count, String name) { Item item = new Item(); item.reaction = reaction; item.count = count; + item.name = name; + item.nameHash = name == null ? -233 : name.hashCode(); return item; } @@ -68,17 +113,130 @@ public boolean equals(@Nullable Object obj) { return false; } Item that = (Item) obj; - return this.count == that.count && this.reaction.hash == that.reaction.hash; + return this.count == that.count && this.reaction.hash == that.reaction.hash && this.nameHash == that.nameHash; } } - public SearchTagsList(Context context, SizeNotifierFrameLayout contentView, int currentAccount, Theme.ResourcesProvider resourcesProvider) { + public void setChosen(ReactionsLayoutInBubble.VisibleReaction visibleReaction, boolean notify) { + if (visibleReaction == null) { + chosen = 0; + if (notify) { + setFilter(null); + } + adapter.notifyDataSetChanged(); + return; + } + for (int i = 0; i < items.size(); i++) { + SearchTagsList.Item item = items.get(i); + if (visibleReaction.hash == item.reaction.hash) { + chosen = item.hash(); + if (notify) { + setFilter(item.reaction); + } + adapter.notifyDataSetChanged(); + listView.scrollToPosition(i); + break; + } + } + } + + private void createPremiumLayout() { + if (premiumLayout != null) { + return; + } + + premiumLayout = new LinearLayout(getContext()); + premiumLayout.setOnClickListener(v -> { + new PremiumFeatureBottomSheet(fragment, PremiumPreviewFragment.PREMIUM_FEATURE_SAVED_TAGS, true).show(); + }); + premiumLayout.setOrientation(LinearLayout.HORIZONTAL); + ScaleStateListAnimator.apply(premiumLayout, 0.03f, 1.25f); + + TextView tagView = new TextView(getContext()) { + private final Path path = new Path(); + private final RectF bounds = new RectF(); + private final Paint paint = new Paint(); + @Override + protected void dispatchDraw(Canvas canvas) { + paint.setColor(Theme.multAlpha(Theme.getColor(Theme.key_windowBackgroundWhiteBlueText2, resourcesProvider), 0.10f)); + bounds.set(0, 0, getWidth(), getHeight()); + ReactionsLayoutInBubble.fillTagPath(bounds, path); + canvas.drawPath(path, paint); + super.dispatchDraw(canvas); + } + + @Override + protected void onLayout(boolean changed, int l, int t, int r, int b) { + super.onLayout(changed, l, t, r, b); + int left = getWidth(), right = 0; + for (int i = 0; i < getChildCount(); ++i) { + left = Math.min(left, getChildAt(i).getLeft()); + right = Math.max(right, getChildAt(i).getRight()); + } + setPivotX((left + right) / 2f); + } + }; + tagView.setTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteBlueText2, resourcesProvider)); + tagView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 12); + tagView.setTypeface(AndroidUtilities.getTypeface(AndroidUtilities.TYPEFACE_ROBOTO_MEDIUM)); + SpannableStringBuilder ssb = new SpannableStringBuilder(); + Drawable lockDrawable = getContext().getResources().getDrawable(R.drawable.msg_mini_lock3).mutate(); + lockDrawable.setColorFilter(new PorterDuffColorFilter(Theme.key_chat_messageLinkIn, PorterDuff.Mode.SRC_IN)); + ColoredImageSpan span = new ColoredImageSpan(lockDrawable); + span.setTranslateY(0); + span.setTranslateX(0); + span.setScale(.94f, .94f); + SpannableString lock = new SpannableString("l"); + lock.setSpan(span, 0, lock.length(), Spanned.SPAN_INCLUSIVE_EXCLUSIVE); + ssb.append(lock); + ssb.append(" ").append(LocaleController.getString(R.string.AddTagsToYourSavedMessages1)); + tagView.setText(ssb); + tagView.setPadding(dp(4), dp(4), dp(9), dp(4)); + + TextView textView = new TextView(getContext()); + textView.setTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteBlueText2, resourcesProvider)); + textView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 12); + textView.setTypeface(AndroidUtilities.getTypeface(AndroidUtilities.TYPEFACE_ROBOTO_MEDIUM)); + ssb = new SpannableStringBuilder(LocaleController.getString(R.string.AddTagsToYourSavedMessages2)); + SpannableString arrow = new SpannableString(">"); + Drawable imageDrawable = getContext().getResources().getDrawable(R.drawable.msg_arrowright).mutate(); + imageDrawable.setColorFilter(new PorterDuffColorFilter(Theme.key_chat_messageLinkIn, PorterDuff.Mode.SRC_IN)); + span = new ColoredImageSpan(imageDrawable); + span.setScale(.76f, .76f); + span.setTranslateX(-dp(1)); + span.setTranslateY(dp(1)); + arrow.setSpan(span, 0, arrow.length(), Spanned.SPAN_INCLUSIVE_EXCLUSIVE); + ssb.append(arrow); + textView.setText(ssb); + textView.setPadding(dp(5.66f), dp(4), dp(9), dp(4)); + + premiumLayout.addView(tagView, LayoutHelper.createLinear(LayoutHelper.WRAP_CONTENT, LayoutHelper.MATCH_PARENT)); + premiumLayout.addView(textView, LayoutHelper.createLinear(LayoutHelper.WRAP_CONTENT, LayoutHelper.MATCH_PARENT)); + + addView(premiumLayout, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.CENTER_VERTICAL | Gravity.FILL_HORIZONTAL, 16.33f, 0, 16.33f, 0)); + } + + private long topicId; + + public SearchTagsList(Context context, BaseFragment fragment, SizeNotifierFrameLayout contentView, int currentAccount, long topicId, Theme.ResourcesProvider resourcesProvider, boolean showWithCut) { super(context, contentView); + this.showWithCut = showWithCut; this.currentAccount = currentAccount; + this.fragment = fragment; this.resourcesProvider = resourcesProvider; + this.topicId = topicId; + ReactionsLayoutInBubble.initPaints(resourcesProvider); listView = new RecyclerListView(context, resourcesProvider) { + @Override + public boolean dispatchTouchEvent(MotionEvent ev) { + if (premiumLayout != null && premiumLayout.getAlpha() > 0.5f) { + return false; + } + return super.dispatchTouchEvent(ev); + } + @Override public Integer getSelectorColor(int position) { return 0; @@ -90,59 +248,291 @@ public Integer getSelectorColor(int position) { layoutManager.setOrientation(RecyclerView.HORIZONTAL); listView.setLayoutManager(layoutManager); listView.setAdapter(adapter = new Adapter()); - addView(listView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT)); + listView.setOverScrollMode(OVER_SCROLL_NEVER); + addView(listView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 48)); listView.setOnItemClickListener((view, position) -> { if (position < 0 || position >= items.size()) { return; } + if (!UserConfig.getInstance(currentAccount).isPremium()) { + new PremiumFeatureBottomSheet(fragment, PremiumPreviewFragment.PREMIUM_FEATURE_SAVED_TAGS, true).show(); + return; + } + long hash = items.get(position).hash(); + if (!setFilter(chosen == hash ? null : items.get(position).reaction)) { + return; + } + for (int i = 0; i < listView.getChildCount(); i++) { + View child = listView.getChildAt(i); + if (child == view) { + if (i <= 1) { + listView.smoothScrollBy(-dp(i == 0 ? 90 : 50), 0); + } else if (i >= listView.getChildCount() - 2) { + listView.smoothScrollBy(dp((i == listView.getChildCount() - 1) ? 80 : 50), 0); + } + } + } listView.forAllChild(view2 -> { if (view2 instanceof TagButton) { ((TagButton) view2).setChosen(false, true); } }); - long hash = items.get(position).hash(); if (chosen == hash) { chosen = 0; - setFilter(null); } else { chosen = hash; - setFilter(items.get(position).reaction); ((TagButton) view).setChosen(true, true); } }); + listView.setOnItemLongClickListener((view, position) -> { + if (position < 0 || position >= items.size() || !UserConfig.getInstance(currentAccount).isPremium()) + return false; + if (!UserConfig.getInstance(currentAccount).isPremium()) { + new PremiumFeatureBottomSheet(fragment, PremiumPreviewFragment.PREMIUM_FEATURE_SAVED_TAGS, true).show(); + return true; + } + TagButton btn = (TagButton) view; + if (btn.reactionButton != null) { + btn.reactionButton.startAnimation(); + } + final Item item = items.get(position); + ItemOptions.makeOptions(fragment, view) + .setGravity(Gravity.LEFT) + .add(R.drawable.menu_tag_rename, LocaleController.getString(TextUtils.isEmpty(item.name) ? R.string.SavedTagLabelTag : R.string.SavedTagRenameTag), () -> { + openRenameTagAlert(getContext(), currentAccount, item.reaction.toTLReaction(), resourcesProvider, false); + }) + .show(); + return true; + }); DefaultItemAnimator itemAnimator = new DefaultItemAnimator() { @Override - public boolean animateMove(RecyclerView.ViewHolder holder, ItemHolderInfo info, int fromX, int fromY, int toX, int toY) { - int position = holder.getAdapterPosition(); - if (position >= 0 && position < items.size()) { - Item item = items.get(position); - TagButton btn = (TagButton) holder.itemView; - boolean updatedChosen = btn.setChosen(chosen == item.hash(), true); - boolean updatedCount = btn.setCount(item.count); - if (updatedChosen || updatedCount) { - return true; - } - } - return super.animateMove(holder, info, fromX, fromY, toX, toY); + public boolean canReuseUpdatedViewHolder(@NonNull RecyclerView.ViewHolder viewHolder) { + return true; } - @Override - protected void animateMoveImpl(RecyclerView.ViewHolder holder, MoveInfo moveInfo) { - super.animateMoveImpl(holder, moveInfo); + public boolean animateMove(RecyclerView.ViewHolder holder, ItemHolderInfo info, int fromX, int fromY, int toX, int toY) { + final View view = holder.itemView; + if (view instanceof TagButton) { + ((TagButton) view).startAnimate(); + } + fromX += (int) holder.itemView.getTranslationX(); + fromY += (int) holder.itemView.getTranslationY(); + resetAnimation(holder); + int deltaX = toX - fromX; + int deltaY = toY - fromY; + if (deltaX == 0 && deltaY == 0) { + dispatchMoveFinished(holder); + return false; + } + if (deltaX != 0) { + view.setTranslationX(-deltaX); + } + if (deltaY != 0) { + view.setTranslationY(-deltaY); + } + mPendingMoves.add(new MoveInfo(holder, fromX, fromY, toX, toY)); + checkIsRunning(); + return true; } }; - itemAnimator.setSupportsChangeAnimations(false); itemAnimator.setInterpolator(CubicBezierInterpolator.EASE_OUT_QUINT); itemAnimator.setDurations(320); listView.setItemAnimator(itemAnimator); MediaDataController.getInstance(currentAccount).loadSavedReactions(false); - updateTags(); + updateTags(false); + } + + @Override + protected boolean drawChild(Canvas canvas, View child, long drawingTime) { + if (child == listView && premiumLayout != null) { + if (premiumLayout.getAlpha() >= 1f) + return false; + canvas.saveLayerAlpha(0, 0, getWidth(), getHeight(), (int) (0xFF * (1f - premiumLayout.getAlpha())), Canvas.ALL_SAVE_FLAG); + boolean r = super.drawChild(canvas, child, drawingTime); + canvas.restore(); + return r; + } + return super.drawChild(canvas, child, drawingTime); + } + + private static AlertDialog currentDialog; + public static boolean onBackPressedRenameTagAlert() { + if (currentDialog != null) { + currentDialog.dismiss(); + currentDialog = null; + return true; + } + return false; + } + public static void openRenameTagAlert(Context context, int currentAccount, TLRPC.Reaction reaction, Theme.ResourcesProvider resourcesProvider, boolean forceNotAdaptive) { + Activity activity = AndroidUtilities.findActivity(context); + View currentFocus = activity != null ? activity.getCurrentFocus() : null; + final boolean adaptive = currentFocus instanceof EditText && !forceNotAdaptive; + AlertDialog[] dialog = new AlertDialog[1]; + AlertDialog.Builder builder; + if (adaptive) { + builder = new AlertDialogDecor.Builder(context, resourcesProvider); + } else { + builder = new AlertDialog.Builder(context, resourcesProvider); + } + String[] hintText = new String[1]; + String name = MessagesController.getInstance(currentAccount).getSavedTagName(reaction); + builder.setTitle(new SpannableStringBuilder(ReactionsLayoutInBubble.VisibleReaction.fromTLReaction(reaction).toCharSequence(20)).append(" ").append(LocaleController.getString(TextUtils.isEmpty(name) ? R.string.SavedTagLabelTag : R.string.SavedTagRenameTag))); + + final int MAX_NAME_LENGTH = 12; + EditTextBoldCursor editText = new EditTextBoldCursor(context) { + AnimatedColor limitColor = new AnimatedColor(this); + private int limitCount; + AnimatedTextView.AnimatedTextDrawable limit = new AnimatedTextView.AnimatedTextDrawable(false, true, true); { + limit.setAnimationProperties(.2f, 0, 160, CubicBezierInterpolator.EASE_OUT_QUINT); + limit.setTextSize(dp(15.33f)); + limit.setCallback(this); + limit.setGravity(Gravity.RIGHT); + } + + @Override + protected boolean verifyDrawable(@NonNull Drawable who) { + return who == limit || super.verifyDrawable(who); + } + + @Override + protected void onTextChanged(CharSequence text, int start, int lengthBefore, int lengthAfter) { + super.onTextChanged(text, start, lengthBefore, lengthAfter); + + if (limit != null) { + limitCount = MAX_NAME_LENGTH - text.length(); + limit.cancelAnimation(); + limit.setText(limitCount > 4 ? "" : "" + limitCount); + } + } + + @Override + protected void dispatchDraw(Canvas canvas) { + super.dispatchDraw(canvas); + + limit.setTextColor(limitColor.set(Theme.getColor(limitCount < 0 ? Theme.key_text_RedRegular : Theme.key_dialogSearchHint, resourcesProvider))); + limit.setBounds(getScrollX(), 0, getScrollX() + getWidth(), getHeight()); + limit.draw(canvas); + } + + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + super.onMeasure(widthMeasureSpec, MeasureSpec.makeMeasureSpec(AndroidUtilities.dp(36), MeasureSpec.EXACTLY)); + } + }; + editText.setOnEditorActionListener(new TextView.OnEditorActionListener() { + @Override + public boolean onEditorAction(TextView v, int actionId, KeyEvent event) { + if (actionId == EditorInfo.IME_ACTION_DONE) { + String text = editText.getText().toString(); + if (text.length() > MAX_NAME_LENGTH) { + AndroidUtilities.shakeView(editText); + return true; + } + MessagesController.getInstance(currentAccount).renameSavedReactionTag(ReactionsLayoutInBubble.VisibleReaction.fromTLReaction(reaction), text); + if (dialog[0] != null) { + dialog[0].dismiss(); + } + if (dialog[0] == currentDialog) { + currentDialog = null; + } + if (currentFocus != null) { + currentFocus.requestFocus(); + } + return true; + } + return false; + } + }); + MediaDataController.getInstance(currentAccount).fetchNewEmojiKeywords(AndroidUtilities.getCurrentKeyboardLanguage(), true); + editText.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 18); + editText.setText(name == null ? "" : name); + editText.setTextColor(Theme.getColor(Theme.key_dialogTextBlack, resourcesProvider)); + editText.setHintColor(Theme.getColor(Theme.key_groupcreate_hintText, resourcesProvider)); + editText.setHintText(LocaleController.getString(R.string.SavedTagLabelPlaceholder)); + editText.setSingleLine(true); + editText.setFocusable(true); + editText.setInputType(InputType.TYPE_TEXT_FLAG_CAP_SENTENCES); + editText.setLineColors(Theme.getColor(Theme.key_windowBackgroundWhiteInputField, resourcesProvider), Theme.getColor(Theme.key_windowBackgroundWhiteInputFieldActivated, resourcesProvider), Theme.getColor(Theme.key_text_RedRegular, resourcesProvider)); + editText.setImeOptions(EditorInfo.IME_ACTION_DONE); + editText.setBackgroundDrawable(null); + editText.setPadding(0, 0, dp(42), 0); +// editText.addTextChangedListener(new TextWatcher() { +// boolean ignoreTextChange; +// @Override +// public void beforeTextChanged(CharSequence s, int start, int count, int after) {} +// @Override +// public void onTextChanged(CharSequence s, int start, int before, int count) {} +// @Override +// public void afterTextChanged(Editable s) { +// if (ignoreTextChange) { +// return; +// } +// if (s.length() > MAX_NAME_LENGTH) { +// ignoreTextChange = true; +// s.delete(MAX_NAME_LENGTH, s.length()); +// AndroidUtilities.shakeView(editText); +// editText.performHapticFeedback(HapticFeedbackConstants.KEYBOARD_TAP, HapticFeedbackConstants.FLAG_IGNORE_GLOBAL_SETTING); +// ignoreTextChange = false; +// } +// } +// }); + + LinearLayout container = new LinearLayout(context); + container.setOrientation(LinearLayout.VERTICAL); + + TextView textView = new TextView(context); + textView.setTextColor(Theme.getColor(Theme.key_dialogTextBlack, resourcesProvider)); + textView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 16); + textView.setText(LocaleController.getString(R.string.SavedTagLabelTagText)); + container.addView(textView, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, 24, 5, 24, 12)); + + container.addView(editText, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, 24, 0, 24, 10)); + builder.setView(container); + builder.setWidth(dp(292)); + + builder.setPositiveButton(LocaleController.getString(R.string.Save), (dialogInterface, i) -> { + String text = editText.getText().toString(); + if (text.length() > MAX_NAME_LENGTH) { + AndroidUtilities.shakeView(editText); + return; + } + MessagesController.getInstance(currentAccount).renameSavedReactionTag(ReactionsLayoutInBubble.VisibleReaction.fromTLReaction(reaction), text); + dialogInterface.dismiss(); + }); + builder.setNegativeButton(LocaleController.getString("Cancel", R.string.Cancel), (dialogInterface, i) -> { + dialogInterface.dismiss(); + }); + if (adaptive) { + dialog[0] = currentDialog = builder.create(); + currentDialog.setOnDismissListener(d -> { + currentDialog = null; + currentFocus.requestFocus(); + }); + currentDialog.setOnShowListener(d -> { + editText.requestFocus(); + AndroidUtilities.showKeyboard(editText); + }); + currentDialog.showDelayed(250); + } else { + dialog[0] = builder.create(); + dialog[0].setOnDismissListener(d -> { + AndroidUtilities.hideKeyboard(editText); + }); + dialog[0].setOnShowListener(d -> { + editText.requestFocus(); + AndroidUtilities.showKeyboard(editText); + }); + dialog[0].show(); + } + dialog[0].setDismissDialogByButtons(false); + editText.setSelection(editText.getText().length()); } public boolean hasFilters() { - return !items.isEmpty(); + return !items.isEmpty() || shownPremiumLayout; } public void clear() { @@ -154,68 +544,109 @@ public void clear() { chosen = 0; } - protected void setFilter(ReactionsLayoutInBubble.VisibleReaction reaction) { - + protected boolean setFilter(ReactionsLayoutInBubble.VisibleReaction reaction) { + return true; } public void attach() { NotificationCenter.getInstance(currentAccount).addObserver(this, NotificationCenter.savedReactionTagsUpdate); + NotificationCenter.getInstance(currentAccount).addObserver(this, NotificationCenter.emojiLoaded); } public void detach() { NotificationCenter.getInstance(currentAccount).removeObserver(this, NotificationCenter.savedReactionTagsUpdate); + NotificationCenter.getInstance(currentAccount).removeObserver(this, NotificationCenter.emojiLoaded); } @Override public void didReceivedNotification(int id, int account, Object... args) { if (id == NotificationCenter.savedReactionTagsUpdate) { - updateTags(); + final long thisTopicId = (long) args[0]; + if (thisTopicId == 0 || thisTopicId == topicId) { + updateTags(true); + } + } else if (id == NotificationCenter.emojiLoaded) { + invalidate(); + AndroidUtilities.forEachViews(listView, View::invalidate); } } - public void updateTags() { + public void updateTags(boolean notify) { HashSet hashes = new HashSet<>(); + oldItems.clear(); oldItems.addAll(items); items.clear(); - TLRPC.TL_messages_savedReactionsTags savedReactionsTags = MessagesController.getInstance(currentAccount).getSavedReactionTags(); + + final MessagesController ms = MessagesController.getInstance(currentAccount); + TLRPC.TL_messages_savedReactionsTags savedReactionsTags = ms.getSavedReactionTags(topicId); + boolean hasChosen = false; + if (savedReactionsTags != null) { for (int i = 0; i < savedReactionsTags.tags.size(); ++i) { TLRPC.TL_savedReactionTag tag = savedReactionsTags.tags.get(i); ReactionsLayoutInBubble.VisibleReaction r = ReactionsLayoutInBubble.VisibleReaction.fromTLReaction(tag.reaction); if (!hashes.contains(r.hash)) { - items.add(Item.get(r, tag.count)); + if (topicId != 0 && tag.count <= 0) + continue; + Item item = Item.get(r, tag.count, topicId != 0 ? ms.getSavedTagName(tag.reaction) : tag.title); + if (item.hash() == chosen) { + hasChosen = true; + } + items.add(item); hashes.add(r.hash); } } } -// ArrayList defaultReactions = MediaDataController.getInstance(currentAccount).getSavedReactions(); -// for (int i = 0; i < defaultReactions.size(); ++i) { -// ReactionsLayoutInBubble.VisibleReaction r = ReactionsLayoutInBubble.VisibleReaction.fromTLReaction(defaultReactions.get(i)); -// if (!hashes.contains(r.hash)) { -// items.add(Item.get(r, 0)); -// hashes.add(r.hash); -// } -// } - DiffUtil.calculateDiff(new DiffUtil.Callback() { - @Override - public int getOldListSize() { - return oldItems.size(); - } - @Override - public int getNewListSize() { - return items.size(); - } - @Override - public boolean areItemsTheSame(int oldItemPosition, int newItemPosition) { - return oldItems.get(oldItemPosition).equals(items.get(newItemPosition)); + if (!hasChosen && chosen != 0) { + chosen = 0; + setFilter(null); + } + + if (notify) { + DiffUtil.calculateDiff(new DiffUtil.Callback() { + @Override + public int getOldListSize() { + return oldItems.size(); + } + + @Override + public int getNewListSize() { + return items.size(); + } + + @Override + public boolean areItemsTheSame(int oldItemPosition, int newItemPosition) { + return oldItems.get(oldItemPosition).hash() == items.get(newItemPosition).hash(); + } + + @Override + public boolean areContentsTheSame(int oldItemPosition, int newItemPosition) { + return oldItems.get(oldItemPosition).equals(items.get(newItemPosition)); + } + }).dispatchUpdatesTo(adapter); + } else { + adapter.notifyDataSetChanged(); + } + + if (shownPremiumLayout = !UserConfig.getInstance(currentAccount).isPremium()) { + createPremiumLayout(); + if (!notify) { + premiumLayout.setVisibility(View.VISIBLE); + premiumLayout.setAlpha(0f); + premiumLayout.animate().alpha(1f).start(); } - @Override - public boolean areContentsTheSame(int oldItemPosition, int newItemPosition) { - return oldItems.get(oldItemPosition).hash() == items.get(newItemPosition).hash(); + } else if (premiumLayout != null) { + if (notify) { + premiumLayout.animate().alpha(0f).withEndAction(() -> { + premiumLayout.setVisibility(View.GONE); + }).start(); + } else { + premiumLayout.setAlpha(1f); + premiumLayout.setVisibility(View.VISIBLE); } - }).dispatchUpdatesTo(adapter); + } } @Override @@ -231,36 +662,87 @@ public boolean dispatchTouchEvent(MotionEvent ev) { return super.dispatchTouchEvent(ev); } - private float shownT; + public float shownT; + public boolean showWithCut = true; public void setShown(float shownT) { this.shownT = shownT; listView.setPivotX(listView.getWidth() / 2f); listView.setPivotY(0); listView.setScaleX(lerp(0.8f, 1, shownT)); listView.setScaleY(lerp(0.8f, 1, shownT)); - listView.setAlpha(shownT); + if (showWithCut) { + listView.setAlpha(shownT); + } else { + setAlpha(shownT); + } invalidate(); } - public boolean shown() { - return shownT > 0.5f; + protected void onShownUpdate(boolean finish) { + } -// private final Paint backgroundPaint = new Paint(); -// @Override -// public void setBackgroundColor(int color) { -// backgroundPaint.setColor(color); -// } + private float actionBarTagsT; + private ValueAnimator actionBarTagsAnimator; + public void show(boolean show) { + if (actionBarTagsAnimator != null) { + Animator a = actionBarTagsAnimator; + actionBarTagsAnimator = null; + a.cancel(); + } + if (show) { + setVisibility(View.VISIBLE); + } + actionBarTagsAnimator = ValueAnimator.ofFloat(actionBarTagsT, show ? 1f : 0f); + actionBarTagsAnimator.addUpdateListener(valueAnimator1 -> { + actionBarTagsT = (float) valueAnimator1.getAnimatedValue(); + setShown(actionBarTagsT); + onShownUpdate(false); + }); + actionBarTagsAnimator.setInterpolator(CubicBezierInterpolator.EASE_OUT_QUINT); + actionBarTagsAnimator.setDuration(320); + actionBarTagsAnimator.addListener(new AnimatorListenerAdapter() { + @Override + public void onAnimationEnd(Animator animation) { + if (animation != actionBarTagsAnimator) return; + actionBarTagsT = show ? 1f : 0f; + setShown(actionBarTagsT); + if (!show) { + setVisibility(View.GONE); + } + onShownUpdate(true); + } + }); + actionBarTagsAnimator.start(); + } + public boolean shown() { + return shownT > 0.5f; + } public int getCurrentHeight() { return (int) (getMeasuredHeight() * shownT); } + private Paint backgroundPaint2; + @Override + public void setBackgroundColor(int color) { + if (SharedConfig.chatBlurEnabled() && super.sizeNotifierFrameLayout != null) { + super.setBackgroundColor(color); + } else { + backgroundPaint2 = new Paint(Paint.ANTI_ALIAS_FLAG); + backgroundPaint2.setColor(color); + } + } + @Override protected void dispatchDraw(Canvas canvas) { canvas.save(); -// canvas.drawRect(0, 0, getWidth(), getCurrentHeight(), backgroundPaint); - canvas.clipRect(0, 0, getWidth(), getCurrentHeight()); + if (showWithCut) { + canvas.clipRect(0, 0, getWidth(), getCurrentHeight()); + } + if (backgroundPaint2 != null) { + canvas.drawRect(0, 0, getWidth(), getCurrentHeight(), backgroundPaint2); + } super.dispatchDraw(canvas); canvas.restore(); } @@ -288,7 +770,16 @@ public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position) { if (position < 0 || position >= items.size()) return; final Item item = items.get(position); - ((TagButton) holder.itemView).set(item.reaction.toTLReaction(), item.count); + ((TagButton) holder.itemView).set(item); + ((TagButton) holder.itemView).setChosen(item.hash() == chosen, false); + } + + @Override + public void onViewAttachedToWindow(@NonNull RecyclerView.ViewHolder holder) { + super.onViewAttachedToWindow(holder); + int position = holder.getAdapterPosition(); + if (position < 0 || position >= items.size()) return; + final Item item = items.get(position); ((TagButton) holder.itemView).setChosen(item.hash() == chosen, false); } @@ -305,50 +796,93 @@ public boolean isEnabled(RecyclerView.ViewHolder holder) { private class TagButton extends View { public ReactionsLayoutInBubble.ReactionButton reactionButton; + private final AnimatedFloat progress = new AnimatedFloat(this, 0, 260, CubicBezierInterpolator.EASE_OUT_QUINT); + private int count; public TagButton(Context context) { super(context); ScaleStateListAnimator.apply(this); } - private int count; - public void set(TLRPC.Reaction reaction, Integer count) { - TLRPC.TL_reactionCount reactionCount = new TLRPC.TL_reactionCount(); - reactionCount.reaction = reaction; - reactionCount.count = this.count = count == null ? 0 : count; + private ReactionsLayoutInBubble.VisibleReaction lastReaction; + public void set(Item item) { + boolean newReactionButton = lastReaction == null || !lastReaction.equals(item.reaction); + if (newReactionButton) { + TLRPC.TL_reactionCount reactionCount = new TLRPC.TL_reactionCount(); + reactionCount.reaction = item.reaction.toTLReaction(); + reactionCount.count = item.count; + + reactionButton = new ReactionsLayoutInBubble.ReactionButton(null, currentAccount, this, reactionCount, false, true, resourcesProvider) { + @Override + protected void updateColors(float progress) { + lastDrawnTextColor = ColorUtils.blendARGB(fromTextColor, chosen ? Theme.getColor(Theme.key_chat_inReactionButtonTextSelected, resourcesProvider) : Theme.getColor(Theme.key_actionBarActionModeReactionText, resourcesProvider), progress); + lastDrawnBackgroundColor = ColorUtils.blendARGB(fromBackgroundColor, chosen ? Theme.getColor(Theme.key_chat_inReactionButtonBackground, resourcesProvider) : Theme.getColor(Theme.key_actionBarActionModeReaction, resourcesProvider), progress); + lastDrawnTextColor = Theme.blendOver(lastDrawnBackgroundColor, lastDrawnTextColor); + lastDrawnTagDotColor = ColorUtils.blendARGB(fromTagDotColor, chosen ? 0x5affffff : Theme.getColor(Theme.key_actionBarActionModeReactionDot, resourcesProvider), progress); + } - reactionButton = new ReactionsLayoutInBubble.ReactionButton(null, currentAccount, this, reactionCount, false, resourcesProvider) { - @Override - protected void updateColors(float progress) { - lastDrawnTextColor = ColorUtils.blendARGB(fromTextColor, chosen ? Theme.getColor(Theme.key_chat_inReactionButtonTextSelected) : Theme.getColor(Theme.key_windowBackgroundWhiteGrayText2), progress); - lastDrawnBackgroundColor = ColorUtils.blendARGB(fromBackgroundColor, chosen ? Theme.getColor(Theme.key_chat_inReactionButtonBackground, resourcesProvider) : Theme.getColor(Theme.key_actionBarActionModeReaction, resourcesProvider), progress); - } + @Override + protected boolean drawTagDot() { + return !drawCounter(); + } - @Override - protected boolean drawTagDot() { - return !drawCounter(); - } + @Override + protected int getCacheType() { + return AnimatedEmojiDrawable.CACHE_TYPE_SAVED_REACTION; + } - @Override - protected int getCacheType() { - return AnimatedEmojiDrawable.CACHE_TYPE_ALERT_EMOJI_STATUS; - } + @Override + protected boolean drawCounter() { + return count > 0 || hasName || counterDrawable.countChangeProgress != 1f; + } - @Override - protected boolean drawCounter() { - return count > 0 || counterDrawable.countChangeProgress != 1f; - } - }; + @Override + protected boolean drawTextWithCounter() { + return true; + } + }; + reactionButton.counterDrawable.setSize(dp(29), dp(100)); + reactionButton.isTag = true; + } else { + reactionButton.count = item.count; + } + lastReaction = item.reaction; + if (!newReactionButton) { + reactionButton.animateFromWidth = reactionButton.width; + } reactionButton.width = dp(44.33f); - reactionButton.counterDrawable.setCount(reactionCount.count, false); - if (reactionButton.counterDrawable != null && reactionButton.count > 0) { - reactionButton.width += reactionButton.counterDrawable.textPaint.measureText(reactionButton.countText); + reactionButton.hasName = !TextUtils.isEmpty(item.name); + if (reactionButton.hasName) { + reactionButton.textDrawable.setText(Emoji.replaceEmoji(item.name, reactionButton.textDrawable.getPaint().getFontMetricsInt(), false), !newReactionButton); + } else if (reactionButton.textDrawable != null) { + reactionButton.textDrawable.setText("", !newReactionButton); + } + reactionButton.countText = Integer.toString(item.count); + reactionButton.counterDrawable.setCount(item.count, !newReactionButton); + if (reactionButton.counterDrawable != null && (reactionButton.count > 0 || reactionButton.hasName)) { + reactionButton.width += reactionButton.counterDrawable.getCurrentWidth() + dp(reactionButton.hasName ? 4 : 0) + reactionButton.textDrawable.getAnimateToWidth(); + } + if (newReactionButton) { + reactionButton.animateFromWidth = reactionButton.width; } reactionButton.height = dp(28); reactionButton.choosen = chosen; if (attached) { reactionButton.attach(); } + + if (!newReactionButton) { + requestLayout(); + } + } + + public void startAnimate() { + if (reactionButton == null) return; + reactionButton.fromTextColor = reactionButton.lastDrawnTextColor; + reactionButton.fromBackgroundColor = reactionButton.lastDrawnBackgroundColor; + reactionButton.fromTagDotColor = reactionButton.lastDrawnTagDotColor; + progress.set(0, true); + invalidate(); } private boolean chosen; @@ -361,6 +895,7 @@ public boolean setChosen(boolean value, boolean animated) { if (animated) { reactionButton.fromTextColor = reactionButton.lastDrawnTextColor; reactionButton.fromBackgroundColor = reactionButton.lastDrawnBackgroundColor; + reactionButton.fromTagDotColor = reactionButton.lastDrawnTagDotColor; progress.set(0, true); } else { progress.set(1, true); @@ -370,30 +905,11 @@ public boolean setChosen(boolean value, boolean animated) { return true; } - public boolean setCount(int count) { - if (this.count != count && reactionButton != null) { - reactionButton.animateFromWidth = reactionButton.width; - reactionButton.count = count; - reactionButton.width = dp(44.33f); - reactionButton.counterDrawable.setCount(count, true); - if (reactionButton.counterDrawable != null && reactionButton.count > 0) { - reactionButton.width += reactionButton.counterDrawable.textPaint.measureText(reactionButton.countText); - } - progress.set(0, true); - invalidate(); - return true; - } - return false; - } - @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(MeasureSpec.makeMeasureSpec(dp(8.67f) + (reactionButton != null ? reactionButton.width : dp(44.33f)), MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec(dp(40), MeasureSpec.EXACTLY)); } - - private AnimatedFloat progress = new AnimatedFloat(this, 0, 260, CubicBezierInterpolator.EASE_OUT_QUINT); - @Override protected void onDraw(Canvas canvas) { reactionButton.draw(canvas, (getWidth() - reactionButton.width) / 2f, (getHeight() - reactionButton.height) / 2f, progress.set(1f), 1f, false); 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 ec2c5e6436..38f0cdb7ad 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/ShareAlert.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/ShareAlert.java @@ -3035,8 +3035,10 @@ public TLRPC.Dialog getItem(int position) { TLRPC.Dialog dialog = new TLRPC.TL_dialog(); if (object instanceof TLRPC.User) { dialog.id = ((TLRPC.User) object).id; - } else { + } else if (object instanceof TLRPC.Chat) { dialog.id = -((TLRPC.Chat) object).id; + } else { + return null; } return dialog; } @@ -3055,8 +3057,10 @@ public TLRPC.Dialog getItem(int position) { TLRPC.Dialog dialog = new TLRPC.TL_dialog(); if (object instanceof TLRPC.User) { dialog.id = ((TLRPC.User) object).id; - } else { + } else if (object instanceof TLRPC.Chat) { dialog.id = -((TLRPC.Chat) object).id; + } else { + return null; } return dialog; } 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 03989a6987..2ce5fe07ae 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/SharedMediaLayout.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/SharedMediaLayout.java @@ -1,6 +1,7 @@ package org.telegram.ui.Components; import static org.telegram.messenger.AndroidUtilities.dp; +import static org.telegram.messenger.AndroidUtilities.lerp; import static org.telegram.messenger.MediaDataController.MEDIA_PHOTOVIDEO; import android.animation.Animator; @@ -58,7 +59,6 @@ import androidx.annotation.NonNull; import androidx.annotation.Nullable; -import androidx.core.content.ContextCompat; import androidx.core.view.accessibility.AccessibilityNodeInfoCompat; import androidx.recyclerview.widget.DefaultItemAnimator; import androidx.recyclerview.widget.GridLayoutManager; @@ -129,6 +129,7 @@ import org.telegram.ui.ChatActivityContainer; import org.telegram.ui.Components.Forum.ForumUtilities; import org.telegram.ui.Components.Premium.LimitReachedBottomSheet; +import org.telegram.ui.Components.Reactions.ReactionsLayoutInBubble; import org.telegram.ui.DialogsActivity; import org.telegram.ui.PhotoViewer; import org.telegram.ui.PremiumPreviewFragment; @@ -501,13 +502,56 @@ public float getPhotoVideoOptionsAlpha(float progress) { return 0; } float alpha = 0; - if (mediaPages[1] != null && (mediaPages[1].selectedType == TAB_PHOTOVIDEO || mediaPages[1].selectedType == TAB_STORIES || mediaPages[1].selectedType == TAB_ARCHIVED_STORIES)) + if (mediaPages[1] != null && (mediaPages[1].selectedType == TAB_PHOTOVIDEO || mediaPages[1].selectedType == TAB_STORIES || mediaPages[1].selectedType == TAB_ARCHIVED_STORIES || mediaPages[1].selectedType == TAB_SAVED_DIALOGS)) alpha += progress; - if (mediaPages[0] != null && (mediaPages[0].selectedType == TAB_PHOTOVIDEO || mediaPages[0].selectedType == TAB_STORIES || mediaPages[0].selectedType == TAB_ARCHIVED_STORIES)) + if (mediaPages[0] != null && (mediaPages[0].selectedType == TAB_PHOTOVIDEO || mediaPages[0].selectedType == TAB_STORIES || mediaPages[0].selectedType == TAB_ARCHIVED_STORIES || mediaPages[0].selectedType == TAB_SAVED_DIALOGS)) alpha += 1f - progress; return alpha; } + public float getSearchAlpha(float progress) { + if (isArchivedOnlyStoriesView()) { + return 0; + } + float alpha = 0; + if (mediaPages[1] != null && isSearchItemVisible(mediaPages[1].selectedType) && mediaPages[1].selectedType != TAB_SAVED_DIALOGS) + alpha += progress; + if (mediaPages[0] != null && isSearchItemVisible(mediaPages[0].selectedType) && mediaPages[0].selectedType != TAB_SAVED_DIALOGS) + alpha += 1f - progress; + return alpha; + } + + public void updateSearchItemIcon(float progress) { + if (searchItemIcon == null) { + return; + } + float alpha = 0; + if (mediaPages[1] != null && mediaPages[1].selectedType == TAB_SAVED_DIALOGS) + alpha += progress; + if (mediaPages[0] != null && mediaPages[0].selectedType == TAB_SAVED_DIALOGS) + alpha += 1f - progress; + searchItemIcon.setAlpha(alpha); + searchItemIcon.setScaleX(.85f + .15f * alpha); + searchItemIcon.setScaleY(.85f + .15f * alpha); + searchItemIcon.setVisibility(alpha <= 0.01f ? View.GONE : View.VISIBLE); + } + + public void updateSearchItemIconAnimated() { + if (searchItemIcon == null) { + return; + } + boolean visible = mediaPages[1] != null && mediaPages[1].selectedType == TAB_SAVED_DIALOGS; + if (visible) { + searchItemIcon.setVisibility(View.VISIBLE); + } + searchItemIcon.animate().alpha(visible ? 1f : 0f).scaleX(visible ? 1 : .85f).scaleY(visible ? 1 : .85f).withEndAction(() -> { + if (!visible) { + searchItemIcon.setVisibility(View.GONE); + } + }).setDuration(420).setInterpolator(CubicBezierInterpolator.EASE_OUT_QUINT).start(); + } + + public void updateFastScrollVisibility(MediaPage mediaPage, boolean animated) { boolean show = mediaPage.fastScrollEnabled && isPinnedToTop; View view = mediaPage.listView.getFastScroll(); @@ -569,9 +613,13 @@ public void updateFastScrollVisibility(MediaPage mediaPage, boolean animated) { private GroupUsersSearchAdapter groupUsersSearchAdapter; private MediaPage[] mediaPages = new MediaPage[2]; private ActionBarMenuItem deleteItem; + public ActionBarMenuItem searchItemIcon; private ActionBarMenuItem searchItem; private ActionBarMenuItem forwardNoQuoteItem; + private float searchAlpha; + private float optionsAlpha; public ImageView photoVideoOptionsItem; + private RLottieImageView optionsSearchImageView; private ActionBarMenuItem forwardItem; private ActionBarMenuItem gotoItem; private ActionBarMenuItem pinItem; @@ -588,6 +636,7 @@ public void updateFastScrollVisibility(MediaPage mediaPage, boolean animated) { private ArrayList audioCellCache = new ArrayList<>(10); private ArrayList audioCache = new ArrayList<>(10); public ScrollSlidingTextTabStripInner scrollSlidingTextTabStrip; + public SearchTagsList searchTagsList; private View shadowLine; private ChatActionCell floatingDateView; private AnimatorSet floatingDateAnimation; @@ -604,6 +653,7 @@ public void updateFastScrollVisibility(MediaPage mediaPage, boolean animated) { private boolean searchWas; private boolean searching; + private ReactionsLayoutInBubble.VisibleReaction searchingReaction; private int[] hasMedia; private int initialTab; @@ -657,6 +707,23 @@ public static class SharedMediaPreloader implements NotificationCenter.Notificat private ArrayList delegates = new ArrayList<>(); private boolean mediaWasLoaded; + public boolean hasSharedMedia() { + int[] hasMedia = getLastMediaCount(); + if (hasMedia == null) return false; + for (int i = 0; i < hasMedia.length; ++i) { + if (hasMedia[i] > 0) + return true; + } + if (hasSavedMessages) { + return true; + } + if (parentFragment != null && dialogId == parentFragment.getUserConfig().getClientUserId() && topicId == 0 && parentFragment.getMessagesController().getSavedMessagesController().hasDialogs()) { + return true; + } + // TODO: stories? + return false; + } + public SharedMediaPreloader(BaseFragment fragment) { parentFragment = fragment; if (fragment instanceof ChatActivityInterface) { @@ -699,6 +766,8 @@ public SharedMediaPreloader(BaseFragment fragment) { } else if (fragment instanceof MediaActivity) { MediaActivity mediaActivity = (MediaActivity) fragment; dialogId = mediaActivity.getDialogId(); + } else if (fragment instanceof DialogsActivity) { + dialogId = fragment.getUserConfig().getClientUserId(); } sharedMediaData = new SharedMediaData[6]; @@ -786,7 +855,7 @@ public void didReceivedNotification(int id, int account, Object... args) { type = MediaDataController.MEDIA_VIDEOS_ONLY; } } - parentFragment.getMediaDataController().loadMedia(did, lastLoadMediaCount[a] == -1 ? 30 : 20, 0, 0, type, topicId,2, parentFragment.getClassGuid(), 0, skipPhotos); + parentFragment.getMediaDataController().loadMedia(did, lastLoadMediaCount[a] == -1 ? 30 : 20, 0, 0, type, topicId,2, parentFragment.getClassGuid(), 0, null, null, skipPhotos); lastLoadMediaCount[a] = mediaCount[a]; } } @@ -1424,6 +1493,7 @@ public SharedMediaLayout(Context context, long did, SharedMediaPreloader preload profileActivity.getNotificationCenter().addObserver(this, NotificationCenter.storiesUpdated); profileActivity.getNotificationCenter().addObserver(this, NotificationCenter.channelRecommendationsLoaded); profileActivity.getNotificationCenter().addObserver(this, NotificationCenter.savedMessagesDialogsUpdate); + profileActivity.getNotificationCenter().addObserver(this, NotificationCenter.dialogsNeedReload); for (int a = 0; a < 10; a++) { //cellCache.add(new SharedPhotoVideoCell(context)); @@ -1450,6 +1520,10 @@ public boolean needPlayMessage(MessageObject messageObject) { maximumVelocity = configuration.getScaledMaximumFlingVelocity(); searching = false; + searchingReaction = null; + if (searchTagsList != null) { + searchTagsList.show(false); + } searchWas = false; pinnedHeaderShadowDrawable = context.getResources().getDrawable(R.drawable.photos_header_shadow); @@ -1480,25 +1554,59 @@ public void onLayoutChange(View view, int i, int i1, int i2, int i3, int i4, int searchItem.setTranslationX(parent.getMeasuredWidth() - searchItem.getRight()); } }); - searchItem = menu.addItem(0, R.drawable.ic_ab_search).setIsSearchField(true).setActionBarMenuItemSearchListener(new ActionBarMenuItem.ActionBarMenuItemSearchListener() { + if (dialog_id == profileActivity.getUserConfig().getClientUserId() && profileActivity instanceof MediaActivity && canShowSearchItem()) { + searchItemIcon = menu.addItem(11, R.drawable.ic_ab_search); + } + searchItem = menu.addItem(0, 0).setIsSearchField(true).setActionBarMenuItemSearchListener(new ActionBarMenuItem.ActionBarMenuItemSearchListener() { @Override public void onSearchExpand() { searching = true; + if (searchTagsList != null) { + searchTagsList.show((getSelectedTab() == TAB_SAVED_DIALOGS || getSelectedTab() == TAB_SAVED_MESSAGES) && searchTagsList.hasFilters()); + } + if (photoVideoOptionsItem != null) { + photoVideoOptionsItem.setVisibility(View.GONE); + } + if (searchItemIcon != null) { + searchItemIcon.setVisibility(View.GONE); + } + searchItem.setVisibility(View.GONE); onSearchStateChanged(true); + if (optionsSearchImageView != null) { + optionsSearchImageView.animate().scaleX(0.6f).scaleY(0.6f).alpha(0).setDuration(320).setInterpolator(CubicBezierInterpolator.EASE_OUT_QUINT).start(); + } } @Override public void onSearchCollapse() { searching = false; + searchingReaction = null; + if (searchItemIcon != null) { + searchItemIcon.setVisibility(View.VISIBLE); + } + if (photoVideoOptionsItem != null && getPhotoVideoOptionsAlpha(0) > .5f) { + photoVideoOptionsItem.setVisibility(View.VISIBLE); + } + if (searchTagsList != null) { + searchTagsList.clear(); + searchTagsList.show(false); + } + if (savedMessagesContainer != null) { + savedMessagesContainer.chatActivity.clearSearch(); + } searchWas = false; + searchItem.setVisibility(View.VISIBLE); documentsSearchAdapter.search(null, true); linksSearchAdapter.search(null, true); audioSearchAdapter.search(null, true); groupUsersSearchAdapter.search(null, true); if (savedMessagesSearchAdapter != null) { - savedMessagesSearchAdapter.search(null); + savedMessagesSearchAdapter.search(null, null); } onSearchStateChanged(false); + if (optionsSearchImageView != null) { + optionsSearchImageView.animate().scaleX(1f).scaleY(1f).alpha(1f).setDuration(320).setInterpolator(CubicBezierInterpolator.EASE_OUT_QUINT).start(); + } if (ignoreSearchCollapse) { ignoreSearchCollapse = false; return; @@ -1509,11 +1617,14 @@ public void onSearchCollapse() { @Override public void onTextChanged(EditText editText) { String text = editText.getText().toString(); - if (text.length() != 0) { - searchWas = true; - } else { - searchWas = false; + if (savedMessagesContainer != null) { + savedMessagesContainer.chatActivity.setSearchQuery(text); + if (TextUtils.isEmpty(text) && searchingReaction == null) { + savedMessagesContainer.chatActivity.clearSearch(); + } } + searchItem.setVisibility(View.GONE); + searchWas = text.length() != 0 || searchingReaction != null; switchToCurrentSelectedMode(false); if (mediaPages[0].selectedType == TAB_FILES) { if (documentsSearchAdapter == null) { @@ -1539,7 +1650,15 @@ public void onTextChanged(EditText editText) { if (savedMessagesSearchAdapter == null) { return; } - savedMessagesSearchAdapter.search(text); + savedMessagesSearchAdapter.search(text, searchingReaction); + } + } + + @Override + public void onSearchPressed(EditText editText) { + super.onSearchPressed(editText); + if (savedMessagesContainer != null) { + savedMessagesContainer.chatActivity.hitSearch(); } } @@ -1550,7 +1669,7 @@ public void onLayout(int l, int t, int r, int b) { } }); searchItem.setTranslationY(dp(10)); - searchItem.setSearchFieldHint(LocaleController.getString("Search", R.string.Search)); + searchItem.setSearchFieldHint(LocaleController.getString(searchTagsList != null && searchTagsList.hasFilters() && getSelectedTab() == TAB_SAVED_DIALOGS ? R.string.SavedTagSearchHint : R.string.Search)); searchItem.setContentDescription(LocaleController.getString("Search", R.string.Search)); searchItem.setVisibility(isStoriesView() ? View.GONE : View.INVISIBLE); @@ -1559,16 +1678,58 @@ public void onLayout(int l, int t, int r, int b) { photoVideoOptionsItem.setTranslationY(dp(10)); photoVideoOptionsItem.setVisibility(View.INVISIBLE); - Drawable calendarDrawable = ContextCompat.getDrawable(context, R.drawable.ic_ab_other).mutate(); - calendarDrawable.setColorFilter(new PorterDuffColorFilter(getThemedColor(Theme.key_actionBarActionModeDefaultIcon), PorterDuff.Mode.MULTIPLY)); - photoVideoOptionsItem.setImageDrawable(calendarDrawable); - photoVideoOptionsItem.setScaleType(ImageView.ScaleType.CENTER_INSIDE); +// Drawable calendarDrawable = ContextCompat.getDrawable(context, R.drawable.ic_ab_other).mutate(); +// calendarDrawable.setColorFilter(new PorterDuffColorFilter(getThemedColor(Theme.key_actionBarActionModeDefaultIcon), PorterDuff.Mode.MULTIPLY)); +// photoVideoOptionsItem.setImageDrawable(calendarDrawable); +// photoVideoOptionsItem.setScaleType(ImageView.ScaleType.CENTER_INSIDE); if (!isArchivedOnlyStoriesView()) { actionBar.addView(photoVideoOptionsItem, LayoutHelper.createFrame(48, 56, Gravity.RIGHT | Gravity.BOTTOM)); + + optionsSearchImageView = new RLottieImageView(context); + optionsSearchImageView.setScaleType(ImageView.ScaleType.CENTER_INSIDE); + optionsSearchImageView.setAnimation(R.raw.options_to_search, 24, 24); + optionsSearchImageView.getAnimatedDrawable().multiplySpeed(2f); + optionsSearchImageView.getAnimatedDrawable().setPlayInDirectionOfCustomEndFrame(true); + optionsSearchImageView.setColorFilter(new PorterDuffColorFilter(getThemedColor(Theme.key_actionBarActionModeDefaultIcon), PorterDuff.Mode.MULTIPLY)); + optionsSearchImageView.setVisibility(GONE); + actionBar.addView(optionsSearchImageView, LayoutHelper.createFrame(48, 56, Gravity.RIGHT | Gravity.BOTTOM)); } photoVideoOptionsItem.setOnClickListener(new OnClickListener() { @Override public void onClick(View view) { + if (getSelectedTab() == TAB_SAVED_DIALOGS) { + ItemOptions.makeOptions(profileActivity, photoVideoOptionsItem) + .add(R.drawable.msg_discussion, LocaleController.getString(R.string.SavedViewAsMessages), () -> { + profileActivity.getMessagesController().setSavedViewAs(false); + Bundle args = new Bundle(); + args.putLong("user_id", profileActivity.getUserConfig().getClientUserId()); + profileActivity.presentFragment(new ChatActivity(args), true); + }) + .addGap() + .add(R.drawable.msg_home, LocaleController.getString(R.string.AddShortcut), () -> { + try { + profileActivity.getMediaDataController().installShortcut(profileActivity.getUserConfig().getClientUserId()); + } catch (Exception e) { + FileLog.e(e); + } + }) + .add(R.drawable.msg_delete, LocaleController.getString(R.string.DeleteAll), () -> { + TLRPC.User currentUser = profileActivity.getUserConfig().getCurrentUser(); + AlertsCreator.createClearOrDeleteDialogAlert(profileActivity, false, null, currentUser, false, true, true, (param) -> { + profileActivity.finishFragment(); + if (profileActivity instanceof NotificationCenter.NotificationCenterDelegate) { + profileActivity.getNotificationCenter().removeObserver((NotificationCenter.NotificationCenterDelegate) profileActivity, NotificationCenter.closeChats); + } + profileActivity.getNotificationCenter().postNotificationName(NotificationCenter.closeChats); + profileActivity.getNotificationCenter().postNotificationName(NotificationCenter.needDeleteDialog, dialog_id, currentUser, null, param); + profileActivity.getMessagesController().setSavedViewAs(false); + }, resourcesProvider); + }) + .translate(0, -dp(52)) + .setDimAlpha(0) + .show(); + return; + } View dividerView = new DividerCell(context); ActionBarPopupWindow.ActionBarPopupWindowLayout popupLayout = new ActionBarPopupWindow.ActionBarPopupWindowLayout(context, resourcesProvider) { @Override @@ -1852,11 +2013,18 @@ public void notifyDataSetChanged() { channelRecommendationsAdapter = new ChannelRecommendationsAdapter(context); savedDialogsAdapter = new SavedDialogsAdapter(context); savedMessagesSearchAdapter = new SavedMessagesSearchAdapter(context); - if (!isStoriesView() && !includeSavedDialogs()) { + if (!isStoriesView() && !includeSavedDialogs() && topicId == 0) { Bundle args = new Bundle(); args.putLong("user_id", profileActivity.getUserConfig().getClientUserId()); args.putInt("chatMode", ChatActivity.MODE_SAVED); - savedMessagesContainer = new ChatActivityContainer(context, profileActivity.getParentLayout(), args); + savedMessagesContainer = new ChatActivityContainer(context, () -> profileActivity.getLayoutContainer(), profileActivity.getParentLayout(), args) { + @Override + protected void onSearchLoadingUpdate(boolean loading) { + if (searchItem != null) { + searchItem.setShowSearchProgress(loading); + } + } + }; savedMessagesContainer.chatActivity.setSavedDialog(dialog_id); savedMessagesContainer.chatActivity.reversed = true; } @@ -1927,18 +2095,18 @@ public void setTranslationX(float translationX) { scrollSlidingTextTabStrip.selectTabWithId(mediaPages[1].selectedType, scrollProgress); if (canShowSearchItem()) { if (searchItemState == 2) { - searchItem.setAlpha(1.0f - scrollProgress); + searchAlpha = 1.0f - scrollProgress; } else if (searchItemState == 1) { - searchItem.setAlpha(scrollProgress); + searchAlpha = scrollProgress; } + updateSearchItemIcon(scrollProgress); - float photoVideoOptionsAlpha = getPhotoVideoOptionsAlpha(scrollProgress); - photoVideoOptionsItem.setAlpha(photoVideoOptionsAlpha); - photoVideoOptionsItem.setVisibility((photoVideoOptionsAlpha == 0 || !canShowSearchItem() || isArchivedOnlyStoriesView()) ? INVISIBLE : View.VISIBLE); + optionsAlpha = getPhotoVideoOptionsAlpha(scrollProgress); + photoVideoOptionsItem.setVisibility((optionsAlpha == 0 || !canShowSearchItem() || isArchivedOnlyStoriesView()) ? INVISIBLE : View.VISIBLE); } else { - searchItem.setAlpha(0.0f); + searchAlpha = 0; } - + updateOptionsSearch(); } } invalidateBlur(); @@ -2098,7 +2266,7 @@ protected void dispatchDraw(Canvas canvas) { if (photoVideoChangeColumnsAnimation && changeColumnsTab == TAB_ARCHIVED_STORIES && mediaPage.animationSupportingListView.getChildCount() > 0) { View supportingTopChild = mediaPage.animationSupportingListView.getChildAt(0); if (supportingTopChild != null && mediaPage.animationSupportingListView.getChildAdapterPosition(supportingTopChild) == 0) { - top = AndroidUtilities.lerp(top, supportingTopChild.getTop(), photoVideoChangeColumnsProgress); + top = lerp(top, supportingTopChild.getTop(), photoVideoChangeColumnsProgress); } } if (archivedHintPaint == null) { @@ -2451,12 +2619,20 @@ public Integer getSelectorColor(int position) { } return super.getSelectorColor(position); } + + @Override + public void onScrolled(int dx, int dy) { + super.onScrolled(dx, dy); + if (scrollingByUser && getSelectedTab() == TAB_SAVED_DIALOGS && profileActivity != null) { + AndroidUtilities.hideKeyboard(profileActivity.getParentActivity().getCurrentFocus()); + } + } }; mediaPages[a].listView.setFastScrollEnabled(RecyclerListView.FastScroll.DATE_TYPE); mediaPages[a].listView.setScrollingTouchSlop(RecyclerView.TOUCH_SLOP_PAGING); mediaPages[a].listView.setPinnedSectionOffsetY(-dp(2)); - mediaPages[a].listView.setPadding(0, dp(2), 0, 0); + mediaPages[a].listView.setPadding(0, 0, 0, 0); mediaPages[a].listView.setItemAnimator(null); mediaPages[a].listView.setClipToPadding(false); mediaPages[a].listView.setSectionsType(RecyclerListView.SECTIONS_TYPE_DATE); @@ -2629,13 +2805,29 @@ public void getItemOffsets(android.graphics.Rect outRect, View view, RecyclerVie position -= savedMessagesSearchAdapter.dialogs.size(); if (position < savedMessagesSearchAdapter.messages.size()) { MessageObject msg = savedMessagesSearchAdapter.messages.get(position); + final int pos = position; Bundle args = new Bundle(); args.putLong("user_id", profileActivity.getUserConfig().getClientUserId()); args.putInt("message_id", msg.getId()); - args.putInt("chatMode", ChatActivity.MODE_SAVED); - ChatActivity chatActivity = new ChatActivity(args); - chatActivity.setSavedDialog(msg.getSavedDialogId()); + ChatActivity chatActivity = new ChatActivity(args) { + boolean firstCreateView = true; + @Override + public void onTransitionAnimationStart(boolean isOpen, boolean backward) { + if (firstCreateView) { + if (searchItem != null) { + openSearchWithText(""); + searchItem.setSearchFieldText(savedMessagesSearchAdapter.lastQuery, false); + } + if (actionBarSearchTags != null) { + actionBarSearchTags.setChosen(savedMessagesSearchAdapter.lastReaction, false); + } + profileActivity.getMediaDataController().portSavedSearchResults(getClassGuid(), savedMessagesSearchAdapter.lastReaction, savedMessagesSearchAdapter.lastQuery, savedMessagesSearchAdapter.cachedMessages, savedMessagesSearchAdapter.loadedMessages, pos, savedMessagesSearchAdapter.count, savedMessagesSearchAdapter.endReached); + firstCreateView = false; + } + super.onTransitionAnimationStart(isOpen, backward); + } + }; chatActivity.setHighlightMessageId(msg.getId()); profileActivity.presentFragment(chatActivity); } @@ -2688,6 +2880,9 @@ public boolean onItemClick(View view, int position, float x, float y) { if (photoVideoChangeColumnsAnimation) { return false; } + if (mediaPage.listView.getAdapter() == savedMessagesSearchAdapter) { + return false; + } if (isActionModeShowed && mediaPage.selectedType != TAB_SAVED_DIALOGS) { mediaPage.listView.clickItem(view, position); return true; @@ -2842,6 +3037,50 @@ protected void onDraw(Canvas canvas) { }); addView(scrollSlidingTextTabStrip, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 48, Gravity.LEFT | Gravity.TOP)); + searchTagsList = new SearchTagsList(getContext(), profileActivity, null, profileActivity.getCurrentAccount(), includeSavedDialogs() ? 0 : dialog_id, resourcesProvider, false) { + @Override + protected boolean setFilter(ReactionsLayoutInBubble.VisibleReaction reaction) { + searchingReaction = reaction; + final String text = searchItem.getSearchField().getText().toString(); + searchWas = text.length() != 0 || searchingReaction != null; + switchToCurrentSelectedMode(false); + if (mediaPages[0].selectedType == TAB_SAVED_DIALOGS) { + if (savedMessagesSearchAdapter != null) { + savedMessagesSearchAdapter.search(text, searchingReaction); + } + AndroidUtilities.hideKeyboard(searchItem.getSearchField()); + } else if (mediaPages[0].selectedType == TAB_SAVED_MESSAGES) { + if (savedMessagesContainer != null) { + savedMessagesContainer.chatActivity.setTagFilter(reaction); + } + } + return true; + } + + @Override + protected void onShownUpdate(boolean finish) { + scrollSlidingTextTabStrip.setAlpha(1f - shownT); + scrollSlidingTextTabStrip.setPivotX(scrollSlidingTextTabStrip.getWidth() / 2f); + scrollSlidingTextTabStrip.setScaleX(.8f + .2f * (1f - shownT)); + scrollSlidingTextTabStrip.setPivotY(dp(48)); + scrollSlidingTextTabStrip.setScaleY(.8f + .2f * (1f - shownT)); + } + + @Override + public void updateTags(boolean notify) { + super.updateTags(notify); + show(searching && (getSelectedTab() == TAB_SAVED_DIALOGS || getSelectedTab() == TAB_SAVED_MESSAGES) && searchTagsList.hasFilters()); + if (searchItemIcon != null) { + searchItemIcon.setIcon(hasFilters() && profileActivity.getUserConfig().isPremium() ? R.drawable.navbar_search_tag : R.drawable.ic_ab_search, notify); + } + if (searchItem != null) { + searchItem.setSearchFieldHint(LocaleController.getString(searchTagsList != null && searchTagsList.hasFilters() && getSelectedTab() == TAB_SAVED_DIALOGS ? R.string.SavedTagSearchHint : R.string.Search)); + } + } + }; + searchTagsList.setShown(0f); + searchTagsList.attach(); + addView(searchTagsList, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 40, Gravity.LEFT | Gravity.TOP, 0, 4, 0, 0)); addView(actionModeLayout, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 48, Gravity.LEFT | Gravity.TOP)); } @@ -3118,7 +3357,7 @@ private void startPinchToMediaColumnsCount(boolean pinchScaleUp) { } mediaPage.animationSupportingListView.setPadding( mediaPage.animationSupportingListView.getPaddingLeft(), - changeColumnsTab == TAB_ARCHIVED_STORIES ? dp(2 + 64) : dp(2), + changeColumnsTab == TAB_ARCHIVED_STORIES ? dp(64) : 0, mediaPage.animationSupportingListView.getPaddingRight(), mediaPage.animationSupportingListView.getPaddingBottom() ); @@ -3319,7 +3558,7 @@ private void animateToMediaColumnsCount(int newColumnsCount) { } mediaPage.animationSupportingListView.setPadding( mediaPage.animationSupportingListView.getPaddingLeft(), - dp(2) + (mediaPage.animationSupportingListView.hintPaddingTop = (changeColumnsTab == TAB_ARCHIVED_STORIES ? dp(64) : 0)), + (mediaPage.animationSupportingListView.hintPaddingTop = (changeColumnsTab == TAB_ARCHIVED_STORIES ? dp(64) : 0)), mediaPage.animationSupportingListView.getPaddingRight(), mediaPage.animationSupportingListView.getPaddingBottom() ); @@ -3432,6 +3671,8 @@ public void onPageSelected(int id, boolean forward) { switchToCurrentSelectedMode(true); animatingForward = forward; onSelectedTabChanged(); + animateSearchToOptions(!isSearchItemVisible(id), true); + updateOptionsSearch(true); } @Override @@ -3453,19 +3694,16 @@ public void onPageScrolled(float progress) { } onTabProgress(getTabProgress()); - float photoVideoOptionsAlpha = getPhotoVideoOptionsAlpha(progress); - photoVideoOptionsItem.setAlpha(photoVideoOptionsAlpha); - photoVideoOptionsItem.setVisibility((photoVideoOptionsAlpha == 0 || !canShowSearchItem() || isArchivedOnlyStoriesView()) ? INVISIBLE : View.VISIBLE); - if (canShowSearchItem()) { - if (searchItemState == 1) { - searchItem.setAlpha(progress); - } else if (searchItemState == 2) { - searchItem.setAlpha(1.0f - progress); - } - } else { + optionsAlpha = getPhotoVideoOptionsAlpha(progress); + photoVideoOptionsItem.setVisibility((optionsAlpha == 0 || !canShowSearchItem() || isArchivedOnlyStoriesView()) ? INVISIBLE : View.VISIBLE); + if (!canShowSearchItem()) { searchItem.setVisibility(isStoriesView() ? View.GONE : View.INVISIBLE); - searchItem.setAlpha(0.0f); + searchAlpha = 0.0f; + } else { + searchAlpha = getSearchAlpha(progress); + updateSearchItemIconAnimated(); } + updateOptionsSearch(); if (progress == 1) { MediaPage tempPage = mediaPages[0]; mediaPages[0] = mediaPages[1]; @@ -3648,13 +3886,13 @@ private void checkLoadMoreScroll(MediaPage mediaPage, RecyclerListView recyclerV lastVisiblePosition = Math.max(position, lastVisiblePosition); } if (mediaPage.listView.getAdapter() == savedMessagesSearchAdapter) { - if (lastVisiblePosition + 1 >= savedMessagesSearchAdapter.dialogs.size() + savedMessagesSearchAdapter.messages.size()) { + if (lastVisiblePosition + 1 >= savedMessagesSearchAdapter.dialogs.size() + savedMessagesSearchAdapter.loadedMessages.size()) { savedMessagesSearchAdapter.loadMore(); } return; } if (lastVisiblePosition + 1 >= profileActivity.getMessagesController().getSavedMessagesController().getLoadedCount()) { - profileActivity.getMessagesController().getSavedMessagesController().loadDialogs(); + profileActivity.getMessagesController().getSavedMessagesController().loadDialogs(false); } } else if (mediaPage.selectedType != TAB_RECOMMENDED_CHANNELS && mediaPage.selectedType != TAB_SAVED_MESSAGES) { final int threshold; @@ -3688,10 +3926,10 @@ private void checkLoadMoreScroll(MediaPage mediaPage, RecyclerListView recyclerV } if (!sharedMediaData[mediaPage.selectedType].endReached[0]) { sharedMediaData[mediaPage.selectedType].loading = true; - profileActivity.getMediaDataController().loadMedia(dialog_id, 50, sharedMediaData[mediaPage.selectedType].max_id[0], 0, type, topicId, 1, profileActivity.getClassGuid(), sharedMediaData[mediaPage.selectedType].requestIndex, skipPhotos); + profileActivity.getMediaDataController().loadMedia(dialog_id, 50, sharedMediaData[mediaPage.selectedType].max_id[0], 0, type, topicId, 1, profileActivity.getClassGuid(), sharedMediaData[mediaPage.selectedType].requestIndex, null, null, skipPhotos); } else if (mergeDialogId != 0 && !sharedMediaData[mediaPage.selectedType].endReached[1]) { sharedMediaData[mediaPage.selectedType].loading = true; - profileActivity.getMediaDataController().loadMedia(mergeDialogId, 50, sharedMediaData[mediaPage.selectedType].max_id[1], 0, type, topicId, 1, profileActivity.getClassGuid(), sharedMediaData[mediaPage.selectedType].requestIndex, skipPhotos); + profileActivity.getMediaDataController().loadMedia(mergeDialogId, 50, sharedMediaData[mediaPage.selectedType].max_id[1], 0, type, topicId, 1, profileActivity.getClassGuid(), sharedMediaData[mediaPage.selectedType].requestIndex, null, null, skipPhotos); } } @@ -3741,26 +3979,34 @@ private void loadFromStart(int selectedType) { type = MediaDataController.MEDIA_URL; } sharedMediaData[selectedType].loading = true; - profileActivity.getMediaDataController().loadMedia(dialog_id, 50, 0, sharedMediaData[selectedType].min_id, type, topicId, 1, profileActivity.getClassGuid(), sharedMediaData[selectedType].requestIndex); + profileActivity.getMediaDataController().loadMedia(dialog_id, 50, 0, sharedMediaData[selectedType].min_id, type, topicId, 1, profileActivity.getClassGuid(), sharedMediaData[selectedType].requestIndex, null, null); } public ActionBarMenuItem getSearchItem() { return searchItem; } + public RLottieImageView getSearchOptionsItem() { + return optionsSearchImageView; + } + public boolean isSearchItemVisible() { - if (mediaPages[0].selectedType == TAB_GROUPUSERS) { + return isSearchItemVisible(mediaPages[0].selectedType); + } + + public boolean isSearchItemVisible(int type) { + if (type == TAB_GROUPUSERS) { return delegate.canSearchMembers(); } return ( - mediaPages[0].selectedType != TAB_PHOTOVIDEO && - mediaPages[0].selectedType != TAB_STORIES && - mediaPages[0].selectedType != TAB_ARCHIVED_STORIES && - mediaPages[0].selectedType != TAB_VOICE && - mediaPages[0].selectedType != TAB_GIF && - mediaPages[0].selectedType != TAB_COMMON_GROUPS && - mediaPages[0].selectedType != TAB_SAVED_MESSAGES && - mediaPages[0].selectedType != TAB_RECOMMENDED_CHANNELS + type != TAB_PHOTOVIDEO && + type != TAB_STORIES && + type != TAB_ARCHIVED_STORIES && + type != TAB_VOICE && + type != TAB_GIF && + type != TAB_COMMON_GROUPS && + type != TAB_SAVED_DIALOGS && + type != TAB_RECOMMENDED_CHANNELS ); } @@ -3769,7 +4015,7 @@ public boolean isTabZoomable(int type) { } public boolean isCalendarItemVisible() { - return mediaPages[0].selectedType == TAB_PHOTOVIDEO || mediaPages[0].selectedType == TAB_STORIES || mediaPages[0].selectedType == TAB_ARCHIVED_STORIES; + return mediaPages[0].selectedType == TAB_PHOTOVIDEO || mediaPages[0].selectedType == TAB_STORIES || mediaPages[0].selectedType == TAB_ARCHIVED_STORIES || mediaPages[0].selectedType == TAB_SAVED_DIALOGS; } public int getSelectedTab() { @@ -3795,6 +4041,9 @@ protected void onSelectedTabChanged() { if (storiesAdapter.poller != null) { storiesAdapter.poller.start(pollerEnabled && getClosestTab() == TAB_STORIES); } + if (searchItem != null) { + searchItem.setSearchFieldHint(LocaleController.getString(searchTagsList != null && searchTagsList.hasFilters() && getSelectedTab() == TAB_SAVED_DIALOGS ? R.string.SavedTagSearchHint : R.string.Search)); + } } protected boolean canShowSearchItem() { @@ -3821,6 +4070,10 @@ public void onDestroy() { profileActivity.getNotificationCenter().removeObserver(this, NotificationCenter.storiesUpdated); profileActivity.getNotificationCenter().removeObserver(this, NotificationCenter.channelRecommendationsLoaded); profileActivity.getNotificationCenter().removeObserver(this, NotificationCenter.savedMessagesDialogsUpdate); + profileActivity.getNotificationCenter().removeObserver(this, NotificationCenter.dialogsNeedReload); + if (searchTagsList != null) { + searchTagsList.detach(); + } if (storiesAdapter != null && storiesAdapter.storiesList != null) { storiesAdapter.destroy(); @@ -3886,7 +4139,13 @@ private void loadFastScrollData(boolean force) { req.filter = new TLRPC.TL_inputMessagesFilterMusic(); } req.limit = 100; - req.peer = MessagesController.getInstance(profileActivity.getCurrentAccount()).getInputPeer(dialog_id); + req.peer = profileActivity.getMessagesController().getInputPeer(dialog_id); + if (topicId != 0) { + if (profileActivity.getUserConfig().getClientUserId() == dialog_id) { + req.flags |= 4; + req.saved_peer_id = profileActivity.getMessagesController().getInputPeer(topicId); + } + } int reqIndex = sharedMediaData[type].requestIndex; int reqId = ConnectionsManager.getInstance(profileActivity.getCurrentAccount()).sendRequest(req, (response, error) -> AndroidUtilities.runOnUIThread(() -> @@ -3982,9 +4241,11 @@ public void onActionBarItemClick(View v, int id) { selectedDialogs.add(did); } } + boolean firstDialogSelf = false; String firstDialog = ""; if (!selectedDialogs.isEmpty()) { long did = selectedDialogs.get(0); + firstDialogSelf = did == profileActivity.getUserConfig().getClientUserId(); if (did < 0) { TLRPC.Chat chat = profileActivity.getMessagesController().getChat(-did); if (chat != null) { @@ -4002,8 +4263,8 @@ public void onActionBarItemClick(View v, int id) { } } AlertDialog dialog = new AlertDialog.Builder(getContext(), resourcesProvider) - .setTitle(selectedDialogs.size() == 1 ? LocaleController.formatString(R.string.ClearHistoryTitleSingle, firstDialog) : LocaleController.formatPluralString("ClearHistoryTitleMultiple", selectedDialogs.size())) - .setMessage(selectedDialogs.size() == 1 ? LocaleController.formatString(R.string.ClearHistoryMessageSingle, firstDialog) : LocaleController.formatPluralString("ClearHistoryMessageMultiple", selectedDialogs.size())) + .setTitle(selectedDialogs.size() == 1 ? LocaleController.formatString(firstDialogSelf ? R.string.ClearHistoryMyNotesTitle : R.string.ClearHistoryTitleSingle2, firstDialog) : LocaleController.formatPluralString("ClearHistoryTitleMultiple", selectedDialogs.size())) + .setMessage(selectedDialogs.size() == 1 ? LocaleController.formatString(firstDialogSelf ? R.string.ClearHistoryMyNotesMessage : R.string.ClearHistoryMessageSingle, firstDialog) : LocaleController.formatPluralString("ClearHistoryMessageMultiple", selectedDialogs.size())) .setPositiveButton(LocaleController.getString(R.string.Remove), (di, w) -> { for (int i = 0; i < selectedDialogs.size(); ++i) { final long did = selectedDialogs.get(i); @@ -4174,7 +4435,7 @@ public void onActionBarItemClick(View v, int id) { selectedDialogs.add(did); } } - if (!controller.updatePinned(selectedDialogs, id == pin)) { + if (!controller.updatePinned(selectedDialogs, id == pin, true)) { LimitReachedBottomSheet limitReachedBottomSheet = new LimitReachedBottomSheet(profileActivity, getContext(), LimitReachedBottomSheet.TYPE_PIN_SAVED_DIALOGS, profileActivity.getCurrentAccount(), null); profileActivity.showDialog(limitReachedBottomSheet); } else { @@ -4194,20 +4455,14 @@ private boolean prepareForMoving(MotionEvent ev, boolean forward) { if (id < 0) { return false; } - if (canShowSearchItem()) { - if (searchItemState != 0) { - if (searchItemState == 2) { - searchItem.setAlpha(1.0f); - } else if (searchItemState == 1) { - searchItem.setAlpha(0.0f); - searchItem.setVisibility(isStoriesView() ? View.GONE : View.INVISIBLE); - } - searchItemState = 0; - } - } else { + if (!canShowSearchItem()) { searchItem.setVisibility(isStoriesView() ? View.GONE : View.INVISIBLE); - searchItem.setAlpha(0.0f); + searchAlpha = 0; + } else { + searchAlpha = getSearchAlpha(0); + updateSearchItemIcon(0); } + updateOptionsSearch(); getParent().requestDisallowInterceptTouchEvent(true); hideFloatingDateView(true); @@ -4370,19 +4625,15 @@ public boolean onTouchEvent(MotionEvent ev) { mediaPages[1].setTranslationX(dx - mediaPages[0].getMeasuredWidth()); } float scrollProgress = Math.abs(dx) / (float) mediaPages[0].getMeasuredWidth(); - if (canShowSearchItem()) { - if (searchItemState == 2) { - searchItem.setAlpha(1.0f - scrollProgress); - } else if (searchItemState == 1) { - searchItem.setAlpha(scrollProgress); - } - - float photoVideoOptionsAlpha = getPhotoVideoOptionsAlpha(scrollProgress); - photoVideoOptionsItem.setAlpha(photoVideoOptionsAlpha); - photoVideoOptionsItem.setVisibility((photoVideoOptionsAlpha == 0 || !canShowSearchItem() || isArchivedOnlyStoriesView()) ? INVISIBLE : View.VISIBLE); + if (!canShowSearchItem()) { + searchAlpha = 0; } else { - searchItem.setAlpha(0.0f); + searchAlpha = getSearchAlpha(scrollProgress); + updateSearchItemIcon(scrollProgress); + optionsAlpha = getPhotoVideoOptionsAlpha(scrollProgress); + photoVideoOptionsItem.setVisibility((optionsAlpha == 0 || !canShowSearchItem() || isArchivedOnlyStoriesView()) ? INVISIBLE : View.VISIBLE); } + updateOptionsSearch(); scrollSlidingTextTabStrip.selectTabWithId(mediaPages[1].selectedType, scrollProgress); onTabProgress(getTabProgress()); onSelectedTabChanged(); @@ -4482,17 +4733,14 @@ public void onAnimationEnd(Animator animator) { tabsAnimation = null; if (backAnimation) { mediaPages[1].setVisibility(View.GONE); - if (canShowSearchItem()) { - if (searchItemState == 2) { - searchItem.setAlpha(1.0f); - } else if (searchItemState == 1) { - searchItem.setAlpha(0.0f); - searchItem.setVisibility(isStoriesView() ? View.GONE : View.INVISIBLE); - } - } else { + if (!canShowSearchItem()) { searchItem.setVisibility(isStoriesView() ? View.GONE : INVISIBLE); - searchItem.setAlpha(0.0f); + searchAlpha = 0; + } else { + searchAlpha = getSearchAlpha(0); + updateSearchItemIcon(0); } + updateOptionsSearch(); searchItemState = 0; } else { MediaPage tempPage = mediaPages[0]; @@ -4699,7 +4947,7 @@ public void didReceivedNotification(int id, int account, Object... args) { } if (!fromStart && loadIndex == 0 && sharedMediaData[type].endReached[loadIndex] && mergeDialogId != 0) { sharedMediaData[type].loading = true; - profileActivity.getMediaDataController().loadMedia(mergeDialogId, 50, sharedMediaData[type].max_id[1], 0, type, topicId, 1, profileActivity.getClassGuid(), sharedMediaData[type].requestIndex, skipPhotos); + profileActivity.getMediaDataController().loadMedia(mergeDialogId, 50, sharedMediaData[type].max_id[1], 0, type, topicId, 1, profileActivity.getClassGuid(), sharedMediaData[type].requestIndex, null, null, skipPhotos); } if (adapter != null) { RecyclerListView listView = null; @@ -4986,6 +5234,8 @@ public void didReceivedNotification(int id, int account, Object... args) { checkCurrentTabValid(); onSelectedTabChanged(); } + } else if (id == NotificationCenter.dialogsNeedReload) { + savedDialogsAdapter.update(true); } } @@ -5331,7 +5581,7 @@ private void updateTabs(boolean animated) { if (hasRecommendations != scrollSlidingTextTabStrip.hasTab(TAB_RECOMMENDED_CHANNELS)) { changed++; } - hasSavedDialogs = includeSavedDialogs() && !profileActivity.getMessagesController().getSavedMessagesController().unsupported && profileActivity.getMessagesController().getSavedMessagesController().getAllCount() > 0; + hasSavedDialogs = includeSavedDialogs() && !profileActivity.getMessagesController().getSavedMessagesController().unsupported && profileActivity.getMessagesController().getSavedMessagesController().hasDialogs(); if (hasSavedDialogs != scrollSlidingTextTabStrip.hasTab(TAB_SAVED_DIALOGS)) { changed++; } @@ -5453,6 +5703,12 @@ public Animator onDisappear(ViewGroup sceneRoot, View view, TransitionValues sta } } } + if (hasSavedMessages) { + if (!scrollSlidingTextTabStrip.hasTab(TAB_SAVED_MESSAGES)) { + scrollSlidingTextTabStrip.addTextTab(TAB_SAVED_MESSAGES, LocaleController.getString(R.string.SavedMessagesTab2), idToView); + } + MessagesController.getGlobalMainSettings().edit().putInt("savedhint", 3).apply(); + } if (hasMedia[1] > 0) { if (!scrollSlidingTextTabStrip.hasTab(TAB_FILES)) { scrollSlidingTextTabStrip.addTextTab(TAB_FILES, LocaleController.getString("SharedFilesTab2", R.string.SharedFilesTab2), idToView); @@ -5496,12 +5752,6 @@ public Animator onDisappear(ViewGroup sceneRoot, View view, TransitionValues sta scrollSlidingTextTabStrip.addTextTab(TAB_RECOMMENDED_CHANNELS, LocaleController.getString(R.string.SimilarChannelsTab), idToView); } } - if (hasSavedMessages) { - if (!scrollSlidingTextTabStrip.hasTab(TAB_SAVED_MESSAGES)) { - scrollSlidingTextTabStrip.addTextTab(TAB_SAVED_MESSAGES, LocaleController.getString(R.string.SavedMessagesTab), idToView); - } - MessagesController.getGlobalMainSettings().edit().putInt("savedhint", 3).apply(); - } } } int id = scrollSlidingTextTabStrip.getCurrentTabId(); @@ -5551,6 +5801,9 @@ private void switchToCurrentSelectedMode(boolean animated) { if (animated) { if (mediaPages[a].selectedType == TAB_PHOTOVIDEO || mediaPages[a].selectedType == TAB_VOICE || mediaPages[a].selectedType == TAB_GIF || mediaPages[a].selectedType == TAB_COMMON_GROUPS || mediaPages[a].selectedType == TAB_GROUPUSERS && !delegate.canSearchMembers()) { searching = false; + if (searchTagsList != null) { + searchTagsList.show(false); + } searchWas = false; switchToCurrentSelectedMode(true); return; @@ -5590,7 +5843,7 @@ private void switchToCurrentSelectedMode(boolean animated) { } } else if (mediaPages[a].selectedType == TAB_SAVED_DIALOGS) { if (savedMessagesSearchAdapter != null) { - savedMessagesSearchAdapter.search(text); + savedMessagesSearchAdapter.search(text, searchingReaction); if (currentAdapter != savedMessagesSearchAdapter) { recycleAdapter(currentAdapter); mediaPages[a].listView.setAdapter(savedMessagesSearchAdapter); @@ -5641,7 +5894,7 @@ private void switchToCurrentSelectedMode(boolean animated) { mediaPages[a].listView.setPinnedHeaderShadowDrawable(null); mediaPages[a].listView.setPadding( mediaPages[a].listView.getPaddingLeft(), - dp(2) + (mediaPages[a].listView.hintPaddingTop = mediaPages[a].selectedType == TAB_ARCHIVED_STORIES ? dp(64) : 0), + (mediaPages[a].listView.hintPaddingTop = mediaPages[a].selectedType == TAB_ARCHIVED_STORIES ? dp(64) : 0), mediaPages[a].listView.getPaddingRight(), mediaPages[a].listView.getPaddingBottom() ); @@ -5750,14 +6003,15 @@ private void switchToCurrentSelectedMode(boolean animated) { } } if (savedMessagesContainer != null && mediaPages[a].selectedType != TAB_SAVED_MESSAGES && savedMessagesContainer.getParent() == mediaPages[a]) { + savedMessagesContainer.chatActivity.onRemoveFromParent(); mediaPages[a].removeView(savedMessagesContainer); } - if (mediaPages[a].selectedType == TAB_PHOTOVIDEO || mediaPages[a].selectedType == TAB_STORIES || mediaPages[a].selectedType == TAB_ARCHIVED_STORIES || mediaPages[a].selectedType == TAB_VOICE || mediaPages[a].selectedType == TAB_GIF || mediaPages[a].selectedType == TAB_COMMON_GROUPS || mediaPages[a].selectedType == TAB_GROUPUSERS && !delegate.canSearchMembers() || mediaPages[a].selectedType == TAB_RECOMMENDED_CHANNELS || mediaPages[a].selectedType == TAB_SAVED_MESSAGES) { + if (mediaPages[a].selectedType == TAB_PHOTOVIDEO || mediaPages[a].selectedType == TAB_SAVED_DIALOGS || mediaPages[a].selectedType == TAB_STORIES || mediaPages[a].selectedType == TAB_ARCHIVED_STORIES || mediaPages[a].selectedType == TAB_VOICE || mediaPages[a].selectedType == TAB_GIF || mediaPages[a].selectedType == TAB_COMMON_GROUPS || mediaPages[a].selectedType == TAB_GROUPUSERS && !delegate.canSearchMembers() || mediaPages[a].selectedType == TAB_RECOMMENDED_CHANNELS) { if (animated) { searchItemState = 2; } else { searchItemState = 0; - searchItem.setVisibility(isStoriesView() ? View.GONE : View.INVISIBLE); + searchItem.setVisibility(isStoriesView() || searching ? View.GONE : View.INVISIBLE); } } else { if (animated) { @@ -5768,20 +6022,23 @@ private void switchToCurrentSelectedMode(boolean animated) { } else { searchItem.setVisibility(isStoriesView() ? View.GONE : View.INVISIBLE); } - searchItem.setAlpha(0.0f); + searchAlpha = getSearchAlpha(a); + updateSearchItemIcon(1f - a); } else { searchItemState = 0; + searchAlpha = 1f; } } else if (searchItem.getVisibility() == View.INVISIBLE) { if (canShowSearchItem()) { searchItemState = 0; - searchItem.setAlpha(1.0f); + searchAlpha = 1; searchItem.setVisibility(View.VISIBLE); } else { searchItem.setVisibility(isStoriesView() ? View.GONE : View.INVISIBLE); - searchItem.setAlpha(0.0f); + searchAlpha = 0; } } + updateOptionsSearch(); } if (mediaPages[a].selectedType == TAB_COMMON_GROUPS) { if (!commonGroupsAdapter.loading && !commonGroupsAdapter.endReached && commonGroupsAdapter.chats.isEmpty()) { @@ -5817,7 +6074,7 @@ private void switchToCurrentSelectedMode(boolean animated) { type = MediaDataController.MEDIA_VIDEOS_ONLY; } } - profileActivity.getMediaDataController().loadMedia(dialog_id, 50, 0, 0, type, topicId, 1, profileActivity.getClassGuid(), sharedMediaData[mediaPages[a].selectedType].requestIndex, skipPhotos); + profileActivity.getMediaDataController().loadMedia(dialog_id, 50, 0, 0, type, topicId, 1, profileActivity.getClassGuid(), sharedMediaData[mediaPages[a].selectedType].requestIndex, null, null, skipPhotos); } } if (mediaPages[a].selectedType == TAB_STORIES) { @@ -5848,8 +6105,9 @@ private void switchToCurrentSelectedMode(boolean animated) { ignoreSearchCollapse = true; actionBar.closeSearchField(); searchItemState = 0; - searchItem.setAlpha(0.0f); + searchAlpha = 0; searchItem.setVisibility(isStoriesView() ? View.GONE : View.INVISIBLE); + updateOptionsSearch(); } } @@ -6927,7 +7185,7 @@ public MediaSearchAdapter(Context context, int type) { currentType = type; } - public void queryServerSearch(final String query, final int max_id, long did) { + public void queryServerSearch(final String query, final int max_id, long did, long topicId) { if (DialogObject.isEncryptedDialog(did)) { return; } @@ -6954,6 +7212,15 @@ public void queryServerSearch(final String query, final int max_id, long did) { } req.q = query; req.peer = profileActivity.getMessagesController().getInputPeer(did); + if (topicId != 0) { + if (did == profileActivity.getUserConfig().getClientUserId()) { + req.flags |= 4; + req.saved_peer_id = profileActivity.getMessagesController().getInputPeer(topicId); + } else { + req.flags |= 2; + req.top_msg_id = (int) topicId; + } + } if (req.peer == null) { return; } @@ -7035,9 +7302,9 @@ public void search(final String query, boolean animated) { AndroidUtilities.runOnUIThread(searchRunnable = () -> { if (!sharedMediaData[currentType].messages.isEmpty() && (currentType == 1 || currentType == 4)) { MessageObject messageObject = sharedMediaData[currentType].messages.get(sharedMediaData[currentType].messages.size() - 1); - queryServerSearch(query, messageObject.getId(), messageObject.getDialogId()); + queryServerSearch(query, messageObject.getId(), messageObject.getDialogId(), dialog_id == profileActivity.getUserConfig().getClientUserId() ? messageObject.getSavedDialogId() : 0); } else if (currentType == 3) { - queryServerSearch(query, 0, dialog_id); + queryServerSearch(query, 0, dialog_id, topicId); } if (currentType == 1 || currentType == 4) { final ArrayList copy = new ArrayList<>(sharedMediaData[currentType].messages); @@ -7356,7 +7623,7 @@ public boolean isLongPressDragEnabled() { } @Override public int getMovementFlags(@NonNull RecyclerView recyclerView, @NonNull RecyclerView.ViewHolder viewHolder) { - if (!isActionModeShowed) { + if (!isActionModeShowed || recyclerView.getAdapter() == savedMessagesSearchAdapter) { return makeMovementFlags(0, 0); } SavedMessagesController.SavedDialog d = getDialog(viewHolder); @@ -7391,7 +7658,7 @@ public void onSelectedChanged(RecyclerView.ViewHolder viewHolder, int actionStat @Override public boolean onMove(@NonNull RecyclerView recyclerView, @NonNull RecyclerView.ViewHolder sourceHolder, @NonNull RecyclerView.ViewHolder targetHolder) { - if (!isActionModeShowed) { + if (!isActionModeShowed || recyclerView.getAdapter() == savedMessagesSearchAdapter) { return false; } SavedMessagesController.SavedDialog source = getDialog(sourceHolder); @@ -7424,7 +7691,7 @@ public SavedDialogsAdapter(Context context) { mContext = context; controller = profileActivity.getMessagesController().getSavedMessagesController(); if (includeSavedDialogs()) { - controller.loadDialogs(); + controller.loadDialogs(false); } setHasStableIds(true); update(false); @@ -7511,7 +7778,6 @@ public void unselectAll() { @Override public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { DialogCell cell = new DialogCell(null, mContext, false, true) { - @Override public boolean isForumCell() { return false; @@ -7539,6 +7805,7 @@ public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int positi DialogCell cell = (DialogCell) holder.itemView; SavedMessagesController.SavedDialog d = dialogs.get(position); cell.setDialog(d.dialogId, d.message, d.getDate(), false, false); + cell.isSavedDialogCell = true; cell.setChecked(selectedDialogs.contains(d.dialogId), false); cell.useSeparator = position + 1 < getItemCount(); } @@ -7564,6 +7831,8 @@ private class SavedMessagesSearchAdapter extends RecyclerListView.SelectionAdapt private final int currentAccount; public final ArrayList dialogs = new ArrayList<>(); public final ArrayList messages = new ArrayList<>(); + public final ArrayList loadedMessages = new ArrayList<>(); + public final ArrayList cachedMessages = new ArrayList<>(); public SavedMessagesSearchAdapter(Context context) { mContext = context; currentAccount = profileActivity.getCurrentAccount(); @@ -7576,43 +7845,54 @@ public SavedMessagesSearchAdapter(Context context) { private int count = 0; private String lastQuery; + private ReactionsLayoutInBubble.VisibleReaction lastReaction; private int reqId = -1; - public void search(String query) { - if (TextUtils.equals(query, lastQuery)) { + + public void search(String query, ReactionsLayoutInBubble.VisibleReaction reaction) { + if (TextUtils.equals(query, lastQuery) && (lastReaction == null && reaction == null || lastReaction != null && lastReaction.equals(reaction))) { return; } lastQuery = query; + lastReaction = reaction; if (reqId >= 0) { ConnectionsManager.getInstance(currentAccount).cancelRequest(reqId, true); reqId = -1; } + cachedMessages.clear(); + loadedMessages.clear(); messages.clear(); count = 0; endReached = false; loading = true; dialogs.clear(); - dialogs.addAll(MessagesController.getInstance(currentAccount).getSavedMessagesController().searchDialogs(query)); + if (lastReaction == null) { + dialogs.addAll(MessagesController.getInstance(currentAccount).getSavedMessagesController().searchDialogs(query)); + } for (int a = 0; a < mediaPages.length; a++) { if (mediaPages[a].selectedType == TAB_SAVED_DIALOGS) { mediaPages[a].emptyView.showProgress(true, true); } } - notifyDataSetChanged(); + if (lastReaction == null) { + notifyDataSetChanged(); + } AndroidUtilities.cancelRunOnUIThread(searchRunnable); - AndroidUtilities.runOnUIThread(searchRunnable, 600); + AndroidUtilities.runOnUIThread(searchRunnable, lastReaction != null ? 60 : 600); } public void loadMore() { if (endReached || loading) return; + loading = true; sendRequest(); } + int lastSearchId; private Runnable searchRunnable = this::sendRequest; private void sendRequest() { - if (TextUtils.isEmpty(lastQuery)) { + if (TextUtils.isEmpty(lastQuery) && lastReaction == null) { loading = false; return; } @@ -7620,46 +7900,98 @@ private void sendRequest() { req.peer = MessagesController.getInstance(currentAccount).getInputPeer(UserConfig.getInstance(currentAccount).getClientUserId()); req.filter = new TLRPC.TL_inputMessagesFilterEmpty(); req.q = lastQuery; - if (messages.size() > 0) { - MessageObject lastMessage = messages.get(messages.size() - 1); + if (lastReaction != null) { + req.flags |= 8; + req.saved_reaction.add(lastReaction.toTLReaction()); + } + if (loadedMessages.size() > 0) { + MessageObject lastMessage = loadedMessages.get(loadedMessages.size() - 1); req.offset_id = lastMessage.getId(); } req.limit = 10; endReached = false; - reqId = ConnectionsManager.getInstance(currentAccount).sendRequest(req, (res, err) -> AndroidUtilities.runOnUIThread(() -> { - if (!(res instanceof TLRPC.messages_Messages)) { - return; - } - TLRPC.messages_Messages r = (TLRPC.messages_Messages) res; - MessagesController.getInstance(currentAccount).putUsers(r.users, false); - MessagesController.getInstance(currentAccount).putChats(r.chats, false); - MessagesStorage.getInstance(currentAccount).putUsersAndChats(r.users, r.chats, true, true); - for (int i = 0; i < r.messages.size(); ++i) { - TLRPC.Message msg = r.messages.get(i); - messages.add(new MessageObject(currentAccount, msg, false, false)); - } - if (r instanceof TLRPC.TL_messages_messagesSlice) { + final int searchId = ++lastSearchId; + Runnable request = () -> { + if (searchId != lastSearchId) return; + reqId = ConnectionsManager.getInstance(currentAccount).sendRequest(req, (res, err) -> AndroidUtilities.runOnUIThread(() -> { + if (!(res instanceof TLRPC.messages_Messages) || searchId != lastSearchId) { + return; + } + TLRPC.messages_Messages r = (TLRPC.messages_Messages) res; + MessagesController.getInstance(currentAccount).putUsers(r.users, false); + MessagesController.getInstance(currentAccount).putChats(r.chats, false); + MessagesStorage.getInstance(currentAccount).putUsersAndChats(r.users, r.chats, true, true); + for (int i = 0; i < r.messages.size(); ++i) { + TLRPC.Message msg = r.messages.get(i); + MessageObject messageObject = new MessageObject(currentAccount, msg, false, true); + if (messageObject.hasValidGroupId()) { + messageObject.isPrimaryGroupMessage = true; + } + messageObject.setQuery(lastQuery); + loadedMessages.add(messageObject); + } count = r.count; - endReached = messages.size() >= count; - } else if (r instanceof TLRPC.TL_messages_messages) { - count = messages.size(); - endReached = true; + if (r instanceof TLRPC.TL_messages_messagesSlice) { + endReached = loadedMessages.size() >= r.count; + } else if (r instanceof TLRPC.TL_messages_messages) { + endReached = true; + } + updateMessages(false); + loading = false; + reqId = -1; + })); + }; + if (lastReaction != null) { + MessagesStorage.getInstance(currentAccount).searchSavedByTag(lastReaction.toTLReaction(), 0, lastQuery, 100, cachedMessages.size(), (messages, users, chats, emoji) -> { + MessagesController.getInstance(currentAccount).putUsers(users, true); + MessagesController.getInstance(currentAccount).putChats(chats, true); + AnimatedEmojiDrawable.getDocumentFetcher(currentAccount).processDocuments(emoji); + for (int i = 0; i < messages.size(); ++i) { + MessageObject messageObject = messages.get(i); + if (messageObject.hasValidGroupId() && messageObject.messageOwner.reactions != null) { + messageObject.isPrimaryGroupMessage = true; + } + messageObject.setQuery(lastQuery); + cachedMessages.add(messageObject); + } + updateMessages(true); + AndroidUtilities.runOnUIThread(request, 540); + }, false); + } else { + request.run(); + } + } + + private void updateMessages(boolean fromCache) { + messages.clear(); + HashSet msgIds = new HashSet<>(); + for (int i = 0; i < loadedMessages.size(); ++i) { + MessageObject msg = loadedMessages.get(i); + if (msg != null && !msgIds.contains(msg.getId())) { + msgIds.add(msg.getId()); + messages.add(msg); } + } + for (int i = 0; i < cachedMessages.size(); ++i) { + MessageObject msg = cachedMessages.get(i); + if (msg != null && !msgIds.contains(msg.getId())) { + msgIds.add(msg.getId()); + messages.add(msg); + } + } + if (!fromCache || !cachedMessages.isEmpty()) { for (int a = 0; a < mediaPages.length; a++) { if (mediaPages[a].selectedType == TAB_SAVED_DIALOGS) { - if (count == 0 && dialogs.isEmpty()) { - mediaPages[a].emptyView.title.setText(LocaleController.formatString("NoResultFoundFor", R.string.NoResultFoundFor, lastQuery)); + if (messages.isEmpty() && dialogs.isEmpty()) { + mediaPages[a].emptyView.title.setText(lastReaction != null && TextUtils.isEmpty(lastQuery) ? AndroidUtilities.replaceCharSequence("%s", LocaleController.getString(R.string.NoResultFoundForTag), lastReaction.toCharSequence(mediaPages[a].emptyView.title.getPaint().getFontMetricsInt())) : LocaleController.formatString(R.string.NoResultFoundFor, lastQuery)); mediaPages[a].emptyView.showProgress(false, true); } } } - oldItemCounts = count; - reqId = -1; - - notifyDataSetChanged(); - loading = false; - })); + } + oldItemCounts = count; + notifyDataSetChanged(); } @Override @@ -8950,4 +9282,36 @@ public void updateClip(int[] clip) { clip[1] = getMeasuredHeight() - getPaddingBottom(); } } + + private void updateOptionsSearch() { + updateOptionsSearch(false); + } + private void updateOptionsSearch(boolean finish) { + if (optionsSearchImageView == null) return; + optionsSearchImageView.setAlpha(searching ? 0f : Utilities.clamp(searchAlpha + optionsAlpha, 1, 0)); + if (finish) { + animateSearchToOptions(getPhotoVideoOptionsAlpha(1) > 0.5f, true); + } else if (searchItemState == 2) { + animateSearchToOptions(optionsAlpha > 0.1f, true); + } else { + animateSearchToOptions(searchAlpha < 0.1f, true); + } + } + private boolean animatingToOptions; + public void animateSearchToOptions(boolean toOptions, boolean animated) { + if (optionsSearchImageView == null) return; + if (animatingToOptions != toOptions) { + animatingToOptions = toOptions; + if (!animatingToOptions && optionsSearchImageView.getAnimatedDrawable().getCurrentFrame() < 20) { + optionsSearchImageView.getAnimatedDrawable().setCustomEndFrame(0); + } else { + optionsSearchImageView.getAnimatedDrawable().setCustomEndFrame(animatingToOptions ? 50 : 100); + } + if (animated) { + optionsSearchImageView.getAnimatedDrawable().start(); + } else { + optionsSearchImageView.getAnimatedDrawable().setCurrentFrame(optionsSearchImageView.getAnimatedDrawable().getCustomEndFrame()); + } + } + } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/StickerEmptyView.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/StickerEmptyView.java index e4a3553d9f..481078ecdc 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/StickerEmptyView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/StickerEmptyView.java @@ -30,6 +30,7 @@ import org.telegram.messenger.UserConfig; import org.telegram.tgnet.TLRPC; import org.telegram.ui.ActionBar.Theme; +import org.telegram.ui.Components.spoilers.SpoilersTextView; import org.telegram.ui.LaunchActivity; public class StickerEmptyView extends FrameLayout implements NotificationCenter.NotificationCenterDelegate { @@ -43,7 +44,7 @@ public class StickerEmptyView extends FrameLayout implements NotificationCenter. public LinearLayout linearLayout; public BackupImageView stickerView; private RadialProgressView progressBar; - public final TextView title; + public final SpoilersTextView title; public final LinkSpanDrawable.LinksTextView subtitle; private boolean progressShowing; private final Theme.ResourcesProvider resourcesProvider; @@ -103,9 +104,9 @@ public void setVisibility(int visibility) { stickerView = new BackupImageView(context); stickerView.setOnClickListener(view -> stickerView.getImageReceiver().startAnimation()); - title = new TextView(context); + title = new SpoilersTextView(context); - title.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf")); + title.setTypeface(AndroidUtilities.getTypeface(AndroidUtilities.TYPEFACE_ROBOTO_MEDIUM)); title.setTag(Theme.key_windowBackgroundWhiteBlackText); title.setTextColor(getThemedColor(Theme.key_windowBackgroundWhiteBlackText)); title.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 20); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/StickersAlert.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/StickersAlert.java index ca94da0889..b2997635a0 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/StickersAlert.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/StickersAlert.java @@ -39,6 +39,7 @@ import android.transition.Transition; import android.transition.TransitionManager; import android.transition.TransitionValues; +import android.util.Log; import android.util.SparseArray; import android.util.TypedValue; import android.view.Gravity; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/ThanosEffect.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/ThanosEffect.java index a9a9afa9ce..40f9827ec4 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/ThanosEffect.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/ThanosEffect.java @@ -179,6 +179,9 @@ private void destroy() { } public void kill() { + if (destroyed) { + return; + } destroyed = true; for (ToSet set : toSet) { if (set.doneCallback != null) { @@ -366,27 +369,31 @@ public void scroll(int dx, int dy) { } private void resizeInternal(int width, int height) { - if (!alive) return; + if (!alive) { + return; + } this.width = width; this.height = height; GLES31.glViewport(0, 0, width, height); GLES31.glUniform2f(sizeHandle, width, height); } - private boolean killed; public void kill() { - if (killed) return; + if (!alive) { + return; + } try { Handler handler = getHandler(); if (handler != null) { handler.sendMessage(handler.obtainMessage(DO_KILL)); } - killed = true; } catch (Exception e) {} } private void killInternal() { - if (!alive) return; + if (!alive) { + return; + } alive = false; for (int i = 0; i < pendingAnimations.size(); ++i) { Animation animation = pendingAnimations.get(i); @@ -615,36 +622,49 @@ private void draw() { } }; - public void layoutAnimations() { - - } - private final ArrayList toAddAnimations = new ArrayList<>(); public void animateGroup(ArrayList views, Runnable whenDone) { - if (!alive) return; + if (!alive) { + for (int i = 0; i < views.size(); ++i) { + views.get(i).setVisibility(GONE); + } + if (whenDone != null) { + AndroidUtilities.runOnUIThread(whenDone); + } + if (destroy != null) { + AndroidUtilities.runOnUIThread(destroy); + destroy = null; + } + return; + } Animation animation = new Animation(views, whenDone); - Handler handler = getHandler(); running = true; - if (handler == null) { - toAddAnimations.add(animation); - } else { - handler.sendMessage(handler.obtainMessage(DO_ADD_ANIMATION, animation)); - } + postRunnable(() -> addAnimationInternal(animation)); } public void animate(View view, float durationMultipier, Runnable whenDone) { - if (!alive) return; + if (!alive) { + if (view != null) { + view.setVisibility(GONE); + } + if (whenDone != null) { + AndroidUtilities.runOnUIThread(whenDone); + } + if (destroy != null) { + AndroidUtilities.runOnUIThread(destroy); + destroy = null; + } + return; + } Animation animation = new Animation(view, durationMultipier, whenDone); Handler handler = getHandler(); running = true; - if (handler == null) { - toAddAnimations.add(animation); - } else { - handler.sendMessage(handler.obtainMessage(DO_ADD_ANIMATION, animation)); - } + postRunnable(() -> addAnimationInternal(animation)); } public void cancel(View view) { - if (!alive) return; + if (!alive) { + return; + } Handler handler = getHandler(); if (handler == null) { for (int i = 0; i < toAddAnimations.size(); ++i) { @@ -672,15 +692,25 @@ public void cancel(View view) { } public void animate(Matrix matrix, Bitmap bitmap, Runnable whenStart, Runnable whenDone) { - if (!alive) return; + if (!alive) { + AndroidUtilities.runOnUIThread(() -> { + if (whenStart != null) { + whenStart.run(); + } + if (whenDone != null) { + AndroidUtilities.runOnUIThread(whenDone); + } + }); + if (destroy != null) { + AndroidUtilities.runOnUIThread(destroy); + destroy = null; + } + return; + } Animation animation = new Animation(matrix, bitmap, whenStart, whenDone); Handler handler = getHandler(); running = true; - if (handler == null) { - toAddAnimations.add(animation); - } else { - handler.sendMessage(handler.obtainMessage(DO_ADD_ANIMATION, animation)); - } + postRunnable(() -> addAnimationInternal(animation)); } private void cancelAnimationInternal(View view) { @@ -823,7 +853,7 @@ public Animation(ArrayList views, Runnable whenDone) { } MessageObject.GroupedMessages group = cell.getCurrentMessagesGroup(); - MessageObject.GroupedMessagePosition position = group == null || group.positions == null ? null : group.positions.get(cell.getMessageObject()); + MessageObject.GroupedMessagePosition position = group == null || group.positions == null ? null : group.getPosition(cell.getMessageObject()); if (k == 0) { if (position != null || cell.getTransitionParams().animateBackgroundBoundsInner) { if (position == null || (position.last || position.minX == 0 && position.minY == 0)) { @@ -922,6 +952,8 @@ public Animation(ArrayList views, Runnable whenDone) { t -= top; b -= top; + l -= left; + r -= left; boolean useScale = group.transitionParams.cell.getScaleX() != 1f || group.transitionParams.cell.getScaleY() != 1f; if (useScale) { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/spoilers/SpoilersTextView.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/spoilers/SpoilersTextView.java index 82118d6796..f2fa34ea9c 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/spoilers/SpoilersTextView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/spoilers/SpoilersTextView.java @@ -2,13 +2,16 @@ import android.content.Context; import android.graphics.Canvas; +import android.graphics.ColorFilter; import android.graphics.Paint; import android.graphics.Path; import android.graphics.PorterDuff; +import android.graphics.PorterDuffColorFilter; import android.graphics.PorterDuffXfermode; import android.graphics.Rect; import android.graphics.Region; import android.text.Layout; +import android.text.Spannable; import android.text.Spanned; import android.text.StaticLayout; import android.view.MotionEvent; @@ -16,6 +19,8 @@ import org.telegram.messenger.AndroidUtilities; import org.telegram.ui.Cells.TextSelectionHelper; +import org.telegram.ui.Components.AnimatedEmojiDrawable; +import org.telegram.ui.Components.AnimatedEmojiSpan; import java.util.ArrayList; import java.util.List; @@ -32,6 +37,9 @@ public class SpoilersTextView extends TextView implements TextSelectionHelper.Si private Paint xRefPaint; public boolean allowClickSpoilers = true; + public int cacheType = AnimatedEmojiDrawable.CACHE_TYPE_MESSAGES; + private AnimatedEmojiSpan.EmojiGroupedSpans animatedEmoji; + public SpoilersTextView(Context context) { this(context, true); } @@ -70,6 +78,7 @@ public void setText(CharSequence text, BufferType type) { protected void onTextChanged(CharSequence text, int start, int lengthBefore, int lengthAfter) { super.onTextChanged(text, start, lengthBefore, lengthAfter); invalidateSpoilers(); + updateAnimatedEmoji(true); } @Override @@ -78,6 +87,13 @@ protected void onSizeChanged(int w, int h, int oldw, int oldh) { invalidateSpoilers(); } + private ColorFilter animatedEmojiColorFilter; + @Override + public void setTextColor(int color) { + super.setTextColor(color); + animatedEmojiColorFilter = new PorterDuffColorFilter(color, PorterDuff.Mode.SRC_IN); + } + @Override protected void onDraw(Canvas canvas) { int pl = getPaddingLeft(), pt = getPaddingTop(); @@ -102,6 +118,14 @@ protected void onDraw(Canvas canvas) { super.onDraw(canvas); canvas.restore(); + updateAnimatedEmoji(false); + if (animatedEmoji != null) { + canvas.save(); + canvas.translate(getPaddingLeft(), getPaddingTop()); + AnimatedEmojiSpan.drawAnimatedEmojis(canvas, getLayout(), animatedEmoji, 0, spoilers, 0, getHeight(), 0, 1f, animatedEmojiColorFilter); + canvas.restore(); + } + if (!spoilers.isEmpty()) { boolean useAlphaLayer = spoilers.get(0).getRippleProgress() != -1; if (useAlphaLayer) { @@ -129,12 +153,29 @@ protected void onDraw(Canvas canvas) { } } + @Override + protected void onAttachedToWindow() { + super.onAttachedToWindow(); + updateAnimatedEmoji(true); + } + @Override protected void onLayout(boolean changed, int left, int top, int right, int bottom) { super.onLayout(changed, left, top, right, bottom); invalidateSpoilers(); } + private Layout lastLayout = null; + private int lastTextLength; + public void updateAnimatedEmoji(boolean force) { + int newTextLength = (getLayout() == null || getLayout().getText() == null) ? 0 : getLayout().getText().length(); + if (force || lastLayout != getLayout() || lastTextLength != newTextLength) { + animatedEmoji = AnimatedEmojiSpan.update(cacheType, this, animatedEmoji, getLayout()); + lastLayout = getLayout(); + lastTextLength = newTextLength; + } + } + private void invalidateSpoilers() { if (spoilers == null) return; // Check for a super constructor spoilersPool.addAll(spoilers); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/DialogsActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/DialogsActivity.java index 4b0361b42d..cbe6788f3c 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/DialogsActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/DialogsActivity.java @@ -420,6 +420,7 @@ public void updateList(boolean animated) { private boolean askingForPermissions; private RLottieDrawable passcodeDrawable; private SearchViewPager searchViewPager; + private SharedMediaLayout.SharedMediaPreloader sharedMediaPreloader; public DialogStoriesCell dialogStoriesCell; public boolean dialogStoriesCellVisible; public float progressToDialogStoriesCell; @@ -2771,6 +2772,10 @@ public boolean onFragmentCreate() { getContactsController().loadGlobalPrivacySetting(); + if (getMessagesController().savedViewAsChats) { + getMessagesController().getSavedMessagesController().preloadDialogs(true); + } + return true; } @@ -5068,6 +5073,11 @@ public void onMiniListClicked() { animateToHasStories = false; hasOnlySlefStories = false; hasStories = false; + + if (onlySelect && initialDialogsType == DIALOGS_TYPE_FORWARD) { + MessagesController.getInstance(currentAccount).getSavedReactionTags(0); + } + if (!onlySelect || initialDialogsType == DIALOGS_TYPE_FORWARD) { final FrameLayout.LayoutParams layoutParams = LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT); if (inPreviewMode && Build.VERSION.SDK_INT >= 21) { @@ -6026,7 +6036,7 @@ private void updateContextViewPosition() { totalOffset -= dialogsHintCell.getMeasuredHeight() * rightSlidingDialogContainer.openedProgress; } dialogsHintCell.setTranslationY(totalOffset); - totalOffset += dialogsHintCell.getMeasuredHeight(); + totalOffset += dialogsHintCell.getMeasuredHeight() * (1f - searchAnimationProgress); } if (authHintCell != null && authHintCell.getVisibility() == View.VISIBLE) { if (rightSlidingDialogContainer != null && rightSlidingDialogContainer.hasFragment()) { @@ -7243,9 +7253,15 @@ public void onAnimationEnd(Animator animation) { } } } + if (fragmentContextView != null && Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { + fragmentContextView.setTranslationZ(1f); + } searchAnimator.addListener(new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animation) { + if (fragmentContextView != null && Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { + fragmentContextView.setTranslationZ(0f); + } notificationsLocker.unlock(); if (searchAnimator != animation) { return; @@ -7832,7 +7848,17 @@ private void onItemClick(View view, int position, RecyclerListView.Adapter adapt if (searchViewPager.actionModeShowing()) { searchViewPager.hideActionMode(); } - if (searchString != null) { + if (dialogId == getUserConfig().getClientUserId() && getMessagesController().savedViewAsChats) { + args = new Bundle(); + args.putLong("dialog_id", UserConfig.getInstance(currentAccount).getClientUserId()); + args.putInt("type", MediaActivity.TYPE_MEDIA); + args.putInt("start_from", SharedMediaLayout.TAB_SAVED_DIALOGS); + if (sharedMediaPreloader == null) { + sharedMediaPreloader = new SharedMediaLayout.SharedMediaPreloader(this); + } + MediaActivity mediaActivity = new MediaActivity(args, sharedMediaPreloader); + presentFragment(mediaActivity); + } else if (searchString != null) { if (getMessagesController().checkCanOpenChat(args, DialogsActivity.this)) { getNotificationCenter().postNotificationName(NotificationCenter.closeChats); presentFragment(new ChatActivity(args)); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/GroupCreateFinalActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/GroupCreateFinalActivity.java index 53a8381432..b9dfea3d1b 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/GroupCreateFinalActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/GroupCreateFinalActivity.java @@ -326,7 +326,7 @@ private void setDefaultGroupName() { } if (!TextUtils.isEmpty(txt)) { editText.setText(txt); - editText.setSelection(editText.getText().length()); + editText.setSelection(0, editText.getText().length()); } } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/GroupStickersActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/GroupStickersActivity.java index 002829475f..09788178e1 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/GroupStickersActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/GroupStickersActivity.java @@ -75,7 +75,7 @@ public class GroupStickersActivity extends BaseFragment implements NotificationC private boolean removeStickerSet; private TLRPC.ChatFull info; - private long chatId; + private final long chatId; private int infoRow; private int headerRow; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/LaunchActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/LaunchActivity.java index 00336cfc1f..0b2a475167 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/LaunchActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/LaunchActivity.java @@ -52,6 +52,7 @@ import android.text.TextUtils; import android.text.style.ClickableSpan; import android.util.Base64; +import android.util.Log; import android.util.SparseArray; import android.util.SparseIntArray; import android.view.ActionMode; @@ -178,6 +179,7 @@ import org.telegram.ui.Components.RLottieDrawable; import org.telegram.ui.Components.RLottieImageView; import org.telegram.ui.Components.RecyclerListView; +import org.telegram.ui.Components.SearchTagsList; import org.telegram.ui.Components.SharingLocationsAlert; import org.telegram.ui.Components.SideMenultItemAnimator; import org.telegram.ui.Components.SizeNotifierFrameLayout; @@ -1377,6 +1379,7 @@ public FrameLayout getMainContainerFrameLayout() { return frameLayout; } + private boolean switchingAccount; public void switchToAccount(int account, boolean removeAll) { switchToAccount(account, removeAll, obj -> new DialogsActivity(null)); } @@ -1385,6 +1388,7 @@ public void switchToAccount(int account, boolean removeAll, GenericProvider { TLRPC.TL_forumTopic loadedTopic = MessagesController.getInstance(currentAccount).getTopicsController().findTopic(finalPush_chat_id, finalPush_topic_id); FileLog.d("LaunchActivity openForum after load " + finalPush_chat_id + " " + finalPush_topic_id + " TL_forumTopic " + loadedTopic); @@ -3114,6 +3126,12 @@ private boolean handleIntent(Intent intent, boolean isNew, boolean restore, bool closePrevious = true; } else if (open_settings == 6) { fragment = new EditWidgetActivity(open_widget_edit_type, open_widget_edit); + } else if (open_settings == 10) { + fragment = new LanguageSelectActivity(); + } else if (open_settings == 11) { + fragment = new AutoDeleteMessagesActivity(); + } else if (open_settings == 12) { + fragment = new PrivacySettingsActivity(); } else if (open_settings == 100) { fragment = new NekoSettingsActivity(); } else { @@ -5359,13 +5377,12 @@ private List findContacts(String userName, String userPhone, b return foundContacts; } - public void checkAppUpdate(boolean force) { + public void checkAppUpdate(boolean force, Browser.Progress progress) { if (BuildVars.isFdroid || BuildVars.isPlay) return; if (NekoXConfig.autoUpdateReleaseChannel == 0) return; if (!force && System.currentTimeMillis() < NekoConfig.lastUpdateCheckTime.Long() + 48 * 60 * 60 * 1000L) return; NekoConfig.lastUpdateCheckTime.setConfigLong(System.currentTimeMillis()); FileLog.d("checking update"); - final int accountNum = currentAccount; InternalUpdater.checkUpdate((res, error) -> AndroidUtilities.runOnUIThread(() -> { if (res != null) { @@ -5390,6 +5407,74 @@ public void checkAppUpdate(boolean force) { } NotificationCenter.getGlobalInstance().postNotificationName(NotificationCenter.appUpdateAvailable); })); + +// if (!force && BuildVars.DEBUG_VERSION || !force && !BuildVars.CHECK_UPDATES) { +// return; +// } +// if (!force && Math.abs(System.currentTimeMillis() - SharedConfig.lastUpdateCheckTime) < MessagesController.getInstance(0).updateCheckDelay * 1000) { +// return; +// } +// TLRPC.TL_help_getAppUpdate req = new TLRPC.TL_help_getAppUpdate(); +// try { +// req.source = ApplicationLoader.applicationContext.getPackageManager().getInstallerPackageName(ApplicationLoader.applicationContext.getPackageName()); +// } catch (Exception ignore) {} +// +// final int accountNum = currentAccount; +// int reqId = ConnectionsManager.getInstance(currentAccount).sendRequest(req, (response, error) -> { +// SharedConfig.lastUpdateCheckTime = System.currentTimeMillis(); +// SharedConfig.saveConfig(); +// if (response instanceof TLRPC.TL_help_appUpdate) { +// final TLRPC.TL_help_appUpdate res = (TLRPC.TL_help_appUpdate) response; +// AndroidUtilities.runOnUIThread(() -> { +// if (SharedConfig.pendingAppUpdate != null && SharedConfig.pendingAppUpdate.version.equals(res.version)) { +// return; +// } +// final boolean newVersionAvailable = SharedConfig.setNewAppVersionAvailable(res); +// if (newVersionAvailable) { +// if (res.can_not_skip) { +// showUpdateActivity(accountNum, res, false); +// } else if (ApplicationLoader.isStandaloneBuild() || BuildVars.DEBUG_VERSION) { +// drawerLayoutAdapter.notifyDataSetChanged(); +// ApplicationLoader.applicationLoaderInstance.showUpdateAppPopup(LaunchActivity.this, res, accountNum); +// } +// NotificationCenter.getGlobalInstance().postNotificationName(NotificationCenter.appUpdateAvailable); +// } +// if (progress != null) { +// progress.end(); +// if (!newVersionAvailable) { +// BaseFragment fragment = getLastFragment(); +// if (fragment != null) { +// BulletinFactory.of(fragment).createSimpleBulletin(R.raw.chats_infotip, LocaleController.getString(R.string.YourVersionIsLatest)).show(); +// } +// } +// } +// }); +// } else if (response instanceof TLRPC.TL_help_noAppUpdate) { +// AndroidUtilities.runOnUIThread(() -> { +// if (progress != null) { +// progress.end(); +// BaseFragment fragment = getLastFragment(); +// if (fragment != null) { +// BulletinFactory.of(fragment).createSimpleBulletin(R.raw.chats_infotip, LocaleController.getString(R.string.YourVersionIsLatest)).show(); +// } +// } +// }); +// } else if (error != null) { +// AndroidUtilities.runOnUIThread(() -> { +// if (progress != null) { +// progress.end(); +// BaseFragment fragment = getLastFragment(); +// if (fragment != null) { +// BulletinFactory.of(fragment).showForError(error); +// } +// } +// }); +// } +// }); +// if (progress != null) { +// progress.init(); +// progress.onCancel(() -> ConnectionsManager.getInstance(currentAccount).cancelRequest(reqId, true)); +// } } public Dialog showAlertDialog(AlertDialog.Builder builder) { @@ -6155,7 +6240,7 @@ protected void onResume() { } else if (SharedConfig.pendingAppUpdate != null && SharedConfig.pendingAppUpdate.can_not_skip) { showUpdateActivity(UserConfig.selectedAccount, SharedConfig.pendingAppUpdate, true); } - checkAppUpdate(false); + checkAppUpdate(false, null); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { ApplicationLoader.canDrawOverlays = Settings.canDrawOverlays(this); @@ -7347,7 +7432,9 @@ public void onBackPressed() { finish(); return; } - if (ContentPreviewViewer.hasInstance() && ContentPreviewViewer.getInstance().isVisible()) { + if (SearchTagsList.onBackPressedRenameTagAlert()) { + return; + } else if (ContentPreviewViewer.hasInstance() && ContentPreviewViewer.getInstance().isVisible()) { ContentPreviewViewer.getInstance().closeWithMenu(); } if (SecretMediaViewer.hasInstance() && SecretMediaViewer.getInstance().isVisible()) { SecretMediaViewer.getInstance().closePhoto(true, false); @@ -7581,7 +7668,9 @@ public boolean needPresentFragment(INavigationLayout layout, INavigationLayout.N } return result; } else if (!tabletFullSize && layout != rightActionBarLayout) { - rightActionBarLayout.getView().setVisibility(View.VISIBLE); + if (rightActionBarLayout.getView() != null) { + rightActionBarLayout.getView().setVisibility(View.VISIBLE); + } backgroundTablet.setVisibility(View.GONE); rightActionBarLayout.removeAllFragments(); rightActionBarLayout.presentFragment(params.setNoAnimation(true).setRemoveLast(removeLast).setCheckPresentFromDelegate(false)); @@ -7738,7 +7827,7 @@ public boolean needAddFragmentToStack(BaseFragment fragment, INavigationLayout l @Override public boolean needCloseLastFragment(INavigationLayout layout) { if (AndroidUtilities.isTablet()) { - if (layout == actionBarLayout && layout.getFragmentStack().size() <= 1) { + if (layout == actionBarLayout && layout.getFragmentStack().size() <= 1 && !switchingAccount) { onFinish(); finish(); return false; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/PhotoPickerActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/PhotoPickerActivity.java index 4102bc8dd8..36db908a04 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/PhotoPickerActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/PhotoPickerActivity.java @@ -539,7 +539,7 @@ public void onItemClick(int id) { menuItem.setSubMenuDelegate(new ActionBarMenuItem.ActionBarSubMenuItemDelegate() { @Override public void onShowSubMenu() { - showAsListItem.setText(listSort ? LocaleController.getString("ShowAsGrid", R.string.ShowAsGrid) : LocaleController.getString("ShowAsList", R.string.ShowAsList)); + showAsListItem.setText(listSort ? LocaleController.getString(R.string.ShowAsGrid) : LocaleController.getString("ShowAsList", R.string.ShowAsList)); showAsListItem.setIcon(listSort ? R.drawable.msg_media : R.drawable.msg_list); } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/PhotoViewer.java b/TMessagesProj/src/main/java/org/telegram/ui/PhotoViewer.java index f85adf35c7..782da8ad36 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/PhotoViewer.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/PhotoViewer.java @@ -146,7 +146,6 @@ import org.telegram.messenger.BringAppForegroundService; import org.telegram.messenger.BuildVars; import org.telegram.messenger.ChatObject; -import org.telegram.messenger.ContactsController; import org.telegram.messenger.DialogObject; import org.telegram.messenger.DownloadController; import org.telegram.messenger.Emoji; @@ -240,6 +239,7 @@ import org.telegram.ui.Components.QuoteSpan; import org.telegram.ui.Components.RLottieDrawable; import org.telegram.ui.Components.RadialProgressView; +import org.telegram.ui.Components.Reactions.ReactionsLayoutInBubble; import org.telegram.ui.Components.RecyclerListView; import org.telegram.ui.Components.ScaleStateListAnimator; import org.telegram.ui.Components.ShareAlert; @@ -1858,6 +1858,9 @@ public void restore() { private int sharedMediaType; private long topicId; private long currentDialogId; + private ReactionsLayoutInBubble.VisibleReaction currentFilterTag; + private String currentFilterQuery; + private boolean currentFiltered; private long mergeDialogId; private int totalImagesCount; private int startOffset; @@ -4003,7 +4006,7 @@ public void didReceivedNotification(int id, int account, Object... args) { if (needSearchImageInArr && isFirstLoading) { isFirstLoading = false; loadingMoreImages = true; - MediaDataController.getInstance(currentAccount).loadMedia(currentDialogId, 20, 0, 0, sharedMediaType, topicId, 1, classGuid, 0); + MediaDataController.getInstance(currentAccount).loadMedia(currentDialogId, 20, 0, 0, sharedMediaType, topicId, 1, classGuid, 0, currentFilterTag, null); } else if (!imagesArr.isEmpty()) { setIsAboutToSwitchToIndex(switchingToIndex, true, true); } @@ -4088,7 +4091,7 @@ public void didReceivedNotification(int id, int account, Object... args) { if (!endReached[loadIndex]) { loadingMoreImages = true; - MediaDataController.getInstance(currentAccount).loadMedia(loadIndex == 0 ? currentDialogId : mergeDialogId, 40, loadFromMaxId, 0, sharedMediaType, topicId, 1, classGuid, 0); + MediaDataController.getInstance(currentAccount).loadMedia(loadIndex == 0 ? currentDialogId : mergeDialogId, 40, loadFromMaxId, 0, sharedMediaType, topicId, 1, classGuid, 0, currentFilterTag, null); } } } else { @@ -4701,6 +4704,7 @@ public void setAlpha(float alpha) { actionBar.setBackgroundColor(Theme.ACTION_BAR_PHOTO_VIEWER_COLOR); actionBar.setOccupyStatusBar(isStatusBarVisible()); actionBar.setItemsBackgroundColor(Theme.ACTION_BAR_WHITE_SELECTOR_COLOR, false); + actionBar.setItemsColor(Color.WHITE, false); actionBar.setBackButtonImage(R.drawable.ic_ab_back); actionBarContainer = new PhotoViewerActionBarContainer(activity); actionBar.addView(actionBarContainer, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, Gravity.FILL)); @@ -12170,7 +12174,43 @@ private void onPhotoShow(final MessageObject messageObject, final TLRPC.FileLoca dialogPhotos = null; if (currentAnimation == null && !isEvent) { if (currentDialogId != 0 && totalImagesCount == 0 && currentMessageObject != null && !currentMessageObject.scheduled) { - if (MediaDataController.getMediaType(currentMessageObject.messageOwner) == sharedMediaType) { + /*if (currentFilterTag != null && TextUtils.isEmpty(currentFilterQuery)) { + if (needSearchImageInArr && isFirstLoading) { + isFirstLoading = false; + loadingMoreImages = true; + MediaDataController.getInstance(currentAccount).loadMedia(currentDialogId, 50, 0, 0, sharedMediaType, topicId, 1, classGuid, 0, currentFilterTag, null); + } + } else */if (currentFiltered && parentChatActivity != null) { + ArrayList messageObjects = parentChatActivity.getFilteredMessages(); + if (messageObjects != null) { + imagesArr.clear(); + for (int i = 0; i < messageObjects.size(); ++i) { + MessageObject msg = messageObjects.get(i); + if (MediaDataController.getMediaType(msg.messageOwner) != sharedMediaType) + continue; + imagesArr.add(msg); + imagesByIds[0].put(msg.getId(), msg); + } + Collections.sort(imagesArr, (a, b) -> a.getId() - b.getId()); + currentIndex = -1; + for (int i = 0; i < imagesArr.size(); ++i) { + if (imagesArr.get(i) == currentMessageObject || imagesArr.get(i).getId() == currentMessageObject.getId()) { + currentIndex = i; + } + } + if (currentIndex < 0) { + currentIndex = imagesArr.size(); + imagesArr.add(currentMessageObject); + imagesByIds[0].put(currentMessageObject.getId(), currentMessageObject); + } + setImages(); + if (countView != null) { + countView.updateShow(true, false); + countView.set(1 + currentIndex, imagesArr.size(), false); + } + } + isFirstLoading = false; + } else if (MediaDataController.getMediaType(currentMessageObject.messageOwner) == sharedMediaType) { MediaDataController.getInstance(currentAccount).getMediaCount(currentDialogId, topicId, sharedMediaType, classGuid, true); if (mergeDialogId != 0) { MediaDataController.getInstance(currentAccount).getMediaCount(mergeDialogId, topicId, sharedMediaType, classGuid, true); @@ -12407,7 +12447,12 @@ private void setIsAboutToSwitchToIndex(int index, boolean init, boolean animated } allowShare = !noforwardsOverride; } - if (totalImagesCount + totalImagesCountMerge != 0 && !needSearchImageInArr) { + if (currentFiltered && (currentFilterTag != null || !TextUtils.isEmpty(currentFilterQuery))) { + if (countView != null) { + countView.updateShow(true, animated); + countView.set(1 + switchingToIndex, imagesArr.size()); + } + } else if (totalImagesCount + totalImagesCountMerge != 0 && !needSearchImageInArr) { if (opennedFromMedia) { if (startOffset + imagesArr.size() < totalImagesCount + totalImagesCountMerge && !loadingMoreImages && switchingToIndex > imagesArr.size() - 5) { int loadFromMaxId = imagesArr.isEmpty() ? 0 : imagesArr.get(imagesArr.size() - 1).getId(); @@ -12420,7 +12465,7 @@ private void setIsAboutToSwitchToIndex(int index, boolean init, boolean animated } if (!placeProvider.loadMore()) { - MediaDataController.getInstance(currentAccount).loadMedia(loadIndex == 0 ? currentDialogId : mergeDialogId, 40, loadFromMaxId, 0, sharedMediaType, topicId, 1, classGuid, 0); + MediaDataController.getInstance(currentAccount).loadMedia(loadIndex == 0 ? currentDialogId : mergeDialogId, 40, loadFromMaxId, 0, sharedMediaType, topicId, 1, classGuid, 0, currentFilterTag, null); loadingMoreImages = true; } } @@ -12429,7 +12474,7 @@ private void setIsAboutToSwitchToIndex(int index, boolean init, boolean animated int loadFromMinId = imagesArr.get(0).getId(); int loadIndex = 0; if (!placeProvider.loadMore()) { - MediaDataController.getInstance(currentAccount).loadMedia(loadIndex == 0 ? currentDialogId : mergeDialogId, 40, 0, loadFromMinId, sharedMediaType, topicId, 1, classGuid, 0); + MediaDataController.getInstance(currentAccount).loadMedia(loadIndex == 0 ? currentDialogId : mergeDialogId, 40, 0, loadFromMinId, sharedMediaType, topicId, 1, classGuid, 0, currentFilterTag, null); loadingMoreImages = true; } } @@ -12448,7 +12493,7 @@ private void setIsAboutToSwitchToIndex(int index, boolean init, boolean animated } } - MediaDataController.getInstance(currentAccount).loadMedia(loadIndex == 0 ? currentDialogId : mergeDialogId, 80, loadFromMaxId, 0, sharedMediaType, topicId, 1, classGuid, 0); + MediaDataController.getInstance(currentAccount).loadMedia(loadIndex == 0 ? currentDialogId : mergeDialogId, 80, loadFromMaxId, 0, sharedMediaType, topicId, 1, classGuid, 0, currentFilterTag, null); loadingMoreImages = true; } if (countView != null) { @@ -14766,6 +14811,10 @@ public boolean openPhoto(final MessageObject messageObject, placeProvider = provider; mergeDialogId = mDialogId; currentDialogId = dialogId; + currentFilterTag = chatActivity != null ? chatActivity.getFilterTag() : null; + currentFilterQuery = chatActivity != null ? chatActivity.getFilterQuery() : null; + currentFiltered = chatActivity != null && chatActivity.isFiltered(); + this.topicId = topicId; selectedPhotosAdapter.notifyDataSetChanged(); this.pageBlocksAdapter = pageBlocksAdapter; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/PremiumPreviewFragment.java b/TMessagesProj/src/main/java/org/telegram/ui/PremiumPreviewFragment.java index a830ebba72..6940887bed 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/PremiumPreviewFragment.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/PremiumPreviewFragment.java @@ -152,10 +152,14 @@ public class PremiumPreviewFragment extends BaseFragment implements Notification public final static int PREMIUM_FEATURE_STORIES_EXPIRATION_DURATION = 17; public final static int PREMIUM_FEATURE_STORIES_SAVE_TO_GALLERY = 18; public final static int PREMIUM_FEATURE_STORIES_LINKS_AND_FORMATTING = 19; - public static final int PREMIUM_FEATURE_STORIES_PRIORITY_ORDER = 20; - public static final int PREMIUM_FEATURE_STORIES_CAPTION = 21; + public final static int PREMIUM_FEATURE_STORIES_PRIORITY_ORDER = 20; + public final static int PREMIUM_FEATURE_STORIES_CAPTION = 21; public final static int PREMIUM_FEATURE_WALLPAPER = 22; public final static int PREMIUM_FEATURE_NAME_COLOR = 23; + public final static int PREMIUM_FEATURE_SAVED_TAGS = 24; + public final static int PREMIUM_FEATURE_STORIES_QUALITY = 25; + public final static int PREMIUM_FEATURE_LAST_SEEN = 26; + public final static int PREMIUM_FEATURE_MESSAGE_PRIVACY = 27; private int statusBarHeight; private int firstViewHeight; @@ -213,6 +217,8 @@ public static int serverStringToFeatureType(String s) { return PREMIUM_FEATURE_STORIES; case "stories__stealth_mode": return PREMIUM_FEATURE_STORIES_STEALTH_MODE; + case "stories__quality": + return PREMIUM_FEATURE_STORIES_QUALITY; case "stories__permanent_views_history": return PREMIUM_FEATURE_STORIES_VIEWS_HISTORY; case "stories__expiration_durations": @@ -229,6 +235,12 @@ public static int serverStringToFeatureType(String s) { return PREMIUM_FEATURE_WALLPAPER; case "peer_colors": return PREMIUM_FEATURE_NAME_COLOR; + case "saved_tags": + return PREMIUM_FEATURE_SAVED_TAGS; + case "last_seen": + return PREMIUM_FEATURE_LAST_SEEN; + case "message_privacy": + return PREMIUM_FEATURE_MESSAGE_PRIVACY; } return -1; } @@ -267,6 +279,8 @@ public static String featureTypeToServerString(int type) { return "stories"; case PREMIUM_FEATURE_STORIES_STEALTH_MODE: return "stories__stealth_mode"; + case PREMIUM_FEATURE_STORIES_QUALITY: + return "stories__quality"; case PREMIUM_FEATURE_STORIES_VIEWS_HISTORY: return "stories__permanent_views_history"; case PREMIUM_FEATURE_STORIES_EXPIRATION_DURATION: @@ -283,6 +297,12 @@ public static String featureTypeToServerString(int type) { return "wallpapers"; case PREMIUM_FEATURE_NAME_COLOR: return "peer_colors"; + case PREMIUM_FEATURE_SAVED_TAGS: + return "saved_tags"; + case PREMIUM_FEATURE_LAST_SEEN: + return "last_seen"; + case PREMIUM_FEATURE_MESSAGE_PRIVACY: + return "message_privacy"; } return null; } @@ -650,14 +670,17 @@ public static void fillPremiumFeaturesList(ArrayList premium premiumFeatures.add(new PremiumFeatureData(PREMIUM_FEATURE_REACTIONS, R.drawable.msg_premium_reactions, LocaleController.getString(R.string.PremiumPreviewReactions2), LocaleController.getString(R.string.PremiumPreviewReactions2Description))); premiumFeatures.add(new PremiumFeatureData(PREMIUM_FEATURE_STICKERS, R.drawable.msg_premium_stickers, LocaleController.getString(R.string.PremiumPreviewStickers), LocaleController.getString(R.string.PremiumPreviewStickersDescription))); premiumFeatures.add(new PremiumFeatureData(PREMIUM_FEATURE_ANIMATED_EMOJI, R.drawable.msg_premium_emoji, LocaleController.getString(R.string.PremiumPreviewEmoji), LocaleController.getString(R.string.PremiumPreviewEmojiDescription))); - premiumFeatures.add(new PremiumFeatureData(PREMIUM_FEATURE_ADVANCED_CHAT_MANAGEMENT, R.drawable.msg_premium_tools, LocaleController.getString(R.string.PremiumPreviewAdvancedChatManagement), LocaleController.getString(R.string.PremiumPreviewAdvancedChatManagementDescription))); + premiumFeatures.add(new PremiumFeatureData(PREMIUM_FEATURE_ADVANCED_CHAT_MANAGEMENT, R.drawable.menu_premium_tools, LocaleController.getString(R.string.PremiumPreviewAdvancedChatManagement), LocaleController.getString(R.string.PremiumPreviewAdvancedChatManagementDescription))); premiumFeatures.add(new PremiumFeatureData(PREMIUM_FEATURE_PROFILE_BADGE, R.drawable.msg_premium_badge, LocaleController.getString(R.string.PremiumPreviewProfileBadge), LocaleController.getString(R.string.PremiumPreviewProfileBadgeDescription))); premiumFeatures.add(new PremiumFeatureData(PREMIUM_FEATURE_ANIMATED_AVATARS, R.drawable.msg_premium_avatar, LocaleController.getString(R.string.PremiumPreviewAnimatedProfiles), LocaleController.getString(R.string.PremiumPreviewAnimatedProfilesDescription))); + premiumFeatures.add(new PremiumFeatureData(PREMIUM_FEATURE_SAVED_TAGS, R.drawable.premium_tags, applyNewSpan(LocaleController.getString(R.string.PremiumPreviewTags2)), LocaleController.getString(R.string.PremiumPreviewTagsDescription2))); premiumFeatures.add(new PremiumFeatureData(PREMIUM_FEATURE_APPLICATION_ICONS, R.drawable.msg_premium_icons, LocaleController.getString(R.string.PremiumPreviewAppIcon), LocaleController.getString(R.string.PremiumPreviewAppIconDescription))); premiumFeatures.add(new PremiumFeatureData(PREMIUM_FEATURE_EMOJI_STATUS, R.drawable.premium_status, LocaleController.getString(R.string.PremiumPreviewEmojiStatus), LocaleController.getString(R.string.PremiumPreviewEmojiStatusDescription))); premiumFeatures.add(new PremiumFeatureData(PREMIUM_FEATURE_TRANSLATIONS, R.drawable.msg_premium_translate, LocaleController.getString(R.string.PremiumPreviewTranslations), LocaleController.getString(R.string.PremiumPreviewTranslationsDescription))); - premiumFeatures.add(new PremiumFeatureData(PREMIUM_FEATURE_WALLPAPER, R.drawable.premium_wallpaper, applyNewSpan(LocaleController.getString(R.string.PremiumPreviewWallpaper)), LocaleController.getString(R.string.PremiumPreviewWallpaperDescription))); - premiumFeatures.add(new PremiumFeatureData(PREMIUM_FEATURE_NAME_COLOR, R.drawable.premium_colors, applyNewSpan(LocaleController.getString(R.string.PremiumPreviewProfileColor)), LocaleController.getString(R.string.PremiumPreviewProfileColorDescription))); + premiumFeatures.add(new PremiumFeatureData(PREMIUM_FEATURE_WALLPAPER, R.drawable.premium_wallpaper, LocaleController.getString(R.string.PremiumPreviewWallpaper), LocaleController.getString(R.string.PremiumPreviewWallpaperDescription))); + premiumFeatures.add(new PremiumFeatureData(PREMIUM_FEATURE_NAME_COLOR, R.drawable.premium_colors, LocaleController.getString(R.string.PremiumPreviewProfileColor), LocaleController.getString(R.string.PremiumPreviewProfileColorDescription))); + premiumFeatures.add(new PremiumFeatureData(PREMIUM_FEATURE_LAST_SEEN, R.drawable.menu_premium_seen, applyNewSpan(LocaleController.getString(R.string.PremiumPreviewLastSeen)), LocaleController.getString(R.string.PremiumPreviewLastSeenDescription))); + premiumFeatures.add(new PremiumFeatureData(PREMIUM_FEATURE_MESSAGE_PRIVACY, R.drawable.menu_premium_privacy, applyNewSpan(LocaleController.getString(R.string.PremiumPreviewMessagePrivacy)), LocaleController.getString(R.string.PremiumPreviewMessagePrivacyDescription))); if (messagesController.premiumFeaturesTypesToPosition.size() > 0) { for (int i = 0; i < premiumFeatures.size(); i++) { @@ -1395,6 +1418,7 @@ private void updateColors() { return; } actionBar.setItemsColor(Theme.getColor(Theme.key_premiumGradientBackgroundOverlay), false); + actionBar.setItemsColor(Theme.getColor(Theme.key_premiumGradientBackgroundOverlay), true); actionBar.setItemsBackgroundColor(ColorUtils.setAlphaComponent(Theme.getColor(Theme.key_premiumGradientBackgroundOverlay), 60), false); particlesView.drawable.updateColors(); if (backgroundView != null) { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/PrivacyControlActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/PrivacyControlActivity.java index 613cbf72f0..b6d3a573ae 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/PrivacyControlActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/PrivacyControlActivity.java @@ -421,12 +421,10 @@ public PrivacyControlActivity(int type, boolean load) { avatarForRestPhoto = userFull.fallback_photo; } } - } } - @Override public boolean onFragmentCreate() { super.onFragmentCreate(); @@ -578,6 +576,18 @@ protected void dispatchDraw(Canvas canvas) { ).show(); BotWebViewVibrationEffect.APP_ERROR.vibrate(); AndroidUtilities.shakeViewSpring(view, shakeDp = -shakeDp); + } else if (rulesType == PRIVACY_RULES_TYPE_VOICE_MESSAGES && (position == myContactsRow || position == nobodyRow) && !getUserConfig().isPremium()) { + BulletinFactory.of(this).createSimpleBulletin( + R.raw.star_premium_2, + LocaleController.getString(R.string.OptionPremiumRequiredTitle), + AndroidUtilities.replaceTags(LocaleController.getString(R.string.OptionPremiumRequiredMessage)), + LocaleController.getString(R.string.OptionPremiumRequiredButton), + () -> { + presentFragment(new PremiumPreviewFragment("settings")); + } + ).show(); + BotWebViewVibrationEffect.APP_ERROR.vibrate(); + AndroidUtilities.shakeViewSpring(view, shakeDp = -shakeDp); } else if (position == nobodyRow || position == everybodyRow || position == myContactsRow) { int newType; if (position == nobodyRow) { @@ -709,16 +719,20 @@ private void applyCurrentPrivacySettings() { TLRPC.TL_account_setGlobalPrivacySettings req2 = new TLRPC.TL_account_setGlobalPrivacySettings(); req2.settings = new TLRPC.TL_globalPrivacySettings(); TLRPC.TL_globalPrivacySettings settings = getContactsController().getGlobalPrivacySettings(); - req2.settings.archive_and_mute_new_noncontact_peers = settings.archive_and_mute_new_noncontact_peers; - req2.settings.keep_archived_folders = settings.keep_archived_folders; - req2.settings.keep_archived_unmuted = settings.keep_archived_unmuted; + if (settings != null) { + req2.settings.archive_and_mute_new_noncontact_peers = settings.archive_and_mute_new_noncontact_peers; + req2.settings.keep_archived_folders = settings.keep_archived_folders; + req2.settings.keep_archived_unmuted = settings.keep_archived_unmuted; + req2.settings.hide_read_marks = settings.hide_read_marks; + } req2.settings.new_noncontact_peers_require_premium = currentType == TYPE_CONTACTS; - req2.settings.hide_read_marks = settings.hide_read_marks; getConnectionsManager().sendRequest(req2, (response, error) -> AndroidUtilities.runOnUIThread(() -> { if (error != null) { showErrorAlert(); } else { - settings.new_noncontact_peers_require_premium = req2.settings.new_noncontact_peers_require_premium; + if (settings != null) { + settings.new_noncontact_peers_require_premium = req2.settings.new_noncontact_peers_require_premium; + } finishFragment(); getNotificationCenter().postNotificationName(NotificationCenter.privacyRulesUpdated); } @@ -944,15 +958,15 @@ private void checkPrivacy() { initialRulesSubType = currentSubType; } - updateRows(false); if (rulesType == PRIVACY_RULES_TYPE_LASTSEEN) { TLRPC.TL_globalPrivacySettings privacySettings = getContactsController().getGlobalPrivacySettings(); selectedReadValue = currentReadValue = privacySettings != null && privacySettings.hide_read_marks; } + updateRows(false); } private boolean hasChanges() { - if (rulesType == PRIVACY_RULES_TYPE_LASTSEEN && currentType != TYPE_EVERYBODY && currentReadValue != selectedReadValue) { + if (rulesType == PRIVACY_RULES_TYPE_LASTSEEN && (currentType != TYPE_EVERYBODY || currentMinus != null && !currentMinus.isEmpty()) && currentReadValue != selectedReadValue) { return true; } if (initialRulesType != currentType) { @@ -1033,7 +1047,7 @@ private void updateRows(boolean animated) { phoneContactsRow = rowCount++; } detailRow = rowCount++; - if (rulesType != PRIVACY_RULES_TYPE_MESSAGES) { + if (rulesType != PRIVACY_RULES_TYPE_MESSAGES && (rulesType != PRIVACY_RULES_TYPE_VOICE_MESSAGES || getUserConfig().isPremium())) { shareSectionRow = rowCount++; if (currentType == TYPE_NOBODY || currentType == TYPE_CONTACTS) { alwaysShareRow = rowCount++; @@ -1055,11 +1069,11 @@ private void updateRows(boolean animated) { } photoForRestDescriptionRow = rowCount++; } - if (rulesType == PRIVACY_RULES_TYPE_LASTSEEN && currentType != TYPE_EVERYBODY) { + if (rulesType == PRIVACY_RULES_TYPE_LASTSEEN && (currentType != TYPE_EVERYBODY || currentMinus != null && !currentMinus.isEmpty())) { readRow = rowCount++; readDetailRow = rowCount++; } - if (rulesType == PRIVACY_RULES_TYPE_LASTSEEN && !getUserConfig().isPremium() && !getMessagesController().premiumFeaturesBlocked()) { + if (rulesType == PRIVACY_RULES_TYPE_LASTSEEN && !getMessagesController().premiumFeaturesBlocked()) { readPremiumRow = rowCount++; readPremiumDetailRow = rowCount++; } @@ -1156,7 +1170,7 @@ private void processDone() { return; } - if (currentType != 0 && rulesType == PRIVACY_RULES_TYPE_LASTSEEN) { + if (currentType != 0 && rulesType == PRIVACY_RULES_TYPE_LASTSEEN && !getUserConfig().isPremium()) { final SharedPreferences preferences = MessagesController.getGlobalMainSettings(); boolean showed = preferences.getBoolean("privacyAlertShowed", false); if (!showed) { @@ -1361,7 +1375,7 @@ public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) { } textCell.setTextAndValue(LocaleController.getString("PrivacyP2P2", R.string.PrivacyP2P2), value, false); } else if (position == readPremiumRow) { - textCell.setText(LocaleController.getString(R.string.PrivacyLastSeenPremium), false); + textCell.setText(LocaleController.getString(getUserConfig().isPremium() ? R.string.PrivacyLastSeenPremiumForPremium : R.string.PrivacyLastSeenPremium), false); textCell.setTextColor(getThemedColor(Theme.key_windowBackgroundWhiteBlueText)); } break; @@ -1373,6 +1387,13 @@ public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) { presentFragment(new PremiumPreviewFragment("noncontacts")); })); backgroundResId = R.drawable.greydivider_bottom; + } else if (position == detailRow && rulesType == PRIVACY_RULES_TYPE_VOICE_MESSAGES) { + privacyCell.setText(LocaleController.getString(R.string.PrivacyVoiceMessagesInfo)); + if (getUserConfig().isPremium()) { + backgroundResId = R.drawable.greydivider; + } else { + backgroundResId = R.drawable.greydivider_bottom; + } } else if (position == detailRow) { if (rulesType == PRIVACY_RULES_TYPE_PHONE) { if (prevSubtypeContacts = (currentType == TYPE_NOBODY && currentSubType == 1)) { @@ -1411,10 +1432,8 @@ public void onClick(@NonNull View view) { privacyCell.setText(LocaleController.getString("WhoCanCallMeInfo", R.string.WhoCanCallMeInfo)); } else if (rulesType == PRIVACY_RULES_TYPE_INVITE) { privacyCell.setText(LocaleController.getString("WhoCanAddMeInfo", R.string.WhoCanAddMeInfo)); - } else if (rulesType == PRIVACY_RULES_TYPE_VOICE_MESSAGES) { - privacyCell.setText(LocaleController.getString(R.string.PrivacyVoiceMessagesInfo)); } else { - privacyCell.setText(LocaleController.getString("CustomHelp", R.string.CustomHelp)); + privacyCell.setText(LocaleController.getString(R.string.CustomHelp)); } backgroundResId = R.drawable.greydivider; } else if (position == shareDetailRow) { @@ -1456,7 +1475,7 @@ public void onClick(@NonNull View view) { privacyCell.setText(LocaleController.getString(R.string.HideReadTimeInfo)); backgroundResId = readPremiumDetailRow == -1 ? R.drawable.greydivider_bottom : R.drawable.greydivider; } else if (position == readPremiumDetailRow) { - privacyCell.setText(LocaleController.getString(R.string.PrivacyLastSeenPremiumInfo)); + privacyCell.setText(LocaleController.getString(getUserConfig().isPremium() ? R.string.PrivacyLastSeenPremiumInfoForPremium : R.string.PrivacyLastSeenPremiumInfo)); backgroundResId = R.drawable.greydivider_bottom; } if (backgroundResId != 0) { @@ -1509,17 +1528,20 @@ public void onClick(@NonNull View view) { radioCell.setText(LocaleController.getString("LastSeenEverybody", R.string.LastSeenEverybody), currentType == TYPE_EVERYBODY, true); } } else if (position == myContactsRow) { + if ((rulesType == PRIVACY_RULES_TYPE_VOICE_MESSAGES || rulesType == PRIVACY_RULES_TYPE_MESSAGES) && !getUserConfig().isPremium()) { + radioCell.setRadioIcon(getContext().getResources().getDrawable(R.drawable.mini_switch_lock).mutate()); + } if (rulesType == PRIVACY_RULES_TYPE_P2P) { radioCell.setText(LocaleController.getString("P2PContacts", R.string.P2PContacts), currentType == TYPE_CONTACTS, nobodyRow != -1); } else if (rulesType == PRIVACY_RULES_TYPE_MESSAGES) { - if (!getUserConfig().isPremium()) { - radioCell.setRadioIcon(getContext().getResources().getDrawable(R.drawable.mini_switch_lock).mutate()); - } radioCell.setText(LocaleController.getString(R.string.PrivacyMessagesContactsAndPremium), currentType == TYPE_CONTACTS, nobodyRow != -1); } else { radioCell.setText(LocaleController.getString("LastSeenContacts", R.string.LastSeenContacts), currentType == TYPE_CONTACTS, nobodyRow != -1); } } else { + if ((rulesType == PRIVACY_RULES_TYPE_VOICE_MESSAGES || rulesType == PRIVACY_RULES_TYPE_MESSAGES) && !getUserConfig().isPremium()) { + radioCell.setRadioIcon(getContext().getResources().getDrawable(R.drawable.mini_switch_lock).mutate()); + } if (rulesType == PRIVACY_RULES_TYPE_P2P) { radioCell.setText(LocaleController.getString("P2PNobody", R.string.P2PNobody), currentType == TYPE_NOBODY, false); } else { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/PrivacySettingsActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/PrivacySettingsActivity.java index 6d97dcb0b7..9b8ea9502e 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/PrivacySettingsActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/PrivacySettingsActivity.java @@ -8,12 +8,20 @@ package org.telegram.ui; +import static org.telegram.messenger.AndroidUtilities.dp; + import android.content.Context; import android.content.DialogInterface; import android.graphics.PorterDuff; import android.graphics.PorterDuffColorFilter; +import android.graphics.drawable.Drawable; +import android.text.Spannable; +import android.text.SpannableString; import android.text.SpannableStringBuilder; +import android.text.Spanned; import android.text.TextUtils; +import android.text.style.DynamicDrawableSpan; +import android.text.style.ImageSpan; import android.view.HapticFeedbackConstants; import android.view.View; import android.view.ViewGroup; @@ -51,9 +59,11 @@ import org.telegram.ui.Cells.TextInfoPrivacyCell; import org.telegram.ui.Cells.TextSettingsCell; import org.telegram.ui.Components.AlertsCreator; +import org.telegram.ui.Components.AnimatedEmojiDrawable; import org.telegram.ui.Components.Bulletin; import org.telegram.ui.Components.BulletinFactory; import org.telegram.ui.Components.LayoutHelper; +import org.telegram.ui.Components.Premium.PremiumGradient; import org.telegram.ui.Components.RecyclerListView; import org.telegram.ui.Components.TextStyleSpan; @@ -299,7 +309,7 @@ public boolean supportsPredictiveItemAnimations() { for (int a = 0; a < items.length; a++) { RadioColorCell cell = new RadioColorCell(getParentActivity()); - cell.setPadding(AndroidUtilities.dp(4), 0, AndroidUtilities.dp(4), 0); + cell.setPadding(dp(4), 0, dp(4), 0); cell.setTag(a); cell.setCheckColor(Theme.getColor(Theme.key_radioBackground), Theme.getColor(Theme.key_dialogRadioBackgroundChecked)); cell.setTextAndValue(items[a], selected == a); @@ -356,17 +366,6 @@ public boolean supportsPredictiveItemAnimations() { } else if (position == forwardsRow) { presentFragment(new PrivacyControlActivity(ContactsController.PRIVACY_RULES_TYPE_FORWARDS)); } else if (position == voicesRow) { - if (!getUserConfig().isPremium()) { - try { - if (!NekoConfig.disableVibration.Bool()) - fragmentView.performHapticFeedback(HapticFeedbackConstants.KEYBOARD_TAP, HapticFeedbackConstants.FLAG_IGNORE_GLOBAL_SETTING); - } catch (Exception e) { - FileLog.e(e); - } - BulletinFactory.of(this).createRestrictVoiceMessagesPremiumBulletin().show(); - return; - } - presentFragment(new PrivacyControlActivity(ContactsController.PRIVACY_RULES_TYPE_VOICE_MESSAGES)); } else if (position == noncontactsRow) { presentFragment(new PrivacyControlActivity(ContactsController.PRIVACY_RULES_TYPE_MESSAGES)); @@ -523,7 +522,7 @@ public boolean supportsPredictiveItemAnimations() { CheckBoxCell checkBoxCell = new CheckBoxCell(getParentActivity(), 1, 21, null); checkBoxCell.setTag(a); checkBoxCell.setBackgroundDrawable(Theme.getSelectorDrawable(false)); - checkBoxCell.setPadding(AndroidUtilities.dp(4), 0, AndroidUtilities.dp(4), 0); + checkBoxCell.setPadding(dp(4), 0, dp(4), 0); linearLayout.addView(checkBoxCell, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, 50)); checkBoxCell.setText(name, null, true, false); checkBoxCell.setTextColor(Theme.getColor(Theme.key_dialogTextBlack)); @@ -1016,19 +1015,12 @@ public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) { } else { value = formatRulesString(getAccountInstance(), ContactsController.PRIVACY_RULES_TYPE_VOICE_MESSAGES); } - textCell.setTextAndValue(LocaleController.getString(R.string.PrivacyVoiceMessages), value, noncontactsRow != -1); + textCell.setTextAndValue(addPremiumStar(LocaleController.getString(R.string.PrivacyVoiceMessages)), value, noncontactsRow != -1); ImageView imageView = textCell.getValueImageView(); - if (!getUserConfig().isPremium()) { - imageView.setVisibility(View.VISIBLE); - imageView.setImageResource(R.drawable.msg_mini_premiumlock); - imageView.setTranslationY(AndroidUtilities.dp(1)); - imageView.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_windowBackgroundWhiteValueText), PorterDuff.Mode.MULTIPLY)); - } else { - imageView.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_windowBackgroundWhiteGrayIcon), PorterDuff.Mode.MULTIPLY)); - } + imageView.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_windowBackgroundWhiteGrayIcon), PorterDuff.Mode.MULTIPLY)); } else if (position == noncontactsRow) { value = LocaleController.getString(noncontactsValue ? R.string.ContactsAndPremium : R.string.P2PEverybody); - textCell.setTextAndValue(LocaleController.getString(R.string.PrivacyMessages), value, false); + textCell.setTextAndValue(addPremiumStar(LocaleController.getString(R.string.PrivacyMessages)), value, false); } else if (position == passportRow) { textCell.setText(LocaleController.getString("TelegramPassport", R.string.TelegramPassport), true); } else if (position == deleteAccountRow) { @@ -1234,6 +1226,20 @@ public int getItemViewType(int position) { } } + private SpannableString premiumStar; + private CharSequence addPremiumStar(String text) { + if (!getUserConfig().isPremium()) { + return text; + } + if (premiumStar == null) { + premiumStar = new SpannableString("★"); + Drawable drawable = new AnimatedEmojiDrawable.WrapSizeDrawable(PremiumGradient.getInstance().premiumStarMenuDrawable, dp(18), dp(18)); + drawable.setBounds(0, 0, dp(18), dp(18)); + premiumStar.setSpan(new ImageSpan(drawable, DynamicDrawableSpan.ALIGN_CENTER), 0, premiumStar.length(), Spanned.SPAN_INCLUSIVE_EXCLUSIVE); + } + return new SpannableStringBuilder(text).append("  ").append(premiumStar); + } + @Override public ArrayList getThemeDescriptions() { ArrayList themeDescriptions = new ArrayList<>(); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ProfileActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/ProfileActivity.java index 29087e6411..9c505eacd0 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ProfileActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ProfileActivity.java @@ -167,6 +167,7 @@ import org.telegram.ui.ActionBar.BackDrawable; import org.telegram.ui.ActionBar.BaseFragment; import org.telegram.ui.ActionBar.INavigationLayout; +import org.telegram.ui.ActionBar.OKLCH; import org.telegram.ui.ActionBar.SimpleTextView; import org.telegram.ui.ActionBar.Theme; import org.telegram.ui.ActionBar.ThemeDescription; @@ -2055,11 +2056,11 @@ protected void onLayout(boolean changed, int left, int top, int right, int botto updateStoriesViewBounds(false); } }; - actionBar.setColorFilterMode(PorterDuff.Mode.SRC_IN); actionBar.setForceSkipTouches(true); actionBar.setBackgroundColor(Color.TRANSPARENT); actionBar.setItemsBackgroundColor(peerColor != null ? 0x20ffffff : getThemedColor(Theme.key_avatar_actionBarSelectorBlue), false); actionBar.setItemsColor(getThemedColor(Theme.key_actionBarDefaultIcon), false); + actionBar.setItemsColor(getThemedColor(Theme.key_actionBarDefaultIcon), true); actionBar.setBackButtonDrawable(new BackDrawable(false)); actionBar.setCastShadows(false); actionBar.setAddToContainer(false); @@ -3114,17 +3115,10 @@ protected void onDetachedFromWindow() { protected int processColor(int color) { return applyPeerColor(color, false); } - @Override protected void onSelectedTabChanged() { updateSelectedMediaTabText(); } - - @Override - protected boolean canShowSearchItem() { - return mediaHeaderVisible; - } - @Override protected boolean includeSavedDialogs() { return dialogId == getUserConfig().getClientUserId() && !saved; @@ -3211,6 +3205,9 @@ public void onTextChanged(EditText editText) { searchItem.setContentDescription(LocaleController.getString("SearchInSettings", R.string.SearchInSettings)); searchItem.setSearchFieldHint(LocaleController.getString("SearchInSettings", R.string.SearchInSettings)); sharedMediaLayout.getSearchItem().setVisibility(View.GONE); + if (sharedMediaLayout.getSearchOptionsItem() != null) { + sharedMediaLayout.getSearchOptionsItem().setVisibility(View.GONE); + } if (expandPhoto) { searchItem.setVisibility(View.GONE); } @@ -4031,8 +4028,7 @@ public boolean onItemClick(View view, int position) { BuildVars.DEBUG_VERSION ? (SharedConfig.useSurfaceInStories ? "back to TextureView in stories" : "use SurfaceView in stories") : null, BuildVars.DEBUG_PRIVATE_VERSION ? (SharedConfig.photoViewerBlur ? "do not blur in photoviewer" : "blur in photoviewer") : null, !SharedConfig.payByInvoice ? "Enable Invoice Payment" : "Disable Invoice Payment", - BuildVars.DEBUG_PRIVATE_VERSION ? "Update Attach Bots" : null, - BuildVars.DEBUG_PRIVATE_VERSION ? ((SharedConfig.forceLessData ? "Disable using less data" : "Use less data on stories") + (ApplicationLoader.isConnectionSlow() ? " (connection is already slow)" : "")) : null + BuildVars.DEBUG_PRIVATE_VERSION ? "Update Attach Bots" : null }; builder.setItems(items, (dialog, which) -> { @@ -4066,7 +4062,7 @@ public boolean onItemClick(View view, int position) { getMessagesStorage().clearSentMedia(); SharedConfig.setNoSoundHintShowed(false); SharedPreferences.Editor editor = MessagesController.getGlobalMainSettings().edit(); - editor.remove("archivehint").remove("proximityhint").remove("archivehint_l").remove("speedhint").remove("gifhint").remove("reminderhint").remove("soundHint").remove("themehint").remove("bganimationhint").remove("filterhint").remove("n_0").remove("storyprvhint").remove("storyhint").remove("storyhint2").remove("storydualhint").remove("storysvddualhint").remove("stories_camera").remove("dualcam").remove("dualmatrix").remove("dual_available").remove("archivehint").remove("askNotificationsAfter").remove("askNotificationsDuration").remove("viewoncehint").remove("taptostorysoundhint").remove("nothanos").remove("voiceoncehint").remove("savedhint").apply(); + editor.remove("archivehint").remove("proximityhint").remove("archivehint_l").remove("speedhint").remove("gifhint").remove("reminderhint").remove("soundHint").remove("themehint").remove("bganimationhint").remove("filterhint").remove("n_0").remove("storyprvhint").remove("storyhint").remove("storyhint2").remove("storydualhint").remove("storysvddualhint").remove("stories_camera").remove("dualcam").remove("dualmatrix").remove("dual_available").remove("archivehint").remove("askNotificationsAfter").remove("askNotificationsDuration").remove("viewoncehint").remove("taptostorysoundhint").remove("nothanos").remove("voiceoncehint").remove("savedhint").remove("savedsearchhint").remove("savedsearchtaghint").apply(); MessagesController.getEmojiSettings(currentAccount).edit().remove("featured_hidden").remove("emoji_featured_hidden").commit(); SharedConfig.textSelectionHintShows = 0; SharedConfig.lockRecordAudioVideoHint = 0; @@ -4092,7 +4088,7 @@ public boolean onItemClick(View view, int position) { } else if (which == 8) { SharedConfig.toggleRoundCamera16to9(); } else if (which == 9) { - ((LaunchActivity) getParentActivity()).checkAppUpdate(true); + ((LaunchActivity) getParentActivity()).checkAppUpdate(true, null); } else if (which == 10) { getMessagesStorage().readAllDialogs(-1); } else if (which == 11) { @@ -4323,8 +4319,6 @@ protected void onSend(LongSparseArray dids, int count, TLRPC.TL_fo SharedConfig.togglePaymentByInvoice(); } else if (which == 26) { getMediaDataController().loadAttachMenuBots(false, true); - } else if (which == 27) { - SharedConfig.setForceLessData(!SharedConfig.forceLessData); } }); builder.setNegativeButton(LocaleController.getString("Cancel", R.string.Cancel), null); @@ -6527,6 +6521,7 @@ private void setMediaHeaderVisible(boolean visible) { headerShadowAnimatorSet.cancel(); } ActionBarMenuItem mediaSearchItem = sharedMediaLayout.getSearchItem(); + ImageView mediaOptionsItem = sharedMediaLayout.getSearchOptionsItem(); if (!mediaHeaderVisible) { if (callItemVisible) { callItem.setVisibility(View.VISIBLE); @@ -6541,14 +6536,22 @@ private void setMediaHeaderVisible(boolean visible) { eventLogItem.setVisibility(View.VISIBLE); } otherItem.setVisibility(View.VISIBLE); + if (mediaOptionsItem != null) { + mediaOptionsItem.setVisibility(View.GONE); + } } else { if (sharedMediaLayout.isSearchItemVisible()) { mediaSearchItem.setVisibility(View.VISIBLE); } + if (mediaOptionsItem != null) { + mediaOptionsItem.setVisibility(View.VISIBLE); + } if (sharedMediaLayout.isCalendarItemVisible()) { sharedMediaLayout.photoVideoOptionsItem.setVisibility(View.VISIBLE); + sharedMediaLayout.animateSearchToOptions(true, false); } else { sharedMediaLayout.photoVideoOptionsItem.setVisibility(View.INVISIBLE); + sharedMediaLayout.animateSearchToOptions(false, false); } } updateStoriesViewBounds(false); @@ -7786,9 +7789,9 @@ public void onTransitionAnimationStart(boolean isOpen, boolean backward) { } if (isOpen) { if (imageUpdater != null) { - transitionIndex = getNotificationCenter().setAnimationInProgress(transitionIndex, new int[]{NotificationCenter.dialogsNeedReload, NotificationCenter.closeChats, NotificationCenter.mediaCountDidLoad, NotificationCenter.mediaCountsDidLoad, NotificationCenter.userInfoDidLoad}); + transitionIndex = getNotificationCenter().setAnimationInProgress(transitionIndex, new int[]{NotificationCenter.dialogsNeedReload, NotificationCenter.closeChats, NotificationCenter.mediaCountDidLoad, NotificationCenter.mediaCountsDidLoad, NotificationCenter.userInfoDidLoad, NotificationCenter.needCheckSystemBarColors}); } else { - transitionIndex = getNotificationCenter().setAnimationInProgress(transitionIndex, new int[]{NotificationCenter.dialogsNeedReload, NotificationCenter.closeChats, NotificationCenter.mediaCountDidLoad, NotificationCenter.mediaCountsDidLoad}); + transitionIndex = getNotificationCenter().setAnimationInProgress(transitionIndex, new int[]{NotificationCenter.dialogsNeedReload, NotificationCenter.closeChats, NotificationCenter.mediaCountDidLoad, NotificationCenter.mediaCountsDidLoad, NotificationCenter.needCheckSystemBarColors}); } if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP && !backward && getParentActivity() != null) { navigationBarAnimationColorFrom = getParentActivity().getWindow().getNavigationBarColor(); @@ -8927,7 +8930,7 @@ private void updateProfileData(boolean reload) { } else { isOnline[0] = false; newString2 = LocaleController.formatUserStatus(currentAccount, user, isOnline, shortStatus ? new boolean[1] : null); - hiddenStatusButton = user != null && !getUserConfig().isPremium() && user.status != null && user.status.by_me; + hiddenStatusButton = user != null && !isOnline[0] && !getUserConfig().isPremium() && user.status != null && (user.status instanceof TLRPC.TL_userStatusRecently || user.status instanceof TLRPC.TL_userStatusLastMonth || user.status instanceof TLRPC.TL_userStatusLastWeek) && user.status.by_me; if (onlineTextView[1] != null && !mediaHeaderVisible) { int key = isOnline[0] && peerColor == null ? Theme.key_profile_status : Theme.key_avatar_subtitleInProfileBlue; onlineTextView[1].setTag(key); @@ -9430,6 +9433,7 @@ private void updateProfileData(boolean reload) { } private void updatedPeerColor() { + adaptedColors.clear(); if (topView != null) { topView.setBackgroundColorId(peerColor, true); } @@ -9475,6 +9479,8 @@ private void updatedPeerColor() { ((TextDetailCell) view).valueTextView.setTextColor(applyPeerColor(getThemedColor(Theme.key_windowBackgroundWhiteGrayText2), false)); } else if (view instanceof TextCell) { ((TextCell) view).updateColors(); + } else if (view instanceof AboutLinkCell) { + ((AboutLinkCell) view).updateColors(); } else if (view instanceof NotificationsCheckCell) { ((NotificationsCheckCell) view).getCheckBox().invalidate(); } @@ -9494,9 +9500,21 @@ private int applyPeerColor(int color, boolean actionBar) { return applyPeerColor(color, actionBar, null); } + private final SparseIntArray adaptedColors = new SparseIntArray(); private int applyPeerColor(int color, boolean actionBar, Boolean online) { if (!actionBar) return color; if (peerColor != null) { + if (!actionBar) { + int index = adaptedColors.indexOfKey(color); + if (index < 0) { + final int baseColor = Theme.adaptHSV(peerColor.getBgColor1(Theme.isCurrentThemeDark()), Theme.isCurrentThemeDark() ? 0 : +.05f, Theme.isCurrentThemeDark() ? -.1f : -.04f); + int adapted = OKLCH.adapt(color, baseColor); + adaptedColors.put(color, adapted); + return adapted; + } else { + return adaptedColors.valueAt(index); + } + } final int baseColor = getThemedColor(actionBar ? Theme.key_actionBarDefault : Theme.key_windowBackgroundWhiteBlueIcon); final int storyColor = ColorUtils.blendARGB(peerColor.getStoryColor1(Theme.isCurrentThemeDark()), peerColor.getStoryColor2(Theme.isCurrentThemeDark()), .5f); int accentColor = actionBar ? storyColor : peerColor.getBgColor1(Theme.isCurrentThemeDark()); @@ -10466,6 +10484,11 @@ protected void didResizeEnd() { protected void didResizeStart() { layoutManager.mIgnoreTopPadding = true; } + + @Override + protected int processColor(int color) { + return applyPeerColor(color, false); + } }; break; } @@ -10796,7 +10819,6 @@ public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) { detailCell.setImageClickListener(null); } detailCell.setTag(position); - detailCell.valueTextView.setTextColor(applyPeerColor(getThemedColor(Theme.key_windowBackgroundWhiteGrayText2), false)); break; case VIEW_TYPE_ABOUT_LINK: AboutLinkCell aboutLinkCell = (AboutLinkCell) holder.itemView; @@ -10885,7 +10907,8 @@ public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) { } } else if (position == addMemberRow) { textCell.setColors(Theme.key_windowBackgroundWhiteBlueIcon, Theme.key_windowBackgroundWhiteBlueButton); - textCell.setTextAndIcon(LocaleController.getString("AddMember", R.string.AddMember), R.drawable.msg_contact_add, membersSectionRow == -1); + boolean isNextPositionMember = position + 1 >= membersStartRow && position + 1 < membersEndRow; + textCell.setTextAndIcon(LocaleController.getString("AddMember", R.string.AddMember), R.drawable.msg_contact_add, membersSectionRow == -1 || isNextPositionMember); } else if (position == sendMessageRow) { textCell.setText(LocaleController.getString("SendMessageLocation", R.string.SendMessageLocation), true); } else if (position == addToContactsRow) { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/SelectAnimatedEmojiDialog.java b/TMessagesProj/src/main/java/org/telegram/ui/SelectAnimatedEmojiDialog.java index 53458fb50f..2f6e29f7c6 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/SelectAnimatedEmojiDialog.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/SelectAnimatedEmojiDialog.java @@ -149,6 +149,7 @@ public class SelectAnimatedEmojiDialog extends FrameLayout implements Notificati public final static int TYPE_EXPANDABLE_REACTIONS = 8; public final static int TYPE_EMOJI_STATUS_CHANNEL = 9; public final static int TYPE_EMOJI_STATUS_CHANNEL_TOP = 10; + public final static int TYPE_TAGS = 11; public boolean isBottom() { return type == TYPE_SET_REPLY_ICON || type == TYPE_EMOJI_STATUS_CHANNEL_TOP; @@ -689,7 +690,7 @@ public void onScrolled(int dx, int dy) { updateTabsPosition(layoutManager.findFirstCompletelyVisibleItemPosition()); } updateSearchBox(); - AndroidUtilities.updateViewVisibilityAnimated(emojiTabsShadow, emojiGridView.computeVerticalScrollOffset() != 0 || type == TYPE_EMOJI_STATUS || type == TYPE_EMOJI_STATUS_CHANNEL_TOP || type == TYPE_REACTIONS || type == TYPE_CHAT_REACTIONS, 1f, true); + AndroidUtilities.updateViewVisibilityAnimated(emojiTabsShadow, emojiGridView.computeVerticalScrollOffset() != 0 || type == TYPE_EMOJI_STATUS || type == TYPE_EMOJI_STATUS_CHANNEL_TOP || type == TYPE_REACTIONS || type == TYPE_TAGS || type == TYPE_CHAT_REACTIONS, 1f, true); invalidateParent(); } @@ -823,7 +824,7 @@ public void onScrolled(int dx, int dy) { TextView emptyViewText = new TextView(context); if (type == TYPE_AVATAR_CONSTRUCTOR) { emptyViewText.setText(LocaleController.getString("NoEmojiOrStickersFound", R.string.NoEmojiOrStickersFound)); - } else if (type == TYPE_EMOJI_STATUS || type == TYPE_EMOJI_STATUS_CHANNEL || type == TYPE_EMOJI_STATUS_CHANNEL_TOP) { + } else if (type == TYPE_EMOJI_STATUS || type == TYPE_TAGS || type == TYPE_EMOJI_STATUS_CHANNEL || type == TYPE_EMOJI_STATUS_CHANNEL_TOP) { emptyViewText.setText(LocaleController.getString("NoEmojiFound", R.string.NoEmojiFound)); } else if (type == TYPE_REACTIONS || type == TYPE_SET_DEFAULT_REACTION) { emptyViewText.setText(LocaleController.getString("NoReactionsFound", R.string.NoReactionsFound)); @@ -896,6 +897,7 @@ public void onEndAnimation() { RecyclerListView.OnItemLongClickListenerExtended onItemLongClick = new RecyclerListView.OnItemLongClickListenerExtended() { @Override public boolean onItemClick(View view, int position, float x, float y) { + if (type == TYPE_TAGS) return false; if (view instanceof ImageViewEmoji && (type == TYPE_REACTIONS || type == TYPE_EXPANDABLE_REACTIONS)) { incrementHintUse(); if (!NekoConfig.disableVibration.Bool()) @@ -1004,7 +1006,7 @@ public void onAnimationEnd(Animator animation) { } else { onEmojiClick(viewEmoji, viewEmoji.span); } - if (type != TYPE_REACTIONS) { + if (type != TYPE_REACTIONS && type != TYPE_TAGS) { try { if (!NekoConfig.disableVibration.Bool()) performHapticFeedback(HapticFeedbackConstants.KEYBOARD_TAP, HapticFeedbackConstants.FLAG_IGNORE_VIEW_SETTING); @@ -1012,7 +1014,7 @@ public void onAnimationEnd(Animator animation) { } } else if (view instanceof ImageView) { onEmojiClick(view, null); - if (type != TYPE_REACTIONS) { + if (type != TYPE_REACTIONS && type != TYPE_TAGS) { try { if (!NekoConfig.disableVibration.Bool()) performHapticFeedback(HapticFeedbackConstants.KEYBOARD_TAP, HapticFeedbackConstants.FLAG_IGNORE_VIEW_SETTING); @@ -1021,7 +1023,7 @@ public void onAnimationEnd(Animator animation) { } else if (view instanceof EmojiPackExpand) { EmojiPackExpand button = (EmojiPackExpand) view; expand(position, button); - if (type != TYPE_REACTIONS) { + if (type != TYPE_REACTIONS && type != TYPE_TAGS) { try { if (!NekoConfig.disableVibration.Bool()) performHapticFeedback(HapticFeedbackConstants.KEYBOARD_TAP, HapticFeedbackConstants.FLAG_IGNORE_VIEW_SETTING); @@ -1740,7 +1742,7 @@ public void search(String query, boolean liftUp, boolean delay) { if (result.get(i).emoji.startsWith("animated_")) { documentIds.add(Long.parseLong(result.get(i).emoji.substring(9))); } else { - if (type == TYPE_REACTIONS || type == TYPE_SET_DEFAULT_REACTION) { + if (type == TYPE_REACTIONS || type == TYPE_TAGS || type == TYPE_SET_DEFAULT_REACTION) { TLRPC.TL_availableReaction reaction = availableReactions.get(result.get(i).emoji); if (reaction != null) { reactions.add(ReactionsLayoutInBubble.VisibleReaction.fromEmojicon(reaction)); @@ -1878,7 +1880,7 @@ public void search(String query, boolean liftUp, boolean delay) { stickersSearchResult.clear(); } emojiSearchGridView.scrollToPosition(0); - if (type == TYPE_REACTIONS || type == TYPE_SET_DEFAULT_REACTION) { + if (type == TYPE_REACTIONS || type == TYPE_TAGS || type == TYPE_SET_DEFAULT_REACTION) { if (!reactions.isEmpty()) { searchResult.addAll(reactions); } else { @@ -2554,7 +2556,7 @@ private boolean enterAnimationInProgress() { } private void clearRecent() { - if (type == TYPE_REACTIONS && onRecentClearedListener != null) { + if ((type == TYPE_REACTIONS || type == TYPE_TAGS) && onRecentClearedListener != null) { onRecentClearedListener.onRecentCleared(); } } @@ -3073,9 +3075,7 @@ public void setSticker(TLRPC.Document document, View parent) { createImageReceiver(parent); SvgHelper.SvgDrawable svgThumb = DocumentObject.getSvgThumb(document, Theme.key_windowBackgroundWhiteGrayIcon, 0.2f); if (type == TYPE_CHAT_REACTIONS) { - TLRPC.PhotoSize thumb = FileLoader.getClosestPhotoSizeWithSize(document.thumbs, 90); - ImageLocation thumbLocation = ImageLocation.getForDocument(thumb, document); - imageReceiver.setImage(ImageLocation.getForDocument(document), !LiteMode.isEnabled(LiteMode.FLAG_ANIMATED_EMOJI_KEYBOARD) ? "34_34_firstframe" : "34_34", thumbLocation, null, svgThumb, document.size, null, document, 0); + imageReceiver.setImage(ImageLocation.getForDocument(document), !LiteMode.isEnabled(LiteMode.FLAG_ANIMATED_EMOJI_KEYBOARD) ? "34_34_firstframe" : "34_34", null, null, svgThumb, document.size, null, document, 0); } else { imageReceiver.setImage(ImageLocation.getForDocument(document), "100_100_firstframe", null, null, svgThumb, 0, "tgs", document, 0); } @@ -3172,7 +3172,7 @@ public void preload(int type, int account) { return; } MediaDataController.getInstance(account).checkStickers(MediaDataController.TYPE_EMOJIPACKS); - if (type == TYPE_REACTIONS || type == TYPE_SET_DEFAULT_REACTION || type == TYPE_CHAT_REACTIONS) { + if (type == TYPE_REACTIONS || type == TYPE_TAGS || type == TYPE_SET_DEFAULT_REACTION || type == TYPE_CHAT_REACTIONS) { MediaDataController.getInstance(account).checkReactions(); } else if (type == TYPE_EMOJI_STATUS_CHANNEL || type == TYPE_EMOJI_STATUS_CHANNEL_TOP) { if (MessagesController.getInstance(account).getMainSettings().getBoolean("resetemojipacks", true)) { @@ -3343,7 +3343,7 @@ private void updateRows(boolean updateEmojipacks, boolean animated, boolean diff } - if (includeHint && type != TYPE_SET_DEFAULT_REACTION && type != TYPE_TOPIC_ICON && type != TYPE_CHAT_REACTIONS && type != TYPE_EXPANDABLE_REACTIONS && type != TYPE_AVATAR_CONSTRUCTOR && type != TYPE_SET_REPLY_ICON && type != TYPE_SET_REPLY_ICON_BOTTOM) { + if (includeHint && type != TYPE_SET_DEFAULT_REACTION && type != TYPE_TAGS && type != TYPE_TOPIC_ICON && type != TYPE_CHAT_REACTIONS && type != TYPE_EXPANDABLE_REACTIONS && type != TYPE_AVATAR_CONSTRUCTOR && type != TYPE_SET_REPLY_ICON && type != TYPE_SET_REPLY_ICON_BOTTOM) { longtapHintRow = totalCount++; rowHashCodes.add(6L); } @@ -3359,7 +3359,7 @@ private void updateRows(boolean updateEmojipacks, boolean animated, boolean diff if (recentReactionsToSet != null) { topReactionsStartRow = totalCount; ArrayList tmp = new ArrayList<>(recentReactionsToSet); - if (type == TYPE_EXPANDABLE_REACTIONS) { + if (type == TYPE_EXPANDABLE_REACTIONS || type == TYPE_TAGS) { topReactions.addAll(tmp); } else { for (int i = 0; i < 16; i++) { @@ -3374,7 +3374,7 @@ private void updateRows(boolean updateEmojipacks, boolean animated, boolean diff totalCount += topReactions.size(); topReactionsEndRow = totalCount; - if (!tmp.isEmpty() && type != TYPE_EXPANDABLE_REACTIONS) { + if (!tmp.isEmpty() && type != TYPE_EXPANDABLE_REACTIONS && type != TYPE_TAGS) { boolean allRecentReactionsIsDefault = true; for (int i = 0; i < tmp.size(); i++) { if (tmp.get(i).documentId != 0) { @@ -4740,7 +4740,7 @@ private void createCategoriesListView() { if (categoriesListView != null || getContext() == null) { return; } - if (type != TYPE_REACTIONS && type != TYPE_SET_DEFAULT_REACTION && type != TYPE_EMOJI_STATUS && type != TYPE_AVATAR_CONSTRUCTOR) { + if (type != TYPE_REACTIONS && type != TYPE_TAGS && type != TYPE_SET_DEFAULT_REACTION && type != TYPE_EMOJI_STATUS && type != TYPE_AVATAR_CONSTRUCTOR) { return; } @@ -4753,6 +4753,7 @@ private void createCategoriesListView() { categoriesType = StickerCategoriesListView.CategoriesType.PROFILE_PHOTOS; break; case TYPE_REACTIONS: + case TYPE_TAGS: default: categoriesType = StickerCategoriesListView.CategoriesType.DEFAULT; break; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/StatisticActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/StatisticActivity.java index 04c665a528..3f31757d80 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/StatisticActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/StatisticActivity.java @@ -789,6 +789,7 @@ public void onItemClick(final int id) { avatarContainer.setTitleColors(Theme.getColor(Theme.key_player_actionBarTitle), Theme.getColor(Theme.key_player_actionBarSubtitle)); actionBar.setItemsColor(Theme.getColor(Theme.key_player_actionBarTitle), false); + actionBar.setItemsColor(Theme.getColor(Theme.key_player_actionBarTitle), true); actionBar.setItemsBackgroundColor(Theme.getColor(Theme.key_actionBarActionModeDefaultSelector), false); actionBar.setBackgroundColor(Theme.getColor(Theme.key_windowBackgroundWhite)); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Stories/PeerStoriesView.java b/TMessagesProj/src/main/java/org/telegram/ui/Stories/PeerStoriesView.java index ce34313c4e..41c743ae22 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Stories/PeerStoriesView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Stories/PeerStoriesView.java @@ -12,6 +12,7 @@ import android.content.Context; import android.content.DialogInterface; import android.content.Intent; +import android.content.SharedPreferences; import android.graphics.Bitmap; import android.graphics.Canvas; import android.graphics.Color; @@ -109,6 +110,7 @@ import org.telegram.ui.AvatarSpan; import org.telegram.ui.Cells.TextSelectionHelper; import org.telegram.ui.ChatActivity; +import org.telegram.ui.ChooseSpeedLayout; import org.telegram.ui.Components.AlertsCreator; import org.telegram.ui.Components.AnimatedEmojiDrawable; import org.telegram.ui.Components.AnimatedEmojiSpan; @@ -152,6 +154,7 @@ import org.telegram.ui.Components.ScaleStateListAnimator; import org.telegram.ui.Components.ShareAlert; import org.telegram.ui.Components.SizeNotifierFrameLayout; +import org.telegram.ui.Components.SpeedIconDrawable; import org.telegram.ui.Components.TextStyleSpan; import org.telegram.ui.Components.TranslateAlert2; import org.telegram.ui.Components.URLSpanMono; @@ -167,6 +170,7 @@ import org.telegram.ui.PinchToZoomHelper; import org.telegram.ui.PremiumPreviewFragment; import org.telegram.ui.ProfileActivity; +import org.telegram.ui.Stories.recorder.ButtonWithCounterView; import org.telegram.ui.Stories.recorder.CaptionContainerView; import org.telegram.ui.Stories.recorder.HintView2; import org.telegram.ui.Stories.recorder.StoryEntry; @@ -361,6 +365,9 @@ public class PeerStoriesView extends SizeNotifierFrameLayout implements Notifica private float viewsThumbPivotY; private boolean userCanSeeViews; + private ChooseSpeedLayout speedLayout; + private ActionBarMenuSubItem speedItem; + public PeerStoriesView(@NonNull Context context, StoryViewer storyViewer, SharedResources sharedResources, Theme.ResourcesProvider resourcesProvider) { super(context); pinchToZoomHelper.setCallback(new PinchToZoomHelper.Callback() { @@ -1144,7 +1151,10 @@ protected boolean verifyDrawable(@NonNull Drawable who) { MessagesController.getInstance(currentAccount).getStoriesController().loadSendAs(); MessagesController.getInstance(currentAccount).getStoriesController().getDraftsController().load(); } - popupMenu = new CustomPopupMenu(getContext(), resourcesProvider, isSelf) { + final boolean userCanEditStory = isSelf || MessagesController.getInstance(currentAccount).getStoriesController().canEditStory(currentStory.storyItem); + final boolean canEditStory = isSelf || (isChannel && userCanEditStory); + final boolean speedControl = currentStory.isVideo; + popupMenu = new CustomPopupMenu(getContext(), resourcesProvider, speedControl) { private boolean edit; private void addViewStatistics(ActionBarPopupWindow.ActionBarPopupWindowLayout popupLayout, TL_stories.StoryItem storyItem) { @@ -1181,10 +1191,61 @@ public boolean isLightStatusBar() { } } + private void addSpeedLayout(ActionBarPopupWindow.ActionBarPopupWindowLayout popupLayout, boolean addGap) { + if (!speedControl || currentStory != null && currentStory.uploadingStory != null) { + speedLayout = null; + speedItem = null; + return; + } + + speedLayout = new ChooseSpeedLayout(getContext(), popupLayout.getSwipeBack(), new ChooseSpeedLayout.Callback() { + @Override + public void onSpeedSelected(float speed, boolean isFinal, boolean closeMenu) { + if (storyViewer != null) { + storyViewer.setSpeed(speed); + } + updateSpeedItem(isFinal); + if (closeMenu && popupLayout.getSwipeBack() != null) { + popupLayout.getSwipeBack().closeForeground(); + } + } + }); + speedLayout.update(StoryViewer.currentSpeed, true); + + speedItem = new ActionBarMenuSubItem(getContext(), false, false, false, resourcesProvider); + speedItem.setTextAndIcon(LocaleController.getString(R.string.Speed), R.drawable.msg_speed, null); + updateSpeedItem(true); + speedItem.setMinimumWidth(AndroidUtilities.dp(196)); + speedItem.setRightIcon(R.drawable.msg_arrowright); + popupLayout.addView(speedItem); + LinearLayout.LayoutParams layoutParams = (LinearLayout.LayoutParams) speedItem.getLayoutParams(); + if (LocaleController.isRTL) { + layoutParams.gravity = Gravity.RIGHT; + } + layoutParams.width = LayoutHelper.MATCH_PARENT; + layoutParams.height = AndroidUtilities.dp(48); + speedItem.setLayoutParams(layoutParams); + int swipeBackIndex = popupLayout.addViewToSwipeBack(speedLayout.speedSwipeBackLayout); + speedItem.openSwipeBackLayout = () -> { + if (popupLayout.getSwipeBack() != null) { + popupLayout.getSwipeBack().openForeground(swipeBackIndex); + } + }; + speedItem.setOnClickListener(view -> { + speedItem.openSwipeBack(); + }); + + popupLayout.swipeBackGravityRight = true; + + if (addGap) { + ActionBarPopupWindow.GapView gap = new ActionBarPopupWindow.GapView(getContext(), resourcesProvider, Theme.key_actionBarDefaultSubmenuSeparator); + gap.setTag(R.id.fit_width_tag, 1); + popupLayout.addView(gap, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, 8)); + } + } + @Override protected void onCreate(ActionBarPopupWindow.ActionBarPopupWindowLayout popupLayout) { - final boolean userCanEditStory = isSelf || MessagesController.getInstance(currentAccount).getStoriesController().canEditStory(currentStory.storyItem); - boolean canEditStory = isSelf || (isChannel && userCanEditStory); if (canEditStory || currentStory.uploadingStory != null) { TL_stories.StoryItem storyItem = currentStory.storyItem; if (currentStory.uploadingStory != null) { @@ -1215,7 +1276,9 @@ protected void onCreate(ActionBarPopupWindow.ActionBarPopupWindowLayout popupLay } }); item.setItemHeight(56); - + } + addSpeedLayout(popupLayout, false); + if (isSelf || speedControl) { ActionBarPopupWindow.GapView gap = new ActionBarPopupWindow.GapView(getContext(), resourcesProvider, Theme.key_actionBarDefaultSubmenuSeparator); gap.setTag(R.id.fit_width_tag, 1); popupLayout.addView(gap, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, 8)); @@ -1389,6 +1452,7 @@ protected void onCreate(ActionBarPopupWindow.ActionBarPopupWindowLayout popupLay // } // }); + addSpeedLayout(popupLayout, true); final String key = NotificationsController.getSharedPrefKey(dialogId, 0); boolean muted = !NotificationsCustomSettingsActivity.areStoriesNotMuted(currentAccount, dialogId); @@ -1459,7 +1523,11 @@ protected void onCreate(ActionBarPopupWindow.ActionBarPopupWindowLayout popupLay } } - if ((!unsupported && allowShare) || true) { + if (!MessagesController.getInstance(currentAccount).premiumFeaturesBlocked() && currentStory.isVideo) { + createQualityItem(popupLayout); + } + + if (!unsupported && allowShare) { if (UserConfig.getInstance(currentAccount).isPremium() || true) { ActionBarMenuItem.addItem(popupLayout, R.drawable.msg_gallery, LocaleController.getString("SaveToGallery", R.string.SaveToGallery), false, resourcesProvider).setOnClickListener(v -> { saveToGallery(); @@ -1500,7 +1568,7 @@ public void setColorFilter(ColorFilter colorFilter) { createStealthModeItem(popupLayout); } if (allowShareLink) { - ActionBarMenuItem.addItem(popupLayout, R.drawable.msg_link, LocaleController.getString("CopyLink", R.string.CopyLink), false, resourcesProvider).setOnClickListener(v -> { + ActionBarMenuItem.addItem(popupLayout, R.drawable.msg_link2, LocaleController.getString("CopyLink", R.string.CopyLink), false, resourcesProvider).setOnClickListener(v -> { AndroidUtilities.addToClipboard(currentStory.createLink()); onLinkCopied(); if (popupMenu != null) { @@ -1754,6 +1822,92 @@ public void setColorFilter(ColorFilter colorFilter) { } } + private void createQualityItem(ActionBarPopupWindow.ActionBarPopupWindowLayout popupLayout) { + final boolean qualityFull = MessagesController.getInstance(currentAccount).storyQualityFull; + if (UserConfig.getInstance(currentAccount).isPremium()) { + ActionBarMenuItem.addItem(popupLayout, qualityFull ? R.drawable.menu_quality_sd : R.drawable.menu_quality_hd, LocaleController.getString(qualityFull ? R.string.StoryQualityDecrease : R.string.StoryQualityIncrease), false, resourcesProvider).setOnClickListener(v -> { + final boolean newQualityFull = !qualityFull; + MessagesController.getInstance(currentAccount).setStoryQuality(newQualityFull); + BulletinFactory.of(storyContainer, resourcesProvider) + .createSimpleBulletin( + R.raw.chats_infotip, + LocaleController.getString(newQualityFull ? R.string.StoryQualityIncreasedTitle : R.string.StoryQualityDecreasedTitle), + LocaleController.getString(newQualityFull ? R.string.StoryQualityIncreasedMessage : R.string.StoryQualityDecreasedMessage) + ) + .show(); + if (popupMenu != null) { + popupMenu.dismiss(); + } + }); + } else { + Drawable lockIcon2 = ContextCompat.getDrawable(getContext(), R.drawable.msg_gallery_locked2); + lockIcon2.setColorFilter(new PorterDuffColorFilter(ColorUtils.blendARGB(Color.WHITE, Color.BLACK, 0.5f), PorterDuff.Mode.MULTIPLY)); + CombinedDrawable combinedDrawable2 = new CombinedDrawable( + ContextCompat.getDrawable(getContext(), R.drawable.menu_quality_hd2), + lockIcon2 + ) { + @Override + public void setColorFilter(ColorFilter colorFilter) { + + } + }; + combinedDrawable2.setIconSize(dp(24), dp(24)); + combinedDrawable2.setIconOffset(dp(1), -dp(2)); + ActionBarMenuSubItem item2 = ActionBarMenuItem.addItem(popupLayout, R.drawable.menu_quality_hd, LocaleController.getString(R.string.StoryQualityIncrease), false, resourcesProvider); + item2.setOnClickListener(v -> { + BottomSheet sheet = new BottomSheet(getContext(), false, resourcesProvider); + sheet.fixNavigationBar(Theme.getColor(Theme.key_dialogBackground, resourcesProvider)); + + LinearLayout layout = new LinearLayout(getContext()); + layout.setOrientation(LinearLayout.VERTICAL); + layout.setPadding(dp(16), 0, dp(16), 0); + + BackupImageView imageView = new BackupImageView(getContext()); + imageView.getImageReceiver().setAutoRepeat(1); +// imageView.setScaleType(ImageView.ScaleType.CENTER); +// imageView.setAutoRepeat(true); +// imageView.setAnimation(R.raw.utyan_cache, 150, 150); + MediaDataController.getInstance(currentAccount).setPlaceholderImage(imageView, AndroidUtilities.STICKERS_PLACEHOLDER_PACK_NAME_2, "😎", "150_150"); + layout.addView(imageView, LayoutHelper.createLinear(150, 150, Gravity.CENTER_HORIZONTAL, 0, 16, 0, 16)); + + TextView headerView = new TextView(getContext()); + headerView.setTypeface(AndroidUtilities.getTypeface(AndroidUtilities.TYPEFACE_ROBOTO_MEDIUM)); + headerView.setGravity(Gravity.CENTER); + headerView.setTextColor(Theme.getColor(Theme.key_dialogTextBlack, resourcesProvider)); + headerView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 20); + headerView.setText(LocaleController.getString(R.string.StoryQualityPremium)); + layout.addView(headerView, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.CENTER_HORIZONTAL, 12, 0, 12, 0)); + + TextView descriptionView = new TextView(getContext()); + descriptionView.setGravity(Gravity.CENTER); + descriptionView.setTextColor(Theme.getColor(Theme.key_dialogTextGray3, resourcesProvider)); + descriptionView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14); + descriptionView.setText(AndroidUtilities.replaceTags(LocaleController.getString(R.string.StoryQualityPremiumText))); + layout.addView(descriptionView, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.CENTER_HORIZONTAL, 32, 9, 32, 19)); + + ButtonWithCounterView button = new ButtonWithCounterView(getContext(), resourcesProvider); + button.setText(LocaleController.getString(R.string.StoryQualityIncrease), false); + SpannableStringBuilder lock = new SpannableStringBuilder("l"); + ColoredImageSpan coloredImageSpan = new ColoredImageSpan(R.drawable.mini_switch_lock); + coloredImageSpan.setTopOffset(1); + lock.setSpan(coloredImageSpan, 0, 1, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); + button.setSubText(new SpannableStringBuilder().append(lock).append(LocaleController.getString(R.string.OptionPremiumRequiredTitle)), false); + layout.addView(button, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, 48, Gravity.CENTER_HORIZONTAL)); + button.setOnClickListener(view -> { + delegate.showDialog(new PremiumFeatureBottomSheet(storyViewer.fragment, PremiumPreviewFragment.PREMIUM_FEATURE_STORIES, false)); + sheet.dismiss(); + }); + + sheet.setCustomView(layout); + delegate.showDialog(sheet); + if (popupMenu != null) { + popupMenu.dismiss(); + } + }); + item2.setIcon(combinedDrawable2); + } + } + private void showLikesReaction(boolean show) { if (likesReactionShowing == show || currentStory.storyItem == null) { return; @@ -2103,6 +2257,29 @@ private void showPremiumBlockedToast() { bulletin.show(); } + private void updateSpeedItem(boolean isFinal) { + if (speedItem == null || speedLayout == null) return; + if (speedItem.getVisibility() != View.VISIBLE) { + return; + } + if (isFinal) { + if (Math.abs(StoryViewer.currentSpeed - 0.2f) < 0.05f) { + speedItem.setSubtext(LocaleController.getString(R.string.VideoSpeedVerySlow)); + } else if (Math.abs(StoryViewer.currentSpeed - 0.5f) < 0.05f) { + speedItem.setSubtext(LocaleController.getString(R.string.VideoSpeedSlow)); + } else if (Math.abs(StoryViewer.currentSpeed - 1.0f) < 0.05f) { + speedItem.setSubtext(LocaleController.getString(R.string.VideoSpeedNormal)); + } else if (Math.abs(StoryViewer.currentSpeed - 1.5f) < 0.05f) { + speedItem.setSubtext(LocaleController.getString(R.string.VideoSpeedFast)); + } else if (Math.abs(StoryViewer.currentSpeed - 2f) < 0.05f) { + speedItem.setSubtext(LocaleController.getString(R.string.VideoSpeedVeryFast)); + } else { + speedItem.setSubtext(LocaleController.formatString(R.string.VideoSpeedCustom, SpeedIconDrawable.formatNumber(StoryViewer.currentSpeed) + "x")); + } + } + speedLayout.update(StoryViewer.currentSpeed, isFinal); + } + private void createEnterView() { Theme.ResourcesProvider emojiResourceProvider = new WrappedResourceProvider(resourcesProvider) { @Override @@ -3152,7 +3329,7 @@ private void createUnsupportedContainer() { buttonTextView.setOnClickListener(v -> { // if (ApplicationLoader.isStandaloneBuild()) { // if (LaunchActivity.instance != null) { -// LaunchActivity.instance.checkAppUpdate(true); +// LaunchActivity.instance.checkAppUpdate(true, null); // } // } else if (BuildVars.isHuaweiStoreApp()){ // Browser.openUrl(getContext(), BuildVars.HUAWEI_STORE_URL); @@ -3450,6 +3627,7 @@ protected void onAttachedToWindow() { } // sharedResources.muteDrawable.addView(muteIconView); NotificationCenter.getInstance(currentAccount).addObserver(this, NotificationCenter.storiesUpdated); + NotificationCenter.getInstance(currentAccount).addObserver(this, NotificationCenter.storyQualityUpdate); NotificationCenter.getInstance(currentAccount).addObserver(this, NotificationCenter.storiesListUpdated); NotificationCenter.getInstance(currentAccount).addObserver(this, NotificationCenter.stealthModeChanged); NotificationCenter.getInstance(currentAccount).addObserver(this, NotificationCenter.storiesLimitUpdate); @@ -3482,6 +3660,7 @@ protected void onDetachedFromWindow() { } //sharedResources.muteDrawable.removeView(muteIconView); NotificationCenter.getInstance(currentAccount).removeObserver(this, NotificationCenter.storiesUpdated); + NotificationCenter.getInstance(currentAccount).removeObserver(this, NotificationCenter.storyQualityUpdate); NotificationCenter.getInstance(currentAccount).removeObserver(this, NotificationCenter.storiesListUpdated); NotificationCenter.getInstance(currentAccount).removeObserver(this, NotificationCenter.stealthModeChanged); NotificationCenter.getInstance(currentAccount).removeObserver(this, NotificationCenter.storiesLimitUpdate); @@ -3520,6 +3699,8 @@ public void didReceivedNotification(int id, int account, Object... args) { if (editStoryItem != null) { editStoryItem.animate().alpha(storiesController.hasUploadingStories(dialogId) && currentStory.isVideo && !SharedConfig.allowPreparingHevcPlayers() ? .5f : 1f).start(); } + } else if (id == NotificationCenter.storyQualityUpdate) { + updatePosition(); } else if (id == NotificationCenter.emojiLoaded) { storyCaptionView.captionTextview.invalidate(); } else if (id == NotificationCenter.stealthModeChanged) { @@ -6039,7 +6220,7 @@ public void appendColors() { sparseIntArray.put(Theme.key_chat_emojiPanelBackground, ColorUtils.setAlphaComponent(Color.WHITE, 30)); } }); - reactionsContainerLayout.setHint(LocaleController.getString("StoryReactionsHint", R.string.StoryReactionsHint)); + reactionsContainerLayout.setHint(LocaleController.getString(R.string.StoryReactionsHint)); reactionsContainerLayout.skipEnterAnimation = true; addView(reactionsContainerLayout, reactionsContainerIndex, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, 52 + 20, Gravity.TOP | Gravity.CENTER_HORIZONTAL, 0, 0, 0, 64)); reactionsContainerLayout.setDelegate(new ReactionsContainerLayout.ReactionsContainerDelegate() { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Stories/ProfileStoriesView.java b/TMessagesProj/src/main/java/org/telegram/ui/Stories/ProfileStoriesView.java index 54019eac8a..af016594ba 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Stories/ProfileStoriesView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Stories/ProfileStoriesView.java @@ -37,6 +37,7 @@ import org.telegram.messenger.SharedConfig; import org.telegram.messenger.UserConfig; import org.telegram.messenger.Utilities; +import org.telegram.tgnet.ConnectionsManager; import org.telegram.tgnet.TLRPC; import org.telegram.tgnet.tl.TL_stories; import org.telegram.ui.ActionBar.Theme; @@ -182,6 +183,7 @@ public void setStories(TL_stories.PeerStories peerStories) { private void updateStories(boolean animated, boolean asUpdate) { final boolean me = dialogId == UserConfig.getInstance(currentAccount).getClientUserId(); + final int now = ConnectionsManager.getInstance(currentAccount).getCurrentTime(); TL_stories.PeerStories userFullStories = MessagesController.getInstance(currentAccount).getStoriesController().getStoriesFromFullPeer(dialogId); TL_stories.PeerStories stateStories = MessagesController.getInstance(currentAccount).getStoriesController().getStories(dialogId); final TL_stories.PeerStories userStories; @@ -243,6 +245,9 @@ private void updateStories(boolean animated, boolean asUpdate) { continue; } } + if (storyItem.expire_date != 0 && now > storyItem.expire_date) { + continue; + } if (me || storyItem.id > max_read_id) { storiesToShow.add(storyItem); if (storiesToShow.size() >= CIRCLES_MAX) { @@ -282,6 +287,9 @@ private void updateStories(boolean animated, boolean asUpdate) { if (storyItem instanceof TL_stories.TL_storyItemDeleted) { continue; } + if (storyItem.expire_date != 0 && now > storyItem.expire_date) { + continue; + } if (!storiesToShow.contains(storyItem)) { storiesToShow.add(storyItem); if (storiesToShow.size() >= CIRCLES_MAX) { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Stories/StoriesController.java b/TMessagesProj/src/main/java/org/telegram/ui/Stories/StoriesController.java index e963e3c872..cc0cb44885 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Stories/StoriesController.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Stories/StoriesController.java @@ -1356,7 +1356,13 @@ public void stopAllPollers() { HashSet loadingAllStories = new HashSet<>(); void loadSkippedStories(long dialogId) { - loadSkippedStories(getStories(dialogId), false); + boolean profile = false; + TL_stories.PeerStories peerStories = getStories(dialogId); + if (peerStories == null) { + profile = true; + peerStories = getStoriesFromFullPeer(dialogId); + } + loadSkippedStories(peerStories, profile); } void loadSkippedStories(TL_stories.PeerStories userStories, boolean profile) { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Stories/StoryViewer.java b/TMessagesProj/src/main/java/org/telegram/ui/Stories/StoryViewer.java index 22092b5e72..6f87a6de06 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Stories/StoryViewer.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Stories/StoryViewer.java @@ -198,6 +198,8 @@ public class StoryViewer implements NotificationCenter.NotificationCenterDelegat private boolean isBulletinVisible; public boolean isTranslating = false; + public static float currentSpeed = 1f; + public boolean isLongpressed; Runnable longPressRunnable = () -> setLongPressed(true); @@ -274,6 +276,24 @@ public StoryViewer(BaseFragment fragment) { this.fragment = fragment; } + public void setSpeed(float speed) { + currentSpeed = speed; + if (playerHolder != null) { + playerHolder.setSpeed(speed); + StoryViewer otherStoryViewer = null; + if (fragment != null) { + if (fragment.overlayStoryViewer != this) { + otherStoryViewer = fragment.overlayStoryViewer; + } else if (fragment.storyViewer != this) { + otherStoryViewer = fragment.storyViewer; + } + } + if (otherStoryViewer != null && otherStoryViewer.playerHolder != null) { + otherStoryViewer.playerHolder.setSpeed(speed); + } + } + } + public void open(Context context, TL_stories.StoryItem storyItem, PlaceProvider placeProvider) { if (storyItem == null) { return; @@ -340,6 +360,7 @@ public void open(Context context, TL_stories.StoryItem storyItem, ArrayList documents, ArrayList ur playerHolder.uri = uri; playerHolder.document = documents.get(i); FileStreamLoadOperation.setPriorityForDocument(playerHolder.document, FileLoader.PRIORITY_LOW); - playerHolder.preparePlayer(uri, isInSilentMode); + playerHolder.preparePlayer(uri, isInSilentMode, currentSpeed); preparedPlayers.add(playerHolder); if (preparedPlayers.size() > 2) { VideoPlayerHolder player = preparedPlayers.remove(0); @@ -2004,7 +2027,7 @@ public void updatePlayingMode() { if (pause) { playerHolder.pause(); } else { - playerHolder.play(); + playerHolder.play(currentSpeed); } } storiesViewPager.enableTouch(!keyboardVisible && !isClosed && !isRecording && !isLongpressed && !isInPinchToZoom && selfStoriesViewsOffset == 0 && !isInTextSelectionMode); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Stories/recorder/GalleryListView.java b/TMessagesProj/src/main/java/org/telegram/ui/Stories/recorder/GalleryListView.java index 25bcae58f1..13e77719ba 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Stories/recorder/GalleryListView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Stories/recorder/GalleryListView.java @@ -226,6 +226,7 @@ public void onScrolled(@NonNull RecyclerView recyclerView, int dx, int dy) { actionBar.setBackButtonImage(R.drawable.ic_ab_back); actionBar.setItemsBackgroundColor(436207615, false); actionBar.setItemsColor(0xFFFFFFFF, false); + actionBar.setItemsColor(0xFFFFFFFF, true); addView(actionBar, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.TOP | Gravity.FILL_HORIZONTAL)); actionBar.setActionBarMenuOnItemClick(new ActionBar.ActionBarMenuOnItemClick() { @Override @@ -1172,7 +1173,7 @@ public HeaderView(Context context, boolean onlyPhotos) { super(context); setPadding(dp(onlyPhotos ? 14 : 16), dp(16), dp(8), dp(10)); - if (onlyPhotos) { + if (onlyPhotos && false) { searchButton = new ImageView(context); searchButton.setImageResource(R.drawable.ic_ab_search); searchButton.setColorFilter(new PorterDuffColorFilter(Color.WHITE, PorterDuff.Mode.SRC_IN)); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Stories/recorder/HintView2.java b/TMessagesProj/src/main/java/org/telegram/ui/Stories/recorder/HintView2.java index eae8dba769..ce0bfd7e8e 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Stories/recorder/HintView2.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Stories/recorder/HintView2.java @@ -469,6 +469,7 @@ public HintView2 show() { if (shown) { bounceShow(); } + AndroidUtilities.makeAccessibilityAnnouncement(getText()); shown = true; invalidate(); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Stories/recorder/StoryRecorder.java b/TMessagesProj/src/main/java/org/telegram/ui/Stories/recorder/StoryRecorder.java index 0de5175dd6..580f3a08fb 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Stories/recorder/StoryRecorder.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Stories/recorder/StoryRecorder.java @@ -3687,7 +3687,7 @@ public boolean dispatchTouchEvent(MotionEvent ev) { return super.dispatchTouchEvent(ev); } }; -// galleryListView.allowSearch(forAddingPart); + galleryListView.allowSearch(false); galleryListView.setOnBackClickListener(() -> { animateGalleryListView(false); lastGallerySelectedAlbum = null; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/TopicCreateFragment.java b/TMessagesProj/src/main/java/org/telegram/ui/TopicCreateFragment.java index 1f353fd013..5993bb753d 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/TopicCreateFragment.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/TopicCreateFragment.java @@ -63,7 +63,7 @@ public class TopicCreateFragment extends BaseFragment { private final static int EDIT_ID = 2; long chatId; long selectedEmojiDocumentId; - int topicId; + long topicId; TextCheckCell2 checkBoxCell; EditTextBoldCursor editTextBoldCursor; @@ -93,7 +93,7 @@ private TopicCreateFragment(Bundle bundle) { @Override public boolean onFragmentCreate() { chatId = arguments.getLong("chat_id"); - topicId = arguments.getInt("topic_id", 0); + topicId = arguments.getLong("topic_id", 0); if (topicId != 0) { topicForEdit = getMessagesController().getTopicsController().findTopic(chatId, topicId); if (topicForEdit == null) { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/WebviewActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/WebviewActivity.java index 15420a5b2b..4f65541a38 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/WebviewActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/WebviewActivity.java @@ -193,6 +193,7 @@ public void onItemClick(int id) { } else if (type == TYPE_STAT) { actionBar.setBackgroundColor(Theme.getColor(Theme.key_dialogBackground)); actionBar.setItemsColor(Theme.getColor(Theme.key_player_actionBarItems), false); + actionBar.setItemsColor(Theme.getColor(Theme.key_player_actionBarItems), true); actionBar.setItemsBackgroundColor(Theme.getColor(Theme.key_player_actionBarSelector), false); actionBar.setTitleColor(Theme.getColor(Theme.key_player_actionBarTitle)); actionBar.setSubtitleColor(Theme.getColor(Theme.key_player_actionBarSubtitle)); diff --git a/TMessagesProj/src/main/res/drawable-hdpi/menu_external_link.png b/TMessagesProj/src/main/res/drawable-hdpi/menu_external_link.png new file mode 100644 index 0000000000..cc35cd339e Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/menu_external_link.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/menu_premium_privacy.png b/TMessagesProj/src/main/res/drawable-hdpi/menu_premium_privacy.png new file mode 100644 index 0000000000..94e831c6df Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/menu_premium_privacy.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/menu_premium_seen.png b/TMessagesProj/src/main/res/drawable-hdpi/menu_premium_seen.png new file mode 100644 index 0000000000..9ab075e9cf Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/menu_premium_seen.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/menu_premium_tools.png b/TMessagesProj/src/main/res/drawable-hdpi/menu_premium_tools.png new file mode 100644 index 0000000000..537a056d90 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/menu_premium_tools.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/menu_quality_hd.png b/TMessagesProj/src/main/res/drawable-hdpi/menu_quality_hd.png new file mode 100644 index 0000000000..bf43988e8d Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/menu_quality_hd.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/menu_quality_hd2.png b/TMessagesProj/src/main/res/drawable-hdpi/menu_quality_hd2.png new file mode 100644 index 0000000000..a7a8312bdd Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/menu_quality_hd2.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/menu_quality_sd.png b/TMessagesProj/src/main/res/drawable-hdpi/menu_quality_sd.png new file mode 100644 index 0000000000..66c6ce2bd1 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/menu_quality_sd.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/menu_tag_delete.png b/TMessagesProj/src/main/res/drawable-hdpi/menu_tag_delete.png new file mode 100644 index 0000000000..90ea3da0a0 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/menu_tag_delete.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/menu_tag_edit.png b/TMessagesProj/src/main/res/drawable-hdpi/menu_tag_edit.png new file mode 100644 index 0000000000..cd79e07874 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/menu_tag_edit.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/menu_tag_filter.png b/TMessagesProj/src/main/res/drawable-hdpi/menu_tag_filter.png new file mode 100644 index 0000000000..2ad3859802 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/menu_tag_filter.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/menu_tag_plus.png b/TMessagesProj/src/main/res/drawable-hdpi/menu_tag_plus.png new file mode 100644 index 0000000000..b245c6b440 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/menu_tag_plus.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/menu_tag_rename.png b/TMessagesProj/src/main/res/drawable-hdpi/menu_tag_rename.png new file mode 100644 index 0000000000..947153aa32 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/menu_tag_rename.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/navbar_search_tag.png b/TMessagesProj/src/main/res/drawable-hdpi/navbar_search_tag.png new file mode 100644 index 0000000000..9957f98715 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/navbar_search_tag.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/premium_tags.png b/TMessagesProj/src/main/res/drawable-hdpi/premium_tags.png new file mode 100644 index 0000000000..076ee4d382 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/premium_tags.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/menu_external_link.png b/TMessagesProj/src/main/res/drawable-mdpi/menu_external_link.png new file mode 100644 index 0000000000..742dbd18e2 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/menu_external_link.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/menu_premium_privacy.png b/TMessagesProj/src/main/res/drawable-mdpi/menu_premium_privacy.png new file mode 100644 index 0000000000..d22ad8d29d Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/menu_premium_privacy.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/menu_premium_seen.png b/TMessagesProj/src/main/res/drawable-mdpi/menu_premium_seen.png new file mode 100644 index 0000000000..5c767c0b16 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/menu_premium_seen.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/menu_premium_tools.png b/TMessagesProj/src/main/res/drawable-mdpi/menu_premium_tools.png new file mode 100644 index 0000000000..9635343325 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/menu_premium_tools.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/menu_quality_hd.png b/TMessagesProj/src/main/res/drawable-mdpi/menu_quality_hd.png new file mode 100644 index 0000000000..79d0ad3417 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/menu_quality_hd.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/menu_quality_hd2.png b/TMessagesProj/src/main/res/drawable-mdpi/menu_quality_hd2.png new file mode 100644 index 0000000000..f8eb46600c Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/menu_quality_hd2.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/menu_quality_sd.png b/TMessagesProj/src/main/res/drawable-mdpi/menu_quality_sd.png new file mode 100644 index 0000000000..425129fa9b Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/menu_quality_sd.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/menu_tag_delete.png b/TMessagesProj/src/main/res/drawable-mdpi/menu_tag_delete.png new file mode 100644 index 0000000000..28c4aaad02 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/menu_tag_delete.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/menu_tag_edit.png b/TMessagesProj/src/main/res/drawable-mdpi/menu_tag_edit.png new file mode 100644 index 0000000000..aaca45a7b5 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/menu_tag_edit.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/menu_tag_filter.png b/TMessagesProj/src/main/res/drawable-mdpi/menu_tag_filter.png new file mode 100644 index 0000000000..515dcdc988 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/menu_tag_filter.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/menu_tag_plus.png b/TMessagesProj/src/main/res/drawable-mdpi/menu_tag_plus.png new file mode 100644 index 0000000000..adc388dbf4 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/menu_tag_plus.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/menu_tag_rename.png b/TMessagesProj/src/main/res/drawable-mdpi/menu_tag_rename.png new file mode 100644 index 0000000000..0dbcde6a94 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/menu_tag_rename.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/navbar_search_tag.png b/TMessagesProj/src/main/res/drawable-mdpi/navbar_search_tag.png new file mode 100644 index 0000000000..865782ccaf Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/navbar_search_tag.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/premium_tags.png b/TMessagesProj/src/main/res/drawable-mdpi/premium_tags.png new file mode 100644 index 0000000000..a4e3b0d541 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/premium_tags.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/menu_external_link.png b/TMessagesProj/src/main/res/drawable-xhdpi/menu_external_link.png new file mode 100644 index 0000000000..a58df3b3fe Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/menu_external_link.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/menu_premium_privacy.png b/TMessagesProj/src/main/res/drawable-xhdpi/menu_premium_privacy.png new file mode 100644 index 0000000000..c04c185321 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/menu_premium_privacy.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/menu_premium_seen.png b/TMessagesProj/src/main/res/drawable-xhdpi/menu_premium_seen.png new file mode 100644 index 0000000000..4d45b776b3 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/menu_premium_seen.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/menu_premium_tools.png b/TMessagesProj/src/main/res/drawable-xhdpi/menu_premium_tools.png new file mode 100644 index 0000000000..51b04bea0d Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/menu_premium_tools.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/menu_quality_hd.png b/TMessagesProj/src/main/res/drawable-xhdpi/menu_quality_hd.png new file mode 100644 index 0000000000..a2efe33ae5 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/menu_quality_hd.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/menu_quality_hd2.png b/TMessagesProj/src/main/res/drawable-xhdpi/menu_quality_hd2.png new file mode 100644 index 0000000000..189f2dde2d Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/menu_quality_hd2.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/menu_quality_sd.png b/TMessagesProj/src/main/res/drawable-xhdpi/menu_quality_sd.png new file mode 100644 index 0000000000..b90f9f1d38 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/menu_quality_sd.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/menu_tag_delete.png b/TMessagesProj/src/main/res/drawable-xhdpi/menu_tag_delete.png new file mode 100644 index 0000000000..75f81bc71a Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/menu_tag_delete.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/menu_tag_edit.png b/TMessagesProj/src/main/res/drawable-xhdpi/menu_tag_edit.png new file mode 100644 index 0000000000..23a6e406ff Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/menu_tag_edit.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/menu_tag_filter.png b/TMessagesProj/src/main/res/drawable-xhdpi/menu_tag_filter.png new file mode 100644 index 0000000000..3dec62c4d9 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/menu_tag_filter.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/menu_tag_plus.png b/TMessagesProj/src/main/res/drawable-xhdpi/menu_tag_plus.png new file mode 100644 index 0000000000..6be83c70c4 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/menu_tag_plus.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/menu_tag_rename.png b/TMessagesProj/src/main/res/drawable-xhdpi/menu_tag_rename.png new file mode 100644 index 0000000000..3a428a24bb Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/menu_tag_rename.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/navbar_search_tag.png b/TMessagesProj/src/main/res/drawable-xhdpi/navbar_search_tag.png new file mode 100644 index 0000000000..07c09c6db0 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/navbar_search_tag.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/premium_tags.png b/TMessagesProj/src/main/res/drawable-xhdpi/premium_tags.png new file mode 100644 index 0000000000..2f17e87201 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/premium_tags.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/menu_external_link.png b/TMessagesProj/src/main/res/drawable-xxhdpi/menu_external_link.png new file mode 100644 index 0000000000..fb00b5482c Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/menu_external_link.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/menu_premium_privacy.png b/TMessagesProj/src/main/res/drawable-xxhdpi/menu_premium_privacy.png new file mode 100644 index 0000000000..285adf5895 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/menu_premium_privacy.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/menu_premium_seen.png b/TMessagesProj/src/main/res/drawable-xxhdpi/menu_premium_seen.png new file mode 100644 index 0000000000..39ffb9fee5 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/menu_premium_seen.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/menu_premium_tools.png b/TMessagesProj/src/main/res/drawable-xxhdpi/menu_premium_tools.png new file mode 100644 index 0000000000..74c88483af Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/menu_premium_tools.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/menu_quality_hd.png b/TMessagesProj/src/main/res/drawable-xxhdpi/menu_quality_hd.png new file mode 100644 index 0000000000..4fc64ed179 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/menu_quality_hd.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/menu_quality_hd2.png b/TMessagesProj/src/main/res/drawable-xxhdpi/menu_quality_hd2.png new file mode 100644 index 0000000000..f223482090 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/menu_quality_hd2.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/menu_quality_sd.png b/TMessagesProj/src/main/res/drawable-xxhdpi/menu_quality_sd.png new file mode 100644 index 0000000000..f2d15bb135 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/menu_quality_sd.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/menu_tag_delete.png b/TMessagesProj/src/main/res/drawable-xxhdpi/menu_tag_delete.png new file mode 100644 index 0000000000..50fdf3f70c Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/menu_tag_delete.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/menu_tag_edit.png b/TMessagesProj/src/main/res/drawable-xxhdpi/menu_tag_edit.png new file mode 100644 index 0000000000..aac582f18f Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/menu_tag_edit.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/menu_tag_filter.png b/TMessagesProj/src/main/res/drawable-xxhdpi/menu_tag_filter.png new file mode 100644 index 0000000000..867130dc8e Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/menu_tag_filter.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/menu_tag_plus.png b/TMessagesProj/src/main/res/drawable-xxhdpi/menu_tag_plus.png new file mode 100644 index 0000000000..df8bb0f1d3 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/menu_tag_plus.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/menu_tag_rename.png b/TMessagesProj/src/main/res/drawable-xxhdpi/menu_tag_rename.png new file mode 100644 index 0000000000..c512e25c43 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/menu_tag_rename.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/navbar_search_tag.png b/TMessagesProj/src/main/res/drawable-xxhdpi/navbar_search_tag.png new file mode 100644 index 0000000000..3191ae34bc Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/navbar_search_tag.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/premium_tags.png b/TMessagesProj/src/main/res/drawable-xxhdpi/premium_tags.png new file mode 100644 index 0000000000..90751e1696 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/premium_tags.png differ diff --git a/TMessagesProj/src/main/res/raw/options_to_search.json b/TMessagesProj/src/main/res/raw/options_to_search.json new file mode 100644 index 0000000000..e7163ada4c --- /dev/null +++ b/TMessagesProj/src/main/res/raw/options_to_search.json @@ -0,0 +1 @@ +{"v":"5.12.1","fr":60,"ip":0,"op":120,"w":512,"h":512,"nm":"Comp 3","ddd":0,"assets":[{"id":"comp_0","nm":"Comp 2","fr":60,"layers":[{"ddd":0,"ind":1,"ty":3,"nm":"Null 2","sr":1,"ks":{"o":{"a":0,"k":0,"ix":11},"r":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.724]},"o":{"x":[0.167],"y":[0.167]},"t":0,"s":[90]},{"i":{"x":[0.833],"y":[0.866]},"o":{"x":[0.167],"y":[0.119]},"t":1,"s":[87.043]},{"i":{"x":[0.833],"y":[0.739]},"o":{"x":[0.167],"y":[0.22]},"t":2,"s":[80.218]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.122]},"t":3,"s":[76.066]},{"i":{"x":[0.833],"y":[0.838]},"o":{"x":[0.167],"y":[0.167]},"t":4,"s":[67.192]},{"i":{"x":[0.833],"y":[0.878]},"o":{"x":[0.167],"y":[0.172]},"t":5,"s":[58.306]},{"i":{"x":[0.833],"y":[0.764]},"o":{"x":[0.167],"y":[0.262]},"t":6,"s":[49.945]},{"i":{"x":[0.833],"y":[0.879]},"o":{"x":[0.167],"y":[0.129]},"t":7,"s":[46.05]},{"i":{"x":[0.833],"y":[0.767]},"o":{"x":[0.167],"y":[0.267]},"t":8,"s":[38.915]},{"i":{"x":[0.833],"y":[0.845]},"o":{"x":[0.167],"y":[0.13]},"t":9,"s":[35.683]},{"i":{"x":[0.833],"y":[0.88]},"o":{"x":[0.167],"y":[0.181]},"t":10,"s":[29.879]},{"i":{"x":[0.833],"y":[0.77]},"o":{"x":[0.167],"y":[0.272]},"t":11,"s":[24.909]},{"i":{"x":[0.833],"y":[0.847]},"o":{"x":[0.167],"y":[0.131]},"t":12,"s":[22.712]},{"i":{"x":[0.833],"y":[0.88]},"o":{"x":[0.167],"y":[0.183]},"t":13,"s":[18.84]},{"i":{"x":[0.833],"y":[0.771]},"o":{"x":[0.167],"y":[0.274]},"t":14,"s":[15.589]},{"i":{"x":[0.833],"y":[0.847]},"o":{"x":[0.167],"y":[0.131]},"t":15,"s":[14.169]},{"i":{"x":[0.833],"y":[0.881]},"o":{"x":[0.167],"y":[0.184]},"t":16,"s":[11.691]},{"i":{"x":[0.833],"y":[0.772]},"o":{"x":[0.167],"y":[0.275]},"t":17,"s":[9.632]},{"i":{"x":[0.833],"y":[0.848]},"o":{"x":[0.167],"y":[0.131]},"t":18,"s":[8.739]},{"i":{"x":[0.833],"y":[0.881]},"o":{"x":[0.167],"y":[0.184]},"t":19,"s":[7.188]},{"i":{"x":[0.833],"y":[0.772]},"o":{"x":[0.167],"y":[0.276]},"t":20,"s":[5.907]},{"i":{"x":[0.833],"y":[0.848]},"o":{"x":[0.167],"y":[0.131]},"t":21,"s":[5.353]},{"i":{"x":[0.833],"y":[0.881]},"o":{"x":[0.167],"y":[0.185]},"t":22,"s":[4.395]},{"i":{"x":[0.833],"y":[0.773]},"o":{"x":[0.167],"y":[0.277]},"t":23,"s":[3.607]},{"i":{"x":[0.833],"y":[0.848]},"o":{"x":[0.167],"y":[0.132]},"t":24,"s":[3.267]},{"i":{"x":[0.833],"y":[0.881]},"o":{"x":[0.167],"y":[0.185]},"t":25,"s":[2.679]},{"i":{"x":[0.833],"y":[0.773]},"o":{"x":[0.167],"y":[0.277]},"t":26,"s":[2.196]},{"i":{"x":[0.833],"y":[0.848]},"o":{"x":[0.167],"y":[0.132]},"t":27,"s":[1.989]},{"i":{"x":[0.833],"y":[0.881]},"o":{"x":[0.167],"y":[0.185]},"t":28,"s":[1.63]},{"i":{"x":[0.833],"y":[0.773]},"o":{"x":[0.167],"y":[0.277]},"t":29,"s":[1.335]},{"i":{"x":[0.833],"y":[0.848]},"o":{"x":[0.167],"y":[0.132]},"t":30,"s":[1.209]},{"i":{"x":[0.833],"y":[0.881]},"o":{"x":[0.167],"y":[0.185]},"t":31,"s":[0.99]},{"i":{"x":[0.833],"y":[0.773]},"o":{"x":[0.167],"y":[0.277]},"t":32,"s":[0.811]},{"i":{"x":[0.833],"y":[0.848]},"o":{"x":[0.167],"y":[0.132]},"t":33,"s":[0.734]},{"i":{"x":[0.833],"y":[0.881]},"o":{"x":[0.167],"y":[0.185]},"t":34,"s":[0.601]},{"i":{"x":[0.833],"y":[0.773]},"o":{"x":[0.167],"y":[0.277]},"t":35,"s":[0.492]},{"i":{"x":[0.833],"y":[0.848]},"o":{"x":[0.167],"y":[0.132]},"t":36,"s":[0.446]},{"i":{"x":[0.833],"y":[0.881]},"o":{"x":[0.167],"y":[0.185]},"t":37,"s":[0.365]},{"i":{"x":[0.833],"y":[0.773]},"o":{"x":[0.167],"y":[0.277]},"t":38,"s":[0.299]},{"i":{"x":[0.833],"y":[0.848]},"o":{"x":[0.167],"y":[0.132]},"t":39,"s":[0.27]},{"i":{"x":[0.833],"y":[0.881]},"o":{"x":[0.167],"y":[0.185]},"t":40,"s":[0.221]},{"i":{"x":[0.833],"y":[0.773]},"o":{"x":[0.167],"y":[0.277]},"t":41,"s":[0.181]},{"i":{"x":[0.833],"y":[0.848]},"o":{"x":[0.167],"y":[0.132]},"t":42,"s":[0.164]},{"i":{"x":[0.833],"y":[0.881]},"o":{"x":[0.167],"y":[0.185]},"t":43,"s":[0.134]},{"i":{"x":[0.833],"y":[0.773]},"o":{"x":[0.167],"y":[0.277]},"t":44,"s":[0.11]},{"i":{"x":[0.833],"y":[0.848]},"o":{"x":[0.167],"y":[0.132]},"t":45,"s":[0.1]},{"i":{"x":[0.833],"y":[0.881]},"o":{"x":[0.167],"y":[0.185]},"t":46,"s":[0.081]},{"i":{"x":[0.833],"y":[0.773]},"o":{"x":[0.167],"y":[0.277]},"t":47,"s":[0.067]},{"i":{"x":[0.833],"y":[0.848]},"o":{"x":[0.167],"y":[0.132]},"t":48,"s":[0.06]},{"i":{"x":[0.833],"y":[0.881]},"o":{"x":[0.167],"y":[0.185]},"t":49,"s":[0.049]},{"i":{"x":[0.833],"y":[0.773]},"o":{"x":[0.167],"y":[0.277]},"t":50,"s":[0.04]},{"i":{"x":[0.833],"y":[0.848]},"o":{"x":[0.167],"y":[0.132]},"t":51,"s":[0.037]},{"i":{"x":[0.833],"y":[0.881]},"o":{"x":[0.167],"y":[0.185]},"t":52,"s":[0.03]},{"i":{"x":[0.833],"y":[0.773]},"o":{"x":[0.167],"y":[0.277]},"t":53,"s":[0.025]},{"i":{"x":[0.833],"y":[0.848]},"o":{"x":[0.167],"y":[0.132]},"t":54,"s":[0.022]},{"i":{"x":[0.833],"y":[0.881]},"o":{"x":[0.167],"y":[0.185]},"t":55,"s":[0.018]},{"i":{"x":[0.833],"y":[0.773]},"o":{"x":[0.167],"y":[0.277]},"t":56,"s":[0.015]},{"i":{"x":[0.833],"y":[0.848]},"o":{"x":[0.167],"y":[0.132]},"t":57,"s":[0.013]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.185]},"t":58,"s":[0.011]},{"t":59,"s":[0.009]}],"ix":10},"p":{"a":0,"k":[360,360,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"ip":0,"op":60,"st":0,"bm":0},{"ddd":0,"ind":2,"ty":4,"nm":"Path","parent":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":1,"k":[{"i":{"x":0.6,"y":1},"o":{"x":0.167,"y":0.167},"t":10,"s":[0,0,0],"to":[24.223,22.553,0],"ti":[-24.223,-22.553,0]},{"t":20,"s":[145.338,135.315,0]}],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[1000,1000,100],"ix":6,"l":2}},"ao":0,"hasMask":true,"masksProperties":[{"inv":false,"mode":"a","pt":{"a":1,"k":[{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":11,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[1.532,1.378],[-10,31],[12.059,11.806],[28,-10]],"c":true}]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":14,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[-6.433,-5.923],[-10,31],[12.059,11.806],[28,-10]],"c":true}]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":17,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[-8.78,-8.877],[-10,31],[12.059,11.806],[28,-10]],"c":true}]},{"t":20,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[-13.945,-16.199],[-10,31],[12.059,11.806],[28,-10]],"c":true}]}],"ix":1},"o":{"a":0,"k":100,"ix":3},"x":{"a":0,"k":0,"ix":4},"nm":"Mask 1"}],"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":1,"k":[{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":18,"s":[{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[8,8],[-8,-8]],"c":false}]},{"t":20,"s":[{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[8,8],[-8,-8]],"c":false}]}],"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"tm","s":{"a":1,"k":[{"i":{"x":[0.4],"y":[1]},"o":{"x":[0.167],"y":[0]},"t":0,"s":[43]},{"t":20,"s":[0]}],"ix":1},"e":{"a":0,"k":100,"ix":2},"o":{"a":0,"k":0,"ix":3},"m":1,"ix":2,"nm":"Trim Paths 1","mn":"ADBE Vector Filter - Trim","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":5.5,"ix":5},"lc":2,"lj":1,"ml":4,"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":"Path","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":60,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":3,"ty":4,"nm":"Oval 3","parent":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":1,"k":[{"i":{"x":0.833,"y":0.702},"o":{"x":0.167,"y":0.167},"t":0,"s":[180,0,0],"to":[-1.081,0,0],"ti":[3.868,0,0]},{"i":{"x":0.833,"y":0.862},"o":{"x":0.167,"y":0.116},"t":1,"s":[173.512,0,0],"to":[-3.868,0,0],"ti":[4.618,0,0]},{"i":{"x":0.833,"y":0.726},"o":{"x":0.167,"y":0.21},"t":2,"s":[156.792,0,0],"to":[-4.618,0,0],"ti":[6.016,0,0]},{"i":{"x":0.833,"y":0.827},"o":{"x":0.167,"y":0.12},"t":3,"s":[145.803,0,0],"to":[-6.016,0,0],"ti":[8.666,0,0]},{"i":{"x":0.833,"y":0.835},"o":{"x":0.167,"y":0.161},"t":4,"s":[120.696,0,0],"to":[-8.666,0,0],"ti":[8.874,0,0]},{"i":{"x":0.833,"y":0.877},"o":{"x":0.167,"y":0.168},"t":5,"s":[93.809,0,0],"to":[-8.874,0,0],"ti":[6.466,0,0]},{"i":{"x":0.833,"y":0.765},"o":{"x":0.167,"y":0.26},"t":6,"s":[67.451,0,0],"to":[-6.466,0,0],"ti":[5.842,0,0]},{"i":{"x":0.833,"y":0.88},"o":{"x":0.167,"y":0.129},"t":7,"s":[55.016,0,0],"to":[-5.842,0,0],"ti":[5.432,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.272},"t":8,"s":[32.4,0,0],"to":[-5.432,0,0],"ti":[1.663,0,0]},{"t":9,"s":[22.424,0,0]}],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[1000,1000,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":1,"k":[{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":0,"s":[{"i":[[-1.685,0],[0,-1.685],[1.685,0],[0,1.685]],"o":[[1.685,0],[0,1.685],[-1.685,0],[0,-1.685]],"v":[[0,-3],[3,0],[0,3],[-3,0]],"c":true}]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":10,"s":[{"i":[[-1.685,0],[0,-1.685],[1.685,0],[0,1.685]],"o":[[1.685,0],[0,1.685],[-1.685,0],[0,-1.685]],"v":[[0,-3],[3,0],[0,3],[-3,0]],"c":true}]},{"t":20,"s":[{"i":[[-9.27,0],[0,-9.27],[9.27,0],[0,9.27]],"o":[[9.27,0],[0,9.27],[-9.27,0],[0,-9.27]],"v":[[0,-16.5],[16.5,0],[0,16.5],[-16.5,0]],"c":true}]}],"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":5.5,"ix":5},"lc":1,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"fl","c":{"a":0,"k":[1,1,1,1],"ix":4},"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":10,"s":[100]},{"t":12,"s":[0]}],"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","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":"Oval","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":10,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":4,"ty":4,"nm":"Oval 2","parent":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":1,"k":[{"i":{"x":0.833,"y":0.702},"o":{"x":0.167,"y":0.167},"t":0,"s":[-180,0,0],"to":[1.081,0,0],"ti":[-3.868,0,0]},{"i":{"x":0.833,"y":0.862},"o":{"x":0.167,"y":0.116},"t":1,"s":[-173.512,0,0],"to":[3.868,0,0],"ti":[-4.618,0,0]},{"i":{"x":0.833,"y":0.726},"o":{"x":0.167,"y":0.21},"t":2,"s":[-156.792,0,0],"to":[4.618,0,0],"ti":[-6.016,0,0]},{"i":{"x":0.833,"y":0.827},"o":{"x":0.167,"y":0.12},"t":3,"s":[-145.803,0,0],"to":[6.016,0,0],"ti":[-8.666,0,0]},{"i":{"x":0.833,"y":0.835},"o":{"x":0.167,"y":0.161},"t":4,"s":[-120.696,0,0],"to":[8.666,0,0],"ti":[-8.874,0,0]},{"i":{"x":0.833,"y":0.877},"o":{"x":0.167,"y":0.168},"t":5,"s":[-93.809,0,0],"to":[8.874,0,0],"ti":[-6.466,0,0]},{"i":{"x":0.833,"y":0.765},"o":{"x":0.167,"y":0.26},"t":6,"s":[-67.451,0,0],"to":[6.466,0,0],"ti":[-5.842,0,0]},{"i":{"x":0.833,"y":0.88},"o":{"x":0.167,"y":0.129},"t":7,"s":[-55.016,0,0],"to":[5.842,0,0],"ti":[-5.432,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.272},"t":8,"s":[-32.4,0,0],"to":[5.432,0,0],"ti":[-1.663,0,0]},{"t":9,"s":[-22.424,0,0]}],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[1000,1000,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":1,"k":[{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":0,"s":[{"i":[[-1.685,0],[0,-1.685],[1.685,0],[0,1.685]],"o":[[1.685,0],[0,1.685],[-1.685,0],[0,-1.685]],"v":[[0,-3],[3,0],[0,3],[-3,0]],"c":true}]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":10,"s":[{"i":[[-1.685,0],[0,-1.685],[1.685,0],[0,1.685]],"o":[[1.685,0],[0,1.685],[-1.685,0],[0,-1.685]],"v":[[0,-3],[3,0],[0,3],[-3,0]],"c":true}]},{"t":20,"s":[{"i":[[-9.27,0],[0,-9.27],[9.27,0],[0,9.27]],"o":[[9.27,0],[0,9.27],[-9.27,0],[0,-9.27]],"v":[[0,-16.5],[16.5,0],[0,16.5],[-16.5,0]],"c":true}]}],"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":5.5,"ix":5},"lc":1,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"fl","c":{"a":0,"k":[1,1,1,1],"ix":4},"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":10,"s":[100]},{"t":12,"s":[0]}],"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","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":"Oval","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":10,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":5,"ty":4,"nm":"Oval","parent":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":1,"k":[{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":0,"s":[0,0,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":1,"s":[0,0,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":2,"s":[0,0,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":3,"s":[0,0,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":4,"s":[0,0,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":5,"s":[0,0,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":6,"s":[0,0,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":7,"s":[0,0,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":8,"s":[0,0,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.332},"o":{"x":0.167,"y":0.083},"t":9,"s":[0,0,0],"to":[-0.087,-0.103,0],"ti":[0.704,0.832,0]},{"i":{"x":0.833,"y":0.852},"o":{"x":0.167,"y":0.095},"t":10,"s":[-0.523,-0.618,0],"to":[-0.704,-0.832,0],"ti":[1.095,1.294,0]},{"i":{"x":0.833,"y":0.711},"o":{"x":0.167,"y":0.191},"t":11,"s":[-4.222,-4.99,0],"to":[-1.095,-1.294,0],"ti":[1.657,1.958,0]},{"i":{"x":0.833,"y":0.822},"o":{"x":0.167,"y":0.117},"t":12,"s":[-7.091,-8.381,0],"to":[-1.657,-1.958,0],"ti":[2.52,2.978,0]},{"i":{"x":0.833,"y":0.874},"o":{"x":0.167,"y":0.157},"t":13,"s":[-14.165,-16.741,0],"to":[-2.52,-2.978,0],"ti":[2.028,2.397,0]},{"i":{"x":0.833,"y":0.754},"o":{"x":0.167,"y":0.246},"t":14,"s":[-22.209,-26.247,0],"to":[-2.028,-2.397,0],"ti":[2.03,2.399,0]},{"i":{"x":0.833,"y":0.84},"o":{"x":0.167,"y":0.126},"t":15,"s":[-26.336,-31.124,0],"to":[-2.03,-2.399,0],"ti":[2.573,3.04,0]},{"i":{"x":0.833,"y":0.879},"o":{"x":0.167,"y":0.174},"t":16,"s":[-34.39,-40.643,0],"to":[-2.573,-3.04,0],"ti":[1.785,2.11,0]},{"i":{"x":0.833,"y":0.771},"o":{"x":0.167,"y":0.268},"t":17,"s":[-41.772,-49.366,0],"to":[-1.785,-2.11,0],"ti":[1.521,1.798,0]},{"i":{"x":0.833,"y":0.851},"o":{"x":0.167,"y":0.131},"t":18,"s":[-45.1,-53.3,0],"to":[-1.521,-1.798,0],"ti":[1.729,2.044,0]},{"i":{"x":0.833,"y":0.883},"o":{"x":0.167,"y":0.189},"t":19,"s":[-50.899,-60.153,0],"to":[-1.729,-2.044,0],"ti":[1.068,1.262,0]},{"i":{"x":0.833,"y":0.79},"o":{"x":0.167,"y":0.292},"t":20,"s":[-55.477,-65.563,0],"to":[-1.068,-1.262,0],"ti":[0.767,0.907,0]},{"i":{"x":0.833,"y":0.865},"o":{"x":0.167,"y":0.138},"t":21,"s":[-57.304,-67.723,0],"to":[-0.767,-0.907,0],"ti":[0.748,0.883,0]},{"i":{"x":0.833,"y":0.892},"o":{"x":0.167,"y":0.219},"t":22,"s":[-60.081,-71.005,0],"to":[-0.748,-0.883,0],"ti":[0.368,0.435,0]},{"i":{"x":0.833,"y":0.848},"o":{"x":0.167,"y":0.367},"t":23,"s":[-61.789,-73.024,0],"to":[-0.368,-0.435,0],"ti":[0.152,0.18,0]},{"i":{"x":0.833,"y":0.87},"o":{"x":0.167,"y":0.185},"t":24,"s":[-62.292,-73.617,0],"to":[-0.152,-0.18,0],"ti":[0.031,0.037,0]},{"i":{"x":0.833,"y":0.811},"o":{"x":0.167,"y":0.232},"t":25,"s":[-62.704,-74.105,0],"to":[-0.031,-0.037,0],"ti":[-0.086,-0.102,0]},{"i":{"x":0.833,"y":0.677},"o":{"x":0.167,"y":0.149},"t":26,"s":[-62.48,-73.84,0],"to":[0.086,0.102,0],"ti":[-0.19,-0.224,0]},{"i":{"x":0.833,"y":0.812},"o":{"x":0.167,"y":0.112},"t":27,"s":[-62.187,-73.493,0],"to":[0.19,0.224,0],"ti":[-0.317,-0.375,0]},{"i":{"x":0.833,"y":0.872},"o":{"x":0.167,"y":0.15},"t":28,"s":[-61.343,-72.496,0],"to":[0.317,0.375,0],"ti":[-0.272,-0.321,0]},{"i":{"x":0.833,"y":0.748},"o":{"x":0.167,"y":0.238},"t":29,"s":[-60.282,-71.243,0],"to":[0.272,0.321,0],"ti":[-0.287,-0.339,0]},{"i":{"x":0.833,"y":0.837},"o":{"x":0.167,"y":0.125},"t":30,"s":[-59.712,-70.569,0],"to":[0.287,0.339,0],"ti":[-0.375,-0.443,0]},{"i":{"x":0.833,"y":0.878},"o":{"x":0.167,"y":0.171},"t":31,"s":[-58.559,-69.207,0],"to":[0.375,0.443,0],"ti":[-0.268,-0.316,0]},{"i":{"x":0.833,"y":0.768},"o":{"x":0.167,"y":0.263},"t":32,"s":[-57.461,-67.909,0],"to":[0.268,0.316,0],"ti":[-0.236,-0.279,0]},{"i":{"x":0.833,"y":0.848},"o":{"x":0.167,"y":0.13},"t":33,"s":[-56.953,-67.308,0],"to":[0.236,0.279,0],"ti":[-0.276,-0.326,0]},{"i":{"x":0.833,"y":0.882},"o":{"x":0.167,"y":0.185},"t":34,"s":[-56.043,-66.233,0],"to":[0.276,0.326,0],"ti":[-0.176,-0.207,0]},{"i":{"x":0.833,"y":0.785},"o":{"x":0.167,"y":0.285},"t":35,"s":[-55.298,-65.352,0],"to":[0.176,0.207,0],"ti":[-0.133,-0.157,0]},{"i":{"x":0.833,"y":0.861},"o":{"x":0.167,"y":0.136},"t":36,"s":[-54.99,-64.989,0],"to":[0.133,0.157,0],"ti":[-0.136,-0.16,0]},{"i":{"x":0.833,"y":0.889},"o":{"x":0.167,"y":0.208},"t":37,"s":[-54.503,-64.412,0],"to":[0.136,0.16,0],"ti":[-0.073,-0.086,0]},{"i":{"x":0.833,"y":0.822},"o":{"x":0.167,"y":0.333},"t":38,"s":[-54.176,-64.026,0],"to":[0.073,0.086,0],"ti":[-0.039,-0.046,0]},{"i":{"x":0.833,"y":0.903},"o":{"x":0.167,"y":0.157},"t":39,"s":[-54.067,-63.897,0],"to":[0.039,0.046,0],"ti":[-0.024,-0.028,0]},{"i":{"x":0.833,"y":0.825},"o":{"x":0.167,"y":0.604},"t":40,"s":[-53.943,-63.751,0],"to":[0.024,0.028,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.57},"o":{"x":0.167,"y":0.161},"t":41,"s":[-53.924,-63.728,0],"to":[0,0,0],"ti":[0.019,0.022,0]},{"i":{"x":0.833,"y":0.793},"o":{"x":0.167,"y":0.103},"t":42,"s":[-53.945,-63.754,0],"to":[-0.019,-0.022,0],"ti":[0.037,0.044,0]},{"i":{"x":0.833,"y":0.869},"o":{"x":0.167,"y":0.14},"t":43,"s":[-54.035,-63.86,0],"to":[-0.037,-0.044,0],"ti":[0.035,0.041,0]},{"i":{"x":0.833,"y":0.741},"o":{"x":0.167,"y":0.229},"t":44,"s":[-54.168,-64.017,0],"to":[-0.035,-0.041,0],"ti":[0.039,0.047,0]},{"i":{"x":0.833,"y":0.834},"o":{"x":0.167,"y":0.123},"t":45,"s":[-54.244,-64.106,0],"to":[-0.039,-0.047,0],"ti":[0.053,0.063,0]},{"i":{"x":0.833,"y":0.877},"o":{"x":0.167,"y":0.167},"t":46,"s":[-54.404,-64.296,0],"to":[-0.053,-0.063,0],"ti":[0.039,0.046,0]},{"i":{"x":0.833,"y":0.764},"o":{"x":0.167,"y":0.258},"t":47,"s":[-54.564,-64.485,0],"to":[-0.039,-0.046,0],"ti":[0.036,0.042,0]},{"i":{"x":0.833,"y":0.846},"o":{"x":0.167,"y":0.129},"t":48,"s":[-54.64,-64.575,0],"to":[-0.036,-0.042,0],"ti":[0.043,0.051,0]},{"i":{"x":0.833,"y":0.881},"o":{"x":0.167,"y":0.181},"t":49,"s":[-54.78,-64.74,0],"to":[-0.043,-0.051,0],"ti":[0.028,0.033,0]},{"i":{"x":0.833,"y":0.78},"o":{"x":0.167,"y":0.279},"t":50,"s":[-54.898,-64.88,0],"to":[-0.028,-0.033,0],"ti":[0.022,0.026,0]},{"i":{"x":0.833,"y":0.857},"o":{"x":0.167,"y":0.134},"t":51,"s":[-54.949,-64.939,0],"to":[-0.022,-0.026,0],"ti":[0.024,0.028,0]},{"i":{"x":0.833,"y":0.887},"o":{"x":0.167,"y":0.2},"t":52,"s":[-55.031,-65.037,0],"to":[-0.024,-0.028,0],"ti":[0.013,0.016,0]},{"i":{"x":0.833,"y":0.808},"o":{"x":0.167,"y":0.314},"t":53,"s":[-55.091,-65.107,0],"to":[-0.013,-0.016,0],"ti":[0.008,0.01,0]},{"i":{"x":0.833,"y":0.884},"o":{"x":0.167,"y":0.147},"t":54,"s":[-55.112,-65.132,0],"to":[-0.008,-0.01,0],"ti":[0.006,0.008,0]},{"i":{"x":0.833,"y":0.899},"o":{"x":0.167,"y":0.293},"t":55,"s":[-55.14,-65.165,0],"to":[-0.006,-0.008,0],"ti":[0.002,0.002,0]},{"i":{"x":0.833,"y":0.607},"o":{"x":0.167,"y":0.541},"t":56,"s":[-55.151,-65.178,0],"to":[-0.002,-0.002,0],"ti":[-0.001,-0.001,0]},{"i":{"x":0.833,"y":0.744},"o":{"x":0.167,"y":0.109},"t":57,"s":[-55.151,-65.179,0],"to":[0.001,0.001,0],"ti":[-0.004,-0.004,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.124},"t":58,"s":[-55.144,-65.17,0],"to":[0.004,0.004,0],"ti":[-0.003,-0.003,0]},{"t":59,"s":[-55.128,-65.152,0]}],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[1000,1000,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":1,"k":[{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":0,"s":[{"i":[[-1.685,0],[0,-1.685],[1.685,0],[0,1.685]],"o":[[1.685,0],[0,1.685],[-1.685,0],[0,-1.685]],"v":[[0,-3],[3,0],[0,3],[-3,0]],"c":true}]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":10,"s":[{"i":[[-1.685,0],[0,-1.685],[1.685,0],[0,1.685]],"o":[[1.685,0],[0,1.685],[-1.685,0],[0,-1.685]],"v":[[0,-3],[3,0],[0,3],[-3,0]],"c":true}]},{"t":20,"s":[{"i":[[-9.27,0],[0,-9.27],[9.27,0],[0,9.27]],"o":[[9.27,0],[0,9.27],[-9.27,0],[0,-9.27]],"v":[[0,-16.5],[16.5,0],[0,16.5],[-16.5,0]],"c":true}]}],"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":5.5,"ix":5},"lc":1,"lj":1,"ml":4,"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":"Oval","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"fl","c":{"a":0,"k":[1,1,1,1],"ix":4},"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":10,"s":[100]},{"t":12,"s":[0]}],"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false}],"ip":0,"op":60,"st":0,"ct":1,"bm":0}]},{"id":"comp_1","nm":"Comp 1","fr":60,"layers":[{"ddd":0,"ind":1,"ty":3,"nm":"Null 2","sr":1,"ks":{"o":{"a":0,"k":0,"ix":11},"r":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.702]},"o":{"x":[0.167],"y":[0.167]},"t":0,"s":[0]},{"i":{"x":[0.833],"y":[0.862]},"o":{"x":[0.167],"y":[0.116]},"t":1,"s":[3.244]},{"i":{"x":[0.833],"y":[0.726]},"o":{"x":[0.167],"y":[0.21]},"t":2,"s":[11.604]},{"i":{"x":[0.833],"y":[0.827]},"o":{"x":[0.167],"y":[0.12]},"t":3,"s":[17.098]},{"i":{"x":[0.833],"y":[0.835]},"o":{"x":[0.167],"y":[0.161]},"t":4,"s":[29.652]},{"i":{"x":[0.833],"y":[0.877]},"o":{"x":[0.167],"y":[0.168]},"t":5,"s":[43.095]},{"i":{"x":[0.833],"y":[0.765]},"o":{"x":[0.167],"y":[0.26]},"t":6,"s":[56.275]},{"i":{"x":[0.833],"y":[0.88]},"o":{"x":[0.167],"y":[0.129]},"t":7,"s":[62.492]},{"i":{"x":[0.833],"y":[0.775]},"o":{"x":[0.167],"y":[0.272]},"t":8,"s":[73.8]},{"i":{"x":[0.833],"y":[0.853]},"o":{"x":[0.167],"y":[0.132]},"t":9,"s":[78.788]},{"i":{"x":[0.833],"y":[0.884]},"o":{"x":[0.167],"y":[0.193]},"t":10,"s":[87.288]},{"i":{"x":[0.833],"y":[0.796]},"o":{"x":[0.167],"y":[0.299]},"t":11,"s":[93.771]},{"i":{"x":[0.833],"y":[0.871]},"o":{"x":[0.167],"y":[0.141]},"t":12,"s":[96.275]},{"i":{"x":[0.833],"y":[0.897]},"o":{"x":[0.167],"y":[0.234]},"t":13,"s":[99.916]},{"i":{"x":[0.833],"y":[0.897]},"o":{"x":[0.167],"y":[0.429]},"t":14,"s":[101.932]},{"i":{"x":[0.833],"y":[1.471]},"o":{"x":[0.167],"y":[0.431]},"t":15,"s":[102.418]},{"i":{"x":[0.833],"y":[0.849]},"o":{"x":[0.167],"y":[0.071]},"t":16,"s":[102.534]},{"i":{"x":[0.833],"y":[0.707]},"o":{"x":[0.167],"y":[0.186]},"t":17,"s":[101.76]},{"i":{"x":[0.833],"y":[0.821]},"o":{"x":[0.167],"y":[0.116]},"t":18,"s":[101.129]},{"i":{"x":[0.833],"y":[0.874]},"o":{"x":[0.167],"y":[0.156]},"t":19,"s":[99.541]},{"i":{"x":[0.833],"y":[0.753]},"o":{"x":[0.167],"y":[0.245]},"t":20,"s":[97.71]},{"i":{"x":[0.833],"y":[0.84]},"o":{"x":[0.167],"y":[0.126]},"t":21,"s":[96.764]},{"i":{"x":[0.833],"y":[0.879]},"o":{"x":[0.167],"y":[0.174]},"t":22,"s":[94.908]},{"i":{"x":[0.833],"y":[0.771]},"o":{"x":[0.167],"y":[0.267]},"t":23,"s":[93.195]},{"i":{"x":[0.833],"y":[0.85]},"o":{"x":[0.167],"y":[0.131]},"t":24,"s":[92.42]},{"i":{"x":[0.833],"y":[0.883]},"o":{"x":[0.167],"y":[0.188]},"t":25,"s":[91.063]},{"i":{"x":[0.833],"y":[0.789]},"o":{"x":[0.167],"y":[0.291]},"t":26,"s":[89.984]},{"i":{"x":[0.833],"y":[0.865]},"o":{"x":[0.167],"y":[0.138]},"t":27,"s":[89.551]},{"i":{"x":[0.833],"y":[0.891]},"o":{"x":[0.167],"y":[0.217]},"t":28,"s":[88.888]},{"i":{"x":[0.833],"y":[0.842]},"o":{"x":[0.167],"y":[0.359]},"t":29,"s":[88.473]},{"i":{"x":[0.833],"y":[0.945]},"o":{"x":[0.167],"y":[0.177]},"t":30,"s":[88.347]},{"i":{"x":[0.833],"y":[0.781]},"o":{"x":[0.167],"y":[-0.159]},"t":31,"s":[88.236]},{"i":{"x":[0.833],"y":[0.667]},"o":{"x":[0.167],"y":[0.135]},"t":32,"s":[88.274]},{"i":{"x":[0.833],"y":[0.81]},"o":{"x":[0.167],"y":[0.111]},"t":33,"s":[88.337]},{"i":{"x":[0.833],"y":[0.871]},"o":{"x":[0.167],"y":[0.148]},"t":34,"s":[88.523]},{"i":{"x":[0.833],"y":[0.747]},"o":{"x":[0.167],"y":[0.237]},"t":35,"s":[88.763]},{"i":{"x":[0.833],"y":[0.837]},"o":{"x":[0.167],"y":[0.124]},"t":36,"s":[88.893]},{"i":{"x":[0.833],"y":[0.878]},"o":{"x":[0.167],"y":[0.17]},"t":37,"s":[89.157]},{"i":{"x":[0.833],"y":[0.767]},"o":{"x":[0.167],"y":[0.262]},"t":38,"s":[89.411]},{"i":{"x":[0.833],"y":[0.848]},"o":{"x":[0.167],"y":[0.13]},"t":39,"s":[89.529]},{"i":{"x":[0.833],"y":[0.882]},"o":{"x":[0.167],"y":[0.184]},"t":40,"s":[89.741]},{"i":{"x":[0.833],"y":[0.784]},"o":{"x":[0.167],"y":[0.284]},"t":41,"s":[89.916]},{"i":{"x":[0.833],"y":[0.86]},"o":{"x":[0.167],"y":[0.136]},"t":42,"s":[89.989]},{"i":{"x":[0.833],"y":[0.888]},"o":{"x":[0.167],"y":[0.206]},"t":43,"s":[90.104]},{"i":{"x":[0.833],"y":[0.819]},"o":{"x":[0.167],"y":[0.329]},"t":44,"s":[90.183]},{"i":{"x":[0.833],"y":[0.899]},"o":{"x":[0.167],"y":[0.155]},"t":45,"s":[90.21]},{"i":{"x":[0.833],"y":[0.969]},"o":{"x":[0.167],"y":[0.48]},"t":46,"s":[90.241]},{"i":{"x":[0.833],"y":[0.524]},"o":{"x":[0.167],"y":[-0.05]},"t":47,"s":[90.247]},{"i":{"x":[0.833],"y":[0.789]},"o":{"x":[0.167],"y":[0.101]},"t":48,"s":[90.243]},{"i":{"x":[0.833],"y":[0.868]},"o":{"x":[0.167],"y":[0.138]},"t":49,"s":[90.224]},{"i":{"x":[0.833],"y":[0.739]},"o":{"x":[0.167],"y":[0.227]},"t":50,"s":[90.194]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.123]},"t":51,"s":[90.177]},{"i":{"x":[0.833],"y":[0.877]},"o":{"x":[0.167],"y":[0.166]},"t":52,"s":[90.14]},{"i":{"x":[0.833],"y":[0.763]},"o":{"x":[0.167],"y":[0.257]},"t":53,"s":[90.104]},{"i":{"x":[0.833],"y":[0.845]},"o":{"x":[0.167],"y":[0.129]},"t":54,"s":[90.086]},{"i":{"x":[0.833],"y":[0.881]},"o":{"x":[0.167],"y":[0.181]},"t":55,"s":[90.054]},{"i":{"x":[0.833],"y":[0.779]},"o":{"x":[0.167],"y":[0.278]},"t":56,"s":[90.026]},{"i":{"x":[0.833],"y":[0.857]},"o":{"x":[0.167],"y":[0.134]},"t":57,"s":[90.014]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.199]},"t":58,"s":[89.994]},{"t":59,"s":[89.98]}],"ix":10},"p":{"a":0,"k":[360,360,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"ip":0,"op":60,"st":0,"bm":0},{"ddd":0,"ind":2,"ty":4,"nm":"Path","parent":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":1,"k":[{"i":{"x":0.2,"y":1},"o":{"x":0.167,"y":0.167},"t":0,"s":[145,135,0],"to":[-24.167,-22.5,0],"ti":[24.167,22.5,0]},{"t":15,"s":[0,0,0]}],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[1000,1000,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":[[8,8],[-8,-8]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"tm","s":{"a":0,"k":0,"ix":1},"e":{"a":1,"k":[{"i":{"x":[0.4],"y":[1]},"o":{"x":[0.167],"y":[0.167]},"t":0,"s":[100]},{"t":10,"s":[0]}],"ix":2},"o":{"a":0,"k":0,"ix":3},"m":1,"ix":2,"nm":"Trim Paths 1","mn":"ADBE Vector Filter - Trim","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":5.5,"ix":5},"lc":2,"lj":1,"ml":4,"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":"Path","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":60,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":3,"ty":4,"nm":"Oval 3","parent":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":1,"k":[{"i":{"x":0.833,"y":0.702},"o":{"x":0.167,"y":0.167},"t":0,"s":[-55,-65,0],"to":[0.33,0.391,0],"ti":[-1.182,-1.397,0]},{"i":{"x":0.833,"y":0.862},"o":{"x":0.167,"y":0.116},"t":1,"s":[-53.017,-62.657,0],"to":[1.182,1.397,0],"ti":[-1.411,-1.668,0]},{"i":{"x":0.833,"y":0.726},"o":{"x":0.167,"y":0.21},"t":2,"s":[-47.909,-56.619,0],"to":[1.411,1.668,0],"ti":[-1.838,-2.172,0]},{"i":{"x":0.833,"y":0.827},"o":{"x":0.167,"y":0.12},"t":3,"s":[-44.551,-52.651,0],"to":[1.838,2.172,0],"ti":[-2.648,-3.129,0]},{"i":{"x":0.833,"y":0.835},"o":{"x":0.167,"y":0.161},"t":4,"s":[-36.879,-43.585,0],"to":[2.648,3.129,0],"ti":[-2.712,-3.205,0]},{"i":{"x":0.833,"y":0.877},"o":{"x":0.167,"y":0.168},"t":5,"s":[-28.664,-33.876,0],"to":[2.712,3.205,0],"ti":[-1.976,-2.335,0]},{"i":{"x":0.833,"y":0.765},"o":{"x":0.167,"y":0.26},"t":6,"s":[-20.61,-24.357,0],"to":[1.976,2.335,0],"ti":[-1.785,-2.11,0]},{"i":{"x":0.833,"y":0.88},"o":{"x":0.167,"y":0.129},"t":7,"s":[-16.81,-19.867,0],"to":[1.785,2.11,0],"ti":[-1.66,-1.962,0]},{"i":{"x":0.833,"y":0.752},"o":{"x":0.167,"y":0.272},"t":8,"s":[-9.9,-11.7,0],"to":[1.66,1.962,0],"ti":[-1.659,-1.624,0]},{"i":{"x":0.833,"y":0.767},"o":{"x":0.167,"y":0.126},"t":9,"s":[-6.852,-8.098,0],"to":[1.659,1.624,0],"ti":[-3.829,-1.803,0]},{"i":{"x":0.833,"y":0.862},"o":{"x":0.167,"y":0.13},"t":10,"s":[0.053,-1.959,0],"to":[3.829,1.803,0],"ti":[-4.498,-1.082,0]},{"i":{"x":0.833,"y":0.725},"o":{"x":0.167,"y":0.209},"t":11,"s":[16.122,2.723,0],"to":[4.498,1.082,0],"ti":[-6.049,-0.74,0]},{"i":{"x":0.833,"y":0.827},"o":{"x":0.167,"y":0.12},"t":12,"s":[27.043,4.532,0],"to":[6.049,0.74,0],"ti":[-8.822,-0.681,0]},{"i":{"x":0.833,"y":0.875},"o":{"x":0.167,"y":0.16},"t":13,"s":[52.418,7.161,0],"to":[8.822,0.681,0],"ti":[-6.894,-0.301,0]},{"i":{"x":0.833,"y":0.757},"o":{"x":0.167,"y":0.25},"t":14,"s":[79.976,8.617,0],"to":[6.894,0.301,0],"ti":[-6.706,-0.073,0]},{"i":{"x":0.833,"y":0.842},"o":{"x":0.167,"y":0.127},"t":15,"s":[93.779,8.969,0],"to":[6.706,0.073,0],"ti":[-8.352,0.079,0]},{"i":{"x":0.833,"y":0.88},"o":{"x":0.167,"y":0.176},"t":16,"s":[120.209,9.053,0],"to":[8.352,-0.079,0],"ti":[-5.699,0.169,0]},{"i":{"x":0.833,"y":0.774},"o":{"x":0.167,"y":0.271},"t":17,"s":[143.894,8.493,0],"to":[5.699,-0.169,0],"ti":[-4.753,0.267,0]},{"i":{"x":0.833,"y":0.852},"o":{"x":0.167,"y":0.132},"t":18,"s":[154.401,8.038,0],"to":[4.753,-0.267,0],"ti":[-5.312,0.411,0]},{"i":{"x":0.833,"y":0.884},"o":{"x":0.167,"y":0.191},"t":19,"s":[172.409,6.891,0],"to":[5.312,-0.411,0],"ti":[-3.211,0.334,0]},{"i":{"x":0.833,"y":0.793},"o":{"x":0.167,"y":0.296},"t":20,"s":[186.271,5.569,0],"to":[3.211,-0.334,0],"ti":[-2.226,0.337,0]},{"i":{"x":0.833,"y":0.868},"o":{"x":0.167,"y":0.14},"t":21,"s":[191.675,4.885,0],"to":[2.226,-0.337,0],"ti":[-2.083,0.43,0]},{"i":{"x":0.833,"y":0.893},"o":{"x":0.167,"y":0.226},"t":22,"s":[199.628,3.544,0],"to":[2.083,-0.43,0],"ti":[-0.952,0.299,0]},{"i":{"x":0.833,"y":0.842},"o":{"x":0.167,"y":0.382},"t":23,"s":[204.173,2.308,0],"to":[0.952,-0.299,0],"ti":[-0.282,0.257,0]},{"i":{"x":0.833,"y":0.802},"o":{"x":0.167,"y":0.177},"t":24,"s":[205.343,1.748,0],"to":[0.282,-0.257,0],"ti":[0.145,0.293,0]},{"i":{"x":0.833,"y":0.851},"o":{"x":0.167,"y":0.144},"t":25,"s":[205.862,0.767,0],"to":[-0.145,-0.293,0],"ti":[0.436,0.182,0]},{"i":{"x":0.833,"y":0.706},"o":{"x":0.167,"y":0.189},"t":26,"s":[204.471,-0.011,0],"to":[-0.436,-0.182,0],"ti":[0.732,0.132,0]},{"i":{"x":0.833,"y":0.819},"o":{"x":0.167,"y":0.116},"t":27,"s":[203.246,-0.324,0],"to":[-0.732,-0.132,0],"ti":[1.149,0.13,0]},{"i":{"x":0.833,"y":0.873},"o":{"x":0.167,"y":0.155},"t":28,"s":[200.079,-0.803,0],"to":[-1.149,-0.13,0],"ti":[0.945,0.065,0]},{"i":{"x":0.833,"y":0.752},"o":{"x":0.167,"y":0.243},"t":29,"s":[196.354,-1.103,0],"to":[-0.945,-0.065,0],"ti":[0.964,0.029,0]},{"i":{"x":0.833,"y":0.839},"o":{"x":0.167,"y":0.126},"t":30,"s":[194.411,-1.194,0],"to":[-0.964,-0.029,0],"ti":[1.235,0.009,0]},{"i":{"x":0.833,"y":0.879},"o":{"x":0.167,"y":0.173},"t":31,"s":[190.571,-1.274,0],"to":[-1.235,-0.009,0],"ti":[0.866,-0.012,0]},{"i":{"x":0.833,"y":0.77},"o":{"x":0.167,"y":0.266},"t":32,"s":[187,-1.246,0],"to":[-0.866,0.012,0],"ti":[0.748,-0.03,0]},{"i":{"x":0.833,"y":0.85},"o":{"x":0.167,"y":0.131},"t":33,"s":[185.374,-1.201,0],"to":[-0.748,0.03,0],"ti":[0.859,-0.051,0]},{"i":{"x":0.833,"y":0.883},"o":{"x":0.167,"y":0.187},"t":34,"s":[182.512,-1.067,0],"to":[-0.859,0.051,0],"ti":[0.537,-0.044,0]},{"i":{"x":0.833,"y":0.787},"o":{"x":0.167,"y":0.289},"t":35,"s":[180.22,-0.894,0],"to":[-0.537,0.044,0],"ti":[0.394,-0.047,0]},{"i":{"x":0.833,"y":0.863},"o":{"x":0.167,"y":0.137},"t":36,"s":[179.292,-0.8,0],"to":[-0.394,0.047,0],"ti":[0.392,-0.062,0]},{"i":{"x":0.833,"y":0.89},"o":{"x":0.167,"y":0.212},"t":37,"s":[177.858,-0.609,0],"to":[-0.392,0.062,0],"ti":[0.2,-0.045,0]},{"i":{"x":0.833,"y":0.828},"o":{"x":0.167,"y":0.344},"t":38,"s":[176.943,-0.425,0],"to":[-0.2,0.045,0],"ti":[0.093,-0.04,0]},{"i":{"x":0.833,"y":0.878},"o":{"x":0.167,"y":0.162},"t":39,"s":[176.658,-0.34,0],"to":[-0.093,0.04,0],"ti":[0.039,-0.047,0]},{"i":{"x":0.833,"y":0.845},"o":{"x":0.167,"y":0.261},"t":40,"s":[176.382,-0.187,0],"to":[-0.039,0.047,0],"ti":[-0.027,-0.03,0]},{"i":{"x":0.833,"y":0.675},"o":{"x":0.167,"y":0.179},"t":41,"s":[176.426,-0.061,0],"to":[0.027,0.03,0],"ti":[-0.08,-0.023,0]},{"i":{"x":0.833,"y":0.808},"o":{"x":0.167,"y":0.112},"t":42,"s":[176.541,-0.008,0],"to":[0.08,0.023,0],"ti":[-0.141,-0.023,0]},{"i":{"x":0.833,"y":0.871},"o":{"x":0.167,"y":0.148},"t":43,"s":[176.906,0.075,0],"to":[0.141,0.023,0],"ti":[-0.125,-0.013,0]},{"i":{"x":0.833,"y":0.746},"o":{"x":0.167,"y":0.236},"t":44,"s":[177.389,0.132,0],"to":[0.125,0.013,0],"ti":[-0.135,-0.007,0]},{"i":{"x":0.833,"y":0.836},"o":{"x":0.167,"y":0.124},"t":45,"s":[177.654,0.151,0],"to":[0.135,0.007,0],"ti":[-0.178,-0.005,0]},{"i":{"x":0.833,"y":0.878},"o":{"x":0.167,"y":0.169},"t":46,"s":[178.198,0.174,0],"to":[0.178,0.005,0],"ti":[-0.129,0,0]},{"i":{"x":0.833,"y":0.766},"o":{"x":0.167,"y":0.261},"t":47,"s":[178.724,0.179,0],"to":[0.129,0,0],"ti":[-0.115,0.003,0]},{"i":{"x":0.833,"y":0.847},"o":{"x":0.167,"y":0.129},"t":48,"s":[178.971,0.176,0],"to":[0.115,-0.003,0],"ti":[-0.136,0.006,0]},{"i":{"x":0.833,"y":0.882},"o":{"x":0.167,"y":0.184},"t":49,"s":[179.416,0.162,0],"to":[0.136,-0.006,0],"ti":[-0.087,0.006,0]},{"i":{"x":0.833,"y":0.783},"o":{"x":0.167,"y":0.282},"t":50,"s":[179.786,0.14,0],"to":[0.087,-0.006,0],"ti":[-0.067,0.006,0]},{"i":{"x":0.833,"y":0.859},"o":{"x":0.167,"y":0.135},"t":51,"s":[179.94,0.128,0],"to":[0.067,-0.006,0],"ti":[-0.07,0.009,0]},{"i":{"x":0.833,"y":0.888},"o":{"x":0.167,"y":0.204},"t":52,"s":[180.189,0.101,0],"to":[0.07,-0.009,0],"ti":[-0.038,0.007,0]},{"i":{"x":0.833,"y":0.813},"o":{"x":0.167,"y":0.322},"t":53,"s":[180.36,0.075,0],"to":[0.038,-0.007,0],"ti":[-0.022,0.006,0]},{"i":{"x":0.833,"y":0.885},"o":{"x":0.167,"y":0.15},"t":54,"s":[180.418,0.062,0],"to":[0.022,-0.006,0],"ti":[-0.015,0.007,0]},{"i":{"x":0.833,"y":0.88},"o":{"x":0.167,"y":0.302},"t":55,"s":[180.49,0.039,0],"to":[0.015,-0.007,0],"ti":[-0.002,0.005,0]},{"i":{"x":0.833,"y":0.656},"o":{"x":0.167,"y":0.275},"t":56,"s":[180.509,0.019,0],"to":[0.002,-0.005,0],"ti":[0.007,0.004,0]},{"i":{"x":0.833,"y":0.789},"o":{"x":0.167,"y":0.11},"t":57,"s":[180.503,0.01,0],"to":[-0.007,-0.004,0],"ti":[0.016,0.004,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.138},"t":58,"s":[180.467,-0.004,0],"to":[-0.016,-0.004,0],"ti":[0.01,0.002,0]},{"t":59,"s":[180.408,-0.014,0]}],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[1000,1000,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":1,"k":[{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":0,"s":[{"i":[[-9.27,0],[0,-9.27],[9.27,0],[0,9.27]],"o":[[9.27,0],[0,9.27],[-9.27,0],[0,-9.27]],"v":[[0,-16.5],[16.5,0],[0,16.5],[-16.5,0]],"c":true}]},{"t":15,"s":[{"i":[[-1.685,0],[0,-1.685],[1.685,0],[0,1.685]],"o":[[1.685,0],[0,1.685],[-1.685,0],[0,-1.685]],"v":[[0,-3],[3,0],[0,3],[-3,0]],"c":true}]}],"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":5.5,"ix":5},"lc":1,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"fl","c":{"a":0,"k":[1,1,1,1],"ix":4},"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":10,"s":[0]},{"t":11,"s":[100]}],"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","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":"Oval","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":60,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":4,"ty":4,"nm":"Oval 2","parent":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":1,"k":[{"i":{"x":0.833,"y":0.702},"o":{"x":0.167,"y":0.167},"t":0,"s":[-55,-65,0],"to":[0.33,0.391,0],"ti":[-1.182,-1.397,0]},{"i":{"x":0.833,"y":0.862},"o":{"x":0.167,"y":0.116},"t":1,"s":[-53.017,-62.657,0],"to":[1.182,1.397,0],"ti":[-1.411,-1.668,0]},{"i":{"x":0.833,"y":0.726},"o":{"x":0.167,"y":0.21},"t":2,"s":[-47.909,-56.619,0],"to":[1.411,1.668,0],"ti":[-1.838,-2.172,0]},{"i":{"x":0.833,"y":0.827},"o":{"x":0.167,"y":0.12},"t":3,"s":[-44.551,-52.651,0],"to":[1.838,2.172,0],"ti":[-2.648,-3.129,0]},{"i":{"x":0.833,"y":0.835},"o":{"x":0.167,"y":0.161},"t":4,"s":[-36.879,-43.585,0],"to":[2.648,3.129,0],"ti":[-2.712,-3.205,0]},{"i":{"x":0.833,"y":0.877},"o":{"x":0.167,"y":0.168},"t":5,"s":[-28.664,-33.876,0],"to":[2.712,3.205,0],"ti":[-1.976,-2.335,0]},{"i":{"x":0.833,"y":0.765},"o":{"x":0.167,"y":0.26},"t":6,"s":[-20.61,-24.357,0],"to":[1.976,2.335,0],"ti":[-1.785,-2.11,0]},{"i":{"x":0.833,"y":0.88},"o":{"x":0.167,"y":0.129},"t":7,"s":[-16.81,-19.867,0],"to":[1.785,2.11,0],"ti":[-1.66,-1.962,0]},{"i":{"x":0.833,"y":0.788},"o":{"x":0.167,"y":0.272},"t":8,"s":[-9.9,-11.7,0],"to":[1.66,1.962,0],"ti":[-1.089,-1.624,0]},{"i":{"x":0.833,"y":0.808},"o":{"x":0.167,"y":0.137},"t":9,"s":[-6.852,-8.098,0],"to":[1.089,1.624,0],"ti":[0.777,-1.803,0]},{"i":{"x":0.833,"y":0.846},"o":{"x":0.167,"y":0.147},"t":10,"s":[-3.368,-1.959,0],"to":[-0.777,1.803,0],"ti":[2.667,-1.082,0]},{"i":{"x":0.833,"y":0.699},"o":{"x":0.167,"y":0.182},"t":11,"s":[-11.514,2.723,0],"to":[-2.667,1.082,0],"ti":[4.798,-0.74,0]},{"i":{"x":0.833,"y":0.817},"o":{"x":0.167,"y":0.115},"t":12,"s":[-19.373,4.532,0],"to":[-4.798,0.74,0],"ti":[7.67,-0.681,0]},{"i":{"x":0.833,"y":0.873},"o":{"x":0.167,"y":0.153},"t":13,"s":[-40.299,7.161,0],"to":[-7.67,0.681,0],"ti":[6.384,-0.301,0]},{"i":{"x":0.833,"y":0.751},"o":{"x":0.167,"y":0.242},"t":14,"s":[-65.393,8.617,0],"to":[-6.384,0.301,0],"ti":[6.583,-0.073,0]},{"i":{"x":0.833,"y":0.839},"o":{"x":0.167,"y":0.125},"t":15,"s":[-78.602,8.969,0],"to":[-6.583,0.073,0],"ti":[8.486,0.079,0]},{"i":{"x":0.833,"y":0.878},"o":{"x":0.167,"y":0.172},"t":16,"s":[-104.889,9.053,0],"to":[-8.486,-0.079,0],"ti":[5.985,0.169,0]},{"i":{"x":0.833,"y":0.769},"o":{"x":0.167,"y":0.265},"t":17,"s":[-129.52,8.493,0],"to":[-5.985,-0.169,0],"ti":[5.205,0.267,0]},{"i":{"x":0.833,"y":0.849},"o":{"x":0.167,"y":0.13},"t":18,"s":[-140.799,8.038,0],"to":[-5.205,-0.267,0],"ti":[6.008,0.411,0]},{"i":{"x":0.833,"y":0.883},"o":{"x":0.167,"y":0.186},"t":19,"s":[-160.748,6.891,0],"to":[-6.008,-0.411,0],"ti":[3.777,0.334,0]},{"i":{"x":0.833,"y":0.786},"o":{"x":0.167,"y":0.287},"t":20,"s":[-176.848,5.569,0],"to":[-3.777,-0.334,0],"ti":[2.797,0.337,0]},{"i":{"x":0.833,"y":0.862},"o":{"x":0.167,"y":0.137},"t":21,"s":[-183.408,4.885,0],"to":[-2.797,-0.337,0],"ti":[2.81,0.43,0]},{"i":{"x":0.833,"y":0.89},"o":{"x":0.167,"y":0.211},"t":22,"s":[-193.63,3.544,0],"to":[-2.81,-0.43,0],"ti":[1.459,0.299,0]},{"i":{"x":0.833,"y":0.826},"o":{"x":0.167,"y":0.34},"t":23,"s":[-200.267,2.308,0],"to":[-1.459,-0.299,0],"ti":[0.716,0.257,0]},{"i":{"x":0.833,"y":0.885},"o":{"x":0.167,"y":0.16},"t":24,"s":[-202.385,1.748,0],"to":[-0.716,-0.257,0],"ti":[0.351,0.293,0]},{"i":{"x":0.833,"y":0.844},"o":{"x":0.167,"y":0.305},"t":25,"s":[-204.563,0.767,0],"to":[-0.351,-0.293,0],"ti":[-0.128,0.182,0]},{"i":{"x":0.833,"y":0.661},"o":{"x":0.167,"y":0.179},"t":26,"s":[-204.49,-0.011,0],"to":[0.128,-0.182,0],"ti":[-0.509,0.132,0]},{"i":{"x":0.833,"y":0.805},"o":{"x":0.167,"y":0.11},"t":27,"s":[-203.795,-0.324,0],"to":[0.509,-0.132,0],"ti":[-0.929,0.13,0]},{"i":{"x":0.833,"y":0.87},"o":{"x":0.167,"y":0.145},"t":28,"s":[-201.438,-0.803,0],"to":[0.929,-0.13,0],"ti":[-0.835,0.065,0]},{"i":{"x":0.833,"y":0.744},"o":{"x":0.167,"y":0.234},"t":29,"s":[-198.22,-1.103,0],"to":[0.835,-0.065,0],"ti":[-0.916,0.029,0]},{"i":{"x":0.833,"y":0.835},"o":{"x":0.167,"y":0.124},"t":30,"s":[-196.431,-1.194,0],"to":[0.916,-0.029,0],"ti":[-1.22,0.009,0]},{"i":{"x":0.833,"y":0.877},"o":{"x":0.167,"y":0.169},"t":31,"s":[-192.727,-1.274,0],"to":[1.22,-0.009,0],"ti":[-0.887,-0.012,0]},{"i":{"x":0.833,"y":0.765},"o":{"x":0.167,"y":0.26},"t":32,"s":[-189.11,-1.246,0],"to":[0.887,0.012,0],"ti":[-0.799,-0.03,0]},{"i":{"x":0.833,"y":0.847},"o":{"x":0.167,"y":0.129},"t":33,"s":[-187.407,-1.201,0],"to":[0.799,0.03,0],"ti":[-0.946,-0.051,0]},{"i":{"x":0.833,"y":0.882},"o":{"x":0.167,"y":0.183},"t":34,"s":[-184.317,-1.067,0],"to":[0.946,0.051,0],"ti":[-0.612,-0.044,0]},{"i":{"x":0.833,"y":0.782},"o":{"x":0.167,"y":0.281},"t":35,"s":[-181.732,-0.894,0],"to":[0.612,0.044,0],"ti":[-0.474,-0.047,0]},{"i":{"x":0.833,"y":0.858},"o":{"x":0.167,"y":0.135},"t":36,"s":[-180.645,-0.8,0],"to":[0.474,0.047,0],"ti":[-0.497,-0.062,0]},{"i":{"x":0.833,"y":0.887},"o":{"x":0.167,"y":0.202},"t":37,"s":[-178.888,-0.609,0],"to":[0.497,0.062,0],"ti":[-0.276,-0.045,0]},{"i":{"x":0.833,"y":0.811},"o":{"x":0.167,"y":0.319},"t":38,"s":[-177.662,-0.425,0],"to":[0.276,0.045,0],"ti":[-0.161,-0.04,0]},{"i":{"x":0.833,"y":0.885},"o":{"x":0.167,"y":0.149},"t":39,"s":[-177.233,-0.34,0],"to":[0.161,0.04,0],"ti":[-0.117,-0.047,0]},{"i":{"x":0.833,"y":0.886},"o":{"x":0.167,"y":0.299},"t":40,"s":[-176.698,-0.187,0],"to":[0.117,0.047,0],"ti":[-0.024,-0.03,0]},{"i":{"x":0.833,"y":0.662},"o":{"x":0.167,"y":0.313},"t":41,"s":[-176.529,-0.061,0],"to":[0.024,0.03,0],"ti":[0.042,-0.023,0]},{"i":{"x":0.833,"y":0.78},"o":{"x":0.167,"y":0.11},"t":42,"s":[-176.555,-0.008,0],"to":[-0.042,0.023,0],"ti":[0.102,-0.023,0]},{"i":{"x":0.833,"y":0.867},"o":{"x":0.167,"y":0.134},"t":43,"s":[-176.778,0.075,0],"to":[-0.102,0.023,0],"ti":[0.103,-0.013,0]},{"i":{"x":0.833,"y":0.736},"o":{"x":0.167,"y":0.223},"t":44,"s":[-177.165,0.132,0],"to":[-0.103,0.013,0],"ti":[0.123,-0.007,0]},{"i":{"x":0.833,"y":0.831},"o":{"x":0.167,"y":0.122},"t":45,"s":[-177.398,0.151,0],"to":[-0.123,0.007,0],"ti":[0.171,-0.005,0]},{"i":{"x":0.833,"y":0.876},"o":{"x":0.167,"y":0.165},"t":46,"s":[-177.903,0.174,0],"to":[-0.171,0.005,0],"ti":[0.128,0,0]},{"i":{"x":0.833,"y":0.761},"o":{"x":0.167,"y":0.255},"t":47,"s":[-178.422,0.179,0],"to":[-0.128,0,0],"ti":[0.12,0.003,0]},{"i":{"x":0.833,"y":0.844},"o":{"x":0.167,"y":0.128},"t":48,"s":[-178.674,0.176,0],"to":[-0.12,-0.003,0],"ti":[0.146,0.006,0]},{"i":{"x":0.833,"y":0.881},"o":{"x":0.167,"y":0.179},"t":49,"s":[-179.142,0.162,0],"to":[-0.146,-0.006,0],"ti":[0.097,0.006,0]},{"i":{"x":0.833,"y":0.777},"o":{"x":0.167,"y":0.276},"t":50,"s":[-179.548,0.14,0],"to":[-0.097,-0.006,0],"ti":[0.078,0.006,0]},{"i":{"x":0.833,"y":0.855},"o":{"x":0.167,"y":0.133},"t":51,"s":[-179.724,0.128,0],"to":[-0.078,-0.006,0],"ti":[0.085,0.009,0]},{"i":{"x":0.833,"y":0.885},"o":{"x":0.167,"y":0.196},"t":52,"s":[-180.017,0.101,0],"to":[-0.085,-0.009,0],"ti":[0.049,0.007,0]},{"i":{"x":0.833,"y":0.801},"o":{"x":0.167,"y":0.306},"t":53,"s":[-180.233,0.075,0],"to":[-0.049,-0.007,0],"ti":[0.032,0.006,0]},{"i":{"x":0.833,"y":0.875},"o":{"x":0.167,"y":0.143},"t":54,"s":[-180.313,0.062,0],"to":[-0.032,-0.006,0],"ti":[0.027,0.007,0]},{"i":{"x":0.833,"y":0.897},"o":{"x":0.167,"y":0.25},"t":55,"s":[-180.424,0.039,0],"to":[-0.027,-0.007,0],"ti":[0.01,0.005,0]},{"i":{"x":0.833,"y":0.798},"o":{"x":0.167,"y":0.429},"t":56,"s":[-180.478,0.019,0],"to":[-0.01,-0.005,0],"ti":[-0.001,0.004,0]},{"i":{"x":0.833,"y":0.733},"o":{"x":0.167,"y":0.142},"t":57,"s":[-180.486,0.01,0],"to":[0.001,-0.004,0],"ti":[-0.009,0.004,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.121},"t":58,"s":[-180.474,-0.004,0],"to":[0.009,-0.004,0],"ti":[-0.007,0.002,0]},{"t":59,"s":[-180.432,-0.014,0]}],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[1000,1000,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":1,"k":[{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":0,"s":[{"i":[[-9.27,0],[0,-9.27],[9.27,0],[0,9.27]],"o":[[9.27,0],[0,9.27],[-9.27,0],[0,-9.27]],"v":[[0,-16.5],[16.5,0],[0,16.5],[-16.5,0]],"c":true}]},{"t":15,"s":[{"i":[[-1.685,0],[0,-1.685],[1.685,0],[0,1.685]],"o":[[1.685,0],[0,1.685],[-1.685,0],[0,-1.685]],"v":[[0,-3],[3,0],[0,3],[-3,0]],"c":true}]}],"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":5.5,"ix":5},"lc":1,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"fl","c":{"a":0,"k":[1,1,1,1],"ix":4},"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":10,"s":[0]},{"t":11,"s":[100]}],"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","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":"Oval","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":60,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":5,"ty":4,"nm":"Oval","parent":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":1,"k":[{"i":{"x":0.833,"y":0.702},"o":{"x":0.167,"y":0.167},"t":0,"s":[-55,-65,0],"to":[0.33,0.391,0],"ti":[-1.182,-1.397,0]},{"i":{"x":0.833,"y":0.862},"o":{"x":0.167,"y":0.116},"t":1,"s":[-53.017,-62.657,0],"to":[1.182,1.397,0],"ti":[-1.411,-1.668,0]},{"i":{"x":0.833,"y":0.726},"o":{"x":0.167,"y":0.21},"t":2,"s":[-47.909,-56.619,0],"to":[1.411,1.668,0],"ti":[-1.838,-2.172,0]},{"i":{"x":0.833,"y":0.827},"o":{"x":0.167,"y":0.12},"t":3,"s":[-44.551,-52.651,0],"to":[1.838,2.172,0],"ti":[-2.648,-3.129,0]},{"i":{"x":0.833,"y":0.835},"o":{"x":0.167,"y":0.161},"t":4,"s":[-36.879,-43.585,0],"to":[2.648,3.129,0],"ti":[-2.712,-3.205,0]},{"i":{"x":0.833,"y":0.877},"o":{"x":0.167,"y":0.168},"t":5,"s":[-28.664,-33.876,0],"to":[2.712,3.205,0],"ti":[-1.976,-2.335,0]},{"i":{"x":0.833,"y":0.765},"o":{"x":0.167,"y":0.26},"t":6,"s":[-20.61,-24.357,0],"to":[1.976,2.335,0],"ti":[-1.785,-2.11,0]},{"i":{"x":0.833,"y":0.88},"o":{"x":0.167,"y":0.129},"t":7,"s":[-16.81,-19.867,0],"to":[1.785,2.11,0],"ti":[-1.66,-1.962,0]},{"i":{"x":0.833,"y":0.775},"o":{"x":0.167,"y":0.272},"t":8,"s":[-9.9,-11.7,0],"to":[1.66,1.962,0],"ti":[-1.374,-1.624,0]},{"i":{"x":0.833,"y":0.853},"o":{"x":0.167,"y":0.132},"t":9,"s":[-6.852,-8.098,0],"to":[1.374,1.624,0],"ti":[-1.526,-1.803,0]},{"i":{"x":0.833,"y":0.884},"o":{"x":0.167,"y":0.193},"t":10,"s":[-1.657,-1.959,0],"to":[1.526,1.803,0],"ti":[-0.915,-1.082,0]},{"i":{"x":0.833,"y":0.796},"o":{"x":0.167,"y":0.299},"t":11,"s":[2.304,2.723,0],"to":[0.915,1.082,0],"ti":[-0.626,-0.74,0]},{"i":{"x":0.833,"y":0.871},"o":{"x":0.167,"y":0.141},"t":12,"s":[3.835,4.532,0],"to":[0.626,0.74,0],"ti":[-0.576,-0.681,0]},{"i":{"x":0.833,"y":0.897},"o":{"x":0.167,"y":0.234},"t":13,"s":[6.06,7.161,0],"to":[0.576,0.681,0],"ti":[-0.255,-0.301,0]},{"i":{"x":0.833,"y":0.882},"o":{"x":0.167,"y":0.429},"t":14,"s":[7.292,8.617,0],"to":[0.255,0.301,0],"ti":[-0.061,-0.073,0]},{"i":{"x":0.833,"y":0.596},"o":{"x":0.167,"y":0.285},"t":15,"s":[7.589,8.969,0],"to":[0.061,0.073,0],"ti":[0.067,0.079,0]},{"i":{"x":0.833,"y":0.849},"o":{"x":0.167,"y":0.105},"t":16,"s":[7.66,9.053,0],"to":[-0.067,-0.079,0],"ti":[0.143,0.169,0]},{"i":{"x":0.833,"y":0.707},"o":{"x":0.167,"y":0.186},"t":17,"s":[7.187,8.493,0],"to":[-0.143,-0.169,0],"ti":[0.226,0.267,0]},{"i":{"x":0.833,"y":0.821},"o":{"x":0.167,"y":0.116},"t":18,"s":[6.801,8.038,0],"to":[-0.226,-0.267,0],"ti":[0.348,0.411,0]},{"i":{"x":0.833,"y":0.874},"o":{"x":0.167,"y":0.156},"t":19,"s":[5.831,6.891,0],"to":[-0.348,-0.411,0],"ti":[0.283,0.334,0]},{"i":{"x":0.833,"y":0.753},"o":{"x":0.167,"y":0.245},"t":20,"s":[4.712,5.569,0],"to":[-0.283,-0.334,0],"ti":[0.285,0.337,0]},{"i":{"x":0.833,"y":0.84},"o":{"x":0.167,"y":0.126},"t":21,"s":[4.134,4.885,0],"to":[-0.285,-0.337,0],"ti":[0.364,0.43,0]},{"i":{"x":0.833,"y":0.879},"o":{"x":0.167,"y":0.174},"t":22,"s":[2.999,3.544,0],"to":[-0.364,-0.43,0],"ti":[0.253,0.299,0]},{"i":{"x":0.833,"y":0.771},"o":{"x":0.167,"y":0.267},"t":23,"s":[1.953,2.308,0],"to":[-0.253,-0.299,0],"ti":[0.217,0.257,0]},{"i":{"x":0.833,"y":0.85},"o":{"x":0.167,"y":0.131},"t":24,"s":[1.479,1.748,0],"to":[-0.217,-0.257,0],"ti":[0.248,0.293,0]},{"i":{"x":0.833,"y":0.883},"o":{"x":0.167,"y":0.188},"t":25,"s":[0.649,0.767,0],"to":[-0.248,-0.293,0],"ti":[0.154,0.182,0]},{"i":{"x":0.833,"y":0.789},"o":{"x":0.167,"y":0.291},"t":26,"s":[-0.01,-0.011,0],"to":[-0.154,-0.182,0],"ti":[0.112,0.132,0]},{"i":{"x":0.833,"y":0.865},"o":{"x":0.167,"y":0.138},"t":27,"s":[-0.274,-0.324,0],"to":[-0.112,-0.132,0],"ti":[0.11,0.13,0]},{"i":{"x":0.833,"y":0.891},"o":{"x":0.167,"y":0.217},"t":28,"s":[-0.68,-0.803,0],"to":[-0.11,-0.13,0],"ti":[0.055,0.065,0]},{"i":{"x":0.833,"y":0.842},"o":{"x":0.167,"y":0.359},"t":29,"s":[-0.933,-1.103,0],"to":[-0.055,-0.065,0],"ti":[0.024,0.029,0]},{"i":{"x":0.833,"y":0.884},"o":{"x":0.167,"y":0.177},"t":30,"s":[-1.01,-1.194,0],"to":[-0.024,-0.029,0],"ti":[0.007,0.009,0]},{"i":{"x":0.833,"y":0.797},"o":{"x":0.167,"y":0.297},"t":31,"s":[-1.078,-1.274,0],"to":[-0.007,-0.009,0],"ti":[-0.01,-0.012,0]},{"i":{"x":0.833,"y":0.667},"o":{"x":0.167,"y":0.142},"t":32,"s":[-1.055,-1.246,0],"to":[0.01,0.012,0],"ti":[-0.025,-0.03,0]},{"i":{"x":0.833,"y":0.81},"o":{"x":0.167,"y":0.111},"t":33,"s":[-1.017,-1.201,0],"to":[0.025,0.03,0],"ti":[-0.043,-0.051,0]},{"i":{"x":0.833,"y":0.871},"o":{"x":0.167,"y":0.148},"t":34,"s":[-0.903,-1.067,0],"to":[0.043,0.051,0],"ti":[-0.038,-0.044,0]},{"i":{"x":0.833,"y":0.747},"o":{"x":0.167,"y":0.237},"t":35,"s":[-0.756,-0.894,0],"to":[0.038,0.044,0],"ti":[-0.04,-0.047,0]},{"i":{"x":0.833,"y":0.837},"o":{"x":0.167,"y":0.124},"t":36,"s":[-0.677,-0.8,0],"to":[0.04,0.047,0],"ti":[-0.053,-0.062,0]},{"i":{"x":0.833,"y":0.878},"o":{"x":0.167,"y":0.17},"t":37,"s":[-0.515,-0.609,0],"to":[0.053,0.062,0],"ti":[-0.038,-0.045,0]},{"i":{"x":0.833,"y":0.767},"o":{"x":0.167,"y":0.262},"t":38,"s":[-0.36,-0.425,0],"to":[0.038,0.045,0],"ti":[-0.034,-0.04,0]},{"i":{"x":0.833,"y":0.848},"o":{"x":0.167,"y":0.13},"t":39,"s":[-0.288,-0.34,0],"to":[0.034,0.04,0],"ti":[-0.039,-0.047,0]},{"i":{"x":0.833,"y":0.882},"o":{"x":0.167,"y":0.184},"t":40,"s":[-0.158,-0.187,0],"to":[0.039,0.047,0],"ti":[-0.025,-0.03,0]},{"i":{"x":0.833,"y":0.784},"o":{"x":0.167,"y":0.284},"t":41,"s":[-0.051,-0.061,0],"to":[0.025,0.03,0],"ti":[-0.019,-0.023,0]},{"i":{"x":0.833,"y":0.86},"o":{"x":0.167,"y":0.136},"t":42,"s":[-0.007,-0.008,0],"to":[0.019,0.023,0],"ti":[-0.02,-0.023,0]},{"i":{"x":0.833,"y":0.888},"o":{"x":0.167,"y":0.206},"t":43,"s":[0.064,0.075,0],"to":[0.02,0.023,0],"ti":[-0.011,-0.013,0]},{"i":{"x":0.833,"y":0.819},"o":{"x":0.167,"y":0.329},"t":44,"s":[0.112,0.132,0],"to":[0.011,0.013,0],"ti":[-0.006,-0.007,0]},{"i":{"x":0.833,"y":0.899},"o":{"x":0.167,"y":0.155},"t":45,"s":[0.128,0.151,0],"to":[0.006,0.007,0],"ti":[-0.004,-0.005,0]},{"i":{"x":0.833,"y":0.862},"o":{"x":0.167,"y":0.479},"t":46,"s":[0.147,0.174,0],"to":[0.004,0.005,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.524},"o":{"x":0.167,"y":0.219},"t":47,"s":[0.151,0.179,0],"to":[0,0,0],"ti":[0.002,0.003,0]},{"i":{"x":0.833,"y":0.789},"o":{"x":0.167,"y":0.102},"t":48,"s":[0.149,0.176,0],"to":[-0.002,-0.003,0],"ti":[0.005,0.006,0]},{"i":{"x":0.833,"y":0.868},"o":{"x":0.167,"y":0.138},"t":49,"s":[0.137,0.162,0],"to":[-0.005,-0.006,0],"ti":[0.005,0.006,0]},{"i":{"x":0.833,"y":0.739},"o":{"x":0.167,"y":0.227},"t":50,"s":[0.119,0.14,0],"to":[-0.005,-0.006,0],"ti":[0.005,0.006,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.122},"t":51,"s":[0.108,0.128,0],"to":[-0.005,-0.006,0],"ti":[0.007,0.009,0]},{"i":{"x":0.833,"y":0.877},"o":{"x":0.167,"y":0.166},"t":52,"s":[0.086,0.101,0],"to":[-0.007,-0.009,0],"ti":[0.006,0.007,0]},{"i":{"x":0.833,"y":0.763},"o":{"x":0.167,"y":0.257},"t":53,"s":[0.063,0.075,0],"to":[-0.006,-0.007,0],"ti":[0.005,0.006,0]},{"i":{"x":0.833,"y":0.845},"o":{"x":0.167,"y":0.129},"t":54,"s":[0.053,0.062,0],"to":[-0.005,-0.006,0],"ti":[0.006,0.007,0]},{"i":{"x":0.833,"y":0.881},"o":{"x":0.167,"y":0.181},"t":55,"s":[0.033,0.039,0],"to":[-0.006,-0.007,0],"ti":[0.004,0.005,0]},{"i":{"x":0.833,"y":0.779},"o":{"x":0.167,"y":0.278},"t":56,"s":[0.016,0.019,0],"to":[-0.004,-0.005,0],"ti":[0.003,0.004,0]},{"i":{"x":0.833,"y":0.857},"o":{"x":0.167,"y":0.134},"t":57,"s":[0.009,0.01,0],"to":[-0.003,-0.004,0],"ti":[0.003,0.004,0]},{"i":{"x":0.833,"y":0.834},"o":{"x":0.167,"y":0.199},"t":58,"s":[-0.003,-0.004,0],"to":[-0.003,-0.004,0],"ti":[0.001,0.002,0]},{"t":59,"s":[-0.012,-0.014,0]}],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[1000,1000,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":1,"k":[{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":0,"s":[{"i":[[-9.27,0],[0,-9.27],[9.27,0],[0,9.27]],"o":[[9.27,0],[0,9.27],[-9.27,0],[0,-9.27]],"v":[[0,-16.5],[16.5,0],[0,16.5],[-16.5,0]],"c":true}]},{"t":15,"s":[{"i":[[-1.685,0],[0,-1.685],[1.685,0],[0,1.685]],"o":[[1.685,0],[0,1.685],[-1.685,0],[0,-1.685]],"v":[[0,-3],[3,0],[0,3],[-3,0]],"c":true}]}],"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.702]},"o":{"x":[0.167],"y":[0.167]},"t":0,"s":[5.5]},{"i":{"x":[0.833],"y":[0.862]},"o":{"x":[0.167],"y":[0.116]},"t":1,"s":[5.716]},{"i":{"x":[0.833],"y":[0.726]},"o":{"x":[0.167],"y":[0.21]},"t":2,"s":[6.274]},{"i":{"x":[0.833],"y":[0.827]},"o":{"x":[0.167],"y":[0.12]},"t":3,"s":[6.64]},{"i":{"x":[0.833],"y":[0.835]},"o":{"x":[0.167],"y":[0.161]},"t":4,"s":[7.477]},{"i":{"x":[0.833],"y":[0.877]},"o":{"x":[0.167],"y":[0.168]},"t":5,"s":[8.373]},{"i":{"x":[0.833],"y":[0.765]},"o":{"x":[0.167],"y":[0.26]},"t":6,"s":[9.252]},{"i":{"x":[0.833],"y":[0.88]},"o":{"x":[0.167],"y":[0.129]},"t":7,"s":[9.666]},{"i":{"x":[0.833],"y":[0.789]},"o":{"x":[0.167],"y":[0.272]},"t":8,"s":[10.42]},{"i":{"x":[0.833],"y":[0.912]},"o":{"x":[0.167],"y":[0.138]},"t":9,"s":[10.753]},{"i":{"x":[0.833],"y":[1.342]},"o":{"x":[0.167],"y":[1.567]},"t":10,"s":[11.262]},{"i":{"x":[0.833],"y":[0.615]},"o":{"x":[0.167],"y":[0.067]},"t":11,"s":[11.291]},{"i":{"x":[0.833],"y":[0.8]},"o":{"x":[0.167],"y":[0.106]},"t":12,"s":[11.145]},{"i":{"x":[0.833],"y":[0.87]},"o":{"x":[0.167],"y":[0.143]},"t":13,"s":[10.616]},{"i":{"x":[0.833],"y":[0.743]},"o":{"x":[0.167],"y":[0.232]},"t":14,"s":[9.873]},{"i":{"x":[0.833],"y":[0.835]},"o":{"x":[0.167],"y":[0.123]},"t":15,"s":[9.455]},{"i":{"x":[0.833],"y":[0.877]},"o":{"x":[0.167],"y":[0.168]},"t":16,"s":[8.584]},{"i":{"x":[0.833],"y":[0.765]},"o":{"x":[0.167],"y":[0.26]},"t":17,"s":[7.727]},{"i":{"x":[0.833],"y":[0.847]},"o":{"x":[0.167],"y":[0.129]},"t":18,"s":[7.322]},{"i":{"x":[0.833],"y":[0.881]},"o":{"x":[0.167],"y":[0.182]},"t":19,"s":[6.583]},{"i":{"x":[0.833],"y":[0.781]},"o":{"x":[0.167],"y":[0.281]},"t":20,"s":[5.962]},{"i":{"x":[0.833],"y":[0.858]},"o":{"x":[0.167],"y":[0.135]},"t":21,"s":[5.7]},{"i":{"x":[0.833],"y":[0.887]},"o":{"x":[0.167],"y":[0.202]},"t":22,"s":[5.273]},{"i":{"x":[0.833],"y":[0.811]},"o":{"x":[0.167],"y":[0.318]},"t":23,"s":[4.972]},{"i":{"x":[0.833],"y":[0.887]},"o":{"x":[0.167],"y":[0.149]},"t":24,"s":[4.866]},{"i":{"x":[0.833],"y":[0.922]},"o":{"x":[0.167],"y":[0.321]},"t":25,"s":[4.73]},{"i":{"x":[0.833],"y":[-0.358]},"o":{"x":[0.167],"y":[-1.182]},"t":26,"s":[4.683]},{"i":{"x":[0.833],"y":[0.763]},"o":{"x":[0.167],"y":[0.089]},"t":27,"s":[4.686]},{"i":{"x":[0.833],"y":[0.866]},"o":{"x":[0.167],"y":[0.129]},"t":28,"s":[4.734]},{"i":{"x":[0.833],"y":[0.734]},"o":{"x":[0.167],"y":[0.22]},"t":29,"s":[4.822]},{"i":{"x":[0.833],"y":[0.83]},"o":{"x":[0.167],"y":[0.121]},"t":30,"s":[4.876]},{"i":{"x":[0.833],"y":[0.876]},"o":{"x":[0.167],"y":[0.164]},"t":31,"s":[4.994]},{"i":{"x":[0.833],"y":[0.761]},"o":{"x":[0.167],"y":[0.254]},"t":32,"s":[5.116]},{"i":{"x":[0.833],"y":[0.844]},"o":{"x":[0.167],"y":[0.128]},"t":33,"s":[5.176]},{"i":{"x":[0.833],"y":[0.88]},"o":{"x":[0.167],"y":[0.179]},"t":34,"s":[5.288]},{"i":{"x":[0.833],"y":[0.777]},"o":{"x":[0.167],"y":[0.275]},"t":35,"s":[5.385]},{"i":{"x":[0.833],"y":[0.855]},"o":{"x":[0.167],"y":[0.133]},"t":36,"s":[5.427]},{"i":{"x":[0.833],"y":[0.885]},"o":{"x":[0.167],"y":[0.196]},"t":37,"s":[5.498]},{"i":{"x":[0.833],"y":[0.8]},"o":{"x":[0.167],"y":[0.305]},"t":38,"s":[5.551]},{"i":{"x":[0.833],"y":[0.875]},"o":{"x":[0.167],"y":[0.143]},"t":39,"s":[5.57]},{"i":{"x":[0.833],"y":[0.902]},"o":{"x":[0.167],"y":[0.251]},"t":40,"s":[5.598]},{"i":{"x":[0.833],"y":[0.987]},"o":{"x":[0.167],"y":[0.544]},"t":41,"s":[5.612]},{"i":{"x":[0.833],"y":[0.547]},"o":{"x":[0.167],"y":[-0.016]},"t":42,"s":[5.614]},{"i":{"x":[0.833],"y":[0.858]},"o":{"x":[0.167],"y":[0.102]},"t":43,"s":[5.612]},{"i":{"x":[0.833],"y":[0.72]},"o":{"x":[0.167],"y":[0.202]},"t":44,"s":[5.603]},{"i":{"x":[0.833],"y":[0.825]},"o":{"x":[0.167],"y":[0.119]},"t":45,"s":[5.596]},{"i":{"x":[0.833],"y":[0.875]},"o":{"x":[0.167],"y":[0.159]},"t":46,"s":[5.581]},{"i":{"x":[0.833],"y":[0.756]},"o":{"x":[0.167],"y":[0.248]},"t":47,"s":[5.564]},{"i":{"x":[0.833],"y":[0.841]},"o":{"x":[0.167],"y":[0.127]},"t":48,"s":[5.555]},{"i":{"x":[0.833],"y":[0.879]},"o":{"x":[0.167],"y":[0.176]},"t":49,"s":[5.539]},{"i":{"x":[0.833],"y":[0.773]},"o":{"x":[0.167],"y":[0.27]},"t":50,"s":[5.524]},{"i":{"x":[0.833],"y":[0.852]},"o":{"x":[0.167],"y":[0.132]},"t":51,"s":[5.517]},{"i":{"x":[0.833],"y":[0.884]},"o":{"x":[0.167],"y":[0.191]},"t":52,"s":[5.506]},{"i":{"x":[0.833],"y":[0.793]},"o":{"x":[0.167],"y":[0.295]},"t":53,"s":[5.497]},{"i":{"x":[0.833],"y":[0.868]},"o":{"x":[0.167],"y":[0.139]},"t":54,"s":[5.494]},{"i":{"x":[0.833],"y":[0.894]},"o":{"x":[0.167],"y":[0.225]},"t":55,"s":[5.488]},{"i":{"x":[0.833],"y":[0.867]},"o":{"x":[0.167],"y":[0.391]},"t":56,"s":[5.485]},{"i":{"x":[0.833],"y":[1.041]},"o":{"x":[0.167],"y":[0.223]},"t":57,"s":[5.484]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.028]},"t":58,"s":[5.484]},{"t":59,"s":[5.485]}],"ix":5},"lc":1,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"fl","c":{"a":0,"k":[1,1,1,1],"ix":4},"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":10,"s":[0]},{"t":11,"s":[100]}],"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","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":"Oval","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":60,"st":0,"ct":1,"bm":0}]}],"layers":[{"ddd":0,"ind":1,"ty":0,"nm":"Comp 2","refId":"comp_0","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":[360,360,0],"ix":1,"l":2},"s":{"a":0,"k":[71.111,71.111,100],"ix":6,"l":2}},"ao":0,"tm":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":60,"s":[0]},{"t":119,"s":[0.983]}],"ix":2},"w":720,"h":720,"ip":60,"op":120,"st":60,"bm":0},{"ddd":0,"ind":2,"ty":0,"nm":"Comp 1","refId":"comp_1","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":[360,360,0],"ix":1,"l":2},"s":{"a":0,"k":[71.111,71.111,100],"ix":6,"l":2}},"ao":0,"tm":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":0,"s":[0]},{"t":59,"s":[0.983]}],"ix":2},"w":720,"h":720,"ip":0,"op":60,"st":0,"bm":0}],"markers":[],"props":{}} \ No newline at end of file diff --git a/TMessagesProj/src/main/res/raw/premium_object_check.svg b/TMessagesProj/src/main/res/raw/premium_object_check.svg new file mode 100644 index 0000000000..3b5b9c95cb --- /dev/null +++ b/TMessagesProj/src/main/res/raw/premium_object_check.svg @@ -0,0 +1,7 @@ + + + Filled / premium_object_check + + + + \ No newline at end of file diff --git a/TMessagesProj/src/main/res/raw/premium_object_star.svg b/TMessagesProj/src/main/res/raw/premium_object_star.svg new file mode 100644 index 0000000000..66af2c02d3 --- /dev/null +++ b/TMessagesProj/src/main/res/raw/premium_object_star.svg @@ -0,0 +1,7 @@ + + + Filled / filled_stories_closefriends + + + + \ No newline at end of file diff --git a/TMessagesProj/src/main/res/raw/premium_object_tag.svg b/TMessagesProj/src/main/res/raw/premium_object_tag.svg new file mode 100644 index 0000000000..fbf6bbf324 --- /dev/null +++ b/TMessagesProj/src/main/res/raw/premium_object_tag.svg @@ -0,0 +1,7 @@ + + + Filled / premium_object_tag + + + + \ No newline at end of file diff --git a/TMessagesProj/src/main/res/raw/tag_icon_3.json b/TMessagesProj/src/main/res/raw/tag_icon_3.json new file mode 100644 index 0000000000..5e044579e9 --- /dev/null +++ b/TMessagesProj/src/main/res/raw/tag_icon_3.json @@ -0,0 +1 @@ +{"tgs":1,"v":"5.5.2","fr":60,"ip":0,"op":57,"w":512,"h":512,"nm":"TAG ICON 3","ddd":0,"assets":[],"layers":[{"ddd":0,"ind":2,"ty":4,"nm":"Tag Body","sr":1,"ks":{"r":{"a":1,"k":[{"i":{"x":[0.7],"y":[1]},"o":{"x":[0.3],"y":[0]},"t":1,"s":[-106]},{"i":{"x":[0.7],"y":[1]},"o":{"x":[0.3],"y":[0]},"t":16,"s":[25]},{"i":{"x":[0.7],"y":[1]},"o":{"x":[0.3],"y":[0]},"t":27,"s":[-13]},{"i":{"x":[0.71],"y":[1]},"o":{"x":[0.3],"y":[0]},"t":37,"s":[8]},{"i":{"x":[0.71],"y":[1]},"o":{"x":[0.29],"y":[0]},"t":47,"s":[-4]},{"t":56,"s":[0]}]},"p":{"a":1,"k":[{"i":{"x":0.7,"y":0.931},"o":{"x":0.3,"y":0},"t":0,"s":[254,408,0],"to":[-74.5,-134.5,0],"ti":[-49.225,2.261,0]},{"i":{"x":0.7,"y":1},"o":{"x":0.3,"y":0.089},"t":14,"s":[286,158.5,0],"to":[40.849,-1.876,0],"ti":[57,-60.25,0]},{"i":{"x":0.7,"y":1},"o":{"x":0.3,"y":0},"t":25,"s":[315,296,0],"to":[0,-3,0],"ti":[0,0,0]},{"i":{"x":0.71,"y":1},"o":{"x":0.3,"y":0},"t":35,"s":[320,229,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.71,"y":1},"o":{"x":0.29,"y":0},"t":45,"s":[320,267,0],"to":[0,0,0],"ti":[0,0,0]},{"t":54,"s":[320,256,0]}]},"a":{"a":0,"k":[64,0,0]}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":1,"k":[{"i":{"x":0.833,"y":0.833},"o":{"x":0.3,"y":0},"t":0,"s":[{"i":[[-0.126,0],[0,17.396],[0.126,0],[0,-17.396]],"o":[[0.126,0],[0,-17.396],[-0.126,0],[0,17.396]],"v":[[20.869,31.498],[21.098,0],[20.869,-31.498],[20.64,0]],"c":true}]},{"i":{"x":0.5,"y":1},"o":{"x":0.167,"y":0.167},"t":6,"s":[{"i":[[17.198,-1.425],[-3.426,10.9],[-19.312,-0.892],[5.119,-7.228]],"o":[[-18.295,1.516],[3.427,-10.901],[18.317,0.846],[-3.491,10.891]],"v":[[40.158,-8.836],[10.481,-23.231],[49.943,-45.497],[77.084,-23.231]],"c":true}]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.2,"y":0},"t":12,"s":[{"i":[[21.564,0],[-4.006,7.942],[-22.639,-1.298],[4.67,-9.069]],"o":[[-21.564,0],[4.007,-7.944],[21.477,1.231],[-4.083,7.928]],"v":[[63.815,-7.069],[35.545,-23.661],[85.502,-39.932],[113.636,-23.661]],"c":true}]},{"i":{"x":0.5,"y":1},"o":{"x":0.167,"y":0.167},"t":17,"s":[{"i":[[21.053,2.96],[-4.407,11.239],[-21.674,-3.949],[3.263,-12.53]],"o":[[-21.053,-2.96],[4.407,-11.24],[20.873,3.803],[-2.852,11.733]],"v":[[61.756,2.568],[34.266,-24.33],[83.08,-40.272],[109.731,-16.531]],"c":true}]},{"t":30,"s":[{"i":[[20.556,0],[0,20.556],[-20.556,0],[0,-20.556]],"o":[[-20.556,0],[0,-20.556],[20.556,0],[0,20.556]],"v":[[63.457,37.22],[26.237,0],[63.457,-37.22],[100.678,0]],"c":true}]}]},"nm":"Path 1","hd":false},{"ind":1,"ty":"sh","ks":{"a":1,"k":[{"i":{"x":0.833,"y":0.833},"o":{"x":0.3,"y":0},"t":0,"s":[{"i":[[0.724,9.912],[0,0],[1.951,0],[0,0],[0.289,-28.314],[0,0],[-4.286,0],[0,0],[-0.907,13.68],[0,0]],"o":[[0,0],[-0.907,-13.68],[0,0],[-4.286,0],[0,0],[0,33.937],[0,0],[1.951,0],[0,0],[0.229,-10.345]],"v":[[27.834,-16.955],[26.33,-95.483],[21.682,-117.732],[3.261,-117.732],[-1.844,-55.875],[-0.983,55.649],[3.261,117.732],[21.682,117.732],[26.33,95.483],[27.807,15.958]],"c":true}]},{"i":{"x":0.5,"y":1},"o":{"x":0.167,"y":0.167},"t":6,"s":[{"i":[[4.878,7.791],[0,0],[13.154,0],[56.635,-35.52],[6.841,-25.27],[0,0],[-15.807,9.603],[0,0],[-8.9,8.588],[0,0]],"o":[[0,0],[-6.113,-10.752],[0,0],[-26.801,16.809],[0,0],[-2.437,22.407],[60.444,-36.722],[12.619,3.715],[0,0],[4.723,-7.926]],"v":[[123.359,-30.426],[91.131,-74.085],[59.796,-91.572],[-55.408,-67.096],[-100.621,-13.95],[-114.411,88.552],[-80.707,105.6],[36.254,74.326],[71.252,66.401],[123.789,-8.485]],"c":true}]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.2,"y":0},"t":12,"s":[{"i":[[6.77,6.825],[0,0],[18.256,0],[0,0],[13.655,-22.627],[0,0],[-40.102,0],[0,0],[-8.483,9.419],[0,0]],"o":[[0,0],[-8.483,-9.419],[0,0],[-40.102,0],[0,0],[-6.973,16.6],[0,0],[18.256,0],[0,0],[6.77,-6.825]],"v":[[168.176,-24.368],[120.641,-64.341],[77.153,-79.659],[-61.02,-74.059],[-133.415,-40.227],[-191.355,39.253],[-147.896,79.128],[48.666,67.592],[92.154,52.273],[168.814,-7.424]],"c":true}]},{"i":{"x":0.5,"y":1},"o":{"x":0.167,"y":0.167},"t":17,"s":[{"i":[[6.77,8.194],[0,0],[18.256,0],[67.028,27.809],[11.511,-18.917],[0,0],[-26.572,-13.524],[0,0],[-10.604,10.629],[0,0]],"o":[[0,0],[-8.483,-11.308],[0,0],[-31.083,-12.896],[0,0],[-9.627,21.678],[76.682,39.029],[13.562,-2.257],[0,0],[6.77,-8.194]],"v":[[157.925,-31.952],[118.936,-77.921],[79.796,-91.72],[-60.502,-94.635],[-116.892,-86.389],[-167.855,14.804],[-131.338,78.953],[54.126,97.567],[96.347,76.456],[158.384,-9.149]],"c":true}]},{"t":30,"s":[{"i":[[6.77,11.713],[0,0],[18.256,0],[0,0],[0,-40.102],[0,0],[-40.102,0],[0,0],[-8.483,16.165],[0,0]],"o":[[0,0],[-8.483,-16.165],[0,0],[-40.102,0],[0,0],[0,40.102],[0,0],[18.256,0],[0,0],[6.77,-11.713]],"v":[[168.822,-18.931],[114.552,-112.828],[71.064,-139.119],[-101.289,-139.119],[-173.899,-66.508],[-173.899,66.508],[-101.289,139.119],[71.064,139.119],[114.552,112.828],[168.822,18.931]],"c":true}]}]},"nm":"Path 2","hd":false},{"ty":"fl","c":{"a":0,"k":[1,1,1,1]},"o":{"a":0,"k":100},"r":1,"bm":0,"nm":"Fill 1","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"Transform"}],"nm":"Group 1","bm":0,"hd":false}],"ip":1,"op":180,"st":0,"bm":0}]} \ 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 b026ba42f7..250eefaac3 100644 --- a/TMessagesProj/src/main/res/values/strings.xml +++ b/TMessagesProj/src/main/res/values/strings.xml @@ -161,6 +161,7 @@ yesterday No results No results found for \"%s\". + No results found for %s Welcome to Telegram Recently viewed HIDE @@ -3141,6 +3142,10 @@ Save to gallery %1$d of %2$d **%1$d** of %2$d + %1$d message + %1$d messages + Show as List + Show as Chat Gallery All photos All media @@ -3529,7 +3534,7 @@ My Contacts (-%1$d, +%2$d) Nobody (+%1$d) Everybody - My Contacts and Premium + Contacts & Premium My Contacts Nobody Everybody (-%1$d) @@ -3744,8 +3749,8 @@ Rental Agreement Phone Number Email Address - This message is not supported on your version of Telegram. Update the app to view: https://telegram.org/update - This message is not supported on your version of Telegram. Update the app to view: https://telegram.org/dl + This message is not supported on your version of Telegram. Please update to the latest version. + Your version is up to date. Photo Video Self-Destructing Photo @@ -5308,8 +5313,12 @@ Switch to day theme Close Trending stickers Close Trending emoji + Edit Message Tag Play Pause + Resume + Activate Play Once + Deactivate Play Once Download Cancel download Open file @@ -5756,6 +5765,7 @@ Quick Reactions Double tap this message for a quck reaction. un1 changed chat reactions \nfrom: %1$s \nto: %2$s + un1 changed chat reactions:\n %1$s Nobody viewed QR Code @@ -5939,6 +5949,10 @@ Subscribe to Telegram Premium to download media and files at the fastest possible speed. No Ads No more ads in public channels where Telegram sometimes shows ads. + Tags for Messages + Organize your Saved Messages with tags\nfor quicker access. + Tags in Saved Messages + Organize your Saved Messages with tags for quicker access. Unique Reactions Premium Stickers Exclusive enlarged stickers featuring additional effects, updated monthly. @@ -6202,6 +6216,8 @@ Close topics Reopen topics All Topics + View as Chats + View as Messages View as topics Are you sure you want delete these topics? Are you sure you want delete %s? @@ -7273,6 +7289,8 @@ Get more views as your stories are always displayed first. Stealth Mode Hide the fact that you viewed other people’s stories. + Higher quality + View video stories in double the resolution. Permanent Views History Check who opens your stories — even after they expire. Expiration Durations @@ -7978,14 +7996,18 @@ Message reposted to your profile. Message reposted to **%s**. Select Wallpaper - Saved Messages + Saved Chats %d chat %d chats %d saved message %d saved messages Author Hidden - Unsave messages from %s + Delete all your notes + Are you sure you want to delete all your notes? + Delete all your saved messages + Are you sure you want to delete all your saved messages? + Unsave messages Unsave messages from %d chats Are you sure you want to unsave messages from %s? Are you sure you want to unsave messages from %d chats? @@ -8014,10 +8036,14 @@ Hide the time when you read messages from people who can’t see your last seen. If you turn this on, their read time will also be hidden from you.\nThis setting does not affect group chats. read show when - read %s + read today at %s + read yesterday at %s + read %1$s at %2$s read time unknown Subscribe to Telegram Premium If you subscribe to Premium, you will see other users’ last seen and read time even if you hid yours from them (unless they specifically restricted it). + Subscribed to Telegram Premium + Because you are a Telegram Premium subscriber, you will see the last seen and read time of all users who are sharing it with you – even if you are hiding yours. Show Your Read Date To see when **%s** read the message, either start showing your own read time... To see when **%s** read the message, start showing your own read time. @@ -8038,7 +8064,7 @@ Your read times are now visible. Premium Required Subscribe to **Telegram Premium** to select this option. - Unlock + Subscribe Subscribe to **Premium** to message **%s**. **%s** restricted messaging to only Premium users. Get Premium @@ -8052,10 +8078,42 @@ Show Other Messages Hide Other Messages **%s** only accepts messages from contacts and Premium users. + Remove Tag + Add Name + Edit Name + Name + Add Tags + to your Saved Messages + You can label your emoji tag with a text name. + Filter by Tag + Search messages or tags + Tap this icon to search by tags + Tap and hold to add a name to your tag + You can add a tag to the message + Tag the message with an emoji for quick search + Organize your Saved Messages with tags\nfor quicker access. **Learn more…** + Message tagged with + Messages tagged with View Replies restricted Unlock You need a **Premium** Subscription to reply to **%s**’s stories. Unable to send Only Premium users can message %s + No messages under this tag or search found + Add a tag to selected messages + Edit tags of selected messages + Increase Quality + Quality Increased + You can lower the quality later for faster downloads. + Lower Quality + Quality Lowered + Stories will now download faster. + High-Quality Stories + Subscribe to Premium to view stories in higher resolution. + Messages you sent to Saved Messages + Last Seen Times + View the last seen and read times of others even if you hide yours. + Message Privacy + Restrict people you don\'t know from sending you messages.