update to 10.6.4 (4365)

This commit is contained in:
dkaraush 2024-02-06 20:34:03 +04:00
parent 928146c3da
commit 5dd649197b
182 changed files with 7043 additions and 1797 deletions

View file

@ -2390,7 +2390,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";

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -990,7 +990,7 @@ public class ChatListItemAnimator extends DefaultItemAnimator {
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;

View file

@ -468,7 +468,7 @@ public class DefaultItemAnimator extends SimpleItemAnimator {
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;

View file

@ -25,7 +25,6 @@ public class SQLitePreparedStatement {
private long startTime;
private String query;
//private static HashMap<SQLitePreparedStatement, String> hashMap;
public long getStatementHandle() {
return sqliteStatementHandle;
@ -112,9 +111,6 @@ public class SQLitePreparedStatement {
}
}
try {
/*if (BuildVars.DEBUG_PRIVATE_VERSION) {
hashMap.remove(this);
}*/
isFinalized = true;
finalize(sqliteStatementHandle);
} catch (SQLiteException e) {

View file

@ -73,6 +73,7 @@ import android.text.style.ClickableSpan;
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;
@ -155,6 +156,7 @@ import org.telegram.ui.Components.MotionBackgroundDrawable;
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;
@ -314,6 +316,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")) {
@ -4441,6 +4444,7 @@ public class AndroidUtilities {
}
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();

View file

@ -429,11 +429,6 @@ public class ApplicationLoader extends Application {
return false;
}
public static boolean useLessData() {
ensureCurrentNetworkGet();
return BuildVars.DEBUG_PRIVATE_VERSION && (SharedConfig.forceLessData || isConnectionSlow());
}
public static boolean isConnectionSlow() {
try {
ensureCurrentNetworkGet(false);

View file

@ -23,7 +23,7 @@ public class ChatMessagesMetadataController {
}
public void checkMessages(ChatActivity.ChatActivityAdapter chatAdapter, int maxAdapterPosition, int minAdapterPosition, long currentTime) {
ArrayList<MessageObject> messages = chatActivity.messages;
ArrayList<MessageObject> messages = chatAdapter.getMessages();
if (!chatActivity.isInScheduleMode() && maxAdapterPosition >= 0 && minAdapterPosition >= 0) {
int from = minAdapterPosition - chatAdapter.messagesStartRow - 10;
int to = maxAdapterPosition - chatAdapter.messagesStartRow + 10;

View file

@ -1409,10 +1409,22 @@ public class DatabaseMigrationHelper {
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;

View file

@ -53,7 +53,7 @@ public class DocumentObject {
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;
}

View file

@ -2441,7 +2441,7 @@ public class FileLoadOperation {
}
}, 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++;
}

View file

@ -984,7 +984,7 @@ public class FileLoader extends BaseController {
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;
}

View file

@ -75,7 +75,7 @@ public class FileLog {
private static Gson gson;
private static HashSet<String> 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;
}
@ -97,7 +97,7 @@ public class FileLog {
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);

View file

@ -1,6 +1,7 @@
package org.telegram.messenger;
import android.os.SystemClock;
import android.util.Log;
import org.telegram.tgnet.RequestDelegate;
import org.telegram.tgnet.TLObject;

View file

@ -1722,6 +1722,31 @@ public class LocaleController {
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;

View file

@ -54,7 +54,6 @@ import android.provider.OpenableColumns;
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;
@ -84,6 +83,7 @@ import org.telegram.ui.ChatActivity;
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;
@ -2397,10 +2397,10 @@ public class MediaController implements AudioManager.OnAudioFocusChangeListener,
//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);
}
}
@ -5572,6 +5572,7 @@ public class MediaController implements AudioManager.OnAudioFocusChangeListener,
final String query;
final FiltersView.MediaFilterData filter;
final long dialogId;
public long topicId;
final long minDate;
final long maxDate;
public int totalCount;
@ -5579,6 +5580,8 @@ public class MediaController implements AudioManager.OnAudioFocusChangeListener,
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;

View file

@ -60,10 +60,12 @@ import org.telegram.tgnet.TLObject;
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;
@ -566,7 +568,7 @@ public class MediaDataController extends BaseController {
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));
@ -1199,6 +1201,31 @@ public class MediaDataController extends BaseController {
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);
}
@ -3344,15 +3371,108 @@ public class MediaDataController extends BaseController {
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<MessageObject> searchResultMessages = new ArrayList<>();
private SparseArray<MessageObject>[] searchResultMessagesMap = new SparseArray[]{new SparseArray<>(), new SparseArray<>()};
public ArrayList<MessageObject> searchResultMessages = new ArrayList<>();
public ArrayList<MessageObject> searchServerResultMessages = new ArrayList<>();
public ArrayList<MessageObject> searchLocalResultMessages = new ArrayList<>();
private SparseArray<MessageObject>[] searchServerResultMessagesMap = new SparseArray[]{new SparseArray<>(), new SparseArray<>()};
private ArrayList<MessageObject> 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<MessageObject> previousSearchResultMessages = new ArrayList<>(searchResultMessages);
searchResultMessages.clear();
HashSet<Integer> 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;
@ -3369,10 +3489,12 @@ public class MediaDataController extends BaseController {
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) {
@ -3385,29 +3507,52 @@ public class MediaDataController extends BaseController {
}
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;
}
@ -3417,17 +3562,20 @@ public class MediaDataController extends BaseController {
}
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;
@ -3454,17 +3602,20 @@ public class MediaDataController extends BaseController {
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) {
@ -3527,6 +3678,7 @@ public class MediaDataController extends BaseController {
TLRPC.TL_messages_search req = new TLRPC.TL_messages_search();
req.peer = getMessagesController().getInputPeer(queryWithDialog);
if (req.peer == null) {
loadingMoreSearchMessages = false;
return;
}
lastGuid = guid;
@ -3545,6 +3697,33 @@ public class MediaDataController extends BaseController {
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);
@ -3559,7 +3738,6 @@ public class MediaDataController extends BaseController {
req.flags |= 8;
}
req.filter = new TLRPC.TL_inputMessagesFilterEmpty();
int currentReqId = ++lastReqId;
lastSearchQuery = query;
long queryWithDialogFinal = queryWithDialog;
String finalQuery = query;
@ -3568,10 +3746,13 @@ public class MediaDataController extends BaseController {
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);
}
@ -3594,26 +3775,27 @@ public class MediaDataController extends BaseController {
getMessagesStorage().putUsersAndChats(res.users, res.chats, true, true);
getMessagesController().putUsers(res.users, false);
getMessagesController().putChats(res.chats, false);
Runnable done = () -> {
if (req.offset_id == 0 && queryWithDialogFinal == dialogId) {
lastReturnedNum = 0;
searchResultMessages.clear();
searchResultMessagesMap[0].clear();
searchResultMessagesMap[1].clear();
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(), 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);
added = true;
MessageObject messageObject = messageObjects.get(a);
searchResultMessages.add(messageObject);
searchResultMessagesMap[queryWithDialogFinal == dialogId ? 0 : 1].put(messageObject.getId(), messageObject);
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 (searchResultMessages.isEmpty()) {
if (searchServerResultMessages.isEmpty()) {
getNotificationCenter().postNotificationName(NotificationCenter.chatSearchResultsAvailable, guid, 0, getMask(), (long) 0, 0, 0, jumpToMessage);
} else {
if (added) {
@ -3621,18 +3803,42 @@ public class MediaDataController extends BaseController {
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);
} else if (isSaved) {
getNotificationCenter().postNotificationName(NotificationCenter.chatSearchResultsAvailable, guid, 0, getMask(), dialogId, lastReturnedNum, getSearchCount(), false);
}
}
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();
}
}
}
});
}, ConnectionsManager.RequestFlagFailOnServerErrors);
}
public void portSavedSearchResults(int guid, ReactionsLayoutInBubble.VisibleReaction reaction, String query, ArrayList<MessageObject> local, ArrayList<MessageObject> 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;
}
@ -3651,14 +3857,14 @@ public class MediaDataController extends BaseController {
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) {
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 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);
if (fromCache != 0 && TextUtils.isEmpty(query) || DialogObject.isEncryptedDialog(dialogId)) {
loadMediaDatabase(dialogId, count, max_id, min_id, type, topicId, tag, classGuid, isChannel, fromCache, requestIndex);
} else {
TLRPC.TL_messages_search req = new TLRPC.TL_messages_search();
req.limit = count;
@ -3668,6 +3874,10 @@ public class MediaDataController extends BaseController {
} else {
req.offset_id = max_id;
}
if (tag != null) {
req.flags |= 8;
req.saved_reaction.add(tag.toTLReaction());
}
if (type == MEDIA_PHOTOVIDEO) {
req.filter = new TLRPC.TL_inputMessagesFilterPhotoVideo();
@ -3686,7 +3896,11 @@ public class MediaDataController extends BaseController {
} else if (type == MEDIA_GIF) {
req.filter = new TLRPC.TL_inputMessagesFilterGif();
}
if (!TextUtils.isEmpty(query)) {
req.q = query;
} else {
req.q = "";
}
req.peer = getMessagesController().getInputPeer(dialogId);
if (topicId != 0) {
if (dialogId == getUserConfig().getClientUserId()) {
@ -3834,7 +4048,7 @@ public class MediaDataController extends BaseController {
});
getConnectionsManager().bindRequestToGuid(reqId, classGuid);
}
if (!missing) {
if (!missing || getConnectionsManager().getConnectionState() != ConnectionsManager.ConnectionStateConnected) {
AndroidUtilities.runOnUIThread(() -> getNotificationCenter().postNotificationName(NotificationCenter.mediaCountsDidLoad, dialogId, topicId, countsFinal));
}
}
@ -3864,7 +4078,7 @@ public class MediaDataController extends BaseController {
}
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;
@ -3967,7 +4181,7 @@ public class MediaDataController extends BaseController {
if (fromCache == 2) {
return;
}
loadMedia(dialogId, count, max_id, min_id, type, topicId, 0, classGuid, requestIndex);
loadMedia(dialogId, count, max_id, min_id, type, topicId, 0, classGuid, requestIndex, null, null);
} else {
if (fromCache == 0) {
ImageLoader.saveMessagesThumbs(res.messages);
@ -4093,11 +4307,12 @@ public class MediaDataController extends BaseController {
});
}
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) {
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) {
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<Long> usersToLoad = new ArrayList<>();
@ -4151,6 +4366,20 @@ public class MediaDataController extends BaseController {
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;
@ -4167,17 +4396,17 @@ public class MediaDataController extends BaseController {
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) {
@ -4195,17 +4424,17 @@ public class MediaDataController extends BaseController {
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 {
@ -4220,15 +4449,15 @@ public class MediaDataController extends BaseController {
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));
}
}
}
@ -4254,17 +4483,21 @@ public class MediaDataController extends BaseController {
}
HashSet<Long> 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;
if (DialogObject.isEncryptedDialog(uid)) {
message.random_id = cursor.longValue(2);
}
if (message.grouped_id != 0 && groupsToLoad != null) {
groupsToLoad.add(message.grouped_id);
}
if (reverseMessages) {
res.messages.add(0, message);
} else {
@ -4276,6 +4509,38 @@ public class MediaDataController extends BaseController {
}
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<TLRPC.Message> 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);
}
@ -7566,8 +7831,12 @@ public class MediaDataController extends BaseController {
}
private HashMap<String, Boolean> currentFetchingEmoji = new HashMap<>();
private HashSet<String> fetchedEmoji = new HashSet<>();
public void fetchNewEmojiKeywords(String[] langCodes) {
fetchNewEmojiKeywords(langCodes, false);
}
public void fetchNewEmojiKeywords(String[] langCodes, boolean doNotFetchTwice) {
if (langCodes == null) {
return;
}
@ -7576,7 +7845,7 @@ public class MediaDataController extends BaseController {
if (TextUtils.isEmpty(langCode)) {
return;
}
if (currentFetchingEmoji.get(langCode) != null) {
if (currentFetchingEmoji.get(langCode) != null || doNotFetchTwice && fetchedEmoji.contains(langCode)) {
return;
}
currentFetchingEmoji.put(langCode, true);
@ -7596,7 +7865,11 @@ public class MediaDataController extends BaseController {
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;
@ -7625,7 +7898,9 @@ public class MediaDataController extends BaseController {
AndroidUtilities.runOnUIThread(() -> {
currentFetchingEmoji.remove(langCode);
fetchedEmoji.add(langCode);
fetchNewEmojiKeywords(new String[]{langCode});
getNotificationCenter().postNotificationName(NotificationCenter.emojiKeywordsLoaded);
});
} catch (Exception e) {
FileLog.e(e);
@ -7633,9 +7908,16 @@ public class MediaDataController extends BaseController {
});
} 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);
});
}
});
});
@ -7752,6 +8034,44 @@ public class MediaDataController extends BaseController {
});
}
public void getEmojiNames(String[] langCodes, String emoji, Utilities.Callback<ArrayList<String>> 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<String> 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);
}
@ -8502,7 +8822,7 @@ public class MediaDataController extends BaseController {
saveReactionsToPref(savedReactionsPref, reactions.hash, reactions.reactions);
getNotificationCenter().postNotificationName(NotificationCenter.savedReactionTagsUpdate);
getNotificationCenter().postNotificationName(NotificationCenter.savedReactionTagsUpdate, 0L);
}
if (response instanceof TLRPC.TL_messages_reactionsNotModified) {

View file

@ -34,6 +34,7 @@ import android.text.style.URLSpan;
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;
@ -167,6 +168,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;
@ -315,6 +317,7 @@ public class MessageObject {
public boolean forceAvatar;
public Drawable customAvatarDrawable;
public boolean isSaved;
public boolean isSavedFiltered;
private byte[] randomWaveform;
public boolean drawServiceWithDefaultTypeface;
@ -567,6 +570,10 @@ public class MessageObject {
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;
}
@ -926,9 +933,21 @@ public class MessageObject {
public ArrayList<MessageObject> messages = new ArrayList<>();
public ArrayList<GroupedMessagePosition> posArray = new ArrayList<>();
public HashMap<MessageObject, GroupedMessagePosition> positions = new HashMap<>();
public LongSparseArray<GroupedMessagePosition> 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();
@ -967,6 +986,7 @@ public class MessageObject {
public void calculate() {
posArray.clear();
positions.clear();
positionsArray.clear();
captionMessage = null;
maxSizeWidth = 800;
@ -996,6 +1016,7 @@ public class MessageObject {
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 ||
@ -1026,6 +1047,7 @@ public class MessageObject {
}
positions.put(messageObject, position);
positionsArray.put(messageObject.getId(), position);
posArray.add(position);
if (messageObject.caption != null) {
@ -1048,19 +1070,21 @@ public class MessageObject {
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;
@ -1366,7 +1390,7 @@ public class MessageObject {
}
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() {
@ -1535,7 +1559,7 @@ public class MessageObject {
this.isRepostPreview = isRepostPreview;
this.isRepostVideoPreview = isRepostVideoPreview;
this.isSaved = isSavedMessages;
this.isSaved = isSavedMessages || getDialogId(message) == UserConfig.getInstance(accountNum).getClientUserId();
currentAccount = accountNum;
messageOwner = message;
@ -1565,6 +1589,7 @@ public class MessageObject {
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();
@ -1809,6 +1834,7 @@ public class MessageObject {
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();
@ -2611,19 +2637,31 @@ public class MessageObject {
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**");
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 + "**old**".length(), oldReactions);
}
i = spannableStringBuilder.toString().indexOf("**new**");
if (i > 0) {
spannableStringBuilder.replace(i, i + "**new**".length(), newReactions);
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;
}
} else if (event.action instanceof TLRPC.TL_channelAdminLogEventActionChangeUsernames) {
TLRPC.TL_channelAdminLogEventActionChangeUsernames log = (TLRPC.TL_channelAdminLogEventActionChangeUsernames) event.action;
@ -3030,10 +3068,12 @@ public class MessageObject {
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);
}
@ -3334,6 +3374,18 @@ public class MessageObject {
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;
@ -4554,7 +4606,7 @@ public class MessageObject {
} else if (getMedia(messageOwner) instanceof TLRPC.TL_messageMediaInvoice) {
messageText = getMedia(messageOwner).description;
} else if (getMedia(messageOwner) instanceof TLRPC.TL_messageMediaUnsupported) {
messageText = LocaleController.getString(ApplicationLoader.applicationLoaderInstance.isStandalone() ? R.string.UnsupportedMediaStandalone : R.string.UnsupportedMedia);
messageText = LocaleController.getString(R.string.UnsupportedMedia2);
} else if (getMedia(messageOwner) instanceof TLRPC.TL_messageMediaDocument) {
if (isSticker() || isAnimatedStickerDocument(getDocument(), true)) {
String sch = getStickerChar();
@ -4666,7 +4718,7 @@ public class MessageObject {
} else if (media instanceof TLRPC.TL_messageMediaInvoice) {
return media.description;
} else if (media instanceof TLRPC.TL_messageMediaUnsupported) {
return LocaleController.getString(ApplicationLoader.applicationLoaderInstance.isStandalone() ? R.string.UnsupportedMediaStandalone : R.string.UnsupportedMedia);
return LocaleController.getString(R.string.UnsupportedMedia2);
} else if (media instanceof TLRPC.TL_messageMediaDocument) {
if (isStickerDocument(media.document) || isAnimatedStickerDocument(media.document, true)) {
String sch = getStickerChar();
@ -5770,6 +5822,8 @@ public class MessageObject {
return result;
}
// only set in searching with tags
public boolean isPrimaryGroupMessage;
public boolean hasValidGroupId() {
return getGroupId() != 0 && (photoThumbs != null && !photoThumbs.isEmpty() || isMusic() || isDocument());
}
@ -5823,7 +5877,7 @@ public class MessageObject {
if (text == null) {
return false;
}
if (isRestrictedMessage) {
if (isRestrictedMessage || getMedia(messageOwner) instanceof TLRPC.TL_messageMediaUnsupported) {
ArrayList<TLRPC.MessageEntity> entities = new ArrayList<>();
TLRPC.TL_messageEntityItalic entityItalic = new TLRPC.TL_messageEntityItalic();
entityItalic.offset = 0;
@ -6282,8 +6336,8 @@ public class MessageObject {
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);
@ -6338,7 +6392,8 @@ public class MessageObject {
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);
messageOwner.id < 0
);
if (useManualParse) {
addLinks(isOutOwner(), messageText, true, true);
@ -7239,7 +7294,7 @@ public class MessageObject {
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;
@ -7261,7 +7316,7 @@ public class MessageObject {
return true;
}
if (isSaved) {
return getSavedDialogId() < 0 || getSavedDialogId() == UserObject.ANONYMOUS;
return true;
}
if (forceAvatar || customAvatarDrawable != null) {
return true;
@ -7274,7 +7329,7 @@ public class MessageObject {
return true;
}
if (isSaved) {
return getSavedDialogId() < 0 || getSavedDialogId() == UserObject.ANONYMOUS;
return true;
}
if (forceAvatar || customAvatarDrawable != null) {
return true;
@ -8777,6 +8832,9 @@ public class MessageObject {
}
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();
@ -8788,9 +8846,6 @@ public class MessageObject {
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();
}
@ -9341,7 +9396,7 @@ public class MessageObject {
} 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);
@ -9354,13 +9409,13 @@ public class MessageObject {
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;
}
@ -9462,9 +9517,6 @@ public class MessageObject {
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++) {
@ -9491,9 +9543,6 @@ public class MessageObject {
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) {
@ -9514,9 +9563,6 @@ public class MessageObject {
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();
@ -9797,7 +9843,8 @@ public class MessageObject {
!"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_channel_boost".equals(webpageType) && // drawInstantViewType = 18
!"telegram_chat".equals(webpageType)
;
}
@ -9805,11 +9852,14 @@ public class MessageObject {
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)
);
}

View file

@ -584,6 +584,9 @@ public class MessagesController extends BaseController implements NotificationCe
public int savedDialogsPinnedLimitDefault;
public int savedDialogsPinnedLimitPremium;
public boolean savedViewAsChats;
public boolean storyQualityFull;
public int uploadMaxFileParts;
public int uploadMaxFilePartsPremium;
@ -1472,6 +1475,8 @@ public class MessagesController extends BaseController implements NotificationCe
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")) {
@ -4919,6 +4924,9 @@ public class MessagesController extends BaseController implements NotificationCe
} else if (id == NotificationCenter.currentUserPremiumStatusChanged) {
loadAppConfig(false);
getContactsController().reloadContactsStatusesMaybe(true);
if (storyQualityFull && !getUserConfig().isPremium() || getUserConfig().isPremium()) {
getNotificationCenter().postNotificationName(NotificationCenter.storyQualityUpdate);
}
}
}
@ -7906,6 +7914,9 @@ public class MessagesController extends BaseController implements NotificationCe
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;
}
@ -7930,6 +7941,9 @@ public class MessagesController extends BaseController implements NotificationCe
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);
});
@ -7945,6 +7959,9 @@ public class MessagesController extends BaseController implements NotificationCe
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) {
@ -17284,6 +17301,8 @@ public class MessagesController extends BaseController implements NotificationCe
getMediaDataController().loadRecentAndTopReactions(true);
} else if (baseUpdate instanceof TLRPC.TL_updateRecentReactions) {
getMediaDataController().loadSavedReactions(true);
} else if (baseUpdate instanceof TLRPC.TL_updateSavedReactionTags) {
getSavedReactionTags(0, true);
} else if (baseUpdate instanceof TLRPC.TL_updateFavedStickers) {
getMediaDataController().loadRecents(MediaDataController.TYPE_FAVE, false, false, true);
} else if (baseUpdate instanceof TLRPC.TL_updateContactsReset) {
@ -19960,24 +19979,56 @@ public class MessagesController extends BaseController implements NotificationCe
return rec;
}
private boolean loadedReactionTags;
private TLRPC.TL_messages_savedReactionsTags reactionTags;
public void updateSavedReactionTags(ReactionsLayoutInBubble.VisibleReaction reaction, boolean add) {
if (reactionTags != null) {
private HashSet<Long> loadingReactionTags;
private LongSparseArray<TLRPC.TL_messages_savedReactionsTags> 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;
}
}
}
@ -19985,43 +20036,205 @@ public class MessagesController extends BaseController implements NotificationCe
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);
if (update && changed) {
updateSavedReactionTags(topicId);
}
}
return gchanged;
}
public void updateSavedReactionTags(HashSet<Long> 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 < 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 (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));
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));
}
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.parseLong(Utilities.MD5(tag.title).substring(0, 16), 16));
hash = MediaDataController.calcHash(hash, Long.parseUnsignedLong(Utilities.MD5(tag.title).substring(0, 16), 16));
}
hash = MediaDataController.calcHash(hash, tag.count);
}
reactionTags.hash = hash;
saveSavedReactionsTags(reactionTags);
getNotificationCenter().postNotificationName(NotificationCenter.savedReactionTagsUpdate);
tags.hash = hash;
saveSavedReactionsTags(0, tags);
getNotificationCenter().postNotificationName(NotificationCenter.savedReactionTagsUpdate, 0L);
}
}
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;
}
public TLRPC.TL_messages_savedReactionsTags getSavedReactionTags() {
if (loadedReactionTags) {
return reactionTags;
return 0;
}
loadedReactionTags = true;
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);
}
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) {
@ -20039,20 +20252,31 @@ public class MessagesController extends BaseController implements NotificationCe
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);
}
}));
});
@ -20060,17 +20284,18 @@ public class MessagesController extends BaseController implements NotificationCe
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);
@ -20116,6 +20341,27 @@ public class MessagesController extends BaseController implements NotificationCe
}
}
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<Boolean> cachedIsUserPremiumBlocked = new LongSparseArray<>();
private HashSet<Long> loadingIsUserPremiumBlocked = new HashSet<>();
public boolean isUserPremiumBlocked(long userId) {

View file

@ -43,6 +43,7 @@ import org.telegram.tgnet.tl.TL_stories;
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;
@ -104,7 +105,7 @@ public class MessagesStorage extends BaseController {
}
}
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();
@ -704,7 +705,13 @@ public class MessagesStorage extends BaseController {
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();
@ -1933,13 +1940,26 @@ public class MessagesStorage extends BaseController {
}
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);
@ -2525,6 +2545,7 @@ public class MessagesStorage extends BaseController {
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()) {
@ -4063,6 +4084,9 @@ public class MessagesStorage extends BaseController {
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();
@ -4089,6 +4113,9 @@ public class MessagesStorage extends BaseController {
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();
@ -4559,10 +4586,138 @@ public class MessagesStorage extends BaseController {
});
}
public void searchSavedByTag(TLRPC.Reaction tag, long topic_id, String query, int limit, int offset, Utilities.Callback4<ArrayList<MessageObject>, ArrayList<TLRPC.User>, ArrayList<TLRPC.Chat>, ArrayList<TLRPC.Document>> 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<TLRPC.User> users = new ArrayList<>();
// ArrayList<TLRPC.User> encUsers = new ArrayList<>();
ArrayList<TLRPC.Chat> chats = new ArrayList<>();
ArrayList<Long> animatedEmojiToLoad = new ArrayList<>();
ArrayList<Long> usersToLoad = new ArrayList<>();
ArrayList<Long> chatsToLoad = new ArrayList<>();
ArrayList<TLRPC.Document> animatedEmoji = new ArrayList<>();
// LongSparseArray<SparseArray<ArrayList<TLRPC.Message>>> replyMessageOwners = new LongSparseArray<>();
// LongSparseArray<ArrayList<Integer>> 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<MessageObject> 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<MessageObject> 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) {
@ -4577,6 +4732,10 @@ public class MessagesStorage extends BaseController {
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) {
@ -4594,6 +4753,12 @@ public class MessagesStorage extends BaseController {
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();
}
@ -4603,6 +4768,9 @@ public class MessagesStorage extends BaseController {
cursor = null;
}
database.commitTransaction();
if (dialogId == selfId && pastReactions != null) {
onReactionsUpdate(topicId, pastReactions, reactions);
}
} catch (Exception e) {
checkSQLException(e);
} finally {
@ -4616,6 +4784,145 @@ public class MessagesStorage extends BaseController {
});
}
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<SavedReactionsUpdate> reactionUpdates) {
if (reactionUpdates == null || reactionUpdates.isEmpty()) return;
AndroidUtilities.runOnUIThread(() -> {
boolean updated = false;
HashSet<Long> topicIds = new HashSet<>();
LongSparseArray<ReactionsLayoutInBubble.VisibleReaction> oldTags = new LongSparseArray<>();
LongSparseArray<ReactionsLayoutInBubble.VisibleReaction> 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<ReactionsLayoutInBubble.VisibleReaction> oldTags = new LongSparseArray<>();
LongSparseArray<ReactionsLayoutInBubble.VisibleReaction> 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;
@ -10517,6 +10824,7 @@ public class MessagesStorage extends BaseController {
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;
@ -10532,6 +10840,7 @@ public class MessagesStorage extends BaseController {
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();
@ -10914,6 +11223,8 @@ public class MessagesStorage extends BaseController {
mediaTypesChange.put(mid, type);
}
}
cursor.dispose();
cursor = null;
SparseIntArray mediaTypes = dialogMediaTypes.get(topicKey.dialogId);
@ -10971,6 +11282,7 @@ public class MessagesStorage extends BaseController {
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<Integer> messagesIdsMap = dialogMessagesIdsMap.get(dialogId);
ArrayList<Integer> mentionsIdsMap = dialogMentionsIdsMap.get(dialogId);
@ -11085,7 +11397,6 @@ public class MessagesStorage extends BaseController {
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) {
@ -11113,6 +11424,9 @@ public class MessagesStorage extends BaseController {
}
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<>();
}
@ -11200,6 +11514,16 @@ public class MessagesStorage extends BaseController {
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) {
@ -11341,6 +11665,14 @@ public class MessagesStorage extends BaseController {
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);
@ -11425,7 +11757,7 @@ public class MessagesStorage extends BaseController {
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);
@ -11700,6 +12032,12 @@ public class MessagesStorage extends BaseController {
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();
}
@ -12383,6 +12721,9 @@ public class MessagesStorage extends BaseController {
SQLiteCursor cursor = null;
SQLitePreparedStatement state = null;
try {
if (getUserConfig().getClientUserId() == dialogId) {
database.executeFast(String.format(Locale.US, "DELETE FROM tag_message_id WHERE mid IN(%s)", TextUtils.join(",", messages))).stepThis().dispose();
}
ArrayList<Long> dialogsIds = new ArrayList<>();
if (scheduled) {
String ids = TextUtils.join(",", messages);
@ -12408,6 +12749,8 @@ public class MessagesStorage extends BaseController {
broadcastScheduledMessagesChange(dialogsToUpdate.get(a));
}
} else {
long currentUser = getUserConfig().getClientUserId();
ArrayList<Integer> unknownMessages = new ArrayList<>(messages);
ArrayList<Integer> unknownMessagesInTopics = new ArrayList<>(messages);
LongSparseArray<Integer[]> dialogsToUpdate = new LongSparseArray<>();
@ -12419,8 +12762,8 @@ public class MessagesStorage extends BaseController {
ArrayList<String> namesToDelete = new ArrayList<>();
ArrayList<Pair<Long, Integer>> idsToDelete = new ArrayList<>();
ArrayList<TopicsController.TopicUpdate> topicUpdatesInUi = null;
ArrayList<TLRPC.Message> 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 {
@ -12461,6 +12804,9 @@ public class MessagesStorage extends BaseController {
if (data != null) {
TLRPC.Message message = TLRPC.Message.TLdeserialize(data, data.readInt32(false), false);
message.readAttachPath(data, currentUser);
if (deletedMessages != null) {
deletedMessages.add(message);
}
data.reuse();
if (DialogObject.isEncryptedDialog(did) || deleteFiles) {
addFilesToDelete(message, filesToDelete, idsToDelete, namesToDelete, false);
@ -12830,6 +13176,36 @@ public class MessagesStorage extends BaseController {
database.executeFast(String.format(Locale.US, "UPDATE media_counts_v2 SET old = 1 WHERE uid = %d", dialogId)).stepThis().dispose();
}
}
if (deletedMessages != null && !deletedMessages.isEmpty()) {
AndroidUtilities.runOnUIThread(() -> {
boolean changed = false;
HashSet<Long> 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<Long> 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();
@ -13832,6 +14208,7 @@ public class MessagesStorage extends BaseController {
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;
@ -13900,6 +14277,7 @@ public class MessagesStorage extends BaseController {
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
@ -13910,6 +14288,7 @@ public class MessagesStorage extends BaseController {
ArrayList<String> namesToDelete = new ArrayList<>();
ArrayList<Pair<Long, Integer>> idsToDelete = new ArrayList<>();
ArrayList<TLRPC.Message> changedSavedMessages = null;
ArrayList<SavedReactionsUpdate> reactionUpdates = dialogId == selfId ? new ArrayList<>() : null;
Integer lastMessageId = null;
Long lastMessageGroupId = null;
@ -13923,7 +14302,16 @@ public class MessagesStorage extends BaseController {
int minDeleteTime = Integer.MAX_VALUE;
HashMap<TopicKey, TLRPC.Message> botKeyboards = null;
long channelId = 0;
final long selfId = getUserConfig().getClientUserId();
final boolean self = selfId == dialogId;
if (self) {
ArrayList<Integer> 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) {
@ -13944,6 +14332,9 @@ public class MessagesStorage extends BaseController {
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))) {
@ -14150,6 +14541,10 @@ public class MessagesStorage extends BaseController {
}
currentState.step();
if (i == 0 && state_messages_tags != null) {
bindMessageTags(state_messages_tags, message);
}
if (repliesData != null) {
repliesData.reuse();
}
@ -14248,6 +14643,10 @@ public class MessagesStorage extends BaseController {
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) {
@ -14302,6 +14701,7 @@ public class MessagesStorage extends BaseController {
}
});
}
onReactionsUpdate(reactionUpdates);
}
} catch (Exception e) {
checkSQLException(e);
@ -14312,6 +14712,9 @@ public class MessagesStorage extends BaseController {
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();
}

View file

@ -9,6 +9,7 @@
package org.telegram.messenger;
import android.os.SystemClock;
import android.util.Log;
import android.util.SparseArray;
import android.view.View;
@ -228,6 +229,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++;
@ -507,7 +511,7 @@ public class NotificationCenter {
}
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<Integer> expiredIndices = null;
if (!allowDuringAnimation && allowedNotifications.size() > 0) {
int size = allowedNotifications.size();

View file

@ -2,29 +2,23 @@ package org.telegram.messenger;
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 @@ public class SavedMessagesController {
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 class SavedMessagesController {
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 class SavedMessagesController {
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 class SavedMessagesController {
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 class SavedMessagesController {
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 class SavedMessagesController {
changed = true;
}
}
if (!dialogsCountToCheck.isEmpty()) {
updateDialogsCount(dialogsCountToCheck);
}
return changed;
}
@ -432,6 +452,7 @@ public class SavedMessagesController {
if (d.dialogId == dialogId) {
if (d.messagesCount != messagesCount) {
d.messagesCount = messagesCount;
d.messagesCountLoaded = true;
return true;
}
break;
@ -519,7 +540,7 @@ public class SavedMessagesController {
dialogsCount = 0;
dialogsEndReached = false;
update();
loadDialogs();
loadDialogs(false);
}
public void deleteDialog(long did) {
@ -534,6 +555,14 @@ public class SavedMessagesController {
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 class SavedMessagesController {
saveCacheSchedule();
}
public boolean updatePinned(ArrayList<Long> dialogIds, boolean pin) {
public boolean updatePinned(ArrayList<Long> dialogIds, boolean pin, boolean toServer) {
ArrayList<Long> currentOrder = getCurrentPinnedOrder(allDialogs);
ArrayList<Long> newOrder = new ArrayList<>(currentOrder);
for (int i = dialogIds.size() - 1; i >= 0; --i) {
@ -585,9 +614,16 @@ public class SavedMessagesController {
return false;
}
if (!sameOrder(currentOrder, newOrder)) {
if (toServer) {
updatePinnedOrderToServer(newOrder);
}
return true;
} else {
final boolean updateLoaded = updatePinnedOrder(loadedDialogs, newOrder);
final boolean updateCached = updatePinnedOrder(cachedDialogs, newOrder);
return updateLoaded || updateCached;
}
}
return false;
}
public boolean updatePinnedOrder(ArrayList<Long> newOrder) {
@ -636,18 +672,9 @@ public class SavedMessagesController {
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<SavedDialog>[] 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<Long> 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<Long> newOrder = new ArrayList<>(upd.order.size());
@ -731,49 +758,8 @@ public class SavedMessagesController {
return true;
}
private void updateDialogsCount(HashSet<Long> dialogIds) {
final long selfId = UserConfig.getInstance(currentAccount).getClientUserId();
MessagesStorage messagesStorage = MessagesStorage.getInstance(currentAccount);
messagesStorage.getStorageQueue().postRunnable(() -> {
SQLiteDatabase db = messagesStorage.getDatabase();
LongSparseArray<Integer> 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 @@ public class SavedMessagesController {
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 @@ public class SavedMessagesController {
cachedDialogs.addAll(dialogs);
updateAllDialogs(true);
if (whenDone != null) {
if (whenDone != null && !loadingCacheOnly) {
whenDone.run();
}
});
@ -974,7 +962,7 @@ public class SavedMessagesController {
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 class SavedMessagesController {
public MessageObject message;
public int messagesCount;
public boolean messagesCountLoaded;
// used only in cache
private int localDate;
@ -1032,7 +1022,7 @@ public class SavedMessagesController {
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 class SavedMessagesController {
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<ArrayList<Utilities.Callback<Boolean>>> checkMessagesCallbacks = new LongSparseArray<>();
public void hasSavedMessages(long did, Utilities.Callback<Boolean> 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<Utilities.Callback<Boolean>> 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 class SavedMessagesController {
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();
}
}

View file

@ -2189,6 +2189,7 @@ public class SendMessagesHelper extends BaseController implements NotificationCe
a1--;
}
}
getNotificationCenter().postNotificationNameOnUIThread(NotificationCenter.savedMessagesForwarded, newMessagesByIds);
Integer value = getMessagesController().dialogs_read_outbox_max.get(peer);
if (value == null) {
value = getMessagesStorage().getDialogReadMax(true, peer);
@ -2958,7 +2959,7 @@ public class SendMessagesHelper extends BaseController implements NotificationCe
return voteSendTime.get(pollId, 0L);
}
public void sendReaction(MessageObject messageObject, ArrayList<ReactionsLayoutInBubble.VisibleReaction> visibleReactions, ReactionsLayoutInBubble.VisibleReaction addedReaction, boolean big, boolean addToRecent, ChatActivity parentFragment, Runnable callback) {
public void sendReaction(MessageObject messageObject, ArrayList<ReactionsLayoutInBubble.VisibleReaction> visibleReactions, ReactionsLayoutInBubble.VisibleReaction addedReaction, boolean big, boolean addToRecent, BaseFragment parentFragment, Runnable callback) {
if (messageObject == null || parentFragment == null) {
return;
}
@ -4092,6 +4093,7 @@ public class SendMessagesHelper extends BaseController implements NotificationCe
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);
@ -5102,11 +5104,13 @@ public class SendMessagesHelper extends BaseController implements NotificationCe
}
}
putToDelayedMessages(location, message);
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);
}
}

View file

@ -238,7 +238,6 @@ public class SharedConfig {
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;
@ -310,7 +309,6 @@ public class SharedConfig {
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;
@ -616,7 +614,6 @@ public class SharedConfig {
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);
@ -649,7 +646,6 @@ public class SharedConfig {
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);
@ -1003,13 +999,6 @@ public class SharedConfig {
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();
@ -1545,11 +1534,6 @@ public class SharedConfig {
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);

View file

@ -1001,7 +1001,7 @@ public class TopicsController extends BaseController {
}
}
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 class TopicsController extends BaseController {
} else {
ArrayList<TLRPC.TL_forumTopic> topicToReload = new ArrayList<>();
TLRPC.TL_forumTopic topic = new TLRPC.TL_forumTopic();
topic.id = topicId;
topic.id = (int) topicId;
reloadTopics(chatId, topicToReload, runnable);
}
});

View file

@ -499,6 +499,16 @@ public class Utilities {
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);
}

View file

@ -11,11 +11,10 @@ package org.telegram.messenger;
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 class VideoEncodingService extends Service implements NotificationCenter.
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 class VideoEncodingService extends Service implements NotificationCenter.
}
}
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 class VideoEncodingService extends Service implements NotificationCenter.
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 class VideoEncodingService extends Service implements NotificationCenter.
//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 @@ public class VideoEncodingService extends Service implements NotificationCenter.
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();
}
}

View file

@ -86,7 +86,7 @@ public class VideoPlayerHolderBase {
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 class VideoPlayerHolderBase {
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 class VideoPlayerHolderBase {
}
if (videoPlayer == null) {
ensurePlayerCreated(audioDisabled);
videoPlayer.setPlaybackSpeed(speed);
videoPlayer.preparePlayer(uri, "other");
videoPlayer.setWorkerQueue(dispatchQueue);
if (!paused) {
@ -280,6 +282,17 @@ public class VideoPlayerHolderBase {
}
}
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 class VideoPlayerHolderBase {
});
}
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 class VideoPlayerHolderBase {
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;

View file

@ -379,7 +379,7 @@ public class ConnectionsManager extends BaseController {
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(() -> {

View file

@ -23,6 +23,7 @@ import org.telegram.messenger.FileLoader;
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;
@ -76,7 +77,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;
@ -28863,6 +28864,8 @@ public class TLRPC {
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) {
@ -55720,6 +55723,8 @@ public class TLRPC {
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) {
@ -60820,7 +60825,7 @@ public class TLRPC {
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) {
@ -64959,9 +64964,8 @@ public class TLRPC {
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;
@ -75061,8 +75065,10 @@ public class TLRPC {
}
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
@ -75073,6 +75079,10 @@ public class TLRPC {
@Override
public void serializeToStream(AbstractSerializedData stream) {
stream.writeInt32(constructor);
stream.writeInt32(flags);
if ((flags & 1) != 0) {
peer.serializeToStream(stream);
}
stream.writeInt64(hash);
}
}

View file

@ -24,6 +24,7 @@ import android.graphics.Paint;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffColorFilter;
import android.graphics.Rect;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.os.Build;
import android.text.SpannableString;
@ -147,8 +148,6 @@ public class ActionBar extends FrameLayout {
private View.OnTouchListener interceptTouchEventListener;
private final Theme.ResourcesProvider resourcesProvider;
private PorterDuff.Mode colorFilterMode = PorterDuff.Mode.MULTIPLY;
SizeNotifierFrameLayout contentView;
boolean blurredBackground;
public Paint blurScrimPaint = new Paint();
@ -173,10 +172,6 @@ public class ActionBar extends FrameLayout {
});
}
public void setColorFilterMode(PorterDuff.Mode colorFilterMode) {
this.colorFilterMode = colorFilterMode;
}
public INavigationLayout.BackButtonState getBackButtonState() {
if (backButtonDrawable instanceof INavigationLayout.IBackButtonDrawable) {
return ((INavigationLayout.IBackButtonDrawable) backButtonDrawable).getBackButtonState();
@ -191,9 +186,6 @@ public class ActionBar extends FrameLayout {
backButtonImageView = new ImageView(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));
@ -228,6 +220,8 @@ public class ActionBar extends FrameLayout {
MenuDrawable menuDrawable = (MenuDrawable) drawable;
menuDrawable.setBackColor(actionBarColor);
menuDrawable.setIconColor(itemsColor);
} else if (drawable instanceof BitmapDrawable) {
backButtonImageView.setColorFilter(new PorterDuffColorFilter(itemsColor, PorterDuff.Mode.SRC_IN));
}
}
@ -359,6 +353,7 @@ public class ActionBar extends FrameLayout {
}
backButtonImageView.setVisibility(resource == 0 ? GONE : VISIBLE);
backButtonImageView.setImageResource(resource);
backButtonImageView.setColorFilter(new PorterDuffColorFilter(itemsColor, PorterDuff.Mode.SRC_IN));
}
private void createSubtitleTextView() {
@ -1599,18 +1594,21 @@ public class ActionBar extends FrameLayout {
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));
}
}
}

View file

@ -64,6 +64,7 @@ import org.telegram.ui.Components.FloatingDebug.FloatingDebugProvider;
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;
@ -1627,6 +1628,12 @@ public class ActionBarLayout extends FrameLayout implements INavigationLayout, F
fragmentsStack.add(position, fragment);
onFragmentStackChanged("addFragmentToStack");
}
if (!useAlphaAnimations) {
setVisibility(VISIBLE);
if (backgroundView != null) {
backgroundView.setVisibility(VISIBLE);
}
}
return true;
}
@ -2035,6 +2042,11 @@ public class ActionBarLayout extends FrameLayout implements INavigationLayout, F
removeFragmentFromStackInternal(fragmentsStack.get(a), false);
a--;
}
if (backgroundView != null) {
backgroundView.animate().alpha(0.0f).setDuration(180).withEndAction(() -> {
backgroundView.setVisibility(View.GONE);
}).start();
}
}
@Keep

View file

@ -508,6 +508,13 @@ public class ActionBarMenu extends LinearLayout {
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);

View file

@ -32,6 +32,7 @@ import android.transition.TransitionManager;
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;
@ -990,7 +991,7 @@ public class ActionBarMenuItem extends FrameLayout {
boolean visible = !currentSearchFilters.isEmpty();
ArrayList<FiltersView.MediaFilterData> 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);
@ -1055,6 +1056,7 @@ public class ActionBarMenuItem extends FrameLayout {
TransitionManager.beginDelayedTransition(searchFilterLayout, transition);
}
if (searchFilterLayout != null) {
for (int i = 0; i < searchFilterLayout.getChildCount(); i++) {
boolean removed = localFilters.remove(((SearchFilterView) searchFilterLayout.getChildAt(i)).getFilter());
if (!removed) {
@ -1062,6 +1064,7 @@ public class ActionBarMenuItem extends FrameLayout {
i--;
}
}
}
for (int i = 0; i < localFilters.size(); i++) {
FiltersView.MediaFilterData filter = localFilters.get(i);
@ -2041,10 +2044,11 @@ public class ActionBarMenuItem extends FrameLayout {
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
@ -2052,6 +2056,7 @@ public class ActionBarMenuItem extends FrameLayout {
return AnimatedEmojiDrawable.CACHE_TYPE_ALERT_EMOJI_STATUS;
}
};
reactionButton.isTag = true;
reactionButton.width = dp(44.33f);
reactionButton.height = dp(28);
reactionButton.choosen = true;

View file

@ -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);

View file

@ -65,6 +65,7 @@ import org.telegram.messenger.LocaleController;
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 @@ public class AlertDialog extends Dialog implements Drawable.Callback, Notificati
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,8 +605,14 @@ public class AlertDialog extends Dialog implements Drawable.Callback, Notificati
}
containerView.setFitsSystemWindows(Build.VERSION.SDK_INT >= 21);
if (setContent) {
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 class AlertDialog extends Dialog implements Drawable.Callback, Notificati
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);
@ -1546,6 +1561,11 @@ public class AlertDialog extends Dialog implements Drawable.Callback, Notificati
return this;
}
public Builder setWidth(int width) {
alertDialog.customWidth = width;
return this;
}
public Builder aboveMessageView(View view) {
alertDialog.aboveMessageView = view;
return this;

View file

@ -9,6 +9,7 @@ import android.content.res.TypedArray;
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.ViewCompat;
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 class AlertDialogDecor extends AlertDialog {
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);

View file

@ -16,7 +16,10 @@ import android.graphics.PixelFormat;
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 class BackDrawable extends Drawable {
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);

View file

@ -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]
};
}
}

View file

@ -3643,6 +3643,7 @@ public class Theme {
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
@ -3719,6 +3720,7 @@ public class Theme {
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++;
@ -4101,7 +4103,6 @@ public class Theme {
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++;
@ -4395,6 +4396,7 @@ public class Theme {
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]);

View file

@ -138,8 +138,8 @@ public class ThemeColors {
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;
@ -189,6 +189,7 @@ public class ThemeColors {
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;
@ -957,6 +958,7 @@ public class ThemeColors {
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");

View file

@ -471,7 +471,7 @@ public class DialogsSearchAdapter extends RecyclerListView.SelectionAdapter {
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();
@ -1107,7 +1107,7 @@ public class DialogsSearchAdapter extends RecyclerListView.SelectionAdapter {
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,

View file

@ -23,11 +23,14 @@ import org.telegram.ui.Cells.LoadingCell;
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<Integer> messageIds = new HashSet<>();
private ArrayList<MessageObject> searchResultMessages = new ArrayList<>();
public int loadedCount;
private int currentAccount = UserConfig.selectedAccount;
private final Theme.ResourcesProvider resourcesProvider;
@ -39,7 +42,17 @@ public class MessagesSearchAdapter extends RecyclerListView.SelectionAdapter {
@Override
public void notifyDataSetChanged() {
searchResultMessages = MediaDataController.getInstance(currentAccount).getFoundMessageObjects();
searchResultMessages.clear();
messageIds.clear();
ArrayList<MessageObject> 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 class MessagesSearchAdapter extends RecyclerListView.SelectionAdapter {
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);
}
}

View file

@ -6487,7 +6487,7 @@ public class ArticleViewer implements NotificationCenter.NotificationCenterDeleg
}
videoPlayer.seekTo(playFrom);
videoPlayer.preparePlayer(uri, true);
videoPlayer.preparePlayer(uri, true, 1f);
videoPlayer.play();
}

View file

@ -476,7 +476,13 @@ public class CalendarActivity extends BaseFragment implements NotificationCenter
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();

View file

@ -187,6 +187,14 @@ public class AboutLinkCell extends FrameLayout {
setWillNotDraw(false);
}
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();
@ -283,7 +291,7 @@ public class AboutLinkCell extends FrameLayout {
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);
@ -461,7 +469,8 @@ public class AboutLinkCell extends FrameLayout {
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();
@ -490,11 +499,12 @@ public class AboutLinkCell extends FrameLayout {
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);

View file

@ -62,6 +62,7 @@ import android.text.style.CharacterStyle;
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;
@ -383,11 +384,11 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate
}
}
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);
}
@ -656,6 +657,10 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate
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;
@ -757,7 +762,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate
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();
@ -2512,7 +2517,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate
}
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();
@ -4862,7 +4867,11 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate
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))) {
@ -4924,7 +4933,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate
if (!groupChanged && groupedMessages != null) {
MessageObject.GroupedMessagePosition newPosition;
if (groupedMessages.messages.size() > 1) {
newPosition = currentMessagesGroup.positions.get(currentMessageObject);
newPosition = currentMessagesGroup.getPosition(currentMessageObject);
} else {
newPosition = null;
}
@ -4948,7 +4957,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate
}
widthBeforeNewTimeLine = -1;
if (currentMessagesGroup != null && (currentMessagesGroup.posArray.size() > 1)) {
currentPosition = currentMessagesGroup.positions.get(currentMessageObject);
currentPosition = currentMessagesGroup.getPosition(currentMessageObject);
if (currentPosition == null) {
currentMessagesGroup = null;
}
@ -5163,15 +5172,20 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate
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);
}
}
@ -5381,7 +5395,10 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate
}
if (!drawInstantView) {
if (messageObject.isSponsored()) {
if (messageObject.isUnsupported()) {
drawInstantView = true;
drawInstantViewType = 21;
} else if (messageObject.isSponsored()) {
drawInstantView = true;
hasLinkPreview = true;
instantViewButtonText = messageObject.sponsoredButtonText;
@ -5658,7 +5675,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate
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;
@ -6624,6 +6641,10 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate
blurredPhotoImage.getBitmap().recycle();
blurredPhotoImage.setImageBitmap((Bitmap) null);
}
if (messageObject.isUnsupported()) {
createInstantViewButton();
}
}
} else if (messageObject.type == MessageObject.TYPE_PHONE_CALL) {
createSelectorDrawable(0);
@ -7271,30 +7292,20 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate
}
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;
}
@ -8387,7 +8398,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate
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;
@ -9317,6 +9328,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate
}
useTranscribeButton = (
currentMessageObject != null &&
!currentMessageObject.isRepostPreview &&
(!currentMessageObject.isOutOwner() || currentMessageObject.isSent()) &&
(
UserConfig.getInstance(currentAccount).isPremium()
@ -9566,6 +9578,9 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate
}
int newLineForTimeDp = 14;
if (currentMessageObject.isUnsupported()) {
newLineForTime = true;
}
if (
currentMessageObject.hasCodeAtBottom && (reactionsLayoutInBubble.isEmpty || reactionsLayoutInBubble.isSmall) ||
currentMessageObject.hasQuoteAtBottom && (reactionsLayoutInBubble.isEmpty || reactionsLayoutInBubble.isSmall)
@ -9858,7 +9873,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate
@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
@ -9941,7 +9956,9 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate
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();
@ -10088,6 +10105,8 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate
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);
}
@ -10147,7 +10166,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate
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);
@ -10177,7 +10196,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate
}
}
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);
@ -11616,7 +11635,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate
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;
@ -11743,7 +11762,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate
}
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();
@ -11807,7 +11826,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate
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) {
@ -12223,7 +12242,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate
}
} else {
int color = getThemedColor(Theme.key_chat_inPreviewInstantText);
if (linkLine != null) {
if (linkLine != null && !currentMessageObject.isUnsupported()) {
color = linkLine.getColor();
}
if (this.instantDrawable == null) {
@ -12274,7 +12293,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate
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();
}
@ -12420,17 +12439,18 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate
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;
@ -12447,14 +12467,14 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate
}
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) {
@ -12858,7 +12878,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate
restore = canvas.saveLayerAlpha(rect, (int) (alpha * 255), Canvas.ALL_SAVE_FLAG);
}
}
int spoilersColor = currentMessageObject.isOut() && !ChatObject.isChannelAndNotMegaGroup(currentMessageObject.getChatId(), currentAccount) ? getThemedColor(Theme.key_chat_outTimeText) : Theme.chat_msgTextPaint.getColor();
int spoilersColor = currentMessageObject.isOutOwner() && !ChatObject.isChannelAndNotMegaGroup(currentMessageObject.getChatId(), currentAccount) ? getThemedColor(Theme.key_chat_outTimeText) : Theme.chat_msgTextPaint.getColor();
if (quoteHighlight != null && currentMessagesGroup == null) {
Theme.MessageDrawable backgroundDrawable = currentBackgroundDrawable;
if (backgroundDrawable != null) {
@ -13157,17 +13177,12 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate
if (documentAttachType == DOCUMENT_ATTACH_TYPE_STICKER || documentAttachType == DOCUMENT_ATTACH_TYPE_WALLPAPER || currentMessageObject.type == MessageObject.TYPE_ROUND_VIDEO) {
int maxWidth;
if (AndroidUtilities.isTablet()) {
if (needDrawAvatar()) {
maxWidth = AndroidUtilities.getMinTabletSide() - AndroidUtilities.dp(42);
maxWidth = AndroidUtilities.getMinTabletSide() - AndroidUtilities.dp(needDrawAvatar() ? 42 : 0);
} else {
maxWidth = AndroidUtilities.getMinTabletSide();
}
} else {
if (needDrawAvatar()) {
maxWidth = Math.min(getParentWidth(), AndroidUtilities.displaySize.y) - AndroidUtilities.dp(42);
} else {
maxWidth = Math.min(getParentWidth(), AndroidUtilities.displaySize.y);
maxWidth = Math.min(getParentWidth(), AndroidUtilities.displaySize.y) - AndroidUtilities.dp(needDrawAvatar() ? 42 : 0);
}
if (currentMessageObject != null && currentMessageObject.isSaved && currentMessageObject.isOutOwner() && checkNeedDrawShareButton(currentMessageObject)) {
maxWidth -= dp(25);
}
if (isPlayingRound && (currentMessageObject == null || !currentMessageObject.isVoiceTranscriptionOpen())) {
int backgroundWidthLocal = backgroundWidth - (AndroidUtilities.roundPlayingMessageSize - AndroidUtilities.roundMessageSize);
@ -13195,7 +13210,12 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate
} else if (currentMessageObject.type == MessageObject.TYPE_EMOJIS) {
return Math.max(currentMessageObject.textWidth, (int) ((AndroidUtilities.displaySize.x - AndroidUtilities.dp(52) - (isAvatarVisible ? AndroidUtilities.dp(48) : 0)) * .5f));
} else {
return backgroundWidth - AndroidUtilities.dp(mediaBackground ? 22 : 31);
int width = backgroundWidth;
if (currentMessageObject != null && currentMessageObject.isSaved && currentMessageObject.isOutOwner() && checkNeedDrawShareButton(currentMessageObject)) {
width -= dp(25);
}
width -= dp(mediaBackground ? 22 : 31);
return width;
}
}
@ -14254,6 +14274,12 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate
timeString = LocaleController.formatSmallDateChat(messageObject.messageOwner.date) + ", " + LocaleController.getInstance().formatterDay.format((long) (messageObject.messageOwner.date) * 1000);
} else if (edited) {
timeString = LocaleController.getString("EditedMessage", R.string.EditedMessage) + " " + LocaleController.getInstance().formatterDay.format((long) (messageObject.messageOwner.date) * 1000);
} else if (currentMessageObject.isSaved && currentMessageObject.messageOwner.fwd_from != null && (currentMessageObject.messageOwner.fwd_from.date != 0 || currentMessageObject.messageOwner.fwd_from.saved_date != 0)) {
int date = currentMessageObject.messageOwner.fwd_from.date;
if (date == 0) {
date = currentMessageObject.messageOwner.fwd_from.saved_date;
}
timeString = LocaleController.formatSeenDate(date);
} else {
timeString = LocaleController.getInstance().formatterDay.format((long) (messageObject.messageOwner.date) * 1000);
}
@ -14368,7 +14394,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate
}
if (currentMessagesGroup != null && currentPosition != null) {
final boolean last = (currentPosition.flags & MessageObject.POSITION_FLAG_BOTTOM) != 0 && (currentPosition.flags & (messageObject.isOutOwner() ? MessageObject.POSITION_FLAG_LEFT : MessageObject.POSITION_FLAG_RIGHT)) != 0;
if ((!currentMessagesGroup.reversed && !currentMessagesGroup.isDocuments && !last || currentMessagesGroup.reversed && !last)) {
if (!currentMessagesGroup.isDocuments && !last) {
return false;
}
}
@ -14735,7 +14761,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate
topicButton = null;
}
if (!messageObject.isGiveawayResults() && (!isThreadChat || messageObject.getReplyTopMsgId(isForum) != 0 || isForumGeneral) && messageObject.hasValidReplyMessageObject() || messageObject.messageOwner.fwd_from != null && messageObject.isDice() || (messageObject.messageOwner.reply_to != null && (messageObject.messageOwner.reply_to.story_id != 0 || !TextUtils.isEmpty(messageObject.messageOwner.reply_to.quote_text) || messageObject.messageOwner.reply_to.reply_from != null))) {
if ((!messageObject.isGiveawayResults() && (!isThreadChat || isSavedChat || messageObject.getReplyTopMsgId(isForum) != 0 || isForumGeneral) && messageObject.hasValidReplyMessageObject() || messageObject.messageOwner.fwd_from != null && messageObject.isDice() || (messageObject.messageOwner.reply_to != null && (messageObject.messageOwner.reply_to.story_id != 0 || !TextUtils.isEmpty(messageObject.messageOwner.reply_to.quote_text) || messageObject.messageOwner.reply_to.reply_from != null))) && !messageObject.isRepostPreview) {
if (currentPosition == null || currentPosition.minY == 0) {
if (!messageObject.isAnyKindOfSticker() && messageObject.type != MessageObject.TYPE_ROUND_VIDEO || messageObject.type == MessageObject.TYPE_EMOJIS) {
namesOffset += AndroidUtilities.dp(20) + (Theme.chat_replyTextPaint.getTextSize() + Theme.chat_replyNamePaint.getTextSize());
@ -14753,7 +14779,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate
if (!messageObject.shouldDrawWithoutBackground()) {
maxWidth -= AndroidUtilities.dp(messageObject.isOutOwner() ? 20 : 10);
if (messageObject.type != MessageObject.TYPE_TEXT || messageObject.needDrawShareButton()) {
maxWidth -= AndroidUtilities.dp(10);
maxWidth -= AndroidUtilities.dp(messageObject.isSaved && messageObject.isOutOwner() ? 35 : 10);
}
} else if (messageObject.type == MessageObject.TYPE_ROUND_VIDEO) {
maxWidth += AndroidUtilities.dp(13);
@ -14785,7 +14811,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate
stringFinalText = StoriesUtilities.createReplyStoryString();
maxWidth -= AndroidUtilities.dp(16) + (textPaint.getTextSize() + Theme.chat_replyNamePaint.getTextSize());
}
} else if ((!isThreadChat || messageObject.getReplyTopMsgId(isForum) != 0 || isForumGeneral) && messageObject.hasValidReplyMessageObject() || hasReplyQuote || messageObject.messageOwner.reply_to != null && messageObject.messageOwner.reply_to.reply_from != null) {
} else if ((!isThreadChat || isSavedChat || messageObject.getReplyTopMsgId(isForum) != 0 || isForumGeneral) && messageObject.hasValidReplyMessageObject() || hasReplyQuote || messageObject.messageOwner.reply_to != null && messageObject.messageOwner.reply_to.reply_from != null) {
lastReplyMessage = messageObject.replyMessageObject == null ? null : messageObject.replyMessageObject.messageOwner;
int cacheType = 1;
int size = 0;
@ -15050,7 +15076,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate
replyTextWidth -= sz;
maxWidth += sz;
}
if (changed || !isReplyQuote && (currentMessageObject.shouldDrawWithoutBackground() || Build.VERSION.SDK_INT < Build.VERSION_CODES.M)) {
if (changed || !isReplyQuote) {
stringFinalText = TextUtils.ellipsize(sb, textPaint, maxWidth, TextUtils.TruncateAt.END);
} else {
stringFinalText = sb;
@ -15103,8 +15129,8 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate
FileLog.e(e);
}
}
} else if (!isThreadChat && messageObject.getReplyMsgId() != 0 && !messageObject.isGiveawayResults()) {
if (!(messageObject.replyMessageObject != null && (messageObject.replyMessageObject.messageOwner instanceof TLRPC.TL_messageEmpty || messageObject.replyMessageObject.messageOwner != null && messageObject.replyMessageObject.messageOwner.action instanceof TLRPC.TL_messageActionTopicCreate)) && messageObject.getDialogId() != UserObject.REPLY_BOT) {
} else if (!isThreadChat && messageObject.getReplyMsgId() != 0 && !messageObject.isGiveawayResults() && !messageObject.isRepostPreview) {
if (!(messageObject.replyMessageObject != null && (messageObject.replyMessageObject.messageOwner instanceof TLRPC.TL_messageEmpty || messageObject.replyMessageObject.messageOwner != null && messageObject.replyMessageObject.messageOwner.action instanceof TLRPC.TL_messageActionTopicCreate)) && (delegate == null || delegate.doNotShowLoadingReply(messageObject))) {
if (!messageObject.isAnyKindOfSticker() && messageObject.type != MessageObject.TYPE_ROUND_VIDEO) {
namesOffset += AndroidUtilities.dp(14 + 4) + (Theme.chat_replyTextPaint.getTextSize() + Theme.chat_replyNamePaint.getTextSize());
if (messageObject.type != MessageObject.TYPE_TEXT) {
@ -16432,8 +16458,11 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate
}
}
}
if (drawSideButton != 4 && sideStartY < (layoutHeight - AndroidUtilities.dp(32)) / 2f) {
sideStartY = (layoutHeight - AndroidUtilities.dp(32)) / 2f;
if (drawSideButton != 4) {
float sideMin = (layoutHeight + transitionParams.deltaBottom - AndroidUtilities.dp(32)) / 2f;
if (sideStartY < sideMin) {
sideStartY = sideMin;
}
}
if (!currentMessageObject.isOutOwner() && isRoundVideo && !hasLinkPreview) {
float offsetSize = isAvatarVisible ? ((AndroidUtilities.roundPlayingMessageSize - AndroidUtilities.roundMessageSize) * 0.7f) : AndroidUtilities.dp(50);
@ -16689,7 +16718,8 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate
replyForwardAlpha = 0;
}
}
if (drawNameLayout && nameLayout != null) {
if ((drawNameLayout || transitionParams.animateDrawNameLayout) && nameLayout != null) {
float nameAlpha = !transitionParams.animateDrawNameLayout ? 1f : (drawNameLayout ? transitionParams.animateChangeProgress : 1f - transitionParams.animateChangeProgress);
canvas.save();
int oldAlpha;
@ -16813,6 +16843,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate
(int) (nx + (viaNameWidth > 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) {
@ -16828,12 +16859,16 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate
(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) {
@ -17379,7 +17414,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate
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();
@ -20324,7 +20359,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate
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)) {
@ -20792,7 +20827,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate
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) {
@ -21608,6 +21643,9 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate
public boolean animateRecommendationsExpanded;
public boolean animateFromRecommendationsExpanded;
public boolean lastDrawNameLayout;
public boolean animateDrawNameLayout;
public void recordDrawingState() {
wasDraw = true;
lastDrawingImageX = photoImage.getImageX();
@ -21701,6 +21739,8 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate
} else {
lastDrawReplyY = 0;
}
lastDrawNameLayout = drawNameLayout;
}
public void recordDrawingStatePreview() {
@ -21748,6 +21788,11 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate
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;
@ -22056,6 +22101,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate
animateRadius = false;
animateChangeProgress = 1f;
animateMessageText = false;
animateDrawNameLayout = false;
animateOutTextBlocks = null;
animateEditedLayout = null;
animateTimeLayout = null;
@ -22209,4 +22255,12 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate
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;
}
}

View file

@ -171,6 +171,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
@ -331,7 +332,7 @@ public class DialogCell extends BaseCell implements StoriesListPlaceProvider.Ava
private int currentDialogFolderId;
private int currentDialogFolderDialogsCount;
private int currentEditDate;
private boolean isDialogCell;
public boolean isDialogCell;
private int lastMessageDate;
private int unreadCount;
private boolean markUnread;
@ -950,6 +951,11 @@ public class DialogCell extends BaseCell implements StoriesListPlaceProvider.Ava
}
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));
@ -1226,7 +1232,7 @@ public class DialogCell extends BaseCell implements StoriesListPlaceProvider.Ava
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;
@ -1425,9 +1431,13 @@ public class DialogCell extends BaseCell implements StoriesListPlaceProvider.Ava
} else {
needEmoji = true;
updateMessageThumbs();
if (chat != null && chat.id > 0 && fromChat == null && (!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 && fromChat == null && (!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("-");
@ -2205,7 +2215,7 @@ public class DialogCell extends BaseCell implements StoriesListPlaceProvider.Ava
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);
}
}
@ -3041,7 +3051,7 @@ public class DialogCell extends BaseCell implements StoriesListPlaceProvider.Ava
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;
@ -4797,6 +4807,24 @@ public class DialogCell extends BaseCell implements StoriesListPlaceProvider.Ava
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) {
@ -4809,7 +4837,14 @@ public class DialogCell extends BaseCell implements StoriesListPlaceProvider.Ava
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", "");
@ -4827,7 +4862,7 @@ public class DialogCell extends BaseCell implements StoriesListPlaceProvider.Ava
}
} else if (fromChat != null && fromChat.title != null) {
return fromChat.title.replace("\n", "");
}else {
} else {
return "DELETED";
}
}

View file

@ -14,6 +14,7 @@ import android.text.TextUtils;
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 class ExpiredStoryView {
canvas.save();
canvas.translate(textX, textY);
if (titleLayout != null) {
titleLayout.draw(canvas);
canvas.translate(0, titleLayout.getHeight() + AndroidUtilities.dp(2));
}
if (subtitleLayout != null) {
subtitleLayout.draw(canvas);
}
canvas.restore();
}
}

View file

@ -399,8 +399,13 @@ public class StickerSetCell extends FrameLayout {
} 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) {
@ -424,8 +429,13 @@ public class StickerSetCell extends FrameLayout {
} 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);
}
}
}

View file

@ -268,7 +268,7 @@ public class TextCell extends FrameLayout {
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 class TextCell extends FrameLayout {
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);
}
}

File diff suppressed because it is too large Load diff

View file

@ -14,6 +14,7 @@ import android.widget.FrameLayout;
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<FrameLayout> 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 @@ public class ChatActivityContainer extends FrameLayout {
parent.removeView(fragmentView);
}
}
chatActivity.openedInstantly();
addView(fragmentView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT));
if (isActive) {
chatActivity.onResume();

View file

@ -199,6 +199,7 @@ public class ChatReactionsEditActivity extends BaseFragment implements Notificat
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) {

View file

@ -24,7 +24,7 @@ import org.telegram.ui.Components.SpeedIconDrawable;
public class ChooseSpeedLayout {
ActionBarPopupWindow.ActionBarPopupWindowLayout speedSwipeBackLayout;
public ActionBarPopupWindow.ActionBarPopupWindowLayout speedSwipeBackLayout;
ActionBarMenuSlider.SpeedSlider slider;
private static final float MIN_SPEED = 0.2f;

View file

@ -604,7 +604,7 @@ public class AnimatedEmojiDrawable extends Drawable {
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 @@ public class AnimatedEmojiDrawable extends Drawable {
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);
}
}

View file

@ -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 class AnimatedTextView extends View {
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 class AnimatedTextView extends View {
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 class AnimatedTextView extends View {
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 class AnimatedTextView extends View {
}
}
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 class AnimatedTextView extends View {
}
}
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 class AnimatedTextView extends View {
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 class AnimatedTextView extends View {
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 class AnimatedTextView extends View {
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 class AnimatedTextView extends View {
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 class AnimatedTextView extends View {
}
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
@ -1055,6 +1070,10 @@ public class AnimatedTextView extends View {
drawable.setAnimationProperties(moveAmplitude, startDelay, duration, interpolator);
}
public void setScaleProperty(float scale) {
drawable.setScaleProperty(scale);
}
public AnimatedTextDrawable getDrawable() {
return drawable;
}

View file

@ -80,6 +80,7 @@ import org.telegram.messenger.R;
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;
@ -457,6 +458,12 @@ public class AudioPlayerAlert extends BottomSheet implements NotificationCenter.
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) {

View file

@ -349,6 +349,10 @@ public class BackupImageView extends View {
invalidate();
}
public AnimatedEmojiDrawable getAnimatedEmojiDrawable() {
return animatedEmojiDrawable;
}
ValueAnimator roundRadiusAnimator;
public void animateToRoundRadius(int animateToRad) {

View file

@ -15,7 +15,7 @@ import org.telegram.messenger.SharedConfig;
public class BlurredFrameLayout extends FrameLayout {
private final SizeNotifierFrameLayout sizeNotifierFrameLayout;
protected final SizeNotifierFrameLayout sizeNotifierFrameLayout;
protected Paint backgroundPaint;
public int backgroundColor = Color.TRANSPARENT;
public int backgroundPaddingBottom;

View file

@ -160,10 +160,10 @@ public abstract class BottomSheetWithRecyclerListView extends BottomSheet {
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

View file

@ -22,10 +22,15 @@ import android.graphics.Shader;
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 androidx.dynamicanimation.animation.SpringForce;
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 @@ public class Bulletin {
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 @@ public class Bulletin {
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 class Bulletin {
}
private boolean wrapWidth;
public void setWrapWidth() {
wrapWidth = true;
}
@ -1307,10 +1323,156 @@ public class Bulletin {
}
}
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<ReactionsLayoutInBubble.VisibleReaction> 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;
@ -1322,6 +1484,10 @@ public class Bulletin {
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);
@ -1329,7 +1495,6 @@ public class Bulletin {
}
};
NotificationCenter.listenEmojiLoading(textView);
textView.setDisablePaddingsOffset(true);
textView.setSingleLine();
textView.setTypeface(Typeface.SANS_SERIF);
textView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 15);
@ -1786,6 +1951,7 @@ public class Bulletin {
}
private final BulletinWindowLayout container;
private BulletinWindow(Context context, Delegate delegate) {
super(context);
setContentView(

View file

@ -3,19 +3,22 @@ package org.telegram.ui.Components;
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.View;
import android.view.ViewGroup;
import android.widget.FrameLayout;
import android.widget.ImageView;
import androidx.annotation.CheckResult;
import androidx.annotation.NonNull;
@ -40,6 +43,7 @@ import org.telegram.tgnet.TLObject;
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;
@ -1028,6 +1032,32 @@ public final class BulletinFactory {
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);
@ -1182,6 +1212,39 @@ public final class BulletinFactory {
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 {

View file

@ -1072,9 +1072,14 @@ public class ChatActivityEnterView extends BlurredFrameLayout implements Notific
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);
@ -1498,6 +1503,11 @@ public class ChatActivityEnterView extends BlurredFrameLayout implements Notific
}
}
@Override
protected boolean dispatchHoverEvent(MotionEvent event) {
return super.dispatchHoverEvent(event) || virtualViewHelper.dispatchHoverEvent(event);
}
public void updateColors() {
periodDrawable.updateColors(
getThemedColor(Theme.key_chat_messagePanelVoiceLock),
@ -1580,6 +1590,53 @@ public class ChatActivityEnterView extends BlurredFrameLayout implements Notific
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<Integer> 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;
@ -2763,6 +2820,7 @@ public class ChatActivityEnterView extends BlurredFrameLayout implements Notific
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) {
@ -2932,9 +2990,9 @@ public class ChatActivityEnterView extends BlurredFrameLayout implements Notific
// });
audioVideoSendButton = new ChatActivityEnterViewAnimatedIconView(context);
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));
@ -4165,7 +4223,7 @@ public class ChatActivityEnterView extends BlurredFrameLayout implements Notific
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);

View file

@ -25,6 +25,7 @@ import android.text.TextUtils;
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;
@ -298,7 +299,7 @@ public class ChatAvatarContainer extends FrameLayout implements NotificationCent
}
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));
}
@ -315,6 +316,62 @@ public class ChatAvatarContainer extends FrameLayout implements NotificationCent
}
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() {
@ -406,10 +463,10 @@ public class ChatAvatarContainer extends FrameLayout implements NotificationCent
}
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;
}
@ -427,13 +484,17 @@ public class ChatAvatarContainer extends FrameLayout implements NotificationCent
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();
@ -456,7 +517,7 @@ public class ChatAvatarContainer extends FrameLayout implements NotificationCent
if (fromChatAnimation) {
fragment.setPlayProfileAnimation(byAvatar ? 2 : 1);
}
parentFragment.presentFragment(fragment);
parentFragment.presentFragment(fragment, removeLast);
}
} else if (chat != null) {
Bundle args = new Bundle();
@ -471,7 +532,7 @@ public class ChatAvatarContainer extends FrameLayout implements NotificationCent
if (fromChatAnimation) {
fragment.setPlayProfileAnimation(byAvatar ? 2 : 1);
}
parentFragment.presentFragment(fragment);
parentFragment.presentFragment(fragment, removeLast);
}
}

View file

@ -95,7 +95,7 @@ public class ChatGreetingsView extends LinearLayout {
}
}
private ImageView premiumIconView;
private RLottieImageView premiumIconView;
private TextView premiumTextView;
private TextView premiumButtonView;
@ -105,12 +105,17 @@ public class ChatGreetingsView extends LinearLayout {
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);

View file

@ -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 class ChatScrimPopupContainerLayout extends LinearLayout {
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 @@ public class ChatScrimPopupContainerLayout extends LinearLayout {
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 @@ public class ChatScrimPopupContainerLayout extends LinearLayout {
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 @@ public class ChatScrimPopupContainerLayout extends LinearLayout {
} 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);

View file

@ -12,6 +12,7 @@ import android.text.Layout;
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 class CounterView extends View {
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 @@ public class CounterView extends View {
}
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 class CounterView extends View {
}
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 class CounterView extends View {
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 class CounterView extends View {
}
}
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 class CounterView extends View {
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);

View file

@ -651,6 +651,7 @@ public class EditTextBoldCursor extends EditTextEffects {
}
}
hintLayout = new StaticLayout(text, paint, AndroidUtilities.dp(1000), Layout.Alignment.ALIGN_NORMAL, 1.0f, 0.0f, false);
invalidate();
}
}

View file

@ -269,23 +269,12 @@ public class EditTextCaption extends EditTextBoldCursor {
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) {
@ -299,7 +288,6 @@ public class EditTextCaption extends EditTextBoldCursor {
editText.setSelection(0, editText.getText().length());
}
}
}
public boolean closeCreationLinkDialog() {
if (creationLinkDialog != null && creationLinkDialog.isShowing()) {

View file

@ -476,6 +476,10 @@ public class EditTextEmoji extends FrameLayout implements NotificationCenter.Not
editText.setSelection(selection);
}
public void setSelection(int from, int to) {
editText.setSelection(from, to);
}
public void hidePopup(boolean byBackButton) {
if (isPopupShowing()) {
showPopup(0);
@ -521,6 +525,7 @@ public class EditTextEmoji extends FrameLayout implements NotificationCenter.Not
}
public void openKeyboard() {
editText.requestFocus();
AndroidUtilities.showKeyboard(editText);
}

View file

@ -1648,7 +1648,7 @@ public class InstantCameraView extends FrameLayout implements NotificationCenter
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();

View file

@ -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 class MediaActivity extends BaseFragment implements SharedMediaLayout.Sha
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 class MediaActivity extends BaseFragment implements SharedMediaLayout.Sha
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);
@ -210,10 +212,12 @@ public class MediaActivity extends BaseFragment implements SharedMediaLayout.Sha
}
} 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) {
@ -386,7 +390,7 @@ public class MediaActivity extends BaseFragment implements SharedMediaLayout.Sha
}
};
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();
@ -537,7 +541,7 @@ public class MediaActivity extends BaseFragment implements SharedMediaLayout.Sha
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() {
@ -616,7 +620,7 @@ public class MediaActivity extends BaseFragment implements SharedMediaLayout.Sha
@Override
protected boolean includeSavedDialogs() {
return type == TYPE_MEDIA && dialogId == getUserConfig().getClientUserId();
return type == TYPE_MEDIA && dialogId == getUserConfig().getClientUserId() && topicId == 0;
}
@Override
@ -752,9 +756,15 @@ public class MediaActivity extends BaseFragment implements SharedMediaLayout.Sha
}
}
};
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));
@ -779,14 +789,26 @@ public class MediaActivity extends BaseFragment implements SharedMediaLayout.Sha
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) {
@ -795,8 +817,8 @@ public class MediaActivity extends BaseFragment implements SharedMediaLayout.Sha
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));
@ -809,7 +831,7 @@ public class MediaActivity extends BaseFragment implements SharedMediaLayout.Sha
}
}
} 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);
@ -827,6 +849,13 @@ public class MediaActivity extends BaseFragment implements SharedMediaLayout.Sha
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 {
@ -1114,8 +1143,12 @@ public class MediaActivity extends BaseFragment implements SharedMediaLayout.Sha
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));
@ -1160,11 +1193,9 @@ public class MediaActivity extends BaseFragment implements SharedMediaLayout.Sha
}
private class StoriesTabsView extends BottomPagerTabs {
public StoriesTabsView(Context context, Theme.ResourcesProvider resourcesProvider) {
super(context, resourcesProvider);
}
@Override
public Tab[] createTabs() {
Tab[] tabs = new Tab[] {

View file

@ -693,7 +693,7 @@ public class MessagePreviewView extends FrameLayout {
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 class MessagePreviewView extends FrameLayout {
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 @@ public class MessagePreviewView extends FrameLayout {
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;
}
}

View file

@ -43,6 +43,8 @@ import org.telegram.ui.PremiumPreviewFragment;
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 @@ public class MessagePrivateSeenView extends FrameLayout {
}
} 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 @@ public class MessagePrivateSeenView extends FrameLayout {
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);
}
}

View file

@ -792,7 +792,7 @@ public class MessageEntityView extends EntityView {
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 @@ public class MessageEntityView extends EntityView {
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 class MessageEntityView extends EntityView {
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;
}

View file

@ -648,6 +648,7 @@ public class LimitReachedBottomSheet extends BottomSheetWithRecyclerListView imp
fireworksOverlay.start();
fireworksOverlay.performHapticFeedback(HapticFeedbackConstants.KEYBOARD_TAP);
headerView.boostCounterView.setCount(canApplyBoost.boostCount, true);
recyclerListView.smoothScrollToPosition(0);
}
private void sendInviteMessages() {
@ -1092,7 +1093,7 @@ public class LimitReachedBottomSheet extends BottomSheetWithRecyclerListView imp
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);

View file

@ -488,8 +488,6 @@ public class PremiumFeatureBottomSheet extends BottomSheet implements Notificati
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);
@ -534,6 +532,7 @@ public class PremiumFeatureBottomSheet extends BottomSheet implements Notificati
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));
@ -677,8 +676,11 @@ public class PremiumFeatureBottomSheet extends BottomSheet implements Notificati
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)));

View file

@ -17,6 +17,7 @@ import org.telegram.messenger.AndroidUtilities;
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 class PremiumLockIconView extends ImageView {
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 @@ public class PremiumLockIconView extends ImageView {
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 class PremiumLockIconView extends ImageView {
}
}
public void setAnimatedEmojiDrawable(AnimatedEmojiDrawable emojiDrawable) {
this.emojiDrawable = emojiDrawable;
if (emojiDrawable != null) {
waitingImage = true;
invalidate();
}
}
public ImageReceiver getImageReceiver() {
return imageReceiver;
}

View file

@ -267,6 +267,18 @@ public class StarParticlesView extends View {
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 class StarParticlesView extends View {
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

View file

@ -61,6 +61,11 @@ public class StoriesPageView extends BaseListPageView {
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),

View file

@ -131,12 +131,14 @@ public class VideoScreenPreview extends FrameLayout implements PagerHeaderView,
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 @@ public class VideoScreenPreview extends FrameLayout implements PagerHeaderView,
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());

View file

@ -444,8 +444,13 @@ public class UserSelectorBottomSheet extends BottomSheetWithRecyclerListView imp
actionButton.setShowZero(false);
SpannableStringBuilder stringBuilder = new SpannableStringBuilder();
if (selectedIds.size() == 0) {
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));
}

View file

@ -11,6 +11,7 @@ import android.animation.AnimatorListenerAdapter;
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 class ChatCustomReactionsEditActivity extends BaseFragment implements Not
private boolean closeKeyboard() {
if (emojiKeyboardVisible) {
emojiKeyboardVisible = false;
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 @@ public class ChatCustomReactionsEditActivity extends BaseFragment implements Not
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 class ChatCustomReactionsEditActivity extends BaseFragment implements Not
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;

View file

@ -66,7 +66,9 @@ public class ChatSelectionReactionMenuOverlay extends FrameLayout {
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 class ChatSelectionReactionMenuOverlay extends FrameLayout {
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);

View file

@ -2,6 +2,7 @@ package org.telegram.ui.Components.Reactions;
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 @@ import java.util.List;
public class CustomEmojiReactionsWindow {
ContainerView containerView;
public ContainerView containerView;
WindowManager windowManager;
public FrameLayout windowView;
boolean attachToParent;
@ -164,7 +165,7 @@ public class CustomEmojiReactionsWindow {
// 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 @@ public class CustomEmojiReactionsWindow {
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 class CustomEmojiReactionsWindow {
}
}
private class ContainerView extends FrameLayout {
public class ContainerView extends FrameLayout {
Drawable shadow;
Rect shadowPad = new Rect();
@ -781,7 +782,7 @@ public class CustomEmojiReactionsWindow {
}
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();

View file

@ -12,6 +12,9 @@ import android.graphics.PorterDuffColorFilter;
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.MotionEvent;
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.tgnet.TLRPC;
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<ReactionButton> reactionButtons = new ArrayList<>();
public ArrayList<ReactionButton> reactionButtons = new ArrayList<>();
ArrayList<ReactionButton> outButtons = new ArrayList<>();
HashMap<String, ReactionButton> lastDrawingReactionButtons = new HashMap<>();
HashMap<String, ReactionButton> 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 @@ public class ReactionsLayoutInBubble {
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 class ReactionsLayoutInBubble {
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<ReactionButton> oldButtons = new ArrayList<>(reactionButtons);
hasUnreadReactions = false;
@ -159,9 +176,9 @@ public class ReactionsLayoutInBubble {
// 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<TLObject> users = null;
if (messageObject.getDialogId() > 0 && !UserObject.isReplyUser(messageObject.getDialogId())) {
@ -212,7 +229,7 @@ public class ReactionsLayoutInBubble {
}
}
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 class ReactionsLayoutInBubble {
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 class ReactionsLayoutInBubble {
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 class ReactionsLayoutInBubble {
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 class ReactionsLayoutInBubble {
}
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 class ReactionsLayoutInBubble {
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 class ReactionsLayoutInBubble {
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 @@ public class ReactionsLayoutInBubble {
}
}
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 class ReactionsLayoutInBubble {
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 class ReactionsLayoutInBubble {
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 class ReactionsLayoutInBubble {
public int lastDrawnTextColor;
public int lastDrawnBackgroundColor;
public int lastDrawnTagDotColor;
boolean isSelected;
public boolean isTag;
AvatarsDrawable avatarsDrawable;
ArrayList<TLObject> users;
@ -581,13 +623,17 @@ public class ReactionsLayoutInBubble {
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 class ReactionsLayoutInBubble {
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 class ReactionsLayoutInBubble {
} else {
throw new RuntimeException("unsupported");
}
countText = Integer.toString(reactionCount.count);
imageReceiver.setParentView(parentView);
isSelected = reactionCount.chosen;
counterDrawable.updateVisibility = false;
@ -633,17 +686,54 @@ public class ReactionsLayoutInBubble {
counterDrawable.setSize(dp(26), dp(100));
counterDrawable.textPaint = textPaint;
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 class ReactionsLayoutInBubble {
}
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 class ReactionsLayoutInBubble {
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,18 +835,32 @@ public class ReactionsLayoutInBubble {
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 (!isTag) {
if (avatarsDrawable != null) {
canvas.save();
canvas.translate(x + dp(10) + dp(20) + dp(2), y);
@ -743,10 +870,12 @@ public class ReactionsLayoutInBubble {
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 class ReactionsLayoutInBubble {
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 class ReactionsLayoutInBubble {
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 class ReactionsLayoutInBubble {
}
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();
}
}

View file

@ -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.RectF;
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.MotionEvent;
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.SharedConfig;
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.ReactionsEffectOverlay;
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;
@ -102,6 +112,34 @@ public class ReactionsContainerLayout extends FrameLayout implements Notificatio
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<InnerItem> items = new ArrayList<>();
public ArrayList<InnerItem> 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);
@ -109,10 +147,10 @@ public class ReactionsContainerLayout extends FrameLayout implements Notificatio
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;
@ -179,9 +217,10 @@ public class ReactionsContainerLayout extends FrameLayout implements Notificatio
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);
@ -203,7 +242,7 @@ public class ReactionsContainerLayout extends FrameLayout implements Notificatio
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) {
@ -289,14 +328,14 @@ public class ReactionsContainerLayout extends FrameLayout implements Notificatio
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 {
@ -331,7 +370,7 @@ public class ReactionsContainerLayout extends FrameLayout implements Notificatio
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];
@ -350,8 +389,8 @@ public class ReactionsContainerLayout extends FrameLayout implements Notificatio
} 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 -> {
@ -361,8 +400,8 @@ public class ReactionsContainerLayout extends FrameLayout implements Notificatio
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);
}
@ -376,6 +415,17 @@ public class ReactionsContainerLayout extends FrameLayout implements Notificatio
}
}
@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();
@ -386,14 +436,6 @@ public class ReactionsContainerLayout extends FrameLayout implements Notificatio
return items.get(position).viewType;
}
ArrayList<InnerItem> items = new ArrayList<>();
ArrayList<InnerItem> 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();
@ -411,28 +453,6 @@ public class ReactionsContainerLayout extends FrameLayout implements Notificatio
}
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() {
@ -474,9 +494,9 @@ public class ReactionsContainerLayout extends FrameLayout implements Notificatio
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);
}
}
});
@ -500,7 +520,7 @@ public class ReactionsContainerLayout extends FrameLayout implements Notificatio
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) {
@ -515,6 +535,16 @@ public class ReactionsContainerLayout extends FrameLayout implements Notificatio
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);
@ -535,8 +565,10 @@ public class ReactionsContainerLayout extends FrameLayout implements Notificatio
}
public void dismissWindow() {
if (reactionsWindow != null) {
reactionsWindow.dismiss();
}
}
public CustomEmojiReactionsWindow getReactionsWindow() {
return reactionsWindow;
@ -555,9 +587,14 @@ public class ReactionsContainerLayout extends FrameLayout implements Notificatio
delegate.onEmojiWindowDismissed();
}
});
onShownCustomEmojiReactionDialog();
//animatePullingBack();
}
protected void onShownCustomEmojiReactionDialog(){
}
private void invalidateLoopViews() {
for (int i = 0; i < recyclerListView.getChildCount(); i++) {
View child = recyclerListView.getChildAt(i);
@ -612,7 +649,7 @@ public class ReactionsContainerLayout extends FrameLayout implements Notificatio
this.visibleReactionsList.clear();
if (showCustomEmojiReaction()) {
int i = 0;
int n = (AndroidUtilities.displaySize.x - AndroidUtilities.dp(36)) / AndroidUtilities.dp(34);
int n = (AndroidUtilities.displaySize.x - dp(36)) / dp(34);
if (n > 7) {
n = 7;
}
@ -637,8 +674,8 @@ public class ReactionsContainerLayout extends FrameLayout implements Notificatio
allReactionsList.clear();
allReactionsList.addAll(visibleReactionsList);
// checkPremiumReactions(this.visibleReactionsList);
int size = getLayoutParams().height - (hasHint ? AndroidUtilities.dp(20) : 0) - getPaddingTop() - getPaddingBottom();
if (size * visibleReactionsList.size() < AndroidUtilities.dp(200)) {
int size = getLayoutParams().height - (int) getTopOffset() - getPaddingTop() - getPaddingBottom();
if (size * visibleReactionsList.size() < dp(200)) {
getLayoutParams().width = ViewGroup.LayoutParams.WRAP_CONTENT;
}
@ -708,7 +745,7 @@ public class ReactionsContainerLayout extends FrameLayout implements Notificatio
chatScrimPopupContainerLayout.setExpandSize(expandSize);
}
float transitionLeftOffset = (getWidth() - getPaddingRight()) * Math.min(1f, lt);
float hintHeight = (hasHint ? AndroidUtilities.dp(20) : 0);
float hintHeight = getTopOffset();
rect.set(getPaddingLeft() + transitionLeftOffset, getPaddingTop() + recyclerListView.getMeasuredHeight() * (1f - otherViewsScale) - expandSize, (getWidth() - getPaddingRight()) * rt, getHeight() - getPaddingBottom() + expandSize);
radius = ((rect.height() - hintHeight) - expandSize * 2f) / 2f;
@ -805,7 +842,7 @@ public class ReactionsContainerLayout extends FrameLayout implements Notificatio
}
if (pullingLeftOffsetProgress > 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;
@ -820,9 +857,9 @@ public class ReactionsContainerLayout extends FrameLayout implements Notificatio
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) {
@ -887,12 +924,12 @@ public class ReactionsContainerLayout extends FrameLayout implements Notificatio
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));
@ -906,9 +943,9 @@ public class ReactionsContainerLayout extends FrameLayout implements Notificatio
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()) {
@ -943,8 +980,8 @@ public class ReactionsContainerLayout extends FrameLayout implements Notificatio
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;
@ -1012,7 +1049,7 @@ public class ReactionsContainerLayout extends FrameLayout implements Notificatio
}
public float getPullingLeftProgress() {
return Utilities.clamp(pullingLeftOffset / AndroidUtilities.dp(42), 2f, 0f);
return Utilities.clamp(pullingLeftOffset / dp(42), 2f, 0f);
}
@Override
@ -1025,7 +1062,7 @@ public class ReactionsContainerLayout extends FrameLayout implements Notificatio
* 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));
@ -1090,6 +1127,9 @@ public class ReactionsContainerLayout extends FrameLayout implements Notificatio
}
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) {
@ -1118,6 +1158,74 @@ public class ReactionsContainerLayout extends FrameLayout implements Notificatio
listAdapter.notifyDataSetChanged();
}
public void setSelectedReactions(ArrayList<MessageObject> 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<ReactionsLayoutInBubble.VisibleReaction> getSelectedReactions() {
return selectedReactions;
}
public static HashSet<ReactionsLayoutInBubble.VisibleReaction> getInclusiveReactions(ArrayList<MessageObject> messages) {
LongSparseArray<ReactionsLayoutInBubble.VisibleReaction> arr = new LongSparseArray<>();
HashSet<Long> 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<ReactionsLayoutInBubble.VisibleReaction> selectedReactions = new HashSet<>();
for (int j = 0; j < arr.size(); ++j) {
selectedReactions.add(arr.valueAt(j));
}
return selectedReactions;
}
public void setSelectedReactionsInclusive(ArrayList<MessageObject> 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<ReactionsLayoutInBubble.VisibleReaction> visibleReactions) {
HashSet<ReactionsLayoutInBubble.VisibleReaction> set = new HashSet<>();
for (int i = 0; i < visibleReactions.size(); i++) {
@ -1166,7 +1274,7 @@ public class ReactionsContainerLayout extends FrameLayout implements Notificatio
HashSet<ReactionsLayoutInBubble.VisibleReaction> 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);
@ -1175,12 +1283,12 @@ public class ReactionsContainerLayout extends FrameLayout implements Notificatio
visibleReactions.add(visibleReaction);
added++;
}
if (added == 16) {
break;
}
}
// if (added == 16) {
// break;
// }
}
}
} else {
for (int i = 0; i < topReactions.size(); i++) {
ReactionsLayoutInBubble.VisibleReaction visibleReaction = ReactionsLayoutInBubble.VisibleReaction.fromTLReaction(topReactions.get(i));
if (!hashSet.contains(visibleReaction) && (type == TYPE_TAGS || UserConfig.getInstance(currentAccount).isPremium() || visibleReaction.documentId == 0)) {
@ -1188,8 +1296,9 @@ public class ReactionsContainerLayout extends FrameLayout implements Notificatio
visibleReactions.add(visibleReaction);
added++;
}
if (added == 16) {
break;
// if (added == 16) {
// break;
// }
}
}
@ -1257,11 +1366,17 @@ public class ReactionsContainerLayout extends FrameLayout implements Notificatio
public int getTotalWidth() {
int itemsCount = getItemsCount();
int width;
if (!showCustomEmojiReaction()) {
return AndroidUtilities.dp(36) * itemsCount + AndroidUtilities.dp(2) * (itemsCount - 1) + AndroidUtilities.dp(16);
width = dp(36) * itemsCount + dp(2) * (itemsCount - 1) + dp(16);
} else {
return AndroidUtilities.dp(36) * itemsCount - AndroidUtilities.dp(4);
width = dp(36) * itemsCount - dp(4);
}
return width;
}
public int getHintTextWidth() {
return hintViewWidth;
}
public int getItemsCount() {
@ -1298,7 +1413,7 @@ public class ReactionsContainerLayout extends FrameLayout implements Notificatio
public void setCustomEmojiReactionsBackground(boolean isNeed) {
if (isNeed) {
customEmojiReactionsIconView.setBackground(Theme.createSimpleSelectorCircleDrawable(AndroidUtilities.dp(28), Color.TRANSPARENT, ColorUtils.setAlphaComponent(Theme.getColor(Theme.key_listSelector), 40)));
customEmojiReactionsIconView.setBackground(Theme.createSimpleSelectorCircleDrawable(dp(28), Color.TRANSPARENT, ColorUtils.setAlphaComponent(Theme.getColor(Theme.key_listSelector), 40)));
} else {
customEmojiReactionsIconView.setBackground(null);
}
@ -1404,18 +1519,64 @@ public class ReactionsContainerLayout extends FrameLayout implements Notificatio
invalidate();
}
public void setHint(String storyReactionsHint) {
public void setHint(CharSequence storyReactionsHint) {
hasHint = true;
hintView = new TextView(getContext());
if (hintView == null) {
hintView = new LinkSpanDrawable.LinksTextView(getContext(), resourcesProvider);
hintView.setPadding(dp(8), 0, dp(8), 0);
hintView.setClickable(true);
hintView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 12);
if (type == TYPE_STORY || type == TYPE_STORY_LIKES) {
hintView.setTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteBlackText, resourcesProvider));
hintView.setText(storyReactionsHint);
hintView.setAlpha(0.5f);
} else {
hintView.setTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteGrayText2, resourcesProvider));
}
hintView.setGravity(Gravity.CENTER_HORIZONTAL);
addView(hintView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, 0, 0, 6, 0, 0));
}
hintView.setText(storyReactionsHint);
hintMeasured = false;
((LayoutParams) nextRecentReaction.getLayoutParams()).topMargin = AndroidUtilities.dp(20);
((LayoutParams) recyclerListView.getLayoutParams()).topMargin = AndroidUtilities.dp(20);
((LayoutParams) nextRecentReaction.getLayoutParams()).topMargin = dp(20);
((LayoutParams) recyclerListView.getLayoutParams()).topMargin = dp(20);
}
private boolean hintMeasured;
public void measureHint() {
if (hintMeasured || !hasHint || getMeasuredWidth() <= 0) return;
int maxWidth = Math.min(dp(320), getMeasuredWidth() - dp(16));
StaticLayout 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)));
}
if (layout.getLineCount() > 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) {
@ -1423,7 +1584,7 @@ public class ReactionsContainerLayout extends FrameLayout implements Notificatio
}
public float getTopOffset() {
return hasHint ? AndroidUtilities.dp(20) : 0;
return hasHint ? ((LayoutParams) recyclerListView.getLayoutParams()).topMargin : 0;
}
public void setBubbleOffset(float v) {
@ -1482,6 +1643,7 @@ public class ReactionsContainerLayout extends FrameLayout implements Notificatio
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;
@ -1655,6 +1817,25 @@ public class ReactionsContainerLayout extends FrameLayout implements Notificatio
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;
@ -1662,6 +1843,18 @@ public class ReactionsContainerLayout extends FrameLayout implements Notificatio
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);
@ -1673,15 +1866,26 @@ public class ReactionsContainerLayout extends FrameLayout implements Notificatio
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;
@ -1695,11 +1899,11 @@ public class ReactionsContainerLayout extends FrameLayout implements Notificatio
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);
}
}
@ -1727,6 +1931,9 @@ public class ReactionsContainerLayout extends FrameLayout implements Notificatio
preloadImageReceiver.setAllowStartLottieAnimation(false);
MediaDataController.getInstance(currentAccount).preloadImage(preloadImageReceiver, ImageLocation.getForDocument(defaultReaction.around_animation), ReactionsEffectOverlay.getFilterForAroundAnimation());
}
if (lockIconView != null) {
lockIconView.setImageReceiver(loopImageView.getImageReceiver());
}
}
}
@ -1833,17 +2040,14 @@ public class ReactionsContainerLayout extends FrameLayout implements Notificatio
@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());
}
}
@ -1871,13 +2075,13 @@ public class ReactionsContainerLayout extends FrameLayout implements Notificatio
@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);
@ -2088,7 +2292,7 @@ public class ReactionsContainerLayout extends FrameLayout implements Notificatio
}
public float expandSize() {
return (int) (getPullingLeftProgress() * AndroidUtilities.dp(6));
return (int) (getPullingLeftProgress() * dp(6));
}
public void setParentLayout(ChatScrimPopupContainerLayout layout) {

View file

@ -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<Item> oldItems = new ArrayList<>();
private final ArrayList<Item> 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 class SearchTagsList extends BlurredFrameLayout implements NotificationCe
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 class SearchTagsList extends BlurredFrameLayout implements NotificationCe
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) {
public boolean canReuseUpdatedViewHolder(@NonNull RecyclerView.ViewHolder viewHolder) {
return true;
}
}
return super.animateMove(holder, info, fromX, fromY, toX, toY);
}
@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 class SearchTagsList extends BlurredFrameLayout implements NotificationCe
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<Long> 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<TLRPC.Reaction> 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);
// }
// }
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).equals(items.get(newItemPosition));
}
@Override
public boolean areContentsTheSame(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();
}
} else if (premiumLayout != null) {
if (notify) {
premiumLayout.animate().alpha(0f).withEndAction(() -> {
premiumLayout.setVisibility(View.GONE);
}).start();
} else {
premiumLayout.setAlpha(1f);
premiumLayout.setVisibility(View.VISIBLE);
}
}
}
@Override
@ -231,36 +662,87 @@ public class SearchTagsList extends BlurredFrameLayout implements NotificationCe
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));
if (showWithCut) {
listView.setAlpha(shownT);
} else {
setAlpha(shownT);
}
invalidate();
}
protected void onShownUpdate(boolean finish) {
}
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;
}
// private final Paint backgroundPaint = new Paint();
// @Override
// public void setBackgroundColor(int color) {
// backgroundPaint.setColor(color);
// }
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);
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 class SearchTagsList extends BlurredFrameLayout implements NotificationCe
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,23 +796,29 @@ public class SearchTagsList extends BlurredFrameLayout implements NotificationCe
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) {
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 = reaction;
reactionCount.count = this.count = count == null ? 0 : count;
reactionCount.reaction = item.reaction.toTLReaction();
reactionCount.count = item.count;
reactionButton = new ReactionsLayoutInBubble.ReactionButton(null, currentAccount, this, reactionCount, false, resourcesProvider) {
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) : Theme.getColor(Theme.key_windowBackgroundWhiteGrayText2), 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);
}
@Override
@ -331,24 +828,61 @@ public class SearchTagsList extends BlurredFrameLayout implements NotificationCe
@Override
protected int getCacheType() {
return AnimatedEmojiDrawable.CACHE_TYPE_ALERT_EMOJI_STATUS;
return AnimatedEmojiDrawable.CACHE_TYPE_SAVED_REACTION;
}
@Override
protected boolean drawCounter() {
return count > 0 || counterDrawable.countChangeProgress != 1f;
return count > 0 || hasName || 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 class SearchTagsList extends BlurredFrameLayout implements NotificationCe
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 class SearchTagsList extends BlurredFrameLayout implements NotificationCe
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);

View file

@ -3022,8 +3022,10 @@ public class ShareAlert extends BottomSheet implements NotificationCenter.Notifi
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;
}
@ -3042,8 +3044,10 @@ public class ShareAlert extends BottomSheet implements NotificationCenter.Notifi
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;
}

View file

@ -30,6 +30,7 @@ import org.telegram.messenger.SvgHelper;
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 class StickerEmptyView extends FrameLayout implements NotificationCenter.
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);

View file

@ -35,6 +35,7 @@ import android.text.TextWatcher;
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;

View file

@ -179,6 +179,9 @@ public class ThanosEffect extends TextureView {
}
public void kill() {
if (destroyed) {
return;
}
destroyed = true;
for (ToSet set : toSet) {
if (set.doneCallback != null) {
@ -366,27 +369,31 @@ public class ThanosEffect extends TextureView {
}
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 @@ public class ThanosEffect extends TextureView {
}
};
public void layoutAnimations() {
}
private final ArrayList<Animation> toAddAnimations = new ArrayList<>();
public void animateGroup(ArrayList<View> views, Runnable whenDone) {
if (!alive) 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));
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);
running = true;
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 class ThanosEffect extends TextureView {
}
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 class ThanosEffect extends TextureView {
}
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 class ThanosEffect extends TextureView {
t -= top;
b -= top;
l -= left;
r -= left;
boolean useScale = group.transitionParams.cell.getScaleX() != 1f || group.transitionParams.cell.getScaleY() != 1f;
if (useScale) {

View file

@ -2,13 +2,16 @@ package org.telegram.ui.Components.spoilers;
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 android.widget.TextView;
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;
@ -30,6 +35,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);
}
@ -68,6 +76,7 @@ public class SpoilersTextView extends TextView implements TextSelectionHelper.Si
protected void onTextChanged(CharSequence text, int start, int lengthBefore, int lengthAfter) {
super.onTextChanged(text, start, lengthBefore, lengthAfter);
invalidateSpoilers();
updateAnimatedEmoji(true);
}
@Override
@ -76,6 +85,13 @@ public class SpoilersTextView extends TextView implements TextSelectionHelper.Si
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();
@ -100,6 +116,14 @@ public class SpoilersTextView extends TextView implements TextSelectionHelper.Si
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) {
@ -127,12 +151,29 @@ public class SpoilersTextView extends TextView implements TextSelectionHelper.Si
}
}
@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);

View file

@ -401,6 +401,7 @@ public class DialogsActivity extends BaseFragment implements NotificationCenter.
private boolean askingForPermissions;
private RLottieDrawable passcodeDrawable;
private SearchViewPager searchViewPager;
private SharedMediaLayout.SharedMediaPreloader sharedMediaPreloader;
public DialogStoriesCell dialogStoriesCell;
public boolean dialogStoriesCellVisible;
public float progressToDialogStoriesCell;
@ -2718,6 +2719,10 @@ public class DialogsActivity extends BaseFragment implements NotificationCenter.
getContactsController().loadGlobalPrivacySetting();
if (getMessagesController().savedViewAsChats) {
getMessagesController().getSavedMessagesController().preloadDialogs(true);
}
return true;
}
@ -4979,6 +4984,11 @@ public class DialogsActivity extends BaseFragment implements NotificationCenter.
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) {
@ -6055,7 +6065,7 @@ public class DialogsActivity extends BaseFragment implements NotificationCenter.
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 class DialogsActivity extends BaseFragment implements NotificationCenter.
}
}
}
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;
@ -7829,7 +7845,17 @@ public class DialogsActivity extends BaseFragment implements NotificationCenter.
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));

View file

@ -316,7 +316,7 @@ public class GroupCreateFinalActivity extends BaseFragment implements Notificati
}
if (!TextUtils.isEmpty(txt)) {
editText.setText(txt);
editText.setSelection(editText.getText().length());
editText.setSelection(0, editText.getText().length());
}
}
}

View file

@ -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;

Some files were not shown because too many files have changed in this diff Show more